Thinking in Java
Thinking in Java
razmisluva
vo
Java
^etvrto izdanie
Bruce Eckel
President, MindView, Inc.
Komentari od ~itatelite:
Sekoj Java programer bi trebalo da ja pro~ita knigata Da se razmisluva vo Java od korica do korica, i da mu bide pri raka za ~esti konsultirawa. Ve`bite se predizvik, i poglavjeto za Kolekcii e super! Ovaa kniga mi pomogna da go polo`am ispitot i da se zdobijam so Sun sertifikatot za Java programer; toa e isto taka i prva kniga vo koja {to baram odgovor sekoga{ koga imam pra{awe vo vrska so Java. Jim Plege r , Loudoun
Israel.
Eden od apsolutno najdobrite tutorijali za programirawe {to sum go videl za koj bilo programski jazik. Joakim Ziegler, FIX sysop. Vi blagodaram za Va{ata izvonredna, prekrasna kniga za Java. Dr. Gavin Pillay, Registrar, King Edward VIII Hospital, South Africa. U{te edna{ Vi blagodaram za Va{ata stra{na kniga. Jas navistina se ma~ev (ne sum C programer), no Va{ata kniga me dovede do nivo na koe {to Java ja u~ev so ista brzina kolku {to brgu mo`am da ~itam. Navistina e odli~no da si vo mo`nost da gi razbere{ osnovnite principi i koncepti od samiot po~etok, {to e podobro otkolku da se obiduva{ da izgradi{ konceptualen model preku obidi i gre{ki. Se nadevam deka }e bidam vo mo`nost da go posetam Va{iot seminar vo bliska idnina. Randall R.
informacii pri intervjuiraweto na pretpriema~i za pomo{ na na{iot tim. Otkriv kolkavo znaewe za Java tie imaat taka {to gi pra{uvav za rabotite koi {to gi nau~iv dodeka ja ~itav Va{ata kniga (na primer za razlikata pome|u nizi i vektori). Va{ata kniga e sjajna! Steve Wilkinson,
Iverson
Sakam samo da Ve pofalam za Va{ata rabota na knigata Da se razmisluva na Java. Lu|eto kako Vas ja vozdignuvaat idninata na Internetot i samo sakam da Vi se zablagodaram za Va{iot trud. Toj e mnogu cenet. Patrick
Jas navistina go cenam Va{iot entuzijazam i Va{ata rabota. Gi prezedov od Internet site prerabotki na Va{ite onlajn knigi. Istra`uvam jazici i otkrivam ona {to dosega ne sum se osmelil (C#, C++, Python i Ruby, kako sporeden efekt). Imam najmalku 15 drugi knigi za Java (mi bea potrebni 3 za da gi napravam JavaScript i PHP odr`livi!) i sum pretplaten na Dr. Dobbs, JavaPro, JDJ, JavaWorld, i taka natamu, kako rezultat na na mojata rabota so Java (i Enterprise Java) i sertifikat , no se u{te Va{ata kniga visoko ja cenam. Se pretplativ na Va{eto spisanie i se nadevam deka eden den }e sednam i }e re{am nekoi od problemite {to gi dodadovte vo vodi~ite so re{enija (}e gi kupam vodi~ite!) vo znak na blagodarnost kon Vas. No, vo me|uvreme, mnogu Vi blagodaram. Joshua Long, www.starbuxman.com Pogolemiot broj na knigite za Java se dobri za po~etok, i pove}eto samo gi zapo~nuvaat rabotite i vo site ima mnogu isti primeri. Va{ata kniga do sega e najdobra kniga za napredno nivo {to dosega sum videl. Ve molam poskoro da ja objavite! ... Bidej}i tolku bev impresioniran so knigata Da se razmisluva na Java, ja kupiv i knigata Da se razmisluva na C++. George
Cincinnati, Ohio
Va{ite primeri se jasni i lesni za razbirawe. Ste vodele smetka za mnogu va`nite detali na Java, koi ne mo`at lesno da se najdat vo siroma{nata dokumentacija za Java. I Vie ne go tro{ite vremeto na ~itatelot so osnovnite fakti {to programerot ve}e gi znae. Kai Engert, Innovative
Software,Germany
Jas sum golem qubitel na Va{ata kniga Da se razmisluva na C++ i ja imam prepora~ano na sorabotnicite. Kako {to ja ~itam elektronskata verzija na Va{ata kniga za Java, otkrivam deka ste go zapazile istoto visoko nivo na pi{uvawe. Vi blagodaram! Peter R. NeuwaJd
Mnogu dobro napi{ana kniga za Java. .. Mislam deka ste napravile IZVONREDNA rabota so ova. Kako ~len na grupata so specijalen interes za Java od podra~jeto na ^ikago, jas nekolku pati ja spomnav Va{ata kniga i Va{iot Veb na na{ite neodamne{ni sredbi. Bi sakal da ja koristam knigata Da se razmisluva na Java kako osnova za del od mese~nite sostanoci na SIC, na koi {to bi ja razgleduvale i diskutirale sekoja glava po red . Mark Ertes Popatno, pe~atena verzija na knigata Da se razmisluva na Java na ruski jazik s u{te odli~no se prodava i poleka stanuva bestseler. U~eweto Java stanuva sinonim na ~itaweto Da se razmisluva na Java, zarem toa ne e ubavo? Ivan Porty, preveduva~ i izdava~ na knigata Da se razmisluva na Java, 2-roto izdanie na ruski jazik. Navistina ja cenam Va{ata rabota i Va{ata kniga e dobra. Ja predlo`iv knigata ovde na na{ite korisnici i na studentite na doktorski studii. HUb'1.leS Leroy / / Il"isa-Inria Rennes Fra nce , Head of Scient ific Computing and Industrial Tranferl Dobro, pro~itav samo ~etirieset stranici od knigata Da se razmisluva na Java, no ve}e otkriv deka taa e najjasno napi{ana kniga i najdobro pretstavena kniga za programirawe na koi {to sum nai{ol...i jas samiot sum pisatel, pa verojatno malku sum kriti~en. Ja imam knigata Da se razmisluva na C++ i ne mo`am da ~ekam da ja prou~am - po~etnik sum vo programiraweto. Ova e samo kratka bele{ka za da se zablagodaram za Va{ata odli~na rabota. Po~nav da gubam entuzijazam od vle~kaweto niz lo{ite, mra~ni, zdodevni tekstovi na pove}eto kompjuterski knigi - duri i onie {to dojdoa so besprekorni preporaki. Sega se ~uvstvuvam mnogu podobro. Glenn Becker , Educational Theatre Association Vi blagodaram {to Va{ata ~udesna kniga ja napravivte da bide dostapna. Otkriv deka knigata za mene e od ogromna korist za kone~no da gi razberam rabotite koi{to me zbunuvaa vo Java i C++. Da se ~ita Va{ata kniga be{e golemo zadovolstvo. Felix Bizaoui, "Twin Oaks Industries,
Louisa , Va.
Moram da Vi ~estitam za izvonrednata kniga. Odlu~iv da ja razgledam knigata Da se razmisluva na Java vrz osnova na moeto iskustvo so knigata Da se razmisluva na C++, i voop{to ne bev razo~aran. J acovander
Va{ata kniga pravi site drugi knigi za Java {to sum gi pro~ital ili prelistal da izgledaat dvoli~no beskorisni i navredlivi. Brett Porter,
od neodamna i kako samovraboten, pa bi sakal da mislam deka dovolno imam videno (ne "sum videl s," no dovolno). Me|utoa, ovie knigi bea pri~ina mojata devojka da me narekuva "perverzen." Nemam ni{to protiv konceptot na knigata - samo mislam deka taa faza e zad mene. No, otkriv deka u`ivam i vo dvete knigi, kako nitu vo edna druga kompjuterska kniga {to sum ja doprel ili kupil dosega. Odli~en stil na pi{uvawe, mnogu ubavi voveduvawa vo sekoja nova tema, i mnogu mudrost vo knigite. Dobro sraboteno. Simon Goland, [email protected], Simon Says Consulting, Inc. Moram da ka`am deka Va{ata kniga Da se razmisluva na Java e sjajna! Ova e tokmu onoj vid na dokumentacija kakov {to barav. Osobeno delovite za dobar i lo{ softverski dizajn, koristej}i Java. Dirk Duehr, Lexikon
DCL Enterprises
Vi blagodaram {to oddelivte vreme da napi{ete navistina korisna kniga za Java. Ako predavaweto pravi da razberete ne{to, dosega mora da ste mnogu zadovolni so sebe. Dominic Turner, GEAC Support Ova e najdobrata kniga za Java {to nekoga{ sum ja pro~ital - a imam pro~itano nekolku. Jean-Yves MENGANT, ChiefSoftware Architect
Vanguard Group
Da se razmisluva na Java e odli~na i ~itliva kniga. Ja prepora~uvam na site moi studenti. Dr. Paul Gorman, Department ofComputer Science,
Vi blagodaram za mo`nosta da gledam kako ovaa kniga se razviva vo remek delo! TOA E NAJDOBRATA kniga na ovaa tema koja sum ja pro~ital ili prelistal. Jeff Lapchinsky, Programmer, Net Results Technologies Va{ata kniga e koncizna, dostapna i zadovolstvo e da se ~ita. Keith
Gary Entsminger
Author, The Tao ofObjects
" Da se razmisluva na C++ trpelivo i metodi~no gi istra`uva pra{awata za toa kako i kade da se koristat vmetnuvawa? (inlines), referenci, preoptovaruvawe na parametri, nasleduvawe i dinami~ki objekti, isto kako i napredni temi kako {to se pravilno koristewe na templejti, isklu~oci i pove}ekratno nasleduvawe. Celosniot napor e protkaen vo materijal {to ja vklu~uva filozofijata na Eckel za objekti i proektirawe na programi. Ovaa kniga na svojata polica za knigi mora da ja ima sekoj {to saka seriozno da napreduva vo C++."
Da se
razmisluva
vo
Java
^etvrto izdanie
Bruce Eckel
President, MindView, Inc.
Posveteno na Dawn
PREGLED
Predgovor ............................................................................................1 Voved ...................................................................................................11 Zapoznavawe so objekti ..................................................................20 Se e objekt ..........................................................................................57 Operatori ..........................................................................................87 Kontrolirawe na izvr{uvaweto ...............................................126 Inicijalizacija i ~istewe..........................................................145 Kontrola na pristapot .................................................................197 Povtorno koristewe na klasite ................................................223 Polimorfizam................................................................................260 Interfejsi ......................................................................................292 Vnatre{ni klasi ............................................................................323 ^uvawe objekti ...............................................................................364 Obrabotka na gre{ki so pomo{ na isklu~oci .......................413 Znakovni nizi (stringovi) ..........................................................471 Podatoci za tipot ..........................................................................519 Generi~ki tipovi ...........................................................................577 Nizi ...................................................................................................697 Detalno razgleduvawe na kontejnerite ....................................735 Vlezno-izlezen sistem vo Java ....................................................838 Nabroeni tipovi ............................................................................941 Anotacii ..........................................................................................985 Paralelno izvr{uvawe ..............................................................1030 Grafi~ki korisni~ki opkru`uvawa......................................1210 A: Dodatoci ...................................................................................1346 B: Resursi .......................................................................................1351 Indeks ...................................................................................................1
Preduslovi......................................... 12 U~ewe na Java .................................... 12 Celi ..................................................... 13 Pou~uvawe vrz osnova na knigata . 14 Dokumentacija na Veb...................... 15 Ve`bi .................................................. 15 Temelite na Java ............................... 15
Izvoren kod ....................................... 16 Se e objekt Na~in na pi{uvawe vo knigata . 18 Gre{ki ................................................ 19 Zapoznavawe so objekti 20
Rabota so objektite preku referenci........................................... 57 Morate da gi kreirate site objekti59 Kade se nao|a skladi{teto......... 59 Specijalen slu~aj: prosti tipovi60 Nizi vo Java ................................... 62 Nikoga{ nemate potreba da uni{tite objekt ................................ 63 Oblast na va`ewe......................... 63 Oblast na va`ewe na Objektite 64
Razvoj na apstrakcija ....................... 21 Objektot ima interfejs .................. 23 Objektot dava uslugi........................ 26 Skriena realizacija ........................ 27 Povtorno koristewe na realizacija......................................... 28 Nasleduvawe ...................................... 29
Kreirawe novi tipovi na podatoci: .................................................... 65 Poliwa i Metodi ......................... 66 Metodi, argumenti i povratni vrednosti ............................................ 68 Listata so argumenti .................. 69 Pravewe na Java programa .............. 70 Vidlivost na imeto ..................... 70 Koristewe drugi komponenti ... 71 klu~eniot zbor static ................... 72 Va{ata prva Java programa ............ 74 Preveduvawe i izvr{uvawe ....... 76 Komentari i vgradena dokumentacija .................................... 77 Dokumentacija na komentari ..... 77 Sintaksa ......................................... 78 Vgraden HTML ............................... 79 Primeri na oznaki....................... 80 Primer za dokumentacija ........... 82 Stil na programirawe .................... 83 Rezime ................................................. 84 Ve`bi .................................................. 84 Operatori 87
Avtomatsko zgolemuvawe i namaluvawe ......................................... 95 Relacioni operatori ....................... 96 Ispituvawe ednakvost na objekti96 Logi~ki operatori ........................... 98 Nepotpolno presmetuvawe ....... 100 Literali ........................................... 101 Eksponencijalna notacija ........ 103 Operatori brz bitovite ............... 104 Operatori za pomestuvawe ........... 105 Ternaren if-else operator.............. 109 Operatori + i += za znakovni nizi (string operatori) ............................ 110 Voobi~aeni gre{ki pri koristewe na operatori .................................... 112 Operatori za eksplicitna konverzija ......................................... 112 Otsekuvawe i zaokru`uvawe ... 114 Unapreduvawe .............................. 115 Java nema sizeof (operator za odreduvawe na golemina) .............. 115 Pregled na operatori .................... 116 Rezime ................................................ 125 Kontrolirawe na izvr{uvaweto 126
Poednostavni naredbi za ispi{uvawe ........................................ 87 Koristewe na operatorite vo Java88 Prioriteti ........................................ 89 Dodeluvawe na vrednosti ............... 89 Koristewe na psevdonimi pri povikuvawe na metod ................... 91 Matemati~ki operatori ................. 92 Unarni operatori minus i plus 94
Logi~ki vrednosti (true i false) .... 126 if-else .................................................. 126 Povtoruvawa .................................... 128 do-while ........................................ 128 Ciklusot for ................................ 129 Operator zapirka ....................... 130 Sintaksa Foreach............................. 131
Rezerviraniot zbor return ........... 134 Rezervirani zborovi break i continue ............................................ 135 Nepopularnoto goto ................... 136 Naredbata switch ............................. 141 Rezime ............................................... 143 Inicijalizacija i ~istewe 145
Eksplicitna inicijalizacija na stati~ni elementi...................... 179 Inicijalizacija na nestati~ni instanci........................................ 180 Inicijalizacija na nizi ............... 182 Lista na promenlivi argumenti186 Nabroeni tipovi............................. 193
Rezime ................................................ 195 Garantirana inicijalizacija so 197 pomo{ na konstruktorot .............. 145 Kontrola na pristapot Preklopuvawe na metodi .............. 147 Razlikuvawe na preklopeni metodi ........................................... 150 Preklopuvawe so prosti tipovi151 Preklopuvawe na povratni vrednosti...................................... 155 Podrazbirani konstruktori ... 155 Rezerviraniot zbor this................ 157 Povikuvawe konstruktori od konstruktori ................................... 159 Zna~eweto na rezerviraniot zbor static ...................................... 161 ^istewe: finalizacija i sobirawe na otpadocite .................................. 162 Za {to slu`i metodot finalize( )?163 Morate da ~istite sami ............ 164 Sostojba na prestanuvawe ........ 165 Kako raboti sobira~ot na otpadoci ....................................... 167 Inicijalizacija na ~lenovi .... 171 Paket: Bibliote~na edinica ....... 198 Organizacija na kodot............... 200 Pravewe edinstveni imiwa na paket .............................................. 202 Li~na biblioteka so alatki .... 205 Koristewe uvoz so cel promena na odnesuvaweto .......................... 207 Predupreduvawe pri rabotewe so paketite ........................................ 208 Specifikatori na pristapot vo Java ..................................................... 209 Paketen pristap ......................... 209 public: interfejs za pristap.... 210 private: Ne smeete da go dopirate toa! ................................................. 212 protected: Pristap so nasleduvawe ................................. 213 Interfejs i realizacija ............... 215 Pristap kon klasite ...................... 217 Rezime ................................................ 221 223
Zadavawe na inicijalizacija .. 172 Povtorno koristewe na klasite Inicijalizacija na konstruktori ............................... 174
Inicijalizirawe na osnovna klasa .............................................. 229 Delegirawe ...................................... 232 Kombinirawe na kompozicija i nasleduvawe ..................................... 234 Garantirawe na pravilno ~istewe ......................................... 236 Kriewe na imiwa ....................... 239 Izbor pome|u kompozicija i nasleduvawe ..................................... 241 Rezerviraniot zbor: protected.... 243 Sveduvawe nagore ........................... 244 Povtorno za izborot pome|u kompozicijata i nasleduvaweto246 Rezerviraniot zbor final............... 247 final podatoci .............................. 247 Final metodi ................................. 251 final klasi ..................................... 254 Vnimatelno so rezerviraniot zbor final ....................................... 255 Inicijalizacija i v~ituvawe na klasi .................................................. 256
Gre{ka: redefinirawe na privatnite metodi ..................... 272 Gre{ka: poliwa i stati~ni metodi ........................................... 272 Konstruktori i polimorfizam... 274 Redosled za povikuvawe konstruktori ............................... 274 Nasleduvawe i ~istewe............. 277 Odnesuvawe na polimorfnite metodi vo konstruktorite ........ 282 Kovarijantni povratni tipovi.... 284 Dizajnirawe so nasleduvawe ........ 285 Sporedba pome|u zamena i pro{iruvawe ............................... 287 Sveduvawe nadolu i podatoci za tipot pri izvr{uvawe............... 288 Rezime ................................................ 290 Interfejsi 292
Apstraktni klasi i metodi .......... 292 Interfejsi ....................................... 296 Potpolno razdvojuvawe ................. 301
Pove}ekratno nasleduvawe vo Inicijalizacija so nasleduvawe257 Java ..................................................... 306 Pro{iruvawe na interfejsot so nasleduvawe...................................... 308 Sudir na imiwa pri kombinirawe na interfejsi .... 310 Prilagoduvawe na interfejsot ... 311 Poliwa vo interfejsi ................... 314 Inicijalizacija na poliwa vo interfejsi.................................... 315 Vgnezduvawe na interfejsi .......... 315 Interfejsi i proizvoditeli ....... 318
Povtorno za sveduvaweto nagore 260 Zanemaruvawe na tipot na objektite ...................................... 262 Zastoj ................................................. 263 Vrzuvawe na povikot na metodot264 Dobivawe na pravilno odnesuvawe ................................... 265 Pro{irlivost ............................ 268
Iteratori......................................... 380 ListIterator...................................... 383 Povrzana Lista ............................... 384 Stack ................................................... 386
Sozdavawe na vnatre{ni klasi ... 323 Vrska so nadvore{nata klasa ...... 325
Upotreba na sintaksata .this i .new327 Set ....................................................... 388 Vnatre{ni klasi i sveduvawe nagore ................................................ 329 Vnatre{ni klasi vo metodi i oblastite na va`ewe...................... 331 Anonimni vnatre{ni klasi ......... 333 Povtorno za proizvodnite metodi ........................................... 338 Vgnezdeni klasi .............................. 340 Klasite vo interfejsite .......... 342 Za{to vnatre{ni klasi? .............. 344 Zaklu~oci i povratni povici . 347 Vnatre{ni klasi i skeleti na upravuvawe ................................... 350 Nasleduvawe na vnatre{ni klasi357 Dali vnatre{nata klasa mo`e da se redefinira? .................................... 358 Lokalni vnatre{ni klasi ............ 360 Identifikatori na vnatre{nite klasi .................................................. 362 Rezime ............................................... 362 ^uvawe objekti 364 Mapa ................................................... 392 Pravewe redovi za ~ekawe - Queue396 Prioriteten red za ~ekawe (PriorityQueue) ............................. 397 Sporedba pome|u Collection i Iterator399 Foreach i iteratori ......................... 403 Adapterski metod ....................... 405 Rezime ................................................ 409 Obrabotka na gre{ki so pomo{ na isklu~oci 413 Koncept ............................................. 414 Osnovni Isklu~oci........................ 415 Argumenti na isklu~ok ............. 416 Fa}awe na isklu~ok ....................... 417 Blokot try ................................... 417 Pravewe na sopstveni isklu~oci 420 Isklu~oci i zapi{uvawe ......... 422 Specifikacija na isklu~oci ....... 426 Fa}awe na bilo koj isklu~ok....... 427 Polo`ba na nastanuvawe na isklu~oci na stekot na izvr{uvawe .................................. 430 Povtorno generirawe na isklu~oci ..................................... 431 Nadovrzuvawe na isklu~oci .... 434 Standardni isklu~oci vo Java ..... 438
Generi~ki klasi i kontejneri za bezbedna rabota so tipovite ........ 365 Osnovni poimi ................................ 369 Dodavawe grupa od elementi ........ 370 Ispi{uvawe na sodr`inite na kontejnerite .................................... 373 Listi ................................................. 375
Specijalen slu~aj: RuntimeException ..................... 438 ^istewe so odredbata finally ....... 440
Za {to slu`i odredbata finally?442 Regularni izrazi............................. 491 Koristewe na finally pri vra}awe so return ....................... 445 Nedostatok: zagubeniot isklu~ok446 Ograni~uvawe kaj isklu~oci ....... 448 Konstruktori .................................. 452 Pronao|awe na sli~ni isklu~oci458 Alternativni pristapi ................ 459 Istorija ....................................... 461 Perspektivi ................................ 462 Prosleduvawe isklu~oci na konzolata ..................................... 465 Pretvorawe na provereni isklu~oci vo neprovereni ....... 466 Upatstva za isklu~oci:.................. 468 Rezime ............................................... 469 Znakovni nizi (stringovi) 471 Osnovi ........................................... 492 Kreirawe na regularni izrazi 495 Kvantifikatori ......................... 497 CharSequence .............................. 498 Klasite Pattern i Matcher ......... 499 Metodot find() .............................. 501 Grupi ............................................. 502 Metodite start() i end()............. 503 Indikatori na klasata Pattern 505 split() .............................................. 508 Operacii na zamena ................... 508 Metodot reset() ........................... 511 Regularni izrazi i vleznoizlezen sistem vo Java ............... 511 Leksi~ko analizirawe na vlezot 513 Grani~nici od klasata Scanner516 Leksi~ka analiza so pomo{ na regularni izrazi ........................ 516 Klasata StringTokenizer ................. 517 Podatoci za tipot 519
Nepromenlivi znakovni nizi ...... 471 Sporedba na preklopuvaweto na operatorot + i StringBuilder....... 472 Nenamerna rekurzija ..................... 477 Operacii so znakovni nizi .......... 478 Formatirawe na izlez................... 482 Metodot printf() ........................... 482 System.out.format() ..................... 483 Klasata Formatter...................... 484 Specifikatori na format ...... 485 Konverzii na klasata Formater 486
Potreba za prepoznavawe na tipot vo tekot na izvr{uvawe ................ 519 Objekt tip Class ............................. 522 Literali na klasa ...................... 527 Generi~ki referenci na klasi 530 Nova sintaksa za konverzija na tipovi............................................ 533
Proverka pred konverzija na tip 534 Koristewe na literali na klasa541 Dinami~ki instanceof .............. 543 Rekurzivno broewe .................... 545 Registrirani proizvodni metodi 546 Sporeduvawe na instanceof so ekvivalenciite na klasite........... 550 Refleksija: informacii za klasata vo tekot na izvr{uvawe ................ 551 Izdvojuva~ na metodot na klasata553 Dinami~ki posrednici.................. 556 Null Objekti...................................... 561 La`ni objekti i vrzuva~ki funkcii ........................................ 568 Interfejs i podatoci za tip ....... 569 Rezime ............................................... 575 Generi~ki tipovi 577
Poednostavuvawe na upotrebata na n-torkata ................................. 597 Uslu`en metod za Set ................ 599 Anonimni vnatre{ni klasi ......... 603 Pravewe na slo`eni modeli ........ 604 Tainstveno bri{ewe...................... 607 Pristap vo C++ ........................... 608 Migraciska kompatibilnost ... 611 Problem so bri{eweto ............ 612 [to se slu~uva na granicite ... 614 Kompenzacija za bri{ewe ............. 618 Pravewe instanci na tipovi ... 619 Nizi na generi~ki tipovi ........ 622 Granici ............................................. 628 Xokerski argumenti ....................... 632 Kolku e pameten preveduva~ot?635 Kontravarijansa ......................... 637 Neograni~eni xokerski argumenti ..................................... 640 Konverzija so fa}awe ............... 646 Nedostatoci ..................................... 647 Prostite tipovi ne mo`at da bidat parametri na tipot ......... 647 Realizacija na parametriziranite interfejsi650 Preklopuvawe ............................. 653 Osnovnata klasa go kidnapira interfejsot.................................. 653 Samoograni~eni tipovi ................ 654 Generi~ki kod koj neobi~no se povtoruva...................................... 655 Samoograni~uvawe ..................... 656
Sporeduvawe so C++....................... 578 Ednostavni generi~ki tipovi ..... 579 Biblioteka n-torki ................... 581 Klasa na stekot ........................... 584 RandomList ................................. 585 Generi~ki interfejsi ................... 586 Generi~ki metodi ........................... 590 Koristewe na zaklu~uvawe za tipot na argumenti .................... 591 Eksplicitno zadavawe na tipot593 Argumenti so promenlivi dol`ina i generi~ki metodi ... 594 Generi~ki metod koj se upotrebuva so Generator-i ....... 595 Generator za op{ta namena...... 596
Kovarijansa na argumentite .... 659 Dinami~ka bezbednost na tipovi 662 Isklu~oci ........................................ 663 Miksini ............................................ 665 Miksini vo jazikot C++ ........... 666 Me{awe so pomo{ na interfejs667 Koristewe na obrazecot Decorator ....................................... 669 Miksini so dinami~ki posrednici ................................... 670 Latentni tipovi ............................. 672
Generatori na podatoci Generators ................................... 711 Pravewe nizi od Generator - i 717 Metodi na klasata Arrays ............. 721 Kopirawe na niza ....................... 722 Sporeduvawe nizi....................... 723 Sporeduvawe elementi na nizi 724 Ureduvawe na niza ...................... 728 Prebaruvawe na podredena niza729 Rezime ................................................ 732
Detalno razgleduvawe na Kompenzacija za nepostoewe na kontejnerite 735 latentnite tipovi .......................... 677 Potpolna taksonomija na Refleksija ................................... 677 kontejnerite .................................... 735 Primena na metod na sekvenca 679 Koga slu~ajno nemate soodveten interfejs...................................... 682 Simulirawe na latentni tipovi so pomo{ na adapter .................. 684 Upotreba na funkciski objekti kako strategija ................................ 687 Rezime: dali eksplicitnata konverzija na tipovi e navistina tolku lo{a? ..................................... 693 Pro~itajte go i ova.................... 695 Nizi 697 Popolnuvawe na kontejneri ......... 737 Re{enie na baza na Generator . 738 Generatori na Map-i ................. 740 Koristewe Abstract klasi ....... 743 Funkcii na interfejsot Collection751 Opcionalni operacii.................... 755 Nepoddr`ani operacii ............. 756 Funkcionalnost na List-ite ......... 759 Mno`estva (Sets) i redosled na skladirawe ....................................... 762 SortedSet...................................... 767 Redovi za ~ekawe ............................. 768 Redovi za ~ekawe so prioritet 769 Dvostrani redovi za ~ekawe .... 771 Pove}e za Map-ite .......................... 772 Performansi............................... 774 SortedMap .................................... 778
[to nizite gi pravi posebni....... 697 Nizite se prvoklasni objekti ..... 699 Vra}awe vrednosti na niza .......... 702 Pove}edimenzionalni nizi ......... 703 Nizi i generi~ki tipovi .............. 707 Pravewe podatoci za testirawe . 710 Arrays.fill() ................................... 710
LinkedHashMap .......................... 779 Transformirawe na klu~evi i klu~evi za he{irawe ..................... 780 Na~in na rabota na metodot hashCode() .................................. 784 Transformirawe klu~evi poradi brzina............................................ 787 Redefinirawe na metodot hashCode( ) ................................. 791 Izbor na realizacija ..................... 798 Struktura za testirawe na performansite ........................... 799 Performansi na razli~ni List-i803 Opasnosti od mikrosporeduvawe na performansi .......................... 810 Izbor na mno`estvo (Set) ........ 811 Izbor na mapa (Map) .................. 813 Uslu`ni metodi .............................. 818 Ureduvawe i prebaruvawe List-i822 Napravete nepromenliva mapa ili kolekcija .............................. 824 Sinhronizirawe na kolekcija ili mapa ........................................ 826 ^uvawe referenci ......................... 827 WeakHashMap ............................ 830 Kontejneri na Java 1.0/1.1 ............. 831 Vector i Enumeration ............... 831 Hashtable ..................................... 833 Stack.............................................. 833 BitSet............................................. 834 Rezime ............................................... 837 Vlezno-izlezen sistem vo Java 838
Klasata File ...................................... 838 Listawe na imenikot................. 839 Uslu`ni metodi za imenici .... 842 Proverka na postoewe i pravewe na imenici.................................... 848 Vlez i izlez ...................................... 850 Vidovi na vlezni tekovi (InputStream) .............................. 851 Vidovi na izlezni tekovi (OutputStream) ........................... 853 Dodavawe atributi i korisni interfejsi ........................................ 855 Filtrirawe na vlezniot tek ... 855 Filtrirawe na izlezniot tek . 857 Klasi za ~itawe i vpi{uvawe (Readers & Writers) ........................ 859 Izvori i bezdni na podatoci ... 860 Menuvawe na odnesuvawe na tek861 Klasi koi ne se smeneti ............ 862 Poseben slu~aj: klasata RandomAccessFile ........................ 863 Tipi~ni primeni na V/I tekovite864 Baferirana vlezna datoteka ... 864 Formatiran vlez od memorijata866 Osnovi na pi{uvawe vo datoteka867 Kratenka za pi{uvawe vo tekstualna datoteka ................... 868 ^uvawe i rekonstruirawe na podatoci ....................................... 869 ^itawe i vpi{uvawe datoteki so slu~aen pristap .......................... 871 Cevovodi....................................... 873
Uslu`ni klasi za ~itawe i pi{uvawe .......................................... 873 ^itawe binarni datoteki ........ 876 Standardni V/I tekovi ................. 877
Osnovni mo`nosti na nabroenite tipovi ................................................ 941 Uvoz na stati~ni ~lenovi vo nabroeniot tip............................ 943 Dodavawe metodi vo nabroeniot tip ...................................................... 944 Redefinirawe na enum metodite945 Nabroeni tipovi vo naredbite switch ................................................ 945 Misterijata na metodot values() 947 Realizira, ne nasleduva ................ 949 Slu~aen izbor .................................. 950 Upotreba na interfejsot za organizirawe ................................... 951 Zbirot EnumSet namesto indikatori ....................................... 956 Koristewe na mapata EnumMap . 959 Metodi koi se menuvaat vo zavisnost od konstantata ............. 960 Sozdavawe sinxir na odgovornosti so pomo{ na nabroenite tipovi ..................... 964 Ma{ini na sostojbite so nabroenite tipovi ..................... 968 Pove}ekratno otkrivawe na tipot974 Otkrivawe na tipot so pomo{ na nabroeni tipovi ......................... 977 Koristewe metodi koi se menuvaat vo zavisnost od konstantata na nabroeniot tip979 Otkrivawe na tip so pomo{ na mapata EnumMap ........................ 981
^itawe na standarden vlezen tek877 Obvitkuvawe na tekot System.out vo PrintWriter ........ 878 Prenaso~uvawe na standardniot V/I ................................................. 879 Upravuvawe so procesi ................. 880 Novi V/I klasi ............................... 882 Konverzija na podatoci ............ 886 Pribavuvawe na prosti tipovi889 Baferi na prikaz ....................... 890 Rabota so podatoci so pomo{ na bafer............................................. 894 Detalno za baferite ................. 896 Datoteki preslikani vo memorija ....................................... 900 Zaklu~uvawe na datoteki ......... 903 Komprimirawe ................................ 906 Ednostavno komprimirawe vo formatot GZIP............................ 908 Kompresirawe na pove}e datoteki vo Zip format ............. 909 Java arhivi (JARs) ..................... 911 Serijalizirawe na objekti .......... 913 Pronao|awe na klasata ............. 917 Upravuvawe so serijalizacijata919 Koristewe trajnost ................... 928 XML .................................................... 934 Preferences ....................................... 937
Koristewe na nizata 2-D .......... 982 Zaklu~ok ........................................... 983 Anotacii 985
Site aspekti na paralelnoto izvr{uvawe .................................... 1032 Pobrzo izvr{uvawe ................. 1032 Podobren dizajn na kodot ....... 1035 Osnovi na programiraweto so pove}e ni{ki ................................. 1037 Definirawe na zada~ite ........ 1037 Klasa Thread ............................. 1039 Upotreba na izvr{iteli (Executors) ................................ 1041 Dobivawe povratni vrednosti od zada~ite ...................................... 1045 Spiewe ........................................ 1046 Prioritet .................................. 1048 Prepu{tawe .............................. 1050 Servisni ni{ki ........................ 1050 Varijanti na programirawe ... 1055 Terminologija ........................... 1061 Pridru`uvawe na postoe~kata ni{ka .......................................... 1062 Korisni~ko opkru`uvawe koe brzo reagira............................... 1064 Grupi ni{ki .............................. 1065 Fa}awe na isklu~ocite .......... 1065 Delewe na resursite .................... 1068 Nepravilno pristapuvawe na resursite .................................... 1069 Razre{uvawe na eto za delewe na resursite .................................... 1072 Upotreba na eksplicitni bravi (Lock objekti) ........................... 1076
Osnovna sintaksa ............................ 986 Definirawe na anotacijata .... 987 Metaanotacii ............................. 989 Pi{uvawe procesori na anotaciite........................................ 990 Elementi na anotaciite ........... 991 Ograni~uvawa na podrazbiranite vrednosti ....... 991 Generirawe na nadvore{ni datoteki........................................ 992 Drugi re{enija ........................... 995 Anotaciite ne podr`uvaat nasleduvawe ................................. 996 Realizacija na procesorot....... 996 Koristewe na alatkata apt za obrabotka na anotaciite .............. 999 Upotreba na obrazecot Visitor so alatkata apt ................................... 1004 Edini~no testirawe so pomo{ na anotaciite...................................... 1007 Testirawe na generi~kite tipovi so alatkata @Unit ..... 1017 Sviti ne se potrebni ........... 1018 Realizacija na interfejsot @Unit........................................... 1019 Otstranuvawe na kodot za testirawe ................................... 1026 Zaklu~ok ......................................... 1028 Paralelno izvr{uvawe 1030
Atomskite operacii i momentalnata vidlivost......... 1078 Atomski klasi .......................... 1086 Kriti~ni oddeli ...................... 1087 Sinhronizacija so drugi objekti1093 Lokalen sklad na ni{ki ......... 1094 Otka`uvawe na zada~ite............. 1096 Ukrasna gradina ....................... 1096 Otka`uvawe na blokiranite zada~i .......................................... 1100 Sostojbi na ni{kite ............... 1100 Premin vo sostojba na blokiranost ............................... 1101 Prekin na izvr{uvaweto ....... 1101 Blokiranost predizvikana od zaemno isklu~ivata brava (mutex) ........................................ 1107 Meusebna sorabotka na zada~ite1113 wait() i notifyAll() ......................... 1114 Propu{teni signali ............... 1119 notify() vo odnos na notifyAll() .... 1120 Proizveduva~i i potro{uva~i .. 1123 Koristewe eksplicitni objekti od tipovite Lock i Condition ......... 1127 Proizveduva~i-potro{uva~i i redovi za ~ekawe ........................... 1130 Blokira~ki redovi za ~ekawe tost .............................................. 1132 Cevki za vlezno/izlezni operacii pomeu zada~ite ............................. 1135 Zaemna blokada ............................. 1137
CountDownLatch - brava so odbrojuvawe ............................... 1143 Bezbednost na ni{kite od bibliotekata ............................. 1145 Klasata CyclicBarrier.............. 1146 DelayQueue ............................... 1148 PriorityBlockingQueue ........... 1151 Kontrolor na staklenikot so pomo{ na ScheduledExecutor1154 Semafor ..................................... 1158 Exchanger .................................. 1162 Simulacija ..................................... 1164 Simulacija na {alterski slu`benik................................... 1164 Simulacija na restoran .......... 1169 Raspredelba na rabotata......... 1174 Optimizacija na performansite1179 Sporedba na tehnologiite na zaemno isklu~ivite bravi (mutex) ........................................ 1180 Kontejneri bez zaklu~uvawe .. 1189 Za performansite .................... 1190 Sporedba na realizaciite na Map .............................................. 1195 Optimisti~ko zaklu~uvawe ....... 1197 ReadWriteLock ......................... 1199 Aktivni objekti ............................ 1202 Zaklu~ok ......................................... 1206 Literatura za ponatamo{no usovr{uvawe .............................. 1208
Grafi~ki korisni~ki opkru`uvawa Novi komponenti na bibliotekata1143 1210 Apleti ............................................. 1213
Osnovite na Swing ....................... 1213 Alatka za prika`uvawe .......... 1217 Pravewe kop~ ........................ 1217 Fa}awe na nastani ................... 1218 Pove}eredni poliwa za tekst.... 1221 Rasporeduvawe na elementite ... 1223 Rasporeduva~ BorderLayout .. 1223 Rasporeduva~ FlowLayout ...... 1225 Rasporeduva~ GridLayout ....... 1225 Rasporeduva~ GridBagLayout 1226 Apsolutno pozicionirawe .... 1226 Rasporeduva~ BoxLayout ........ 1227 Koj pristap e najdobar? .......... 1227 Model na nastani na grafi~kata biblioteka Swing ........................ 1227 Tipovi nastani i priemnici . 1228 Koristewe na priemni~kite adapteri poradi ednostavnosta1235 Sledewe na pove}e nastani .... 1236 Izbor na Swing komponenti ...... 1239 Kop~iwa ..................................... 1239 Grupi kop~iwa .......................... 1241 Ikoni .......................................... 1242 Prira~ni soveti ...................... 1244 Ednoredni poliwa za tekst.... 1244 Rabovi ......................................... 1246 Mala programa za ureduvawe na tekstot ........................................ 1247 Poliwa za potvrda ................... 1248 Radio-kop~iwa .......................... 1250
Kombinirani listi (pa|a~ki listi) .......................................... 1251 Grafi~ki listi ........................ 1252 Okno so jazi~iwa ...................... 1254 Prozor~iwa za poraki ............ 1255 Menija ......................................... 1257 Popup (iskoknuva~ki) menija 1263 Crtawe ........................................ 1264 Ramki za dijalog ........................ 1268 Dijalozi za rabota so datotekite1272 HTML vo komponentite na bibliotekata Swing ................ 1274 Lizga~i i lenti za napreduvawe1275 Izbirawe izgled i odnesuvawe1276 Stebla, tabeli i clipboard..... 1279 JNLP i Java Web Start ................ 1279 Paralelnoto izvr{uvawe i Swing1284 Dolgotrajni zada~i .................. 1285 Vizuelno programirawe so pove}e ni{ki............................................... 1292 Vizuelnoto programirawe i zrnata na Java ............................................. 1295 [to e zrno? ................................ 1296 Ispituvawe na zrnata so klasata Introspector ............................... 1298 Ponapredno zrno ...................... 1303 Zrnata na Java i sinhronizacijata ...................... 1307 Pakuvawe na zrnoto ................. 1311 Poslo`ena poddr{ka za zrnata1313 Pove}e za zrnata ..................... 1314 Alternativi za Swing ................. 1314
1346 Pravewe klientski Flash Web so A: Dodatoci pomo{ na Flex ................................ 1315 Dodatoci koi mo`at da se prezemat Zdravo, Flex ............................... 1316 od Internet .................................... 1346 Preveduvawe na MXML ............ 1317 MXML i ActionScript............... 1318 Kontejneri i kontroli ........... 1319 Efekti i stilovi ..................... 1321 Nastani ....................................... 1322 Povrzuvawe so Java ................. 1322 Modeli podatoci i povrzuvawe na podatocite ............................ 1325 Izgradba i primena ................. 1326 Da se misli na jazikot C: osnova za Java .................................................. 1346 Seminar Thinking in Java .......... 1347 CD so seminar Hands-On Java .. 1347 Seminar Thinking in Objects ..... 1347 Thinking in Enterprise Java ....... 1348 Thinking in Patterns (with Java)1348 Seminar Thinking in Patterns ... 1349 Konsultacii i revizii na dizajnite1350 1351 .......................................... 1351 Programi za ureduvawe tekst i alatki za pravewe aplikacii..... 1351 Knigi ............................................... 1352 Analiza i proektirawe .......... 1353 Jazikot Python ......................... 1355 Spisok na moite knigi ............ 1356 Spisok na termini koristeni vo knigata ........................................ 1358 1
Izrabotka SWT aplikaciii ...... 1328 B: Resursi Instalirawe SWT ................... 1329 Zdravo, SWT .............................. 1329 Izbegnuvawe na redundantnost1332 Menija ......................................... 1334 Prozor~iwa so karti~ki, kop~iwa i nastani ................... 1336 Grafika ...................................... 1339 Paralelno izvr{uvawe vo SWT1341 Sporedba na SWT i Swing...... 1343 Zaklu~ok ......................................... 1344 Resursi ........................................ 1345
Indeks
Predgovor
Vo po~etokot kon Java imav pristap kako kon "samo u{te eden programski jazik," {to taa vo mnogu ne{ta i e.
No, kako {to vremeto pominuva{e i kolku pove}e ja prou~uvav Java, po~nav da zabele`uvam deka osnovnata namena na Java e poinakva od namenata na site drugi jazici so koi sum se zapoznal. Programirawe zna~i upravuvawe so slo`enost: slo`enosta na problemot koj {to sakate da go re{ite po~iva na slo`enosta na kompjuterot na koj {to problemot se re{ava. Zaradi ovaa slo`enost pogolemiot del od na{ite proekti propa|aat. Sepak, re~isi za nitu eden programski jazik za koj {to znam ne e odlu~eno deka negovata glavna cel bi trebalo da bide sovladuvawe na slo`enosta na razvoj i odr`uvawe na programi1. Sekako, pri kreirawe na programskite jazici slo`enosta se zema predvid vo donesuvawe na mnogu odluki, no vo nekoj moment sekoga{ se nao|ale nekoi raboti za koi {to se mislelo deka se neophodni da se vmetnat vo kombinacija. Tie drugi raboti sekoga{ se pri~ina programerite koi {to go koristat dadeniot jazik da "udrat so glava vo yid". Na primer, C++ mora{e da bide kompatibilen so postariot jazik C (za da im ovozmo`i lesen preod na C programerite) i u{te da bide i efikasen. I dvete raboti se mnogu korisni celi i imaat golemi zaslugi za uspeh na jazikot C++, no isto taka vnesuvaat dopolnitelna slo`enost {to pretstavuva pri~ina nekoi proekti da ostanaat nedovr{eni (sekako, mo`ete da gi obvinite programerite i menaxerite, no ako jazikot bi mo`el da pomogne taka {to }e gi otkriva gre{kite, zo{to toa da ne go pravi?). U{te eden primer, Visual BASIC (VB) be{e vrzan so BASIC, koj {to i ne be{e jazik {to mo`e da se pro{iri, taka {to site pro{iruvawa natrupani vo VB dovedoa do navistina neodr`liva sintaksa. Perl e kompatibilen so postarite Awk, Sed, Grep, i drugi UNIX alatki koi {to treba{e da gi zameni, i kako rezultat na toa e {to toj ~esto e obvinuvan deka proizveduva "kod samo za zapi{uvawe" (toa zna~i deka po nekoe vreme kodot pove}e ne mo`ete da go pro~itate). Od druga strana, koga se kreirani C++, VB, Perl, i drugi jazici kako {to e Smalltalk, vlo`eni se i napori za re{avawe na slo`enosta i kako rezultat na toa, ovie jazici se uspe{ni vo re{avawe na opredeleni vidovi na problemi.
Mislam deka programskiot jazik Python e najblisku do ovaa cel. Poglednete na www.Python.org
Predgovor
Dodeka ja u~ev Java, najmnogu vpe~atok na mene ima{e toa {to nekade vo kombinacijata na celite na proektirawe na kompanijata Sun postoe{e cel za namaluvawe na slo`enosta za programerot. Tie kako da ka`uvaat, "Nam ni e va`no da go reducirame vremeto i te{kotiite pri proizvodstvoto na golem kod." Vo po~etokot, ovaa cel rezultirala so kod koj {to ne se izvr{uval brzo (iako toj so tekot na vremeto se podobruval), no toa navistina za~uduva~ki go namalilo vremeto potrebno za pi{uvawe na programa za izrabotka na programa vo Java treba dvapati pomalku vreme otkolku za izrabotka na soodvetna programa vo C++. Samo ovoj rezultat mo`e da za{tedi mnogu vreme i pari, no Java ne zastanuva tuka. Taa mnogu od slo`enite zada~i koi {to stanuvaat va`ni, kako {to se pove}eni{kovnoto i mre`noto programirawe, prodol`uva da gi pakuva vo svojstva na jazikot ili biblioteki koi {to ponekoga{ ovie zada~i gi pravat lesni. I kone~no, taa se zafati so nekoi mnogu slo`eni problemi: me|uplatformsko programirawe, dinami~ki primeni na kod, duri i pra{awe na za{tita, sekoj od ovie problemi na va{ata skala na slo`enosta mo`e da se najde kade bilo vo delot od "pre~ka" do "nevozmo`no". Zna~i, i pokraj problemite so performansite so koi {to se sretnavme, vetuvaweto na Java e golemo: taa od nas mo`e da napravi mnogu poproduktivni programeri. Na site na~ini so kreirawe na programi, so rabota vo tim, so izrabotka na korisni~ki opkru`uvawa kako vrska so korisnikot, so izvr{uvawe programi na razli~ni tipovi na kompjuteri, i so lesno pi{uvawe programi koi komuniciraat preku Internet - Java go zgolemuva opsegot na komunikacija pome|u lu|eto. Mislam deka rezultatite na komunikaciskata revolucija mo`ebi ne mo`at da se vidat od efektite na dvi`eweto na ogromni koli~estva bitovi (informacii) preku Internetot. Nie }e ja vidime vistinskata revolucija bidej}i nie site }e komunicirame pome|u sebe polesno: eden so eden, no isto taka vo grupi i kako cela planeta. Se zboruva deka slednata revolucija bi mo`ela da proizvede nekoj vid na globalen um koj {to bi bil rezultat na dovolno lu|e i nivna dovolna me|usebna povrzanost. Java mo`e, no i ne mora, da bide alatka koja {to }e ja pottikne takvata revolucija, no i najmala takva mo`nost pravi da se ~uvstvuvam deka pravam ne{to mnogu zna~ajno, obiduvaj}i se da gi pou~uvam lu|eto za ovoj jazik
Da se razmisluva vo Java
Brus Ekel
jazikot Java ne postignaa celosen uspeh vo taa zada~a, no voop{to, tie napravija golemi ~ekori vo vistinskata nasoka. Edna od va`nite celi na ova izdanie e vo potpolnost da se opfatat podobruvawata na Java SE5/6, i tie da se vovedat i iskoristat vo celata kniga. Toa zna~i deka ova izdanie pravi jasen ~ekor da bide "samo Java SE5/6," i golem del od kodot vo knigata nema da se preveduva (kompajlira) so porane{nite verzii na Java; dokolku se obidete toa da go napravite, sistemot }e se pobuni i }e zastane. Sepak, mislam deka dobivkite se vredni za takov rizik. Dokolku morate da koristite porane{ni verzii na Java, preku www.MindView.net mo`ete besplatno da gi prezemete prethodnite izdanija na ovaa kniga. Od razli~ni pri~ini, odlu~iv vo besplaten elektronski oblik da ne go ponudam tekovnoto izdanie na knigata, tuku samo prethodnite verzii.
Java SE6
Ovaa kniga be{e ogromen proekt za koj {to treba{e mnogu vreme, i pred taa da izleze se pojavi beta verzija na Java SE6 (so rabotnoto ime mustang). Iako vo Java SE6 postojat nekoi mali izmeni koi podobrija nekoi primeri od knigata, tie glavno nemaat vlijanie na sodr`inata na ovaa kniga; glavnite obele`ja bea prvenstveno podobruvawata na brzinata i bibliote~nite obele`ja koi {to ne se tema na ovaa kniga. Kodovite od knigata uspe{no se testirani na kandidatskata verzija na Java SE6, taka {to ne o~ekuvam deka nekoi nejzini izmeni }e imaat vlijanie na sodr`inata na knigata. Dokolku ima nekoi pova`ni izmeni od vremeto na objavuvawe na oficijalnata verzija na Java SE6, tie }e bidat prifateni vo izvorniot kod vo knigata koj {to mo`ete da go prezemete na www.MindView.net.Na koricite e istaknato deka knigata e za "Java SE5/6," {to zna~i deka e "pi{uvana za Java SE5 i mnogu va`ni izmeni koi {to taa verzija gi vnese vo jazikot, no podednakvo mo`e da se primeni i za Java SE6."
^etvrtoto izdanie
Zadovolstvoto vo pi{uvawe na novo izdanie na kniga e vo "pravilno" zemawe na rabotite spored ona {to sum go nau~il od izleguvaweto na poslednoto izdanie. ^esto tie uvidi se od tipot "U~ebno iskustvo e ona {to }e go dobie{ koga nema da go dobie{ ona {to go saka{ " i za mene toa e mo`nost da go ispravam ona {to e pogre{no ili ednostavno e zamorno. Isto taka, pi{uvawe na novo izdanie doveduva do novi fascinantni idei, i pogodenosta od gre{kite e mnogu pomal od u`ivaweto vo otkrivawe i mo`nosta ideite da se izrazat podobro otkolku prethodno.
Predgovor
Isto taka postoi predizvikot knigata da se napi{e taka {to i sopstvenicite na nekoi od prethodnite izdanija }e posakaat da ja kupat knigata. Toa me prinuduva da podobruvam, preureduvam i povtorno organiziram s {to mo`am za knigata da ja napravam da bide novo i vredno iskustvo za posvetenite ~itateli.
Izmeni
CD-ROM-ot, koj {to tradicionalno be{e sostaven del od ovaa kniga, nema da bide del od ova izdanie. Osnovniot del od ova CD, multimedijalniot seminar Da se razmisluva vo C (koj {to za MindView go napravil ^ak Alison), sega e dostapen i mo`e da se prezeme kako Fle{ prezentacija. Celta na ovoj seminar e da gi podgotvi onie {to ne se dovolno zapoznaeni so sintaksata na C da go razberat materijalot prezentiran vo ovaa kniga. Iako dve glavi vo knigata davaat pristoen voved vo sintaksata, tie mo`ebi nema da bidat dovolni za lu|eto bez soodvetno predznaewe, a prezentacijata Da se razmisluva vo C tokmu nim im e nameneta, za da go dostignat potrebnoto nivo. Glavata Paralelnoto izvr{uvawe (porano nare~eno "Izvr{uvawe vo pove}e ni{ki") e kompletno prerabotena za da gi prilagodi golemite izmeni vo soodvetnite biblioteki na Java SE5, no s u{te dava temel za osnovnite koncepti na paralelnoto izvr{uvawe. Bez ova jadro, }e vi bide te{ko da gi razberete poslo`enite oblasti na paralelnoto izvr{uvawe. Mnogu meseci sum rabotel na ova, zadlabo~en vo toj drug "paralelen," svet, i na kraj se poka`a deka taa glava obezbeduva ne samo osnova, tuku isto taka i potfati vo ponapredna teritorija. Vo knigata ima i nova glava posvetena na novite mo`nosti na Java SE5, a nekolku drugi mo`nosti se protkaeni vo izmenite napraveni na postojniot materijal. Bidej}i jas neprekinato gi prou~uvam dizajnite na modelite, nivniot broj vo knigata isto taka e zgolemen. Knigata pretrpi zna~ajna reorganizacija. Mnogu od preureduvawata se pottiknati od procesot na pou~uvawe i od sfa}aweto deka, mo`ebi, moeto sogleduvawe za toa {to treba da sodr`i edna "glava" bi mo`elo povtorno da se obmisli. Jas nepromisleno bev ubeden deka edna tema mora da bide "dovolno golema" za da mo`e da bide glava. No, osobeno dodeka predavav za modeli na dizajn, sfativ deka posetitelite na seminarot najdobro razbiraat koga voveduvam eden po eden model i vedna{ potoa }e napravime soodvetna ve`ba, duri i ako toa zna~i deka jas samo nakratko zboruvam (otkriv deka takvoto tempo e pozabavno i za mene kako predava~). Od tie pri~ini vo ovaa verzija na knigata se obidov da gi podelam glavite na temi bez da se gri`am za toa kolku temite se dolgi. Smetam deka toa be{e podobruvawe.
Da se razmisluva vo Java
Brus Ekel
Isto taka sfativ kolku e va`no testiraweto na programi. Dokolku nemate vgradeno ramka za testirawe so testovi koi se izvr{uvaat sekoga{ koga go gradite Va{iot sistem, ne mo`ete da znaete dali va{ata programa e sigurna ili ne. Za da ja odbegnam takvata nesigurnost, napraviv ramka za testirawe koj {to prika`uva i potvrduva rezultati na sekoja programa. (Ramkata e napi{ana vo Python; mo`ete da ja najdete vo kodot na knigata koj {to mo`ete da go prezemete od lokacijata www.MindView.net.) Testiraweto voop{to e razgledano vo dodatokot objaven na adresata http://MindView.net/ Books/BetterJava, vo koj {to se objasneti osnovnite ve{tini koi, spored mene sega, site programeri trebalo da gi imaat vo nivniot osnoven programski alat. Osven toa, gi pregledav site primeri vo knigata u{te edna{ i se zapra{av sebe si, "Zo{to toa go stori na ovoj na~in?" Vo pogolemiot broj na primeri napraviv nekoi izmeni i podobruvawa, so cel primerite da bidat podosledni i isto taka da go demonstriram ona za {to jas smetam deka e najdobra praksa za pi{uvawe kodovi vo Java (kolku {to toa e mo`no vo tekst od po~etno nivo). Mnogu od postojnite primeri zna~itelno se izmeneti vo dizajnot i realizacijata. Primeri koi {to za mene pove}e nemaa smisla se otstraneti, a dodadeni se novi primeri. ^itatelite mi ispratija mnogu navistina ubavi komentari za prvite tri izdanija na knigata, {to za mene be{e vistinsko zadovolstvo. Se slu~uva{e ponekoj da ima i primedba, od nekoja pri~ina, od vreme na vreme ima{e ista primedba "Knigata e pregolema." Spored mene, dokolku na ~itatelot mu pre~i samo toa {to "ima premnogu stranici " toa i ne e tolku stra{no. (Da se potsetime na primedbata na avstriskiot car za deloto na Mocart: "Premnogu noti!" Ova ne zna~i deka jas na koj bilo na~in se sporeduvam so Mocart.) Mo`am samo da pretpostavam deka takva primedba doa|a od onie koi {to u{te ne se zapoznale so ogromnosta na samiot jazik Java i koi {to ne gi videle drugite knigi za ovoj jazik. Sepak, se obidov vo ova izdanie da gi namalam delovite koi {to stanaa zastareni ili barem nemaat pregolemo zna~ewe. Voop{to, se obidov da go otstranam s ona {to pove}e ne e potrebno, da gi vklu~am izmenite i da go podobram s ona {to mo`ev da go podobram. Bev sloboden toa da go napravam, bidej}i originalniot materijal i ponatamu e na Veb sajtot (na adresata www.MindView.net) vo forma na prvite tri izdanija koi {to besplatno mo`at da se prezemaat, i vo forma na dodatoci na ovaa kniga, koi isto taka mo`at besplatno da se prezemat. Iskreno im se izvinuvam na site onie koi{to ne mo`at da se pomirat so goleminata na knigata. Veruvale ili ne, rabotev naporno za da go namalam obemot na stranicite.
Predgovor
Blagodarnost
Prvo, im se blagodaruvam na sorabotnicite koi {to rabotea so mene na seminari, vo konsultacii i vo razvivawe na nastavni proekti: Dave Bartlett, Bill Venncrs, Chuck Allison, Jeremy Meyer i Jamie King. Go po~ituvam Va{eto trpenie, dodeka i ponatamu se obiduvam da napravam najdobar model za sorabotka na nezavisni lu|e kako {to sme nie.
Da se razmisluva vo Java
Brus Ekel
Od pred nekoe vreme, bez somnenie blagodarej}i na Internet, se povrzav so za~uduva~ki golem broj lu|e koi {to mi pomagaat vo rabotata, glavno rabotej}i vo svoite doma{ni kancelarii. Porano bi bil prinuden da iznajmam ogromen kancelariski prostor kade {to bi gi smestil site tie lu|e, no blagodarej}i im na Mre`ata, ekspresnata po{ta i telefonot, jas ja imam nivnata pomo{ bez dopolnitelni tro{oci. Dodeka se obiduvav da nau~am kako "ubavo da igram so ostanatite," site Vie bevte od golema pomo{, i jas se nadevam deka i ponatamu }e u~am kako da ja rabotam podobro mojata rabota so tu|a pomo{. Paula Steuer e neprocenliva zatoa {to ja prezede mojata slu~ajna delovna praksa i ja postavi na zdravi temeli (ti blagodaram Paula, {to ne mi dava{e mir koga nemav `elba ne{to da napravam). Jonathan Wilcox, Esq., ubavo ja razgleda strukturata na moeto pretprijatie, go svrte sekoj kamen pod koj mo`ebi se krijat {korpioni i ne primora da ja pomineme postapkata na pravnoto organizirawe. Ti blagodaram na gri`ata i upornosta. Sharlynn Cobaugh od sebe napravi stru~wak za obrabotka na zvuk i stana va`en del od timot za kreirawe na multimedijalni prezentacii, i isto taka za re{avawe na drugi problemi. Ti blagodaram na upornosta {to ja ima{ koga se soo~uva{ so nepredvidlivi kompjuterski problemi. Lu|eto od firmata Amaio vo Praga mi pomognaa da se izvle~am od nepriliki vo nekolku proekti. Daniel Will-Harris prv me zapozna so rabota preku Internet, i toj e glaven dizajner na site re{enija na grafi~ki dizajn.
Niz godinite, preku svoite konferencii i rabotilnici, Gerald Weinberg stana moj neoficijalen trener i mentor, za {to sum mu blagodaren. Ervin Varga be{e isklu~itelno korisen so tehni~kite ispravki vo ~etvrtoto izdanie iako drugi pomagaa vo poedine~ni glavi i primeri, Ervin be{e osnoven tehni~ki recenzent na celata kniga, i toj go preraboti vodi~ot so re{enija za ~etvrtoto izdanie. Ervin gi najde gre{kite i vovede podobruvawa vo knigata koi {to pretstavuvaat neprocenliv pridones na tekstot. Negovata temelnost i vnimanieto {to go obrnuva na detalite se za~uduva~ki, toj e najdobriot recenzent {to dosega sum go imal. Ti blagodaram, Ervin.
Mojot blog na sajtot na Bill Venners www.Artima.com be{e izvor na pomo{ koga barav tu|i mislewa. Im se zablagodaruvam na ~itatelite koi {to mi pomognaa da gi razjasnam konceptite so ispra}awe na komentari vklu~uvaj}i gi James Watson, Howard Lovatt, Michael Barker, i drugi, osobeno onie {to mi pomignaa so generi~kite tipovi0. Mu se zablagodaruvam na Mark Welsh za negovata postojana pomo{. Evan Cofsky prodol`uva da mi dava golema poddr{ka so negovoto poznavawe (vo detali) na site zamrseni poedinosti za podesuvawe i odr`uvawe na Veb serveri bazirani na Linux, toj se gri`i serverot MindView sekoga{ da bide dostapen i bezbeden.
Predgovor
Osobeno mu se zablagodaruvam na mojot nov prijatel, kafeto, koe {to mi vlea re~isi neograni~en entuzijazam za ovoj proekt. Kafuleto Camp4 vo gradot Crested Butte vo dr`avata Kolorado, stana standardno sobirali{te na lu|eto koi {to doa|aa na seminarite na MindView, i za vreme na seminarite na odmorite ni obezbeduva{e najdobroto snabduvawe so hrana i pija~ki {to nekoga{ sum go imal. Mu blagodaram na mojot drugar Al Smith {to go napravil kafuleto i {to go pretvoril vo tolku interesno i zabavno mesto. Im se zablagodaruvam i na site barmeni vo kafuleto koi taka veselo razdeluvaat pijaloci. Im se zablagodaruvam i na lu|eto od Prentice Hall za postojanoto davawe na se {to }e posakam, izleguvaj}i vo presret na site moi barawa i za izleguvaweto nadvor od nivniot standarden pat za da ovozmo`at rabotite vo vrska so mene da se izvr{uvaat glatko. Odredeni alatki se poka`aa neprocenlivi za vreme na mojot razvoen proces i jas ~uvstvuvam golema blagodarnost kon nivnite kreatori sekoga{ koga }e gi koristam niv. Cygwin (www.cygwin.com) re{i bezbroj problemi za mene koi {to Windows ne saka ili ne mo`e da gi re{i, sekoj den s pove}e sum mu privrzan (samo da go imav pred 15 godini koga mojot mozok be{e prilepen za GNU Emacse). Eclipse na IBM (www.eclipse.org) navistina e ubav pridones za zaednicata na proektanti, pa o~ekuvam deka i ponatamu }e dava golemi rezultati, bidej}i i ponatamu se razviva (od koga IBM stana kul? Mora ne{to da sum propu{til). Jet-Brains IntelliJ Idea prodol`uva da probiva novi kreativni pati{ta vo razvoj na alatkite. Za ovaa kniga zapo~nav da go koristam Enterprise Architect od Sparxsysteill i toj nabrgu stana mojata omilena UML alatka. Vo mnogu priliki dobro mi koriste{e formaterot na kodovi Jalopy na Marco Hunsicker (www.triemax.com), a Marco mi izleze presret i formaterot go konfigurira{e spored moite specifi~ni potrebi. Ponekoga{ mi koriste{e i Jedit na Slava Pestov (www.jedit.org) i negovite softverski dodatoci (plug-ins) i toa e sosema dobar editor za po~etnicite na seminarot. I sekako, dokolku ve}e toa dosega ne go ka`av dovolen broj pati na site mo`ni mesta, za re{avawe na problemi sekoga{ go koristam Python (www.Python.org). Toj e proizvod na mojot drugar Guido Van Rossum i grupa na budalesti genijalci so koi sum pominal nekolku prekrasni denovi tr~aj}i (Tim Peters, gluv~eto {to mi go pozajmi go uramiv i go narekov "TimBotMouse"). Vie, mom~iwa, treba da najdete pozdravi mesta za ru~ek. (Isto taka, golema blagodarnost do celata zaednica na Python, toa e fenomenalna grupa na lu|e.) Mnogu lu|e mi pra}aa ispravki i kon site niv sum dol`en, no osobena blagodarnost zaslu`uvaat (za prvoto izdanie): Kevin Raulerson (koj {to
Da se razmisluva vo Java
Brus Ekel
pronajde izobilie na sjajni buba~ki), Bob Resendes (ednostavno neverojaten), John Pinto, Joe Dante, Joe Sharp (site trojca se ~udesni), David Combs (mnogu gramati~ki ispravki i pojasnenija), Dr. Robert Stephenson, John Cook, Franklin Chen, Zev Griner, David Karr, Leander A. Stroschein, Steve Clark, Charles A. Lee, Austin Maher, Dennis P. Roth, Roque Oliveira, Douglas Dunn, Dejan Risti}, Neil Galarneau, David B. Malkovsky, Steve Wilkinson, i mnogu drugi. Prof. dr. Marc Meurrens vlo`i golemi sili za da ja objavi i napravi dostapna elektronskata verzija na prvoto izdanie vo Evropa. Im se zablagodaruvam na site {to mi pomognaa povtorno da gi napi{am primerite so koristewe na bibliotekata Swing (za vtoroto izdanie), i za sekoja druga pomo{: Jon Shvarts, Thomas Kirsch, Rahim Adatia, Rajesh Jain, Ravi Manthena, Banl! Rajamani, Jens Brandt, Nitin Shivaram, Malcolm Davis, i na site {to mi izrazija poddr{ka. Vo ~etvrtoto izdanie, Chris Grindstaff mnogu mi pomogna vo razvojot na delot za SWT, a Sean Neville za mene ja napi{a prvata verzija na delot za Flex. Sekoga{ koga }e pomislam deka kone~no s sum nau~il za programirawe za paralelnoto izvr{uvawe, se otvora nova vrata i se poka`uva deka imam nova planina za iska~uvawe. Mu se zablagodaruvam na Brian Goetz {to mi pomogna da gi sovladam site pre~ki vo novata verzija na glavata Paralelnoto izvr{uvawe, i {to gi pronajde site gre{ki (se nadevam!). Ne e iznenaduvawe toa {to poznavaweto na Delphi mi pomogna da ja razberam Java, bidej}i ovie dva jazika imaat mnogu zaedni~ki koncepti i proektantski re{enija. Moite prijateli {to se zanimavaat so Delphi mi pomognaa dlaboko da navlezam vo vnatre{nosta na ova sjajno programersko opkru`uvawe. Toa se Marco Cantu (u{te eden Italijan mo`ebi dobro poznavawe na Latinskiot jazik pridonesuva na naklonetosta kon programskite jazici?) Neil Rubenking (koj {to se zanimava{e so joga, vegetarijanstvo i zen dodeka ne gi otkri kompjuterite), i, sekako, Zack Urlocker (prviot direktor na proektot Delphi), stariot prijatel so koj sum go propatuval svetot. Site nie sme dol`nici na brilijantniot Anders Hejlsberg, koj {to i ponatamu se ma~i so C# (a toj jazik be{e glavnata inspiracija za Java SE5, kako {to ponatamu }e vidite vo knigata).
Uvidite i poddr{kata na mojot prijatel Richard Hale Shaw mi bea mnogu korisni (isto kako i onie na Kim). Richard i jas pominavme pove}e meseci zaedno vo odr`uvawe seminari i vo obidi da ostvarime sovr{eno u~ebno iskustvo za u~esnicite na seminarite.
Predgovor
Dizajnot na knigata, dizajnot na koricite i slikata na koricite gi napravi mojot prijatel Daniel Will-Harris, priznat avtor i dizajner (www.WillHarris.com) koj {to si igra{e so samoleplivi bukvi vo osnovnoto u~ili{te dodeka ~eka{e kompjuterite i izdava{tvoto da bidat otkrieni, i koj {to mi se `ale{e, mrmorej}i nad moite algebarski problemi. Sepak, knigata sam ja sostaviv, taka {to site gre{ki za sostavuvaweto se na moja smetka. Pi{uvav vo Microsoft Word XP za Windows, a fotoslogot e podgotven vo Adobe Acrobat; knigata e kreirana direktno od Acrobat PDF datoteki. Se slu~i da prestojuvam vo stranstvo koga gi napraviv finalnite verzii na prvoto i vtoroto izdanie na knigata prvoto izdanie go isprativ od Kejptaun, Ju`na Afrika, a vtoroto od Praga. Tretoto i ~etvrtoto izdanie gi prativ od Crested Butte, Kolorado. Oblikot na fontot na glavniot del od tekstot e Georgia, a na naslovite e Verdarw. Fontot na naslovnata strana na knigata e fTC Ren nie Mackintosh. Osobeno im se zablagodaruvam na moite u~iteli i na site moi studenti (koi {to isto taka se i moi u~iteli). Dodeka rabotev na ova izdanie, ma~kata Moli ~esto mi le`e{e vo skut i na toj na~in mi dava{e svoja topla i krznena poddr{ka. Na spisok na prijatelite koi {to mi pomagaa, pome|u ostanatite se nao|aat i: Patty Gast (Masseuse extraordinaire), Andrew Binstock, Steve Sinofsky, JD Hildebrandt, Tom Keffer, Brian McElhinney, Brinkley Barr, Bill Gates od Midnight Engineering Magazine, Larry Constantine i Lucy Lockwood, Gene Wang, Dave Mayer, David Intersimone, Chris i Laura Strand, familijata Almquists, Brad Jerbic, Marilyn Cvitanic, Mark Mabry, familijata Robbins, familijata Moelter (i familijata McMillans), Michael Wilk, Dave Stoner, familijata Cranstons, Larry Fogg, Mike Sequeira, Gary Entsminger, Kevin i Sanda Donovan, Joe Lordi, Dave i Brenda Bartlett, Patti Gast, Blake, Annette & Jade, familijata Rentschlers, familijata Sudeks, Dick, Patty, i Lee Eckel, Lynn i Todd, i nivnite familii. i sekako, moite roditeli.
10
Da se razmisluva vo Java
Brus Ekel
Voved
Na ~ovekot mu dade govor, a govorot ja stvori mislata, koja e merka na Univerzumot Oslobodeniot Prometej, [eli.
^ove~kite bitija...sosema se pod vladeewe na opredelen jazik koj {to stana sredstvo na izrazuvawe vo nivnite op{testva. Vo zabluda e onoj {to misli deka vo prilagoduvaweto na poedinecot kon stvarnosta, jazikot ne igra zna~ajna uloga i deka jazikot e samo slu~ajno sredstvo za re{avawe na specifi~nite problemi na komunikacijata i misleweto. Fakt e deka vistinskiot svet vo golema merka nesvesno e izgraden vrz osnova na jazi~kite naviki na grupata. Status na lingvistikata kako nauka, Edvard Sapir 1929. Kako i koj bilo drug ~ove~ki jazik, Java ovozmo`uva izrazuvawe na poimi. Dokolku uspe{no go sovladate, so samoto rastewe i uslo`nuvawe na problemite, ovoj na~in na izrazuvawe }e vi bide mnogu polesen i pofleksibilen od koj bilo drug jazik. Na Java ne mo`ete da gledate samo kako na kolekcija od mo`nosti nekoi od mo`nostite nemaat smisla sami za sebe. Sevkupnosta na site delovi mo`ete da ja koristite samo dokolku razmisluvate za proektirawe, a ne samo za pi{uvawe kod. Za da ja razberete Java na vakov na~in, morate da gi razberete i problemite {to }e se javuvaat pri proektiraweto, kako i pri programiraweto voop{to. Vo knigava se razgledani problemi {to mo`at da se javat pri programirawe, objasneto e zo{to tie pretstavuvaat problem i se uka`uva na postapkite so koi {to Java gi re{ava. Zaradi tie pri~ini, mno`estvoto na mo`nostite {to gi objasnuvam vo sekoja glava se zasnovuva na na~inot na re{avawe na opredelen vid na problem so pomo{ na Java. Na toj na~in, jas se nadevam deka, malku po malku, }e ve dovedam do nivo koga na Java }e razmisluvate kako na va{iot maj~in jazik. Od po~etok pa do kraj, poa|am od stavot deka vie sakate vo Va{ata glava da izgradite model koj }e Vi ovozmo`i da razviete dlaboko razbirawe na jazikot; dokolku naidete na problem, }e mo`ete da go ufrlite vo svojot model i da pronajdete odgovor.
Voved
11
Preduslovi
Ovaa kniga pretpostavuva deka Vie ste kolku-tolku zapoznaeni so programirawe. Razbirate deka programa e mno`estvo od naredbi, zapoznaeni ste so principite na potprogrami/funkcii/makroa, zapoznaeni ste so kontrolnite strukturi kako {to se if, konstrukciite na jazol kako {to e while i taka natamu. S ova ste mo`ele da go nau~ite na razli~ni mesta, da re~eme pri programirawe na nekoj makro-jazik ili pri rabota so alatka kako {to e Perl. Bez razlika kolku vo dosega{noto programirawe ste gi sovladale osnovnite idei, }e mo`ete da rabotite po ovaa kniga. Se razbira deka knigava }e im bide polesna na C programerite, i u{te pove}e na C++ programerite, no ne otka`uvajte se dokolku nemate iskustvo vo ovie jazici samo bidete podgotveni naporno da rabotite. Isto taka, so pomo{ na multimedijalniot seminar Thinking in C koj {to mo`ete da go prezemete od lokacijata www.MindView.net, vo potpolnost }e gi sovladate osnovite potrebni za u~ewe Java. Niz knigata postapno }e gi voveduvam konceptite na objektno orientiranoto programirawe (OOP) i osnovnite kontrolni mehanizmi na Java. Duri i koga se povikuvam na osobini na jazicite C i C++, toa ne go pravam so namera da dadam komentar kako poznava~ na tie jazici, tuku da im uka`am na programerite da ja sporedat Java so jazicite od koi {to taa e proizlezena. ]e se obiduvam sporedbite da bidat ednostavni i }e go objasnam s ona za koe {to mislam deka ne mu e poznato na nekoj {to ne gi koristi C/C++.
U~ewe na Java
Nekade vo isto vreme koga izleze mojata prva kniga, Using C++ (Osborne/McGraw Hill, 1989), zapo~nav da go pou~uvam toj jazik. Pou~uvaweto na programskite jazici stana moja profesija: gledav glavi {to se klimaat, beli lica i zbuneti izrazi vo publika niz celiot svet u{te od 1987. Koga zapo~nav privatno da obu~uvam pomali grupi, vo tekot na ve`bite otkriv ne{to. Duri i onie lu|e koi se smeeja ili klimaa so glavite bea zbuneti od mnogu pra{awa. Pove}e godini predsedavav na otsekot za C++ na Konferencijata za razvoj na softverot (podocna i na otsekot za Java), i zabele`av deka jas i drugi govornici sme skloni na prose~nata publika da servirame premnogu informacii za kuso vreme. Zaradi razli~ni nivoa na lu|eto vo publikata i zaradi na~inot na koj {to go pretstavuvav materijalot, na kraj bi zagubil eden del na slu{atelite. Mo`ebi jas premnogu baram, no zaradi otporot {to go ~uvstvuvam kon tradicionalniot na~in na predavawe (a veruvam deka i pogolemiot del na slu{atelite go ~uvstvuva istiot otpor zaradi dosada), se obidov moite predavawa da gi napravam taka {to na nikogo nema da mu bidat dosadni. 12 Da se razmisluva vo Java Brus Ekel
Edno vreme imav mnogu razli~ni prezentacii za relativno kus period. Taka i se najdov vo situacija da u~am so metod na obidi i gre{ki ({to pretstavuva dobar na~in i za proektirawe na programite). Na kraj go iskoristiv seto ona {to go imam nau~eno kako predava~ i napraviv kurs koj {to bi sakal da go odr`uvam podolgo vreme. Sega ovoj kurs mojata kompanija MindView Inc. go nudi kako javen i privaten seminar za Java; toa e na{iot glaven voveden seminar, koj {to ja dava osnovata za ponaprednite seminari. Za ovie seminari mo`ete da doznaete pove}e na adresata www.MindView.net. (Vovedniot seminar e isto taka dostapen i vo oblik na kompakt disk Hands on Java. Podatocite za nego se nao|aat na istiot Veb sajt.) Povratnite informacii koi {to gi dobivam od sekoj seminar mi pomagaat da go prerabotuvam materijalot s dodeka ne dojdam do zaklu~ok deka materijalot e soodveten kako sredstvo za podu~uvawe. Ovaa kniga ne ja so~inuvaat samo zabele{kite od seminarite: vo nea se obidov da dadam {to pove}e informacii i gi podrediv taka {to }e ve vodat od eden do drug predmet. Imav ideja knigata da mu slu`i na poedine~en ~itatel koj {to se bori so nov programski jazik.
Celi
Kako i mojata prethodna kniga, Da se razmisluva vo jazikot C++ i ovaa kniga e pi{uvana vo soglasnost so na~inot na koj {to lu|eto go u~at jazikot Java. Koga razmisluvam za glava vo knigata, nea ja zamisluvam kako dobra lekcija vo tekot na seminar. Povratnite informacii od slu{atelite na seminarite mi pomognaa da otkrijam delovi {to se pote{ki za razbirawe i baraat dopolnitelni objasnuvawa. Vo oblastite kade {to bev premnogu ambiciozen i imav vovedeno premnogu novi poimi i svojstva naedna{, sfativ niz procesot na prika`uvawe na materijalot deka pri voveduvawe na pove}e novi poimi potrebni se objasnuvawa za site niv, {to lesno mo`e da go zabuni slu{atelot. Sekoja glava se obiduva da podu~uva eden poim, ili mala grupa na svrzani poimi, bez potpirawe na konceptite koi s u{te ne ste gi vovele. Na toj na~in, pred da prodol`ite ponatamu, mo`ete da go prerabotite sekoj del od teorijata vo kontekstot na Va{eto tekovno znaewe. Celite {to sakav da gi ostvaram vo knigata se slednite:
Voved
13
14
Da se razmisluva vo Java
Brus Ekel
poglavjeto Obrabotka na gre{ki so isklu~oci, kon {to bi mo`ele da go dodadete vovedot vo JDBC, servletite i serverskite Java stranici. Ova go so~inuva osnovniot kurs i jadroto na CD-to Hands-On Java. Ostatokot od knigata go opfa}a kursot od sredno nivo i se nao|a na CD-to Intermediate Thinking in Java. I dvata CD-a mo`ete da gi kupite na www.MindView.net. Dokolku vi se potrebni informacii za dopolnitelni materijali za poddr{ka na profesorot, obratete se do Prentice-Hall na sajtot www.prenhallprofessional.com.
Dokumentacija na Veb
Jazikot Java i negovite biblioteki od Sun Microsystems (besplatno se prezemaat od lokacijata http://java.sun.com) imaat dokumentacija vo elektronski oblik, na koja {to mo`ete da pristapite i da ja ~itate koristej}i Veb pregleduva~. Mnogu knigi za Java ja kopiraat ovaa dokumentacija. Zaradi toa {to takvata dokumentacija ili ve}e ja imate, ili mo`ete da ja prezemete od Veb, i dokolku toa ne e neophodno, vo knigata nema da ja povtoruvame, bidej}i obi~no mnogu pobrgu }e najdete opisi na nekoja klasa so pomo{ na Veb pregleduva~, otkolku da ja barate vo kniga (i dokumentacijata na Veb verojatno poredovno se a`urira). Ednostavno }e ve upatam na dokumentacija na JDK. Knigata }e obezbedi dopolnitelni opisi na klasite samo toga{ koga e neophodno da ja dopolnite dokumentacijata za mo`ete da razberete odreden primer.
Ve`bi
Zabele`av deka poednostavni ve`bi im pomagaat na studentite da go razberat materijalot od seminarite, zatoa na krajot na sekoja glava }e dadam po nekolku ve`bi. Pogolemiot broj od ve`bite se taka dizajnirani za relativno lesno i vo razumen period da mo`at da se srabotat vo u~ilnica, pod nadzor na instruktor koj {to }e kontrolira dali site studenti ja imaat sovladano izlo`enata materija. Nekoi od ve`bite se popredizvikuva~ki, no niedna od niv ne e nere{liva. Re{enija na odbranite ve`bi se nao|aat vo elektronskiot dokument pod imeto The Thinking in Java Annotated Solution Guide, koj {to mo`ete da go kupite preku sajtot www.MindView.com..
Temelite na Java
So knigata dobivate i besplaten multimedijalen seminar koj {to mo`ete da go prezemete od sajtot www.MindView.com. Toa e seminarot Da se razmisluva
Voved
15
vo C (Thinking in C), koj {to }e Ve vovede vo sintaksata, operatorite i funkciite na jazikot C na koi se bazira sintaksata na Java. Vo prethodnite izdanija na knigata na angliski jazik, seto ova se nao|a{e na pridru`noto CD-to Osnovi na Java (Foundations for Java), no sega mo`e besplatno da se prezeme. Najnapred go ovlastiv ^ak Alison (Chuck Allison) da go napravi seminarot Da se razmisluva vo C (Thinking in C) kako nezavisen proizvod, no potoa odlu~iv da go vklu~am nego kon vtoroto izdanie na knigata Da se razmisluva vo C++ (Thinking in C++) i kon vtoroto i tretoto izdanie na knigata Da se razmisluva na Java (Thinking in Java), od pri~ina {to na seminarite sekoga{ doa|aa lu|e bez dovolno da ja poznavaat osnovnata sintaksa na C. Se ~ini deka takvite lu|e razmisluvaat: Jas sum umen programer i nema da go u~am jazikot C, tuku C++ ili Java, C }e go skoknam i vedna{ }e pominam na C++/Java. Otkako }e dojdat na seminar, lu|eto poleka }e sfatat deka imav mnogu dobra pri~ina {to poznavaweto na C sum go navel kako preduslov za sledewe na seminarot. Tehnologiite se menuvaat, i be{e podobro seminarot Da se razmisluva vo C da se preraboti kako Flash prezentacija koja {to mo`e da se prezeme od Internet, otkolku da se prisposobi za CD. Kako toj seminar e dostapen preku Internet, mo`am da obezbedam sekoj zainteresiran u~esnik na mojot seminar da mo`e da zapo~ne so soodvetna podgotovka. Seminarot Da se razmisluva vo C isto taka ovozmo`uva knigata da se obrati do po{iroka publika. Iako nejzinite glavi Operatori i Kontrolirawe na izvr{uvaweto gi opfa}aat osnovite na Java koi {to proizleguvaat od jazikot C, mre`niot (onlajn) seminar pove}e postapno go voveduva ~itatelot, i pretpostavuva pomalo programerskoto predznaewe otkolku za knigata.
Izvoren kod
Kompletniot izvoren kod od knigata e dostapen kako sloboden softver za{titen so avtorskite prava, koj se distribuira kako eden paket, so posetuvawe na Veb sajtot www.MindView.net. Ova e oficijalen Veb sajt za distribucija na kodot i elektronskoto izdanie na knigata, zatoa mo`ete da bidete sigurni deka tuka sekoga{ }e ja najdete najnovata verzija. Kodot mo`ete da go delite i koristite vo u~ilnici i za drugi obrazovni nameni. Osnovnata cel za zadr`uvawe na avtorskoto pravo e ispravno da se navede potekloto na kodot i da se spre~i objavuvawe na kodot vo pe~atenite mediumi bez dozvola. (Dokolku potekloto na kodot e ispravno navedeno, primerite od knigata mo`at da se naveduvaat vo pogolemiot del od mediite.) Vo sekoja datoteka so izvoren kod }e ja najdete slednata napomena za avtorskite prava (obi~no na angliskiot jazik):
16
Da se razmisluva vo Java
Brus Ekel
//:! AvtorskitePrava.txt
Ovoj kompjuterski izvoren kod e zastiten so avtorskite prava 2006 MindView, Inc. Site prava se zadrzani. Se dozvoluva besplatna upotreba, kopiranje, prepravanje i distribuiranje na ovoj kompjuterski izvoren kod i negovata dokumentacija, za dolunavedenite nameni i bez pismeno odobruvanje, dokolku gornata poraka za avtorskite prava, ovoj i slednite pet numerirani pasusi ne gi otstranite nitu od edna kopija. Se dozvoluva preveduvanje na Izvorniot kod. Prevedeniot Izvoren kod mozete da go vklucite vo privatni i komercijalni softverski programi, no samo vo izvrsen format. Neizmenetiot Izvoren kod smeete da go upotrebuvate za potrebite na nastava i vo materijalite za prezentacii, dokolku navedete deka toj e proizlezen od knigata Da se razmisluva na Java. Dozvola za koristenje na Izvorniot kod vo pecatenite medii mozete da nabavite dokolku se obratite na slednata adresa: MindView, Inc. 5343 [email protected]. Valle Vista La Mesa, California 91941
MindView, Inc. gi ima zastiteno avtorskite prava na Izvorniot kod i dokumentacijata. Izvorniot kod e dostapen bez direktna ili indirektna garancija od bilo koj vid, vklucuvajki ja osnovnata garancija za prodazba, pogodnosta za opredelena upotreba ili nekrsenje na necii prava. MindView, Inc. ne garantira deka koja bilo programa koja sto go sodrzi Izvorniot kod ke raboti bez prekin ili greska. MindView, Inc. ne tvrdi deka Izvorniot kod ili koj bilo softver sto toj go opfaka e soodveten za kakva bilo namena. Celokupniot rizik, vo vrska so kvalitetot i performansite na ovoj softver, go prezema samiot korisnik na Izvorniot kod. Korisnikot na Izvorniot kod razbira deka Izvorniot kod e napraven za istrazuvacki i nastavni nameni, zaradi sto mu se sovetuva vo nikoj slucaj i od kakvi bilo pricini da ne se potpira isklucivo na Izvorniot kod, nitu pak na koja bilo programa koja sto toj ja sodrzi. Dokolku se ispostavi deka Izvorniot kod e neispraven, site trosoci na servisiranje, popravka ili ispravka se na tovar na korisnikot. VO NITU EDEN SLUCAJ NITU MINDVIEW, INC. NITU NEGOVIOT IZDAVAC NEMA DA BIDAT ODGOVORNI NA KOJ BILO, BEZ RAZLIKA NA KAKVA BILO PRAVNA TEORIJA, ZA DIREKTNA, INDIREKTNA, POSEBNA, PRICINSKA ILI SLUCAJNA STETA, ZA KAKOV BILO PREKIN NA RABOTENJE, GUBENJE NA PROFIT ILI DELOVNI PODATOCI, ILI KAKOV BILO DRUG PARICEN GUBITOK, ODNOSNO TELESNA POVREDA KOI STO NASTANALE SO UPOTREBA NA OVOJ IZVOREN KOD I NEGOVATA DOKUMENTACIJA ILI SE POSLEDICA NA NEMOZNOSTA NA UPOTREBA NA KOJA BILO PROGRAMA STO E REZULTAT NA IZVORNIOT KOD, DURI I KOGA NA MINDVIEW, INC. ILI NA NEGOVIOT IZDAVAC BI IM SE OBRNALO VNIMANIE NA MOZNOSTA OD TAKVITE STETI. MINDVIEW, INC. NE DAVA NIKAKVA POSEBNA GARANCIJA, VKLUCITELNO NITU IMPLICITNA GARANCIJA ZA PRODAZBA I POGODNOSTI ZA OPREDELENA UPOTREBA. IZVORNIOT KOD E DOSTAPEN VO OBLIKOT VO KOJ STO E DADEN I SO NEGO NE SE DOBIVA KAKVA BILO USLUGA OD MINDVIEW, INC, KOJ NEMA NITU PREZEMA KAKVI BILO OBVRSKI ZA DAVAWE NA USLUGI, PODDRSKA, AZURIRANJE, PODOBRUVANJE ILI MODIFIKACIJA. Ve molime da imate predvid deka MindView, Inc. go odrzuva Web sajtot http://www.MindView.net (i negovite oficijalni duplikati). Edinstveno od tuka
Voved
17
mozat da se prezemaat elektronskite kopii na Izvorniot kod, koi sto se besplatno dostapni pod prethodno navedenite uslovi. Dokolku mislite deka vo Izvorniot kod ste pronasle greska, ve molam ispravkata da mi ja pratite preku sistemot na povratni informacii koj sto mozete da go najdete na sajtot www.MindView.com.
///:~ Kodot mo`ete da go koristite vo Va{ite proekti i vo nastavata (vklu~uvaj}i gi i va{ite materijali za prezentacija), s dodeka ja zdr`uvate porakata za avtorskite prava koi {to se pojavuvaat vo sekoja izvorna datoteka.
18
Da se razmisluva vo Java
Brus Ekel
Gre{ki
Bez razlika kolku mnogu alatki koristi pisatelot za da gi otkrie gre{kite, nekoi od gre{kite sekoga{ }e se provle~at, a nov ~itatel sekoga{ }e gi zabele`i. Dokolku se slu~i da otkriete {to bilo za {to smetate deka e gre{ka, ve molam da ja iskoristite hipervrskata za ovaa kniga na sajtot www.MindView.net , da ja prijavite gre{kata i da pratite predlog za ispravka. Va{ata pomo{ }e bide ceneta od moja strana.
Voved
19
Zapoznavawe so objekti
Prirodata ja raspar~uvame i organizirame vo koncepti, na koi {to im gi pripi{uvame znaewata, glavno zaradi toa {to se pridr`uvame do dogovorot od na{ata jazi~na zaednica i e kodificiran vo obrascite na na{iot jazik ... voop{to ne moeme da zboruvame dokolku ne se pridr`uvame do organizacija i klasifikacija na podatoci koi {to toj dogovor gi propi{uva Beamin Lee Whorf (18971941)
Za~etocite na kompjuterskata revolucija se vo ma{inata. Od tie pri~ini i programskite jazici imaat tendencija da nalikuvaat na ma{ina. No kompjuterite i ne se tolku ma{ini kolku {to se zajaknuva~i na umot ("velosipedi za umot", kako {to Stiv Xobs (Steve Jobs) saka da re~e) i poinakov na~in na izrazuvawe. Zaradi toa, ovie alatki s pomalku nalikuvaat na ma{ina, a s pove}e na delovi na na{iot um, i na drugi oblici na izrazuvawe, kako {to se pi{uvawe, crtawe, vajawe, animirawe i snimawe filmovi. Objektno orientiranoto programirawe (OOP) pretstavuva del od pribli`uvawe kon koristeweto na kompjuterite kako sredstvo na izrazuvawe. Ovaa glava }e ve vovede vo osnovnite koncepti na OOP, vklu~uvaj}i go i pregledot na metodite na razvoj. Ovaa glava i ovaa kniga pretpostavuvaat deka imate iskustvo so programirawe, koe {to ne mora da e na jazikot C. Dokolku smetate deka u{te imate potreba da se podgotvuvate za programirawe pred da po~nete da ja prou~uvate knigata, treba da porabotite vo ramkite na multimedijalniot seminar Da se razmisluva vo C, koj {to moete da go prezemete od adresata www.MindView.net. Ova poglavje pretstavuva i podloga i dopolnitelen materijal. Mnogumina ne se ~uvstvuvaat prijatno vo svetot na objektno orientiranoto programirawe dokolku pred toa ne ja razberat golemata slika. Od tie pri~ini ovde e daden bogat pregled na konceptite na OOP. Drugite pak ne mo`at da gi razberat konceptite na golemata slika ako najnapred ne se zapoznaat so barem nekoi od mehanizmite. Dokolku i pripa|ate na vtorata grupa i sakate da gi otkriete specifi~nostite na jazikot, slobodno mo`ete da ja skoknete ovaa glava vo ovoj moment toa nema da vi bide pre~ka da pi{uvate programi ili da go nau~ite jazikot. Me|utoa, }e posakate da se vratite na ovoj del od
20
Da se razmisluva vo Java
Brus Ekel
knigata za da go dopolnite va{eto znaewe i da razberete zo{to objektite se vani i kako da gi koristite pri pi{uvaweto programi.
Razvoj na apstrakcija
Site programski jazici obezbeduvaat apstrakcija. Bi mo`elo da se diskutira za toa dali slo`enosta na problemot koj {to vie ste vo sostojba da go re{ite direktno e svrzana so vidot i kvalitetot na apstrakcijata. Pod vidot go podrazbiram ona {to go apstrahirate. Ma{inskiot jazik pretstavuva mala apstrakcija na ma{inata na koja {to se izvr{uvaat programite. Mnogu od takanare~enite proceduralni jazici koi {to sledea po ma{inskite (kako FORTRAN, BASIC i C) bea apstrakcija za ma{inskiot jazik. Ovie jazici pretstavuvaat golem napredok vo odnos na ma{inskiot jazik, no sepak nivnata primarna apstrakcija od vas bara da razmisluvate od gledna to~ka na strukturata na kompjuterot namesto strukturata na problemot {to se obiduvate da go re{ite. Programerot mora da vospostavi vrska pome|u modelot na ma{inata (vo prostorot na re{enieto, koj {to pretstavuva mesto kade {to }e go primenite re{enieto na problemot, na primer, vo kompjuterot) i modelot na problemot koj {to nevistina e re{en (vo prostorot na problemot, koj {to pretstavuva mesto kade {to problemot postoi, da re~eme biznisot). Naporot potreben za izvr{uvawe na vakvoto preslikuvawe i faktot deka istoto ne e od golemo zna~ewe za programskiot jazik proizveduvaat programi koi {to te{ko se pi{uvaat i ~ie {to odr`uvawe e skapo, a kako sporeden efekt nastanuva celokupnata industrija na programskite metodi. Alternativata na modelirawe na ma{inata e modelirawe na problemot koj {to se obiduvate da go re{ite. Ranite jazici kako {to se LISP i APL gi odrazuvaa poedinite pretstavi za svetot (Na kraj site problemi se sveduvaat na listi ili Site problemi se od algoritamska priroda, soodvetno). Prolog gi odlea site problemi vo verigi od odluki. Kreirani se jazici za programirawe bazirano na ograni~uvawa i za programirawe isklu~ivo so manipulacija na grafi~ki simboli (poslednovo se poka`a kako premnogu restriktivno). Sekoj od ovie pristapi moe da pretstavuva dobro re{enie za opredelena klasa na problemi za koi {to se nameneti da ja re{at, no koga }e otstapite od toj domen, tie stanuvaat nezgrapni. Objektno orientiraniot pristap odi ~ekor ponatamu, gi obezbeduva alatkite so pomo{ na koi programerot gi pretstavuva elementite vo prostorot na problemot. Ova pretstavuvawe e dovolno op{to taka {to ne go ograni~uva programerot samo na eden vid na problem. Elementite vo prostorot na problemot i nivnoto pretstavuvawe vo prostorot na re{enieto gi narekuvameobjekti. (]e imate potreba i od drugi objekti koji {to nemaat svoj par vo prostorot na problemite.) Idejata se sostoi vo toa na programata da se dozvoli samata da se prilagodi kon nerazbirliviot
Zapoznavawe so objekti
21
jazik na problemot taka {to }e se dodadat novi tipovi na objekti. Na toj na~in koga go ~itate kodot {to go opi{uva re{enieto, vo isto vreme gi ~itate i zborovite koi {to go izrazuvaat problemot. Ova e mnogu pofleksibilna i posilna apstrakcija od prethodnata.2 Od tie pri~ini OOP vi dozvoluva problemot da go opi{ete od agolot na problemot, namesto od agolot na kompjuterot na koj {to re{enieto }e se izvr{uva. S u{te postoi povratna vrska kon kompjuterot: sekoj od objektite nalikuva na mal kompjuter ima vnatre{na sostojba i operacii koi {to moete da pobarate da gi izvr{i. Me|utoa, ova i ne e taka lo{a analogija so objektite vo realniot svet site tie si imaat svoi karakteristiki i odnesuvawa. Alan Kej (Alan Kay) navede pet osnovni karakteristiki na Smalltalk, prviot uspe{en objektno orientiran jazik, i eden od jazicite na koi {to se bazira Java. Tie karakteristiki pretstavuvaat ~ist pristap kon objektno orientiranoto programirawe. 1. S e objekt. Gledajte na objekt kako na podobrena promenliva; taa gi ~uva podatocite, no moete i da zadadete barawa koi {to taa }e gi ispolni izvr{uvaj}i operacii vrz tie podatoci. Teoretski, moete da zemete koja bilo idejna komponenta na problemot {to go re{avate (ku~iwa, zgradi, uslugi i taka natamu.) i da gi pretstavite kako objekti vo Va{ata programa. 2. Programa e mno`etvo od objekti koi {to edni na drugi preku ispra}awe na poraki im soop{tuvaat {to da rabotat. Za da zadadete barawe na objekt, vie mu pra}ate poraka"na toj objekt. Pokonkretno, moete da zamislite deka vo porakata se sodr`i barawe za da se povika metod koj {to pripa|a na opredelen objekt. 3. Sekoj objekt si ima svoj sopstven memoriski prostor koj {to se sostoi od drugi objekti. Ka`ano so drugi zborovi, Vie sozdavate nov vid objekti pravej}i paket koj {to sodri nekoi od postojnite objekti. Toa zna~i deka moete da ja uslonuvate programata, kriej}i ja nea zad ednostavnosta na objektite. 4. Sekoj objekt ima tip. So stru~ni zborovi ka`ano, sekoj objekt pretstavuva instanca (primerok) od nekoja klasa, pri {to klasa" e sinonim na "tip". Najva`noto prepoznatlivo svojstvo na edna klasa e: Koi poraki moete da gi pratite na klasata?"
Nekoi od avtorite na programski jazici mislea deka samoto objektno orientirano programirawe ne e dovolno za da ovozmo`i lesno re{avawe na site programski problemi, pa poddruva kombinirawe na razli~ni pristapi niz multistandardnite programski jazici. Poglednete go Multiparadigm Programming in Leda, Timothy Budd (Addison-Wesley 1995).
22
Da se razmisluva vo Java
Brus Ekel
5. Site objekti od opredelen tip mo`at da primaat isti poraki. Ovo, vsu{nost, e pove}ezna~na izjava, kako {to podocna }e vidite. Kako {to objekt od tipot krug" vo isto vreme e i objekt od tipot oblik", krugot sigurno }e mo`e da gi primi i porakite za oblikot. Toa zna~i deka moete da napi{ete kod koj {to }e komunicira so oblici i koj {to avtomatski }e poddruva i s drugo {to spa|a pod opisot oblik. Ovaa zamenlivost e edna od najmo}nite osobini na OOP. Bu~ (Booch) dava u{te pokusa definicija za objekt: Objektot ima sostojba, odnesuvawe i identitet. Toa zna~i deka objekt moe da ima interni podatoci (koi {to ja odreduvaat negovata sostojba) i metodi (za da proizvedat odnesuvawe) i deka sekoj objekt na edinstven na~in e prepoznatliv (se razlikuva od site drugi objekti) konkretno, sekoj objekt ima edinstvena adresa vo memorijata.3
Vsu{nost ova e premnogu tesno objasnuvawe, zatoa {to objekti mo`at da postojat vo razli~ni kompjuteri i adresni prostori, a mo`at i da bidat snimeni na disk. Vo takvite slu~ai, identitetot na objektot mora da se odredi na poinakov na~in, namesto so pomo{ na negovata adresa vo memorijata.
Zapoznavawe so objekti
23
vreme, sekoj element ima sopstvena sostojba: sekoja smetka ima poinakvo saldo, sekoj blagajnik ima poinakvo ime. Od tie pri~ini blagajnici, klienti, smetki, transakcii i taka natamu, poedine~no mo`at da bidat pretstaveni so edinstven entitet vo kompjuterskata programa. Entitetot e objekt, a sekoj objekt pripa|a na opredelena klasa koja {to gi definira negovite karakteristiki i odnesuvawa. Zna~i, iako nie vo objektno orientiranoto programirawe kreirame novi tipovi na podatoci, site objektno orientirani programski jazici go koristat rezerviraniot zbor class. Koga }e go vidite zborot tip", vie pomisluvate na klasa" i obratno.4 S dodeka klasa opi{uva mno`estvo od objekti koi {to imaat identi~ni karakteristiki (elementi so podatoci) i koi {to se odnesuvaat na ist na~in (funkcionalnost), klasa navistina pretstavuva tip na podatoci, bidej}i i brojot vo format na podvi`na zapirka, na primer, isto taka ima mno`estvo na karakteristiki i odnesuvawa. Razlikata e vo toa {to programer pove}e saka da definira klasa koja {to soodvetstvuva so problemot, otkolku da bide prinuden da koristi posto~ki tip na podatoci koj {to e proektiran za da pretstavuva memoriska edinica vnatre vo kompjuterot. Programskiot jazik }e go pro{irite so dodavawe na novi tipovi podatoci, specifi~ni za va{ite potrebi. Programskiot sistem prifa}a novi klasi, vodi smetka za niv i kontrolira tipovi, isto kako {to toa go pravi so vgradenite tipovi. Objektno orientiraniot pristap ne e ograni~en samo na pravewe simulacii. Bez razlika na toa dali se slo`uvate so stavot deka sekoja programa e simulacija na sistemot {to go proektirate, so upotreba na tehniki na OOP, golemo mno`estvo na problemi lesno mo`e da svedete do ednostavno re{enie. [tom }e se vospostavi klasa, moete da napravite kolku {to sakate objekti od taa klasa, i potoa so tie objekti da rabotite kako da se elementi vo problemot koj {to se obiduvate da go re{ite. Navistina, eden od predizvicite na objektno orientiranoto programirawe e ostvaruvawe na ednozna~no preslikuvawe pome|u elementite vo prostorot na problemot i objektite vo prostorot na re{enieto. Kako da naterate objekt da izvr{i korisna rabota za Vas? Mora da postoi na~in kako na objektot da mu dadete barawe za ne{to da napravi, na primer, da zavr{i transakcija, da nacrta ne{to na ekran ili da vklu~i prekinuva~i. A sekoj objekt moe da ispolni samo opredeleni barawa. Barawata koi {to mo`ete da gi napravite od site objekti se definirani so negoviot
Nekoi lu|e pravat razlika i tvrdat deka tip opredeluva interfejs, dodeka klasa e posebna realizacija na toj interfejs.
24
Da se razmisluva vo Java
Brus Ekel
interfejs, a tipot e ona {to go odreduva interfejsot. Prost primer bi mo`ela da bide obi~na sijalica:
Ime na tipot
Interfejs
Interfejsot opredeluva kakvi barawa moete da mu postavite na poedine~niot objekt. Sekako, nekade mora da postoi kod koj {to }e go zadovoli baraweto. Takov kod, zaedno so skrienite podatoci, so~inuva implementacija (realizacija ili primena na interfejs). Gledano od strana na proceduralnoto programirawe, toa i ne e tolku komplicirano. Za sekoe mo`no barawe tipot ima pridruen metod taka {to koga }e dostavite opredeleno barawe do objektot, se povikuva soodvetniot metod. Za vakov proces obi~no velime deka sme pratile poraka (sme postavile barawe) do objekt, a objektot opredeluva {to }e napravi so porakata (toj izvr{uva kod). Vo na{iot primer, imeto na tipot/klasata e Sijalica, imeto na poedine~niot objekt od tipot Sijalica e sj, a barawata koi {to moeme da gi postavime do objektot Sijalica se: vklu~i se, isklu~i se, zasili svetlina ili prigu{i svetlina. Objekt od tipot Sijalica }e kreirate koga }e definirate referenca (sj) za dadeniot objekt i koga }e povikate new, so {to barate nov objekt od toj tip. Za da pratite poraka do objekt, navedete go imeto na objektot i povrzete go so porakata barawe, pri {to }e gi razdelite so to~ka. Gledano od strana na korisnik na odnapred definirana klasa, toa pretstavuva re~isi s {to vi e potrebno za da programirate so objekti. Dijagramot pogore e napraven vo soglasnost so formatot {to go koristi op{tiot jazik za modelirawe (angl. Unied Modeling Language, UML). Sekoja od klasite e pretstavena so pravoagolnik, imeto na tip e vo gorniot del, podatocite za elementite koi {to treba da se opi{at se nao|aat vo sredi{niot del, dodeka vo dolniot del na pravoagolnikot se nao|aat metodite (funkciite koi {to mu pripa|aat na objektot i gi primaat porakite {to gi pra}ate do objektot). ^esto vo UML dijagramite se prika`uvaat samo imeto na klasata i javnite metodi, dodeka sredi{niot del ne se prika`uva kakov {to e slu~ajot so prethodniot dijagram. Dokolku Ve interesira samo ime na klasa, nema potreba da go prika`uvate nitu dolniot del.
Zapoznavawe so objekti
25
26
Da se razmisluva vo Java
Brus Ekel
za interfejs na pe~ata~i), tuku i se proizveduvaat i novi objekti koji {to mo`at povtorno da se upotrebuvaat na drugi mesta (katalog na izgled na ~ekovi). Mnogu }e si ja olesnite rabotata dokolku na objekti gledate kako na daveteli na uslugi. Toa }e vi bide od polza ne samo na vas vo procesot na proektiraweto, tuku i na site drugi koi bi se obidele da go razberat va{iot kod ili povtorno da upotrebat nekoi od Va{ite objekti. Dokolku mo`at da ja utvrdat vrednosta na objektot vrz osnova na toa koi uslugi toj gi dava, }e im bide mnogu polesno objektot da go vklopat vo svoite proektirawa.
Skriena realizacija
Od golema polza e poleto na dejnosti da se podeli na avtori na klasi (onie {to kreiraat novi tipovi na podatoci) i programeri klienti5 (korisnicite na klasite koi {to gi koristat tipovi podatoci vo svoite aplikacii). Programerot klient ima za cel da gi sobere klasite vo kutija so alatki, koja {to }e ja koristi za brz razvoj na aplikacijata. Avtorot na klasa ima za cel da napravi klasa koja {to go otkriva samo ona {to mu e neophodno na programerot klient, dodeka s ostanato }e dr`i skrieno. Zo{to? Programerot klient ne moe da gi koristi sokrienite delovi, a toa zna~i deka avtorot na klasata moe da go izmeni skrieniot del koga i da posaka, bez da razmisluva dali toj ima dopir so ostanatite delovi. Skrieniot del obi~no ja pretstavuva ~uvstvitelnata vnatre{nost na objektot koja {to lesno mo`e da bide o{tetena od strana na nevnimatelen ili neinformiran programer klient, taka {to krieweto na realizacijata ja namaluva mo`nosta da se pojavat gre{ki vo programite. Vo sekoj odnos vano e site vklu~eni strani da gi po~ituvaat granicite. Koga }e pravite biblioteka, vie kreirate odnos so klient koj isto taka e programer, no koj {to sostavuva aplikacija koristej}i ja va{ata biblioteka, moebi za da napravi pogolema biblioteka. Dokolku site elementi na klasa bi bile dostapni na sekogo, toga{ programerot klient bi mo`el da napravi {to bilo so klasata i ne bi postoel na~in da se nametnat pravila. Duri i koga vie bi sakale programerot klient da ne raboti direktno so nekoi elementi od Va{ata klasa, dokolku nemate kontrola na pristap ne bi postoel na~in toa da go spre~ite. Toa bi bilo izloeno na javnosta. Zaradi toa prvata pri~ina za voveduvawe kontrola na pristap e onevozmo`uvawe na programerite klienti da im pristapuvaat na delovite koi {to ne smeat da gi menuvaat, a koi {to se neophodni za interna rabota so tipot na podatocite. Ovie delovi ne se del od interfejsot koj {to im e
5
Zapoznavawe so objekti
27
potreben na korisnicite za re{avawe na nivnite problemi. Vo isto vreme ova pretstavuva i usluga za programerite klienti, zatoa {to lesno mo`at da razdvojat ona {to za niv e va`no od ona {to mo`at da go ignoriraat (za {to nema potreba da se gri`at). Vtorata pri~ina za voveduvawe na kontrola na pristap e da mu ovozmo`i na proektantot na biblioteka da go menuva na~inot na koj {to klasata interno raboti, bez da mora da se gri`i kako toa }e se odrazi na programerite klienti. Na primer, moete da realizirate nekoja klasa na ednostaven na~in za brz razvoj, i podocna da otkriete deka istata treba povtorno da se napi{e za da raboti pobrzo. Koga interfejsot i realizacijata se jasno se razdeleni i za{titeni, ova lesno mo`ete da go napravite. Java koristi tri rezervirani zborovi za da postavi granici vnatre vo klasata: public, private i protected. Ovie specifikatori na pristap opredeluvaat koj mo`e da gi koristi definiciite {to sleduvaat po niv. Rezerviraniot zbor public (javen) zna~i deka elementot {to sleduva mu e dostapen na sekogo. Rezerviraniot zbor private (privaten) zna~i deka na toj element ne moe da mu pristapi nikoj drug osven samiot avtor na klasata, vnatre vo metodite na toj tip. Rezerviraniot zbor private pretstavuva yid pome|u avtorot i programerot klient. Onaj {to }e se obide da mu pristapi na elementot ozna~en so private, }e predizvika gre{ka pri preveduvawe na programata. Rezerviraniot zbor protected (za{titen) ima isto dejstvo kako i private, edinstvenata razlikata e vo toa {to klasite nasledni~ki imaat pristap do za{titenite elementi, no ne i do privatnite elementi. Za nasleduvaweto }e zboruvame naskoro. Java isto taka ima podrazbiran (standarden) pristap koj {to se koristi dokolku nema da navedete nitu eden od pogore navedenite specifikatori. Ova obi~no se narekuva paketen pristap, bidej}i klasite mo`at da pristapat do ~lenovite na drugi klasi vo istiot paket (bibliote~na komponenta), no nadvor od paketot istite tie ~lenovi se gledaat kako privatni.
28
Da se razmisluva vo Java
Brus Ekel
mo`ete da go stavite i vo nova klasa. Ova se narekuva sozdavawe na ~lenobjekt (angl. member object). Va{ata nova klasa mo`e da bide sostavena od kolku i da sakate drugi objekti, od koj bilo tip i vo koja bilo kombinacija koja {to vam vi e potrebna za da ja postignete posakuvanata funkcionalnost na svojata nova klasa. Bidej}i sostavuvate nova klasa od ve}e postoe~ki klasi, ovoj koncept se narekuva kompozicija (ako kompozicijata se slu~uva dnami~ki , toga{ obi~no se narekuva agregacija). Kompozicijata ~esto se odnesuva na relacijata ima kako vo re~enicata Avtomobilot ima motor.
(Na ovoj UML dijagram, kompozicija se ozna~uva so popolnet romb, koj ozna~uva deka postoi eden avtomobil. Koga }e ozna~uvam spojuvawe, obi~no }e koristam poednostaven oblik: samo linija, bez rombot6) Kompozicija e mnogu fleksibilna. Objektite ~lenovi na va{ata nova klasa obi~no se privatni, {to gi pravi nedostapni za programerite klienti koi {to ja koristat klasata. Ova vi ovozmo`uva da gi izmenite tie ~lenovi bez da go poremetite postoe~kiot kod na klientot. Isto taka mo`ete da gi menuvate objektite ~lenovi za vreme na izvr{uvaweto za da dinami~ki go menuvate i odnesuvaweto na Va{ata programa. Nasleduvaweto, koe sledno }e go opi{uvame, ja nema ovaa fleksibilnost bidej}i preveduva~ot mora da vgradi vremenski ograni~uvawa za preveduvawe na klasite sozdadeni so nasleduvawe. Bidej}i nasleduvaweto e mnogu va`no, vo objektno orientiranoto programirawe toa ~esto mnogu se naglasuva, a noviot programer mo`e da pomisli deka nasleduvaweto treba da se koristi sekade. Kako rezultat na toa mo`e da se dobie neve{ta i premnogu komplicirana programa. Namesto toa, prvo treba da se vidi dali pri sozdavawe novi klasi mo`e da se iskoristi kompozicija, bidej}i taa e mnogu poednostavna i pofleksibilna. Ako go primenite ovoj pristap, Va{ite proektirawa }e bidat po~isti. [tom }e se zdobiete so nekakvo iskustvo, }e vi bide o~igledno koga da koristite nasleduvawe.
Nasleduvawe
Sama po sebe, idejata za objekt e mnogu pogodna alatka. Taa Vi ovozmo`uva podatocite i funkcionalnosta da gi grupirate spored koncept, taka {to soodvetna ideja mo`ete da pretstavite vo prostorot na problemot, namesto da bidete prinudeni da koristite izrazi na komputerot na koj rabotite. Koga
6
Ova e vo princip dovolno detaqno za pove}eto dijagrami i ne treba da precizirate dali koristite agregacija ili kompozicija.
Zapoznavawe so objekti
29
se koristi rezerviraniot zbor class, tie idei se izrazeni kako osnovni edinici vo ovoj programski jazik. Bi bilo {teta da se nama~ite i da napravite nekoja klasa, a potoa da bidete prinudeni da pravite potpolno nova klasa koja ima sli~na funkcionalnost. Bi bilo poubavo da zemete postoe~ka klasa, da ja klonirate, a potoa da ja dopolnuvate i da ja menuvate kloniranata klasa. Ova vsu{nost e istoto {to se postignuva so nasleduvawe (angl. inheritance), osven koga originalnata klasa (koja se narekuva osnovna klasa ili nadklasa ili klasa roditel) }e se izmeni, a tie izmeni se odrazuvaat na klonot (koj {to se narekuva izvedena ili nasledena klasa ili klasa naslednik; angl. derived class).
(Strelkata vo ovoj UML dijagram poa|a od izvedenata klasa kon osnovnata klasa. Kako {to }e vidite, moe da postojat pove}e izvedeni klasi.) Tipot ne gi opi{uva samo ograni~uvawata na mno`estvo objekti; toj ima odnos i so drugi tipovi. Dva tipa mo`at da imaat nekoi zaedni~ki karakteristiki i odnesuvawa, no pri toa edniot tip mo`e da ima pove}e karakteristiki od drugiot i mo`e isto taka da obrabotuva pove}e poraki (ili razli~no da gi obrabotuva). Kaj nasleduvaweto, ovaa sli~nost pome|u tipovite se izrazuva preku konceptot na osnovnite i izvedenite tipovi. Osnovniot tip gi sodr`i site karakteristiki i odnesuvawa koi {to se zaedni~ki za tipovite izvedeni od nego. Pravej}i osnoven tip, ja izrazuvate su{tinata na svoite idei za nekoi objekti vo sistemot. Od osnovniot tip gi izveduvate ostanatite tipovi i poka`uvate razli~ni na~ini za realizacija na ovaa su{tina. Na primer, ma{inata za reciklirawe gi rasporeduva par~iwata otpad. Osnovniot tip e otpad, a sekoe par~e otpad ima te`ina, vrednost i taka natamu, i moe da bide ise~eno, stopeno ili raspadnato. Od osnovniot tip izveduvame posebni vidovi otpad so dodatni karakteristiki ({i{eto ima boja), ili odnesuvawa (aluminiumskata konzerva moe da se zdrobi, ~eli~nite konzervi gi privlekuva magnet). Odnesuvawata mo`at da bidat razli~ni (vrednosta na hartija zavisi od nejziniot vid i sostojbata) Koristej}i go nasleduvaweto mo`ete da izgradite hierarhija na tipovi. Taa hierarhija go izrazuva problemot koj {to se obiduvate da go re{ite preku tipovite koi {to se pojavuvaat vo problemot. 30 Da se razmisluva vo Java Brus Ekel
Drug primer e klasi~niot primer na oblik, koj {to mo`e da se koristi vo sistemot na kompjuterski-potpomognat dizajn, poznat kako CAD sistem (angl. Computer-Aided Design) ili vo nekoja kompjuterski simulirana igra. Osnovniot tip e oblik, a sekoj oblik ima golemina, boja, pozicija i taka natamu. Sekoj oblik mo`e da se nacrta, rotira, pomestuva, boi i taka natamu. Ottuka izveduvame (nasleduvame) specifi~ni vidovi oblici - krug, kvadrat, triagolnik i drugi - od koi {to sekoj mo`e da ima dodatni karakteristiki i odnesuvawa. Nekoi oblici, na primer, mo`at da se rotiraat. Nekoi odnesuvawa mo`at da bidat razli~ni, da re~eme koga sakate da ja presmetate plo{tinata na oblikot. Hierarhijata na tipovi gi obedinuva sli~nostite i razlikite pome|u oblicite.
Pretstavuvaweto na re{enieto vo ist oblik kako i problemot e mnogu korisno bidej}i ne vi e potreben golem broj na me|umodeli za od opisot na problemot da preminete na opisot na re{enieto. Kaj objektite, hierarhija na tipovi e osnoven model taka {to od opisot na sistemot vo realniot svet direktno preo|ate na opis na sistemot vo kod. Navistina, edna od te{kotiite koja {to lu|eto ja imaat so objektno orientiranoto programirawe e toa deka premnogu ednostavno se stignuva od po~etokot do krajot. Um koj e treniran da bara slo`eni re{enija mo`e u{te vedna{ da bide zbunet od ovaa ednostavnost. Koga koristite nasleduvawe od postoe~ki tip, sozdavate nov tip. Toj tip ne samo {to gi sodr`i site ~lenovi na postoe~kiot tip (iako privatnite ~lenovi se skrieni i nedostapni) tuku, {to e i mnogu pova`no, go kopira interfejsot na osnovnata klasa. Zna~i, site poraki koi {to mo`ete da gi pratite do objektite od osnovnata klasa, isto taka mo`ete da gi pratite i do objektite od izvedenata klasa. Bidej}i tipot na klasata se odreduva vrz
Zapoznavawe so objekti
31
osnova na porakite koi {to mo`eme da i gi pratime, toa zna~i deka izvedenata klasa e od istiot tip kako i osnovnata klasa. Vo prethodniot primer Krugot e oblik. Ovaa ekvivalencija na tipovite dobiena preku nasleduvawe e osnovniot ~ekor na patot kon razbirawe na zna~eweto na objektno orientiranoto programirawe. Bidej}i i osnovnata i izvedenata klasa imaat ist osnoven interfejs, mora da postoi i nekakva realizacija koja {to odi zaedno so toj interfejs. Zna~i, mora da postoi kod koj {to se izvr{uva koga objektot }e primi odredena poraka. Ako ednostavno nasledite nekoja klasa i ne napravite ni{to pove}e, metodite na interfejsot na osnovnata klasa }e preminat i vo izvedenata klasa. Toa zna~i deka objektite na izvedenata klasa go imaat ne samo istiot tip, tuku i istoto odnesuvawe, {to i ne e posebno interesno. Postojat dva na~ina da napravite razlika pome|u Va{ata nova izvedena klasa i originalnata osnovnata klasa. Prviot e sosema jasen: na izvedenata klasa dodajte potpolno novi metodi. Tie novi metodi ne se del od interfejsot na osnovnata klasa, {to zna~i deka osnovnata klasa ne go pravela seto ona {to ste sakale, pa zatoa ste i dodale u{te metodi. Ovoj ednostaven i primitiven na~in na koristewe na nasleduvawe ponekoga{ e sovr{eno re{enie za Va{iot problem. Me|utoa, vnimatelno prou~ete dali tie dodatnite metodi mo`ebi se potrebni i na Va{ata osnovna klasa. Ovoj proces na otkrivawe i iteracija na programata e redovna pojava vo objektno orientiranoto programirawe.
Iako nasleduvawe ponekoga{ mo`e da najavi (osobeno vo Java, kade {to rezerviraniot zbor koj {to ozna~uva nasleduvawe glasi extends pro{iruva)
32
Da se razmisluva vo Java
Brus Ekel
deka }e dodavate novi metodi vo interfejsot, toa ne e sekoga{ vistina. Vtoriot i pova`niot na~in da napravite razlika vo novata klasa e da smenite odnesuvaweto na postoe~ki metod na osnovnata klasa. Toa se narekuva redefinirawe na metoda (angl. overriding).
Za da redefinirate nekoja metoda, napravete nova definicija za metodot vo izvedenata klasa. Vie ka`uvate: Ovde go koristam istiot metod na interfejsot, no sakam taa da pravi ne{to drugo vo mojot nov tip L
Relacii E i E-KAKO
Ima edno pra{awe koe {to se postavuva vo vrska so nasleduvaweto: dali nasleduvawe treba da gi redefinira samo metodite na osnovnata klasa (i da ne dodava novi metodi koi ne postojat vo osnovnata klasa)? Toa bi zna~elo deka izvedenata klasa e od potpolno ist tip kako i osnovnata klasa, bidej}i ima potpolno ist interfejs. Kako rezultat, mo`ete to~no da zamenite objekt od izvedenata klasa so objekt od osnovnata klasa. Ova se narekuva ~ista supstitucija, ili princip na supstitucija. Ova e idealen na~in za primena na nasleduvaweto. Vo ovoj slu~aj, relacijata pome|u osnovnata i izvedenata klasa nie ~esto ja narekuvame e relacija, bidej}i mo`eme da re~eme, Krugot e oblik. Obidot da utvrdime dali mo`eme da vospostavime e relacija pome|u klasite, i toa da ima smisla, pretstavuva svoeviden test za nasleduvaweto.
Zapoznavawe so objekti
33
Ponekoga{ morate da dodadete novi elementi vo interfejsot na izvedeniot tip i taka da go pro{irite postoe~kiot interfejs. Noviot tip i ponatamu mo`e da bide sveden na osnovniot tip, no supstitucijata ne e sovr{ena, bidej}i novite metodi ne se dostapni od osnovniot tip. Ova mo`e da se opi{e kako relacija e-kako (moj termin). Noviot tip go ima interfejsot na stariot tip, no sodr`i i drugi metodi, taka {to ne mo`e da se re~e deka se potpolno isti. Kako primer }e go zememe uredot za klimatizirawe. Da pretpostavime deka po va{ata ku}a se o`i~eni (wired) site kontroli za ladewe, odnosno, ku}ata ima interfejs koj ovozmo`uva da go kontrolirate ladeweto. Zamislete uredot za klimatizirawe da se rasipe i da go zamenite so toplotna pumpa koja mo`e i da gree i da ladi. Toplotnata pumpa e kako ured za klimatizirawe, no taa mo`e i pove}e. Bidej}i kontrolniot sistem na va{ata ku}a e proektiran taka {to mo`e da go kontrolira samo ladeweto, toj e ograni~en vo komunikacijata so delot za ladewe na noviot objekt. Interfejsot na noviot objekt e pro{iren, a postoe~kiot sistem ne poznava ni{to drugo osven originalniot interfejs. Sekako, otkako }e go vidite ovoj dizajn, }e vi stane jasno deka osnovnata klasa sistem za ladewe ne e dovolno op{ta i treba da se preimenuva vo sistem za kontrola na temperaturata, za da mo`e da sodr`i i greewe - po {to bi va`el sistemot za supstitucija. Ovoj dijagram poka`uva {to mo`e da se slu~i vo realniot svet za vreme na proektiraweto. Koga }e se zapoznaete so principot na supstitucija, lesno mo`ete da pomislite deka toj pristap (~ista supstitucija) e edinstven na~in ne{to da se napravi. I navistina e dobro programata da ja napravite na toj na~in. No }e sfatite deka vo interfejsot na izvedenata klasa ponekoga{ mora da dodadete novi metodi. Otkako }e go istra`ite problemot, bi trebalo da bide prili~no o~igledno za koj od tie dva slu~aji se raboti.
34
Da se razmisluva vo Java
Brus Ekel
Zapoznavawe so objekti
35
specifi~niot tip Ptici, pravilno se odigra odnesuvaweto (Guska-ta odi, leta ili pliva, a Pingvin-ot odi ili pliva)?
Odgovorot le`i vo osnovniot trik na objektno orientiranoto programirawe: preveduva~ot ne mo`e da ja povika funkcijata na tradicionalen na~in. Preveduva~ot koj ne e objektno orientiran predizvikuva rano svrzuvawe (ang. early binding). Ovoj termin mo`ebi ne ste go ~ule porano, bidej}i za povikuvawe na funkcii ne ste razmisluvale na drug na~in. Toa zna~i deka preveduva~ot generira povik do ime na odredena funkcija, a izvr{niot sistem podocna go razre{uva ovoj povik so vmetnuvawe na apsolutnata adresa na kodot koj {to treba da se izvr{i.Vo objektno orientiranoto programirawe, programata ne mo`e da ja odredi adresata na kodot s do momentot na izvr{uvawe, taka {to e neophodna nekoja druga {ema koga porakata se pra}a na generi~kiot objekt. Za da go re{at ovoj problem, objektno orientiranite jazici go koristat konceptot na zadocneto svrzuvawe (ang. late binding). Koga }e pratite poraka na objekt, kodot koj se povikuva ne e opredelen s do momentot na izvr{uvawe. Preveduva~ot sepak proveruva dali metodot postoi, i izvr{uva proverka na tipot na argumentite i povratnata vrednost, no ne znae to~no koj kod }e go izvr{i. Za da se izvr{i zadocneto svrzuvawe, Java koristi specijalen del od kodot namesto da koristi apsoluten povik. Ovoj kod ja presmetuva adresata na teloto na metodot so pomo{ na informacii vgradeni vo konkretniot objekt (ovoj proces e podetaqno opi{an vo glavata Polimorfizam). Taka sekoj objekt mo`e da se odnesuva razli~no, vo sklad so sodr`inata na sekoj poedine~en specijalen del od kodot. Koga pra}ate poraka na objekt, toj samiot odlu~uva {to }e napravi so nea. Vo nekoi jazici morate eksplicitno da navedete deka sakate metodot da ima fleksibilnost na svojstvata na zadocneto svrzuvawe (vo jazikot C++ toa se
36
Da se razmisluva vo Java
Brus Ekel
pravi so pomo{ na rezerviraiot zbor virtual). Vo tie jazici, podrazbirlivo, metodite ne se svrzuvaat dinami~ki. Vo Java dinami~koto svrzuvawe se podrazbira, taka {to da ne mora da zapomnite da dodavate posebni rezervirani zborovi za da dobiete polimorfizam. Da go razgledame primerot so oblik. Dijagramot na familijata od klasi (koi {to se zasnovani na ist uniformiran interfejs) e daden prethodno vo ovaa glava. Za da pretstavime polimorfizam, }e napi{eme eden del od kod koj ignorira specifi~ni detali za tipot i se obra}a samo na osnovnata klasa. Tie naredbi ne se povrzani so informaciite specifi~ni za poedine~ni tipovi, pa zatoa poednostavno se pi{uvaat i polesno se razbiraat. Ako so pomo{ na nasleduvawe dodademe nov tip - Sestoagolnik, na primer - tie naredbi }e rabotat podednakvo dobro so noviot tip na Oblik kako {to rabotea so ve}e postoe~kite tipovi. Zna~i, programata e pro{irliva. Ako napi{ete metod vo Java (naskoro }e nau~ite kako toa da go pravite):
void praviNesto (Oblik oblik) { oblik.brisi(); // oblik.crtaj();
Ovoj metod se obra}a na koj bilo Oblik, pa ne zavisi od specifi~niot tip objekti koi gi crta i bri{e. Ako vo nekoj drug del od programata go povikame metodot praviNesto( ):
Krug krug = new Krug(); Triagolnik triagolnik = new Triagolnik (); Linija linija = new Linija(); praviNesto (krug); praviNesto (triagolnik); praviNesto (linija) ;
Povicite po metodot praviNesto( ) avtomatski rabotat ispravno, bez obzir na to~niot tip na objektot. Ova e prili~no za~uduva~ki trik. Razgledajte go redot:
praviNesto (krug);
Ovde Krug e prosleden na metodot koj o~ekuva Oblik. Bidej}i Krug e Oblik, funkcijata praviNesto( ) mo`e taka i da go tretira. Odnosno, koja bilo poraka koja metodot praviNesto( ) mo`e da ja prati na Oblik, Krug mo`e da ja prifati. Zatoa gorniot povik e potpolno siguren i logi~en. Procesot pri koj izvedeniot tip go tretirame kako negoviot osnoven tip, go narekuvame sveduvawe nagore (ang. upcasting). Imeto cast e iskoristeno zatoa {to ozna~uva vmetnuvawe vo kalap (ang. casting into a mold - vmetnuvawe vo kalap), a up poteknuva od na~inot na koj obi~no se orgnizira dijagramot na nasleduvawe, so osnovniot tip na vrvot i izvedenite klasi koi lepezesto se
Zapoznavawe so objekti
37
{irat nadolu. Spored toa, konverzija vo osnoven tip e ka~uvawe po dijagramot na nasleduvawe: sveduvawe nagore ili upcasting.
Vo objektno orientiranata programa sekoga{ postoi sveduvawe nagore, bidej}i pri toa ne mora da go znaete to~niot tip so koj {to rabotite. Poglednete ja funkcijata praviNesto( ):
oblik.brisi(); II oblik.crtaj();
Obrnete vnimanie na toa deka nikade ne se veli: Ako si Krug, pravi go ova, ako si Kvadrat pravi go ona, i taka natamu. Taka napi{aniot kod koj {to gi proveruva site mo`ni tipovi koi {to Oblik mo`e da gi pokrie e neureden i mora da go menuvate sekoj pat koga dodavate nov vid na Oblik. Vo na{iot slu~aj, samo velime: Ti si oblik, jas znam deka ti mo`e{ samiot da se iscrta{ erase() i izbri{e{ draw(), napravi go toa, i sam vodi smetka za detalite. Ona {to e impresivno okolu kodot vo funkcijata praviNesto( ) e toa deka, nekako, se slu~uva to~nata rabota. Samiot povik za metodot iscrtajSe( ) za Krug predizvikuva izvr{uvawe na razli~en kod od onoj pri povikuvawe na metodot iscrtajSe( ) za Kvadrat ili Linija; no koga porakata iscrtajSe( ) ja pratime na nepoznat Oblik, se dobiva pravilnoto odnesuvawe, zasnovano vrz vistinskiot tip na Oblik. Ova e dobra osobina, kako {to e i porano spomenato, bidej}i koga Java preveduva~ot go preveduva metodot praviNesto( ), toj ne mo`e da znae to~no so koj tip raboti. So toa obi~no bi o~ekuvale toj da gi povika verziite na metodite izbrisiSe( ) i iscrtajSe( ) za osnovnata klasa Oblik, a ne za odreden Krug, Kvadrat ili Linija. Poradi polimorfizmot sepak s se odviva pravilno. Preveduva~ot i sistemot za izvr{uvawe vodat smetka za site detali; se {to treba da znaete to~no sega e deka polimorfizmot funkcionira i, u{te pova`no, kako da pi{uvate programi koristej}i go toj pristap. Koga }e pratite poraka na objekt, objektot }e go napravi toa {to treba, duri i koga treba da sveduva nagore.
38
Da se razmisluva vo Java
Brus Ekel
Kontejneri
Op{to zemeno, ne mo`ete da znaete kolku objekti }e vi bidat potrebni za re{avawe na nekoja zada~a, nitu kolku dolgo tie treba da postojat vo memorijata. Ne znaete ni kako da gi skladirate tie objekti. Ako pred izvr{uvawe na programata ne go znaete ni brojot na objekti ni nivniot vek na traewe, kako da ja odredite koli~inata memoriski prostor za nivno skladirawe?
Zapoznavawe so objekti
39
Re{enieto na pove}eto problemi vo objektno orientiranoto programirawe ponekoga{ deluva neseriozno: }e sozdadete u{te eden tip na objekt. Noviot tip na objekt koj go re{ava spomnatiot problem ~uva referenci na drugi objekti. Sekako, istoto toa mo`ete da go napravite i so pomo{ na nizi, koi postojat vo pove}eto jazici. No toj nov objekt, obi~no nare~en kontejner (se narekuva i kolekcija, no bidej}i bibliotekite na Java go koristat toj termin vo druga smisla, taka {to vo ovaa kniga }e se koristi imeto kontejner), }e se {iri po potreba za da primi se {to }e stavite vo nego. Taka {to ne mora da znaete kolku objekti }e ~uvate vo kontejnerot. Samo napravete kontejnerski objekt i prepu{tete mu nemu da se gri`i za detalite. Za sre}a, dobar OOP jazik sodr`i mno`estvo kontejneri kako del od paketot. Vo jazikot C++ toj e del od standardnata biblioteka na C++ i ~esto se narekuva standardna biblioteka na {abloni (ang. Standard Template Library, STL). Smalltalk ima prili~no dobro mno`estvo kontejneri. I Java ima mnogu kontejneri vo svojata standardna biblioteka. Vo nekoi biblioteki eden ili dva generi~ki kontejneri se dovolni za site potrebi, dodeka vo drugi biblioteki (na primer vo Java) postojat razli~ni tipovi kontejneri za razli~ni potrebi: pove}e razli~ni tipovi na klasi Spisok (List), (za ~uvawe sekvenci), Mapi (Maps) (koi se isto taka poznati i kako asocijativni nizi, za povrzuvawe na edni objekti so drugi), Mnozestva (Sets) (za ~uvawe po eden primerok od sekoj tip objekti) i drugi komponenti me|u koi se redici (na ~ekawe, opa{ki), stebla, stekovi i taka natamu. Od gledna to~ka na programata, s {to navistina sakate e kontejner so koj {to mo`ete da rabotite za da re{ite problem. Ako kontejner od eden tip gi zadovoluva site Va{i potrebi, nema potreba da voveduvate drugi. Postojat dve pri~ini poradi {to Vi e potreben izbor na kontejneri. Prvo, kontejnerite obezbeduvaat razli~ni tipovi interfejsi i nadvore{no odnesuvawe. Stekot ima razli~en interfejs i odnesuvawe od redicata, koj{to e razli~en od mno`estvo ili spisok. Za re{enie na va{iot problem eden od niv e obi~no podobar od ostanatite. Vtoro, razli~ni kontejneri izvr{uvaat isti operacii so razli~na efikasnost. Na primer, postojat dva osnovni vida spisoci: ArrayList i LinkedList. I edniot i drugiot se ednostavni nizi koi {to mo`at da imaat identi~ni interfejsi i nadvore{no odnesuvawe. No, odredeni operacii mo`at da imaat zna~ajno razli~ni tro{oci. Na primer, pristapuvaweto po slu~aen izbor kon elementite na kontejner ArrayList e operacija so postojano vreme na izvr{uvawe; bez ogled na toa koj element }e go izbereme, potrebno e isto koli~estvo vreme. Me|utoa, dvi`ewe niz listata LinkedList do slu~ajno odbran element e poskapo i kolku pove}e se oddale~eni elementite od po~etokot na listata, tolku pove}e vreme treba da im se pristapi. Od druga strana, ako sakate da vmetnete element vo sredina na nizata, toa e mnogu poednostavno i pobrzo vo listata LinkedList, otkolku vo listata ArrayList. Ovie i drugi operacii ne se ednakvo efikasni, {to zavisi od strukturata
40
Da se razmisluva vo Java
Brus Ekel
koja se nao|a vo osnovata na oddelna niza. Vo fazata na pi{uvawe na programata, mo`ete da trgnete od kontejnerot LinkedList, a koga }e gi popravate performansite, prefrlete se na kontejnerot ArrayList. Blagodarej}i na apstrakcijata preku interfejsot List, prefrlaweto od edna struktura vo druga }e ima minimalno vlijanie na va{iot kod.
Zapoznavawe so objekti
41
preveduva~ot bi mo`el da go prilagodi taka {to }e ja prifa}a i vra}a samo klasata Oblik. Edna od golemite promeni koi gi donese Java SE5 e dodavaweto na parametriziranite tipovi, koi vo Java gi narekuvame generi~ki tipovi. ]e gi prepoznaete po aglestite zagradi vo koi se naveduvaat; na primer, vaka mo`e da se napravi ArrayList koja sodr`i Oblik: Ar r ayList<Oblik > oblik = new Array List<Oblik>(); Za dobro iskoristuvawe na generi~kite tipovi, izmeneti se i mnogu standardni komponenti na bibliotekata. Kako {to }e vidite, generi~kite tipovi vlijaat na dobar del na kodot vo ovaa kniga.
42
Da se razmisluva vo Java
Brus Ekel
potreben na nekoj drug del od programata. Istiot problem mo`e da se pojavi i da stane mnogu slo`en vo mnogu drugi situacii i vo programskite sistemi (kako {to e C++) vo koi {to morate to~no da go izbri{ete objektot koga }e zavr{ite so nego. Kade se nao|aat podatocite za objektot i kako se kontrolira traeweto na objektot? C++ zazema stav deka najva`na e efikasnosta, pa izborot go prepu{ta na programerot. Za da se postigne maksimalnata brzina na izvr{uvawe, skladiraweto i vekot na traewe mo`e da bidat opredeleni za vreme na pi{uvawe na programata, taka {to objektite se stavaat na stek (tie ponekoga{ se narekuvaat i avtomatski ili vidlivi - ang. scoped promenlivi) ili vo stati~kata oblast za skladirawe. Tie mesta imaat visok prioritet i prostorot vo niv brzo se zazema i osloboduva, pa kontrolata nad niv e mnogu zna~ajna vo nekoi situacii. Me|utoa, so toa ja `rtvuvate fleksibilnosta bidej}i morate da go znaete to~niot broj, traeweto i tipot na objektite za vreme na pi{uvawe na programata. Ako se obiduvate da re{ite poop{t problem, na primer proektirawe so pomo{ na kompjuter (CAD), upravuvawe so skladi{te ili kontrola na vozdu{en soobra}aj, ovoj metod e premnogu restriktiven. Vtoriot pristap e dinami~koto sozdavawe na objekti vo dinami~kata oblast na memorijata (ang. heap). Pri ovoj pristap, s dodeka ne po~ne izvr{uvaweto, ne znaete kolku objekti vi trebaat, kolku }e traat, nitu od koj tip se. Seto toa se odreduva koga programata ve}e raboti (vakviot na~in na pravewe objekti se narekuvaa dinami~ki). Dokolku vi zatreba nov objekt, napravete go vo dinami~kata memorija, vo momentot koga vi zatrebal. Bidej}i so oblasta za ~uvawe se upravuva dinami~ki, za vreme na izvr{uvaweto, zazema weto na memoriskiot prostor trae zna~itelno podolgo od oddeluvaweto na prostor na stek. Oddeluvawe na prostorot na stek ~esto se postignuva samo so asemblerska naredba poka`uva~ot na stekot da se pomesti nadolu i da se vrati nazad. Vremeto za koe {to treba da se odvoi prostorot vo dinami~kata memorija, zavisi od dizajnot na mehanizmot za skladirawe. Dinami~kiot pristap se zasnova vrz op{tata logi~ka pretpostavka deka objektite se stremat da bidat slo`eni, taka {to dodatnite re`iski tro{oci za nao|awe prostor i negovoto osloboduvawe nema da imaat va`no vlijanie vrz sozdavaweto objekti. U{te pove}e, pogolemata fleksibilnost na dinami~kiot pristap e su{tinska za re{avawe na poop{tite programski problemi.
Zapoznavawe so objekti
43
Java isklu~itelno go koristi vtoriot pristap8 Sekoj pat koga sakate da sozdadete objekt, go koristite noviot operator (rezerviraniot zbor) new za da napravite dinami~ki primerok (instanca) od toj objekt. Se nametnuva u{te i pra{aweto za traeweto na objektot. Vo jazicite koi {to dozvoluvaat objektite da se sozdavaat na stek, preveduva~ot opredeluva kolku dolgo objektite traat i mo`e avtomatski da gi uni{ti. Me|utoa, koga objektot go sozdavate dinami~ki, preveduva~ot nema informacii za negoviot `ivoten vek. Vo jazik kako {to e C++ mora programski da odredite koga }e go uni{tite objektot, {to mo`e da dovede do gubewe na memorijata ako toa ne go napravite toa ispravno (toa e ~est problem vo programite pi{uvani na C++). Java obezbeduva svojstvo nare~eno sobira~ na otpad (ang. garbage collector) koj avtomatski otkriva koj objekt ve}e ne se upotrebuva i go uni{tuva. Sobira~ot na otpad e mnogu pogoden, bidej}i go namaluva brojot na stavki na koi {to morate da mislite i koli~inata na kod koja {to morate da ja napi{ete. U{te pova`no e toa {to sobiraweto na otpad obezbeduva mnogu povisoko nivo na za{tita od problemi so gubewe na memorijata ({to mnogu proekti pi{uvani na C++ gi frli na kolena). Vo Java, sobira~ot na otpad vodi smetka za problemot so osloboduvawe memorija (iako vo toa ne spa|aat drugi aspekti na ~istewe objekti). Sobira~ot na otpad znae koga objektot ve}e ne se koristi i avtomatski ja osloboduva memorijata koja {to ja zazemal toj objekt. Toa, vo kombinacija so faktot deka site objekti izvedeni od edna osnovna klasa Object, kako i deka postoi samo eden na~in za pravewe objekti - dinami~ki - go pravi procesot na programirawe vo Java mnogu poednostaven od programiraweto na jazikot C++. Ima mnogu pomalku odluki koi {to treba da gi donesete i pre~ki koi {to treba da gi nadminete.
44
Da se razmisluva vo Java
Brus Ekel
dogovoreni konvencii koi {to ne se nametnati od jazikot. Ako programerot ne e pretpazliv - {to ~esto se slu~uva dokolku toj brza - tie {emi lesno mo`at da se zaboravat, odnosno ispu{tat od vid. Obrabotka na isklu~oci ja vgraduva obrabotkata na gre{ki direktno vo programskiot jazik i ponekoga{ duri i vo operativniot sistem. Isklu~ok e objektot isfrlen (ang. thrown) od mestoto na gre{kata i mo`e da bide faten (ang. caught) od soodvetniot upravuva~ so isklu~oci koj {to go obrabotuva odredeniot tip na gre{ka. Toa e kako obrabotkata na isklu~oci da e razli~en, paralelen pat na izvr{uvawe po koj {to mo`e da se trgne dokolku ne{tata trgnat naopaku. Zatoa {to koristi poseben pat za izvr{uvawe, obrabotkata na isklu~oci ne mora da se me{a so va{iot kod koj {to normalno se izvr{uva. Bidej}i ne mora postojano da proveruvate dali imalo gre{ki, pi{uvaweto na kodot naj~esto }e bide poednostavno. Osven toa, isfrleniot isklu~ok se razlikuva od vrednosta na gre{kata koja e vratena od metodot i od indikatorot na sostojbata koja {to uka`uva na gre{ka, po toa {to tie mo`at da se ignoriraat. Isklu~okot ne mo`e da se ignorira i se garantira deka }e bide obraboten vo nekoj moment. Kone~no, isklu~ocite obezbeduvaat sigurno da se izvle~ete od lo{a situacija. Namesto samo da izlezete od programata, ~esto ste vo mo`nost da gi sredite rabotite i da prodol`ite so izvr{uvawe, so {to dobivate mnogu porobusni programi. Obrabotkata na isklu~oci na Java se izvojuva od drugite programski jazici bidej}i e vgradena od po~etok, pa ste prinudeni da ja koristite. Toa e edinstveniot prifatliv na~in za prijavuvawe na gre{ki. Ako ne go napi{ete kodot taka {to pravilno }e gi obrabotuva isklu~ocite, }e se pojavi gre{ka pri preveduvaweto. Ovaa garantirana doslednost ponekoga{ zna~itelno ja poednostavuva obrabotkata na gre{ki. Va`no e da se napomene deka obrabotkata na isklu~oci ne e objektno orientirana mo`nost, iako vo objektno orientiranite jazici isklu~ocite obi~no se pretstaveni preku objekti. Obrabotkata na isklu~oci postoela i pred objektno orientiranite jazici.
Paralelno programirawe
Osnoven koncept vo kompjuterskoto programirawe e obrabotkata na pove}e zada~i istovremeno. Mnogu programskite problemi baraat programata da prestane so rabotata, da se spravi so nekoj drug problem, pa potoa da se vrati na glavniot proces. Za re{avawe na problemot se pristapilo na pove}e na~ini. Na po~etokot, programerite so nisko nivo na poznavawe na ma{inata, pi{uvale prekinuva~ki servisni rutini, a suspenzijata na glavniot proces bila inicirana preku hardverski prekin. Iako seto toa dobro rabotelo, bilo te{ko i neprenoslivo, pa prefrlaweto na programata na nov tip na ma{ina bilo bavno i skapo.
Zapoznavawe so objekti
45
Ponekoga{, za obrabotka na zada~i koi {to vedna{ mora da se izvr{at, prekinite na rabotata se neophodni, no postoi golema klasa na problemi vo koja se obiduvame problemot da go podelime na pove}e delovi koi {to se izvr{uvaat posebno i paralelno, za celata programa da reagira pobrgu. Delovite koi {to posebno se izvr{uvaat vnatre vo programata se narekuvaat ni{ki (ang. thread), a celiot koncept paralelna rabota (ang. concurrency). Tipi~en primer za paralelnata rabota e korisni~koto opkru`uvawe. Poradi podelbata na programata na ni{ki, korisnikot mo`e da pritisne na kop~e i da dobie brz odgovor, namesto da bide prinuden da ~eka dodeka programata ne zavr{i so tekovnata zada~a. So ni{kite obi~no se raspredeluva vremeto na eden (i edinstven) procesor. Me|utoa, ako operativniot sistem poddr`uva pove}eprocesorska rabota, sekoja ni{ka mo`e da bide dodelena na razli~ni procesori, i toga{ tie navistina mo`e da rabotat paralelno. Posle s ova, paralelnata rabota zvu~i prili~no ednostavno. Sepak postoi edna zamka: delewe na resursi. Ako simultano se izvr{uvaat pove}e ni{ki koi {to o~ekuvaat da pristapat do ist resurs, }e se pojavi problem. Na primer, dva procesa ne mo`at istovremeno da pra}aat podatoci na ist pe~atar. Za da se re{i problemot, resursite koi {to mo`at da bidat deleni, kako {to e pe~atarot, mora da bidat zaklu~eni dodeka se koristat. Zna~i, ni{kata go zaklu~uva resursot, ja zavr{uva zada~ata, a potoa go otklu~uva resursot, po {to nekoj drug mo`e da go koristi. Paralelnata rabota e vgradena vo Java, a Java SE5 dodatno go podr`uva so svojata biblioteka.
Java i Internetot
Ako Java e vsu{nost samo u{te eden kompjuterski programski jazik, mo`e da se zapra{ate zo{to e tolku va`na i zo{to se pretstavuva kako revolucioneren ~ekor vo kompjuterskoto programirawe. Odgovorot ne e vedna{ o~igleden, dokolku se nabquduva od tradicionalna programerska perspektiva. Iako Java e mnogu korisna za re{avawe tradicionalni samostojni programski problemi, isto taka e va`no toa {to so pomo{ na nea mo`ete da re{ite i programski problemi koi {to go zasegaat Veb-ot.
[to e Veb?
Otprvo Veb mo`e da deluva pomalku tainstveno, so celata prikazna za surfawe, prisustvo i po~etni stranici. Korisno e malku da se vratite nanazad i da sogledate {to e vsu{nost Veb, no za da go napravite toa morate da gi razbirate sistemite od tip klient/server, u{te eden aspekt na kompjuterska obrabotka koj {to e poln so zbunuva~ki temi.
46
Da se razmisluva vo Java
Brus Ekel
Klient/server obrabotka
Osnovnata ideja na sistemot klient/server e da s ima centralno skladi{te na informacii - nekoi vidovi podatoci, obi~no vo baza na podatoci - koi {to sakate da gi pra}ate po barawe, na grupa lu|e ili ma{ini. Vo konceptot klient/server klu~no e toa {to skladi{teto na informacii e centralizirano taka {to informaciite mo`at da se menuvaat i tie promeni da se prenesat na site korisnici na informaciite. Skladi{teto na informacii, softverot koj {to gi pra}a informaciite i ma{inata/ma{inite kade {to softverot i informaciite se nao|aat, zaedno se narekuvaat server. Softverot koj {to se nao|a na ma{inata na korisnikot, sorabotuva so serverot, prevzema informacii, gi obrabotuva i gi prika`uva na taa ma{ina, se narekuva klient. Osnovniot koncept na klient/server obrabotkata, zna~i, ne e premnogu slo`en. Se pojavuvaat problemi bidej}i imate eden server koj {to se obiduva da opslu`i pove}e klienti istovremeno. Glavno se koristi sistem za upravuvawe so baza na podatoci, taka {to programerot go uramnote`uva rasporedot na podatocite vo tabelite za da postigne optimalno koristewe. Sistemite ~esto dozvoluvaat na klientite i da dodavaat informacii na serverot. Toa zna~i deka mora da obezbedite novite podatoci od eden klient da ne gi pregazat novite podatoci na drug klient, ili tie podatoci da ne se izgubat vo procesot na dodavawe vo bazata. (Ova se narekuva obrabotka na transakcija - angl. transaction processing). Koga klientskiot softver treba da se izmeni, toj mora da se sozdade, da se is~isti od gre{ki i da se instalira na ma{inata na klientot, {to e mnogu pokomplicirano i poskapo otkolku {to {to mo`e da pomislite. Osobeno problemati~no e da se poddr`uvaat pove}e tipovi na ma{ini i operativni sistemi. Kone~no, tuka e mnogu va`no i pra{aweto za performansite: stotici klienti mo`at da postavuvaat barawa na va{iot server vo koj bilo moment, pa i najmaloto zadocnuvawe e problemati~no. Za da se minimizira docneweto, programerite naporno rabotat za da gi oslobodat procesnite zada~i, prefrlaj}i del od obrabotkata na ma{inata na klientot, a ponekoga{ i na drugi ma{ini na serverskata strana, koristej}i takanare~eni posrednici (angl. middleware). (Posrednicite isto taka se koristat za da se podobri odr`uvaweto.) Ednostavnata postapka za pra}awe informacii e tolku sloevita i slo`ena {to celiot problem izgleda beznade`no enigmati~en. No i pokraj toa e mnogu va`na: klient/server obrabotkata nosi otprilika polovina od site programski aktivnosti. Taa e zadol`ena za s, po~nuvaj}i od zemawe na nara~kite, transakcijata so kreditni karti~ki, pa do pra}awe na raznite vidovi podatoci - berzanski, nau~ni, vladini; {to i da vi dojde na um. Vo minatoto sme se soo~uvale so individualni re{enija za individualni problemi; sekoj pat smisluvavme novo re{enie. Be{e te{ko da se osmislat, be{e te{ko da se upotrebuvaat i korisnikot treba{e da u~i nov interfejs
Zapoznavawe so objekti
47
ednostavno gi interpretira{e i prika`uva{e. Osnovniot jazik HyperText Markup Language (HTML) sodr`i ednostavni mehanizmi za sobirawe podatoci: poliwa za tekst, poliwa za potvrda, poliwa so radio kop~iwa, listi i pa|a~ki listi, kako i kop~iwa koi {to mo`at da bidat programirani samo da gi izbri{at podatocite vo obrazecot ili da gi dostavat(angl. submit) podatocite od obrazecot nazad do serverot. Ova dostavuvawe se izvr{uva preku interfejsot CGI (angl. Common Gateway Interface), koj {to postoi na site Veb serveri. Tekstot koj {to se nao|a vo prateniot paket mu ka`uva na serverot {to da napravi so toj paket. Naj~estata akcija e da se startuva programata koj {to se nao|a na serverot, vo imenikot koj {to naj~esto e narekuva cgi-bin. (Ako go gledate poleto so adresata vo gorniot del od Va{iot prelistuva~ koga }e pritisnete na nekoe kop~e na Veb stranicata, ponekoga{ mo`ete da vidite cgi-bin.) Ovie programi mo`at da bidat napi{ani na re~isi site jazici. ^esto se pi{uva{e na Perl, bidej}i toj e napraven za rabota so tekst, a pritoa se interpretira, pa mo`e da bide instaliran na bilo koj server, bez ogled na procesorot ili na operativniot sistem. Deneska s pove}e se koristi Python (www.Python.org), zatoa {to e posilen i poednostaven. Mnogu dene{ni mo}ni Veb stranici se izgradeni isklu~ivo na CGI programi, so koi {to mo`ete da napravite re~isi s. Sepak, odr`uvaweto na Veb stranicite izgradeni na CGI programi mo`e brzo da stane premnogu slo`eno za odr`uvawe, a postoi i problem so vremeto na odziv. Odzivot na CGI programata zavisi od toa kolku podatoci se pra}aat, kako i od opteretuvaweto na serverot i na Internetot. (Pritoa, startuvaweto na CGI programite mo`e da bide bavno.) Prvite proektanti na Veb-ot ne predvidele kolku brzo ovaa propustnost (opseg) }e stane premala za novite vidovi aplikacii koi {to lu|eto gi razvile. Na primer, re~isi e nevozmo`no dosledno da se ostvari koj bilo vid na dinami~ko crtawe grafika bidej}i za sekoja verzija, grafikata mora da se napravi GIF datoteka i taa da se prenese od serverot do klientot. (GIF e akronim od Graphic Interchange Format, format za razmena na grafika.) Pokraj toa, bezsomneno ste se steknale so neposredno iskustvo so proverka na pravilnosta na podatocite na vlezniot Veb obrazec. Go pritiskate kop~eto za pra}awe na stranicata, serverot }e ja startuva CGI programata koja ja otkriva gre{kata, ja formatira HTML stranicata i Ve informira za gre{kata, a potoa Vi ja vra}a taa stranica. Toga{ morate da se vratite na prethodnata stranica i da se obidete povtorno. Ova ne samo {to e bavno, tuku e i zamorno. Re{enieto e programirawe od strana na klientot. Pove}eto stati~ni kompjuteri na koi rabotat Veb prelistuva~ite se mo}ni ma{ini sposobni da napravat golema rabota, a so prvobitniot stati~ki HTML pristap samo stoeja i bez rabota ~ekaa serverot da ja ispora~a slednata stranica. Programiraweto od strana na klientot zna~i deka Veb prelistuva~ot ja
Zapoznavawe so objekti
49
pravi seta rabota koja {to mo`e da se zavr{i, korisnikot mnogu pobrzo go dobiva rezultatot i iskustvoto so Veb stranicata e pointeraktivno. Diskusiite za programiraweto od strana na klientot malku se razlikuvaat od diskusiite za programiraweto, voop{to. Parametrite se re~isi istite, no platformata e razli~na; Veb prelistuva~ot e sli~en na ograni~en operativen sistem. Na kraj, sepak morate da programirate, i zatoa programiraweto od strana na klientot povlekuva niza problemi i re{enija. Ostatokot od ovoj del dava pregled na pra{awa i pristapi na programiraweto od strana na klientot.
Dodatoci (Plug-ins)
Razvojot na dodatoci pretstavuva eden od najgolemite napredoci vo programiraweto od strana na klinetot. Na ovoj na~in programerot ima mo`nost da dodava nova funkcionalnost na Veb prelistuva~ot taka {to }e prezeme del od kod koj {to se smestuva na soodvetnoto mesto vo prelistuva~ot. Mu veli na prelistuva~ot: Od sega pa natamu mo`e{ da ja vr{i{ ovaa nova aktivnost.(Dodatokot treba da go prezemete samo edna{.) Preku dodatocite na prelistuva~ite im se pridavaat brzi i mo}ni pro{iruvawa, no pi{uvaweto na dodatocite ne e trivijalna zada~a i ne e ne{to {to bi sakale da go pravite kako del od izgradba na odreden sajt. Vrednosta na dodatocite za programiraweto od strana na klientot e toa {to tie mu ovozmo`uvaat na stru~noto lice da pravi novi pro{iruvawa i da gi dodava tie pro{iruvawa na prelistuva~ot bez odobruvawe na proizveduva~ot na prelistuva~ot. Zatoa, podatocite pretstavuvaat zadna vrata koja {to ovozmo`uva sozdavawe novi jazici za programirawe od strana na klientot (iako site jazici ne se realizirani kako dodatoci).
Skriptni jazici
Dodatocite rezultiraa vo razvojot na skriptnite jazici za prelistuva~ite. So pomo{ na skriptnite jazici go vgraduvate izvorniot kod na programata za klientskata strana direktno vo HTML stranicata, a dodatokot koj go tolkuva toj jazik avtomatski se aktivira pri prika`uvaweto na HTML stranicata. Skriptnite jazici obi~no lesno se sfa}aat i bidej}i se pi{uvaat vo delot na HTML stranicata, se v~ituvaat mnogu brzo, so eden pristap na serverot na koj {to se nao|a taa stranica. Nedostatokot e toa {to va{iot kod e izlo`en i sekoj mo`e da go vidi (i ukrade). Vo princip, sepak ne pravite nekoi sofisticirani ne{ta so pomo{ na skriptnite jazici, pa ovoj nedostatok i ne e nekoj golem problem. Postoi eden skripten jazik koj pove}eto Veb prelistuva~i go podr`uvaat i bez bilo kakov dodatok - toa e JavaScript (koj ima mnogu mala sli~nost so Java, i mora da se u~i posebno. Taka e imenuvan samo za da prigrabi del od marketin{kiot zalet na Java). Za `al, pove}eto Veb prelistuva~i svojata
50
Da se razmisluva vo Java
Brus Ekel
podr{ka za JavaScript ja realiziraa na svoj edinstven na~in, razli~en od ostanatite prelistuva~i, pa duri i od ostanatite svoi verzii. Standardizacijata na JavaScript vo oblik na ECMAScript pomogna, no na raznite prelistuva~i im treba{e mnogu vreme za da dojdat do toa nivo (ne pomogna mnogu toa {to Microsoft go forsira{e svojot VBScript, koj {to ima neodredeni sli~nosti so JavaScript). Za programata mo`e da se izvr{uva na site prelistuva~i, po pravilo morate da ja pi{uvate koristej}i go najmaliot zaedni~ki imenitel na site postoe~ki verzii na JavaScript. Programskata obrabotka na gre{ki, kako i otkrivaweto i otstranuvaweto na gre{ki od JavaScript, mo`at da se opi{at samo kako ma~ewe. Dokaz za tie pote{kotii e faktot deka duri neodamna e napi{ana navistina slo`ena programa na JavaScript (toa e Gmail na Google), {to bara{e golema posvetenost i stru~nost. So ova se naglasuva deka skriptnite jazici koi {to se koristat vo Veb prelistuva~ite se predvideni za da re{at odredeni vidovi problemi, prvenstveno da se napravat pobogati i pointeraktivni grafi~ki korisni~ki okolini. Skriptniot jazik mo`e da re{i do 80 procenti od problemite koi {to gi sre}avame pri programirawe od strana na klientot. Va{ite problemi verojatno spa|aat vo tie 80 procenti, a bidej}i skriptnite jazici ovozmo`uvaat polesna i pobrza rabota, bi trebalo da razmislite za skriptnite jazici pred da se vpu{tite vo mnogu pozamrseni re{enija, kako {to e programiraweto na Java.
Java
Ako skriptnite jazici mo`at da re{at 80 procenti od problemite pri klientskoto programirawe, {to e so ostanatite 20 procenti, navistina te{kite ne{ta? Java e popularno re{enie za tie 20 procenti. Pred s, toa e mo}en programski jazik, siguren, me|uplatformski i internacionalen. Java postojano se {iri: se dodavaat novi mo`nosti na jazikot i bibliotekata koi {to mo`at elegantno da gi re{at problemite koi{to se te{ki i vo tradicionalnite programski jazici, kako {to se istovremena rabota, pristap na bazi, mre`noto programirawe i distribuiranata obrabotka. Java dozvoluva programirawe od strana na klientot preku aplet (applet) i so pomo{ na Java Web Start. Aplet e mala programa koja {to mo`e da se izvr{uva samo vo Veb prelistuva~ot. Aplet se prezema avtomatski kako del od Veb stranicata (kako {to, na primer, avtomatski se prevzema grafikata). Koga apletot se aktivira, toj izvr{uva programa. Del od negovata pogodnost e toa {to ovozmo`uva avtomatski da go distribuirate klientskiot softver od serverot vo momentot koga na korisnikot mu e potreben, a ne porano. Korisnikot ja dobiva najnovata verzija od klientskiot softver i toa bez slo`ena reinstalacija. Poradi na~inot na koj {to Java e proektirana, programerot treba da napravi samo edna edinstvena programa, a taa programa avtomatski raboti na site smeta~i koi {to imaat prelistuva~i so poddr{ka
Zapoznavawe so objekti
51
za Java. (Ova opfa}a golem del od smeta~ite.) Bidej}i Java e potpoln programski jazik, mo`ete da ja zavr{ite seta rabota koja {to mo`e da se zavr{i na klientskata strana, pred i po postavuvaweto barawa na serverot. Na primer, nema potreba da pra}ate obrazec so barawe preku Internet za da otkriete dali ste zgre{ile pri vpi{uvawe na datumot ili nekoj drug parametar; va{iot smeta~ mo`e brzo da iscrtuva grafiki vrz osnova na podatoci, namesto da ~eka serverot da gi iscrta i da ja vrati slikata. Pokraj momentalnoto podobruvawe na brzinata i odzivot, se namaluvaat i vkupniot mre`en soobra}aj i opteretuvaweto na serverot i se spre~uva zabavuvawe na celiot Internet.
Drugi mo`nosti
Iskreno ka`ano, Java apletite ne gi ispolnija golemite po~etni o~ekuvawa. Koga Java najprvin se pojavi, najmnogu se zboruva{e tokmu za apletite, bidej}i tie treba{e kone~no da ovozmo`at seriozno programirawe od strana na klientot, da ja zgolemat brzinata na odzivot i da go namalat protokot na podatoci potreben za Internet aplikaciite. Na Veb navistina mo`at da se najdat i mnogu umni apleti, no ne dojde do seop{to preo|awe na apletite. Najverojatno najgolemiot problem be{e goleminata na izvr{nata okolina na Java (Java Runtime Environment, JRE) od 10 MB, koja {to treba{e da ja prezemete od Veb i da ja instalirate, {to go ispla{i prose~niot korisnik. Sudbinata mo`ebi im ja zape~ati faktot deka Microsoft odlu~i da ne go ispora~uva JRE kako del od svojot Internet Explorer. Vo sekoj slu~aj, Java apletite ne se pro{irija sekade. Bez obzir na toa, vo nekoi situacii s u{te vredi da gi imate Java apletite i Java Web Start aplikaciite. Dokolku upravuvate so smeta~ite na korisnikot, da re~eme vo nekoja korporacija, bi bilo umno distribucijata i a`uriraweto na klientskite aplikacii da gi vr{ite so pomo{ na ovie tehnologii, bidej}i taka }e za{tedite zna~itelna koli~ina na vreme, trud i pari, osobeno ako morate ~esto da go a`urirate nivniot softver. Vo glavata Grafi~ki korisni~ki okolini }e se zapoznaeme so Flex, novata tehnologija na Adobe koja vetuva - vo nea se pravat Flash apleti. Bidej}i pove}e od 98 procenti od site Veb prelistuva~i imaat Flash Player (na Windows, Linux i Mac), mo`eme da smetame deka toj e usvoen standard. Flash Player-ot se instalira i a`urira lesno i brzo. Jazikot ActionScript e napraven vrz osnova na ECMAScript taka {to e dovolno poznat, no Flash-ot ovozmo`uva programirawe bez da se gri`ite za specifi~nostite na razni prelistuva~i zatoa e mnogu poprivle~en od JavaScript-ot. Pri programiraweto od strana na klientot, ovaa mo`nost vredi da se razgleda.
52
Da se razmisluva vo Java
Brus Ekel
.NET i C#
Edno vreme glaven konkurent na Java apletite be{e ActiveX na Microsoft, iako samo na Windows smeta~ite. Od toga{ Microsoft go napravi prviot vistinski konkurent na Java vo oblik na platformata .NET i programskiot jazik C#. Platformata .NET e pribli`no ista kako i virtuelnata ma{ina na Java (Java Virtual Machine, JVM) plus bibliotekata na Java. JVM e softverska platforma na koja {to se izvr{uvaat Java programite, a C# ima golemi sli~nosti so Java. Bez somnenie, se raboti za dosega najdobriot proizvod na Microsoft vo podra~jeto na programskite jazici i programskite okolini. Sekako, Microsoft ima{e golema prednost bidej}i mo`e{e da u~i na tu|i gre{ki, no toj navistina nau~il. Prv pat od svoeto nastanuvawe, Java dobi vistinska konkurencija. Zatoa proektantite na Java vo Sun dobro go razgledaa C#, dobro razmislija za toa zo{to programerite bi sakale da preminat na C#, i odgovorija so pravewe fundamentalni podobruvawa na Java - Java SE5. Momentalno najgolemata slabost na .NET i va`noto pra{awe e dali Microsoft }e dozvoli negovo potpolno prenesuvawe na drugi platformi. Microsoft tvrdi deka toa mo`e da se napravi bez problem, i deka ve}e postoi delumna realizacija na .NET koja {to raboti na Linux (proekt na Mono, www.gomono.com), no dodeka ne se napravi potpolna realizacija od koja {to Microsoft ni{to nema isfrleno, rizi~no e .Net da se smeta za re{enie za site platformi.
Internet i Intranet
Veb e najop{toto re{enie na klient/server problemot, pa logi~no e da ja iskoristite istata tehnologija za re{avawe podno`estvo na toj problem, osobeno klasi~niot klient/server problem vo nekoja kompanija. Pri tradicionalniot klient/server pristap, postoi problem poradi raznite tipovi smeta~i kako i problem poradi te{koto instalirawe na noviot klientski softver. Dvata problema se dobro re{eni so pomo{ na Veb prelistuva~ot i programirawe od strana na klientot. Koga Veb tehnologijata se koristi za informaciona mre`a ograni~ena na odredena kompanija, toa go narekuvame intranet. Intranet obezbeduva mnogu pogolema bezbednost od Internetot bidej}i pristapot na serverite vo komanijata mo`ete fizi~ki da go kontrolirate. Izgleda deka korisnicite, koga edna{ }e go sfatat osnovniot princip na rabota na prelistuva~ot, mnogu polesno izleguvaat na kraj so razli~nite izgledi na stranicite i apletite, pa pobrzo u~at novi sistemi. Problemot so bezbednosta n smestuva vo edna od grupite koi {to se sozdavaat, se ~ini, po avtomatizam, vo svetot na klient/server programiraweto. Ako va{ata programa se izvr{uva na Internet, ne znaete na koja platforma taa }e raboti i sakate da bidete sosem sigurni deka ne
Zapoznavawe so objekti
53
{irite nepravilen kod. Vi treba ne{to nezavisno od platformata i bezbedno, kako {to se skripten jazik ili Java. Ako rabotite na intranet, pred Vas se postavuvaat razli~ni ograni~uvawa. Ne e nevoobi~aeno site smeta~i da bidat platformi na Intel/Windows. Na intranetot sami ste odgovorni za kvalitetot na svojata prorama i mo`ete da gi otstranuvate gre{kite kako {to tie se pojavuvaat. Pokraj toa, mo`ebi ve}e dovolno imate nasleden kod koj {to ste go koristele za potradicionaen klient/server pristap, pri {to fizi~ki morate da gi instalirate klientskite programi sekoj pat koga rabotite na podobruvawe. Vremeto potro{eno na instalirawe na podobruvawata vi dava pri~ina pove}e da prejdete na smeta~i kade {to podobruvawata se nevidlivi i avtomatski. (Ovoj problem go re{ava i Java Web Start.) Ako imate rabota so takov intranet, najrazumen pristap e da trgnete po najkratkiot pat koj Vi ovozmo`uva da ja koristite postoe~kata baza na kodovi, namesto povtorno da gi pi{uvate programite na noviot jazik. Koga se soo~uvate so ovaa zbunuva~ka niza re{enija za programirawe od strana na klientot, najdobriot plan za napad e analiza na isplatlivosta. Razgledajte gi ograni~uvawata koi {to va{iot problem go nametnuva i najkratkiot pat do re{enieto. Bidej}i programiraweto od strana na klientot e sepak programirawe, sekoga{ e dobro da se odbere pristap koj {to ovozmo`uva najbrz razvoj za Va{ata momentalna situacija. Ova e hrabar stav koj {to ve podgotvuva za neizbe`nite sredbi so problemi od programski razvoj.
54
Da se razmisluva vo Java
Brus Ekel
programiraweto od strana na server se vr{i na Perl, Python, C++, ili nekoj drug jazik za pi{uvawe CGI programi, no se pojavija i ponapredni sistemi. Me|u niv se i Veb serverite bazirani vrz Java, koi {to ovozmo`uvaat pi{uvawe na takanare~eni servleti (angl. servlets). Kompaniite koi razvivaat Veb stranici preo|aat na Java poradi tehnologijata na servleti i od niv izvedenite JSP stranici, najmnogu zatoa {to taka se isklu~uvaat problemite pri rabota so prelistuva~i so razli~ni mo`nosti. Programiraweto od strana na serverot e razgledano vo knigata Thinking in Enterprise Java, koja {to mo`ete da ja najdete na adresata www.MindView.net. Nasproti toa {to za Java se zboruva samo vo vrska so Internetot, toa e programski jazik so op{ta namena so ~ija pomo{ mo`ete da re{ite koj bilo tip na problem, kako i so pomo{ na drugi jazici. Tuka silata na Java ne e samo vo prenoslivosta, tuku i vo lesnotijata na programirawe, robusnosta, golemata standardna biblioteka i brojnite biblioteki od drugi proizveduva~i ko postojano se razvivaat.
Rezime
Znaete kako izgleda proceduralna programa: definicii za podatoci i povici na funkcii. Za da ja pronajdete zna~eweto na takvata programa, morate malku da se poma~ite i da gi pregledate povicite na funkcii konceptite od nisko nivo za da si sozdadete model vo Va{ata glava. Poradi toa ni treba posredno pretstavuvawe koga proektirame proceduralni programi: sami za sebe, tie programi mo`at da zbunuvaat bidej}i na~inite na izrazuvawe pove}e se naso~eni kon smeta~ot otkolku kon problemot koj go re{avame. Bidej}i OOP dodava mnogu novi idei na onie koi gi nao|ate vo proceduralen jazik, mo`ebi mislite deka Java programata }e bide mnogu pokompliciran od ekvivalentnata C programa. ]e bidete prijatno iznenadeni: edna dobro napi{ana Java programa e glavno daleku poednostavna i mnogu porazbirliva od ekvivalentnata C programa. ]e imate definicii za objektite koi pretstavuvaat idei vo Va{iot prostor na problemi (namesto pra{awa na prikazot na smeta~ot) i poraki prateni do tie objekti koi {to pretstavuvaat aktivnosti vo toj prostor. Dobrata strana vo objektno orientiranoto programirawe e toa {to pri dobro proektirana programa e lesno da se razbere kodot dodeka go ~itate. Obi~no ima i zna~itelno pomal kod , bidej}i mnogu od Va{ite problemi }e gi re{ite so povtorno koristewe na postoe~ki kod od bibliotekata. OOP i Java mo`ebi ne se za sekogo. Va`no e da gi procenite svoite potrebi i da odlu~ite dali Java optimalno }e gi zadovoli tie potrebi ili bi bilo podobro da rabotite so nekoj drug programski sistem (vklu~uvaj}i go onoj koj momentalno go koristite). Ako znaete deka Va{ite potrebi }e bidat tesno specijalizirani vo bliska idnina i ako imate specifi~ni ograni~uvawa koi
Zapoznavawe so objekti
55
Java mo`ebi ne mo`e da gi zadovoli, toga{ razgledajte gi ostanatite raspolo`livi mo`nosti. Konkretno, prepora~uvam da go razgledate Python; posetete ja stranicata www.Python.org. Ako sepak ja odberete Java, barem }e znaete koi mo`nosti ste gi imale i }e imate jasna vizija zo{to ba{ nea ste ja odbrale, odnosno zo{to ste trgnale vo taa nasoka.
56
Da se razmisluva vo Java
Brus Ekel
Se e objekt
Da zboruvavme poinakov jazik, }e percepiravme sosema poinakov svet.
Ludwig Wittgenstein (1889-1951)
Se e objekt
57
ponatamu da go kontrolirate televizorot, }e go zemete so Vas dale~inskiot upravuva~ t.e. referencata, a ne televizorot.
Dale~inskiot upravuva~ mo`e da postoi sam za sebe, bez televizor. Odnosno, toa {to imate referenca, ne zna~i zadol`itelno deka imate i nekoj objekt povrzan so nea. Pa ako sakate da ~uvate zbor ili re~enica, treba da napravite referenca na objektot od klasa String:
String 5;
No so ova ste ja kreirale samo referencata, ne i objektot. Dokolku re{ite vo ovoj moment da pratite poraka preku s , }e naidete na gre{ka bidej}i vsu{nost s ne e povrzana so ni{to (nema televizor). Pobezbeden na~in, e sekoga{ da ja inicijalizirate referencata koga ja kreirate:
String 5 = asdf;
1 Ova mo`e da dojde do nesoglasuvawa. Ima lu|e koi velat, Jasno e deka e poka`uva~ no ova povlekuva pretpostavka za realizacija. Isto taka, po svojata sintaksa referencite na Java se posrodni so referencite na S++ otkolku so poka`uva~ite. Vo prvoto izdanie na ovaa kniga, izbrav da vovedam eden nov poim identifikator (handle), bidej}i S++ i Java referencite mnogu se razlikuvaat. Jas izleguvav od S++ i ne sakav da gi zbunuvam S++ programerite za koi pretpostavuvav deka }e bidat najbrojni korisnici na Java. Pred da go podgotvam vtoroto izdanie, sfativ deka poimot referenca e naj~esto upotrebuvan poim i deka bilo koj {to }e saka da se prefrli na Java }e mora da se spravuva so mnogu pova`ni poimi pokraj terminologijata na referencite, pa u{te eden poim nema premnogu da pre~i. Sepak, ima mnogu lu|e koi ne se soglasuvaat so poimot referenca. Vo edna kniga go pro~itav tvrdeweto deka e sosema pogre{no da se ka`e deka Java podr`uva prosleduvawe preku referenca, bidej}i Java identifikatorite na objektite vo Java (spored avtorot) se vsu{nost referenci na objektot. I (toj prodol`uva) bidej}i s vsu{nost se prosleduva spored vrednost, Vie ne izvr{uvate prosleduvawe preku referenca, tuku prosleduvate referenca na objekt po vrednost. Nekoj mo`e da prigovara za to~nosta na takvi zamrseni objasnuvawe, no mislam deka mojot pristap go poednostavnuva razbiraweto na konceptot bez kakvi bilo zagubi (sepak, branitelite na jazikot mo`e da tvrdat deka ve la`am, no sepak }e re~am deka obezbeduvam soodvetna apstrakcija.
Ovde se koristi specijalna karakteristika na Java: Stringovite (znakovnite nizi) mo`at da bidat inicijalizirani so tekst pod navodnici. Obi~no, za objektite mora da koristite poop{t (globalen) tip na inicijalizacija.
58
Da se razmisluva vo Java
Brus Ekel
Ova ne zna~i samo Napravi mi nov objekt od klasa String. tuku isto taka dava informacija za toa kako da se napravi objektot String taka {to se naveduva inicijalnata znakovna niza. Se razbira, pokraj podatocite od tip String, Java izobiluva so golemo koli~estvo odnapred definirani tipovi podatoci. Mnogu e pova`no da mo`ete da kreirate svoi tipovi. Vsu{nost, sozdavaweto novi tipovi e fundamentalna aktivnost vo Java programiraweto i toa e ona {to }e go u~ite ponatamu vo knigava.
Se e objekt
59
Dobrata strana na dinami~kata memorija e deka za razlika od stekot, preveduva~ot ne mora da znae kolku dolgo skladi{teto mora da ostane vo dinami~kata memorija. Ottamu, ima golema fleksibilnost vo skladiraweto na podatoci na dinami~kata memorija. Koga i da Vi zatreba nekoj objekt, ednostavno go pi{uvate (vnesuvate) kodot za negovo sozdavawe koristej}i new i skladi{teto }e se sozdade vo dinami~kata memorija. Sekako, ima cena koja {to mora da se plati za vakvata fleksibilnost: ]e treba mnogu pove}e vreme za da se dodeli i sredi skladi{te vo dinami~kata memorija otkolku vo stekot (dokolku mo`ete da kreirate objekti na stekot vo Java, kako {to mo`ete vo S++). 4. Konstantno skladi{te. Konstantni vrednosti ~esto se vnesuvaat direktno vo kodot na programata, {to e bezbedno bidej}i tie nikoga{ ne mo`at da se promenat. Ponekoga{ konstantite izdvoeno se grupiraat za opcionalno da mo`at da se smestat vo ROM memorijata (memorija samo za ~itawe, read-only memory), vo vgradeni sistemi.*2 5. Skladi{te koe ne e RAM. Dokolku podatocite se smesteni kompletno nadvor od programata, mo`at da postojat i koga programata ne se izvr{uva, nadvor od nejzinata kontrola. Dva osnovni primeri za ova se strujnite objekti (angl. streamed objects), {to se objekti pretvoreni vo strui od bajti, so cel da bidat prateni na druga ma{ina i trajni objekti(angl. persistent objects), {to se objekti smesteni na disk za da ja za~uvaat svojata sostojba duri i koga programata }e go prekine svoeto izvr{uvawe. Trikot so ovie tipovi na skladi{ta e deka vo niv te{ko e da se pretvorat objektite vo ne{to {to mo`e da postoi na drugiot medium, a {to mo`e da postane regularen memoriski (RAM-baziran) objekt koga }e bide potrebno. Java obezbeduva poddr{ka za lesna trajnost, a mehanizmite kakvi {to se JDVS i Hibernate obezbeduvaat posofisticirana poddr{ka za skladirawe i prezemawe na informacii za objektite vo bazite na podatoci.
2 Primer za ova e skladi{teto na znakovni nizi. Site literalni znakovni nizi i konstantnite izrazi ~ij rezultat e znakovna niza avtomatski se smestuvaat vo posebniot del od memorijata so nepromenliva (stati~ka adresa).
60
Da se razmisluva vo Java
Brus Ekel
smestuva objektite vo dinami~kata memorija. Za ovie tipovi Java se vra}a na pristap koj go imaat S i S++. Taka, namesto kreirawe promenliva so koristewe new, se kreira avtomatska promenliva, koja ne e referenca. Promenlivata direktno ja ~uva vrednosta, i rabotata so nea e mnogu poefikasna, bidej}i se ~uva na stekot. Java ja odreduva goleminata na sekoj prost tip. Ovie golemini ne se menuvaat od edna do druga ma{inska arhitektura kako {to toa e slu~aj vo pove}eto jazici. Nepromenlivosta na goleminata e edna od pri~inite poradi koi Java programite se poprenoslivi otkolku programite vo drugite jazici. Site numeri~ki tipovi se ozna~eni, pa ne barajte neozna~eni tipovi. Goleminata na tipot boolean ne e eksplicitno odredena. Boolean e edinstveno definiran da bide sposoben da zema vrednosti kako true (to~no) ili false (neto~no).
Prost tip
Golemina vo bitovi
Najmal broj
Najgolem broj
Obviva~ki tip
Obvitkuva~kite (pokriva~kite) (angl. wrapper) klasi za prostite tipovi na podatoci ovozmo`uvaat vo dinami~kata memorija da napravite objekt koj pretstavuva odreden prost tip. Na primer: Se e objekt 61
Java YE5 so avtomatsko pakuvawe (angliski autoboxing) avtomatski gi konvertira (pretvori, obvitka) prostite tipovi vo objekti (obvitkuva~ki tipovi):
Character ch = x;
Nizi vo Java
Prakti~no site programski jazici poddr`uvaat nekakov vid na nizi. Koristeweto na nizi vo S i S++ e opasno bidej}i nizite se samo memoriski blokovi. Ako programata i pristapi na nizata nadvor od nejziniot
62
Da se razmisluva vo Java
Brus Ekel
memoriski blok ili ja koristi memorijata pred da inicijalizira (voobi~aeni programski gre{ki), }e dojde do nepredvidlivi rezultati. Edna od osnovnite celi na Java e sigurnosta, pa mnogu od problemite koi gi ma~at programerite vo S i S++ ne se povtoruvaat vo Java. Vo Java nizata e garantirano inicijalizirana i ne mo`e da i se pristapi nadvor od nejzinite granici. Opsegot na nizata se proveruva po cena na malo koli~estvo potro{uva~ka na memorija vo sekoja niza, kako i so proverkata na indeksot pri izvr{uvawe na programata, no se pretpostavuva deka bezbednosta i zgolemenata produktivnosta se vredni za toa (a Java ponekoga{ mo`e da gi optimizira ovie operacii). Koga sozdavate niza so objekti, vsu{nost sozdavate niza na referenci i sekoja od tie referenci avtomatski se inicijalizira na posebna vrednost so nejzin sopstven rezerviran (klu~en) zbor: null. Koga Java }e naide na null, taa prepoznava deka doti~nata referenca ne poka`uva na objekt. Na sekoja referenca, pred da ja upotrebite, morate da i dodelite objekt, i dokolku se obidete da koristite referenca koja s u{te ima vrednost null, problemot }e bide prijaven pri izvr{uvaweto. Na toj na~in, vo Java se spre~eni tipi~nite gre{ki so nizite. Mo`ete isto taka da kreirate i niza od prosti tipovi. Povtorno, preveduva~ot garantira inicijalizacija bidej}i ja memorijata za taa niza ja polni so nuli. Nizite }e bidat detaqno pretstaveni vo narednite poglavja.
Oblast na va`ewe
Mnogu proceduralni jazici go imaat konceptot na oblast na va`ewe (angliski scope). Taa gi opredeluva vidlivosta i `ivotniot vek na imiwata definirani vo ramkite na taa oblast. Vo S, S++ i Java, oblasta na va`ewe e opredelena so golemi zagradi {}. Na primer:
{ int x = 12;
Se e objekt
63
// Dostapna e samo promenlivata x ( int q =96: // Dostapni se i x i q ) // Dostapna e samo x // q e nadvor od oblasta na vazenje }
Promenliva definirana so oblast na va`ewe, e dostapna samo do krajot od taa oblast na va`ewe. Kakov bilo tekst posle // pa se do krajot od redot e komentar. Vovlekuvaweto go pravi Java kodot polesen za ~itawe. Bidej}i Java e jazik od slobodna forma, dodatnite prazni mesta, tabulatori i novi redici ne vlijaat na rezultantnata programa. Vo Java ne mo`ete da go napravite slednovo, iako toa e mo`no vo S i S++:
{ int x = 12; { int x = 96; // } }
nepropisno
Preveduva~ot }e objavi deka promenlivata h e ve}e definirana. Ottamu, mo`nosta na S i S++ da skrijat promenliva vo pogolema oblast ne e dozvolena, bidej}i Java dizajnerite smetaa deka toa }e vodi kon zbunuva~ki programi.
referencata s is~eznuva na krajot od oblasta na va`ewe. Me|utoa, objektot od klasata String na koj s poka`uva, s u{te }e zazema memorija. Vo ovoj mal del od kodot, nema na~in da mu pristapite na objektot po krajot na oblasta na va`ewe, bidej}i edinstvenata referenca na nego e nadvor od oblasta na
64
Da se razmisluva vo Java
Brus Ekel
va`ewe. Vo podocne`nite poglavja }e vidite kako referencata na objektot mo`e da se prosleduva i umno`uva vo tekot na traeweto na programata. Bidej}i objektite sozdadeni so pomo{ na new se zadr`uvaat onolku dolgo kolku {to Vi se potrebni, proizleguva deka cela niza na S++ programski problemi ednostavno ne postojat vo Java. Vo S++ morate da se pogri`ite ne samo za toa dali objektite postojat s dodeka Vi se potrebni, tuku i da gi uni{tite koga }e zavr{ite so niv. Toa povlekuva interesno pra{awe. Ako Java gi ostava objektite da le`at naokolu, {to gi spre~uva da ja prepolnat memorijata i da ja prekinat programata? Ova e tokmu takov tip na problem {to bi se javil vo S++. Tuka vsu{nost se slu~uva magijata. Java ima sobira~ na |ubre, {to ja interesiraat samo objektite koi bile sozdadeni so new i gi otkriva samo onie na koi ve}e nema referenci. Potoa ja osloboduva memorijata za tie objekti, taka {to istata mo`e da se koristi za novi objekti. Ova zna~i deka nikoga{ nema da ima potreba sami da se gri`ite za osloboduvaweto na memorijata. Ednostavno kreirate objekti i koga nema pove}e da vi trebaat, tie samite }e gi snema. Ova eliminira edna odredena klasa na programski problem: takanare~eno istekuvawe na memorija vo koj programerot zaborava da ja oslobodi memorijata.
Ova voveduva nov tip, iako teloto na klasata se sostoi samo od komentar (yvezdata, kosata crta i toa se nao|a me|u tie znaci, za {to }e sledi objasnuvawe podocna vo ova poglavje), pa nema {to mnogu da se napravi so nego. Sepak, mo`ete da kreirate objekt od vakov tip so koristewe na new:
NekoeImeNaTip a = new NekoeImeNaTip ();
No na klasata ne mo`ete da ka`ete da napravi mnogu raboti(toa zna~i deka ne mo`ete da pra}ate nekoi interesni poraki) dodeka ne definirate nekoi nejzini metodi.
Se e objekt
65
Poliwa i Metodi
Koga definirate klasa (a se {to pravite vo Java e definirawe klasa, pravewe objekti na tie klasi i pra}awe poraki do tie objekti), vo nea mo`ete da stavite dva tipa na elementi: poliwa (koi ponekoga{ se narekuvaat ~lenovi na podatocite), i metodi (koi ponekoga{ se narekuvaat funkciski ~lenovi). Pole e objekt od koj bilo tip so kogo mo`ete da se povrzete preku negovata referenca ili prost tip. Dokolku e referenca na objekt, morate da ja inicijalizirate taa referenca za da ja povrzete so realen objekt (so koristewe na new, kako {to vidovme prethodno). Sekoj objekt si ima svoe sopstveno skladi{te za svoite poliwa. Obi~nite poliwa ne se delat me|u objektite od ista klasa. Sledi primer od klasa so nekolku poliwa:
Class SamoPodatoci { int i; double d; boolean b; }
Ovaa klasa ne pravi ni{to osven {to ~uva podatoci, no mo`e da kreirate objekt sli~en na ovoj:
SamoPodatoci data = new SamoPodatoci ();
Mo`ete da dodeluvate vrednosti na poliwata, no prvo morate da znaete kako da se obratite na ~len od eden objekt. Ova se postignuva so naveduvawe na imeto na referencata na objektot, potoa sleduva to~ka, posle koja pak, sleduva imeto na ~lenot vnatre vo objektot.
referencaNaObjekt.pole
Na primer:
podatoci.i = 47; podatoci.d = 1.1; podatoci.b = false;
Va{iot objekt mo`e da sodr`i i drugi objekti koi pak, sodr`at podatoci {to bi sakale da gi modificirate. Za da go postignete ova, samo prodol`ete da gi nadovrzuvate to~kite, na primer:
mojAvion.levRezervoar.kapacitet = 100;
Klasata nameneta za podatoci (DataOnly class) ne mo`e da napravi ni{to drugo osven da skladira podatoci, bidej}i nema metodi. Za da razberete kako rabotat metodite, }e morate prvo da nau~ite {to zna~at argumentite i povratnite vrednosti, koi }e bidat nakratko objasneti.
66
Da se razmisluva vo Java
Brus Ekel
Ovaa garancija ne va`i za lokalnite promenlivi - onie koi {to ne se poliwa na klasa. Ottuka, dokolku vnatre vo definicijata za metod imate:
int x;
toga{ h }e dobie nekoja proizvolna vrednost (kako i vo S i S++) i nema avtomatski da se inicijalizira na nula. Vie ste odgovorni za dodeluvawe na soodvetna vrednost za h pred voop{to da go koristite. Dokolku zaboravite, Java definitivno voveduva podobruvawe vo odnos na S++: }e dobiete gre{ka pri preveduvawe {to }e vi dade na znaewe deka promenlivata mo`ebi ne
Se e objekt
67
bila inicijalizirana. (Mnogu S++ preveduva~i }e ve predupredat za neinicijaliziranite promenlivi, no vo Java, tie se smetaat za gre{ki.)
Povratniot tip ja opi{uva vrednosta {to se vra}a kako rezultat na metodot koj ste go povikale. Listata na argumenti gi zadava tipovite i imiwata na informaciite {to sakate da gi prosledite do metodot. Imeto na metodot i listata na argumenti (koi zaedno go ~inat potpisot na metodot) edinstveno go identifikuvaat toj metod. Metodite vo Java mo`at da bidat kreirani kako del od klasa. Metodot mo`e da se povika samo za nekoj objekt3 i toj objekt mora da bide sposoben da go izvr{i toj povik. Ako se obidete da go povikate pogre{niot metod za objekt, vo tekot na preveduvaweto }e dobiete poraka za gre{ka. Metod za objekt se povikuva so naveduvawe na imeto na objektot prosledeno so to~ka, posle koja doa|a imeto na metodot i negovata lista so argumenti. Na primer:
imeNaObjektot.imeNaMetodot (arg1, arg2, arg3):
Na primer, da pretpostavime deka imate metod f() koj nema argumenti i vra}a vrednosti od tip int. Potoa, dokolku imate objekt so ime a za koj mo`e da se povika metodot f(), mo`ete da go napi{ete slednoto:
int x = a.f();
68
Da se razmisluva vo Java
Brus Ekel
^inot na povikuvawe na metod voobi~aeno se narekuva pra}awe poraka na objektot. Vo prethodniot primer, porakata e f(), a objektot e a. Objektno orientiranoto programirawe ~esto nakratko se pretstavuva kako ednostavno pra}awe poraki do objekti.
Listata so argumenti
Listata so argumenti na metodot odreduva koi informacii gi prosleduvate do metodot. Kako {to pretpostavuvate, ovaa informacija - kako se drugo vo Java - ja imaat formata na objektite. Zatoa vo listata so argumenti morate da gi precizirate tipovite na objekti koi se prosleduvaat i imiwata koi }e se koristat za sekoj od niv. Kako i vo drugi situacii vo Java kade izgleda deka Vie rabotite so objektite, Vie vsu{nost prosleduvate referenci.4 Sepak, tipot na referencata mora da bide ispraven. Dokolku argumentot treba da bide objekt od klasata String, toga{ morate da prosledite objekt od tip String, bidej}i vo sprotivno preveduva~ot }e prijavi gre{ka. Da razgledame metod ~ij argument e objekt od tip String. Eve ja definicijata na metodot, koja mora da bide smestena vo ramkite na definicijata na klasa za da se prevede:
int skladiste(String s) { return s.length() 2; }
Ovoj metod vi ka`uva kolku bajti se potrebni za da ja ~uvaat informacijata vo opredelen objekt od tip String. (Goleminata na sekoj znak vo String e 16 bita ili 2 bajta, za da go podr`i Unicode standardot). Argumentot e objekt od tip String i e nare~en s. Koga s }e se prosledi vo metodot, mo`ete da go tretirate kako koj bilo drug objekt. (Mo`ete da mu pra}ate poraki.) Ovde se povikuva metodot length(), kako eden od metodite na klasata String. Toj go vra}a brojot na znaci vo znakovnata niza. Isto taka mo`ete da ja vidite upotrebata na rezerviraniot zbor return, koj pravi dve raboti. Prvo, toj zna~i Ostavi go metodot, jas zavr{iv. Vtoro, dokolku metodot proizveduva vrednost, taa vrednost se smestuva vedna{ po naredbata return. Vo ovoj slu~aj, povratnata vrednost se proizveduva so presmetuvawe na izrazot s.length()*2.
4 So voobi~aeniot isklu~ok od prethodno spomnatiot specijalen tip na podatoci - boolean, char, byte, short, int, long, float i double. Vo celost, premestuvate objekti, {to vsu{nost zna~i deka premestuvate referenci na objekti.
Mo`ete da vratite podatok od kakov bilo tip, no dokolku ne sakate da vratite ni{to, toga{ uka`ete deka metodot vra}a void. Eve nekolku primeri:
Se e objekt
69
boolean indikator() { return true; } double osnovaPrirodenLog () { return 2.718; } void nisto() { return; } void nisto2() {}
Koga povratniot tip e void, toga{ rezerviraniot zbor return se koristi samo za da se izleze od metodot i zatoa e nepotreben koga }e go dostignete krajot na metodot. Od metodot mo`ete da se vratite od koja bilo to~ka, no dokolku ste navele povraten tip koj ne e void (non-void return type), vo toj slu~aj preveduva~ot }e ve prisili (so poraki za gre{ki) da go vratite soodvetniot tip na vrednost, bez razlika od kade se vra}ate. Vo ovoj pogled, mo`e da izgleda deka programata e samo kup od objekti so metodi ~ii argumenti se drugi objekti i koi ispra}aat poraki do tie drugi objekti. Toa e ona {to glavno i se slu~uva, no vo slednoto poglavje }e nau~ite kako da pravite detaqna rabota od nisko nivo so pravewe odluki vo ramkite na metodot. Za ova poglavje, pra}aweto na poraki }e bide dovolno.
Vidlivost na imeto
Kontrolata vrz imiwata e problem vo site programski jazici. Dokolku koristite ime vo eden modul od programata, a drug programer go koristi istoto ime vo drug modul, kako da gi razlikuvate tie imiwa i da gi spre~ite tie dve imiwa od sudirawe?. Vo S ova e poseben problem bidej}i mnogu ~esto programata e nezamislivo more od imiwa. S++ klasite (na koi se zasnovani i klasite na Java) vgnezduvaat funkcii vo ramkite na klasite pa nivnite imiwa ne mo`e da se sudrat so onie od drugite klasi. Sepak, S++ s u{te dozvoluva globalni podatoci i globalni funkcii, pa sudiraweto e s u{te vozmo`no. Za da go re{i ovoj problem, S++ vnese imenski prostor (namespaces) so koristewe na dodatni rezervirani zborovi. Java uspea da go izbegne seto ova blagodarenie na noviot pristap. Za da proizvede ednozna~no ime za biblioteka, Java kreatorite sakaat da go koristite imeto na Va{iot Internet domen vo obraten redosled bidej}i tie imiwa se sigurno edinstveni i unikatni. Bidej}i imeto na mojot domen e MindView.net, mojata uslu`na biblioteka za otstranuvawe na nedostatocite bi go dobila imeto net.mindview.utility.foibles. Otkako }e go navedete imeto na domenot vo obraten redosled, slednite to~ki treba da gi pretstavuvaat podimenikite. Vo Java 1.0 i Java 1.1 nastavkite na domenite com, edu, org, net itn. po dogovor se napi{ani so golemi bukvi, pa bibliotekata bi se narekuvala:
70
Da se razmisluva vo Java
Brus Ekel
NET.mindview.utility.foibles. Vo tekot na patot na razvojot na Java 2, se otkri deka toa predizvikuva problemi, pa sega celoto ime na paketot se pi{uva so mali bukvi. Mehanizmot zna~i deka site Va{i datoteki avtomatski `iveat vo svoi imenski prostori i sekoja klasa vo ramkite na datotekata mora da ima edinstven identifikator - jazikot go spre~uva sudirot na imiwa namesto Vie.
za da mu ka`ete na preveduva~ot deka sakate da ja koristite klasata na Java ArrayList. Sepak, paketot util sodr`i pove}e klasi i mo`ete da posakate da koristite nekolku od niv bez da gi deklarirate eksplicitno. Toa lesno se postignuva so koristewe na znakot za sloboden izbor *:
import java.util.*;
Se e objekt
71
Za da napravite edno pole ili metod da bide stati~no, ednostavno go stavate rezerviraniot zbor static pred definicijata. Sledniot primer proizveduva stati~no pole i go inicijalizira:
class StaticTest { static int i = 47; }
72
Da se razmisluva vo Java
Brus Ekel
Sega duri i ako napravite dva objekta od klasa StaticTest, i ponatamu }e postoi samo eden primerok na skladi{te za promenlivata StaticTest.i. I dvata objekta }e ja delat istata promenliva i. Da go razgledame slednoto:
StaticTest stI = new StaticTest(); StaticTest st2 = new StaticTest();
Tuka, i dvete, st1.i i st2.i imaat ista vrednost koja iznesuva 47, bidej}i tie se odnesuvaat na istiot del od memorijata. Ima dva na~ina na pristap kon stati~na promenliva. Kako {to e poka`ano vo prethodniot primer, vie }e mo`ete da i pristapuvate preku objekt, so naveduvawe na primer, st2.i. Vie isto taka mo`ete da pristapuvate direktno preku imeto na klasata, ne{to {to ne mo`ete da go napravite so nestati~en ~len.
StaticTest.i++;
Operatorot ++ ja zgolemuva promenlivata za 1. Ottuka, i dvete, st.i i st2.i }e imaat vrednost 48. Koristeweto na imeto na klasata e pretpo~itan na~in za pristapuvawe kon stati~na promenliva. Ne samo {to taka ja naglasuva stati~kata priroda na taa promenliva, tuku vo nekoi slu~ai mu dava na preveduva~ot podobri mo`nosti za optimizacija. Sli~na logika se primenuva i na stati~ni metodi. Mo`ete da mu pristapite na stati~en metod ili preku objekt, kako i na sekoj metod, ili so pomo{ na posebna dodatna sintaksa ImeNaKlasa.metoda(). Vie definirate stati~en metod na sli~en na~in:
class MozeDaSeZgolemi { static void zgolemi() } {staticTest.i++; }
Obratete vnimanie deka metodot zgolemi() vo klasata MozeDaSeZgolemi, go zgolemuva stati~niot podatok i so koristewe na ++ operatorot. Mo`e da go povikate metodot zgolemi() na voobi~aen na~in, preku objektot:
MozeDaSeZgolemi sp = new MozeDaSeZgolemi (); sp.zgolemi();
Ili bidej}i zgolemi() e stati~en metod, mo`ete da go povikate direktno preku negovata klasa:
MozeDaSeZgolemi.zgolemi();
Iako rezerviraniot zbor static, koga }e se primeni na pole, definitivno go menuva na~inot na koj podatocite se formiraat (po eden za sekoja klasa vo odnos na po eden nestati~en za sekoj objekt), koga }e se primeni vrz metod, promenite ne se tolku dramati~ni. Va`na upotreba na static za metodite e Se e objekt 73
deka vi ovozmo`uva da go povikuvate metodot bez kreirawe na objekti. Ova e mnogu va`no, kako {to }e vidite, za definiraweto na metodot main(), koj e po~etna to~ka za startirawe na aplikacijata.
Na po~etokot od sekoja programska datoteka, }e morate da gi navedete site neophodni naredbi import za da gi uvezete site potrebni dodatni klasi {to }e vi trebaat za kodot vo taa datoteka. Obratete vnimanie deka velam dodatni, bidej}i ima to~no opredelena biblioteka na klasi koja {to avtomatski se uvezuva vo sekoja Java datoteka: java.lang. Startuvajte go va{iot Veb prelistuva~ i poglednete ja dokumentacijata od Sun. (Dokolku ne ste ja prezemale JDK dokumentacijata od http://java.sull.call, napravete go toa sega.6 Imajte vo predvid deka ovaa dokumentacija ne doa|a zaedno so JDK, morate oddelno da ja prezemete). Dokolku ja poglednete listata na paketi, }e vidite razli~ni biblioteki na klasi {to se ispora~uvaat so Java.
6 Java preveduva~ot i dokumentacijata na Sun postojano se menuvaat i najdobro e da se prezemaat direktno od Sun. Ako sami ja prezemete, }e ja dobiete najnovata verzija.
Izberete go paketot java.lang i }e dobiete lista na site klasi {to se del od taa biblioteka. Bidej}i java.lang e implicitno vklu~en vo sekoja datoteka so Java kodot, ovie klasi se avtomatski dostapni. Vo listata na java.lang ja nema klasata Date, {to zna~i deka morate da vovedete druga biblioteka za da ja koristite. Dokolku ne znaete vo koja biblioteka se nao|a opredelena klasa ili dokolku sakate da gi vidite site klasi, mo`e da izberete Tree vo dokumentacijata na Java. Sega mo`ete da ja najdete koja bilo klasa {to doa|a so Java. Toga{ mo`ete da ja koristete funkcijata na prelistuva~ot find za da ja pronajdete klasata Date. Koga }e go napravite toa }e vidite deka taa na listata se nao|a kako java.util.Date, {to zna~i deka e vo paketot Util i deka morate da vnesete importjava.util.* so cel da ja koristite klasata Date.
74
Da se razmisluva vo Java
Brus Ekel
Ako se vratite na po~etokot, izberete java.lang i potoa System, }e vidite deka klasata System ima nekolku poliwa, i dokolku selektirate out, }e doznaete deka toa e stati~en objekt od klasata PrintStream. Bidej}i e stati~en, ne morate da kreirate ni{to so pomo{ na new. Objektot out e sekoga{ tamu i mo`ete ednostavno da go koristite. Upotrebata na ovoj out objekt e opredelena od negoviot tip: PrintStream. Zaradi prakti~nost, PrintStream e prika`an vo opisot kako hipervrska, pa ako kliknete na nego, }e vidite lista na site metodi koi {to mo`ete da gi povikate za PrintStream. Niv gi ima relativno mnogu i za niv }e stane zbor podocna vo knigava. Zasega, ne interesira samo println(), {to zna~i Ispi{i go samo ona {to ti go davam do konzolata i prejdi vo nov red. Ottuka vo koja bilo Java programa ako sakate ne{to da napi{ete na konzolata, mo`ete da zapi{ete:
System.out.println(Znakovna niza za izlez);
Imeto na klasata e isto so imeto na datotekata. Koga sozdavate nezavisna programa, kakva {to e ovaa, edna od klasite vo datotekata mora da go ima istoto ime kako i datotekata. (Preveduva~ot se `ali ako ne napravite taka) Taa klasa mora da sodr`i metod nare~en main() so ovoj potpis i povraten tip:
public static void main(String[] args) {
Javniot rezerviran zbor zna~i deka metodot e dostapen za nadvore{niot svet (opi{an detaqno vo poglavieto Kontrola na pristap). Argumentot na metodot main( ) e niza od objekti od klasa String. Argumentite Args nema da se koristat vo ovaa programa, no Java preveduva~ot insistira tie da bidat tamu bidej}i vo niv se smestuvaat argumentite od komandniot red. Redot so ispi{an datum e prili~no interesen:
System.out.println(new Date());
Argumentot e objekt od tip Date. Toj se kreira samo za da ja prati svojata vrednost (koja avtomatski se konvertira vo objekt od tip String) do metodot println(). [tom ovoj izraz zavr{i, objektot Date ve}e ne e potreben i sobira~ot na |ubre mo`e da dojde vo koe bilo vreme i da go sobere. Nie ne mora da se gri`ime za negovoto ~istewe. Koga }e ja prou~ite JDK dokumentacijata od sajtot http://java.sun.com, }e vidite deka System ima mnogu drugi metodi {to vi ovozmo`uvaat da proizvedete interesni efekta (edna od najmo}nite prednosti na Java e golemiot broj na standardni biblioteki). Na primer:
//: object/ShowProperties.java public class ShowProperties { public static void main(String[] args) { System.getProperties().list(System.out); System.out.println(System.getProperty(user.name); System.out.println( System.getProperty(java.library.path));
Se e objekt
75
} }///:~
Prviot red vo metodot main() gi ozna~uva site osobini na sistemot na koj ja izvr{uvate programata, pa vi dava informacii za okolinata. Metodot list() gi pra}a rezultatite do svojot argument System.out. Vo prodol`enieto na ovaa kniga }e vidite deka niv mo`ete da gi pratite i na drugi mesta, do datoteka, na primer. Isto taka mo`ete da pobarate odredena osobina - vo ovoj slu~aj, korisni~ko ime andjava.library.pat. (Neobi~nite komentari na po~etokot i na krajot }e bidat objasneti malku podocna.)
Preveduvawe i izvr{uvawe
Za da ja prevedete i izvr{ite ovaa programa i site drugi programi vo ovaa kniga, prvo }e morate da imate Java okolina za programirawe. Postojat pove}e nezavisni razvojni okolini, no vo ovaa kniga }e pretpostavam deka koristite besplatna razvojna Java okolina JDK (Java Developers Kit) od Sun. Dokolku koristite drug razviva~ki sistem, }e morate da poglednete vo dokumentacijata za toj sistem za da opredelite kako se preveduvaat i startuvaat programite.
7 Obi~no e toa IBM preveduva~ot jikes na, bidej}i e zna~ajno pobrz od javac na Sun (iako dokolku pravite grupi od datoteki so koristewe na Ant, nema mnogu golema razlika). Isto taka postojat i programi so otvoren kod za kreirawe Java preveduva~i, izvr{ni okolini i biblioteki.
Povrzete se na Internet i pogledajte go sajtot http://java.sun.com. Tamu }e najdete informacii i linkovi {to }e ve vodat niz procesot na prezemawe na JDK za va{ata posebna platforma. [tom e instalirana JDK i e podesena informacijata za patot preku koj va{iot kompjuter }e gi najde javac i java, prezemete go i otpakuvajte go izvorniot kod za ovaa kniga (mo`ete da go najdete na adresata www.MindView.net). Odete vo podimenikot so ime Object i vpi{ete:
javac HelloDate.java
Po ovaa komanda ne treba da o~ekuvate odziv. Dokolku dobiete kakva bilo poraka za gre{ka, toa zna~i deka ne ste ja instalirale JDK kako {to treba i deka }e treba da gi ispitate tie problemi. Od druga strana, dokolku ja dobiete nazad samo Va{ata komanda, mo`ete da napi{ete:
java HelloDate
76
Da se razmisluva vo Java
Brus Ekel
Ova e proces {to mo`ete da go koristite za preveduvawe i startuvawe na koja bilo programa od ovaa kniga. Sepak, }e vidite deka izvorniot kod za ovaa kniga isto taka ima datoteka pod imeto build.xml vo sekoe poglavje, a taa sodr`i Ant komandi za avtomatsko gradewe na datotekite za ova poglavje. Datotekite za gradewe i Ant (vklu~uvajki ja informacijata od kade se prezemaat od Internet) se opi{ani vo celost vo dodatokot {to }e go najdete na http://MindView.net/Books/BetterJava, no po instalirawe na Ant (od http://jakarta.apache.org/ant), dovolno e da vnesete ant vo komandniot odzivnik (prompt) za da gi preveduvate i da gi startuvate programite vo sekoe poglavje. Dokolku go nemate instalirano Ant s u{te, mo`ete ednostavno samite ra~no da gi vnesite komandite javac i java.
Zapomnete deka sepak s {to e vnatre, me|u /* i */ se ignorira, pa nema razlika i da ka`ete:
/* Ova e komentar sto prodolzuva vo poveke redici */
Vtor na komentari doa|a od S++. Toa e komentar vo eden red, {to po~nuva so // i prodol`uva s do krajot na toj red. Ovoj vid na komentar e prakti~en i ~esto se koristi e ednostaven. Ne vi treba da prebaruvate po tastaturata za da najdete / pa potoa * (namesto toa, ednostavno go pritiskate istoto kop~e dva pati) i ne morate da go zatvorite komentarot. Zatoa po~esto }e sre}avame:
// Ova e komentar vo eden red
Dokumentacija na komentari
Verojatno najgolemiot problem pri dokumentirawe na kodot bilo odr`uvaweto na taa dokumentacija. Dokolku dokumentacijata i kodot se oddeleni, toga{ stanuva nezgodno da se menuva dokumentacijata sekoj pat koga }e sakate da go smenite kodot. Re{enieto izgleda ednostavno: Povrzete go kodot so dokumentacijata. Najlesniot na~in da go napravite ova e s da stavite vo ista datoteka. Za da ja zaokru`ite postapkata, sepak }e vi treba
Se e objekt
77
posebna sintaksa za dokumentaciski komentari, kako i alatka za da gi izdvoite tie komentari i da gi prefrlite niv vo korisen vid. Toa go napravi Java. Alatkata za izdvojuvawe na komentarite se vika Javadoc i e del od instalacijata na JDK. Toj koristi nekoi od tehnologiite na Java preveduva~ot za da bara posebni oznaki na komentarite vo Va{ata programa. Ne samo {to ja izdvojuva ozna~enata informacija, tuku isto taka go izvlekuva imeto na klasata ili imeto na metodot pridru`en na komentarot. Na ovoj na~in so minimalen napor }e generirate pristojna programska dokumentacija. Izlezot od Javadoc e HTML datoteka {to mo`ete da ja vidite so va{iot Veb prelistuva~. Ottuka, Javadoc dozvoluva da kreirate i odr`uvate edna izvorna datoteka i avtomatski da generirate korisna dokumentacija. Blagodarenie na programata Javadoc, imate ednostaven standard za kreirawe dokumentacija, pa mo`ete da o~ekuvate, pa duri i da barate dokumentacija od site biblioteki na Java. Pokraj s, mo`ete da napi{ete sopstveni Javadoc identifikatori, nare~eni doclets, dokolku sakate da izvedete specijalni operacii na informaciite procesirani od Javadoc (da proizvedete izlez vo razli~en format, na primer.) Dokletite se pretstaveni vo dodatokot na http://MindView.net/Book/BetterJava. Sledi voved i pregled vo osnovite na Javadoc. Detalen opis mo`e da najdete vo dokumentacijata za JDK. Koga }e ja otpakuvate, poglednete vo podimenikot tooldocs (ili sledete go linkot tooldocs).
Sintaksa
Site programi na komandata Javadoc }e se pojavat isklu~ivo vo ramkite na komentarite /**. Komentarite zavr{uvaat so */ kako i obi~no. Ima 2 osnovni na~ini za da se koristi Javadoc: vgraden HTML ili koristewe na dokumentaciski oznaki (doc tags). Samostojnite dokumentaciski oznaki se komandi {to po~nuvaat so @ i se nao|aat na po~etokot na redot za komentar (vode~kiot znak * se zanemaruva) Nesamostojnite dokumentaciski oznaki mo`e da bidat napi{ani kade bilo vo ramkite na eden Javadoc komentar i isto taka po~nuvaat so @ no se nao|aat me|u golemi zagradi. Postojat tri tipa na dokumentaciski komentari, koi {to odgovaraat na elementot na koj komentarot mu prethodi: klasa, pole ili metod. Toa zna~i deka komentarot za klasata se pojavuva vedna{ pred definicijata za klasa, komentar za poleto se pojavuva vedna{ pred definicijata za pole i komentarot za metodot se pojavuva vedna{ pred definicijata za metod. Sleduva ednostaven primer:
78
Da se razmisluva vo Java
Brus Ekel
//: object/Documentationl.java /** Komentar za klasata */ public class Documentationl.java { /** Komentar za poleto */ public int i; /** Komentar za metodot */ public void f() {} } ///: -
Obratete vnimanie deka Javadoc }e ja obraboti dokumentacijata za komentarot samo za javni i za{titeni ~lenovi. Komentarite za privatnite ~lenovi i za ~lenovite na koi im se pristapuva vo paket (poglednete go poglavjeto Kontrola na pristap) se ignoriraat i nema da vidite nikakov izlez. (Sepak, mo`ete da koristite indikator - private za da vklu~ite i privatni ~lenovi isto taka.) Ova ima smisla, bidej}i samo javni i za{titeni ~lenovi se dostapni nadvor od datotekata, {to e perspektiva na programerot na klientot. Izlezot od prethodniot kod e HTML datoteka {to ima ist standarden format kako i celokupnata ostanata Java dokumentacijata, pa korisnicite }e bidat zadovolni so formatot i }e mo`at lesno da se dvi`at niz Va{ite klasi. Povtorno vpi{ete go prethodniot kod, propu{tete go niz Javadoc, i pogledajte ja rezultira~kata HTML datoteka za da gi vidite rezultatite.
Vgraden HTML
Javadoc propu{ta HTML komandi do generiraniot HTML dokument. Toa ovozmo`uva potpolno koristewe na HTML, me|utoa, osnovniot motiv e da se ovozmo`i formatirawe na kodot, kako:
//: object/Documentation2.java /** * <pre> * Sys t em.out . pr in t ln(new Date()); * </pre> */ ///:-
Mo`ete isto taka da koristite HTML isto kako i vo sekoj drug Veb dokument, za da go formatirate obi~niot tekst vo Va{ite opisi:
//: object/Documentation3.java /** * Mozete da ufrlite <em> duri </ em> i lista: * <ol> * <li> Prva stavka * <li> Vtora stavka * <Ii> Treta stavka * </ol>
Se e objekt
79
Obratete vnimanie deka vo ramkite na komentarot za dokumentacijata, Javadoc ja otfrla yvezdi~kata na po~etokot na redot, zaedno so praznite mesta. Javadoc povtorno se formatira za da se prilagodi na standardniot izgled na dokumentacijata. Nemojte da koristite naslovi kako <h1> ili <hr> kako vgraden HTML, bidej}i Javadoc vmetnuva svoi naslovi i Va{ite }e im pre~at. Site tipovi na dokumentaciski komentari - klasa, pole i metod poddr`uvaat vgraden HTML.
Primeri na oznaki
Eve primeri na nekoi Javadoc oznaki dostapni za dokumentacijata na kodot. Pred da se obidete da napravite ne{to seriozno so koristewe na Javadoc, treba da go pro~itate Javadoc delot vo JDK dokumentacijata za da gi nau~ite site razli~ni na~ini na koristewe na Javadoc. @see: Ovaa oznaka vi ovozmo`uva da se obratite do dokumentacijata vo drugite klasi. Javadoc }e generira HTML so oznakite @seetags kako hipervrski povrzani so druga dokumentacija. Formite se:
@see @see @see @see imeNaKlasa celosno-opisano-imeNaKlasa celosno-opisano-imeNaKlasa celosno-opisano-imeNaKlasa#ime-metoda
Sekoj od niv dodava do generiranata dokumentacija hipervrska Pogledni isto taka (angliski See also). Javadoc ne ja proveruva ispravnosta na hipervrskite {to vie i gi predavate.
{@docRoot}
Proizveduva relativen pat do korenskiot imenik na dokumentacijata. Se koristi za eksplicitno hiperpovrzuvawe so stranici vo drvoto na dokumentacijata.
{@inheritDoc}
Tekovniot dokumentaciski komentar ja nasleduva dokumentacijata na najbliskata osnovna klasa na ovaa klasa.
80
Da se razmisluva vo Java
Brus Ekel
@version
Nejziniot oblik e:
@version informacija-za-verzijata
kade informacija-za-verzijata e koja bilo va`na informacija koja {to treba da se vklu~i. Koga indikatorot -version se navede vo komandniot red na programata Javadoc, informacijata za verzijata }e bide prosledena vo generiranata HTML dokumentacija.
@author
Nejziniot oblik e:
@author informacija-za-avtorot
kade informacija-za-verzijata e, verojatno Va{eto ime, no mo`e da bide isto taka i Va{a elektronska adresa ili koja bilo druga soodvetna informacija. Koga indikatorot author e smesten vo Javadoc komandniot red, informacijata za avtorot }e bide prosledena vo generiranata HTML dokumentacija. Mo`e da imate pove}e avtorski oznaki za lista od avtori, no tie moraat da bidat podredeni posledovatelno. Site informacii za avtorite }e bidat spoeni vo eden pasus vo generiraniot HTML.
@since
Ovaa oznaka vi ovozmo`uva da ja nazna~ite verzijata na ovoj kod {to po~nal da koristi odredena mo`nost. ]e vidite kako se pojavuva vo HTML Java dokumentacijata za da nazna~i koja verzijata na JDK se upotrebuva.
@param
Ova e koristeno za dokumentacija na metodi vo oblik:
@param ime-parametar opis
kade ime-parametar e identifikator vo listata na parametri na metodot, a opis e tekst koj mo`e da prodol`i na slednite redovi. Se smeta deka opisot e zavr{en koga }e se naide na nova dokumentaciska oznaka. Mo`ete da imate bilo kolku od ovie oznaki, naj~esto po edna za sekoj parametar.
@return
Se koristi za dokumentacija na metodi i izgleda vaka:
@return opis
kade opis vi go dava zna~eweto na povratnata vrednost. Mo`e da prodol`i na slednite redovi.
Se e objekt
81
@throws Isklu~ocite }e bidat razgledani vo poglavjeto Obrabotka na gre{ki so pomo{ na isklu~oci. Nakratko, tie se objekti {to mo`e da se isfrlat nadvor od metodot vo slu~aj na gre{ka. Iako samo eden objekt na isklu~ok mo`e da se pojavi koga }e povikate metod, opredelen metod mo`e da proizvede pove}e razli~ni tipovi izrazi, a site moraat da bidat odnapred nazna~eni. Taka oznakata za isklu~ok go ima sledniot oblik:
@throws celosno-opisano-imeNaKlasa opis
kade celosno-opisano-imeNaKlasa nedvosmisleno dava ime za klasa na isklu~ok i koja e nekade definirana, a opis (koj mo`e da prodol`i na slednite redovi) Vi poka`uva zo{to opredeleniot tip na isklu~ok mo`e da se javi pri povik na metodot. @deprecated Ova se koristi za nazna~uvawe mo`nosti koi {to se zastareni. Oznakata deprecated e sugestija deka ne treba da ja koristite ponatamu taa mo`nost, bidej}i naskoro najverojatno }e bide otstraneta. Metodot koj e ozna~en so @deprecated predizvikuva preveduva~ot da prika`e predupreduvawe dokolku e koristen. Vo Java YE5, Javadoc oznakata @deprecated, e zameneta so anotacijata @Deprecatedannotation (}e nau~ite za ova vo poglavjeto Anotacija).
Primer za dokumentacija
Eve ja povtorno prvata programa vo Java, ovoj pat so dodatnite dokumentaciski komentari:
//: object/Zdravo. java import java.util.*; / ** Prv primer na programot od knigata Da se razmisluva na Java. * Ispisuva znakovna niza i denesen datum. * @author Bruce Eckel * @author www.HindView.net * @version 4.0 */ public class Zdravo { /** Vlezna tocka vo klasata i aplikacijata. * @param args niza od argumenti od tip string * @throws exceptions ne frla isklucoci */ publiC static void main(Stringll args) { System.out.println(Zdravo, denes e: ); System.out.printlnCnew Date()) } } / * Output: (55% match) Hello. it's:
82
Da se razmisluva vo Java
Brus Ekel
Prviot red od datotekata koristi moja tehnika: se stava '//:' kako specijalna oznaka za red so komentar {to sodr`i ime na izvorna datoteka. Toj red sodr`i informacija za patot do datotekata (object go ozna~uva ova poglavje) prosledeno so imeto na datotekata. Posledniot red isto taka zavr{uva so komentar i znakot (///:-), koj go ozna~uva krajot na listingot na izvorniot kod i ovozmo`uva toj kod avtomatski da se a`urira vo tekstot na ovaa kniga, otkako }e bide proveren od preveduva~ot, i da se izvr{i. Oznakata /* Output: nazna~uva po~etok na izlezot {to }e bide generiran od ovaa datoteka. Vo ovaa forma mo`e avtomatski da se testira za da se potvrdi negovata preciznost. Vo ovoj slu~aj, (55% poklopuvawe) mu nazna~uva na sistemot za testirawe deka izlezot }e bide prili~no razli~en od edno do drugo izvr{uvawe pa bi se o~ekuvala korelacija od samo 55% so ovde prika`aniot izlez. Mnogu primeri vo ovaa kniga {to davaat izlezi }e go sodr`at ovoj oblik na izlezot, pa }e mo`ete da go vidite izlezot i }e znaete deka e ispraven.
Stil na programirawe
Spored stilot opi{an vo Code Conventions for the Java Programming Language8 , prvata bukva od imeto na klasata treba da bide golemo. Ako imeto na klasata se sostoi od nekolku zborovi, tie se pi{uvaat zaedno (toa zna~i deka ne koristite dolni crti za da gi odvoite imiwata), i prvata bukva od sekoj vgraden zbor e golema, kako:
class SiteBoiNaVinozitoto { // . .
Vaka napi{ano imeto na klasata li~i na grba od kamila, pa ottamu ova ponekoga{ se narekuva camel-casing.
8 http://java.sun.com/docs/coneconv/index.html. Ne mo`ev da gi sledam site nasoki od ovaa preporaka za da se za~uva prostor vo knigava i seminarskite prezentacii, no }e se uverite deka stilot {to go koristam ovde odgovara na stilot na Java kolku {to e mo`no pove}e.
Za re~isi se drugo - metodi, poliwa (promenlivi ~lenovi) i imiwa na referenci na objekti, usvoeniot stil e ednostaven kako i za klasite osven {to prvata bukva od identifikatorot se pi{uva so mala bukva. Na primer:
class SiteBoiNaVinozitoto { int celBrojKojGiPretstavuvaBoite; void promeniJaNijansataNaBoite (int novaNijansa)
Se e objekt
83
// ... } // ... }
Korisnikot }e mora isto taka da gi vnese preku tastatura site ovie dolgi imiwa, zatoa imajte milost. Java kodot {to }e go vidite vo bibliotekite na Sun go sledi istiot stil na pi{uvawe na otvoreni i zatvoreni golemi zagradi kako i stilot upotreben vo ovaa kniga.
Rezime
Celta na ova poglavje e da nau~ite tolku Java kolku {to e dovolno da napi{ete ednostavna programa. Steknavte uvid vo jazikot i negovite osnovni idei. Sepak, primerite dosega bea od vid Napravi go ova, pa potoa pravi ne{to drugo. Vo slednite dve poglavja }e gi zapoznaete osnovnite operatori {to se koristat vo programiraweto vo Java i }e nau~ite kako da go upravuvate so tekot na Va{ata programa.
Ve`bi
Normalno, ve`bite }e bidat rasprostraneti nasekade niz poglavjata, no bidej}i vo ova poglavje u~evte kako da pi{uvate osnovni programi, ve`bite gi ostavivme na krajot.
Brojot vo zagradi posle sekoj reden broj na ve`bata e indikator za slo`enosta na ve`bata, vo skala od 1 do 10. Re{enijata za slednite ve`bi mo`e da se najdat vo elektronskiot dokument The thinking in Java Annotated Solution Guide, koj {to mo`e da se kupi na www.MindView.net. Ve`ba 1: (2) Kreirajte klasa koja {to }e sodr`i neinicijalizirani poliwa od tip int i char, a potoa ispi{ete gi nivnite vrednosti za da se uverite deka Java ja izvr{uva podrazbiranata inicijalizacija. Ve`ba 2: (1) Sledej}i go primerot so Zdravo.java vo ova poglavje, napi{ete programa Zdravo na site {to ednostavno }e ja prika`uva taa naredba na ekranot. Vi treba samo eden metod vo Va{ata klasa (main, koj {to se izvr{uva koga se startuva programata). Zapomnete da go napravite stati~en i da vklu~ite i lista so argumenti, iako nema da ja koristite. Prevedete ja programata so komandata javac i startuvajte ja koristej}i ja komandata java.
84
Da se razmisluva vo Java
Brus Ekel
Dokolku koristite razli~na razvojna okolina od JDK, nau~ete kako da preveduvate i startuvate programi vo taa okolina. Ve`ba 3: (1) Najdete gi delovite od kodot {to ja opfa}aat klasata NekoeImeNaTipot i transformirajte gi vo programa koja mo`e da se prevede i izvr{i. Ve`ba 4: (1) Pretvorete gi delovite od kodot koi ja opfa}aat klasata SamoPodatoci vo programa {to mo`e da se prevede i izvr{i. Ve`ba 5: (1) Modificirajte ja prethodnata ve`ba taka {to vrednostite na podatocite vo klasata SamoPodatoci bidat dodeleni i ispi{ani od metodot main(). Ve`ba 6: (2) Napi{ete programa {to vklu~uva i povikuva metod skladiste() definiran kako del od kod vo ova poglavje. Ve`ba 7: (1) Pretvorete gi delovite od kodot MozeDaSeZgolemi vo rabotosposobna programa. Ve`ba 8: (3) Napi{ete programa koja demonstrira deka postoi samo eden primerok od odredeno stati~no pole vo klasata, bez ogled na toa kolku objekti od taa klasa }e kreirate. Ve`ba 9: (2) Napi{ete programa koja {to poka`uva deka avtomatskoto pakuvawe funkcionira za site prosti tipovi i nivnite obvivki.
Ve`ba 10: (2) Napi{ete programa {to ispi{uva tri argumenti prezemeni od komandniot red. Za da go napravite ova, vo redot za komandi }e treba da se pozanimavate so indeksite vo nizata objekti od klasata String. Ve`ba 11: (1) Od primerot SiteBoiNaVinozitoto napravete programa koja {to mo`e da se prevede i izvr{i. Ve`ba 12: (2) Najdete go kodot za vtorata verzija na programata Zdravo.java, {to e ednostaven primer za dokumentaciski komentari. Propu{tete ja datotekata niz Javadoc na datotekata i videte gi rezultatite so pomo{ na Va{iot Veb prelistuva~. Ve`ba 13: (1) Propu{tete gi datotekite Documentation1.java, Documentation2.java i Documentation3.java niz Javadoc i proverete ja rezultantnata dokumentacijata so pomo{ na va{iot Veb prelistuva~. Ve`ba 14: (1) Dodadete HTML lista so stavki na dokumentacijata vo prethodnata ve`ba. Ve`ba 15: (1) Zemete ja programata od Ve`ba 2 i dodajte i dokumentaciski komentari. Izdvojte gi dokumentaciskite komentari vo HTML datoteka koristej}i Javadoc i pregledajte gi so Va{iot Veb prelistuva~.
Se e objekt
85
Ve`ba 16: (1) Vo poglavjeto Inicijalizacija i ~istewe, pronajdete go primerot Preklopuvanje.java i dodadete mu Javadoc dokumentaciski komentari. Izdvojte gi tie dokumentaciski komentari vo HTML datoteka so koristewe na Javadoc i pregledajte gi so pomo{ na Va{iot Veb prelistuva~.
86
Da se razmisluva vo Java
Brus Ekel
Operatori
Na najnisko nivo, so podatocite vo Java se raboti so pomo{ na operatori.
Bidej}i Java e naslednik na S++, pove}eto od ovie operatori }e im bidat poznati na S i S++ programerite. Java isto taka dodade nekolku podobruvawa i poednostavuvawa. Dokolku ste zapoznaeni so sintaksata na S ili S++, mo`ete da proletate niz ova i niz slednoto poglavje, i da se zadr`ite na mestata kade Java e razli~na od ovie jazici. Sepak, dokolku dokolku malku zapnete vo ovie dve poglavja, pominete niz multimedijalniot seminar Thinking in C, koj mo`e slobodno da go prevzemete od www.MindView.net. Toj sodr`i audio lekcii, slajdovi, ve`bi i re{enija posebno dizajnirani za da vi ja dadat potrebnata brzina pri sovladuvawe na osnovite za u~ewe na Java.
Mo`ete da zabele`ite deka ovde ima ne samo prili~no mnogu ispi{uvawe (i ottuka izli{ni napori za tetivite), tuku isto taka e i prili~no nerazbirlivo koga }e se pro~ita. Mnogu jazici postari i ponovi od Java imaat mnogu poednostaven pristap do taka ~esto upotrebuvanata naredba. Vo poglavjeto Kontrola na pristapot, se zboruva za poimot static import, {to be{e dodaden na Java SE5, a pokraj toa navedena e i mala biblioteka so cel da go poednostavni pi{uvaweto na naredbite za ispi{uvawe na ekran. Sepak, ne morate da gi znaete ovie detali za da zapo~nete da ja koristite taa biblioteka. Mo`eme da ja prepi{eme programata od prethodnoto poglavje koristej}i ja ovaa nova biblioteka:
//: operators/ZdravoDatum.java import java.util.*; import static net.mindview.util.Print.*; public class ZdravoDatum {
Operatori
87
public static void main(String[] args) { print(Zdravo, denes e: ); print(new Date()); } } / * Izlez: (55% match) Zdravo, denes e: Wed Oct 05 14:39:05 MDT 2085 *///:-
Ovie rezultati se mnogu pojasni. Obratete vnimanie na vmetnuvaweto na stati~en rezerviran zbor vo vtorata naredba import. So cel da ja koristite ovaa biblioteka, morate da go prezemete paketot na kodot od ovaa kniga od www.MindView.net ili od nekoj od negovite preslikani serveri. Ra{irete go drvoto na kodot i dodadete korenski imenik na sistemskata promenliva CLASSPATH na va{iot kompjuter. Kone~no, }e dobiete celosno opi{uvawe na patot na klasata (angliski classpath), no nema da vi na{teti ako vedna{ po~nete da se naviknuvate na borbata so nea. Za `al, toa e edna od po~estite bitki koi {to }e gi vodite so Java. Iako koristeweto na net.mindview.util.Print ubavo gi poednostavnuva pogolemiot del od programite, ne mo`e da se opravda nejzinoto koristewe nasekade. Ako vo programata ima samo mal del naredbi za pe~atewe, go preskoknuvam uvozot (angl. import) na taa biblioteka i pi{uvame podolgo System.out.println(). Ve`ba 1: (1) Napi{ete programa {to gi koristi i skratenata i normalnata forma na naredbata za pe~atewe.
88
Da se razmisluva vo Java
Brus Ekel
Prioriteti
Prioritetite na operatorite opredeluvaat kako eden izraz }e se presmeta koga vo nego se prisutni nekolku operatori. Java ima specifi~ni pravila {to go opredeluvaat redosledot na presmetuvawe. Najlesno za pametewe e deka deleweto i mno`eweto se vr{at pred sobiraweto i odzemaweto. Programerite ~esto zaboravaat na ostanatite zakoni za prioritetite, pa zatoa treba da koristite zagradi za da go napravite ekspliciten redosledot na presmetki. Na primer, poglednete gi naredbite (1) i (2):
//: operatori/Prioriteti.java public class Prioriteti { public static void main(String[] args) { int x = 1, Y = 2, z = 3; int a = x + y - 2/2 + z; // (1) int b = x + (y - 2)/(2 + z); // (2) System.out.println(a = + a + b = + b); } } /* Izlez; a = 5 b = 1 * ///:-
Ovie naredbi izgledaat skoro ednakvo, no od izlezot gledate deka zaradi upotrebata na zagradi imaat sosema razli~ni zna~ewa. Obratete vnimanie deka naredbata System.out.println() go vklu~uva operatorot +. Vo ovoj kontekst, + zna~i nadovrzuvawe na stringovi i dokolku e neophodno konverzija na stringovi. Koga preveduva~ot }e naide na String prosleden so + prosleden so ne-String, }e se obide da go konvertira ona ne-String vo String. Kako {to mo`ete da vidite od izlezot, a i b uspe{no se konvertirani od tipot int vo String.
Dodeluvawe na vrednosti
Dodeluvaweto na vrednosti se vr{i so operatorot =. Toj zna~i Zemete ja vrednosta od desnata strana (~esto nare~ena dvrednost) i kopirajte ja na levata strana (~esto nare~ena lvrednost). Dvrednost e bilo koja konstanta, promenliva ili izraz {to dava vrednost, no lvrednost mora da bide posebna imenuvana promenliva. (Toa zna~i, deka mora da postoi fizi~ki prostor za da se skladira vrednosta.) Na primer, mo`ete da dodelite konstantna vrednost na promenliva.
a =4;
Operatori
89
no na konstantata vrednost ne mo`ete da i dodelite ni{to - taa ne mo`e da bide lvrednost. (Ne mo`ete da re~ete 4 = a; .) Dodeluvaweto na vrednosti od prost tip e prili~no o~igledna. Bidej}i prostite tipovi ~uvaat vistinska vrednost, a ne referenca na nekoj objekt, koga dodeluvate vrednost na promenliva od prost tip, vie gi kopirate sodr`inite od edno mesto na drugo. Na primer, ako napi{ete a = b za prosti tipovi, toga{ sodr`inata na promenlivata b se kopira vo sodr`inata na promenlivata a. Ako potoa re{ite da ja modificirate promenlivata a, taa modifikacija normalno nema da vlijae na promenlivata b. Kako programer, ova mo`e da go o~ekuvate vo pogolemiot broj situacii. Sepak, koga dodeluvate vrednosti na objekti, rabotite se menuvaat. Dodeka rabotite so objekt, Vie rabotite so referenca, pa koga }e dodelite eden objekt na drug, vie vsu{nost ja kopirate referencata od edno mesto na drugo. Ova zna~i deka ako napi{ete c = d za objekti, i c i d }e poka`uvaat kon objektot kon koj vsu{nost, prvi~no poka`uval samo d. Eve primer {to go demonstrira ova odnesuvawe:
//: operatori/Dodeluvanje.java // Dodeluvawnjeto na vrednosti na objektite ponekogas moze da izlaze. import static net.mindview.util.Print.*; class Rezervoar { int nivo; } public class Dodeluvanje { public static void main(String[] args) { Rezervoar t1 = new Rezervoar (); Rezervoar t2 = new Rezervoar (); tl.nivo = 9; t2.nivo = 47; print(1: r1.nivo: + r1.nivo +, r2.nivo: + r2.nivo); r1 = r2; print(2: : r1.nivo: + r1.nivo +, r2.nivo: + r2.nivo); r1.nivo = 27; print(3: r1.nivo: + r1.nivo +, r2.nivo: + r2.nivo); } } /* Izlez: 1: r1.nivo: 9. r2.nivo: 47 2: r1.nivo: 47, r2.nivo: 47 3: r1.nivo: 27, r2.nivo: 27 * ///: -
Klasata Rezervoar e ednostavna i nejzinite dva primeroka (instanci) (r1 i r2) se kreirani vo ramkite na metodot main(). Na poleto nivo vo sekoj od primerocite na klasata Rezervoar im se dodeleni razli~ni vrednosti, a potoa vrednosta r2 e dodelena na primerokot r1, a potoa r1 se menuva. Vo mnogu programski jazici bi o~ekuvale r1 i r2 da bidat nezavisni celoto
90
Da se razmisluva vo Java
Brus Ekel
vreme, no bidej}i ste dodelile referenca, menuvaweto na objektot r1 predizvikuva promena na objektot r2! Ova se slu~uva bidej}i r1 i r2 ja sodr`at istata referenca, koja poka`uva kon istiot objekt. (Prvobitnata referenca {to be{e vo r1, koja poka`uva{e kon objektot koj ja ~uva vrednosta 9, be{e izmeneta pri dodeluvaweto i efekta vno izgubena. Nejziniot objekt }e bide is~isten od strana na sobira~ot na |ubre (angliski garbage collector). Ovoj fenomen ~esto se narekuva pojava na psevdonim (angl. aliasing) i e osnoven na~in na koj Java raboti so objekti. No {to ako ne sakate vo ovoj slu~aj da se pojavi psevdonim? Bi mo`ele da go precizirate dodeluvaweto i da napi{ete:
r1.nivo = r2.nivo;
Ova gi zadr`uva dvata oddelni objekti, namesto eden od niv da bide otfrlen i dvete referenci r1 i r2 da se povrzat so istiot objekt. Naskoro }e razberete deka rabotata so poliwa vo ramkite na objektite e mnogu zbrkano i odi protiv dobrite principi na objektno-orientiraniot dizajn. Ova ne e osnovna tema, pa bi trebalo da imate na um deka pri dodeluvaweto na objekti mo`e da se javat iznenaduvawa. Ve`ba 2: (1) Kreirajte klasa {to sodr`i broj od tipot float i so pomo{ na nea demonstrirajte pojava na psevdonimi.
Operatori
91
Vo mnogu programski jazici, metodot f() bi napravil kopija od svojot argument Bukva y vnatre vo oblasta na va`ewe na metodot. No, bidej}i e prosledena referencata, toga{ redot
y.c = z:
e vsu{nost menuvawe na objekt nadvor od f(). Pra{aweto na psevdonimot i negovoto re{enie e kompleksen problem {to e razgledan vo eden od mre`nite dodatoci na ovaa kniga. Sepak, }e treba da bidete svesni za ovoj problem i da vnimavate da ne zapadnete vo zamka. Ve`ba 3: (1) Sozdadete klasa {to sodr`i podatok od tip float i so nejzina pomo{ demonstrirajte pojava na psevdonimi za vreme na povikuvawe na metod.
Matemati~ki operatori
Osnovnite matemati~ki operatori se isti kako i vo pove}eto programski jazici: sobirawe (+), odzemawe (-), delewe (/), mno`ewe (*) i modulo (%, koj se dobiva kako ostatok pri celobrojno delewe). Pri celobrojno delewe, ne se zaokru`uva rezultatot tuku se otsekuva realniot del. Java isto taka ja koristi kratenkata od S/S++ za istovremeno izveduvaawe na operacija i dodeluvawe. Toa se nazna~uva so operator prosleden so znakot za ednakvost i dosledno mo`e da se primeni na site operatori vo jazikot (koga toa ima smisla). Na primer, za da go dodadete 4 na promenlivata h i rezultatot da go dodadete na h, pi{uvate: h + = 4. Primerot ja prika`uva upotrebata na matemati~ki operatori:
//: operatori/MatematickiOperatori.java // Prikazuvanje na matematicki operatori import java.util .*; import static net.mindview.util.Print.*; public class MatematickiOperatori { public static void main(String[] args) { // Da napravime inicijaliziran generator na slucajni broevi Random slucaen = new Random(47); int i, j, k; // Da izbereme broj pomegu 1 i 180: j = slucaen.nextInt(100) + 1; print(j : + j); k = slucaen.nextInt(100) + 1;
92
Da se razmisluva vo Java
Brus Ekel
print(k : + k); i = j + k; print(j + k : + i); i = j k; print(j - k : + i); i = k / j; print(k / j : + i); i = k * j; print(k * j : + i); i = k % j; print(k % j : + i); j %= k; print(j %= k : + j); // Test za broevi so podvizna zapirka: float u, v, w: // Primenlivo i na double v = slucaen. nextFloat(); print(v : + v); w = slucaen.nextFloat(); print(w : + w); u = v + w; pr int(v + w : + u); u = v - w; print(v - w : + u); u = v * w; print(v * w : + u); u = v / w; print(v / w : + u); // Slednovo raboti i za char, // byte, short, int, long i double: u += v; print(u += v : + u); u -= v; print(u -= v : + u); u * = v; print(u *= v : + u); u /= v; print(u /= v : +u); } j k j j k k k j v w v v } /* Izlez: : 59 : 56 + k : 115 - k : 3 / j : 0 * j : 3304 % j : 56 %= k : 3 : 0.5309454 : 0.0534122 + w : 0.5843576 - w : 0.47753322
Operatori
93
Za generirawe broevi, programata najprvin kreira objekt od klasa Random. Dokolku kreirate Random objekt bez prosleduvawe argumenti, Java go koristi momentalnoto vreme kako vrednost za inicijalizacija na generatorot na psevdoslu~ajni broevi, pa ottuka }e proizvede razli~en izlez pri sekoe izvr{uvawe na programata. Sepak, vo primerite od ovaa kniga, va`no e izlezot {to e prika`an na krajot od primerite da bide pouedna~en kolku {to e mo`no pove}e, taka {to izlezot da mo`e da se proveri so pomo{ na nadvore{ni alatki. So obezbeduvaweto na seme (po~etna vrednost za inicijalizacija na generator na psevdoslu~ajni broevi {to sekoga{ }e proizveduva ista niza za opredelena vrednost na semeto) koga kreirate Random objekt, istite psevdoslu~ajni broevi }e se generiraat sekoj pat koga }e se izvr{i programata, taka {to izlezot na programata }e mo`e da se proveri.1 Za da generirate poinakov izlez sekoga{ koga ja pokrenuvate programata, slobodno otstranete go semeto od primerite vo ovaa kniga. 1 Brojot 47 se smeta{e za magi~en broj na kolexot kade u~ev, pa toa mi e vre`ano vo se}avawe. Programata generira razni tipovi na slu~ajni broevi so pomo{ na objektot Random ednostavno povikuvaj}i gi metodite nextInt() i nextFloat() (isto taka mo`ete da go povikate i nextLong() ili nextDouble(). Argumentot na metodot nextInt() ja postavuva gornata granica za generiraniot broj. Dolnata granica e nula, a toa ne go sakame bidej}i postoi mo`nost za delewe so nula, pa zatoa na rezultatot mu dodavame 1. Ve`ba 4: (2) Napi{ete programa {to ja presmetuva brzinata koristej}i konstantno rastojanie i konstantno vreme.
94
Da se razmisluva vo Java
Brus Ekel
Unarniot minus go promenuva znakot na podatokot. Unarniot plus ovozmo`uva simetrija so unarniot minus, no negoviot edinstven efekt e da gi pretvori byte, short, char vo int.
Operatori
95
Mo`ete da vidite deka vrednosta za prefiksnata forma se vra}a otkako }e se izvr{i operacijata, no so sufiksnata forma, ja dobivate vrednosta na promenlivata pred da se izvr{i operacijata. Ovie se edinstvenite operatori, osven onie koi {to vgraduvaat i dodeluvaat, koi {to imaat sporedni efekta - tie go menuvaat operandot namesto da ja upotrebat negovata vrednost.
Operatorot za zgolemuvawe e edno od objasnuvawata za potekloto na imeto S++, {to zna~i eden ~ekor pred S. Vo eden porane{en govor za Java, Bili DZoi (Eden od kreatorite na Java), rekol deka Java = S++-- (S plus plus minus minus), navestuvaj}i deka Java e jazikot S++ od koj se otfrleni nepotrebni te{ki delovi i zatoa e mnogu poednostaven jazik. Kako {to }e napreduvate vo ovaa kniga, }e vidite deka mnogu delovi se poednostavni i deka sepak Java ne e mnogu poednostavna od S++.
Relacioni operatori
Relacionite operatori (operatorite za sporedba) generiraat logi~ka vrednost (boolean). Tie ja ocenuvaat relacijata pome|u vrednostite na operandite. Relacioniot izraz dava vrednost true dokolku relacijata e vistinita i false dokolku relacijata e nevistinita. Relacioni operatori se: pomalo od (<), pogolemo od (>), pomalo ili ednakvo (<=), pogolemo ili ednakvo (>=), ednakvo (==) i razli~no (!=). Ednakvosta i razli~nosta mo`at da se primenat na site prosti tipovi na podatoci, no drugite sporedbi ne mo`at da se primenat na tipot boolean. Objektite od tip boolean mo`at da imaat samo vrednosti true ili false, pa ne bi imalo smisla da se bara koj od niv e pogolem, a koj pomal.
96
Da se razmisluva vo Java
Brus Ekel
public class Ednakvost { public static void main(String[] args) { Integer n1 = new Integer(47); Integer n2 = new Integer(47); System.out.println(n1 == n2); System.out.println(n1 != n2); } } /* Output; false true '///: -
Naredbata System.out.println(nl == n2) }e go ispi{e rezultatot od logi~kata sporedba koja se nao|a vnatre vo nea. Sekako deka izlezot sigurno bi trebalo da bide true, a izlezot na slednata naredba }e bide false, bidej}i vrednostite na dvata objekti od klasata Integer se isti. No iako sodr`inite na objektite se isti, referencite se razli~ni, a operatorite == i ! = gi sporeduvaat referencite na objektite, a ne nivnata sodr`ina. Zatoa izlezot na prvata sporedba e vsu{nost false, a na vtorata true. Normalno, ova na prv pogled iznenaduva. [to ako sakate da ja sporedite ekvivalencijata na vistinskite sodr`ini na objektot? Vo toj slu~aj morate da go koristite specijalniot metod equals() {to postoi za site objekti (ovoj metod ne se koristi za prosti tipovi na podatoci, za koi i taka odli~no funkcioniraat so == i ! =). Eve primer kako toj se koristi:
//: operatori/MetodotEquals.java public class MetodEquals { public static void main(String[] args) { Integer n1 = new Integer(47); Integer n2 = new Integer(47); System.Qut.println(nl.equals(n2)); } } /* Izlez: true *///:-
Rezultatot sega }e bide kako {to i o~ekuvavte. No, toa sepak ne e ba{ taka ednostavno. Dokolku sozdadete va{a klasa, kako na primer:
//: operatori/MetodEquals2.java // Ne se podrazbira deka equals() gi sporeduva sodrzinite. class Vrednost { int i; } public class MetodEquals2 { public static void main(String[] args) {
Operatori
97
Vrednost v1 = new Value(); Vrednost v2 = new Value(); vl.i = v2.i = 100; System.out.println(vl.equals(v2)) } } /* Izlez: false * ///:-
povtorno }e bidete zbuneti: rezultatot e false. Ova e zatoa {to podrazbiranoto odnesuvawe na equals() e da gi sporedi referencite. Zatoa nema da go dobiete posakuvanoto odnesuvawe osven ako ne go redefinirate (angliski override) metodot equals() vo va{ata nova klasa. Za `al, za redefiniraweto nema da u~ite se do poglavjeto Povtorna upotreba na klasite, a za pravilniot na~in za definirawe equals() s do poglavjeto Detaqno razgleduvawe na kontejnerot, no ako ste svesni za na~inot na odnesuvawe na equals() mo`e da se spasite od mnogu neprijatnosti vo me|uvreme. Pove}eto od klasite od bibliotekata na Java go realiziraat metodot equals() taka {to taa }e gi sporedi sodr`inite na objektite namesto nivnite referenci. Ve`ba 5: (2) Kreirajte klasa Kuche {to sodr`i dve promenlivi od tip String: ime i veli. Vo main(), sozdadete dva objekti od tip Kuche so imiwa Sharko (koj veli: Raf!) i Bleki (koj veli, Vaf!). Potoa prika`ete gi nivnite imiwa i toa {to go velat. Ve`ba 6: (3) Sledej}i ja ve`ba 5, sozdadete nova referenca Kuche i dodelete ja na objektot Sharko. Potoa napravete sporedba koristej}i == i equals() za site referenci.
Logi~ki operatori
Sekoj od ovie logi~ki operatori: konjunkcija (&&), disjunkcija (||) i negacija (!) davaat vrednost true ili false od tipot boolean vo zavisnost od logi~kata vrska na sopstvenite argumenti. Vo ovoj primer se koristat relaciskite i logi~kite operatori:
//: operatori/Logicki.java // Relaciski operatori (sporedbeni) i logicki operatori. import java.util.*; import static net.mindview.util.Print.*; public class Logicki { public static void main(String[] args) { Random slucaen = new Random(47); int i = slucaen.nextInt(100); int j = slucaen.nextInt(100);
98
Da se razmisluva vo Java
Brus Ekel
= + i); = + j); , j e + (i > j)); < j e + (i < j)); >= j e + (i >= j)); <= j e + (i <= j)); == j e + (i == j)); ! = j e + (i != j));
// Tipot int vo Java ne moze da se koristi kako logicki tip //! print(i && j e + (i && j)); //! print(i || j e + (i || j)); //! print(!i e + !i); print((i < 10) && (j < 10) e + ((i < 10 ) && (j < 10)) ); print((i < 10) || (j < 10) e + ((i < 10) || (j < 10)) ); } i j i i i i i i ( ( * } /* Izlez: = 58 = 55 > j e true < j e false >= j e true <= j e false == j e false != j e true i < 10) && ( j < 10) e false i < 10) || (j < 10) e false ///:-
Operatorite AND, OR i NOT (konjunkcija, disjunkcija i negacija) mo`ete da gi primenite samo na vrednosti tip boolean. Za logi~kite uslovi, ne mo`ete da gi koristite ostanatite nelogi~ki tipovi kako {to mo`ete vo S i S++. Vakvite neuspe{ni obidi mo`ete da gi vidite vo komentarite so oznaka //!' (Ovaa sintaksa za komentari ovozmo`uva avtomatsko otstranuvawe na komentari {to go olesnuva testiraweto). Slednite izrazi, sepak, davaat vrednosti od tip boolean taka {to koristat relaciski sporedbi, a potoa na tie rezultati gi primenuvaat logi~kite operacii. Obratete vnimanie deka vrednosta od tip boolean avtomatski se konvertira vo soodvetna tekstualna forma ako se koristi tamu kade {to se o~ekuva objekt od klasata String. Mo`ete da ja zamenite definicijata za int vo slednata programa so koj bilo drug prost tip na podatoci osven boolean. Bidete svesni deka sporedbata na broevite vo format na podvi`na zapirka e mnogu precizna. Broj koj i vo
Operatori
99
poslednata decimala se razlikuva od drug broj, i ponatamu e razli~en. Broj koj e na najmalata decimala nad nulata i ponatamu e razli~en od nulata. Ve`ba 7: (3) Napi{ete programa {to simulira frlawe na pari~ka (pismo glava).
Nepotpolno presmetuvawe
Koga rabotite so logi~ki operatori, }e naidete na fenomen nare~en nepotpolno presmetuvawe. Ova zna~i deka izrazot }e bide presmetuvan se dodeka to~nosta ili neto~nosta na celiot izraz mo`e da se odredi nedvosmisleno. Kako rezultat na toa, preostanatite delovi od logi~kiot izraz voop{to nema da bidat presmetani. Eve primer {to go demonstrira nepotpolnoto presmetuvawe:
//: operatori/NepotpolnoPresmetuvanje.java // Prikazuva pojava za nepotpolno presemtuvanje // pri rabota so logicki operatori. import static net.mindview.util.Print.*; public class ShortCircuit { static boolean testl(int vrednost) { print(testl( + vrednost + )); print(resultat: + (vrednost < 1)); return vrednost < 1; } static boolean test2(int vrednost) { print(test2( + vrednost + )); print(resultat: + (vrednost < 2)); return vrednost < 2; } static boolean test3(int vrednost) { print(test3( + vrednost + )); print(resultat: + (vrednost < 3)); return vrednost < 3; } public static void main(String[] args) { boolean b = testl(0) && test2(2) && test3(2): print(izrazot ima logicka vrednost + b): } } /* Izlez: test1(0) resultat: true test2(2) resultat: false izrazot ima logicka vrednost false *///: -
100
Da se razmisluva vo Java
Brus Ekel
Sekoj test vr{i sporedba so argumentot i vra}a vrednosti true ili false. Isto taka ja ispi{uva informacijata deka bil povikan. Testovite se povikuvaat preku sledniot izraz:
testl(0) && test2(2) && test3(2)
Prirodno e da pomislite deka site tri testa }e bidat izvr{eni, no izlezot poka`uva poinaku. Prviot test dava rezultat true, taka {to presmetuvaweto na izrazot prodol`uva. Sepak, vtoriot test dava rezultat false. Bidej}i ova zna~i deka rezultatot na celiot izraz sigurno }e bide false, za{to da prodol`ite so presmetuvaweto na izrazot? Toa mo`e da potrae podolgo vreme. To~no zatoa i se koristi nepotpolnoto presmetuvawe: ako ne treba do kraj da se presmetuvaat site delovi od logi~kiot izraz, programata mo`ebi }e raboti pobrzo.
Literali
Voobi~aeno, koga vo programata bukvalno vnesuvate vrednosti, preveduva~ot to~no znae vo kakov tip da gi pretstavi. Sepak, ponekoga{ mo`e da se javi dilema. Vo toj slu~aj, morate da go naveduvate va{iot preveduva~ so dodatni informacii vo forma na znaci pridru`eni na vrednosta na literalot. Sledniot kod gi poka`uva tie znaci:
//: operatori/Vrednosti.java import static net.mindview.util.Print.*: public class literals { public static void main(String[] args) { int i1 = 0x2f; // Heksadecimalno zadavawe na cel broj // (so mali bukvi) print(i1: + Integer.toBinaryString(i1)); int i2 = 0X2F; // Heksadecimalno zadavawe na cel broj // (so golemi bukvi) print(i2: + Integer.toBinaryString(i2)); int i3 = 0177; // Octadno zadavanje na cel broj // (so vodecka nula) print(i3: + Integer.toBinaryStr ing(i3)) char c = 0xffff; // najgolema vrednost za tip char, heksadecimalno print(c: + Integer.toBinaryString(c)); byte b = 0x7f; // najgolema vrednost za tip byte, heksadecimalno print(b: + Integer.toBinaryString(b)); short s = 0x7fff; // najgolema vrednost za tip short, heksadecimalno print(s: + Integer.toBinaryString(s)); long n1 = 200L; // sufiks za long long n2 = 200l; // sufiks za long (moza da zbuni bidejki lici na // edinica)
Operatori
101
long n3 = 200; float f1 = 1; float f2 = 1F; float f3 = 1f; double d1 = 1d; double d2 = 1D; i
// sufiks za float // sufiks za float // sufiks za double // sufiks za double // (Heksadecimalno i oktadno moze da se zadavaat //broevite ot tipot long)
} } /* Izlez: i1: 101111 i2: 101111 i3: 1111111 c: 1111111111111111 b: 1111111 s: 111111111111111 *///:-
Sledniot znak po literalot go zadava negoviot tip. Golemo ili malo L ozna~uva tip long (sepak , maloto l zbunuva bidej}i li~i na edinica). Golemo ili malo F ozna~uva tip float. Golemo ili malo D ozna~uva tip double. Vo heksadecimalna forma (so osnova 16), mo`e da se zadadat site celobrojni tipovi na podatoci, so obele`uvawe na vode~ko 0x ili 0X, prosledeni so simboli 0-9 ili a-f, bilo so golemi ili so mali bukvi. Dokolku se obidete da inicijalizirate promenliva so vrednost pogolema od onaa koja {to mo`e da ja ~uva (nezavisno od numeri~kata forma na vrednosta), preveduva~ot }e prijavi gre{ka. Vo posledniot primer, obratete vnimanie na maksimalnite mo`ni heksadecimalni vrednosti za char, byte i short. Dokolku gi nadminete, preveduva~ot avtomatski }e gi pretvori vo int i }e ve izvesti deka treba da se izvr{i stesnuvawe so eksplicitna konverzija za dadenoto dodeluvawe (eksplicitnite konverzii se definirani podocna vo ova poglavje). Vo toj slu~aj }e znaete deka ste ja preminale dozvolenata vrednost. Oktalnata forma (so osnova 8) se obele`uva so vode~ka nula vo zapisot na brojot, po {to sledat cifrite od 0-7. Vo jazicite S, S++ i Java ne postoi pretstavuvawe na binarnite broevi kako literal. Me|utoa, koga se raboti so heksadecimalna i oktalna notacija, pogodno e rezultatite da se prika`at vo binarna forma. Ova lesno se postignuva so metodite static toBinaryString() od klasite Integer i Long. Imajte na um deka koga gi prosleduvate pomalite tipovi vo Integer.toBinaryString(), tipot avtomatski se konvertira vo int. Ve`ba 8: (2) Poka`ete deka heksadecimaliot i oktalniot zapis rabotat so broevi od tip long. Koristete Long.toBinaryString() za da gi prika`ete rezultatite.
102
Da se razmisluva vo Java
Brus Ekel
Eksponencijalna notacija
Za eksponencijalen zapis na realen broj se koristi notacija {to jas sekoga{ sum ja smetal za obeshrabruva~ka:
//: operatori/Exponenti. java // e znaci 10 na stepen. public class Exponenti { public static void main{String[] args) { // Golemo i malo 'e' se ednakvi: float expFloat = 1.39e - 43f; expFloat = 1.39E - 43f; System.out.println(expFloat); double expDouble; 47e47d; // 'd' e opciono double expDouble2; 47e47; // Avtomatska konverzija vo double System.out.println(expDouble); } } /* Output; 1. 39E-43 4.7E48 * ///:-
Vo naukata i in`enerstvoto, e ozna~uva osnova na prirodni logaritmi, koja pribli`no iznesuva 2,718. (Poprecizna vrednost od tipot double e dostapna vo Java kako Math.E.) Taa se koristi vo eksponencijalnite izrazi kako 1,39 x e-43, {to zna~i 1,39 x 2,718-43. Sepak, koga programskiot jazik FORTRAN bil izmislen, negovite kreatori re{ile e da ozna~uva 10 na stepen, {to e ~udna odluka bidej}i FORTRAN bil dizajniran za nauka i in`enerstvo i sekoj bi pomislil deka dizajnerite bi obratile vnimanie na takva dvosmislenost.2 Vo sekoj slu~aj, ovoj obi~aj prodol`i vo S, S++, a sega i vo Java. Pa dokolku ste naviknati na e kako na osnova na normalnite logaritmi, morate da obratite vnimanie koga vo Java }e vidite izraz kako 1,39 x e-43f; toj vsu{nost ozna~uva 1,39 x 10-43. Obratete vnimanie deka ne morate da go koristite pridru`niot znak koga preveduva~ot mo`e sam da go odredi soodvetniot tip. Koga }e napi{ete
long n3 = 200;
preveduva~ot obi~no gi tolkuva eksponencijalnite broevi kako broevi so dvojna to~nost (double), pa bez pridru`nata bukva f, }e prijavi gre{ka, baraj}i eksplicitna konverzija od double vo float. Ve`ba 9: (1) Prika`ete gi najgolemiot i najmaliot broj koi mo`at da se zapi{at so eksponencijalniot zapis na tipovite float i double.
Operatori
103
2 John Kirkham napi{al: Po~nav da se zanimavam so kompjuterite vo 1962, koristej}i FORTRAN na IBM 1620. Vo toa vreme i za vreme na 1960-tite i 1970tite, FORTRAN be{e jazik koj koristi samo golemi bukvi. Ova poteknuva najverojatno od tamu {to mnogu od starite uredi za vlez koristea 5 biten Baudotov kod, koj ne poddr`uva{e mali bukvi. E vo eksponencijalna notacija sekoga{ be{e pi{uvano so golema bukva i zatoa nikoga{ ne se me{a{e so osnovata na prirodnite logaritmi e, koe sekoga{ se pi{uva so mala bukva. E ednostavno ozna~uva{e eksponent, obi~no 10, za koristeniot broen sistem. Vo toa vreme oktalnite broevi bea {iroko upotrebuvani me|u programerite. Dokolku naidev na oktalen broj vo eksponencijalna notacija, }e smetav deka e so osnova 8. Se se}avam deka prvpat vidov eksponencijalen zapis napi{an so malo e vo docnite 1970-ti i isto taka go smetav za zbunuva~ko. Problemot se pojavi koga vo FORTRAN prodrea malite bukvi, ne na samiot po~etok. Nie vsu{nost, imavme funkcii koi gi koristevme dokolku navistina ni be{e potrebna osnova na priroden logaritam, no site bea pi{uvani so golemi bukvi.
104
Da se razmisluva vo Java
Brus Ekel
Operatorite nad bitovi i logi~kite operatori koristat isti znaci, pa }e Vi bide polesno da se setite na zna~eweta ako se dosetite za slednovo: Bidej}i bitovite se mali, za operatorite nad bitovite se koristi samo eden znak. Operatorite nad bitovi mo`e da se kombiniraat so znakot = za da ja obedinat operacijata so dodeluvaweto: dozvoleni se &=, |= i ^=. (Bidej}i ~ e unaren operator, toj ne mo`e da se kombinira so znakot za ednakvost =.) Tipot boolean se tretira kako vrednost od eden bit, pa situacijata e malku poinakva. Nad nego mo`e da primenite konjunkcija, disjunkcija i isklu~iva disjunkcija nad bitovite, no ne i negacija nad bitovite (verojatno za da se izbegne me{aweto so logi~kata negacija). Za tipot boolean, operatorite nad bitovite go imaat istiot efekt kako logi~kite operatori, osven toa {to ne se javuva nepotpolno presmetuvawe. Operatorot isklu~iva disjunkcija nad bitovite nema ekvivalenten logi~ki operator. Zatoa ovoj operator pretstavuva edinstven na~in na dve vrednosti od tip boolean da im se primeni operacijata XOR. Na promenlivite od tipot boolean ne mo`ete da im primenuvate izrazi na pomestuvawe, koi se opi{ani vo tekstot podolu. Ve`ba 10: (3) Napi{ete programa so dve binarni konstanti koi imaat naizmeni~ni edinici i nuli, pri {to prvata da ima nula na mestoto na najmalku zna~ajnata cifra, a vtorata pak, tamu da ima edinica (sovet: Najlesno e koga za ova bi se koristele heksadecimalni konstanti). Zemete dve vrednosti i napravete kombinacii od niv na site mo`ni na~ini so koristewe na operatorite nad bitovi, a potoa prika`ete gi rezultatite so koristewe na metodot Integer.toBinaryString()
Operatori za pomestuvawe
Operatorite za pomestuvawe (angliski shift) isto taka rabotat so bitovi. Tie mo`e da se koristat isklu~ivo so prosti, celobrojni tipovi. Operatorot za pomestuvawe nalevo (<<) kako rezultat dava operand od levata strana na operatorot, pomesten nalevo za brojot na bitovi naveden posle operatorot (bitovite od ponizok rang se popolnuvaat so nuli). Operatorot na ozna~enoto pomestuvawe nadesno (>>) kako rezultat dava operand od levata strana na operatorot, pomesten nadesno za brojot na bitovi naveden posle operatorot. Ozna~enoto pomestuvawe nadesno >> koristi prodol`uvawe so za~uvuvawe na znakot (angliski sign extension), pa dokolku vrednosta e pozitivna, vo bitovite od povisok rang se vnesuvaat nuli. Dokolu pak vrednosta e negativna, vo bitovite od povisok rang se vnesuvaat edinici. Java e isto taka dopolneta so neozna~eno pomestuvawe na desno >>>, koe koristi pro{iruvawe so dodavawe nuli: nezavisno od znakot, nulite se vnesuvaat vo bitovite od povisok rang. Ovoj operator ne postoi vo S ili S++.
Operatori
105
Dokolku pomestuvate vrednosti od tip char, byte ili short, tie }e bidat pro{ireni vo int pred da se izvr{i pomestuvaweto i rezultatot }e bide od tip int. ]e se koristat samo pette bitovi od ponizok rang od desnata strana na operatorot. Ova ve spre~uva da izvr{ite pomestuvawe za pove}e mesta otkolku {to ima bitovi vo promenlivata od tip int. Dokolku vr{ite operacii nad vrednosti od tip long, }e dobiete rezultat od tipot long. ]e bidat iskoristeni samo {este bitovi od ponizok rang od desnata strana na operatorot, pa ne mo`ete da izvr{ite pomestuvawe za pove}e mesta otkolku {to ima bitovi vo promenlivata od tipot long. Pomestuvawata mo`e da se kombiniraat so znakot za ednakvost (<<= ili >>= ili >>>=). Lvrednosta e zameneta so vrednosta lvrednost pomestena za dvrednost mesta. Sepak, koga se kombinira neozna~enoto pomestuvawe nadesno so dodeluvaweto, se javuva problem Dokolku ovaa operacija ja primenite na vrednosti od tipot byte ili short, ne dobivate to~ni rezultati. Namesto toa, ovie se pro{iruvaat vo int, se pomestuvaat nadesno, a potoa se skratuvaat (otsekuvaat) pri dodeluvaweto vrednosti na promenlivite, pa vo tie slu~ai kako rezultat }e dobiete -1. Sledniot primer go demonstrira toa:
//: operatori/ NeoznacenoPomestuvanjeNaDesno.java // Test za neoznaceno pomestuvanje na desno. import static net.mindview.util.Print.*; public class NeoznacenoPomestuvanjeNaDesno { public static void main(String[] args) { int i = -1; print(Integer.toBinaryString(i)); i >>>= 10: print(Integer.toBinaryString(i)); long 1 = - l: print(Long.toBinaryString(l)); 1 >>>= 10: print(Long.toBinaryString(l)); short s = -1; print(Integer.toBinaryString(s)); s >>>= 10; print(Integer.toBinaryString(s)); byte b = - 1; print(Integer.toBinaryString(b)); b >>>= 18; print(Integer.toBinaryString(b)); b = -1; print(Integer.toBinaryString(b)); print(Integer.toBinaryString(b>>>10); } } /* Izlez: 11111111111111111111111111111111 1111111111111111111111 1111111111111111111111111111111111111111111111111111111111111111
106
Da se razmisluva vo Java
Brus Ekel
Vo poslednoto premestuvawe, rezultantnata vrednost ne e dodelena na promenlivata h, tuku direktno se ispi{uva, pa se dobiva ispravno odnesuvawe. Eve primer {to ja demonstrira koristeweto na site operatorite koi se odnesuvaat na bitovite:
//: operators/RabotaSoBitovi.java // Koristenje operatori nad bitovi. import java.util.d*; import static net.mindview.util.Print.*; public class RabotaSoBitovi { public static void main(String[] args) { Random slucaen = new Random(47): int i = slucaen.nextInt(); int j = slucaen.nextInt(); printBinaryInt(-1. -1); printBinaryInt(+1, +1); int maxpos = 2147483647; printBinaryInt(najgolem, maxpos); int max neg = -2147483648; printBinaryInt(najmal, maxneg); printBinaryInt(i, i); printBinaryInt(~i, ~i); printBinaryInt(-i, -i); printBinaryInt(j, j); printBinaryInt(i & j, i & j); printBinaryInt(i | j, i | j); printBinaryInt(i ^ j, i ^ j); printBinaryInt(i << 5, i << 5); printBinaryInt(i >> 5, i >> 5); printBinaryInt((-i) >> 5, (-i) >> 5); printBinarylnt(i >>> 5, i >>> 5); printBinarylnt((-i) >>> 5, (-i) >>> 5); long l = slucaen.nextLong (); long m = slucaen.nextLong (); printBinaryLong(-1L, -IL); printBinaryLong(+1L, +1L ); long ll = 9223372036854775807L; printBinaryLong (najgolem, ll); long lln = -9223372836854775808L;
Operatori
107
printBinarylong(maxneg, lln); printBinaryLong(l, 1); printBinaryLong(~1, ~1); printBinaryLong(-l, -1); printBinaryLong(m, m); printBinaryLong(1 & m, l &m); printBinaryLong(1 | m, l | m); printBinaryLong(1 ^ m, 1 ^ m); printBinaryLong(1 << 5, 1 << 5); printBinaryLong(l >> 5, 1 >> 5); printBinaryLong( (-l) >> 5, (-l) >> 5); printBinaryLong(1 >>> 5, l >>> 5); printBinaryLong((-l) >>> 5, (-l) >>> 5); } static void printBinaryInt(String s, int i) { print(s + , int: + i + , binarno:\n Integer.toBinaryString(i)); }
static void printBinaryLong(String s, long l) { print(s + , long: + 1 + , binarno:\n + Long.toBinaryString(l)); } } / izlez; -1, int: - 1, binary: 11111111111111111111111111111111 +1, int: 1, binary: 1 maxpos, int: 2147483647, binary: 1111111111111111111111111111111 maxneg, int: -2147483648, binary: 10000000000000000000000000000000 i, int: - 1172028779, binary: 10111010001001000100001010010101 ~i , int: 1172828778, binary: 1808101118110111811110101181818 -i, int: 1172828779, binary: 1080181110118111011118181181011 j, int: 1717241118. binary: 110011001011el10e0e0101e0e1e110 i & j, int: 570425364. binary: 100010000e00000000e0e000010100 i | j, int: -25213033, binary: 11111110011111110100011110810111 i ^ j, int: -595638397, binary: 11011100011111110100011110000011 i << 5, int: 1149784736, binary: 10e01e0100e1e000101001010100000 i >> 5, int: -36625900, binary:
108
Da se razmisluva vo Java
Brus Ekel
111111011101000100100e1000010100 (~i) >> 5, int: 36625899, binary: 10001011101101110111101011 i >>> 5, int: 97591828, binary: 101110100010010001000010100 (~i) >>> 5, int: 36625899, binary: 10001011101101110111101011 ... *///:-
Dvata metodi na krajot, printBinaryInt() i printBinaryLong(), ispi{uvaat vrednost od tip int ili long, vo binaren format zaedno so tekstualen opis. Kako {to ovoj primer vi go demonstrira dejstvoto na site operatori nad bitovi za int i long, isto taka go poka`uva minimumot, maksimumot, kako i vrednostite +1 i -1 za tipovite int i long za da mo`ete da vidite kako tie izgledaat. Vakvoto binarno komplement. pretstavuvawe na broevite se narekuva binaren
Ve`ba 11: (3) Zapo~nete so broj {to ima edna binarna edinica na najzna~ajnoto mesto (sovet: koristete heksadecimalna konstanta). So koristewe na operatorot na ozna~enoto pomestuvawe nadesno, pomestuvajte ja taa edinica po site mo`ni binarni pozicii nadesno i prika`ete gi site so metodot Integer.toBinaryString(). Ve`ba 12: (3) Zapo~nete so broj so site binarni edinici. Pomestete go za edno mesto nalevo, a potoa so operatorot za neozna~eno pomestuvawe pomestuvajte go nadesno po site mo`ni binarni pozicii i prika`ete gi site so metodot Integer.toBinaryString(). Ve`ba 13: (1) Napi{ete metod {to prika`uva char vrednosti vo binarna forma. Demonstrirajte gi rezultatite na nekolku razli~ni znaci.
Ako vrednosta na logicki-izraz e true, se presmetuva vrednost0 i toj rezultat stanuva vrednost na operacijata. Ako vrednosta na logicki-izraz e false, se presmetuva vrednost1 i nejziniot rezultat stanuva vrednost na operacijata. Sekako, bi mo`ele da koristite i obi~na if-else naredba (opi{ana podocna), no ternarniot operator e pokratok. Iako S (od kade ovoj operator poteknuva) se karakterizira so mo`nost za pi{uvawe kratki izrazi, kade Operatori 109
ternarniot operator delumno bil voveden za efikasnost, treba da bidete vnimatelni vo negovata sekojdnevna upotreba, bidej}i mnogu lesno mo`e da proizvede ne~itliv kod.
Uslovniot operator e razli~en od if-else bidej}i presmetuva vrednost. Eve primer za sporedba:
//: operatori/TernaryIfElse.java import static net.mindview.util.Print. * : public class TernaryIfElse { static int ternaren (int i) { return i < 10 ? i * 100 : i * 10; } static int if (i < return else return } standardenIfElse (int i) { 10) i * 100: i * 10:
public static void main(String [] args) { print (ternaren(9)); print( ternaren(10)); print(standardenIfElse(9)); print(standardenIfElse(10)); } } /* Rezultat: 900 100 900 100 * ///: -
Obratete vnimanie deka kodot na metodot ternaren() e pokratok otkolku onoj {to bi morale da go napi{ete bez ternarniot operator, kako vo metodot standardenIfElse(). Sepak, standardenIfElse() polesno se razbira i pobrzo se pi{uva. Zatoa dobro razmislete pred da go izberete ternarniot operator. Po pravilo, toa e poprigodno koga na promenlivata dodeluvate edna od dve mo`ni vrednosti.
110
Da se razmisluva vo Java
Brus Ekel
~ini deka e prirodna upotrebata na ovie operatori iako ne se vklopuva vo tradicionalniot na~in na nivno koristewe.
Ovaa mo`nost se ~ine{e kako dobra ideja na proektantite vo S++, pa vo jazikot dodale preklopuvawe na operatorot (overloading) za da mu ovozmo`i na S++ programerot da dodava zna~ewa na re~isi sekoj operator. Za `al, preklopuvaweto na operator kombiniran so nekoi drugi ograni~uvawa vo S++ se poka`alo premnogu komplicirano za programerite koi taa mo`nost sakale da ja vgradat vo svoite klasi. Iako preklopuvaweto na operator polesno bi se realizirano vo Java otkolku vo S++ (kako {to be{e poka`ano vo jazikot S#, koj ima ednostavno preklopuvawe na operatori), ovaa mo`nost s u{te be{e smetana za preslo`ena, pa programerite na Java ne mo`ea da implementiraat svoi operatori na preklopuvawe kako {to mo`ea programerite na S++ i S#. Upotrebata na String operatorite e prili~no interesna. Ako izrazot zapo~nuva so operand od tip String, toga{ site operandi {to sledat mora da bidat od toj tip (potsetete se deka preveduva~ot avtomatski ja pretvora nizata znaci pod navodnici vo String):
//: operatori/StringOperators.java import static net.mindview.util.Print.*; public class StringOperatori { public static void main(String [] args) { int x = 0, y = 1. z = 2; String s = x, y, z ; print(s + x + y + z); print(x + + s); // Go pretvara x vo String s += (sobrano) = ; // Operator za nadovrzuvanje (konkatenacija) print(s + (x + y + z)); print( + xl; // Skraten zapis namesto Integer.toString() } } /* Rezultat: x, y, z 012 o x, y, z x, y, z (sobrano) = 3 0 * ///:-
Obratete vnimanie deka izlezot od prvata naredba print e 012 namesto 3, {to vsu{nost bi ja dobile ako gi soberevme tie celi broevi. Ova se slu~uva bidej}i Java preveduva~ot gi konvertira x, y i z vo nivnite znakovni ekvivalenti i gi nadovrzuva, namesto prvin da gi sobere. Vtorata naredba print ja konvertira vode~kata promenliva vo String, taka {to taa konverzija nema da zavisi od redosledot na argumentite. Na kraj, gledate kako operatorot += e upotreben za na promenlivata s da se dodade znakovna niza
Operatori
111
i, bidej}i so zagradi e odreden redosledot na presmetuvawe na izrazot, za celite broevi vo zagradata da bi bile sobrani pred prika`uvaweto. Imajte go vo predvid posledniot primer vo metodot main(): prazen znakoven string prosleden so znakot + i nekoj prost tip. Java avtomatski }e go pretvori toj tip vo tip String, bez da imame potreba od povikuvawe na glomazniot ekspliciten metod (vo ovoj slu~aj, Integer.toString( )).
Programerot o~igledno se obiduval da ispita ednakvost (==), a ne da vr{i dodeluvawe. Vo S i S++ rezultatot na ova dodeluvawe sekoga{ }e bide true ako y ne e nula, a i verojatno bi dobile beskone~en ciklus. Vo Java, rezultatot od ovoj izraz ne e boolean, no preveduva~ot o~ekuva boolean i nema da konvertira od tipot int, tuku pri preveduvaweto }e prijavi gre{ka. Taka problemot }e bide otkrien pred izvr{uvaweto na programata. Pa ovoj nedostatok nikoga{ ne se slu~uva vo Java. (Edinstven slu~aj koga nema da dobiete gre{ka pri preveduvawe e koga h i u se boolean, kade h = u e dozvolen izraz, {to vo prethodniot primer najverojatno bi pretstavuvalo gre{ka.) Sli~en problem se javuva vo S i S++ pri koristewe na operatorite nad bitovi AND i OR namesto nivnite logi~ki varijanti. Operatorite nad bitovi AND i OR se pi{uvaat so eden od znacite (& ili |) dodeka logi~kite AND i OR se pi{uvaat so dva (&& i ||). Kako i so = i ==, polesno e da se vpi{e samo eden znak namesto dva. Vo Java, preveduva~ot toa povtorno go spre~uva, bidej}i nema da vi dozvoli od nebre`nost da iskoristite pogre{en tip vo izrazot.
112
Da se razmisluva vo Java
Brus Ekel
avtomatski }e go konvertira tipot int vo tip float. Programerot mo`e da bara eksplicitna konverzija (angliski - Casting), ili da ja izvede vo slu~aj koga toa normalno ne bi se slu~ilo. Za da izvedete eksplicitna konverzija, vnesete go posakuvaniot tip na podatok vo zagradite na levata strana od vrednosta {to sakate da ja konvertirate. Mo`ete da go vidite ova vo sledniot primer>
//: operatori/Konverzii. java public class Konverzii { publi c static void main(String [] args) { int i = 200; long lng = (long)i; lng = i; // Prosirena konverzija, pa // eksplicitna konverzija ne e potrebna long lng2 = (long)200; lng2 = 200; // Skratena konverzija: i = (int) lng2; // Ovde eksplicitna konverzija e neophodna } } ///:-
Kako {to gledate, vozmo`no e da se izvede eksplicitna konverzija na numeri~ka vrednost kako i na promenliva. Obratete vnimanie deka e dozvolena i izli{na eksplicitna konverzija. Na primer, preveduva~ot avtomatski }e ja prevede vrednosta od tip int vo tip long, koga toa }e bide potrebno. Sepak, izli{nata konverzija se dozvoluva za da ja istaknete ne{to ili va{iot kod da go napravite pojasen. Vo drugi situacii, konverzijata mo`e da bide esencijalna samo za da go preveduvate kodot. Vo S i S++, avtomatskata konverzija mo`e da predizvika mali glavobolki. Vo Java, avtomatskata konverzija e sosema bezbedna, osven vo slu~aj koga vr{ite t.n. stesnuva~ka konverzija (angliski narrowing conversion) (toa e, koga preminuvate od tip na podatok {to mo`e da ~uva pove}e informacii na drug tip koj ~uva pomalku), pri {to rizikuvate da izgubite informacija. Vo toj slu~aj preveduva~ot ve prisiluva da vr{ite eksplicitna konverzija, izvestuvaj}i Ve deka: Ova mo`e da e opasno - ako sepak sakate da go napravam, toga{ morate izri~no da pobarate konverzija. Pro{iruva~kata konverzija ne treba eksplicitno da se bara, bidej}i noviot tip mo`e da ~uva mnogu pove}e informacija otkolku stariot tip, taka {to nema da se izgubi nikakva informacija. Java dozvoluva da izvr{ite eksplitina konverzija od koj bilo prost tip vo koj bilo drug prost tip, osven boolean, koj voop{to ne mo`e da se konvertira. Klasite isto taka ne dozvoluvaat eksplicitna konverzija. Za da konvertirate edna klasa vo druga, mora da postojat specijalni metodi. (]e doznaete podocna vo ovaa kniga deka objektite mo`at eksplicitno da se
Operatori
113
konvertiraat vo ramkite na familijata od tipovi. Dabot mo`e eksplicitno da se konvertira vo Drvo i obratno, no ne vo tu| tip kakov {to e Karpa.)
Otsekuvawe i zaokru`uvawe
Koga izveduvate stesnuva~ka konverzija, morate da obrnete vnimanie na skratuvaweto i zaokru`uvaweto. Na primer, ako eksplicitno konvertirate realen broj so podvi`na zapirka vo cel broj, {to pravi Java? Na primer, ako vrednosta 29.7 ja konvertirate vo int, rezultatot }e bide 30 ili 29? Odgovorot na ova pra{awe mo`e da se vidi vo primerot:
//: operatori/KonverzijaNaBroevi.java // Sto se slucuva koga brojot e od tip float // ili od dva pati go konvertirate vo cel broj? import static net.mindview.util.Print.*; public class KonverzijaNaBroevi { public static void main(String [] args) { double nad = 0.7. pod = 0.4; float fnad = 0.7f. fpod = 0.4f; print((int)nad: + (int)nad); print((int)pod: + (int)pod); print((int)fnad: + (int)fnad): print((int)fpod: + (int)fpod): } } /* Rezultat: (int)nad: 0 (int)pod: 0 (int)fnad: 0 (int)fpod: 0 *///: -
Zna~i, odgovorot e deka pri eksplicitno konvertirawe od float ili double vo cel broj sekoga{ se otsekuva brojot. Ako sakate rezultatot da bide zaokru`en, toga{ koristete go metodot round( ) od bibliotekata java.lang.Math:
//: operatori/ZaokruzuvanjeNaBroevi.java // Zaokruzuvanje na broevi od tipot float i double. import static net.mindview.util.Print.*; public class ZaokruzuvanjeNaBroevi { public st ati c void main(String[) args) { double nad = e.7, pod = 0.4: float fnad = e.lf. pod = e.4f; print(Math.round(nad): + Math.round(above)); print(Math.round(pod): + Math.round(pod)); print(Math.round(fnad): + Math.round(fnad); print(Math.round(fpod): + Math.round (fpod));
114
Da se razmisluva vo Java
Brus Ekel
Bidej}i round( ) pripa|a na bibliotekata java.lang, naredba import za nejzino uvezuvawe i koristewe.
ne vi treba posebna
Unapreduvawe
Ako izveduvate kakvi bilo matemati~ki operacii ili operacii nad bitovi na prosti tipovi na podatoci {to se pomali od int (t.e. char, byte ili short), }e vidite deka tie vrednosti }e se unapredat vo tip int pred da se izvedat operaciite i vrednosta {to }e se dobie kako rezultat }e bide od tip int. Pa, ako sakate taa vrednost povtorno da ja dodelite na pomaliot tip, morate da koristite eksplicitna konverzija. (I bidej}i vr{ite dodeluvawe na pomal tip, mo`e da zagubite informacii.) Vo princip, najgolemiot tip na podatoci vo izrazot ja opredeluva goleminata na rezultatot na toj izraz; dokolku pomno`ite float i double, rezultatot }e bide od tip double. Ako soberete int i long, rezultatot }e bide od tip long.
Operatori
115
Pregled na operatori
Sledniot primer poka`uva koi prosti tipovi na podatoci mo`e da koristat odredeni operatori. Vo osnova, istiot primer se povtoruva nekolku pati, no so koristewe na drugi prosti tipovi na podatoci. Datotekata }e se prevede bez gre{ka bidej}i redovite {to koi mo`at da predizvikaat gre{ka se pretvoreni vo komentar so pomo{ na //!.
//: operatori/ SiteOperatori.java // Gi prikazuva site operatori na site prosti tipovi na podatoci // za da pokaze koi operacii se dozvoleni. public class SiteOperatori.java { // Za da se prifatat rezultatite od logickiot test: void f(boolean b) {} void boolTest(boolean x. boolean y) { //! Aritmeticki operatori: //! x = x * y; //! x = x / y; //! x = x%y; //! x = x+y ; //! x = x - y; //! x++; //! x--; //! x = +y; // Sporedbeni i logicki: //! (x>y); //! f(x >= y); //! f(x < y); //! f(x <= y); f( x == y); f(x!=y); f ( !y) ; x = x && y; x = x | | y; // Operatori na bitovi: // ! x = -y; x = x & y; x = x | y; x = x ^ y; // !x =x << 1 ; // !x =x >> 1; //! x = x >>> 1; // Slozeno dodeluvanje: // x += y; // x -= y; // x *= y; // x /= y; // x %= y;
116
Da se razmisluva vo Java
Brus Ekel
// x <<= 1 ; // x >>= 1; // x >>>= 1; x &= y; x ^= y; x |= Y; // Eksplicitna konverzija: // char c = (char )x; // byte b = (byte)x; // short s = (short)x; // int i = (int)x; // long 1 = (long)x; // float f = (float)x; // double d = (double)x; } void charTest(char x, char y){ // Aritmeticki operatori: x = (char)(x* y); x = (char)(x / y); x = (char)(x % y); x = (Char)(x + y); x = (char) (x - y); x++; x--; x = (char)+y; x = (char)-y; // Sporedbeni i logicki: f(x > y); f(x>=y); f(x < y); f(x <= y); f(x == y); f(x != y); //! f(!x); //! f(x && y); //! f(x | | y); // Operatori na bitovi: x= (char)-y; x = (char)(x & y); x = (char)(x | y); x = (char)(x ^ y); x = (char) (x << 1); x = (char) (x >> 1); x = (char) (x >>> 1); // Slozeno dodeluvanje: x += y; x -= y; x *= y; x /= y; x %= y;
Operatori
117
x <<= 1; x >>= 1 ; x >>>= 1; x &= y; x ^= y; x |= Y; // Eskplicitna konverzija : //! boolean bl = (boolean)x; byte b = (byte)x; short s = (short)x; int i = (int)x; long l = (long)x; float f = (float)x; double d = (double)x; } void byteTest( byte x, byte y) { // Aritmeticki Operatori: x = (byte)(x * y); x = (byte)(x / y); x = (byte)(x % y); x = (byte)(x + y); x = (byte)(x - y); x++; x--; X = (byte)+ y; x = (byte)- y; // Sporedbeni i logicki: f(x>y) ; f(x>=y) ; f(x < y); f(x<=y); f(x==y); f(x !=y); //! f(!x); //! f(x && y); //! f(x | | y); // Operatori na bitovi: x = (byte) - y; x = (byte)(x &y); x = (byte)(x | y); x = (byte)(x ^ y); x = (byte)(x << 1); x = (byte)(x >> 1); x = (byte)(x >>> 1); // Slozeno dodeluvanje: x += y; x -- y; x *=y; x /= y; x %= y;
118
Da se razmisluva vo Java
Brus Ekel
x <<= 1; x >>= I; x >>>= 1 ; x &= y; x ^= y; x |= y; // Eksplicitna konverzija: //! boolean bl = (boolean)x; char c = (char)x; short s = (short)x; int i = (int)x; long l = (long)x; float f = ( float)x ; double d = (double)x; } void shortTest(short x, short y) { // Aritmeticki operatori; x = (short) (x * y); x = (short) (x I y); x = (short) (x % y); x = (short) (x + y ); x = (short) (x - y); x++; x--; x = (short)+y; x = (short) -y; // Sporedbeni i logicki: f(x>y) ; f(x>=y) ; f(x < y); f(x< =y); f(x ==y); f(x !=y); //! f(!x); //! f(x && y); //! f(x || y); // Operatori na bitovi: x = (short) - y; x = (short)(x &y); x = (short)(x | y); x = (short)(x ^ y); x = (short)(x << 1); x = (short)(x >> 1); x = (short)(x >>> 1); // Slozeno dodeluvanje: x += y; x -- y; x *=y; x /= y; x %= y;
Operatori
119
x <<= 1; x >>= I; x >>>= 1 ; x &= y; x ^= y; x |= y; // Eskplicitna konverzija: // ! boolean bl = (boolean)x; char c = (char)x; byte b = (byte)x; int i = (int)x; long l = (long)x; float f = (float)x; double d = (double)x; } void intTest(int x, int y) { // Aritmeticki operatori: x = x*y; x = x / y; x = x % y; x = x + y; x = x - y; x++; x--; x = +y; x = -y; //Sporedbeni i logicki: f(x>y) ; f(x>=y) ; f(x < y); f(x<=y); f(x==y); f(x !=y); //! f(!x); //! f(x && y); //! f(x | | y); // Operatori na bitovi: x = -y; x = x & y; x = x | y; x = x ^ y; x = x << 1 ; x = x >> 1 ; x = x >>> 1; // Slozeno dodeluvanje: x += y; x - = y; x *= y; x /= y; x %= y;
120
Da se razmisluva vo Java
Brus Ekel
x <<= l; x >>= 1; x >>>= 1; x &= y; x ^= y; x | = y; // Eksplicitna konverzija: //! boolean bl = (boolean)x; char c = (char)x; byte b = (byte)x; short s = (short)x; long l = (long)x; float f = (float)x; double d = (double)x; } void longTest(long x. long y) { // Aritmeticki operatori: x = x * y; x = x | y ; x = x % y; x = x + y; x = x - y; x++; x -- ; x = +y; x = -y; // Sporedbeni i logicki: f(x>y) ; f(x>=y) ; f(x < y); f(x< =y); f(x ==y); f(x!=y); //! f(!x); //! f(x && y); //! f(x || y); // Operatori na bitovi: x = - y; x = x &y ; x = x | y; x = x ^ y; x = x << 1; x = x >>1; x = x>>> 1 ; // Slozeno dodeluvanje : x += y; x - = y; x *= y; x /= y; x %= y;
Operatori
121
x <<= l; x >>= 1; x >>>= 1; x &= y; x ^= y; x | = y; // Eskplicitna konverzija: //! boolean bl = {boolean)x; char c = (char)x; byte b = (byte)x; short s = (short)x; int i = (int)x; float f = (float)x; double d = (double)x; } void floatTest(float x, float y) { // Aritmeticki operatori: x = x * y; x = x | y ; x = x % y; x = x + y; x = x - y; x++; x-- ; x = +y; x = -y; // Sporedbeni i logicki: f(x>y) ; f(x>=y) ; f(x < y); f(x< =y); f(x ==y); f(x !=y); //! f(!x); //! f(x && y); //! f(x || y); // Operatori na bitovi : x = - y; x = x &y ; x = x | y; x = x ^ y; x = x << 1; x = x >> 1; x = x>>> 1; // Slozeno dodeluvanje : x += y; x - = y; x *= y; x /= y; x %= y;
122
Da se razmisluva vo Java
Brus Ekel
x <<= l; x >>= 1; x >>>= 1; x &= y; x ^= y; x | = y; // Eksplicitna konverzija: // ! boolean bl = (boolean)x; char c = (char)x; byte b = (byte)x; shor t s = (short)x; int i = (int)x ; long l = (long)x; double d = (double)x; } void doubleTest(double x. double y) { // Aritmeticki operatori: x = x * y; x = x | y ; x = x % y; x = x + y; x = x - y; x++; x -- ; x = +y; x = -y; // Sporedbeni i logicki: f(x>y); f(x>=y); f(x<y); f(x<=y); f(x==y); f(x!=y); //! f(!x); //! f(x && y); //! f(x | | y); // Operatori na bitovi: x = - y; x = x &y ; x = x | y; x = x ^ y; x = x << 1; x = x >>1; x = x>>> 1; // Slozeno dodeluvanje: x += y; x - = y; x *= y; x /= y; x %= y;
Operatori
123
x <<= l; x >>= 1; x >>>= 1; x &= y; x ^= y; x | = y; // Eksplicitna konverzija: //! boolean bl = (boolean)x; char c = (char)x; byte b = (byte)x; short s = (short)x; int i = (int)x; long l = (long)x; float f = (float)x; } } ///:-
Obratete vnimanie deka tipot boolean e prili~no ograni~en. Mo`ete da mu dodelite vrednosti true i false, a mo`ete i da mu ja ispituvate vrednosta (vistina ili laga), no ne mo`ete da sobirate promenlivi od tip boolean ili da izveduvate kakov bilo drug tip na operacija vrz niv. Kaj tipovite char, byte i short, mo`ete da go vidite efektot od unapreduvaweto na tipot koe se pojavuva pri upotreba na aritmeti~kite operatori. Sekoja aritmeti~ka operacija primeneta na koj bilo od tie tipovi dava rezultat od tip int, koj mora so eksplicitna konverzija da bide vraten vo prvobitniot tip ({to pretstavuva stesnuva~ka konverzija {to mo`e da predizvika gubewe informacii). Pri koristewe na vrednosti od tipot int vrednostite, sepak, nema da vi bide potrebna eksplicitna konverzija, bidej}i se {to vi treba e ve}e od tip int. Sepak nemojte da bidete sigurni deka s e sigurno. Ako pomno`ite dve vrednosti od tip int {to se dovolno golemi, }e go prepolnite rezultatot. Toa go poka`uva sledniot primer:
//: operatori/Prestapuvanje.java // Iznenaduvanje! Java dozvoluva prestapuvanje. public class Prestap { public static void main(String [] args) { int golem = Integer.MAX_VALUE; System.Qut.println(golem = + golem); int pogolem = golem * 4 ; System.out.println (pogolem = + pogolem); } } /* Rezultat: golem = 2147483647 pogolem = -4 * ///: -
124
Da se razmisluva vo Java
Brus Ekel
Ne dobivate nitu poraki za gre{ki nitu predupreduvawa od preveduva~ot, a isto taka ne se pojavuvaat isklu~oci pri izvr{uvaweto. Java e dobra, no ne tolku dobra. Slo`enite dodeluvawa ne baraat eksplicitni konverzii za tipovite char, byte ili short, iako izveduvaat unapreduvawa {to imaat isti rezultati kako i direktnite aritmeti~ki operacii. Od druga strana, so izostavuvawe na eksplicitnata konverzija definitivno se uprostuva kodot. Mo`ete da zabele`ite deka site prosti tipovi, so isklu~ok na tipot boolean, mo`at da bidat eksplicitno konvertirani vo koj bilo drug prost tip. Povtorno napomenuvam, morate da vodite smetka za efektot od stesnuva~kite konverzii koga konvertirate vo pomal tip. Inaku, mo`no e neznajno gubewe informacii za vreme na konverzijata. Ve`ba 14: (3) Napi{ete metod koj prima dve znakovni nizi kako argumenti i gi koristi site boolean sporedbi za da gi sporedi i da gi ispi{e rezultatite. Za == i !=, isto taka izvr{ete i test equals( ). Vo main( ), povikajte go va{iot metod so nekolku razli~ni String objekti.
Rezime
Ako ste imale iskustvo so koj bilo jazik koj koristi sintaksa sli~na na sintaksata na S, mo`ete da vidite deka operatorite vo Java se tolku sli~ni so onie od Vam dobro poznatite jazici, taka {to nema da imate pote{kotii pri nivnoto izu~uvawe. Ako go smetate ova poglavje za te{ko, poglednete ja multimedijalnata prezentacija Thinking in C, dostapna na adresata www.MindView.net. Re{enijata na izbranite ve`bi mo`e da se najdat vo elektronskiot dokument The Thinking in Java Annotaed Solution Guide, dostapen za proda`ba na www.MindView.net.
Operatori
125
Kontrolirawe na izvr{uvaweto
Kako i svesnoto su{testvo, i programata mora da upravuva so svoeto opkru`uvawe i da bira {to }e raboti. Vo Java birate so pomo{ na naredbite za kontrola na izvr{uvaweto na tekot na programata.
Java gi koristi site naredbi od S za kontrola na izvr{uvawe, pa ako ste programirale na S ili S++, toga{ pogolemiot del od toa {to }e sledi ve}e vi e poznato. Pove}eto proceduralni programski jazici imaat nekoj odreden tip na naredbi za kontrola, pa ~esto se slu~uvaat sli~nosti me|u jazicite. Vo Java, rezerviranite zborovi vklu~uvaat if-else, while, do-while, for, return, break i naredba za izbor switch. Java sepak, ne ja podr`uva prili~no opasnata naredba goto (koja mo`e s u{te da bide najdobriot na~in za re{avawe na odreden vid problemi). Vie i ponatamu mo`ete da napravite skok sli~en na goto, no sepak }e bide mnogu poograni~en od tipi~nata naredba goto.
if-else
Naredbata if-else e najosnoven na~in za kontrolirawe na tekot na programata. Delot else ne e zadol`itelen, pa zatoa if mo`ete da ja koristite vo dve formi:
if (Logicki-izraz)
126
Da se razmisluva vo Java
Brus Ekel
naredba
ili
if (Logicki-izraz) naredba else naredba
Logi~kiot izraz mora da vra}a rezultat od tip boolean. Naredba e ednostavna naredba koja zavr{uva so znakot to~ka-zapirka, ili slo`ena naredba, odnosno grupa od ednostavni naredbi vo golemi zagradi. Koga i da se koristi zborot naredba, toj sekoga{ podrazbira deka naredbata mo`e da bide ednostavna ili slo`ena. Kako primer za if-else, sleduva metodot test( ) {to }e vi ka`e dali pretpostavenata vrednost e pomala, pogolema ili ednakva na celnata vrednost:
//: control/IfElse.java import static net.mindview.util.Print.*; public class IfElse { static int resultat = 0: static void test(int vrednost. int cel) { if(vrednost > cel) resultat = +1; else if(testval < target) resultat = -1; else result = 0: // Match } public static void main(String [] args) { test(10, 5); print(resultat); test(5, 10); print(resultat); teste(5, 5); print(resultat); } } /* Rezultat: 1 -1 0 * ///:-
Vo sredinata od metodot test( ), isto taka }e ja vidite kombinacijata else if, koja {to ne e nov rezerviran zbor, tuku samo eden else prosleden so novata naredba if.
Kontrolirawe na izvr{uvaweto
127
Iako Java, kako S i S++ pred nego, e jazik so sloboden oblik, korisno e vovlekuvawe na teloto na naredbata za kontrola na tekot na izvr{uvaweto, za ~itatelot da mo`e lesno da odredi kade toa zapo~nuva i zavr{uva.
Povtoruvawa
Cikli~nite strukturi se kontroliraat so rezerviranite zborovi while, dowhile i for, koi ponekoga{ se klasificiraat kako naredbi za povtoruvawe. Naredbata se povtoruva s dodeka logicki-izraz za kontrola ne dobie vrednost false. Formata na naredbata za povtoruvawe while e:
while( logicki-izraz ) naredba
Logicki izraz se presmetuva edna{ na po~etokot na ciklusot i povtorno pred sekoe povtoruvawe na naredbata. Sleduva ednostaven primer {to generira slu~ajni broevi s dodeka ne bide ispolnet opredelen uslov:
//: control/PrimerZaWhile . java // Go prikazuva ciklusot while . public class PrimerZaWhile { static boolean uslov() { boolean rezultat = Math.random() < 0.99: System.out.println(rezultat + , ): return rezultat; } public static void main(String[) args) { while(uslov()) System.out.println( Vo ciklusot 'whi le '''); System . out .p rintln(Izlezen od ciklusot 'while' ) ; } } /* (Izvrsete za da go vidite rezultatot) *///:-
Metodot uslov( ) go koristi stati~niot metod random( ) vo bibliotekata Math, , koja generira vrednost od tipot double pome|u0 i 1. (vklu~uvaj}i 0, no ne i 1.) Na promenlivata rezultat vrednost dava operatorot za sporedba <, ~ij rezultat e od tipot boolean. Ako ispi{uvate vrednost od tipot boolean, avtomatski }e dobiete soodvetna znakovna niza true ili false. Uslovniot izraz za while glasi: Povtoruvaj gi naredbite vo teloto vo ciklus s dodeka metodot uslov( ) vra}a true.
do-while
Formata na naredbata za povtoruvawe do-while e:
do statement
128
Da se razmisluva vo Java
Brus Ekel
while(logicki-izraz);
Edisntvenata razlika pome|u while i do-while e deka naredbata vo ciklusot do-while sekoga{ se izvr{uva najmalku edna{, duri i koga izrazot ima vrednost false i prviot pat. Ako uslovot ima vrednost false pred vlezot vo ciklusot while, naredbata nikoga{ nema da se izvr{i. Vo praksa, do-while se koristi poretko od while.
Ciklusot for
Ciklusot for e verojatno naj~esto upotrebuvanata forma za povtoruvawe. Taa izveduva inicijalizacija pred prvoto izvr{uvawe na ciklusot. Potoa go ispituva uslovot (logicki-izrazi) i ako toj e ispolnet, se izvr{uva naredba, a potoa na krajot od sekoj ciklus izvr{uva cekor i povtorno se ispituva logickiizraz. Formata na naredbata za povtoruvawe for e:
for( inicijalizacija; logicki-izraz; cekor ) naredba
Koj bilo od izrazite inicijalizacija, logicki-izraz ili cekor mo`e da bide prazen. Izrazot se ispituva pred sekoe povtoruvawe i {tom dobie vrednost false, ciklusot se prekinuva i izvr{uvaweto prodol`uva so prvata naredba posle ciklusot for. Na krajot na sekoj ciklus, se izvr{uva cekor. Ciklusite for voobi~aeno se koristat vo zada~i za nabrojuvawe:
//: control/ ListaSoZnaci.java // Go prikazuva for ciklusot taka sto // Gi pecati site mali ASCII bukvi. public class ListaSoZnaci { public static void main(String [] args) { for (char c = 0; c < 128: c++) if (Character . islowerCase(c) System.out.println(value: + (int)c + znak: + c); } } /* Rezultat: vrednost: 97 znak: a vrednost: 98 znak: b vrednost: 99 znak: c vrednost: 100 znak: d vrednost: 101 znak: e vrednost: 102 znak: f vrednost: 103 znak: g vrednost: 104 znak: h vrednost: 105 znak: i vrednost: 106 znak: j ... */// :-
Kontrolirawe na izvr{uvaweto
129
Obratete vnimanie deka promenlivata s e definirana na mestoto kade se koristi, vnatre vo kontrolniot izraz na ciklusot for, namesto na po~etokot od metodot main( ). Oblasta na va`ewe na promenlivata s e naredbata kontrolirana od strana na ciklusot for. Vo ovaa programa isto taka se koristi i obvitkuva~kata klasa java.lang., koja go obvitkuva prostiot tip char vo objekt, tuku isto taka pru`a i drugi uslugi. Tuka, stati~niot metod isLowerCase( ) se koristi za da se otkrie dali tekovniot znak e mala bukva. Tradicionalnite proceduralni jazici kako S baraat site promenlivi da bidat definirani na po~etokot od blokot taka {to, koga preveduva~ot }e kreira blok, mo`e da rezervira mesto za tie promenlivi. Vo Java i S++, definiciite na promenlivite mo`ete da gi napi{ete kade bilo vo blokot, onamu kade {to }e Vi trebaat. Ova ovozmo`uva popriroden stil na kodirawe i go pravi kodot porazbirliv. Ve`ba 1: (1) Napi{ete programa {to gi ispi{uva vrednostite od eden do 2. Ve`ba 2:(2) Napi{ete programa {to generira 25 slu~ajni vrednosti od tip int. Za sekoja vrednost, koristete naredba if-else za go odredite dali e pogolema, pomala ili ednakva na druga slu~ajno generirana vrednost. Ve`ba 3: (1) Promeni ja ve`ba 2 taka {to va{iot kod }e go vklopite vo beskone~en ciklus while. Toga{ programata }e se izvr{uva se dodeka ne ja prekinete od tastatura (Voobi~aeno so pritiskawe na kombinacijata Control+C). Ve`ba 4: (3) Napi{ete programa {to koristi dva vgnezdeni ciklusi for i operator modul na delewe (%) za da otkrie i ispi{e prosti broevi (celi broevi {to se delivi samo so 1 i so sami so sebe). Ve`ba 5: (4) Povtorete ja ve`ba 10 od prethodnoto poglavje, taka {to za prika`uvawe na edinicite i nulite }e upotrebite ternaren operator i ispituvawe na bitovite, namesto metodot Integer.toBinaryString( ).
Operator zapirka
Prethodno vo ova poglavje navedov deka zapirkata kako operator, (ne zapirkata razdvojuva~, koja se koristi za da razdeli definicii i argumenti na metod) ima samo edna primena vo Java: se koristi samo vo kontrolnite izrazi na ciklusot for. Kako i pri inicijalizacijata, taka i pri izvr{uvaweto na ~ekorite na kontrolniot izraz, mo`ete da navedete pove}e naredbi odvoeni so zapirki i tie }e bidat izvr{eni sekvencijalno. So pomo{ na zapirkata kako operator, mo`ete da definirate pove}e promenlivi vo ramkite na naredbata for, no tie mora da bidat od ist tip:
//: control/OperatorZapirka.java
130
Da se razmisluva vo Java
Brus Ekel
public class OperatorZapirka { public static void main (S tr ing[l args) { for {int i = 1, j = i + 10; i < 5: i++, j = i * 2} System.out.println(i = + i + j = + j): } } / * Rezultat: i= l j= 11 i= 2 j = 4 i= 3 j = 6 i= 4 j=8 *///:-
Definicijata na celobrojni promenlivi vo naredbata for gi opfa}a i i j. Delot od inicijalizacijata mo`e da ima pove}e definicii od eden ist tip. Mo`nosta za definirawe na promenlivi vo kontrolniot izraz e ograni~en samo na ciklusot for. Ne mo`ete da go koristite ovoj pristap so koja bilo druga naredba za izbor ili naredbi za povtoruvawe. Uo~ete deka i vo delot za inicijalizacija inicijalizacijata i step porciite, naredbite se ocenuvaat vo sekvencijalen redosled.
Sintaksa Foreach
Java YEY voveduva nova i poefikasna sintaksa na naedbata for, koja se upotrebuva za nizi i kontejneri (}e nau~ite pove}e za niv vo poglavjata Nizi i Detalno razgleduvawe na kontejneri.) Taa ~esto se narekuva foreach sintaksa i zna~i deka vo nea ne morate da kreirate celobrojna promenliva za broewe na pominuvawata niz sekvencata stavki - foreach avtomatski da gi pravi site stavki namesto Vas.. Na primer, da pretpostavime deka imate niza od broevi od tip float i sakate da go izberete sekoj element od taa niza:
//: control/ForeachFloat.java import java.util . *: public class ForeachFloat { public static void main(String [] args) { Random slucaen = new Random(47); float f[] = new float[10]: for(int i = 0; i < 10: i++) f[i] = slucaen.nextFloat(): for (float x : f) System.out.println(x); } } /* Rezultat: 0.72711575 0. 39982635
Kontrolirawe na izvr{uvaweto
131
Nizata e napolneta so stariot ciklus for, bidej}i mora da mu se pristapi so pomo{ na indeks. Mo`ete da ja vidite foreach sintaksata vo sledniot primer:
for (float x : f) {
So nea se definira promenliva h od tip float na koja sekvencijalno se dodeluva sekoj element od nizata f. Za koristewe na foreach sintaksata kandidat e sekoj metod koj vra}a niza. Na primer, klasata String ima metod toCharArray( ) {to vra}a pole od tip char, taka {to }e mo`ete lesno da go izdvoite sekoj znak na znakovnata niza:
//: control/ForEachString.java public class ForeachString { public static void main(String [] args) { for(char znak : Africka lastovica .toCharArray() System.out.print(znak + ): } } / * Rezultat: A f r i c k a l a s t o v i c a * ///:-
Kako {to }e vidite vo poglavjeto ^uvawe na objekti, foreach sintaksata isto taka raboti so sekoj objekt koj pripa|a na klasata Iterable(za koj se znae redosledot na negovite ~lenovi). Mnogu for naredbi go opfa}aat pominuvaweto niz sekvenca od celobrojni vrednosti, da re~eme na ovoj na~in:
for(int i = 0; i < 100; i++)
Vo ovoj slu~aj, sintaksata foreach nema da raboti, osven ako odnapred ne kreirate niza int. Za da ja poednostavnam ovaa zada~a, vklu~iv metod domet( ) vo bibliotekata net.mindview.utiLRange {to avtomatski ja generira soodvetnata niza. Mojata namera be{e metodot domet( ) e da se koristi kako uvoz static:
//: control/ForeachInt.java import static net.mindview.util.Range.*
132
Da se razmisluva vo Java
Brus Ekel
import static net.mindview.util.Print.* public class ForeachInt { public static void main(String[ ] args) { for(int i : range(10)) // 0 . . 9 printnb(i + ): print(): for (int i range(5, 10)) // 5 .. 9 printnb(i + ); print(); for(int i ; range(5. 20, 3)) // 5.. 20 niz cekor 3 printnb(i + ); print(); } } /* Rezultat: 0 1 2 3 4 5 6 7 8 9 5 6 7 8 9 5 8 11 14 17 * ///:-
Metodot range( ) bil preklopen, {to zna~i deka so istoto ime na metodot mo`e da se zadavaat razli~ni listi na argumenti (za preklopuvaweto }e stane zbor naskoro ). Prvata preklopena forma na metodot range( ) po~nuva so nula i dava vrednosti do vrvot na opsegot, ne vklu~uvaj}i go samiot vrv. Vtorata forma zapo~nuva so prvata zadadena vrednost i dava broevi do iznosot za eden pomal od vtoriot argument. Tretata forma prima ~ekor na zgolemuvawe vo svojot tret argument, range( ) e prosta verzija na generator, kako {to }e vidite podocna vo knigata. Obratete vnimanie deka iako range( ) ovozmo`uva koristewe na foreach sintaksa na pove}e mesta i ottuka mo`ebi ja zgolemuva ~itlivosta, no e pomalku efikasno, pa ako se obidete da ja zgolemite efikasnosta na svojata programa, treba da koristite profiler, alatka koja gi meri performansite na va{iot kod. Mo`ebi zabele`avte deka vo prethodniot primer, osven metodot printnb( ) upotreben e i metodot print( ). Printnb( ) metodot ne zadava premin vo nov red, pa ovozmo`uva pove}ekratno pi{uvawe vo ist red. Foreach sintaksata ne samo {to {tedi vreme pri pi{uvawe na kodot, tuku, {to e u{te pova`no, takviot kod e mnogu po~itliv i go ka`uva ona {to se obiduvate da go napravite (da go dobiete sekoj element od poleto) namesto detalite kako toa da go pravite (Go sozdavam ovoj indeks so cel da mo`am da go izberam sekoj element od nizata.) Sintaksata foreach }e se koristi vo ovaa kniga sekade kade e toa mo`no.
Kontrolirawe na izvr{uvaweto
133
Nema potreba od else, bidej}i metodot nema da prodol`i po izvr{uvaweto na return. Ako nemate naredba return vo metod {to vra}a void, postoi impliciten return na krajot od toj metod, pa ne e sekoga{ neophodno da se vklu~i naredbata return, Sepak, ako va{iot metod vra}a koj bilo drug tip osven void, morate da obezbedite sekoj mo`en pat niz negoviot kod da vrati nekoja vrednost. Ve`ba 6: (2) Modificirajte gi dvete metodi test( ) od dvete prethodnite programi taka {to tie zemaat dva u{te dva argumenti, pocetok i kraj i taka {to testval }e ispituva za sekoja vrednost dali se nao|a pome|u pocetok i kraj, vklu~uvaj}i gi i granicite.
134
Da se razmisluva vo Java
Brus Ekel
Kontrolirawe na izvr{uvaweto
135
10 20 30 40 * ///:-
Vo ciklusot for, vrednosta na i nikoga{ nema da stigne do 100 bidej}i naredbata break go prekinuva ciklusot koga i }e dobie vrednost 74. Normalno, bi koristele naredba break samo ako odnapred ne znaete koga }e se sozdade uslov za izleguvawe. Naredbata continue go prodol`uva izvr{uvaweto od po~etokot na ciklusot (taka se zgolemuva i) sekoga{ koga i ne se deli so 9. Koga se deli, se ispi{uva taa vrednost. Vo vtoriot ciklus for prika`ana e upotrebata na foreach sintaksata i se gleda deka taa dava isti rezultati. Na kraj, }e vidite beskone~en ciklus while, {to teoretski, bi se izvr{uval neprekinato. Sepak, vnatre vo ciklusot se nao|a naredbata break so pomo{ na koja se izleguva od ciklusot. Pokraj toa, }e zabele`ime deka naredbata continue go vra}a izvr{uvaweto na vrvot na ciklusot bez da go zavr{i ostatokot na teloto na ciklusot posle sebe. (Taka, ispi{uvaweto vo vtoriot ciklus se slu~uva samo koga vrednosta na i e deliva so 10.) Na izlezot se ispi{uva vrednosta 0 bidej}i vrednosta na izrazot 0% 9 e ednakva na 0. Vtora forma na beskone~en ciklus e for(;;). Preveduva~ot gi tretira while(true) i for(;;) na ist na~in, taka {to izborot e pra{awe na programerski vkus.
Ve`ba 7: (1) Modificirajte ja ve`ba 1 taka {to programata ja zavr{uva rabotata so koristewe na rezerviraniot zbor break koga vrednosta }e dojde do 99. Namesto toa, obidete se da koristite return.
Nepopularnoto goto
Rezerviraniot zbor goto e prisuten vo programskite jazici u{te od samiot po~etok. Vsu{nost, goto nastanal kako posledica na programskata kontrola vo ma{inskiot (asembler) jazik: Ako e ispolnet uslov A, toga{ skokni ovde; inaku, skokni tamu. Ako go pro~itate ma{inskiot kod {to na krajot e generiran od strana na koj bilo preveduva~, }e vidite deka kontrolata vrz programata sodr`i mnogu skokovi (Java preveduva~ot proizveduva svoj asemblerski kod, no ovoj kod go izvr{uva Virtuelnata Ma{ina na Java namesto hardverskata centralna procesna edinica (procesorot). Naredbata goto e skok na nivo na izvorniot kod i toa e pri~inata {to donese lo{ ugled. Ako programata postojano skoka od edna to~ka do druga, dali postoi nekoj na~in da se reorganizira kodot taka {to tekot na kontrolata da ne e tolku poln so skokovi? Naredbata goto padna vo vistinska nemilost po objavuvaweto na poznatiot trud Goto se smeta za {teten na Edsger Dijkstra i ottoga{ napadite vrz goto stanaa popularen sport.
136
Da se razmisluva vo Java
Brus Ekel
Kako {to e svojstveno na situacii kako ovaa, najdobar e sredniot pat. Problemot ne e upotrebata na goto, tuku vo pregolemata upotreba na goto; vo retki situacii goto.e najdobriot na~in za strukturirawe na tekot na izvr{uvawe. Iako zborot goto e rezerviran vo Java, toj ne se koristi vo jazikot; Java nema naredba goto Sepak, taa ima ne{to {to li~i na skok povrzano so rezerviranite zborovi break i continue. Toa ne e skok, tuku pove}e na~in za da izleze od ciklusot. Toj ~esto se povrzuva so naredbata goto bidej}i koristi ist mehanizam: oznakata label.
oznaka1:
Edinstvenoto mesto kade se koristi oznakata vo Java e tokmu pred naredbata za povtoruvawe, a toa zna~i neposredno pred nea ne se prepora~uva smestuvawe na koja bilo druga naredba pome|u oznakata i ciklusot. Vsu{nost, osnovnata pri~ina za smestuvawe na oznakata pred ciklusot e ako sakate vnatre vo ciklusot da vgnezdite u{te eden ciklus ili naredba za izbor switch (za {to }e u~ite naskoro). Rezerviranite zborovi break i continue normalno }e go prekinuvaat samo tekovniot ciklus, no koga se koristat so oznaka, tie }e gi prekinuvaat site ciklusi do mestoto kade {to e postavena taa oznaka.
oznaka1: nadvoresna-iteracija { vnatresna-iteracija // . . . break : // (1) // ... continue: // (2) // . . . continue oznaka1: // (3) // ... break oznaka1: // (4) } }
Vo (1), break go prekinuva vnatre{niot ciklus, a Vie prodol`uvate so nadvore{niot... Vo (2), continue se vra}a nazad na po~etokot od vnatre{niot ciklus. No, vo (3), continue oznaka1 go prekinuva vnatre{niot i nadvore{niot ciklus, se do oznaka1. Toga{ vsu{nost se prodol`uva ciklusot, no po~nuvaj}i od nadvore{niot ciklus. Vo (4) break oznaka1 isto taka pravi prekin se do oznaka1, no ne vleguva povtorno vo ciklus. Vsu{nost, taa navistina gi prekinuva dvata ciklusa. Eve primer za koristewe na ciklusi for:
//: control/OznacenCiklusFor.java // Ciklus for so oznacena naredba break i oznacena naredba continue. import static net.mindview.util.Print. * ;
Kontrolirawe na izvr{uvaweto
137
public class LabeledFor { public static void main(String [] args) { int i = 0: nadvoresna : // Ovde ne mozat da stojat naredbi for(; true ;) { // beskonecen ciklus vnatresna: // Ovde ne moze da stojat naredbi for(; i < 10; i++) { print( i = + i); if(i == 2) { print( prodolzi); continue: } if(i == 3) { print(stopiraj) : i++; // Inaku i nikogas // ne se zgolemuva. break; } if(i == 7) { print(prodolzi nadvoresen); i++; // Inaku i nikogas // ne se zgolemuva. continue nadvoresen: } if(i == 8) { print(stopiraj nadvoresen): break nadvoresen; } for(int k = 0: k < 5: k++) { if(k == 3) { print(prodolzi vnatresen); continue vnatresen; } } } // Ovde ne moze da gi povikate // oznacenite naredbi break i continue } }/* Rezultat: i = 0 continue inner i = 1 continue inner i = 2 continue i = 3 break i = 4 continue inner
138
Da se razmisluva vo Java
Brus Ekel
Obratete vnimanie na toa deka naredbata break go prekinuva ciklusot for, i deka izrazot za zgolemuvawe ne se izvr{uva se do krajot na preminot niz ciklusot for. Bidej}i break go preskoknuva izrazot za zgolemuvawe, zgolemuvaweto se izveduva direktno vo slu~aj koga i=3. Naredbata continue nadvoresna vo slu~aj koga i ==7 isto taka skoka na vrvot od ciklusot i go preskoknuva zgolemuvaweto, taka {to toa se vr{i direktno. Ako ne postoi naredbata break nadvoresna, bi nemalo na~in da se izleze nadvor od nadvore{niot ciklus od ramkite na vnatre{en ciklus, bidej}i samata naredba break mo`e da go prekine samo najvnatre{niot ciklus. (Istoto va`i i za contiune.) Sekako, vo slu~ai koga izleguvaweto od ciklus isto taka zna~i izleguvawe od metod, mo`ete ednostavno da upotrebite return. Sleduva mal primer na ozna~enite naredbi break i continue so diklusite while:
//: control/OznacenWhile.java // Ciklusot while so oznacena naredba break i oznacena naredba continue. import static net.mindview. util.Print. * ; public class OznacenWhile { public static void main(String [] args) { int i = 0; nadvoresna: while(true) { print(Nadvoresen ciklus while): while(true) { i++; print(i = + i): if(i == 1) { print(prodolzi); continue; } if(i == 3) { print(prodolzi nadvoresen ): continue nadvoresen: } if(i == 5) { print(stopiraj ) :
Kontrolirawe na izvr{uvaweto
139
break; } if(i == 7) { print( stopiraj nadvoresen); break nadvoresna: } } } } /* Rezultat: Nadvoresen ciklus while i = 1 prodolzi i = 2 i = 3 prodolzi nadvoresen Nadvoresen ciklus while i = 4 i = 5 stopiraj Nadvoresen ciklus while i = 6 i = 7 stopiraj nadvoresen * ///:-
Istite pravila se to~ni za while: 1. Obi~nata naredba continue odi do vrvot na tekovniot ciklus i prodol`uva. 2. Ozna~enata naredba Continue odi do oznakata i povtorno vleguva vo ciklusot koj {to se nao|a vedna{ po taa oznaka. 3. break izleguva od ciklusot
4. Ozna~enata naredba break izleguva od ciklusot obele`en so dadena oznaka. Va`no e da se zapomni deka edinstvenata pri~ina za upotreba na oznaki vo Java e koga }e imate vgnezdeni ciklusi i }e sakate da gi prekinete (break) ili prodol`ite (continue) vo pove}e nivoa na vgnezduvawe. Vo ovoj trud Goto se smeta za {teten Dijkstra posebno imal zamerki na upotrebata na oznaki, a ne na samata naredba goto. Zabele`al deka brojot na buba~ki raste so brojot na oznaki vo programata i deka oznakite i goto ja ote`nuvaat analizite na programite. Obratete vnimanie deka oznakite vo Java ne patat od toj problem, bidej}i mestoto na koe mo`at da stojat e ograni~eno i ne mo`at da se koristat za op{t prenos na kontrolata. Treba da se zabele`i deka ova e slu~aj kade nekoja osobina na jazikot stanuva pokorisna koga }e se ograni~at nejzinite mo`nosti. 140 Da se razmisluva vo Java Brus Ekel
Naredbata switch
Naredbata switch ponekoga{ se narekuva naredba za izbor. Taa naredba bira me|u nekolku delovi od kodot vo zavisnost od vrednosta na celobrojniot izraz. Nejzinata osnovna forma e:
switch(izraz) { case vrednost1 : naredba; case vrednost2 : naredba; case vrednost3 : naredba; case vrednost4 : naredba; case vrednost5 : naredba; // ... default : naredba; } break; break; break; break; break;
Izraz e izraz {to ima celobrojna vrednost. Naredbata switch gi sporeduva rezultatot od izraz so sekoja od vrednostite vrednost1-vrednost5. Ako najde sovpa|awe (ekvivalentna vrednost), soodvetnata naredba (edna naredba ili pove}e naredbi, golemite zagradi ne se potrebni) }e se izvr{i. Ako ne pronajde ekvivalentna vrednost, }e se izvr{i naredba ozna~ena kako default. Vo prethodnata definicija }e zabele`ite deka sekoj blok case zavr{uva so break, {to predizvikuva tekot na izvr{uvaweto da gi preskokne ostanatite delovi i da dojde na krajot od teloto na naredbata switch. Ova e voobi~aen na~in za gradewe na naredbata switch, no break ne e zadol`itelen. Ako ne ste go vmetnale, }e se izvr{uvaat slednive case naredbi se dodeka ne se naide na break. Iako voobi~aeno ne sakate toa da se slu~uva, toa sepak mo`e da bide korisno za eden iskusen programer. Obratete vnimanie deka poslednata naredba, po default, nema break bidej}i izvr{uvaweto ednostavno prodol`uva ba{ tamu kade {to vo sekoj slu~aj bi prodol`ilo posle break. Bez nikakvi posledici bi mo`ele da stavite break na krajot od blokot default, ako smetale deka stilski bi izgledalo podobro. Naredbata switch e ~ist na~in za realizacija na pove}epaten izbor (izbirawe me|u pove}e razli~ni pati{ta za izvr{uvawe), no za nea e potreben izraz koj ima vrednost od tipovite kakvi {to se int i char. So naredbata switch ne mo`ete da koristite, kako izraz za izbor, na primer, znakovna niza (string) ili broj vo format na podvi`na zapirka. Za necelobrojni tipovi, morate da koristite niza od if naredbi. Na krajot od slednoto poglavje, }e vidite deka enum, novata karakteristika na Java SES vi pomaga da go olesnite toa ograni~uvawe, bidej}i enum se dizajnirani da rabotat odli~no so switch. Vo sledniot primer slu~ajno se kreiraat bukvi i se odreduva dali tie se soglaski ili samoglaski:
//: control/VowelsAndConsonants.java
Kontrolirawe na izvr{uvaweto
141
// Demonstrates the switch statement. import java.util.*; import static net.mindview.util.Print. * ; public class SamoglaskiISoglaski { public static void main(String [] args) { Random slucaen = new Random(47); for(int i = 0; i < 100: i++) { int c = rand . nextlnt(26) + 'a'; printnb((char)c + , + c + : ): switch(c) { case 'a': case 'e': case 'i': case 'o': case 'u': print(vowel); break; default: print(soglaska); } } } / * Rezultat: y, 121: soglaska n, 110: soglaska z, 122 soglaska b, 98: soglaska r, 114: ponekogas samoglaska n, 110: soglaska y, 121: soglaska g, 103: soglaska c, 99 soglaska f, 102: soglaska o, 111: samoglaska w, 119: soglaska z, 122: consonant ... ///:-
Bidej}i metodot Random.nextInt(26) generira vrednost pome|u 0 i 26, }e treba da dodadete pomestuvawe na bukvite a za da se dobijat malite bukvi. Znakovite vo polunavodnici vo naredbite case isto taka se pretvoraat vo celobrojni vrednosti {to se koristat pri sporedba. Obratete vnimanie na toa deka naredbite case mo`at da se natrupaat edna vrz druga taka {to ist del od kodot se izvr{uva vo pove}e slu~ai. Isto taka treba da vodite smetka da se stavi naredbata break na krajot od opredeleniot slu~aj. Vo sprotivno, kontrolata ednostavno }e se ignorira i programata }e prodol`i ponatamu i }e po~ne da gi izvr{uva naredbite predvideni za sledniot slu~aj. Vo izrazot:
142
Da se razmisluva vo Java
Brus Ekel
metodot Random.nextInt( ) dava slu~aen cel broj me|u 0 do 25, koja se dodava na vrednosta na a. Ova zna~i deka a avtomatski se konvertira vo tip int za da se izvr{i sobiraweto. So cel promenlivata s da se ispi{e kako znak, mora da bide konvertirana vo tip char, bidej}i vo sprotiven slu~aj bi se ispi{uvale broevi kako izlez. Ve`ba 8: (2) Napi{ete naredba switch {to ispi{uva poraka za sekoj slu~aj (case) i stavete go switch vnatre vo ciklusot for {to go ispituva sekoj slu~aj. Stavete naredba break posle sekoj slu~aj i ispitajte ja, a potoa otstranetete gi naredbite break i videte {to }e se slu~i. Ve`ba 9: (4) Fibona~ievata niza e niza od broevi 1, 1, 2, 3, 5, 8, 13, 21, 34 itn. kade sekoj broj (od tretiot pa natamu) e ednakov na zbirot od prethodnite dva. Napi{ete metod {to prima cel broj kako argument i prika`uva to~no tolku Fibona~ievi broevi po~nuvaj}i od po~etokot, na pr. Ako koristite Fibonacci 5 (Kade Fibonacci e imeto na klasata) izlezot }e bide: 1, 1, 2, 3, 5. Ve`ba 10: (5) Vampirski broj ima paren broj na cifri i se formira taka {to se mno`at parovi na broevi {to sodr`at polovina od brojot na cifri od rezultatot. Cifrite se zemaat od pojdovniot broj vo koj bilo redosled. Parovi so zavr{ni nuli ne se dozvoleni. Videte gi primerite: 1260 1827 2187 = 27 * 81 = = 21 21 * * 60 87
Napi{ete programa {to gi nao|a site ~etiricifreni vampirski broevi. (Predlo`eno od Den Forhan.)
Rezime
So ova poglavje zavr{uva prou~uvaweto na osnovnite karakteristiki koi se pojavuvaat vo pove}eto programski jazici: presmetuvawe, prioritet na operator, eksplicitna konverzija me|u tipovi, kako i izbor i povtoruvawe (ciklus). Sega ste podgotveni za da zapo~nete da odite po patot {to }e ve pribli`i do svetot na objektno-orientiranoto programirawe. Slednoto poglavje }e gi obraboti va`nite pra{awa na inicijalizacija i ~istewe na objekti, a vo poglavjeto posle nego }e bide razgledan konceptot na sokrivawe na realizacijata.
Kontrolirawe na izvr{uvaweto
143
Re{enijata za desette ve`bi mo`e da se najdat vo elektronskiot dokument The Thinking in Java Annotaed Solution Guide, dostapni za proda`ba na sajtot www.MindView.net.
144
Da se razmisluva vo Java
Brus Ekel
Inicijalizacija i ~istewe
Kako {to napreduva kompjuterskata revolucija, nesigurnoto programirawe stana edna od glavnite pri~ini za visokata cena na programiraweto.
Dve bitni oblasti na sigurnost se inicijalizacija i ~istewe. Mnogu gre{ki vo S se slu~uvaat koga programerot }e zaboravi da inicijalizira promenliva. Ova posebno va`i za bibliotekite koga korisnicite ne znaat kako da inicijaliziraat komponenta od biblioteka, pa duri i ne znaat deka e toa potrebno. ^isteweto e poseben problem bidej}i lesno e da se zaboravi elementot otkako }e zavr{ite rabota so nego, bidej}i pove}e ne Ve interesira, {to e i prili~no normalno. Zatoa, resursite {to bile koristeni od toj element se zadr`uvaat i mo`ete mnogu lesno da ostanete bez resursi, (naj~esto memorija). S++ go vovede konceptot na konstruktor, specijalen metod koj avtomatski se povikuva pri sozdavawe objekt. Java isto taka gi usvoi konstruktorite, a pokraj toa ima i svoj sobira~ na otpadoci {to avtomatski gi osloboduva memoriskite resursi koga tie pove}e nema da se koristat. Vo ova poglavje se razgleduvaat pra{awata na inicijalizacija i ~istewe i na~inot na koj se poddr`ani vo Java.
Inicijalizacija i ~istewe
145
isto taka se koristi i vo Java: imeto na konstruktorot e isto so imeto na klasata. Mnogu logi~no e takov metod avtomatski da bide povikan vo tekot na inicijalizacijata. Sleduva primer za ednostavna klasa so konstruktor:
//: initialization/EdnostavenKonstruktor.java // Prezentacija na ednostaven konstruktor . class Kamen { Kamen() { // Ova e konstruktorot System.out.pr int(Kamen ): } } public class EdnostavenKonstruktor { public static void main(String [] args) { for (int i = 0; i < 10; i++) new Rock (); } } /* Rezultat: Kamen Kamen Kamen Kamen Kamen Kamen Kamen Kamen Kamen Kamen * ///:-
se zazema memorijata i se povikuva konstruktorot. Se garantira deka objektot }e bide pravilno inicijaliziran pred da bide upotreben. Obratete vnimanie deka stilot na pi{uvawe, spored koj prvata bukva od imiwata na site metodi se pi{uva so mali bukvi, ne se odnesuva na konstruktorite, bidej}i imeto na konstruktorot mora to~no da se sovpa|a so imeto na klasata. Konstruktor koj ne prima argumenti se narekuva podrazbiran konstruktor. Vo pogolemiot del od literaturata za Java {to ja izdade Sun, se narekuvaat konstruktori bez argumenti (angliski: no-arg constructors). Terminot podrazbiran konstruktor se upotrebuva podolg vremenski period niz godinite, pa i jas }e go koristam isto taka. No kako i sekoj drug metod, konstruktorot mo`e da ima argumenti koi ovozmo`uvaat da odredite kako eden objekt }e se kreira. Prethodniot primer mo`e lesno da se promeni taka {to konstruktorot nema da ima eden argument:
//: inicijalizacija/EdnostavenKonstruktor2.java // Konstruktorite mozat da imaat argumenti. class Kamen2 { Kamen2(int i) { System.out.print(Kamen + i + ); } }
146
Da se razmisluva vo Java
Brus Ekel
public class EdnostavenKonstruktor2 { public static void main(String [] args) { for(int i = 0; i < 8: i++) new Kamen2(i): } } /* Rezultat: Kamen 0 Kamen 1 Kamen 2 Kamen 3 Kamen 4 Kamen 5 Kamen 6 Kamen 7 * ///:-
Argumentite na konstruktorot ovozmo`uvaat da obezbedite parametri za inicijalizacijata na eden objekt. Na primer, ako klasata Drvo ima konstruktor {to prima eden celobroen argument koj ja odreduva viso~inata na drvoto, objektot Drvo, }e go napravite na ovoj na~in:
Drvo d = new Drvo(12); // drvo od 12 metri
Ako Drvo(int) e Va{iot edinstven konstruktor, toga{ preveduva~ot nema da vi dozvoli da kreirate objekt Drvo na koj bilo drug na~in. Konstruktorite eliminiraat edna golema klasa na problemi i gi pravat programite porazbirlivi. Vo prethodniot primer ne postoi ekspliciten povik kon nekoj metod initialize( ) {to e konceptualno razdelen od praveweto objekti. Vo Java, praveweto objekt i negovata inicijalizacija se obedineti koncepti - ednoto bez drugoto ne odat. Konstruktorot e neobi~en tip na metod bidej}i nema povratna vrednost. Ova e sosem razli~no od povratnata vrednost od tip void, vo koja metodot ne vra}a ni{to, no i ponatamu imate mo`nost da go naterate da vrati ne{to drugo.Konstruktorite ne vra}aat ni{to, a i nemate nikakva druga mo`nost (izrazot new vra}a referenca na novonapraveniot objekt, no samiot konstruktor ne vra}a ni{to). Ako bi postoela povratna vrednost i bi mo`ele da ja izberete, preveduva~ot bi moral da znae {to da pravi so taa povratna vrednost. Ve`ba 1: (1) Napravete klasa {to sodr`i neinicijalizirana String referenca. Poka`ete deka Java ja inicijalizira ovaa referenca so vrednosta null. Ve`ba 2: (2) Napravete klasa so pole String {to se inicijalizira na mestoto na definirawe i druga klasa koja se inicijalizira od konstruktor. Koja e razlikata me|u dvata pristapa?
Preklopuvawe na metodi
Edno od va`nite svojstva vo sekoj programski jazik e upotrebata na imiwa. Koga sozdavate objekt, i davate ime na oblasta od memorijata. Metodot e ime na nekoja akcija. Na site objekti i metodi im se obra}ate preku imiwa. Dobro izbranite imiwa sozdavaat sistem {to za lu|eto e polesen za
Inicijalizacija i ~istewe
147
razbirawe i menuvawe. Toa mnogu li~i na pi{uvawe na proza, celta e da se dobli`ite do ~itatelite, da vospostavite vrska so niv.
Problemot se pojavuva koga nijansite od ~ove~kiot jazik se preslikuvaat vo programskiot jazik. ^esto, istiot zbor ima pove}e razli~ni zna~ewa - toj e preklopen (angliski overloaded). Ova e korisno, osobeno koa stanuva zbor za osnovni razliki vo zna~eweto. Velite, Isperi ja maicata, Isperi ja kolata, Isperi go ku~eto. Mnogu bi bilo sme{no da bidete prisileni da ka`ete, Maicata isperi ja vo ma{inata za perewe, Kolata isperi ja so crevo, Ku~eto isperi go vo kadata, samo za slu{atelot da napravi razlika za akcijata {to se izveduva. Pove}eto ~ove~ki jazici se redundantni, pa i ako ispu{tite nekolku zborovi, sepak mo`ete da go odredite ili dolovite zna~eweto. Ne vi trebaat edinstveni identifikatori - mo`ete da go dolovite zna~eweto od samiot kontekst. Pove}eto programski jazici (posebno S) baraat od vas da imate edinstven identifikator za sekoj metod (vo tie jazici ~esto nare~eni funkcii) . Taka ne bi mo`ele da imate edna funkcija nare~ena print( ) za ispi{uvawe na celi broevi i druga nare~ena print( ) za ispi{uvawe na broevi vo format na podvi`na zapirka bidej}i sekoja funkcija mora da ima edinstveno ime. Vo Java (i S++), postoi drug faktor koj go nametnuva preklopuvaweto na imiwata na metodite: konstruktorot. Bidej}i imeto na konstruktorot e odnapred odredeno u{te so imeto na klasata, konstruktorot mo`e da go ima samo toa edno ime. No {to ako sakate da sozdadete objekt na pove}e na~ini? Na primer, da pretpostavime deka gradite klasa {to mo`e da se inicijalizira samata na standarden na~in ili so ~itawe na informacija od datoteka. ]e vi bidat potrebni dva konstruktora, podrazbiraniot konstruktor i u{te eden konstruktor ~ij argument e od tipot String, {to e imeto na datotekata od koja treba da se inicijalizira objektot. Dvata se konstruktori, pa moraat da imaat isto ime - imeto na klasata. Ottuka, preklopuvaweto na metodite e su{tinski zna~ajno vo Java bidej}i ovozmo`uva istoto ime na metodot da se koristi so razli~ni tipovi na argumenti. Iako preklopuvaweto na metodite e neophodno za konstruktorite, toa e op{ta pogodnost dostapna za koj bilo metod. Eve primer {to gi poka`uva preklopenite konstruktori i preklopenite metodi:
//: inicijaliziacija//Preklopuvanje.java // Demonstracija preklopuvanje na konstruktori // i preklopuvanje na obicni metodi . import static net.mindview.util.Print.*: class Drvo { int visina:
148
Da se razmisluva vo Java
Brus Ekel
Drvo() { print(Sadenje na drvca); visina = 0: } Drvo (int pocetnaVisina) { visina = pocetnaVisina: print(Pravime novo Drvo koe e visoko + visina + m): } void info() { print(Drvoto e visoko + + visina + m); } void info(String s) print(s + : Drvoto e visoko + visina + m); } public class Preklopuvanje { public static void main(String [] args) { for(int i = 0; i < 5; i++) { Drvo d = new Drvo(i); d.info(): d.info(preklopen metod): } // Preklopen konstruktor: new Drvo(); } } / * Rezultat: Pravime novo Drvo koe e visoko 0 m Drvoto e visoko 0 m preklopen metod: Drvoto e visoko 0 m Pravime novo Drvo koe e visoko 1 m Drvoto e visoko 1 m preklopen metod: Drvoto e visoko 1 m Pravime novo Drvo koe e visoko 2 m Drvoto e visoko 2 m preklopen metod: Drvoto e visoko 2 m Pravime novo Drvo koe e visoko 3 m Drvoto e visoko 3 m preklopen metod: Drvoto e visoko 3 m Pravime novo Drvo koe e visoko 4 m Drvoto e visoko 4 m preklopen metod: Drvoto e visoko 4 m Sadenje ne drvca * ///:-
Objektot od klasa Drvo mo`e da se sozdade ili kako sadnica, bez argumenti ili kako rastenie odgledano vo oran`erija (rasadnik), so dadena viso~ina. Za da se ovozmo`i ova, postojat dva konstruktora, edniot bez argumenti
Inicijalizacija i ~istewe
149
(podrazbiraniot konstruktor) i vtoriot ~ij argument e postoe~kata viso~ina. Mo`e da Vi zatreba da go povikate metodot info( ) na pove}e na~ini. Na primer, ako sakate da ispi{ete u{te nekoja poraka, mo`ete da go koristite metodot info(String), a ako nemate {to pove}e da ka`ete go koristite metodot info( ). Bi bilo neobi~no ako dadete dve oddelni imiwa na ne{to {to o~igledno ima ist koncept. Za sre}a, preklopuvaweto na metodite vi dozvoluva da koristite isti imiwa za dvete raboti.
Dvata metoda f( ) imaat identi~ni argumenti, no nivniot redosled e razli~en i toa gi pravi razli~ni.
150
Da se razmisluva vo Java
Brus Ekel
void f5(long x) { printnb(f5(long) ) ; } void f5(float x) { printnb(f5(float) ) ; } void f5 (double x) { printnb(f5(double) ) ; void f6(float x) { printnb(f6(float) ) ; } void f6(double x) { printnb(f6(double) ) ; } void f7(double x) { printnb(f7(double) ) ; } void testKonstanta(){ printnb(5: ); fl(5);f2(5);f3(5);f4(5);f5(5) ;f6(5);f7(5); print(); }
Inicijalizacija i ~istewe
151
void testChar() { char x = 'x'; printnb(char: ); fl(,);f2(,);f3(,);f4(,);15 (,);16(,);f7(,); print(); } void testByte() { byte x = 0; printnb(byte: ); fl(x);f2(x);f3(x);f4(x);f5(x) ;f6(x);f7(x ); print(); } void test5hort() { short x = 0; printnb(short: ); f1(x) ;f2(x) ;f3(x);f4(x) ;f5(x) ;f6(x );f7(x) ; print(); } void testint() { intx=0; printnb(int: ); f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x); print(); } void testlong() { long x =0; printnb(long: ); f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x); printO; } void testFloat() { float x = 0; printnb(float: ); f1 (x) ; fl (x) ; f3 (x) ; f4 (x); f5 (x); f6(x); f7 (x); print 0 ; } void testDouble() { double x = 0; printnb(double: ); f1(x); fl(x); f3(x) ;f4 (x); f5(x); f6 (x); f7(x); printo; } public static void main(String [] args) { PreklopuvanjeNaProstiTipovi p = new PrimitiveOverloading(); p.testConstVal(): p.testChar(): p.testByte(); p.testShort(); p.testInt () :
152
Da se razmisluva vo Java
Brus Ekel
p.testLong(): p.testFloat(): p.testDouble(): } } / * Rezultat: 5: f1(int) f2(int) f3(int) f4(int) f5(long) f6(float) f7(double) char: fl(char) f2(int) f3(int) f4(int) f5(long) f6(float) f7 (double) byte: fl(byte) f2(byte) f3 ( short) f 4 (int) f5(long) f6(float) f7(double) short: f1(short) f2(short) f3(short) f4(int) f5(long) f6(float) f7(double) int: f1(int) f2(int) f3(int) f4(int) f5(long) f6(float) f7(double) long: f1(long) f2(long) f3(long) f4(long) f5(long) f6(float) f7(double) float: fl(float) f2(float) f3(float) f4(float) f5(float) f6(float) f7(double) double: fl(double) f2(double) f3(double) f4(double) f5(double) f 6(double) f7(double) * ///:-
Obratete vnimanie deka konstantata 5 se tretira kako vrednost od tip int, pa ako e dostapen, se povikuva preklopen metod ~ij argument e od tipot int. Vo site drugi slu~ai, ako imate tip na podatok {to e pomal od argumentot vo metodot, toga{ tipot na podatok se pro{iruva. Kodot od tip char dava malku poinakov efekt, bidej}i ako ne najde to~no poklopuvawe od tipot char, toj se pro{iruva vo int. [to se slu~uva ako va{iot argument e pogolem od argumentot koj se o~ekuva vo preklopeniot metod? Odgovorot go dava modifikacijata od prethodnata programa:
//: inicijalizacija/Degradiranje. java // Degradiranje na prostite tipovi i preklopuvanje. import static net.mindview.util.Print.*: public class Degradiranje { void fl(char x) { print(fl(char)); void fl(byte x) { print(fl(byte)); } void fl(short x) ( print(fl(short)); } void fl(int x) { print(fl(int)): } void fl(long x) { print(fl(long)); } void fl(float x) { print( f l(float)): } void fl(double x) { print(fl(double)); } void void void void f2(char x) ( print(f2(char)): } f2(byte x) ( print(f2(byte)); } f2(short x) { print(f2(short)): 12(int x) { print(f2(int)); }
Inicijalizacija i ~istewe
153
void f2(long x) { print(f2(long)); } void f2(float x) { print(f2(float)): void void void void void void void void void f3(char x) { print(f3(char)); } f3(byte x) { print(f3(byte) ); } f3(short x) ( print( f3(short)); } f3(int x) { print(f3(int)); } f3(long x) { print(f3(long)): } f4(char x) print(f4(char)): f4(byte x) { print(f4(byte)): } f4(short x) { print(f4(short)); } f4(int x) { print(f4(int)); }
void f5(char x) ( print(f5(char)); } void f5(byte x) ( print(f5(byte)); } void f5(short x) ( print(f5(short)) ; } void f6(char x) ( print(f6(char)) ; } void f6(byte x) ( print(f6(byte)) ; void f7(char x) print(f7(char)): } void testDouble() { double x = 0; print(argument od tipot double:); f1(x) ;f2(float)x);f3((long)x) :f4(int)x): f5(( short) x) : f6 ( (byte) x) : f7 ((char) x) ; } public static void main(String [] args) { Degradiranje p = new Degradiranje(); p. testDouble(); } } /* Rezultat: argument od tipot double: fl(double) f2(float) f3 (long) f4(int) f5(short) f6(byte) f7(char) *///: -
Vo ovoj slu~aj metodite zemaat stesneti vrednosti od prost tip. Ako va{iot argument e po{irok, }e morate eksplicitno da go konvertirate vo potrebniot tip. Dokolku ne napravite vaka, preveduva~ot }e prijavi gre{ka.
154
Da se razmisluva vo Java
Brus Ekel
Ova dobro raboti s dodeka preveduva~ot nedvosmisleno }e odredi zna~eweto od kontekstot, kako vo int x = f( ). Sepak, mo`ete isto taka da povikate metod i da ja ignorirate povratnata vrednost. Ova ~esto se narekuva povikuvawe na metod poradi negoviot sporeden efekt, bidej}i ne se gri`ite za povratnata vrednost, tuku namesto Vi trebaat drugi efekti pri povikot na metodot. Pa, ako go povikate metodot na sledniov na~in:
f();
kako mo`e Java da odredi koj metod f( ) treba da se povika? I kako nekoj {to go ~ita kodot bi mo`el toa da go vidi? Kako rezultat na ovoj tip na problem, ne mo`ete da koristite tipovi na povratni vrednosti za da razlikuvate preklopeni metodi.
Podrazbirani konstruktori
Kako {to spomenavme prethodno, podrazbiran konstruktor (isto taka nare~en no-arg konstruktor) e onoj koj nema argumenti, a se koristi za kreirawe na podrazbirani objekti. Ako sozdadete klasa {to nema konstruktori, preveduva~ot avtomatski, namesto Vas, }e go napravi podrazbiraniot konstruktor. Na primer:
//: inicijalizacija/PodrazbiranKonstruktor.java class Ptica {} public class PodrazbiranKonstruktor { public static void main(String [] args) { Ptica p = new Ptica(): // Podrazbiran! } } ///:-
Izrazot
new Ptica();
sozdava nov objekt i go povikuva podrazbiraniot konstruktor, iako konstruktorot porano ne e eksplicitno definiran. Bez nego, ne bi postoel nieden metod koj bi mo`ele da go povikate za da go napravite objektot. Inicijalizacija i ~istewe 155
Sepak, ako definirate kakov bilo konstruktor (so ili bez argumenti), preveduva~ot nema namesto Vas da go napravi podrazbiraniot konstruktor:
//: inicijalizacija/NemaSinteza.java class Ptica2 { Ptica2(int i) {} Ptica2(double d) {} } public class NemaSinteza { public static void main(String [] args) { //! Ptica 2 p = new Ptica (): // Nema podrazbiran konstruktor Ptica 2 p2 = new Bi rd2 (1): Ptica 2 p3 = new Bird2(1.0): } }///
preveduva~ot }e se po`ali deka ne mo`e da go najde soodvetniot konstruktor. Toa e kako da ne ste napravile nitu eden konstruktor, pa preveduva~ot }e ka`e: Morate da imate nekakov konstruktor, pa zatoa, dozvolete mi mene da Vi napravam eden. No ako ste napi{ale konstruktor preveduva~ot veli: Napi{avte kontstruktor, zna~i znaete {to rabotite; ako ne ste go stavile kako podrazbiran, namerno ste sakale da go izostavite. Ve`ba 3: (1) Napravete klasa so podrazbiran konstruktor (onoj koj ne prima argumenti) koj ispi{uva nekoja poraka. Napravete i objekt od ovaa klasa. Ve`ba 4: (1) Na prethodnata ve`ba dodadete preklopen konstruktor {to prima eden String argument i go ispi{uva zaedno so va{ata poraka. Ve`ba 5: (2) Napravete klasa nare~ena Kuce so preklopen metod lae( ). Ovoj metod bi trebalo da e preklopen vrz baza na razli~ni prosti tipovi na podatoci i da ispi{uva razli~nite tipovi na laewe, zavivawe itn., vo zavisnost od toa koja preklopena verzija se povikuva. Napi{ete metod main( ) {to gi povikuva site tie razli~ni verzii. Ve`ba 6: (1) Modificirajte ja prethodnata ve`ba taka {to dva od preklopenite metodi primaat po dva argumenta (od dva razli~ni tipovi), no vo obraten redosled relativno eden na drug. Uverete se deka ova raboti. Ve`ba 7: (1) Napravete klasa bez konstruktor, a potoa kreirajte objekt od taa klasa vo metodot main( ) za da se uverite deka podrazbiraniot konstruktor avtomatski se sintetizira.
156
Da se razmisluva vo Java
Brus Ekel
Ako postoi samo eden metod nare~ena izlupi( ), kako mo`e toj metod da znae dali se povikuva za objektot a ili za objektot b? Za da vi dozvoli pi{uvawe na kod vo prakti~na objektno orientirana sintaksa pri {to pra}ate poraka do objekt, preveduva~ot pravi nekolku tajni raboti za vas. Postoi taen prv argument koj se prosleduva do metodot izlupi( ), i toj argument e referencata na objektot so koj se rakuva. Pa, dvata povika za metodot po~nuvaat da stanuvaat vakvi:
Banana.izlupi (a, 1); Banana.izlupi (b, 2);
Ova se samo interni izrazi i ne mo`ete da gi napi{ete niv i da go naterate preveduva~ot da gi prifati, no toj }e Vi dade ideja za toa {to se slu~uva. Da pretpostavime deka se nao|ate vnatre vo metodot i deka sakate da ja koristite referencata na tekovniot objekt. Bidej}i referencata tajno e prosledena od strana na preveduva~ot, za nea ne postoi identifikator. Sepak, za ovaa namena postoi rezerviran zbor: this. Rezerviraniot zbor this koj mo`e da se koristi samo vnatre vo metod koj ne e od tipot static - ja vra}a referencata na objektot za koj toj metod bil povikan. Ovaa referenca mo`ete da ja koristite kako i sekoja druga referenca na objekt. Imajte na um deka ako povikuvate metod od va{ata klasa od nekoj drug metod od istata klasa, nema da imate potreba od koristewe na rezerviraniot zbor this. Mo`ete ednostavno da go povikate metodot. Momentalnata referenca this avtomatski se koristi i za drugiot metod. Ottuka, mo`ete da napi{ete:
//: inicijalizacija/Kajsija.java public class Kajsija { void iscisti() { / * ... */ void koska() { iscisti(); / * */ }
Inicijalizacija i ~istewe
157
} ///:-
Vnatre vo metodot koska( ), bi mo`ele da napi{ete this.iscisti( ), no nemate potreba od toa.1 Preveduva~ot avtomatski go pravi toa namesto vas. Rezerviraniot zbor this se koristi samo za specijalni slu~ai vo koi }e treba eksplicitno da ja iskoristite referencata za tekovniot objekt. Na primer, toj ~esto se koristi vo naredbite return koga sakate da ja vratite referencata na tekovniot objekt:
//: inicijalizacija/List.java // Ednostavna upotreba na rezerviraniot zbor this. public class List { int i = 0; List prelistaj() { i++; return this; } void print() { System.out.println(i = + i); } public static void main(String [] args) List x = new List(); x.prelistaj(),prelistaj (),prelistaj (),pecati(); } Rezultat:
} /* i = 3 * ///:-
Bidej}i metodot prelistaj( ) ja vra}a referencata na tekovniot objekt preku ovoj rezerviran zbor, mo`e da se izvr{at pove}e operacii nad istiot objekt. Rezerviraniot zbor this isto taka se koristi za prosleduvawe na tekovniot objekt na drug vo drug metod:
//: inicijalizacija/ProslediSoPomosNaThis.java class Licnost { public void jadi (Jabolko jabolko) { Jabolko izlupena = jabolko.seLupi(); System.out.println(Mjam) ; } } class Lupac { static Jabolko lupi(Jabolko jabolko) { // ... otstrani luspa return jabolko: // Izlupena }
158
Da se razmisluva vo Java
Brus Ekel
class Jabolko { jabolko seLupi() { return Lupac.lupi(thi s ); } public class PassingThis ( public static void main(String [] args) ( new Licnost().jadi(new Jabolko()); } } /* Rezultat: Mjam *///: -
1. Na nekoi lu|e kako opsednati }e pi{uvaat this pred sekoj povik za metod i sekoja referenca za pole, obrazlo`uvaj}i dekago pravi kodot pojasen i poekspliciten. Nemojte da go pravite toa. Ima pri~ina za{to koristime jazici od visoko nivo: tie gi pravat rabotite za nas. Ako napi{ete this koga toj rezerviran zbor e nepotreben, }e gi zbunite i nalutite site {to }e go ~itaat va{iot kod, bidej}i vo ostatokot od kodot {to }e go pro~itaat ne se koristi this. Lu|eto normalno o~ekuvaat this da se koristi samo onamu kade {to e neophoden. Sledej}i dosleden i ednostaven stil na kodirawe }e za{tedite mnogu vreme i pari.
Jabolko mora da go povika Lupac.lupi( ), nadvore{en uslu`en metod {to izveduva operacija, koja poradi nekoja pri~ina mora da bide nadvore{na za objektot Jabolko (Mo`ebi nadvore{niot metod mo`e da se primeni na pove}e razli~ni klasi, a Vie ne sakate da go povtoruvate kodot). Za da go prosledite do nadvore{en metod, morate da go koristite rezerviraniot zbor this. Ve`ba 8: (1) Napravete klasa so dva metoda. Vo ramkite na prviot metod, povikajte go vtoriot metod dva pati. Prviot pat bez koristewe na this, a vtoriot so pomo{ na this - samo za da vidite kako funkcionira: inaku ne bi trebale da ja koristite ovaa forma vo praksa.
Inicijalizacija i ~istewe
159
preklopeniot konstruktor so soodvetnata lista na argumenti. Ottuka, imate mnogu direkten na~in da gi povikate ostanatite konstruktori:
//: inicijalizacija/Cvet.java // Povikuvanje na konstruktor so pomos na rezerviraniot zbor this import static net.mindview.util.Print.*; public class Flower { int brojNaListovi = 0: String s = poceten broj: Flower(int petals) { BrojNaListovi = listovi; print(Konstruktorot samo brojNaListovi= + brojNaListovi): }
so
argumenti
od
tipot
int,
Flower(String ss) { print(Konstruktorot samo so argumenti od tipot String. s = + ss): s = ss: } Flower(String s, int listovi) { this(listovi) : //! this(s); // Ne mozete da povikate dva konstruktori! this.s = s: // Uste edna upotreba na rezerviraniot zbor this print(Argumenti od tipot String i int): } Flower () { this(zdravo.47); print(podrazbirliv konstruktor (bez argumenti)): } void pecatiBrojNaListovi() { //! this(ll): // Ne moze nadvor od konstruktorot! print(BrojNaListovi = + BrojNaListovi + 5 = + 5): } public static void main(String [] args) Flower x = new Flower(): x.printPetalCount(): } } /* Rezultat: Konstruktor samo so argumenti od tipot int, Argumenti od tipot String i int podrazbirliv konstruktor (bez argumenti) brojNaListovi = 47 s = zdravo * ///:-
BrojNaListovi = 47
160
Da se razmisluva vo Java
Brus Ekel
Konstruktorot Flower(String s, int listovi) poka`uva deka so koristewe na rezerviraniot zbor this mo`ete da povikate eden konstruktor, no ne mo`ete da povikate dva. Isto taka, povikot kon konstruktorot mora da bide prvoto ne{to {to }e go napravite, bidej}i vo sprotivno preveduva~ot }e javi poraka za gre{ka. Prethodniot primer isto taka poka`uva u{te eden na~in na upotreba na rezerviraniot zbor this. Bidej}i imeto na argumentot s i imeto podatokot na ~lenot s se isti, postoi dvosmislenost. Mo`ete da go re{ite ovoj problem so koristewe na this.s za da ka`ete deka se obra}ate na podatokot na ~lenot. ^esto }e ja vidite ovaa forma kako se koristi vo kodovite na Java, a isto taka ~esto se koristi i vo ovaa kniga. Vo metodot pecatiBrojNaListovi( ) mo`ete da vidite deka preveduva~ot nema da vi dozvoli da povikate konstruktor od koj bilo metod osven od drug konstruktor. Ve`ba 9: (1) Napravete klasa so dva (preklopeni) konstruktori. Koristej}i ja klasata, od prviot konstruktor so pomo{ na this povikajte go vtoriot konstruktor.
Inicijalizacija i ~istewe
161
preku referencata (koja vo toj slu~aj efektivno e this), mo`ete da povikuvate nestati~ni metodi i da imate pristap kon nestati~ni poliwa. Sepak, ako sakate da pravite takvo ne{to, }e napravite samo obi~en, nestati~en metod.
162
Da se razmisluva vo Java
Brus Ekel
deka vo procesot na kreirawe, Va{iot objekt samiot se iscrtuva na ekranot. Ako eksplicitno ne ja izbri{ete negovata slika od ekranot, postoi {ansa taa slika nikoga{ da ne bide otstraneta. Ako vmetnete nekoj vid bri{ewe vo metodot finalize( ), a objektot e sobran od strana na sobira~ot na otpadoci i e povikan metodot finalize( ) (za {to nema garancija deka }e se slu~i), toga{ slikata najprvin }e se otstrani od ekranot, no ako toa ne se slu~i, odnosno ako sobira~ot na otpadoci ne re{i da go is~isti Va{iot objekt, slikata }e ostane na ekranot. Mo`e da se slu~i prostorot {to go zazema Va{iot objekt nikoga{ da ne bide osloboden bidej}i Va{ata programa nikoga{ nema da stigne do taa to~ka koga }e snema memorija. Ako Va{ata programa zavr{i i sobira~ot na otpadoci nikoga{ nemal prilika da ja oslobodi prostor koj {to go zazemal koj bilo Va{ objekt, celokupniot prostor odedna{ }e mu bide vraten na operativniot sistem pri izleguvaweto od programata. Ova e dobra rabota bidej}i sobiraweto na otpadocite ~ini dosta, pa ako nikoga{ ne go izvedete, nikoga{ nema da ja po~uvstvuvate negovata cena.
Se ispostavuva deka metodot finalize( ) postoi kako rezultat na mo`nosta deka memorijata }e ja zazemete koristej}i nekoj mehanizam sli~en na onoj vo jazikot S namesto na voobi~aen na~in vo Java. Ova povikuvawe prvenstveno se slu~uva preku lokalnite metodi (angliski native metods), koi pretstavuvaat na~in od Java da povikate nekoj drug lokalen kod (kod koj ne
Inicijalizacija i ~istewe
163
pripa|a na Java). (Lokalnite metodi se razgleduvaat vo Dodatok B vo vtoroto elektronsko izdanie na knigava, dostapno na www.MindView.net.) S i S++ se edinstvenite jazici koi momentalno se podr`ani od lokalni metodi, no bidej}i tie mo`at da povikaat potprogrami vo drugi jazici, vsu{nost mo`ete da povikate {to bilo. Vnatre vo kodot koj ne pripa|a na Java, memorijata mo`e da se zazeme so nekoja funkcija od familijata funkcii vo S malloc( ). Ako ne povikate soodvetna funkcija free( ), prostorot nema da se oslobodi, predizvikuvaj}i istekuvawe na memorija. Sekako, free( ) e funkcija na jazicite S i S++, pa nema da imate potreba da ja povikate preku nekoj lokalen metod od Va{iot metod finalize( ). Otkako go pro~itavte ova, verojatno razbravte deka nema ~esto da go koristite metodot finalize( ).3 Vo pravo ste: toj ne e prikladno mesto na koe se vr{i voobi~aenoto ~istewe. Pa, kade toga{ toa bi trebalo toa da se pravi?
164
Da se razmisluva vo Java
Brus Ekel
Zapomnete deka deka ne se garantirani nitu sobiraweto na otpadoci nitu finalizacijata. Ako JVM ne e blisku do ostanuvawe bez memorija, toga{ toj ne bi trebalo da tro{i vreme na osloboduvawe na memorijata preku sobirawe na otpadoci .
3 Xo{ua Bloh odi u{te podaleku vo delot nare~en Izbegnuvajte go koristeweto na zavr{nite metodi - finalizatori: Finalizatorite se nepredvidlivi, ~estopati opasni i po pravilo nepotrebni. Efikasno programirawe so Java, str 20 (Addison Wesley, 2001)
Sostojba na prestanuvawe
Generalno, ne mo`ete da se potprete na povikuvawe na metodot finalize( ), tuku isto taka morate da napravite oddelni metodi za ~istewe i da gi povikate eksplicitno. Zatoa se ~ini deka metodot finalize( ) e korisen samo za osloboduvawe na memorijata koja {to pogolemiot del od programerite nikoga{ pove}e nema da ja koristat. Sepak, postoi edna mnogu interesna primena na metodot finalize( ) {to ne se potpira na toa deka toj sekojpat }e bide povikuvan. Ova e proverka na postoeweto na sostojba na prestanuvawe (angliski -termination condition)4 na nekoj objekt. Od momentot koga pove}e nema da bidete zainteresirani za objektot - koga toj }e bide podgotven za ~istewe - toj objekt treba da bide vo sostojba vo koja negovata memorija bi mo`ela bezbedno da se oslobodi. Na primer, ako objektot pretstavuva otvorena datoteka, taa datoteka bi trebalo da bide zatvorena od strana na programerot pred objektot da bide is~isten od strana na sobira~ot na otpadoci. Ako bilo koj del od objektot ne se is~isti pravilno, toga{ }e imate gre{ka vo va{ata programa {to }e bide mnogu te{ka za otkrivawe. Metodot finalize( ) e zna~aen bidej}i mo`e da se iskoristi za otkrivawe na vakvi slu~ai, duri i ako ne se povikuva sekoga{. Ako nekoja finalizacija ja otkrie gre{kata, toga{ vie }e go otkriete problemot, {to Vas, vsu{nost, edinstveno i Ve zagri`uva. Eve ednostaven primer kako da go iskoristite toa:
//: inicijalizacija/UslovZaUnistuvanje.java // Otkrivanje na objekt koj ne bil pravilno iscisten // so pomos na metodot finalize(). class Kniga { boolean pozajmena = false; Book(boolean p2) { pozajmena = p2; } void checkln{) { pozajmena = false;
Inicijalizacija i ~istewe
165
} protected void finalize() { if (pozajmena) { System.out.println{Greska: knigata ne e vratena); // Normalno bi go napravile slednovo: // super.finalize(): // Povik na verzijata na osnovnata klasa } } } public class UslovZaUnistuvanje { public static void main(String [] args) { Kniga roman = new Kniga(true): // Soodvetno: roman,vrati(); // Ispusti ja referencata, zaboravi da ja iscistis new Kniga(true); // Baraj sobiranje na otpadoci i finalizacija System.gc(); } } ///* Rezultat: Greska: Knigata ne e vratena * ///:-
Site pozajmeni knigi vo sostojba na prestanuvawe mora da bidat provereni i vrateni pred da bidat sobraniod strana na sobira~ot na otpadoci, no mo`e da se slu~i vo main( ), programerot po gre{ka da ne vrati edna od tie knigi. Bez metodot finalize( ) koj ja proveruva sostojbata na prestanuvawe, ova mo`e da pretstavuva gre{ka koja te{ko se otkriva. Obratete vnimanie deka System( ) se koristi za barawe na ~istewe. No duri i ako ne se iskoristi, dosta verojatno e deka zalutanata kniga }e se otkrie pri nekolku povtorni izvr{uvawa na programata (pod pretpostavka deka programata zazema dovolno memorija za da se pokrene sobira~ot na otpadoci). Po pravilo, bi trebalo da pretpostavite deka i verzijata finalize( ) vo osnovnata klasa ima va`na rabota i da ja povikate so koristewe na rezerviraniot zbor super, kako {to gledate Kniga.Finalize( ). Vo ovoj slu~aj, toj red se pretvora vo komentar zatoa {to bara prerabotka na isklu~ocite, koi u{te ne sme gi razgledale. Ve`ba 10: (2) Napravete klasa so metodot finalize( ) koja ispi{uva nekoja poraka. Vo metodot main( ), napravete objekt od Va{ata klasa. Objasnete go odnesuvaweto na Va{ata programa.
166
Da se razmisluva vo Java
Brus Ekel
Ve`ba 11: (4) Modificirajte ja prethodnata ve`ba taka {to Va{iot metod finalize( ) sekoga{ }e se povikuva.
Ve`ba 12: (4) Napravete klasa Rezervoar {to mo`e da se polni i da se prazni i koja ima takva sostojba na prestanuvawe {to mora da bide prazna pri ~isteweto na objektot. Napi{ete metod finalize( ) {to ja proveruva sostojbata na prestanuvawe. Vo metodot main( ), ispitajte gi mo`nite scenarija {to mo`e da se odigraat pri upotrebata na klasata Rezervoar.
Inicijalizacija i ~istewe
167
dinami~kata memorija se pomestuva poblisku do po~etokot na podvi`nata lenta i podaleku od krajot na stranicata. Sobira~ot na otpadoci gi reorganizira rabotite i ovozmo`uva za dodeluvawe na prostor da se koristi modelot na brza dinami~ka memorija so beskone~na dol`ina. Za da razberete kako funkcionira sobiraweto na otpadoci vo Java, od va`nost e da nau~ite kako rabotat sobira~ite na otpadoci vo drugite sistemi. Pri nivnata rabota se koristi ednostavna no bavna tehnika za sobirawe na otpadoci, koja se narekuva broewe na referencite. Ova zna~i deka sekoj objekt sodr`i broja~ na referenci i toj broja~ se zgolemuva za edinica sekojpat koga na objektot }e mu se pridru`i nekoja referenca. Sekojpat koga referencata izleguva od oblasta na va`ewe ili bide postavena na vrednost null, brojot na referenci se namaluva. Ottuka, vodeweto smetka za broja~ot na referenci e mal no postojan re`iski tro{ok {to se izveduva vo tekot na traeweto na Va{ata programa. Sobira~ot na otpadoci se dvi`i niz celata lista na objekti i, koga }e naide na objekt so broja~ na referenci ednakov na nula, ja osloboduva memorijata (me|utoa, vo realizaciite na broja~ot na referenci objektot ~esto se osloboduva {tom broja~ot padne na nula). Edna od manite na ovoj pristap e deka ako objektite se vzaemno povrzani so referenci, tie mo`at da imaat broja~i na referenci razli~ni od nula, duri i ako tie objekti pretstavuvaat otpadoci. Otkrivaweto na takvi samo-referencira~ki grupi e zna~ajna dodatna rabota za sobira~ot na otpadoci. Broeweto na referencite voobi~aeno se koristi za objasnuvawe na eden vid na sobirawe na otpadoci, no ne se koristi vo nitu edna virtuelnata ma{ina na Java. Vo pobrzi realizacii, sobiraweto na otpadoci ne se bazira na broeweto na referencite. Namesto toa, toa se bazira na idejata deka sekoj `iv objekt mora na krajot da bide vraten do referencata koja {to se nao|a na stekot ili vo stati~no skladi{te. Sinxirot mo`e da odi niz nekolku nivoa na objekti. Ottuka, ako trgnete od stekot i stati~noto skladi{te i pominete niz site referenci, }e gi najdete site `ivi objekti. Za sekoja referenca {to }e ja najdete, morate da da mu pristapite na objektot kon koj taa poka`uva i potoa da gi sledite site referenci vo toj objekt, tragaj}i po objektite kon koi tie poka`uvaat itn.. Postapkata zavr{uva koga }e pominete niz cela Mre`a koja zapo~nala so taa referenca na stekot ili stati~noto skladi{te. Sekoj objekt niz koj {to minuvate sigurno e `iv. Obratete vnimanie deka nema problem so izdvoenite samo-referenciski grupi - tie ednostavno ne se najdeni na ovoj na~in, pa zatoa avtomatski tie stanuvaat otpadoci. Vo pristapot opi{an ovde, virtuelnata ma{ina na Java koristi adaptivna {ema za sobirawe na otpadoci . [to potoa pravi so pronajdenite `ivi objekti zavisi od varijantata {to momentalno se koristi. Edna od ovie varijanti e sopri-i-kopiraj(stop-and-copy). Ova zna~i deka, od pri~ini {to naskoro }e stanat jasni - programata prvo se stopira (toa ne e sobirawe vo pozadina). Potoa, sekoj `iv objekt se kopira od eden dinami~ki memoriski
168
Da se razmisluva vo Java
Brus Ekel
prostor na drug, pri {to vo stariot ostanuvaat site otpadoci. Pokraj toa, objektite pri kopirawe vo noviot dinami~ki memoriski prostor, se pakuvaat eden po drug, taka zbivaj}i go noviot dinami~ki memoriski prostor (i dozvoluvaj}i noviot prostor za skladirawe samo da se prodol`i na kraj, kako {to be{e prethodno opi{ano). Sekako, koga eden objekt }e se premesti od edno na drugo mesto, site referenci {to poka`uvaat kon toj objekt mora da bidat promeneti. Referencata {to poteknuva od dinami~kiot memoriski prostor ili od stati~ko skladi{te mo`e da bide promeneta vedna{, no mo`e da postojat i drugi referenci koi {to poka`uvaat kon toj objekt na koj }e naideme podocna vo tekot na pro{etkata. Tie se sreduvaat onaka kako {to na niv se naiduva (bi mo`ele da zamislite tabela {to gi preslikuva starite adresi vo novi). Postojat dva faktora koi {to gi pravat neefikasni ovie takanare~eni sobira~i so kopirawe. Prviot e deka imate dva dinami~ki memoriski prostori i deka ja prefrluvate seta memorija pome|u tie dva oddelni prostori, tro{ej}i dvojno pove}e memorija otkolku {to navistina Vi treba. Nekoi virtuelni ma{ini na Java se spravuvaat so ova na toj na~in {to zazemaat dinami~ki memoriski prostor vo par~iwa, po potreba i ednostavno kopiraat od edno par~e na drugo. Vtoriot faktor e samiot proces na kopirawe. [tom Va{ata programa }e stane stabilna, mo`e da generira malku ili voop{to da ne generira otpadoci. Nasproti toa, sobira~ot so kopirawe i ponatamu }e ja kopira celata memorija od edno mesto na drugo, {to e gubewe vreme. Za da go spre~at ova, nekoi virtuelni ma{ini otkrivaat koga ve}e ne se pravat otpadoci i vedna{ preminuvaat na druga {ema na ~istewe ({to e adaptivniot del). Ovaa druga {ema se narekuva ozna~i-i-is~isti i taa e istata {ema {to porane{nite verzii na Java Sun ja koristele celo vreme. Za op{ta upotreba, tehnikata ozna~i-i-is~isti e prili~no bavna, no koga znaete deka imate malo koli~estvo na otpadoci, ili voo{to nemate otpadoci, toga{ taa e brza. Tehnikata ozna~i-i-is~isti raboti na istiot princip so trnuvawe od stekot i od stati~koto skladi{te i sledewe na site referenci za da se najdat `ivi objekti. Sekojpat koga }e naide na `iv objekt, toj se ozna~uva so indikator, no objektot s u{te ne se sobira. Duri koga }e zavr{i procesot na ozna~uvawe, mo`e da zapo~ne procesot na ~istewe. Vo tekot na ~isteweto se osloboduva memorijata koja ja zazemale mrtvite objekti. Sepak, ne se slu~uva nikakvo kopirawe, pa ako sobira~ot re{i da go zbie fragmentiraniot dinami~ki memoriski prostor, toa go pravi na toj na~in {to gi pomestuva objektite. Tehnikata Stopiraj-i-kopiraj po~iva na idejata deka ovoj tip na sobirawe na otpadoci ne se odviva vo pozadina; tuku programata se stopira dodeka se vr{i sobirawe na otpadocite. Vo literaturata na Sun }e najdete mnogu
Inicijalizacija i ~istewe
169
referenci na sobira~ na otpadoci kako pozadinski proces so nizok prioritet, no na krajot se ispostavilo deka sobiraweto na otpadoci vo poranite verzii na Sun NM ne se realiziralo na toj na~in . Namesto toa, sobira~ot na otpadoci na Sun ja stopiral programata koga }e snemalo memorija. I tehnikata ozna~i i is~isti isto taka bara zapirawe na programata. Kako {to spomenavme prethodno, opi{anata virtuelna ma{ina zazema memorija vo golemi blokovi. Ako napravite golem objekt, toj }e dobie sopstven blok. Striktnata tehnika stopiraj-i-kopiraj bara kopirawe na sekoj `iv objekt od izvorniot dinami~ki memoriski prostor vo nov pred da se oslobodi stariot, za {to e neophodno golemo koli~estvo na memorija. So blokovite, sobira~ot na otpadoci vo tekot na sobiraweto obi~no mo`e da gi kopira objektite vo mrtvi blokovi. Sekoj blok broja~ na proizvodstvo koj vodi evidencija za toa dali e `iv blokot ili ne. Obi~no se zbivaat samo blokovite kreirani po poslednoto sobirawe na otpadoci; na site drugi blokovi broja~ot na proizvodstvo se zgolemuva ako od nekade se referencirani. Na ovoj na~in se gri`i za voobi~aenite uslovi na privremenite objekti so kratok `ivoten tek. Periodi~no se vr{i potpolno ~istewe - golemite objekti s u{te ne se kopiraat (kaj niv ednostavno se zgolemuva broja~ot na proizvodstvo), a blokovite koi sodr`at mali objekti se kopiraat i se zbivaat. Virtuelnata ma{ina na Java ja nabquduva efikasnosta na sobiraweto na otpadocite i ako za negovoto koristewe neophodno se tro{i vreme bidej}i site objekti se so dolg `ivoten tek, toga{ go prefrla vo re`im ozna~ii-is~isti. Sli~no, virtuelnata ma{ina na Java ja sledi uspe{nosta na tehnikata ozna~i-i-is~isti i ako dinami~kiot memoriski prostor se podeli na pove}e fragmenti, se prefrla nazad vo re`im stopiraj-i-kopiraj. Prethodniot metod na prefrluvawe go pretstavuva spomnatiot adaptiven del, t.e. postoi tehnika Adaptivno stopiraj-i-kopiraj ozna~i-i-is~isti. Postojat pove}e dodatni mo`nosti za zabrzuvawe na virtuelnata ma{ina na Java. Edna isklu~itelno va`na mo`nost se odnesvua na rabotata na programata za v~ituvawe (angliski loader) i ona {to se narekuva preveduva~ tokmu-koga-treba (just-in-time (JIT)). Preveduva~ot JIT delumno ili celosno ja konvertira programata vo priroden ma{inski kod, taka {to nema potreba da se interpretira od strana na virtuelnata ma{ina na Java, pa zatoa izvr{uvaweto e mnogu pobrzo. Koga klasata mora da se v~ita (obi~no, prviot pat koga }e sakate da kreirate objekt za taa klasa), se pronao|a datotekata .class i bajt kodovite na taa klasa se v~ituvaat vo memorijata. Vo ovoj moment, eden pristap mo`e da bide da go primenime JIT preveduvaweto na celiot kod, no toa ima dva nedostatoka: trae ne{to podolgo, {to, koga }e se nasobere niz `ivotniot vek na programata, ne mo`e da se zanemari. Vtoro, se zgolemuva izvr{nata programa (bajt kodovite se zna~itelno pokompaktni od raspakuvaniot JIT kod), pa mo`e da se izmenat memoriskite stranici {to
170
Da se razmisluva vo Java
Brus Ekel
definitivno ja zabavuva programata. Alternativen pristap e mrzlivata evaluacija, {to zna~i deka kodot ne se preveduva so JIT se dodeka toa ne e potrebno. So toa se postignuva kodot {to nikoga{ ne se izvr{uva, mo`ebi nikoga{ nema da bide JIT preveden. Tehnologiite na Java HotSpot vo novite razvojni okolini (JDK) postapuvaat na sli~en na~in, so optimizirawe na sekoj del od kodot sekoj pat koga toj se izvr{uva, taka {to kolku pove}e kodot se izvr{uva, tolku stanuva s pobrz.
Inicijalizacija na ~lenovi
Java se trudi da garantira deka promenlivite se pravilno inicijalizirani pred nivnata upotreba. Koga promenlivite se definirani lokalno vo metodot, toa go garantira preveduva~ot (bidej}i inaku prijavuva gre{ka pri preveduvawe). Zna~i ako napi{ete:
void f() { int i; i+ +; // Greska -- i ne e inicijalizirana }
}e dobiete poraka za gre{ka so napomena deka promenlivata i mo`ebi ne bila inicijalizirana. Sekako, preveduva~ot mo`el da i ja dodeli na promenlivata i podrazbiranata vrednost, no neinicijaliziranata lokalna promenliva e najverojatno gre{ka na programerot, a podrazbiranata vrednost toa bi go prikrila. So prisiluvaweto na programerot da obezbedi vrednost za inicijalizacija, se zgolemuva verojatnosta za zgolemuvawe na gre{kata. Ako prostiot tip e pole na nekoja klasa, toga{ rabotite se malku poinakvi. Kako {to vidovte vo poglavjeto Se e objekt, se garantira deka sekoe pole od prost tip vo sekoja klasa }e dobie inicijalna vrednost. Eve programa {to go proveruva ova i gi poka`uva vrednostite:
//: inicijalizacija/InicijalniVrednosti.java // Gi prikazuva podrazbiranite inicijalni vrednosti. import static net.mindview.util.Print.*; public class InicijalniVrednosti { boolean t; char c: byte b; short s; int i; long l; float f; double d; InitialValues reference; void printlnitialValues() {
Inicijalizacija i ~istewe
171
print(Tip na podatoci Inicijalna vrednost); print(boolean + t); print(char [ + c + ]); print(byte + b): print(short + s); print(int + i); print(long + 1): print(float + f): print(double + d); print(reference + reference): } public static void main(String [] args) { InicijalniVrednosti iv = new InicijalniVrednosti(); iv.printInicijalniVrednosti(); /* Vo ovoj slucaj mozete da napisete: new InicijalniVrednosti().printInicijalniVrednosti(); */ } } /* Rezultat: Tip na podatoci Initial value boolean false cha r [ ] byte 0 short 0 int 0 long 0 float 0.0 double 0.0 reference null * ///:-
Mo`ete da zabele`ite deka iako vrednostite ne se navedeni, tie avtomatski se inicijaliziraat (vrednosta za tipot char e nula, {to se ispi{uva kako rastojanie, odnosno prazen prostor, angl. space).Ottuka, barem e eliminirana opasnosta od rabotewe so neicijalizirani promenlivi. Koga definirate referenca na objekt vo ramkite na nekoja klasa bez da ja inicijalizirate, taa referenca dobiva specijalna vrednost null.
Zadavawe na inicijalizacija
[to se slu~uva koga sakate na promenlivata da dadete inicijalna vrednost? Eden direkten na~in za da go napravite toa e ednostavno da dodelite vrednosta na mestoto kade {to }e ja definirate promenlivata vo klasata. (Potsetete se deka ne mo`ete da go pravite ova vo S++, iako po~etnicite vo S++ toa sekoga{ se obiduvaat.) Ovde definiciite za poliwata vo klasata InicijalniVrednosti se promeneti za da obezbedat inicijalni vrednosti:
//: inicijalizacija/InicijalniVrednosti2.java
172
Da se razmisluva vo Java
Brus Ekel
// Eksplicitno zadavanje na inicijalni vrednosti. public class InitialValues2 { boolean b = true; char c = 'x'; byte b = 47: short s = 0xff; int i = 999: long l = 1: float f = 3.14f: double d = 3.14159: } * ///:-
Neprostite objekti mo`ete da gi inicijalizirate na istiot na~in. Ako definirate klasa Dlabocina, definirajte promenliva i inicijalizirajte ja na sledniot na~in:
//: inicijalizacija/Merka.java class Dlabocina {} public class Merka { Dlabocina d = new Dlabocina(): // ... } ///:~
Ako i nemate dadeno inicijalna vrednost na promenlivata d, a sepak se obidete da ja koristite, }e dobiete gre{ka pri izvr{uvaweto nare~ena isklu~ok (angliski exception), {to e obraboteno vo poglavjeto Obrabotka na gre{ki so pomo{ na isklu~oci. Mo`ete duri da povikate i metod za da ja obezbedi vrednosta za inicijalizacija:
//: inicijalizacija /InicijalizacijaNaMetodot.java public class InicijalizacijaNaMetodot { inti=f(); int f() { return 11; } } ///:-
Sekako, ovoj metod mo`e da ima argumenti, no tie argumenti ne mo`e da bidat ostanatite ~lenovi na klasata {to s u{te ne se inicijalizirani. Ottuka, mo`ete da go napravite slednoto:
//: initialization/ InicijalizacijaNaMetodot 2.java public class InicijalizacijaNaMetodot 2 ( inti = f(); intj = g(i); int f() { return II; } int g(int n) { return n * 18: } } ///:-
Inicijalizacija i ~istewe
173
Ova e edno od mestata kade preveduva~ot, sosema opravdano se `ali za referenciraweto odnapred. Pri~inata le`i vo redosledot na inicijalizacija, a ne vo na~inot na koj programata se preveduva. Ovoj pristap kon inicijalizacija e ednostaven i prili~no direkten. Ograni~en e so toa {to sekoj objekt od tipot InicijalniVrednosti }e gi dobie istite inicijalni vrednosti. Ponekoga{ ova e ednostavno to~no toa {to vi treba, no vo site drugi slu~ai }e vi treba mnogu pove}e fleksibilnost.
Inicijalizacija na konstruktori
Konstruktorot mo`e da se koristi pri izveduvawe na inicijalizacija i ova vi dava pogolema fleksibilnost vo programiraweto bidej}i mo`ete da povikuvate metodi i da izveduvate akcii za vreme na izvr{uvaweto na programata za da gi odredite inicijalnite vrednosti. Ima edna rabota {to sepak treba da ja imate na um: so toa ne spre~uvate avtomatska inicijalizacija, {to se slu~uva pred da se vleze vo konstruktorot. Zatoa, na primer, ako napi{ete:
//: inicijalizacija/Brojac. java public class Brojac { int i: Brojac() { i = 7; } // ... } ///:-
toga{ promenlivata i prvo }e bide inicijalizirana so vrednosta 0, a potoa so vrednosta 7. Ova va`i za site prosti tipovi i referenci na objekti, vklu~uvaj}i gi i onie koi bile eksplicitno inicijalizirani na mestoto na definicija. Zatoa preveduva~ot nema da se obide da ve prisili da gi inicijalizirate elementite na koe bilo mesto vo konstruktorot, ili pred da gi koristite - inicijalizacijata e ve}e garantirana.
Redosled na inicijalizirawe
Vo ramkite na klasata, redosledot na inicijalizirawe se odreduva so redosledot na definirawe na promenlivite vo ramkite na klasata. Definiciite na promenlivite mo`e da bidat rasfrlani vnatre i pome|u
174
Da se razmisluva vo Java
Brus Ekel
definiciite na metodite, no promenlivite se inicijaliziraat pred da se povikaat koi bilo metodi, pa duri i konstruktorot. Na primer:
//: inicijalizacija/RedosledNaInicijaliziranje.java // Go pokazuva redosledot na inicijaliziranje. import static net.mindview.util.Print.*; // Koga se povikuva konstruktor za pravenje na // objekt od klasata Prozorec, ke ja vidite porakata: class Prozorec { Prozorec(int marker) { print(Prozorec( + marker + )); } } class Kukja { Prozorec pl = new Prozorec(l); // Pred konstruktorot Kukja () { // Pokazuva deka sme vnatre vo konstruktorot: print(Kukja()); p3 = new Prozorec(33); // Povtorno inicijalizira p3 } Prozorec2 = new Prozorec(2); // After constructor void f() { print(f()); } Prozorec p3 = new Prozorec(3): // Na krajot public class RedosledNaInicijalizacija { public static void main(String [] args) Kukja k = new Kukja(); k. f (); // Pokazuva deka e zavrseno pravenjeto } } /* Rezultat: Prozorec(l) Prozorec(2) Prozorec(3) Kukja () Prozorec(33) f() * ///:-
Vo klasata Kukja, definiciite na objektite od klasata Prozorec namerno se rastureni naokolu za da se doka`e deka site tie }e bidat inicijalizirani pred vleguvaweto vo konstruktorot . Osven toa, p3 povtorno se inicijalizira vnatre vo konstruktorot. Od izlezot, mo`ete da vidite deka referencata p3 se inicijalizira dva pati: edna{ pred i edna{ za vreme na povikuvaweto na konstruktorot. (Prviot objekt se otfrla, za da mo`e da se sobere podocna od sobira~ot na otpadoci.) Ova otprvin mo`e da izgleda mnogu neefikasno, no garantira pravilna inicijalizacija. [to bi se slu~ilo ako bi se definiral preklopen
Inicijalizacija i ~istewe
175
176
Da se razmisluva vo Java
Brus Ekel
void f3(int marker) { print(f3( + marker + )); } static Cinija cinija5 = new Cinija(5); } public class StatickaInicijalizacija { public static void main(String [] args) { print(Pravenje na nov objekt od klasata Podmetac() vo metodot main); new Podmetac(); print(Pravenje na nov objekt od klasata Podmetac() vo metodot main): new Podmetac(); table.f2(1): cupboard.f3(1); } static Table table = new Table(); static Cupboard cupboard = new Cupboard(); } /* Rezultat: Cinija (1) Cinija (2) Masa() fl (1) Cinija (4) Cinija (S ) Cinija (3) Podmetac() fl (2) Pravenje na nov objekt od klasata Podmetac vo metodot main Cinija (3) Podmetac() fl(2) Pravenje na nov objekt od klasata Podmetac vo metodot main Cinija (3) Podmetac() f1(2) f2(1) f3(1) * ///:-
Klasata Cinija vi ovozmo`uva da go sledite sozdavaweto na klasata, a klasite Masa i Podmetac imaat stati~ni ~lenovi na pove}e mesta od definicijata na klasata Cinija. Obratete vnimanie deka Podmetac pred stati~nata definicija dodava nestati~en objekt Cinija cinija3. Od rezultatite na prethodnata programa mo`ete da vidite deka inicijalizacija na stati~nite elementi se slu~uva samo ako e navistina
Inicijalizacija i ~istewe
177
potrebna. Ako ne kreirate objekt Table i nikoga{ ne se obratite kon metodite Masa.cinija1 ili Masa.cinija2, stati~nite objekti Cinija cinija1 i Cinija2 nikoga{ nema da bidat napraveni. Tie se inicijaliziraat samo koga se pravi prviot objekt od klasata Masa (ili koga prv pat se pristapuva kon stati~ki objekt). Posle toa, stati~nite objekti ne se inicijaliziraat povtorno. Redosledot na inicijalizacija e sledniov: najprvo se inicijaliziraat stati~nite elementi, ako ne bile prethodno inicijalizirani pri praveweto na prethodniot objekt, a potoa nestati~nite objekti. Mo`ete da go vidite dokazot za ova vo izlezot od prethodnata programa. Za da izvr{ite stati~niot metod main( ), mora da bide v~itana klasata StatickaInicijalizacija, a potoa se inicijaliziraat nejzinite stati~ni poliwa masa i podmetac, {to predizvikuva v~ituvawe na tie klasi i bidej}i dvete sodr`at stati~ni objekti od klasata Cinija, potoa se v~ituva Cinija. Ottuka, site klasi vo ovaa posebna programa se v~ituvaat pred po~etokot na izvr{uvawe na metodot main( ). Toa obi~no ne e toj slu~aj, bidej}i vo tipi~ni programi nema se da bide povrzano so stati~nite elementi kako {to e toa slu~aj vo ovoj primer. Za da napravime rezime na procesot na kreirawe objekti, da ja razgledame klasata nare~ena Kuce:
1. Iako vo klasata eksplicitno ne se koristi rezerviraniot zbor static, konstruktorot vsu{nost e stati~en metod. Pa, prviot pat koga }e se kreira objekt od tip Kuce, ili prviot pat koga }e se pristapi na stati~en metod ili stati~no pole od klasata Kuce, interpreterot na Java }e mora da ja pronajde datotekata Kuce.class, taka {to vr{i prebaruvawe niz patekite od klasata (angliski-classpath) 2. Pri v~ituvaweto na Kuce.class (sozdavawe na objekt od klasata Class, za {to }e u~ite podocna), startuva inicijalizacija na site stati~ni elementi. Zna~i, tie se inicijaliziraat samo edna{, koga soodvetniot objekt od klasata Class se v~ituva za prv pat. 3. Koga kreirate objekt so operacijata new Kuce(), procesot na konstrukcija za objektot Kuce nalaga otprvin da se zazeme dovolno skladi{ten prostor za objektot Kuce vo dinami~kata memorija. 4. Ovoj prostor se popolnuva so nuli, so {to avtomatski se zadava podrazbiranata vrednost na site promenlivi od prost tip vo toj objekt Kuce (nula za broevite i nejzin ekvivalent za boolean i char), a site referenci dobivaat vrednost null. 5. Se izvr{uvaat site inicijalizacii koi se pojavuaat na mestoto na definicijata na pole.1
178
Da se razmisluva vo Java
Brus Ekel
6. Se izvr{uvaat konstruktorite. Kako {to }e vidite vo poglavjeto Povotorno koristewe na klasite, ova mo`e da bide golema rabota, posebno koga se raboti za nasleduvawe.
Ova potsetuva na metod, no vsu{nost toa e samo rezerviraniot zbor static prosleden od blok od kodot. Ovoj kod, kako i drugi stati~ni inicijalizacii, se izvr{uva samo edna{: koga prvpat pravite objekt od taa klasa ili koga prvpat pristapuvate kon stati~en ~len od taa klasa (duri i ako nikoga{ ne ste napravile objekt od taa klasa). Na primer:
//: inicijalizacija/StrogoStaticka.java // Eksplicitna inicijalizacija na staticni elementi preku staticen blok. import static net.mindview.util.Print.*; class Solja { Solja(int marker) { print(Cup( + marker + )); } void feint marker) { print(f( + marker + )); } } class Solji { static Solja soljal; static Solja solja2; static { solja1 = new solja (l); solja2 = new solja (2); } Solji () { print(solji());
Inicijalizacija i ~istewe
179
} } public class StrogoStaticka { public static void main(String [] args) { print(Vnatre vo metodot main()): Solji.solja1.f(99); // (1) } // static Solji solji1 = new Solji(); // (2) // static Solji solji2 = new Solji(); // (2) } /* Rezultat: Vnatre vo metodot main() Solja(l) Solja(2) f (99) * ///:-
Stati~nite inicijalizatori za klasata Solji se izvr{uvaat na dva na~ina: ako se pristapi kon objektot Solja1 vo redot ozna~en so (1), ili koga redot (1) se komentira, a od redovite ozna~eni so (2) se otstraneti komentarite. Ako se komentiraat i dvete, (1) i (2), stati~nata inicijalizacija za Solji nikoga{ nema da se izvr{i, kako {to gledate od rezultatot. Isto taka, ne e bitno dali edniot ili dvata reda ozna~eni so (2) se ostaveni bez komentar; stati~niot element se inicijalizira samo edna{. Ve`ba 13: (1) Proverete gi naredbite od prethodniot pasus. Ve`ba 14: (1) Napravete klasa so edno stati~no pole od tip String {to se inicijalizira na mestoto kade {to i se definira, a patem i so drugo pole {to se inicijalizira od strana na stati~eni blok. Dodadete stati~en metod {to gi ispi{uva dvete poliwa i poka`uva deka dvete se inicijalizirani pred da se koristat.
180
Da se razmisluva vo Java
Brus Ekel
print(f( + marker + )): } } public class Pregratki { Pregratka pregratka1; Pregratka pregratka2; { pregratkal = new Pregratka(l): pregratka 2 = new Pregratka (2): print(pregratka1 i pregratka 2 se iniciajalizirani): } Pregratki() { print(Pregratki ()): } Pregratki (int i) { print(Pregratki (int) ): } public static void main(String [] args) { print(Vnatre vo metodot main()): new Pregratki(): print(new Pregratki() se zavrseni): new Pregratki(1): print(new Pregratki(l) se zavrseni): } } /* Rezultat: Vnatre vo metodot main() Pregratka(1) Pregratka (2) pregratka1 & pregratka2 se inicijalizirani Pregratki() new Pregratki () se zavrseni Pregratka (1) Pregratka (2) pregratka1 & pregratka 2 se inicijalizirani Pregratki (int) new Pregratki(l) se zavrseni * ///: -
izgleda sosema isto kako i odredbata za inicijalizacija na stati~ni elementi, samo {to nedostasuva rezerviraniot zbor static. Ovaa sintaksa e
Inicijalizacija i ~istewe
181
neophodna za obezbeduvawe na poddr{ka za inicijalizacijata na anonimni vnatre{ni klasi (pogledneto go poglavjeto Vnatre{ni Klasi), no isto taka vi ovozmo`uva da garantirate deka odredeni operacii }e se izvr{at nezavisno od toa koj ekspliciten konstruktor }e bide povikan. Od rezultatot na programata mo`ete da vidite deka odredbata za za inicijalizacija na instancite se izr{uva pred site kontstruktori. Ve`ba 15: (1) Napravete klasa so edno pole od tip String {to se inicijalizira so koristewe na inicijalizacija na instanci.
Inicijalizacija na nizi
Niza e sekvenca na objekti ili elementi od prost tip, {to site se od eden ist tip i se spakuvani zaedno pod edno ime za identifikacija. Nizite se definiraat i se koristat so pomo{ na operatorot za indeksirawe [ ]. Za da se definira edna referenca na niza, ednostavno }e treba posle imeto na tipot da stavite prazni sredni zagradi:
int[] al;
Ova se vklopuva vo o~ekuvawata na S i S++ programerite. Prviot stil, sodr`i verojatno po~uvstvitelna sintaksa, bidej}i poka`uva deka tipot na promenlivata e niza od celi broevi. Toj stil }e se koristi vo ovaa kniga. Preveduva~ot ne dozvoluva da ja izrazite goleminata na nizata. Ova ne vra}a nazad kaj problemot so referencite. Se {to imate ovde e referenca na niza (ste obezbedile dovolno memorija za taa referenca) i nemate mesto od memorijata rezervirano za smestuvawe na samata niza. Za da napravite skladi{te za nizata, morate da napi{tete izraz za inicijalizacijata. Za nizite, inicijalizacijata mo`e da se pojavi kade bilo vo kodot, a isto taka mo`ete da koristite specijalen vid na izraz za inicijalizacija {to mora da se slu~i na mestoto na e kreirana nizata. Ovaa specijalna inicijalizacija e mno`estvo od vrednosti vo golemi zagradi.Za zazemaweto na skladi{niot prostor (isto kako da se koristelo new) se gri`i preveduva~ot vo ovoj slu~aj. Na primer:
int[] al = { 1, 2, 3, 4, 5 }:
182
Da se razmisluva vo Java
Brus Ekel
Ona {to vsu{nost go pravite e kopirawe na referenca, kako {to e poka`ano vo sledniot primer:
//: inicijalizacija /NizaOdProstiTipovi.java import static net.mindview.util.Print.*; public class NizaOdProstiTipovi { public static void main(String [] args) { int[] a1 = { 1, 2, 3,4, 5 }: int[] a2; a2 = a1; for(i nt i = 0: i < a2.length: i ++ ) a2[i] = a2[i] + 1: for(int i = 0 ; i < al.length: i ++ ) print(a1[ + i + ] = + a1 r i]); } } /* Rezultat: a1[0] = 2 a1[1]=3 a1[2] = 4 a1[3] = 5 al[4] =6 * ///:-
Obratete vnimanie deka na nizata a1 i e dodelena inicijalizaciona vrednost, no ne i na nizata a2.Na a2 i se dodeluva vrednost podocna, vo ovoj slu~aj, taa poka`uva na druga niza. Bidej}i a2 i a1 taka stanuvaat psevdonimi na istata niza, promenite napraveni preku a2 se odrazuvaat i vo a1. Site nizi imaat ~len (nezavisno od toa dali se nizi od objekti ili nizi od elementi od prost tip) {to mo`ete da go ~itate no ne i da go promenite, za da vi ka`e kolku elementi ima nizata. Ovoj ~len e length. Bidej}i nizite vo Java, kako i vo S i S++, po~nuvaat da gi brojat elementite od indeksot nula, najgolemiot element {to mo`ete go indeksirate e length-1. Ako izlezete nadvor od granicite, S i S++ tivko vi go prifa}aat ova i vi dozvoluvaat da {etate niz Va{ata memorija, {to e izvor na mnogu neslavni gre{ki. Sepak, Java ve {titi od takvi problemi so toa {to javuva poraka za gre{ka pri izvr{uvaweto (isklu~ok) ako izlezete nadvor od granicite.5 [to ako ne znaete kolku elementi }e vi trebaat vo nizata dodeka ja pi{uvate programata? Vie ednostavno koristete go new za da gi napravite elementite vo nizata. Tuka, new raboti iako sozdava niza od elementi od prost tip (new nema da sozdade promenliva od prost tip {to ne e niza):
//: inicijalizacija/NiziNew.java // Pravenje na novi nizi so koristenje na operatorot new. import java.util.*: import static net.mindview.util.Print.*; public class NiziNew {
Inicijalizacija i ~istewe
183
public static void main{String [] args) { int[] a: Random slucaen = new Random(47); a = new int[rand.nextlnt(20)); print(dolzinata na nizata a = + a.length); print(Arrays.toString(a)); } } */ Rezultat: dolzinata na nizata a = 18 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0] * ///:-
Goleminata na nizata se izbira slu~ajno so koristewe na metodot Random.nextInt( ), koj proizveduva vrednost pome|u nula i onaa od nejziniot argument. Kako rezultat od slu~ajnosta, jasno e deka sozdavaweto na nizite vsu{nost se slu~uva pri izvr{uvaweto. Osven toa, rezultatot od ovaa programa poka`uva deka elementite na nizata od prosti tipovi avtomatski se inicijaliziraat na prazni vrednosti. (Za numeri~ki promenlivi i promenlivi od tip char, ova e nula, a za boolean, toa e false.) Metodot Arrays.toString( ), koj pripa|a na standardnata biblioteka na Java java.util, proizveduva verzija na ednodimenzionalna niza {to mo`e da se ispi{e.
5 Sekako, proveruvaweto na sekoj pristap tro{i mnogu vreme i kod i nema na~in taa proverka da se isklu~i, {to zna~i deka pristapite kon taa niza mo`e da bidat izvor za neefikasnost vo va{ata programa ako se javuvaat na va`ni mesta. Dizajnerite na Java smetaa deka vredi da se `rtvuva del od efikasnosta na smetka na sigurnosta na Internet bezbednosta i produktivnosta na programerot,. Iako mo`ebi }e padnete vo isku{enie da napi{ete kod {to mo`e poefikasno da im pristapuva kon nizite, toa e nepotrebno gubewe vreme bidej}i avtomatski optimizacii pri preveduvaweto i izvr{uvaweto }e gi zabrzaat pristapuvawata kon poliwata.
Sekako, vo ovoj slu~aj nizata isto taka mo`e da se definira i inicijalizira vo istata naredba:
int[] a = new int[rand . nextInt(20)];
Ako mo`ete, prepora~livo e da go koristite ovoj na~in. Koga sozdavate neprosta niza, vie sozdavate niza od referenci. Da go razgledame obvitkuva~kiot tip Integer, {to e klasa, a ne prost tip:
//: inicijalizacija/NizaOdObjekti . java // Pravenje na niza cii elementi ne se od prost tip . import java.util.*; import static net.m1ndview.util.Pr1nt.* ;
184
Da se razmisluva vo Java
Brus Ekel
public class NizaOdObjekti { public static void main(String [] args) { Random slucaen = new Random(47); Integer[] a = new Integer(slucaen.nextInt (20)); print ( dolzinata na nizata a = + a.length); for(int i = 0; i < a.length: i++) a[i] = slucaen.nextlnt(500 ); // Avtomatkso pakuvanje print(Arrays.toString(a));: } } /* Rezultat: (Primer) dolzinata na nizata a = 18 [55, 193, 361, 461, 429, 368, 200, 22, 207, 288, 128, 51, 89, 309, 278, 498, 361, 20] * ///:-
}e dobieme samo niza od referenci i inicijalizacijata nema da bide potpolna se dodeka ne se inicijalizira samata referenca so kreirawe nov objekt od tip Integer (vo ovoj slu~aj, preku avtopakuvawa)
a[i] = new Integer (slucaen.nextInt(500));
Ako pri izvr{uvaweto zaboravite da napravite objekt, }e se pojavi isklu~ok koga }e se obidete da ja koristite praznata lokacija na nizata. Isto taka e mo`no da se inicijaliziraat nizite na objekti so koristewe na lista zatvorena so golemi zagradi. Za toa postojat dve formi:
//: inicijalizacija/InicijalizacijaNaNiza.ja va // Inicijalizacija na niza. import java.util.*; public class InicijalizacijaNaNiza { public static void main(String [] args) { Integer[ ] a = { new Integer(1) , new Integer(2 ) , 3, // Avtomatsko pakuvanje }; Integer[ ] b = new Integer[ ]{ new Integer(1), new Integer(2), 3, // Avtomatsko pakuvanje } ; System,out .println(Arrays,toString (a)); System.out. println(Arrays,toString (b)): } } /* Rezultat: [1. 2. 3] [1. 2. 3] *///:~
Inicijalizacija i ~istewe
185
Vo dvata slu~aja, poslednata zapirka vo listata na inicijalizatori ne e zadol`itelna. (Ovaa karakteristika doprinesuva za poednostavno odr`uvawe na dolgite listi.) Iako prvata forma e korisna, taa e pove}e ograni~ena bidej}i mo`e da se koristi samo na mestoto kade {to se definira nizata. Mo`ete da gi koristite vtorata i tretata forma kade bilo, duri i vo povikot na nekoj metod. Na primer, bi mo`ele da napravite niza objekti od tip String koi }e mu gi prosledite na metodot main( ) od drug metod, za da ovozmo`ite alternativni argumenti na komandna linija na toj metod main( ):
//: inicijalizacija/DinamickaNiza. j ava // Inicijalizacija na niza. public class DinamickaNiza { public static void main(String [] args) { Druga.main(new String [ ] { tra, la , la }); } } class Druga { public static void main(String [ ] args) { for(String 5 : args) System.out .print(s + ); } } /* Rezultat: tra la la * ///:-
Nizata napravena za argumentot od metodot Druga.main( ) e napraveno na mestoto na povikot na metodot, pa vo momentot na povikot mo`ete duri i da zadadete alternativni argumenti. Ve`ba 16: (1) Napravete niza od objekti od tip String objekti i na sekoj element dodelete mu po eden String. Ispi{ete ja nizata so koristewe na ciklusot for. Ve`ba 17: (2) Napravete klasa so konstruktor koj prima argument od tip String. Za vreme na konstrukcijata, ispi{ete go go argumentot. Napravete niza od referenci na objektite od ovaa klasa, no nemojte da pravite objekti koi }e i gi dodelite na nizata. Koga ja izvr{uvate programite, proverete dali se ispi{uvaat porakite za inicijalizacijata od povikot na konstruktorot. Ve`ba 18: (1) Dopolnete ja prethodnata ve`ba so sozdavawe objekti koi }e i gi dodelite na nizata od referenci.
listata so promenlivi argumenti vo S (poznata kako i varargs vo S). Listata mo`e da ima nepoznat broj na argumenti kako i nepoznati tipovi. Bidej}i site klasi na krajot se nasleduvaat od zaedni~kata korenska klasa Object (tema za koja }e nau~ite pove}e napreduvaj}i niz ovaa kniga), mo`ete da napravite metod ~ij argument e niza od elementi od tip Object i da go povikate na sledniot na~in:
//: inicijalizacija/ListaSoPromenlivi.java // Koristenje na sintaksa za nizi za pravenje na promenlivi listi so parametri. class A {} public class ListaSoPromenlivi { static void otpecatenaNiza(Object[ ] argumenti) for (Object obj args) System.out.print(obj + ); System.out.println{); } public static void main(String [ ] argumenti) { otpecatenaNiza(new Object [ ] { new Integer(47), new Float(3.14), new Double(11.11) } ) ; otpecatenaNiza(new Object [ ]{eden, dva , tri }): otpecatenaNiza(new Object [ ]{new A(), new A(), new A()}): } } /* Rezultat: (Primer) 47 3.14 11 .11 eden dva tri A@1a46e30 A@3e25a5 A@19821f * ///: -
Obratete vnimanie deka print() zema niza na elementi od tipot na Object, a potoa so koristewe na sintaksata foreach pominuva niz nizata i gi ispi{uva site nejzini elementi poedine~no. Klasite od standardnata biblioteka na Java davaat razumni rezultati, no objektite od klasite sozdadeni ovde go pe~atat imeto na klasata, po {to sleduva znakot @ i heksadecimalni cifri. Zna~i, podrazbiranoto odnesuvawe (ako za svojata klasa ne definirate metod toString( ), {to }e bide podetaqno opi{ano ponatamu vo ovaa kniga) e pe~ateweto na imeto na klasata i adresata na objektot. Na ovoj na~in pred pojavata na Java SE5 se pi{uvale Java programite so cel da se dobijat promenlivite listi so argumenti. Me|utoa, vo Java SE5, ovaa dolgo o~ekuvana karakteristika be{e kone~no dodadena, pa sega mo`ete da koristite elipsi za da gi definirate promenlivite listi so argumenti, kako {to mo`ete da vidite vo sledniot metod pecatiNiza( ):
//: inicijalizacija/NovaListaSoPromenlivi.java // Koristenje na sintaksi vrzani za nizi, za pravenje na listi so promenlivi
Inicijalizacija i ~istewe
187
// parametri. public class NovaListaSoPromenlivi { static void printArray(Object ... argumenti) { for (Object obj : args) System.out.print(obj + ); System.out.println() ; } public static void main(String []argumenti) { // Moze da primi poedinecni elementi: pecatiNiza(new Integer(47). new FloatC3.14), new Double(11.11)); pecatiNiza(47, 3.14F, 11.11); pecatiNiza(eden, dva, tri): pecatiNiza (new A(), new A(), new A()); // Ili niza; pecatiNiza ((Object[ ])new Integer[]{ 1, 2, 3, 4 }): pecatiNiza (); // Praznite listi se dozvoleni } } /* Rezultat: (75% sovpagjanje) 47 3.14 11.11 47 3.14 11.11 eden dva tri A@1bab50a A@c3c749 A@150bd4d 1 2 3 4 * ///:-
Koga rabotite so promenlivite argumenti, pove}e ne morate eksplicitno da ja ispi{uvate sintaksata na nizata, bidej}i preveduva~ot avtomatski }e go napravi toa namesto Vas {tom }e gi zadadete promenlivite argumenti. Vie sepak dobivate niza, zaradi toa print( ) mo`e so koristewe foreach sintaksata da pomine niz site elementi od nizata. Obrnete vnimanie na pretposledniot red od programata, kade nizata od elementi od tipot Integer (napraveni so avtopakuvawe) eksplicitno se konvertira vo niza od tipot Object (so cel da se izbegne predupreduvaweto na preveduva~ot) i se prosleduva do metodot pecatiNiza( ). Jasno, preveduva~ot gleda deka ova ve}e e niza i ne izveduva nikakva konverzija vrz nego. Zna~i ako imate grupa na stavki {to mo`ete da gi prosledite kako lista i ako ve}e imate niza, preveduva~ot }e ja prifati nea kako lista na promenlivi argumenti (parametri).
Posledniot red od programata poka`uva deka e mo`no na listata na promenlivi argumenti da se prosledat nula argumenti. Toa e korisno koga imate nezadol`itelni slede~ki argumenti:
//: inicijalizacija/OpcionalenPrateckiArgument.java public class OpcionalenPrateckiArgument { static void f(int potreben, String . . . pratecki) { System.out.print(potreben: + potreben + );
188
Da se razmisluva vo Java
Brus Ekel
for(String s : pratecki) System.out.print(s + ); System.out.println(): } public static void main(String[) args) { f(). one); f(2. two, three); f (0) ; } } /* Rezultat: potreben: 1 eden potreben: 2 dva tri potreben: 0 * ///:-
Ova isto taka poka`uva deka mo`ete da koristite promenlivi argumenti so zadaden tip razli~en od Object. Vo posledniot primer, site promenlivi argumenti mora da bidat String objekti. Vo promenlivite argumenti mo`e da se koristat site tipovi, pa duri i prostite tipovi. Sledniot primer isto taka poka`uva deka listata na promenlivite argumenti stanuva niza i ako listata e prazna, toga{ nizata ima golemina ednakva na nula:
//: inicijalizacija/TipNaPromenlivArgument.java public class TipNaPromenlivArgument { static void f(Character ... argumenti) ( System.out.print(argumenti.getClass()); System.out.println( length + argumenti.length): } static void g(int ... argumenti) { System.out.print(args . getClass(; System.out.println( length ., + args . length); } public static void main(String []argumenti) { f (a) ; f(); g(l); g(); System.out.println(int[]: + new int [0].getClass()); } } /* Rezultat: class [l java.lang.Character; length 1 class [l java.lang.Character; length 0 class (I dolzina 1 class [I dolzina 0 int[]: class [I
Inicijalizacija i ~istewe
189
* ///:-
Metodot getClass( ) e del od Object i toj }e bide celosno razgledan vo poglavjeto Podatoci za tipot. Toj ja proizveduva klasata na objektot i koga }e ja ispi{ete ovaa klasa, dobivate kodirana znakovna moza koj pretstavuva tip na klasata. Vode~koto [ poka`uva deka se raboti za niza od tipot koj {to sledi. I go ozna~uva prostiot tip int; za da proveram u{te edna{, napraviv niza od tipot int vo posledniot red i go ispi{av nejziniot tip. Ova potvrduva deka koristeweto na promenlivi argumenti ne zavisi od avtopakuvaweto, tuku vsu{nost se raboti so prosti tipovi. Promenlivi argumenti sepak rabotat vo sklad so avtopakuvaweto. Na primer:
//: inicijalizacija/AvtomatskoPakuvanjeNaPromenliviArgumenti. java public class AutoboxingVarargs { public static void f(Integer. argumenti) { for (Integer i : argumenti) System.out.print(i + ); System.out.println() ; } public static void main(String [] args) { f(new Integer(l). new Integer(2 ; f(4. 5. 6. 7. 8. 9}: f(10. new Integer(ll), 12); } } /* Rezultat: 1 2 45 6 7 8 9 10 11 12 * ///:-
Imajte vo predvid deka mo`ete da gi me{ate razli~nite tipovi vo edna lista na argumenti, a avtopakuvaweto selektivno }e gi unapredi int argumentite vo Integer. Promenlivite argumenti go uslo`nuvaat procesot na preklopuvawe, iako toa na prv pogled izgleda sosema bezbedno:
//: inicijalizacija/PreklopuvanjeNaPromenliviArgumenti.java public class PreklopuvanjeNaPromenliviArgumenti { static void f (Character ... argumenti) { System.out.print(prv);
190
Da se razmisluva vo Java
Brus Ekel
for (Character c : argumenti) System.out.print( + c): System.out.println{); } static void f{Integer . .. argumenti) { System.out.print(vtor): for (Integer i argumenti) System.out.print( + i); System.out.println(); } static void f(Long ... argumenti) { System.out.println(tret); } public static void main(String [] args) { f{'a', 'b', 'e'); f (1); f(2. 1); f (0); f(0L); //! f(); // Nema da preveduva -- povekjeznacno } Rezultat: a b c 1 2 1 0
Vo sekoj od prethodnite slu~ai preveduva~ot koristi avtopakuvawe za da se prilagodi na preklopeniot metod i go povikuva najsoodvetniot metod. No koga povikuvate f( ) bez argumenti, toj ne znae koj to~no metod da go povika. Iako ovaa gre{ka e razbirliva, najverojatno }e go iznenadi programerot klient. Bi mo`ele da se obidete da go re{ite ovoj problem so dodavawe argument koj e nepromenliv na eden od metodite:
//: inicijalizacija/PreklopuvanjeNaPromenliviArgumenti2.java // {CompileTimeError} (Nema da preveduva) public class PreklopuvanjeNaPromenliviArgumenti2 { static void f(float i, Character... argumenti) { System.out.println(prv); } static void f(Character. argumenti) {
Inicijalizacija i ~istewe
191
System.out.print(vtor) : } public static void main(String []argumenti) { f(1, 'a'): f('a', 'b'): } } ///:-
Oznakata {CompileTimeError} vo komentarot ja isklu~uva ovaa datoteka od skriptata za preveduvawe na primerite od ovaa kniga. Ako ja prevedete ra~no, }e ja dobiete slednata poraka za gre{ka: reference to f is ambigious, both metod f(float,java.lang.Character...) Preklopuvanje.PromenliviArgumenti2 and method f(java.lang.Character...) PreklopuvanjePromenliviArgumenti2 match in in
Po pravilo, bi trebalo listata na promenlivi argumenti da ja upotrebuvate samo vo eden od preklopenite metodi. Ili, voop{to da ne ja upotrebuvate. Ve`ba 19: (2) Napi{ete metod {to prima niza String od promenlivi argumenti. Uverete se deka na toj metod mo`ete da mu prosledite lista na elementi od tipot String razdvoeni so zapirki ili so String[].
Ve`ba 20: (1) Napravete metod main( ) {to koristi promenlivi argumenti namesto voobi~aenata main( ) sintaksa. Ispi{ete gi site elementi vo
192
Da se razmisluva vo Java
Brus Ekel
rezultira~kata niza args. Ispitajte go toj metod so pomo{ na razli~en broj argumenti od komandnata linija.
Nabroeni tipovi
Naizgled mal dodatok vo Java SES e rezerviraniot zbor enum, koj {to mnogu Vi go olesnuva `ivotot koga }e treba da grupirate i da koristite mno`estvo od nabroeni tipovi (angl. ennumerated types). Prethodno bi napravile mno`estvo od konstantni celobrojni vrednosti, no ovie normalno ne se ograni~uvaat samite na Va{eto mno`estvo, pa ottuka se mnogu porizi~ni i pote{ki za koristewe. Nabroenite tipovi se tolku ~esto potrebni taka {to S, S++ i mnogu drugi jazici sekoga{ gi imale. Pred Java SES, Java programerite bea prisileni mnogu da znaat i mnogu da vnimavaat za ispravno da go proizvedat enum efektot. Sega koga i Java ima enum, i toj e mnogu pomo}en od onoj {to go imaat S ili S++. Eve eden ednostaven primer:
//: initialization/Zacinetost . java public enum Zacinetost { NE, MALKU, SREDNO, MNOGU, PREZACINETO } ///:-
Ova sozdava nabroen tip nare~en Luto so pet imenuvani vrednosti. Bidej}i primerocite (instancite) na enum (nabroenite tipovi) se konstanti, po konvencija gi pi{uvame so golemi bukvi (ako imeto sodr`i pove}e zborovi, tie se razdeluvaat so dolna crta). Za da koristite enum, napravete referenca od toj tip i dodelete ja na nekoj primerok (instanca):
//: inicijalizacija/EdnostavnaUpotrebaNaNabroeniTipovi.java public class EdnostavnaUpotrebaNaNabroeniTipovi { public static void main(String []argumenti) { Zacineto kolkuzacineto = Zacineto.SREDNO; System.out.println(kolkuzacineto); } Rezultat:
} /* SREDNO * ///:-
Koga }e kreirate enum preveduva~ot avtomatski mu dodava korisni mo`nosti. Na primer, sozdava metod toString( ) so koj }e mo`ete lesno da go prika`ete imeto na instancata enum ({to e i na~inot na koj prethodnata naredba print dade rezultat). Preveduva~ot isto taka proizveduva metod ordinal( ) koj go dava redniot broj na deklarirawe na odredenata enum konstanta vo negovata klasa, a i stati~niot metod values( ) {to proizveduva niza od vrednosti od enum konstantite po redosledot po koj tie bile deklarirani:
Inicijalizacija i ~istewe
193
//: inicijalizacija/RedosledNaNabroeniTipovi.java public class RedosledNaNabroeniTipovi { public static void main(String []argumenti) { for(Zacinetost s : Zacinetost.values()) System.out.println(s + s.ordinal() + . po red); } } /* Rezultat: NE, ordinal 0 MALKU, ordinal 1 SREDNO, ordinal 2 ZACINETO, ordinal 3 PREZACINETO, ordinal 4 * ///:-
Iako enum izgleda kako nov tip na podatok, toj rezerviran zbor samo go odreduva odnesuvaweto na preveduva~ot dodeka ja sozdava klasata za enum, pa na mnogu na~ini mo`ete da go tretirate rezerviraniot zbor enum kako i sekoja druga klasa. Vsu{nost, nabroenite tipovi se klasi so sopstveni metodi. Osobeno dobra karakteristika e na~inot na koj nabroenite tipovi mo`at da se koristat vnatre vo naredbite switch:
//: inicijalizacija/Pleskavica.java public class Pleskavica { Lutina stepen; public Pleskavica(Stepen na lutina) { this.stepen = stepen:} public void opisi() { System.out.print(Ovaa pleskavica e ); switch(stepen) { case NE: System.out.println(voopsto ne e zacineta); break: case SLATKO: case SREDNO: System.out.println(malku luta.): break: case MNOGU: case OGAN: default: System.out.println(mozebi e preluta.); } } public static void main(String [] args) { Pleskavica bez = new Pleskavica(Luto,NE). biber = new Pleskavica(Luto.SREDNO.). feferon = new Pleskavica(Zacineto.MNOGU.): bez.opisi(): biber.opisi (); feferon. opisi (): } } /* Rezultat:
194
Da se razmisluva vo Java
Brus Ekel
Ovaa pleskavica ne e ni malku zacineta. Ovaa pleskavica e malku luta. Ovaa pleskavica e premnogu luta. * ///:-
Bidej}i switch slu`i za izbor od ograni~enoto mno`estvo mo`nosti, idealno odgovara za enum. Obrnete vnimanie deka enum imiwata mnogu pojasno poka`uvaat {to }e raboti programata. Po pravilo mo`ete da go koristite enum kako i sekoj drug na~in na definirawe na tipovi na podatoci, a potoa da gi aktivirate rezultatite. Vsu{nost, toa e celta, za da ne morate mnogu da obra}ate vnimanie na niv. Pred voveduvaweto na nabroenite tipovi vo Java SE5, moravte da vlo`ite mnogu trud za da napravite ekvivalenten nabroen tip {to bi bil bezbeden za koristewe. Ova vi e dovolno za da gi razberete i koristite osnovnite nabroeni tipovi na Java. Niv podetaqno }e razgledame podocna vo ovaa kinga - za niv e rezervirano posebno poglavje: Nabroeni tipovi. Ve`ba 21: (1) Definirirajte enum od {est najmalku vredni tipovi na hartieni banknoti. So metodot values( ) pominete niz site nabroeni vrednosti i ispi{ete ja sekoja vrednost i nejziniot reden broj (so metodot ordinal( )). Ve`ba 22: (2) Napi{ete naredba switch za enum od posledniot primer. Za sekoe case, ispi{ete opis na taa banknota.
Rezime
Prili~no razraboteniot mehanizam na inicijalizacijata, kakov {to e konstruktorot, bi trebalo da uka`e na ogromnata va`nost koja vo ovoj jazik i e dadena na inicijalizacijata. Edno od prvite nabquduvawa za produktivnosta na S, koe Bjarne Stroustrup, go iznel u{te koga go proektiral jazikot S++, bilo deka nepravilnata inicijalizacija na promenlivite predizvika prili~no mnogu problemi pri programiraweto. Ovie tipovi na gre{ki se te{ki za otkrivawe, a sli~ni gre{ki se slu~uvaat pri nepravilno ~istewe. Bidej}i konstruktorite vi ovozmo`uvaat da garantirate pravilna inicijalizacija i ~istewe (preveduva~ot nema da vi dozvoli da kreirate objekt bez ispravni povici na konstruktorot), dobivate potpolna kontrola i sigurnost. Vo S++, uni{tuvaweto e prili~no va`no bidej}i objektite sozdadeni so operatorot new mora eksplicitno da bidat uni{teni. Vo Java, sobira~ot na otpadocite avtomatski ja osloboduva memorijata za site objekti, taka {to ekvivaleten metod za ~istewe vo Java ne e neophoden pogolemiot del od vremeto (no koga e potreben, morate da go napravite toa samite). Vo slu~aite koga ne vi treba odnesuvawe nalik na destruktori, sobira~ot na otpadoci na
Inicijalizacija i ~istewe
195
Java zna~itelno go poednostavuva programiraweto i ja dodava mnogu potrebnata sigurnost pri koristeweto na memorijata. Nekoi sobira~i na otpadoci mo`e duri i da ~istat drugi resursi, kako {to se identifikatorite na datotekite i grafi~kite objekti. Me|utoa, sobira~ot na otpadoci dodava odredeni tro{oci za vreme na izvr{uvaweto na taa programa, ~ija cena te{ko se odreduva poradi tradicionalnata bavnost na Java interpretatorite. Iako Java ima{e zna~aen napredok vo odnos na performansite, toj jazik, zaradi svojata bavnost i ponatamu ne se koristi vo nekoi situacii pri programirawe. Bidej}i garancijata deka site objekti }e bidat konstruirani va`i i koga pravite novi klasi koristej}i kompozicija ili nasleduvawe potrebna e isto taka dodatna sintaksa za da se podr`i ova. Za kompozicijata, nasleduvaweto i za toa kako tie operacii vlijaat vrz konstruktorite }e nau~ite vo slednite poglavja. Re{enijata na izbranite ve`bi mo`e da se najdat vo elektronskiot dokument The Thinking in Java Annotaed Solution Guide, dostapni za proda`ba na www.MindView.net.
196
Da se razmisluva vo Java
Brus Ekel
Kontrola na pristapot
Kontrolata na pristapot (ili krieweto na realizacijata) vsu{nost zna~i mo`nost da se popravi ona {to prviot pat ne bilo dobro napraveno.
Site dobri pisateli, vklu~uvaj}i gi i onie koi {to pi{uvaat softver, znaat deka rabotata ne e zavr{ena kako {to treba se dodeka ne se preraboti pove}e pati. Ako ostavite del od kodot vo fioka za kratko i potoa povtorno go pro~itate, mo`ebi }e najdete mnogu podobar na~in za da go napravite toa. Ova e edna od glavnite pri~ini za povtornata podelba na prosti faktori, za prerabotka na funkcionalniot kod so cel istiot da se napravi po~itliv, porazbirliv i ottuka mnogu polesen za odr`uvawe!1 Me|utoa, postojat problemi koga sakate da go promenite i podobrite va{iot kod. ^esto korisnicite (programerite klienti) smetaat na toa deka odreden aspekt na kodot da ostane neizmenet. Zna~i Vie sakate da go promenite, a tie sakaat da ostane neizmenet. Zatoa edna od glavnite celi na objektnoorientiraniot dizajn e da se oddelat rabotite {to se menuvaat od rabotite {to ostanuvaat isti. Ova e od osobena va`nost za bibliotekite. Korisnicite na biblioteka mora da se potpiraat na delot koj go koristat i da znaat deka nema da ima potreba od povtorno pi{uvawe na kodot ako izleze nova verzija od taa biblioteka. Od druga strana, kreatorot na bibliotekata mora da ima sloboda pri praveweto popravki i razli~ni podobruvawa, a pritoa da bide siguren deka tie promeni nema da vlijaat na kodot na klientskata programa. Seto toa mo`e da se postigne so pomo{ na konvencija. Na primer, programerot na bibliotekata mora da se soglasi deka nema da gi otstrani postoe~kite metodi koga }e modificira edna klasa od bibliotekata, bidej}i toa bi go naru{ilo kodot na programerot klient. Obratnata situacija e zna~itelno potrnliva. Vo slu~aj na pole, kako mo`e kreatorot na bibliotekata da znae vo koi poliwa pristapile programerite klienti? Ova isto taka va`i za metodite koi {to se samo del od realizacijata na klasa, a ne se nameneti za direktno koristewe od strana na programerot klient. [to ako kreatorot na bibliotekata saka da ja otfrli starata realizacija i da napi{e nova?
1 Videte Refactoring: Improving the Design of Existing Code, napi{ano od Martin Fowler i dr. (Addison-Wesley, 1999). Povremeno nekoj se buni protiv povtornata podelba na prosti faktori, sugeriraj}i deka kodot koj raboti e sovr{en i deka e samo
Kontrola na pristapot
197
gubewe vreme da se deli na prosti faktori. Problemot so ovoj na~in na razmisluvawe e deka lavovskiot del od parite i vremeto za proektot ne le`i vo po~etnoto pi{uvawe na kodot, tuku vo negovoto odr`uvawe. Poednostavnuvaweto na kodot za toj da bide porazbirliv, zna~i za{teda na mnogu pari.
Promenuvaweto na koj bilo od ovie ~lenovi mo`e da go naru{i programerskiot kod. Ottuka, na sozdava~ite na bibliotekite im se vrzani racete i ne mo`at ni{to da menuvaat. Za da go re{i ovoj problem, Java ovozmo`uva specifikatori na pristapot koi na na kreatorot na bibliotekata mu ovozmo`uvaat da mu nazna~i na programerot klient {to mu e dostapno, a {to ne. Nivoata na kontrolata vrz pristapot se od celosen pristap do najmal pristap. Tie se public, protected, paketen pristap (za koj ne postoi rezerviran zbor) i private. Od prethodniot pasus mo`e da pomislite deka kako dizajner na bibliotekata }e sakate da ~uvate se kolku {to e mo`no poprivatno, a da gi izlo`ite samo metodite {to sakate programerot klient da gi koristi. Ova e vsu{nost to~no, iako ~esto e sprotivno na intuicijata na lu|eto {to programiraat na drugi jazici (posebno S) i onie koi {to se naviknati da pristapuvaat kon s bez nikakvi ograni~uvawa. Na krajot od ova poglavje bi trebalo da bidete ubedeni za zna~eweto na kontrolata na pristapot vo Java. Konceptot na bibliotekata od komponentite i kontrolata vrz onie koi {to imaat pristap kon tie komponenti od bibliotekata so ova ne e zavr{en. S u{te postoi pra{awe za toa kako komponentite se povrzuvaat vo edna koherentna bibliote~na edinica. Vo Java paketite se pravat so pomo{ na rezerviraniot zbor package, a na specifikatorite na pristapot vlijae dali klasata e vo istiot ili vo nekoj drug paket. Na po~etokot na ova poglavje }e nau~ite kako komponentite od edna biblioteka se stavaat vo paketi, a posle toa }e mo`ete da go razberete celosnoto zna~ewe na specifikatorite na pristapot.
198
Da se razmisluva vo Java
Brus Ekel
public class PolnoIme { public static void main(String [] args) { java.util.ArrayList lista = new java.util .ArrayList(); } } ///:-
Ova brgu stanuva zamorno, pa namesto toa, najverojatno }e sakate da go koristite rezerviraniot zbor import. Ako sakate da uvezete samo edna klasa, mo`ete da go navedete imeto na taa klasa vo naredbata import:
//: pristap/EdenImport . java import java.util.Arraylist; public class EdenImport { public static void main(String [] args) { Arraylist list = new java.util.ArrayList(); } } ///:-
Sega mo`ete da ja koristite ArrayList bez kvalifikacija. Sepak, niedna druga klasa od paketot java.util ne e dostapna. Za da gi uvezete site klasi od bibliotekata, ednostavno upotrebete go znakot * kako {to vidovte vo ostanatite primeri od ovaa kniga:
import java.util. *;
Pri~inata za seto ova uvezuvawe da se obezbedi mehanizam za upravuvawe so prostorite za imiwa (imenskite prostori). Imiwata na site ~lenovi na Va{ite klasi se izolirani edno od drugo. Metodot f( ) od klasata A nema da se sudri so metodot f( ) {to ima ist potpis (lista na argumenti) od klasata V. No {to e so imiwata na klasite? Da pretpostavime deka sozdavate Stack klasa {to e instalirana na kompjuter na koj ve}e postoi klasa Stack {to e napi{ana od nekoj drug? Ova potencijalno sudirawe na imiwata e bitno za celosnata kontrola vrz imenskite prostori vo Java i za sozdavawe na edinstvena kombinacija na identifikatori za sekoja klasa. Pove}eto od primerite {to gi vidovte dosega vo ovaa kniga postoeja vo edna datoteka i bea dizajnirani za lokalna upotreba, pa ne se zanimavaa so imiwata na paketite. Ovie primeri vsu{nost bea vo paketi: neimenuvaniot ili podrazbiraniot paket. Toa sekako mo`e da se raboti i, poradi ednostavnost, ovoj pristap }e bide koristen sekade kade {to e mo`no niz ostatokot na ovaa kniga. Sepak, ako planirate da napravite biblioteki ili programi {to se prijatelski raspolo`eni kon drugi Java programi, odnosno }e vodat smetka za drugite programi na istiot kompjuter, toga{ }e morate da mislite i na spre~uvaweto na sudiri pome|u imiwata na klasite.
Kontrola na pristapot
199
Koga pravite datoteka so izvoren kod vo Java, taa datoteka voobi~aeno se narekuva edinica za preveduvawe (angliski compilation unit, translation unit). Sekoja edinica za preveduvawe mora da ima ime {to zavr{uva so .java i vnatre vo edinicata za preveduvawe mo`e da postoi edna javna (public) klasa {to mora da go ima istoto ime kako i datotekata (vklu~uvaj}i golemi i mali bukvi, no bez nastavkata na imeto na datotekata .java). Vo sekoja edinica za preveduvawe mo`e da ima samo edna klasa public . Vo sprotivno, preveduva~ot }e se po`ali. Ako ima dodatni klasi vo taa edinica za preveduvawe, tie se skrieni od nadvore{niot svet na paketot bidej}i tie ne se javni,a i pretstavuvaat klasi za poddr{ka na glavnata javna klasa.
Organizacija na kodot
Koga preveduvate datoteka .java, dobivate po edna izlezna datoteka za sekoja klasa od datotekata .java. Sekoja od tie izlezni datoteki ima isto ime kako i soodvetnata klasa vo datotekata .java, no so nastavkata .class. Ottuka, od mal broj na .java datoteki, mo`ete da dobiete prili~en broj datoteki .class. Ako ste programirale so jazik koj se preveduva vo izvr{en oblik, bi trebalo da ste naviknati na toa deka preveduva~ot pravi me|uforma (naj~esto datoteka od tipot obj) {to potoa se pakuva so drugite datoteki od istiot vid so koristewe na povrzuva~ (za da napravi izvr{na datoteka) ili so koristewe na bibliotekar ( za da napravi biblioteka). Java ne raboti na toj na~in. Programa {to funkcionira e mno`estvo od pove}e datoteki .class, {to mo`e da se spakuvaat i kompresiraat vo arhivata na Java (JAR) datotekata (so koristewe na arhivarot na Java jar). Rabotata na interpreterot na Java e da gi najde, v~ita i interpretira2 tie datoteki. Biblioteka e grupa od takvi datoteki so klasite. Sekoja izvorna datoteka obi~no ima javna klasa i proizvolen broj na privatni (nejavni) klasi, pa ottuka, za sekoja izvorna datoteka ima po edna javna (public) komponenta. Ako sakate da nazna~ite deka site ovie komponenti (sekoja vo oddelnite datoteki .java i .class) odat zaedno, se koristi rezerviraniot zbor package. Ako koristite naredba package, taa mora da bide vo prviot red koj ne e komentar vo datotekata. Koga }e napi{tete:
package pristap;
vie nazna~uvate deka edinicata za preveduvawe e del od bibliotekata pod imeto pristap. Odnosno, ka`ano so drugi zborovi, nazna~uvate deka javnoto ime na klasata, od taa edinica za preveduvawe, e pod ~adorot na imeto pristap i sekoj {to }e saka da go koristi toa ime }e mora ili potpolno da go navede imeto ili da go koristi rezerviraniot zbor import vo kombinacija so imeto pristap, so koristewe na koj bilo od izborite spomenati prethodno. (Obratete vnimanie deka konvencijata za davawe imiwa na paketi vo Java
200
Da se razmisluva vo Java
Brus Ekel
Java nalaga da se koristat samo mali bukvi, duri i za zborovite vo sredinata na imeto.) Na primer, da pretpostavime deka imeto na datotekata e MojaKlasa.java. Ova zna~i deka mo`e da ima edna i samo edna javna klasa vo taa datoteka i deka imeto na taa klasa mora da bide MojaKlasa (so ovaa kombinacija na mali i golemi bukvi):
2. Java so ni{to ne ja nametnuva upotrebata od interpreter. Postojat Java preveduva~i vo lokalniot kod koi pravat edna izvr{na datoteka.
//: pristap/mypackage/MojaKlasa.java package access.mojpaket; public class MojaKlasa { // ... } ///:-
Sega, ako nekoj saka da ja koristi klasata MojaKlasa ili nekoja druga javna klasa od paketot pristap, }e mora da go upotrebi rezerviraniot zbor import za imet