Thinking in Java

March 13, 2018 | Author: Jas Sum | Category: N/A
Share Embed Donate


Short Description

Java...

Description

Da se

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

County (Virginia) Government. Mnogu podobra kniga od site drugi knigi za Java koi {to nekoga{ sum gi videl. Kompletna, so odli~ni i soodvetno izbrani primeri i inteligentni objasnuvawa ... Za razlika od mnogu drugi knigi za Java, otkriv deka ovaa kniga e nevoobi~aena, dosledna, intelektualno iskrena, dobro napi{ana i precizna. Iskreno govorej}i, idealna kniga za prou~uvawe na Java. Anatoly Vorobey, Technion University, Haifa,

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.

Hawley, Automation Technician, Eli Lilly & Co. Najdobrata kompjuterska kniga koja {to dosega sum ja videl. Tom Holland. Ova e edna od najdobrite knigi za programski jazik {to sum gi pro~ital do sega... Najdobra od koja bilo dosega napi{ana kniga za Java. Ravindra Pai,

Oracle Corporation, SUNOS product line. Ova e najdobrata kniga za Java {to nekoga{ sum ja na{ol! Vie napravivte prekrasna rabota. Va{ata dlabo~ina e neverojatna. Vedna{ {tom knigata }e bide objavena, jas }e ja kupam. Izu~uvam Java od oktomvri 96-ta godina. Sum pro~ital nekolku knigi, i smetam deka Va{ata kniga "MORA DA SE PRO^ITA." Poslednite nekolku meseci se fokusiravme na proizvodi celosno napi{ani vo Java. Va{ata kniga mi pomogna da gi zacvrstam sodr`inite za koi {to bev nesiguren i ja pro{iri osnovata na moeto znaewe. Duri imam koristeno nekoi od Va{ite objasnuvawa kako

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,

Senior Staff Specialist, MCI Telecommunications. Izvonredna kniga. Najdobrata kniga za Java {to dosega sum videl. Jeff Sinclair, Software Engineer, Kcstral Computing. Vi blagodaram za knigata Da se razmisluva na Java. Vreme e nekoj da premine od gol jazi~en opis na vnimatelen, pronikliv analiti~ki tutorijal koj ne im se poklonuva do zemja na proizvoditelite. Sum gi pro~ital re~isi site drugi knigi - do sega, edinstveno Va{ata i knigata na Patrick Winston najdoa mesto vo moeto srce. Ve}e ja imam prepora~ano knigata na kupuva~ite. U{te edna{ Vi blagodaram. Richard Brooks, Java

Consultant, Sun Professional Services, DaUas. Brus, Va{ata kniga e izvonredna! Va{ite objasnuvawa se jasni i direktni. Preku Va{ata fantasti~na kniga jas se zdobiv so ogromno koli~estvo na znaewe za Java. Ve`bite isto taka se FANTASTI^NI i zavr{uvaat odli~na rabota zacvrstuvaj}i gi ideite objasneti vo poglavjata. So netrpenie o~ekuvam da gi pro~itam i drugite Va{i knigi. Vi blagodaram za ogromnata usluga {to ja obezbedivte so pi{uvawe na tolku sjajna kniga. Otkako ja pro~itav knigata Da se razmisluva na Java moite kodovi se mnogu podobri. Jas sum Vi blagodaren i siguren sum deka site programeri koi {to gi odr`uvaat moite kodovi isto taka Vi se blagodarni. Yvonne Watkins, Java Artisan, Discover Teehnolob-leS, Inc. Drugite knigi gi pokrivaat rabotite vo Java (gi opi{uvaat sintaksata i bibliotekite) ili kako rabotat programite vo Java (davaat prakti~ni primeri za programite vo Java). Da se razmisluva na Java e edinstvenata kniga za koja znam {to objasnuva ZO[TO Java; zo{to e dizajnirana taka kako {to e dizajnirana, zo{to raboti taka kako {to raboti, zo{to ponekoga{ ne raboti, zo{to e podobra od C++, zo{to ne e. No, taa isto taka zavr{uva dobra rabota za u~ewe na rabotite i programite vo jazikot. Da se razmisluva na Java definitivno e vistinski izbor na lu|eto {to razmisluvaat za kniga za Java. Robert S. Stephenson Vi blagodaram {to napi{avte izvonredna kniga. Kolku pove}e ja ~itam tolku pove}e mi se dopa|a. I na moite studenti im se dopa|a. Chuck

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

Barrell, Network Officer Mameo, QAF Mfg. Inc.

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

Laframboise, LightWorx Technology Consulting, Inc. Porano Vi pi{uvav za moite povolni vpe~atoci za knigata Da se razmisluva na C++ (kniga {to zazema istaknato mesto na mojata polica ovde na rabota). I denes jas sum vo mo`nost da prekopuvam po Java - so Va{ata elektronska kniga vo moite virtuealni race, i moram da ka`am, "mi se dopa|a!" Mnogu informativna i objasnuva~ka, bez da se ~ita kako suvoparen tekst. Vie gi pokrivate najva`nite koncepti koi {to sé u{te se najmalku poznati za razvojot na Java: objasnuvate zo{to ne{tata se takvi. Sean Brady Jas se usovr{uvam i vo Java i vo C++, i dvete Va{i knigi bea od `ivotno zna~ewe za mene. Koga nemam poim za nekoj koncept, znam deka mo`am da smetam na Va{ite knigi za a) jasno da mi gi objasni mislite i b) da imam mno{tvo primeri za ona {to se obiduvam da go postignam. Sé u{te ne sum na{ol drug avtor koj {to kontinuirano so polno srce mo`am da go prepora~am ponatamu. Josh Asbury, A^3 Software Consulting,

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

Merwe, Software Specialist, DataFusion Systems Ltd, Stellenbosch , South Africa Ova e edna od najdobrite knigi za Java {to sum gi videl. E.F. Pritchal'd,

Senior Software Engineer, Cambridge Animation Systems Ltd., United Kingdom

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,

Senior Programmer, Art & Logic Va{ata kniga ja pro~itav za edna ili dve sedmici i ja sporediv so drugite knigi za Java {to porano sum gi pro~ital, se ~ini deka Va{ata kniga mi dava sjaen po~etok. Ja prepora~av knigata na mnogumina moi prijateli i tie ja vrednuvaa kako odli~na. Ve molam, primete gi moite ~estitki za objavuvawe na odli~na kniga. Ranta Krishna Bhupathi, Software

Engineer, TCSI Corporation, San Jose Sakam samo da ka`am kolku Va{ata kniga e "brilijantno" delo. Ja koristev kako glaven prira~nik za mojata rabota doma na Java. Otkriv deka tabelata so sodr`ina e vistinska za brzo nao|awe na baranata sekcija. Isto taka ubavo e da se vidi kniga {to ne e samo prerabotka na API nitu gi tretira programerite kako neznajkovci. Grant Sayer, Java

Components Group Leader, Ceedata Systems Ply Ltd, Australia Vau! ^itliva, dlaboka kniga za Java. Postojat mnogu siroma{ni (i dopu{teno nekolku dobri) knigi za Java, no ottuka vidov deka Va{ata kniga definitivno e edna od najdobrite. John Root, Web Developer,

Department of Social Security, London Samo {to zapo~nav da ja ~itam knigata Da se razmisluva na Java. O~ekuvam da bide mnogu dobra bidej}i navistina mi se dopadna knigata Da se razmisluva na C++ (koja {to ja pro~itav kako ve}e iskusen C++ programer, obiduvaj}i se da ostanam na vrvot) ... Vie ste ~udesen avtor. Kevin K.

Lewis, Technologist, ObjectSpace, Inc. Mislam deka ova e dobra kniga. S¡ {to znam za Java go nau~iv od ovaa kniga. Vi blagodaram {to ovozmo`ivte knigata da bide dostapna besplatno preku Internet. Da ne be{e taka, jas nema{e da znam ni{to za Java. No najdobroto ne{to e toa {to Va{ata kniga ne e komercijalna bro{ura za Java. Taa isto taka gi poka`uva i lo{ite strani na Java. Ste napravile dobra rabota so knigata. Frederik Fix, Belgium Jas bev prikovan do Va{ata kniga celo vreme. Pred nekolku godini, koga sakav da u~am C++, ima{e kniga C++ inside & Out koja {to me pro{eta niz fantasti~niot svet na C++. Taa mi pomogna da dobijam podobri mo`nosti vo `ivotot. Sega, vo potraga po pove}e znaewe i koga sakav da u~am Java, naletav na knigata Da se razmisluva na Java - bez dvoumewe vo mojata glava dali mi e potrebna druga kniga. Navistina fantasti~no. Toa e kako povtorno da se otkrivam sebesi kako {to pominuvam niz knigata. Pomina samo mesec otkako po~nav da u~am Java, i od s¡ srce Vi blagodaram, sega mnogu podobro gi razbiram rabotite. Anand Kumar S., Software

Engineer, Computervision, India

Va{ata kniga se istaknuva kako odli~en op{t voved. Peter Robinson,

University ofCambridge Computer Laboratory Ova e do sega najdobriot materijal {to sum go koristel kako pomo{ da ja nau~am Java i samo sakam da znaete kako sum sre}en {to sum go na{ol. VI BLAGODARAM! Chuck Peterson, Product Leader, Internet Product

Line, IVlS International Knigata e sjajna. Ova e treta kniga za Java koja {to sum po~nal da ~itam i ve}e pominav dve tretini od nea. Planiram da ja zavr{am ovaa kniga. Za nea se odlu~iv bidej}i taa se koristi vo nekoi interni klasovi vo Lucent Technologies i prijatelite mi ka`aa deka knigata se nao|a na Mre`ata. Dobra rabota. Jerry Nowlin, MTS, Lucent Technologies Od okolu {este knigi za Java {to sum gi nasobral do denes, Va{ata kniga Da se razmisluva na Java dosega e najdobrata i najjasnata. Michael Van

Waas, Ph.D., President, TMR Associates Samo sakam da Vi ka`am blagodaram za Da se razmisluva na Java. Kakva ~udesna kniga ste napravile! I da ne spomnuvame {to besplatno mo`e da se prezeme od Internet! Kako student otkriv deka Va{ata kniga e neprocenliva (Imam kopija od C++ In side Out , u{te edna dobra kniga za C++), bidej}i taa ne me u~i samo kako ne{to da napravam, tuku i za toa zo{to da go napravam, {to sekako e mnogu va`no za izgradba na cvrsta osnova vo jazicite kako {to se C++ ili J ava. Imam mnogu prijateli koi go sakaat programiraweto isto kolku i jas, i im ka`av za Va{ite knigi. Tie za niv mislat deka se sjajni! Vi blagodaram u{te edna{! Popatno, jas sum Indone`anec i `iveam na ostrovot Java. Ray Frederick Djajadinata,

Student at Trisakti University, Jakarta Tokmu faktot {to knigata ja napravivte besplatna preku Mre`ata me {okira{e. Sakam da znaete kolku mnogu go po~ituvam i cenam {to toa go napravivte. Shane LeBouthillier, Computer Engineering student,

University of Alberta, Canada Moram da Vi ka`am so kolkavo netprpenie ~ekam da ja pro~itam Va{ata mese~na kolumna. Kako po~etnik vo svetot na objektno orientiranoto programirawe, jas go po~ituvam vremeto i serioznosta {to í gi posvetivte na sekoja poedine~na tema. Ja prezedov Va{ata kniga, no mo`ete da se oblo`ite deka }e ja kupam tvrdata kopija koga taa }e bide objavena. Vi blagodaram za seta Va{a pomo{. Dan Cashmer, B. C. Ziegler & Co. Samo sakam da Vi ~estitam na dobro srabotenata rabota. Otprvin imav te{kotii so PDF verzijata na knigata Da se razmisluva na Java. I pred da zavr{am so ~itaweto na knigata, pobrzav do prodavnica i ja najdov knigata Da se razmisluva na C++. Sega, jas sum vo biznisot so kompjuteri preku osum godini, kako konsultant, softverski in`ener, nastavnik/obu~uva~, a

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

Verlag, BerteIsmann AG, Germany Vi blagodaram {to napi{avte dve sjajni knigi (Da se razmisluva na Java C++, Da se razmisluva na Java). Bezmerno mi pomognavte vo moeto napreduvawe vo objektno orientiranoto programirawe. Donald Lawson,

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

NAT-SYSTEM, Paris, France Da se razmisluva na Java dava najgolema pokrienost i objasnuvawe. Mnogu e lesna za ~itawe, a istoto go mislam i za delot so kodovi. Ron Chan,

Ph.D., Exper t Choice, Inc., Pittsburgh, Pa. Va{ata kniga e super. Imam pro~itano mnogu knigi za programirawe i Va{ata kniga sé u{te na mojot um mu dodava proniklivost za programirawe. Ningjian Wang, Information System Engineer, The

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,

University of Otago, Dunedin, New Zealand So Va{ata kniga, jas sega sfativ {to zna~i objektno orientiranoto programirawe.... Veruvam deka Java e mnogu pojasna i ~esto duri i polesna od Perl. Torsten Romer, Orange Denmark Vie ovozmo`ivte da postoi na{iroko poznat besplaten ru~ek, ne samo supa za ru~ek, tuku gurmanska naslada za onie koi cenat dobar softver i kniga za nego. Jose Suriot, Scylax Corporation

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

Ritchie, Java Research & Development Team, KL Group Inc. Navistina ova e najdobrata kniga za Java {to sum ja pro~ital! Daniel Eng Najdobrata kniga za Java {to sum ja videl! Rich Hoffarth, Senior

Architect, Wes t Group Vi blagodaram za ovaa prekrasna kniga. Mnogu se zabavuvam minuvaj}i niz glavite. Fred Trimble, Actium Corporation Vie ja usovr{ivte umetnosta poleka i uspe{no da né nau~ite da gi zgrap~ime detalite. U~eweto go pravite da bide MNOGU lesno i so zadovolstvo. Vi blagodaram za vistinski prekrasniot tutorijal.

Rajesh Rau, Software Consultant Da se razmisluva na Java go koleba slobodniot svet! Miko O'Sullivan,

President, Idocs lnc.

Za knigata Da se razmisluva vo C++: Dobitnik na Nagradata za 1995 godina na Magazinot za razvoj na softver Jolt Award za najdobra kniga na godinata "Ovaa kniga e stra{no golemo dostignuvawe. Dol`ni ste kon sebe da imate kopija na Va{ata polica. Poglavjeto za iostream e najdetaqno i najrazbirlivo obraboteno od site temi {to dosega sum gi videl."

AI Stevens Contributing Editor, Doctor Dobbs Joumal "Knigata na Eckel e edinstvenata {to tolku jasno objasnuva kako se preispituva programska konstrukcija za objektno orientiranoto programirawe. Ovaa kniga isto taka e odli~en tutorijal za vlezovi i izlezi vo C++ {to e dodaden kako bonus."

Andrew Binstock Editor, Unix Review "Bruce prodol`uva da me voodu{evuva so negovata proniclivost vo C++, a Da se razmisluva na C++ e negovata dosega najdobra kolekcija od idei. Ako sakate jasni odgovori na te{ki pra{awa za C++, kupete ja ovaa izvonredna kniga."

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++."

Richard Hale Shaw Contributing Editor, PC Magazine

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

[to }e najdete вnatre Relacii E i E-KAKO .................. 33 Predgovor

1

Java SES i SE6 .................................... 2 Java SE6 ............................................ 3 ^etvrtoto izdanie ............................. 3 Izmeni .............................................. 4 Zabele{ka za dizajnot na koricata 6 Blagodarnost ....................................... 6 Voved

11

Preduslovi......................................... 12 U~ewe na Java .................................... 12 Celi ..................................................... 13 Pou~uvawe vrz osnova na knigata . 14 Dokumentacija na Veb...................... 15

Virtuelizacija na objektite preku polimorfizam ................................... 35 Hierarhija so edinstven koren...... 39 Kontejneri.......................................... 39 Parametrizirani (generi~ki) tipovi.............................................. 41 Pravewe objekti i nivniot `ivoten vek ........................................ 42 Obrabotka na isklu~oci: spravuvawe so gre{ki ...................... 44 Paralelno programirawe ............... 45 Java i Internetot ............................. 46 Programirawe od strana na klientot ......................................... 48

Ve`bi .................................................. 15

Programirawe od strana na serverot .......................................... 54

Temelite na Java ............................... 15

Rezime .................................................. 55

Izvoren kod ....................................... 16 Se e objekt Na~in na pi{uvawe vo knigata . 18 Gre{ki ................................................ 19 Zapoznavawe so objekti

20

Razvoj na apstrakcija ....................... 21 Objektot ima interfejs .................. 23 Objektot dava uslugi........................ 26

57

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

Skriena realizacija ........................ 27

Nikoga{ nemate potreba da uni{tite objekt ................................ 63

Povtorno koristewe na realizacija......................................... 28

Oblast na va`ewe......................... 63

Nasleduvawe ...................................... 29

Oblast na va`ewe na Objektite 64

Kreirawe novi tipovi na podatoci: класа .................................................... 65

Avtomatsko zgolemuvawe i namaluvawe ......................................... 95

Poliwa i Metodi ......................... 66

Relacioni operatori ....................... 96

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

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

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

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

Paket: Bibliote~na edinica ....... 198

Razlikuvawe na preklopeni metodi ........................................... 150

Organizacija na kodot............... 200

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

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

Zadavawe na inicijalizacija .. 172 Povtorno koristewe na klasite Inicijalizacija na konstruktori ............................... 174

223

Sintaksa na kompozicijata .......... 223 Sintaksa na nasleduvawe .............. 227

Inicijalizirawe na osnovna klasa .............................................. 229

Gre{ka: „redefinirawe” na privatnite metodi ..................... 272

Delegirawe ...................................... 232

Gre{ka: poliwa i stati~ni metodi ........................................... 272

Kombinirawe na kompozicija i nasleduvawe ..................................... 234

Konstruktori i polimorfizam... 274

Garantirawe na pravilno ~istewe ......................................... 236

Redosled za povikuvawe konstruktori ............................... 274

Kriewe na imiwa ....................... 239

Nasleduvawe i ~istewe............. 277

Izbor pome|u kompozicija i nasleduvawe ..................................... 241

Odnesuvawe na polimorfnite metodi vo konstruktorite ........ 282

Rezerviraniot zbor: protected.... 243

Kovarijantni povratni tipovi.... 284

Sveduvawe nagore ........................... 244

Dizajnirawe so nasleduvawe ........ 285

Povtorno za izborot pome|u kompozicijata i nasleduvaweto246

Sporedba pome|u zamena i pro{iruvawe ............................... 287

Rezerviraniot zbor final............... 247

Sveduvawe nadolu i podatoci za tipot pri izvr{uvawe............... 288

final podatoci .............................. 247

Rezime ................................................ 290

Final metodi ................................. 251 final klasi ..................................... 254

Interfejsi

Vnimatelno so rezerviraniot zbor final ....................................... 255

292

Apstraktni klasi i metodi .......... 292 Interfejsi ....................................... 296

Inicijalizacija i v~ituvawe na klasi .................................................. 256

Potpolno razdvojuvawe ................. 301

Rezime ............................................... 258

Pro{iruvawe na interfejsot so nasleduvawe...................................... 308

„Pove}ekratno” nasleduvawe vo Inicijalizacija so nasleduvawe257 Java ..................................................... 306

Polimorfizam

260

Povtorno za sveduvaweto nagore 260

Sudir na imiwa pri kombinirawe na interfejsi .... 310

Zanemaruvawe na tipot na objektite ...................................... 262

Prilagoduvawe na interfejsot ... 311

Zastoj ................................................. 263 Vrzuvawe na povikot na metodot264 Dobivawe na pravilno odnesuvawe ................................... 265 Pro{irlivost ............................ 268

Poliwa vo interfejsi ................... 314 Inicijalizacija na poliwa vo interfejsi.................................... 315 Vgnezduvawe na interfejsi .......... 315 Interfejsi i proizvoditeli ....... 318

Rezime ............................................... 321 Vnatre{ni klasi

323

Iteratori......................................... 380 ListIterator...................................... 383

Sozdavawe na vnatre{ni klasi ... 323

Povrzana Lista ............................... 384

Vrska so nadvore{nata klasa ...... 325

Stack ................................................... 386

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

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

Vnatre{ni klasi i skeleti na upravuvawe ................................... 350

Osnovni Isklu~oci........................ 415

Nasleduvawe na vnatre{ni klasi357

Argumenti na isklu~ok ............. 416

Dali vnatre{nata klasa mo`e da se redefinira? .................................... 358

Fa}awe na isklu~ok ....................... 417 Blokot try ................................... 417

Lokalni vnatre{ni klasi ............ 360

Pravewe na sopstveni isklu~oci 420

Identifikatori na vnatre{nite klasi .................................................. 362

Isklu~oci i zapi{uvawe ......... 422

Rezime ............................................... 362 ^uvawe objekti

364

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

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

String.format() ............................... 489

Specijalen slu~aj: RuntimeException ..................... 438

Alatka za ispi{uvawe vo heksadecimalen format ............ 490

^istewe so odredbata finally ....... 440

Za {to slu`i odredbata finally?442 Regularni izrazi............................. 491 Koristewe na finally pri vra}awe so return ....................... 445

Osnovi ........................................... 492

Nedostatok: zagubeniot isklu~ok446

Kvantifikatori ......................... 497

Kreirawe na regularni izrazi 495

Ograni~uvawe kaj isklu~oci ....... 448

CharSequence .............................. 498

Konstruktori .................................. 452

Klasite Pattern i Matcher ......... 499

Pronao|awe na sli~ni isklu~oci458

Metodot find() .............................. 501

Alternativni pristapi ................ 459

Grupi ............................................. 502

Istorija ....................................... 461

Metodite start() i end()............. 503

Perspektivi ................................ 462

Indikatori na klasata Pattern 505

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

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

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

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

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

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

Argumenti so promenlivi dol`ina i generi~ki metodi ... 594

Samoograni~eni tipovi ................ 654

Generi~ki metod koj se upotrebuva so Generator-i ....... 595

Generi~ki kod koj neobi~no se povtoruva...................................... 655

Generator za op{ta namena...... 596

Samoograni~uvawe ..................... 656

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

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

Latentni tipovi ............................. 672

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

Popolnuvawe na kontejneri ......... 737

Koga slu~ajno nemate soodveten interfejs...................................... 682

Re{enie na baza na Generator . 738

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

[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

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

LinkedHashMap .......................... 779

Klasata File ...................................... 838

Transformirawe na klu~evi i klu~evi za he{irawe ..................... 780

Listawe na imenikot................. 839

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

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

Opasnosti od mikrosporeduvawe na performansi .......................... 810

Filtrirawe na izlezniot tek . 857

Izbor na mno`estvo (Set) ........ 811

Klasi za ~itawe i vpi{uvawe (Readers & Writers) ........................ 859

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

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

Rezime ................................................ 939 Nabroeni tipovi

^itawe binarni datoteki ........ 876 Standardni V/I tekovi ................. 877 ^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

941

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

Detalno za baferite ................. 896

Zbirot EnumSet namesto indikatori ....................................... 956

Datoteki preslikani vo memorija ....................................... 900

Koristewe na mapata EnumMap . 959

Zaklu~uvawe na datoteki ......... 903

Metodi koi se menuvaat vo zavisnost od konstantata ............. 960

Komprimirawe ................................ 906 Ednostavno komprimirawe vo formatot GZIP............................ 908

Sozdavawe sinxir na odgovornosti so pomo{ na nabroenite tipovi ..................... 964

Kompresirawe na pove}e datoteki vo Zip format ............. 909

Ma{ini na sostojbite so nabroenite tipovi ..................... 968

Java arhivi (JARs) ..................... 911

Pove}ekratno otkrivawe na tipot974

Serijalizirawe na objekti .......... 913 Pronao|awe na klasata ............. 917 Upravuvawe so serijalizacijata919 Koristewe trajnost ................... 928 XML .................................................... 934 Preferences ....................................... 937

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

Koristewe na nizata 2-D .......... 982 Zaklu~ok ........................................... 983 Anotacii

985

Osnovna sintaksa ............................ 986 Definirawe na anotacijata .... 987 Metaanotacii ............................. 989

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

Pi{uvawe procesori na anotaciite........................................ 990

Klasa Thread ............................. 1039

Elementi na anotaciite ........... 991

Upotreba na izvr{iteli (Executors) ................................ 1041

Ograni~uvawa na podrazbiranite vrednosti ....... 991 Generirawe na nadvore{ni datoteki........................................ 992 Drugi re{enija ........................... 995 Anotaciite ne podr`uvaat nasleduvawe ................................. 996

Dobivawe povratni vrednosti od zada~ite ...................................... 1045 Spiewe ........................................ 1046 Prioritet .................................. 1048 Prepu{tawe .............................. 1050 Servisni ni{ki ........................ 1050

Realizacija na procesorot....... 996

Varijanti na programirawe ... 1055

Koristewe na alatkata apt za obrabotka na anotaciite .............. 999

Terminologija ........................... 1061

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

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

Atomskite operacii i momentalnata vidlivost......... 1078

CountDownLatch - brava so odbrojuvawe ............................... 1143

Atomski klasi .......................... 1086

Bezbednost na ni{kite od bibliotekata ............................. 1145

Kriti~ni oddeli ...................... 1087 Sinhronizacija so drugi objekti1093 Lokalen sklad na ni{ki ......... 1094 Otka`uvawe na zada~ite............. 1096

Klasata CyclicBarrier.............. 1146 DelayQueue ............................... 1148 PriorityBlockingQueue ........... 1151

Ukrasna gradina ....................... 1096

Kontrolor na staklenikot so pomo{ na ScheduledExecutor1154

Otka`uvawe na blokiranite zada~i .......................................... 1100

Semafor ..................................... 1158

Sostojbi na ni{kite ............... 1100

Exchanger .................................. 1162

Premin vo sostojba na blokiranost ............................... 1101 Prekin na izvr{uvaweto ....... 1101 Blokiranost predizvikana od zaemno isklu~ivata brava (mutex) ........................................ 1107 Meѓusebna 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 pomeѓu zada~ite ............................. 1135

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

Zaemna blokada ............................. 1137

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

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

Prira~ni soveti ...................... 1244

Ispituvawe na zrnata so klasata Introspector ............................... 1298

Ednoredni poliwa za tekst.... 1244

Ponapredno zrno ...................... 1303

Rabovi ......................................... 1246

Zrnata na Java i sinhronizacijata ...................... 1307

Mala programa za ureduvawe na tekstot ........................................ 1247

Pakuvawe na zrnoto ................. 1311

Poliwa za potvrda ................... 1248

Poslo`ena poddr{ka za zrnata1313

Radio-kop~iwa .......................... 1250

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 Da se misli na jazikot C: osnova za Java .................................................. 1346

Preveduvawe na MXML ............ 1317 MXML i ActionScript............... 1318

Seminar Thinking in Java .......... 1347

Kontejneri i kontroli ........... 1319

CD so seminar Hands-On Java .. 1347

Efekti i stilovi ..................... 1321

Seminar Thinking in Objects ..... 1347

Nastani ....................................... 1322

Thinking in Enterprise Java ....... 1348

Povrzuvawe so Java ................. 1322

Thinking in Patterns (with Java)1348

Modeli podatoci i povrzuvawe na podatocite ............................ 1325

Seminar Thinking in Patterns ... 1349

Izgradba i primena ................. 1326

Konsultacii i revizii na dizajnite1350

Izrabotka SWT aplikaciii ...... 1328 B: Resursi

1351

Instalirawe SWT ................... 1329

Софтвер .......................................... 1351

Zdravo, SWT .............................. 1329

Programi za ureduvawe tekst i alatki za pravewe aplikacii..... 1351

Izbegnuvawe na redundantnost1332

Knigi ............................................... 1352

Menija ......................................... 1334

Analiza i proektirawe .......... 1353

Prozor~iwa so karti~ki, kop~iwa i nastani ................... 1336

Jazikot Python ......................... 1355

Grafika ...................................... 1339

Spisok na moite knigi ............ 1356

Paralelno izvr{uvawe vo SWT1341

Spisok na termini koristeni vo knigata ........................................ 1358

Sporedba na SWT i Swing...... 1343 Zaklu~ok ......................................... 1344 Resursi ........................................ 1345

Indeks

1

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.

1

Mislam deka programskiot jazik Python e najblisku do ovaa cel. Poglednete na www.Python.org

Predgovor

1

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

Java SES i SE6 Ova izdanie na knigata ima korist glavno od podobruvawata na jazikot Java koi {to kompanijata Sun najprvin gi nare~e JDK 1.5, i toa podocna gi smeni vo JDK5 ili J2SE5, za potoa na kraj da go otfrli zastarenoto "2" i go zameni so Java SE5. Mnogu od izmenite na jazikot Java SE5 bea dizajnirani da go podobrat iskustvoto na programerot. Kako {to }e vidite, dizajnerite na

2

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

3

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.

4

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

5

Zabele{ka za dizajnot na koricata Koricata na knigata Da se razmisluva na Java e inspirirana od amerikanskata varijanta na dvi`eweto za umetnost i zanaet~istvo" (American Art & Crafts Movement), dvi`ewe koe {to se pojavilo na po~etokot na 20-tiot vek i go dostignalo vrvot pome|u 1900 i 1920 godina. Dvi`eweto Art & Crafts zapo~na vo Anglija kako reakcija na ma{inskoto proizvodstvo, industriskata revolucija i stilot od viktorijanskoto vreme so premnogu ornamenti. Dvi`eweto potencira{e umeren dizajn i prirodni formi ve}e videni vo novoto umetni~ko dvi`ewe, ra~no zanaet~istvo i va`nosta na zanaet~ijata-umetnik kako edinka i ne go otfrla{e koristeweto na modernite alatki. Ima mnogu vrska so dene{nava sostojba: preo|awe vo noviot vek, evolucija od samiot po~etok na kompjuterskata revolucija do ne{to {to e podobreno i pozna~ajno, istaknuvawe na ve{tinata za pi{uvawe na softver namesto ~isto proizvodstvo na kod. Na Java gledam na istiot na~in: kako na obid za vozdignuvawe na programerite nad nivoto na tehni~ar na operativen sistem, vo nasoka na stanuvawe "softverski zanaet~ija-umetnik". I avtorot i dizajnerot na koricata (koi se prijateli od detstvoto) inspiracija nao|aat vo ova dvi`ewe i dvajcata poseduvaat mebel, lambi i drugi predmeti koi {to poteknuvaat ili se inspirirani od toj period. Drug detaq na koricite e kutija koja mo`ebi prirodonau~nik bi ja koristel za prika`uvawe na primerocite na insekti koi gi za~uval. Tie insekti se objekti staveni vnatre vo objektite na kutijata. Objektite na kutijata pak se staveni vo objektot "korica", {to go ilustrira osnovniot koncept na agregacija vo objektno orientiranoto programirawe. Na programerot lesno mu se nametnuvaat asocijacii na "buba~ki"; buba~kite ovde se fateni, i kako {to se ~ini, ubieni vo tegla za primeroci, za na kraj da bidat zatvoreni vo mala izlo`bena kutija: s¡ ova ja navestuva sposobnosta na Java da gi pronao|a, prika`uva i pokoruva buba~kite (a toa, navistina e eden od nejzinite najjaki svojstva). Za ova izdanie kreirav akvarel koj {to mo`ete da go vidite kako pozadina na koricite.

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.

6

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

7

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

8

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

9

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:

1. Da go pretstavam materijalot so ednostavni ~ekori, taka {to lesno }e mo`ete da ja prerabotite sekoja ideja pred da prodol`ite ponatamu. Vnimatelno da odberam redosled na poimite {to gi prezentiram, taka {to nema da se slu~i da naletate na ne{to so {to dotoga{ se nemate sretnato. Sekako, toa ne e sekoga{ mo`no; vo takvite situacii daden e kus voveden opis.

Voved

13

2. Da koristam, kolku {to e mo`no, poednostavni i pokusi primeri. Toa ponekoga{ mi pre~i da se zanimavam so „vistinski” problemi, no imam zabele`ano deka po~etnicite obi~no se posre}ni koga mo`at da go razberat sekoj detaq na dadeniot primer, i ne se impresionirani so obemot na problemot koj {to go re{avaat. Isto taka postoi i seriozno ograni~uvawe na koli~estvo na kod {to mo`e da se razbere vo u~ilnica. Za ova, bez somnenie }e dobivam kritiki za koristewe na „primeri-igra~ki“, no jas sum spremen da go prifatam toa vo korist na pravewe ne{to pedago{ki korisno. 3. Da Vi go dadam samo ona za {to mislam deka e zna~ajno za Vas za razbirawe na jazikot, a ne sé ona {to jas go znam. Veruvam vo hierarhija na va`nosta na informacii, kako i vo toa deka postojat raboti koi {to 95%od programerite nikoga{ nema da imaat potreba da gi znaat, detali koi {to samo zbunuvaat i ja zgolemuvaat nivnata percepcija za slo`enosta na jazikot. Da zemam primer od jazikot C: ako ja zapametite tabelata na prioriteti na operatorite (jas nikoga{ ne sum go pravel toa), mo`ete da napi{ete efikasen, no ne~itliv kod. No, dokolku malku razmislite za takov stil na pi{uvawe, }e sfatite deka toa go zbunuva onoj {to go ~ita/odr`uva kodot. Zaradi toa zaboravete gi prioritetite i koristete zagradi sekade kade {to rabotite ne se sosema jasni. 4. Sekoj del (poglavje) da bide dovolno fokusiran, taka {to vremeto na izlagawe i pauzata pome|u periodite na ve`bawe }e bide kratko. Toa slu{atelot go dr`i buden i aktiven vo tekot na seminarot, a na ~itatelot mu dava ~uvstvo deka pobrgu ja sovladuva materijata. 5. Da vi obezbedam cvrsta osnova, taka {to }e mo`ete da ja razberete teorijata dovolno dobro za da preminete na pote{ki kursevi i knigi pri izu~uvaweto na Java.

Pou~uvawe vrz osnova na knigata Prvoto izdanie na knigata proizleze od ednonedelniot seminar, {to vo periodot koga Java u{te be{e vo za~etok, be{e dovolno vreme za da se sovlada jazikot. No, kako {to Java raste{e i opfa}a{e sé pove}e mo`nosti i biblioteki, jas tvrdoglavo se obiduvav seto toa da go predavam za edna sedmica. Vo eden moment, nekoj od nara~atelite pobara od mene da gi predavam „samo osnovite”, i pravej}i go toa otkriv deka izlagaweto na celiot materijal vo edna sedmica stana ma~no i za mene i za slu{atelite. Java pove}e ne be{e „ednostaven” jazik koj {to mo`e da se predade za edna nedela. Toa iskustvo i soznanie me pottiknaa da ja reorganiziram knigata, koja {to sega e napi{ana na na~in da mo`e da poddr`i dvonedelen seminar ili dvosemestralen fakultetski predmet (kurs). Vovedniot del zavr{uva so

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.

Na~in na pi{uvawe vo knigata Vo knigata identifikatorite (metodite, promenlivite i imiwata na klasite) se ispi{ani zadebeleno. Pogolemiot broj na rezerviranite zborovi, isto taka se napi{ani zadebeleno, osven onie {to tolku mnogu se koristat {to nivnoto naglasuvawe bi bilo zamorno, kako na primer „klasa”. Za pi{uvawe na primeri vo knigata koristam opredelen stil. Toj stil soodvetstvuva so stilot {to se koristi vo kompanijata Sun prakti~no za site programi koi {to mo`ete da gi najdete na nivniot Veb sajt (vidi http://java.sun.com/docs/codeconv/index.html) i koj {to gi poddr`uva pogolemiot del na razvojnite opkru`uvawa za Java. Dokolku imate ~itano drugi moi knigi, zabele`avte deka stilot na pi{uvawe na programite {to go koristi Sun soodvetstvuva so mojot stil. Milo mi e zaradi toa, iako jas so toa (kolku {to znam) ne sum imal nikakva vrska. Pra{aweto za stilot mo`e da bide predmet na pove}e~asovni raspravi, i samo }e ka`am deka niz moite primeri ne sakam da nametnuvam pravilen stil, tuku imam pri~ini od li~na priroda zaradi koi {to go koristam takviot stil. Zatoa {to Java e programski jazik so slobodna forma, mo`ete da koristite koj bilo stil {to vam vi odgovara. Za da formatiraweto da go uredite onaka kako {to vam vi odgovara i za da go re{ite pra{aweto okolu pi{uvaweto stil, mo`ete da se poslu`ite so alatkata kako {to e Jalopy (www.triemax.com) ‡ dodeka ja pi{uvav knigava, jas se koristev so taa alatka. Programite vo knigata se ufrleni vo tekst direktno od datotekite {to se preveduvani i ispituvani na eden avtomatski sistem. Od tie pri~ini izvorniot kod pe~aten vo knigata bi trebalo da raboti bez gre{ki pri preveduvawe. Knigata se potpira na Java SE5/6, i na nea i e testirana. Dokolku sakate ne{to da nau~ite za porane{nite verzii na jazikot, a toa ne e opfateno so ova izdanie, prvoto, vtoroto i tretoto izdanie na ovaa kniga (na angliskiot jazik) mo`ete besplatno da gi prezemete od sajtot www.MindView.net .

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 moæeme da zboruvame dokolku ne se pridr`uvame do organizacija i klasifikacija na podatoci koi {to toj dogovor gi propi{uva” Beçamin Lee Whorf (1897–1941) 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 moæete 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 vaæni 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 moæe 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 narekuvame„objekti”. (]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 moæete 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 moæete i da „zadadete barawa” koi {to taa }e gi ispolni izvr{uvaj}i operacii vrz tie podatoci. Teoretski, moæete 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, moæete 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 sodræi nekoi od postojnite objekti. Toa zna~i deka moæete da ja usloænuvate 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 moæete da £ gi pratite na klasata?"

2

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 poddræuva 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 moæete da napi{ete kod koj {to }e komunicira so oblici i koj {to avtomatski }e poddræuva 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 moæe 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

Objektot ima interfejs Aristotel verojatno prv zapo~nal vnimatelno da go konceptot na tip – toj zboruval za „klasa na ribi i klasa na ptici". Idejata site objekti, iako edinstveni, istovremeno da i pripa|aat na klasa na objekti so zaedni~ki karakteristiki i odnesuvawe, direktno e iskoristena vo prviot objektno orientiran jazik, Simula-67. Negoviot osnoven rezerviran zbor class voveduva nov tip vo programata. Simula, kao {to i samoto ime ka`uva, e proektirana za razvoj na simulacii kako {to e klasi~niot problem na „bankarskiot blagajnik". Vo ovoj problem ima pove}e blagajnici, klienti, smetki, transakcii i pari~ni edinici – mnogu „objekti". Objektite koi {to se identi~ni po sé osven po nivnata sostojba vo tekot na izvr{uvaweto na programata, grupirani se vo „klasi na objekti" i ottuka poteknuva rezerviraniot zbor class. Kreirawe na apstraktni tipovi podatoci (klasi) pretstavuva osnovna ideja vo objektno orientiranoto programirawe. Apstraktnite tipovi na podatocite rabotat skoro isto kako i vgradenite tipovi: moæete da kreirate promenlivi od daden tip (koi {to vo terminologijata na objektno orentiranoto programirawe se narekuvaat objekti ili instanci) i da rabotite so tie promenlivi ({to se narekuva pra}awe na poraka ili barawe: vie pra}ate poraka a objektot sam opredeluva {to }e napravi so nea). ^lenovite (elementite) na sekoja klasa imaat nekoi zaedni~ki osobini: sekoja smetka ima saldo, sekoj blagajnik moæe da primi depozit i taka natamu. Vo isto 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, moæete 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 moæe da ispolni samo opredeleni barawa. Barawata koi {to mo`ete da gi napravite od site objekti se definirani so negoviot

4

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

Sijalica on(); off(); brighten(); dim();

Sijalica sj = new Sijalica(); sj.vkluci();

Interfejsot opredeluva kakvi barawa moæete 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 pridruæen 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 moæeme 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. Unified 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

Objektot dava uslugi Dodeka se obiduvate da razviete ili da razberete dizajn na nekoja programa, bi bilo dobro na objektite da gledate kako na „davateli na uslugi”. Va{ata programa samata }e mu dava uslugi na korisnikot, i toa so pomo{ na uslugite koi {to gi davaat drugi objekti. Va{ata cel e da sozdadete (ili u{te podobro, vo biblioteki na kodovi da najdete) mno`estvo na objekti koi {to davaat idealni uslugi koi {to }e go re{at Va{iot problem. Toa bi mo`ele da go postignete dokolku se zapra{ate: „Koga bi mo`el da gi izvle~am od {e{ir so vol{ebnoto stap~e, koi objekti vedna{ bi go re{ile mojot problem?” Na primer, da pretpostavime deka pi{uvate programa za smetkovodstvo. Bi mo`ele da zamislite odredeni objekti koi {to sodræat odnapred definirani ekrani za vnesuvawe na podatoci, drugo mno`estvo objekti koi {to izvr{uvaat smetkovodstveni presmetki, i objekt koj {to pe~ati ~ekovi i smetki na site mo`ni vidovi pe~ata~i. Nekoi od takvite objekti moæebi ve}e i postojat? Kako bi izgledale onie {to ne postojat? Kakvi uslugi bi davale tie objekti i koi objekti bi im bile potrebni za izvr{uvawe na nivnite obvrski? Dokolku rabotite na toj na~in, }e dojdete do to~ka koga }e moæete da ka`ete: „Ovoj objekt izgleda dovolno ednostavno za da moæe da se napi{e” ili „Siguren sum deka mora ve}e da postoi vakov objekt”. Toa e racionalen na~in na razlo`uvawe na problem na mno`estvo objekti. Razmisluvaweto za objekt kako davatel na uslugi ima u{te edna prednost: toa pomaga da se podobri splotenosta (usoglasenosta) na objektot. Golema kohezija e eden od temelnite kvaliteti na proektirawe na softver: toa zna~i deka razli~nite aspekti na softverskite komponenti (kakov {to e objektot, iako istoto vaæi i za metod ili biblioteka na objekti) me|usebno se „dobro vklopeni”. Pri proektirawe na objekti, programerite ~esto stavaat premnogu funkcionalnosti vo eden objekt. Koga se raboti za gore spomenatiot modul za pe~atewe na ~ekovi, vie moæete da odlu~ite deka vam vi e potreben objekt koj {to znae sé za formatiraweto i pe~ateweto. Verojatno iskustvoto }e ve nau~i deka toa e premnogu za eden objekt i deka vam vi se potrebni tri ili pove}e objekti. Eden objekt bi mo`el da bide katalog na site mo`ni izgledi na ~ekovi, od koj mo`at da se baraat informacii kako da se otpe~ati odreden ~ek. Eden objekt ili mno`estvo objekti moæe da da bide op{t (generi~ki) interfejs za pe~atewe, koj{to znae sé za razli~nite vidovi pe~ata~i (no ni{to za smetkovodstvoto – takov objekt e kandidat za da go kupite, namesto sami da go pi{uvate). A tret objekt moæe da gi koristi uslugite na prethodnite dva za da ja izvr{i rabotata. Taka sekoj objekt bi imal usoglaseno mno`estvo na uslugite {to gi dava. Vo dobar objektno orientiran proekt, sekoj objekt dobro izvr{uva edna rabota, no ne se obiduva da izvr{uva pove}e razli~ni raboti. Ne samo {to taka mo`at da se najdat objekti {to bi trebalo da se kupat (da re~eme, objekt

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 moæe da gi koristi sokrienite delovi, a toa zna~i deka avtorot na klasata moæe 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 vaæno 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, moæebi 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 izloæeno 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

Mu se zablagodaruvam na svojot prijatel Scott Meyersu za terminot.

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, moæete 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 moæe 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.

Povtorno koristewe na realizacija [tom }e se napravi i testira klasata, taa (vo idealen slu~aj) bi trebalo da pretstavuva korisna ednica na kodot. Na krajot se poka`uva deka povtornoto koristewe ne e nitu blisku do lesno ostvarlivo kako {to mnogumina se nadevaat; potrebno e iskustvo i proniklivost za da se proizvede pove}ekratno upotrebliv objekt. No {tom imate takov dizajn, toj moli da bide povtorno iskoristen. Povtorno koristewe na kodot e edna od najgolemite prednosti na objektno orientiranite programski jazici. Najednostavniot na~in povtorno da ja iskoristite klasata e direktno da koristite objekt od taa klasa; me|utoa, objektot na taa klasa isto taka

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, moæe 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 moæe 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 moæe 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

Virtuelizacija na objektite preku polimorfizam Ako imate rabota so hierarhija na tipovi, ~esto objektot ne go tretirate kako specifi~en tip, tuku kako osnoven tip. Toa vi ovozmo`uva da pi{uvate kod koj {to ne zavisi od specifi~nite tipovi. Vo prethodniot primer so oblici, metodite manipuliraat so generi~kite tipovi (oblicite) bez obzir na toa dali se raboti za krugovi, kvadrati, triagolnici ili duri za oblici koi sé u{te ne se definirani. Site oblici mo`at da bidat iscrtani, izbri{ani i pomesteni, taka {to ovie metodi ednostavno ispra}aat poraka do objektot od tip oblik i ne se gri`at kako objektot }e izleze na kraj so taa poraka. Takov kod e nezasegnat ni po dodavawe na novi tipovi, a so dodavaweto na novi tipovi, objektno orientiranata programa naj~esto se pro{iruva koga treba da se sovlada nekoja nova situacija. Na primer, mo`ete da izvedete nov podtip na oblikot, so ime petagolnik, bez modifikacija na metodite koi rabotat samo so generi~ki oblici. Mo`nosta programata lesno da se pro{iri so izveduvawe novi podtipovi e eden od osnovnite na~ini da se kapsulira promena. So toa zna~itelno se unapreduva programata i istovremeno se namaluvaat tro{ocite za odr`uvawe na softverot. Problemot nastanuva pri obidot objektite od izveden tip da se tretiraat kako generi~ki osnovni tipovi (krugovite kako oblici, velosipedite kako vozila, kormoranite kako ptici i taka natamu.). Ako metodot mu naredi na generi~kiot oblik da se iscrta ili na generi~koto vozilo da go zavrti volanot ili na generi~kata ptica da se pomesti, preveduva~ot za vreme na preveduvaweto ne mo`e to~no da znae koj del od kodot }e bide izvr{en. Toa i e poentata - koga porakata e pratena, programerot ne saka da znae koj del od kodot }e bide izvr{en. Metodot za crtawe mo`e podednakvo da se primeni na krug, kvadrat ili triagolnik, a objektot }e go izvr{i soodvetniot kod vo zavisnost od svojot specifi~en tip. Ako ne mora da znaete koj del od kodot }e bide izvr{en, toga{ koga }e dodadete nov podtip; kodot {to toj nov tip }e go izvr{uva mo`e da bide poinakov, a pritoa da ne mora ni{to da menuvate vo metodot koj {to go povikuva. Zna~i, preveduva~ot ne mo`e to~no da znae koj del od kodot }e bide izvr{en, pa toga{ {to toj da pravi? Na primer, vo sledniot dijagram, objektot KontrolerNaPtici raboti samo so generi~ki objekti od tip Ptica i ne znae od koj tip se tie. Ova e pogodno od perspektiva na KontrolerotNaPtici bidej}i ne treba da se pi{uva poseben kod koj {to bi odredil so to~no koj tip na Ptici se raboti, ili kakvo e odnesuvaweto na taa odredena Ptica. Kako se slu~uva da, koga }e se povika metodot pomestiSe( ) pri ignorirawe na

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

Hierarhija so edinstven koren Edno od pra{awata vo OOP koe {to stana mnogu zna~ajno po voveduvaweto na C++ glasi: dali site klasi treba da bidat izvedeni od edinstvena osnovna klasa. Vo Java (i vo re~isi site drugi OOP jazici osven C++) odgovorot e potvrden, a imeto na ovaa osnovna klasa e ednostavno Object. Se ispostavuva deka postojat brojni prednosti na hierarhijata so edinstven koren. Site objekti vo hierarhijata so edinstven koren imaat zaedni~ki interfejs i spored toa, site se od ist, osnoven tip. Postoi i druga mo`nost (koja ja nudi C++), site objekti da ne bidat od ist osnoven tip. Po vertikalna kompatibilnost ova pove}e odgovara na modelot na jazikot C i mo`e da se smeta pomalku restriktiven; no koga sakate da se zanimavate so objektno orientiranoto programirawe vo celina, mora da izgradite Va{a sopstvena hierarhija za da ja obezbedite istata pogodnost (udobnost) koja e ve}e vgradena vo drugite OOP jazici. Isto taka, vo sekoja nova biblioteka na klasi koja }e ja nabavite, }e bide koristen nekoj drug nekompatibilen interfejs. Treba da se vlo`i napor (i verojatno pove}ekratno nasleduvawe) za da go vgradite toj nov interfejs vo Va{ata programa. Dali dodatnata „fleksibilnost” na C++ e vredna za toa? Ako vi treba - ako ste vlo`ile mnogu vo C - prili~no e vredna. Dokolku po~nuvate od nula, drugite jazici, kako Java, ~esto mo`at da bidat mnogu poproduktivni. Site objekti vo hierarhija so edinstven koren (kakva {to obezbeduva Java) sigurno imaat odredena zaedni~ka funkcionalnost. Znaete deka mo`ete da izvr{ite odredeni osnovni operacii nad sekoj objekt vo va{iot sistem. Hierarhijata so edinstven koren, so sozdavaweto dinami~ki objekti, mnogu go poednostavuva prosleduvaweto argumenti. Hierarhijata so edinstven koren ja olesnuva realizacijata na sobira~ot na otpad, {to e edna od temelnite podobruvawa na Java vo odnos na jazikot C++. Bidej}i pri izvr{uvaweto, vo site objekti e garantirano postoeweto na informacii za tipot na objektot, nikoga{ nema da naidete na objekt ~ij tip ne mo`ete da go utvrdite. Ova e osobeno va`no kaj operaciite na sistemsko nivo, kako {to e i obrabotkata na isklu~oci, i obezbeduva pogolema fleksibilnost pri programiraweto.

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.

Parametrizirani (generi~ki) tipovi Pred Java SE5, kontejnerite mo`ea da sodr`at edinstven univerzalen tip elementi koj {to postoi vo Java: Object. Hierarhijata so edinstven koren zna~i deka sé e od tipot Object, taka {to kontejnerot koj {to mo`e da ~uva Object, mo`e da ~uva {to bilo7. Ova go poednostavuva povtornoto koristewe na kontejnerite. Za da koristite takov kontejner, ednostavno dodadete vo nego referenci na objekti, a podocna pobarajte gi nazad. Me|utoa, bidej}i kontejnerot ~uva samo tip Object, koga }e dodadete referenca na svojot objekt vo kontejnerot, taa se sveduva nagore na Object i go gubi identitetot. Koga }e ja izvadite od kontejnerot, dobivate referenca na Object, a ne referenca na tipot koj {to ste go stavile vnatre. Kako toga{ da ja vratite taa referenca vo ne{to {to ima konkreten tip objekt koj {to ste go stavile vo kontejnerot? Ovde povtorno se koristi sveduvawe tipovi, no ovoj pat ne sveduvate nagore po hierarhijata na nasleduvawe do poop{t tip, tuku se simnuvate po hierarhijata do odreden tip. Ovoj na~in na konverzija se narekuva sveduvawe nadolu (ang. downcasting). Pri sveduvaweto nagore, na primer, znaete deka Krug e od tipot Oblik, pa mo`ete slobodno da izvr{ite sveduvawe nagore; me|utoa, ne zneete deka nekoj Object e zadol`itelno Krug ili Oblik, pa sveduvaweto nadolu ne e ba{ sigurno, osven ako znaeme so {to imame rabota. Ova i ne e premnogu opasno: ako izvr{ite pogre{no sveduvawe nadolu, se javuva gre{ka pri izvr{uvaweto - isklu~ok (ang. exception), koja naskoro }e bide opi{ana. Koga od kontejnerot zemate referenci, mora da obezbedite nekoj na~in da zapomnite na {to tie referenci se odnesuvaat za da mo`ete da izvr{ite pravilno sveduvawe nadolu. Sveduvaweto nadolu i proverkite pri izvr{uvawe pobaruvaat dopolnitelno vreme za izvr{uvawe na programata i dopolnitelen napor od programerot. Zarem ne bi bilo logi~no nekako da napravime kontejner taka {to toj znae koi tipovi gi ~uva, so {to se isklu~uva potreba za sveduvawe nadolu kako i mo`nite gre{ki. Ova se re{ava so pomo{ na parametrizirani tipovi, a toa se klasi koi preveduva~ot avtomatski mo`e da gi prilagodi taka {to }e rabotat so odreden tip. Na primer, parametriziraniot kontejner 6 Ne mo`e da ~uva prosti tipovi, no avtomatskoto pakuvawe (ang. autoboxing) koe go donese Java SE5 re~isi potpolno go otstranuva toa ograni~uvawe. Za toa }e se zboruva ponatamu vo knigata.

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 = new Array List(); 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.

Pravewe objekti i nivniot `ivoten vek Eden od klu~nite pra{awa pri rabota so objekti e na~inot na koj objektite se sozdavaat i uni{tuvaat. Za da mo`e da postoi, na sekoj objekt mu se neophodni nekoi resursi, prvenstveno memorija. Koga objektot ve}e ne e potreben, toj mora da se is~isti za resursite da se oslobodat i da bidat dostapni za povtorno koristewe. Vo ednostavnite programski situacii pra{aweto kako da se is~isti objekt ne izgleda premnogu komplicirano: pravite objekt, go koristite kolku {to vi e potrebno, a potoa toj treba da se uni{ti. Me|utoa, mo`ni se i poslo`eni situacii. Da pretpostavime, na primer, deka pi{uvate programa za upravuvawe so vozdu{niot soobra}aj na nekoj aerodrom. (Istiot model bi mo`el da se primeni i na rakuvawe so sandacite vo nekoe skladi{te, ili na sistemot na iznajmuvawe video kaseti, ili na smestuvawe na doma{ni mileni~iwa.) Na prv pogled, ova izgleda ednostavno: napravete kontejner za ~uvawe avioni, a potoa napravete nov avion i stavete go vo kontejnerot sekoj pat koga avionot }e vleze vo zona na kontrola na vozdu{niot soobra}aj. Za da go is~istite sistemot koga avionot }e ja napu{ti zonata, is~istete go soodvetniot objekt avion od memorijata. Mo`ebi imate i nekoj drug sistem za zapi{uvawe podatoci za avionite za koi {to ne treba neposredno da se vodi smetka. Mo`ebi toa e evidencija za planovi na letawe na malite avioni koi go napu{taat aerodromot. Zna~i, vi treba i drug kontejner za mali avioni i koga i da napravite objekt avion, ako toa e mal avion, isto taka bi go stavile i vo ovoj drug kontejner. Potoa nekoj pozadinski proces bi gi izvr{uval operaciite nad objektite od toj kontejner koga presmetuva~ot ne pravi ni{to drugo. Sega problemot e ne{to pote`ok: kako voop{to mo`ete da znaete koga da gi uni{tite objektite? Koga }e zavr{ite so objektot, mo`ebi sé u{te mu e

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.

Obrabotka na isklu~oci: spravuvawe so gre{ki U{te od prvite programski jazici, obrabotka na gre{ki bila edna od najte{kite pra{awa. Bidej}i e te{ko da se napravi dobra {ema za obrabotka na gre{ki, vo mnogu jazici taa oblast i toa pra{awe se zanemareni, a problemot se prepu{ta na proektantite na biblioteki. Proektantite na biblioteki na{le polovi~ni merki koi {to dobro funkcioniraat vo mnogu situacii, no lesno mo`at da se zaobikolat, obi~no so ignorirawe. Osnovniot problem so site {emi za obrabotka na gre{ki e toa {to se potpiraat na pretpazlivosta na programerot vo sledeweto na 8

Prostite tipovi, za koi podocna }e doznaete pove}e, pretstavuvaat specijalen slu~aj.

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

za sekoe od tie re{enija. Celiot klient/server problem treba{e seopfatno da se re{i.

Veb kako xinovski server Veb-ot vsu{nost e eden xinovski sistem klient/server, i ne{to polo{o od toa, bidej}i site serveri i site klienti postojat zaedno vo isto vreme vo samo edna mre`a. Toa ne morate da go znaete bidej}i se gri`ite samo za povrzuvaweto i interakcijata so eden server vo opredelen moment (iako mo`ebi pritoa talkate nasekade baraj}i go soodvetniot server). Vo po~etokot toa be{e ednostaven ednonaso~en proces. Vie postavuvavte barawe za server i toj vi prosleduval datoteka koja softverot na Va{ata prebaruva~ka ma{ina (browser software) (t.e. klientot) ja preveduva i formatira na Va{ata lokalna ma{ina. No, za kratko vreme lu|eto sakaa da pravat ne{to pove}e otkolku samo da prosleduvaat stranici od serverot. Sakaa polna klient/server kompatibilnost, za klientot da ima mo`nost da vra}a podatoci na serverot, na primer, da prebaruva bazi na serverot, da dodava novi informacii na serverot, ili da ostavi nara~ka ({to pobaruva posebni bezbednosni merki). Ova se promenite ~ii {to svedoci bevme vo tekot na razvojot na Veb. Veb prelistuva~ot (browser) be{e golem ~ekor napred: ja vovede mo`nosta del od informacija da se prika`uva na koj bilo tip kompjuter, bez nikakva izmena. Tie prelistuva~i sepak bea prili~no primitivni i nabrzo se zaglavija vo barawata koi {to im bea postaveni. Ne bea premnogu interaktivni; go zadu{uvaa serverot i samiot Internet, bidej}i sekoj pat koga sakavte da napravite ne{to za {to e potrebno programirawe, treba{e da pra}ate informacii nazad do serverot za da bidat obraboteni. Treba{e da pominat mnogu sekundi ili minuti za da otkriete deka ne{to ste vpi{ale pogre{no, bidej}i prelistuva~ot be{e predviden samo za pregled, ne mo`e{e da gi izvr{i ni najednostavnite zada~i za obrabotka. (Od druga strana , be{e potpolno bezbeden, bidej}i ne mo`e{e da izvr{i niedna programa na va{iot smeta~ koja {to mo`e{e da sodr`i gre{ki ili virusi.) Za da se re{i ovoj problem, bea prezemeni pove}e pristapi. Za po~etok, bea podobreni grafi~kite standardi za da se ovozmo`i podobra animacija i video prikaz vo prelistuva~ite. Drugiot del od problemot mo`e da bide re{en samo so vgraduvawe vo prelistuva~ot na mo`nosta za izvr{uvawe programi na stranata na klientot. Toa se narekuva programirawe od strana na klientot (angl. client-side programming).

Programirawe od strana na klientot Po~etniot dizajn na Veb (server-prelistuva~) ovozmo`uva{e interaktivna sodr`ina, no celokupnata interaktivnost ja obezbeduva{e serverot. Serverot prave{e stati~ki stranici za klientskiot prelistuva~ koi {to 48

Da se razmisluva vo Java

Brus Ekel

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.

Programirawe od strana na serverot Do sega pra{aweto za programirawe od strana na serverot be{e zanemareno, a spored mnogumina, tokmu tuka Java ima{e najgolemi uspesi. [to se slu~uva koga }e pratite barawe do serverot? Naj~estoto barawe e: „Prati mi ja ovaa datoteka”. Va{iot prelistuva~ toga{ ja interpretira taa datoteka na soodveten na~in: kako HTML stranica, slika, Java aplet, skripta i taka natamu. Vo poslo`enite barawa za serverot spa|aat i transakcii so bazite na podatoci. Obi~no se bara kompleksno prebaruvawe niz bazata na podatoci, koja potoa serverot ja formatira vo HTML stranica i Vi ja pra}a kako rezultat. (Sekako, ako klientot e pointelegenten, zatoa {to sodr`i kod na Java ili skrpten jazik, mo`e da pra}a neobraboteni podatoci, a potoa tie da se formatiraat na stranata na klientot, {to bi bilo pobrzo i pomalku bi go optovarilo serverot.) Mo`ebi }e posakate da go registrirate svoeto ime vo bazata na podatoci koga pristapuvate vo nekoja grupa ili koga ostavate nara~ka, {to }e predizvika promeni vo taa baza. Pi{uvawe programi koi {to obrabotuvaat takvi barawa na serverot se narekuva programirawe od strana na serverot (angl. server-side programming). Tradicionalno,

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)

Iako se bazira na S++, Java e „po~ist” objektnoorientiran jazik (OOP). S++ i Java se hibridni jazici, no dizajnerite na Java smetaa deka hibridizacijata na Java ne e tolku va`na kako {to be{e vo S++. Vo hibridniot jazik mo`at da se koristat pove}e programski stilovi. S++ e hibriden so cel da poddr`i povratna kompatibilnost so jazikot S. Bidej}i S++ e nadmno`estvo na S, toj sodr`i mnogu nesakani osobini od S, koi mo`e da napravat nekoi od aspektite na S++ da bidat premnogu slo`eni. Jazikot Java e napraven za onie koi sakaat da se zanimavaat samo so objektno orientirano programirawe OOP. Ova zna~i deka }e mora da razmisluvate objektno-orientirano (osven ako ve}e ne razmisluvate taka). Ovoj po~eten napor }e Vi se isplati bidej}i }e bidete sposobni da programirate na jazik koj e poednostaven za u~ewe i slu{awe otkolku mnogu drugi OOP jazici. Vo ova poglavje }e gi razgledame osnovnite komponenti na edna Java programa i }e nau~ime deka vo Java (re~isi) sé e objekt.

Rabota so objektite preku referenci Sekoj programski jazik si ima svoi na~ini za rabota so elementite vo memorijata. Programerot ~esto mora da bide svesen za tipot na rabotata {to se primenuva. Dali so elementot }e rabotite direktno ili preku posredno (indirektno) pretstavuvawe (poka`uva~ vo S ili S++), koe se opi{uva so posebna sintaksa? Sevo ova e poednostaveno vo Java. Sî tretirate kako objekt, so koristewe na ista dosledna sintaksa. Iako }e tretirate sî kako objekt, identifikatorot so koj }e rabotite vsu{nost e „referenca” na objekt.*1 Zamislete televizor (objektot) i dale~inski upravuva~ (referencata). Se dodeka ja imate v'race referencata, imate vrska so televizorot, no koga nekoj }e re~e „Promeni go kanalot” ili “Namali go zvukot”, Vie rabotite so referencata, koja go modificira objektot. Dokolku sakate da se dvi`ite naokolu vo sobata i

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

Morate da gi kreirate site objekti Koga kreirate referenca, sakate da ja povrzete so nekoj nov objekt. Po pravilo, toa go pravite so pomo{ na noviot operator (rezerviran zbor). Noviot rezerviran zbor veli, „Napravi mi vakov nov objekt”. Zna~i, vo sledniot primer, mo`e da se ka`e: String

5 = new String(‚asdf‛);

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.

Kade se nao|a skladi{teto Korisno e da se pretstavat nekoi aspekti na izvr{uvaweto na programata posebno kako e organizirana memorijata. Ima pet razli~ni mesta za skaladirawe podatoci. 1. Registri (Register). Ova e najbrzoto skladirawe bidej}i registrite se odvoeni od drugite „skladi{ta”: se nao|aat vnatre vo procesorot.Sepak, brojot na registri e ograni~en, pa registrite avtomatski se dodeluvaat vo sklad so potrebite. Vie nemate direktna kontrola, nitu pak gledate nekoj dokaz vo va{ata programa deka registrite voop{to postojat (S i S++, pak, vi ovozmo`uvaat na preveduva~ot da mu predlo`ite dodeluvawe na registri). 2. Stek (Stack). Ovie podatoci se nao|aat vo rabotnata memorija (RAM memorijata) no imaat direktna poddr{ka od procesorot preku negoviot stek poka`uva~. Stek poka`uva~ot se pomestuva nadolu za da zazeme nova memorija, a se pomestuva nagore za da ja oslobodi taa memorija. Ova e mnogu brz i efikasen na~in na dodeluvawe na skladi{ta, od kogo pobrzi se samo registrite.Dodeka ja sozdava programata, Java sistemot mora da go znae `ivotniot vek na site stavki {to se ~uvaat na Stekot. Ova ograni~uvawe ja ome|uva fleksibilnosta na Va{ite programi, pa dodeka postoi nekoe Java skladi{te vo Stekot - posebno referencite na objekti – samite Java objekti ne se ~uvaat na Stekot. 3. Dinami~ka memorija (Heap). Ova e oblast na memorija so posebna namena (isto taka vo RAM oblasta) kade `iveat Java objektite.

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).

Specijalen slu~aj: prosti tipovi Edna grupa na tipovi, koi ~esto se koristat vo programirawe dobiva poseben tretman. Niv mo`ete da gi smetate za „osnovni” tipovi. Pri~inata za ovoj specijalen tretman e slednata: ako kreirate objekt so new, posebno mala i ednostavna promenliva, toa nema da bide mnogu efikasno, bidej}i new gi

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

boolean

-

-

-

Boolean

char

16 bits

Unicode 0

Unicode 216_1

Character

byte

8 bits

-128

+127

Byte

short

16 bits

-215

+215 – 1

Short

int

32 bits

-231

+231 – 1

Integer

long

64 bits

-263

+263 – 1

Long

float

32 bits

IEEE754

IEEE754

Float

double

64 bits

IEEE754

IEEE754

Double

void

-

-

-

Void

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

char c = ‘x’; Character ch = new Character(c):

Isto taka mo`e da koristite: Character ch = new Character(‘x’):

Java YE5 so avtomatsko pakuvawe (angliski autoboxing) avtomatski gi konvertira (pretvori, obvitka) prostite tipovi vo objekti (obvitkuva~ki tipovi): Character ch = ‘x’;

i so avtomatskoto raspakuvawe povtorno gi pretvora vo prosti tipovi: char c = ch:

Pri~inata za obvitkuvaweto (pretvoraweto) na prostite tipovi }e bidat prika`ani ponatamu vo knigata.

Broevi so golema preciznost Java sodr`i dve klasi za izveduvawe aritmeti~ki operacii so visoka to~nost: Biginteger i Bigdecimal. Iako niv re~isi mo`eme da gi smestime vo istata kategorija kako i obvitkuva~kite klasi, nitu edna od niv nema analogen prost tip. Dvete klasi imaat metodi koi obezbeduvaat operacii analogni na operaciite {to gi izveduvate nad prostite tipovi. Toa zna~i deka mo`ete da napravite sî so Biginteger i Bigdecimal {to bi mo`ele da napravite so int ili so float, no }e morate da koristite posebni povikuvawa na metodi namesto na operatori. Isto taka, bidej}i zada~ate e poslo`ena poradi pove}e vklu~eni raboti, operaciite }e se odvivaat pobavno. Brzinata ja zamenuvate so to~nosta. Biginteger poddr`uva celobrojni vrednosti so proizvolna golemina. Ova zna~i deka }e mo`ete to~no da gi pretstavite celobrojnite vrednosti so koja bilo golemina bez da zagubite informacija vo tekot na operaciite. Bigdecimal slu`i za broevi so podvi`na zapirka so proizvolna golemina. Na primer, niv mo`ete da gi koristite za precizni pari~ni presmetki. Vo JDK dokumentacijata pobarajte detali vo vrska so konstruktorite i metodite {to }e mo`ete da gi povikuvate za ovie dve klasi.

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.

Nikoga{ nemate potreba da uni{tite objekt Vo pove}eto programski jazici, konceptot za `ivotniot vek na promenlivata bara pogolem programski napor. Kolku dolgo `ivee promenlivata? Ako treba da ja uni{tite, koga da go storite toa? Konfuzijata zaradi `ivotniot vek na promenlivite mo`e da dovede do mnogu gre{ki, pa ovoj del od knigata }e vi poka`e kako Java gi poednostavuva problemite so toa {to pravi site ~istewa namesto Vas.

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.

Oblast na va`ewe na Objektite Objektite vo Java nemaat ist `ivoten vek kako prostite tipovi. Koga kreirate Java objekt koristej}i new, toj postoi i po krajot na oblasta na va`ewe vo koj e napraven. Ottuka, dokolku koristite: { }

String 5 = new String(‚nekoja znakovna niza‛): // Kraj na oblasta na vazenje

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.

Kreirawe novi tipovi na podatoci: класа Ako sé e objekt, {to opredeluva kako odredena klasa na objekt izgleda ili se odnesuva? Ili, so drugi zborovi, {to go vospostavuva tipot na objektot. Mo`ete da o~ekuvate da postoi rezerviran zbor nare~en “tip”, i toa sekako bi imalo smisla. Istoriski gledano, sepak, pove}eto objektno-orientirani jazici go koristele zborot class {to zna~i „Sega }e vi ka`am kako eden nov tip na objekt izgleda.” Rezerviraniot zbor class ({to e tolku voobi~aen {to nema da bide ponatamu zapi{uvan so zadebeleni bukvi vo knigava) e sleden od imeto na noviot tip. Na primer: class NekoeImeNaTip { /* Ovde doaga teloto na klasata */ }

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

Podrazbirani vrednosti za podatoci od prost tip Ako podatokot od prost tip ne go inicijalizirate, toj }e dobie podrazbirana (prethodno definirana) vrednost: Podrazbiranite vrednosti se garantirani od Java samo vo slu~ai koga promenlivata se koristi kako ~len na klasa. Ova obezbeduva promenlivite ~lenovi na prostite tipovi sekoga{ da bidat inicijalizirani (ponekoga{ S++ ne go pravi ova), so {to se namaluva izvorot na gre{ki. Sepak, ovaa inicijalna vrednost ne mora da bide ispravna nitu legalna za programata koja ja pi{uvate. Najdobro e sekoga{ eksplicitno da gi inicijalizirate Va{ite promenlivite. Prosti tipovi

Podrazbirana (prethodno definirana vrednost)

boolean

false

char

„\uoooo‟(null)

byte

(byte)o

short

(short)o

integer

0

long

oL

float

o.of

double

o.od

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.)

Metodi, argumenti i povratni vrednosti Vo mnogu jazici (kako S i S++), poimot funkcija se koristi za opi{uvawe na imenuvana potprograma. Vo Java po~esto se koristi poimot metod, kako „na~in da se napravi ne{to.” Dokolku sakate, mo`e da prodol`ite da razmisluvate za funkcii. Toa e navistina samo sintaksi~ka razlika, no ovaa kniga }e go koristi voobi~aeniot poim vo Java „metod.” Metodite vo Java gi opredeluvaat porakite {to objektot mo`e da gi primi. Osnovni delovi na metodot se imeto, argumentite, povratniot tip i teloto. Eve kako izgleda edna osnovna forma: PovratenTip imeNaMetodot { /* lista na argumenti * / ) { /* telo na metodot */ }

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();

Tipot na povratnata vrednost mora da bide kompatibilen so tipot na promenlivata h. 3 stati~ni metodi, za koi }e u~ite naskoro, mo`e da se povikaat za klasata, bez objekt.

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.

Pravewe na Java programa Ima pove}e temi {to morate da gi razrabotite i razberete pred da ja sostavite Va{ata prva Java programa.

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.

Koristewe drugi komponenti Koga i da posakate da koristite odnapred definirani klasi vo va{ata programa, preveduva~ot mora da znae kako da gi pronajde. Sekako, klasata mo`e veke da postoi vo istata datoteka na izvoren kod od koja i se povikuva. Vo ovoj slu~aj, ednostavno ja koristite klasata - pa duri i ako klasata e planirana da se definira podocna vo datotekata (Java go eliminira problemot so takanare~enoto „istureno referencirawe”.) [to ako klasata postoi vo nekoja druga datoteka? Mislite deka preveduva~ot treba da e dovolno pameten za ednostavno da trgne i da ja najde? No, tuka se javuva problem. Zamislete deka sakate da koristite klasa so opredeleno ime, no za nea postoi pove}e od edna definicija (pod pretpostavka deka se razli~ni definicii). Ili, u{te polo{o, zamislete deka pi{uvate programa i dodeka ja gradite, dodavate nova klasa na va{ata biblioteka, ~ie ime se sudira so imeto na nekoja postoe~ka klasa. Za da go re{ite ovoj problem, morate da gi eliminirate site potencionalni dvosmislenosti. Toa se postignuva taka {to so rezerviraniot zbor import }e mu ka`ete na Java preveduva~ot koi to~no klasi sakate da gi koristite. Import mu ka`uva na preveduva~ot da donese paket, koj pretstavuva biblioteka na klasi. (Vo drugi jazici, bibliotekata mo`e da se sostoi od funkcii i podatoci kako i od klasi, no setete se deka site kodovi vo Java mora da bidat napi{ani vnatre vo klasata.) Pogolemiot del od vremeto }e koristite komponenti od standarnite biblioteki na Java {to se ispora~uvaat zaedno so va{iot preveduva~. So niv, ne treba da se gri`ite za dolgite, invertirani imiwa na domeni. Ednostavno pi{uvate, na primer: import java. util. Arraylist;

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

Mnogu povoobi~aeno e da se uveze mno`estvo od klasi na ovoj na~in otkolku individualno.

klu~eniot zbor static Koga kreirate klasa, obi~no opi{uvate kako objektite od taa klasa izgledaat i kako se odnesuvaat. Ne dobivate objekt se dodeka ne go napravite so koristewe na operatorot new, vo taa to~ka na objektot mu se dodeluva prostor vo memorijata (skladi{teto) i duri toga{ metodite stanuvaat dostapni. Ima dve situacii vo koi ovoj pristap ne e dovolen. Ednata e, ako sakate da imate isto skladi{te za opredeleno pole, nezavisno od toa kolku objekti od taa klasa se kreirani, ili duri ako sakate da postoi skladi{te iako ne e kreiran nieden objekt. Drugata e, dokolku vi treba metod koj ne e povrzan so nieden odreden objekt od ovaa klasa. Toa zna~i deka Vi treba metod koj mo`e da go povikate iako ne e kreiran nieden objekt. Mo`ete da gi postignete ovie dva efekta so rezerviraniot zbor static. Koga }e ozna~ite ne{to kako static, toa zna~i deka opredeleno pole ili metod ne se povrzani so nitu eden objekt od taa klasa. Ottuka, duri i ako nikoga{ ne ste kreirale objekt od taa klasa, mo`ete da go povikate metodot static ili da mu pristapite na poleto static. Vo slu~aj na obi~ni, nestati~ni poliwa i metodi, morate da kreirate objekt i da go koristite toj objekt za da pristapite na pole ili metod, bidej}i nestati~nite poliwa i metodi mora da gi znaat opredelenite objekti so koi rabotat.5 Vo nekoi objektno-orientirani jazici se koristat terminite podatoci na klasa i metodi na klasa, {to zna~i deka podatocite i metodite postojat samo za klasata vo celina, no ne i za odredeni objekti od taa klasa. Ponekoga{ vo literaturata za Java isto taka se koristat ovie termini. 5. Se razbira, bidej}i stati~nite metodi ne baraat objektite da bidat kreirani pred da se koristat, tie ne mo`at direktno da im pristapat na nestati~ni ~lenovi ili metodi so ednostavno povikuvawe na tie drugi ~lenovi bez obra}awe na imenuvan objekt (bidej}i nestati~nite ~lenovi i metodi mora da bidat povrzani so soodveten objekt).

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.

Va{ata prva Java programa Kone~no, eve ja Va{ata prva kompletna programa. Zapo~nuva so ispi{uvawe na znakovna niza, potoa datumot, koristej}i ja klasata Data od standarnata biblioteka na Java. // Zdravo.java import java.util.*; public class Zdravo { public static void main(String[] args) { System.out.println(‚Zdravo, denes e: ‚): System.out.println(new Date()): } }

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 Developer‟s 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

i kako izlezen rezultat }e dobiete poraka i datum.

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.

Komentari i vgradena dokumentacija Postojat dva tipa na komentari vo Java. Prviot e tradicionalniot stil na pi{uvawe na komentari vo jazikot S, koj {to go nasledi i S++. Ovie komentari po~nuvaat so /* i prodol`uvaat, mo`no e i vo pove}e redovi, se do */. Obratete vnimanie deka mnogu programeri go po~nuvaat sekoj red so prodol`en komentar so *, pa ~esto }e vidite: /* Ova e komentar * sto prodolzuva * vo poveke redici */

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 /** * * Sys t em.out . pr in t ln(new Date()); * */ ///:-

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 duri i lista: * * Prva stavka * Vtora stavka * Treta stavka *

Se e objekt

79

*/ public class Documentation3 {}

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 ili 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.

{@link paket.k1asa#clen na oznaki } Mnogu sli~no na oznakata @see, osven toa {to mo`e da se koristi direktno vo isto nivo i {to kako tekst ja ispi{uva oznakata kako hipervrska namesto „Pogledni isto taka”.

{@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

Wed Oct 05 14:39:36 MDT 2805 * ///:-

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.

Poednostavni naredbi za ispi{uvawe Vo prethodnoto poglavje, bevte zapoznaeni so naredbata za ispi{uvawe vo Java: System.out.println(‚Prilicno mnogu za kucanje‛);

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.

Koristewe na operatorite vo Java Operatorot zema eden ili pove}e argumenti i dava nova vrednost. Argumentite se zadavaat vo razli~na forma od obi~nite povici na metod, no efektot e ist. Sobiraweto i unarniot plus (+), odzemaweto i unarniot minus (-), mno`eweto (*), deleweto (/) i dodeluvaweto vrednosti (=) rabotat isto vo bilo koj programski jazik. Site operatori proizveduvaat vrednost od svoite operandi. Pokraj toa, nekoi operatori mo`at da ja menuvaat vrednosta na operand. Ova se vika sporeden efekt. Najvoobi~aena upotreba za operatorite {to gi modificiraat svoite operandi e da se generira ba{ toj sporeden efekt, no treba da imate na um deka proizvedenata vrednost e dostapna za va{a upotreba, kako i kaj operaciite bez sporedni efekta . Re~isi site operatori rabotat samo so prosti tipovi. Isklu~ocite se „=‟, ‟==‟ i ‟!=‟, koi rabotat so site objekti (i predizvikuvaat konfuzija vo

88

Da se razmisluva vo Java

Brus Ekel

rabotata so objektite). Pokraj toa, klasata String gi oddr`uva i operatorite „+‟ i „+=‟.

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.

Koristewe na psevdonimi pri povikuvawe na metod Psevdonimot isto taka }e se pojavi koga objektot go prosleduvate do metod: //: operatori/ProslediGoObjektot.java // Prosleduvanjeto objekti na metodi ne e nesto na sto ste naviknati. import static net.mindview.util.Print.*; class Bukva { char c: } public class ProslediGoObjektot { static void f(Bukva y) { y.c = 'z'; } public static void main(String[] args) { Bukva x = new Bukva(); x.c = 'a'; print(‚1: x.c: ‚ + x.c); f (x) ; print(‚2: x.c: ‚ + x.c);

Operatori

91

} } /* Izlez: 1: x.c: a 2: x.c: z *///:~

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

v * w : 0.028358962 v / w : 9.940527 u += v : 10.471473 u -= v : 9.940527 u *= v : 5.2778773 u /= v : 9.940527 *///:-

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.

Unarni operatori minus i plus Unarniot minus (-) i unarniot plus (=) se istite operatori kako i binarnite minus i plus. Preveduva~ot }e prepoznae {to ste sakale da upotrebite po na~inot na koj go pi{uvate izrazot. Na primer, naredbata x = -a;

ima o~igledno zna~ewe. Preveduva~ot mo`e da propoznae: x = a * -b;

94

Da se razmisluva vo Java

Brus Ekel

no ~itatelot mo`e da se zbuni, pa zatoa najdobro e da se napi{e pojasno Va{ata naredba: x = a * (-b);

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.

Avtomatsko zgolemuvawe i namaluvawe Java, kako i S, ima mnogu kratenki (angliski shortcuts). Kratenkite go pravat kodot mnogu polesen za pi{uvawe i voedno polesen ili pote`ok za ~itawe. Dve zgodni kratenki se operatorite za zgolemuvawe i namaluvawe (na angliski poznati kako auto-increment i auto-decrement). Operatorot za namaluvawe e „--” i zna~i “namali za edinica.” Operatorot za zgolemuvawe e „++” i zna~i “zgolemi za edinica.” Dokolku a e od tip int, na primer, izrazot ++a e ekvivalenten so izrazot (a =a + 1). Operatorite za zgolemuvawe i namaluvawe ne samo {to ja menuvaat vrednosta na promenlivata, tuku isto taka i ja vra}aat kako rezultat. Postojat dve verzii od sekoj tip na operator, ~esto nare~eni prefiksni i sufiksni verzii. Prefiksnoto zgolemuvawe zna~i deka operatorot ++ se pojavuva pred promenlivata, a sufiksnoto zgolemuvawe zna~i deka operatorot ++ se javuva po promenlivata. Sli~no na ova, prefiksno namaluvawe zna~i deka operatorot -- se pojavuva pred promenlivata, a sufiksno namaluvawe zna~i deka operatorot -- se pojavuva po promenlivata. Pri prefiksnoto zgolemuvawe i prefiksnoto namaluvawe (++a ili --a), najprvo se izveduva operacijata, a potoa se vra}a nova vrednost. Kaj sufiksnoto zgolemuvawe i sufiksnoto namaluvawe ( a++ ili a--), prvo starata vrednost se vra}a a potoa se izveduva operacijata. Na primer: //: operatori/AvtomatskiOperatori.java // Prikazuva operatori ++ i --. import static net.mindview.util.Print.*: public class AvtomatskiOperatori { public static void main(String[] args) { int i = 1; print(‚i : ‚ + 1); print(‚++i : ‚ + ++i); // Prefiksno zgolemuvanje print(‚i++ : ‚ + i++); // Sufiksno zgolemuvanje print(‚i : ‚ + i); print(‚--i : ‚ + --i); // Prefiksno namaluvanje print(‚i -- : ‚ + i++); // Sufiksno namaluvanje print(‚i : ‚ + i);

Operatori

95

} } /* Izlez: i : 1 ++i : 2 i ++ : 2 i : 3 -- i : 2 i -- : 2 i : 1 * ///:-

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 (), pomalo 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.

Ispituvawe ednakvost na objekti Relaciskite operatori == i ! = isto taka mo`at da se primenat na site objekti, no nivnoto zna~ewe ~esto gi zbunuvaat programerite koi se po~etnici vo Java. Eve eden primer: //: operatori/Ednakvost.java

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

print(‚i print(‚j print(‚i print(‚i print(‚i print(‚i print(‚i print(‚i

= ‚ + i); = ‚ + j); , j e ‚ + (i > j)); < j e ‚ + (i < j)); >= j e ‚ + (i >= j)); = j e true 100) System.out.println("Nadminat budzet!"); } private String oznaka = destinacija; public String procitajOznaka() { return oznaka; } }; } public static void main(String[] args) { Pratka10 p = new Pratka10(); Destinacija d = p.destinacija("Tanzanija", 101.395F); } } /* Rezultat: Nadminat budzet! *///:~

Vo vnatre{nosta na inicijalizatorot na primeroci mo`ete da vidite kod {to ne treba da se izvr{uva kako del od inicijalizator na pole (toa zna~i, naredbata if). Zna~i vo praksa, inicijalizator na primerokot e konstruktorot na anonimnata vnatre{na klasa. Sekako, vakviot pristap ima ograni~uvawa. Ne mo`ete da gi preklopite inicijalizatorite na primeroci, pa }e imate samo eden od ovie konstruktori. Anonimnite vnatre{ni klasi se na nekoj na~in poograni~eni vo sporedba so obi~noto nasleduvawe, bidej}i tie mo`at da ja pro{irat klasata ili da realiziraat interfejs, no ne i dvete raboti. A ako realizirate interfejs, mo`ete da realizirate samo eden. Ve`ba 12: (1) Povtorete ja ve`ba 7 koristej}i anonimna vnatre{na klasa. Ve`ba 13: (1) Povtorete ja ve`ba 9 koristej}i anonimna vnatre{na klasa.

Vnatre{ni klasi

337

Ve`ba 14: (1) Modificirajte ja programata interfejsi/HororFilmovi.java za interfejsite OpasnoCudoviste i Vampir da gi realizirate koristej}i anonimni klasi. Ve`ba 15: (2) Napravete klasa koja ima nepodrazbiran konstruktor (onoj so argumenti), no ne i podrazbiran (bez konstruktor koj nema argumenti). Napravete druga klasa koja ima metod {to vra}a referenca na objekt od prvata klasa. Napravete go objektot {to go vra}ate pravej}i anonimna vnatre{na klasa {to ja nasleduva prvata klasa.

Povtorno za proizvodnite metodi Poglednete kolku poubavo izgleda primerot interfejsi/Proizvoditeli.java koga }e se upotrebat anonimni vnatre{ni klasi: //: vnatresniklasi/Proizvoditeli.java import static net.mindview.util.Print.*; interface Usluga { void metod1(); void metod2(); } interface UslugaProizvoditel { Usluga zemiUsluga(); } class Realizacija1 implements Usluga { Realizacija1() {} // Paketen pristap public void metod1() {print("Realizacija1 metod1");} public void metod2() {print("Realizacija1 metod2");} } class Realizacija1Proizvoditel implements UslugaProizvoditel { public Usluga zemiUsluga() { return new Realizacija1(); } } class Realizacija2 implements Usluga { Realizacija2() {} // Paketen pristap public void metod1() {print("Realizacija2 metod1");} public void metod2() {print("Realizacija2 metod2");} } class Realizacija2Proizvoditel implements UslugaProizvoditel { public Usluga zemiUsluga() { return new Realizacija2(); } }

338

Da se razmisluva vo Java

Brus Ekel

public class Proizvoditeli { public static void uslugaPotrosuvac(UslugaProizvoditel proiz) { Usluga s = proiz.zemiUsluga(); s.metod1(); s.metod2(); } public static void main(String[] args) { uslugaPotrosuvac(new Realizacija1Proizvoditel()); // Realizaciite se megjusebno potpolno zamenlivi: uslugaPotrosuvac(new Realizacija2Proizvoditel()); } } /* Rezultat: Realizacija1 metod1 Realizacija1 metod2 Realizacija2 metod1 Realizacija2 metod2 *///:~

Sega konstruktorite za klasite Realizacija1 i Realizacija2 mo`at da bidat privatni i nema potreba da se pravi imenuvana klasa kako proizvoditel. Osven toa, ~esto }e vi treba samo eden proizvoden objekt, pa ovde e napraven kako stati~no pole vo realizacijata na interfejsot Usluga. Se dobiva i posmislena sintaksa. I primerot interfejsi/Igri.java mo`e da bide podobren so pomo{ na anonimni vnatre{ni klasi: //: vnatresniklasi/Igri.java // Skelet za igri napraven so pomos na vnatresni klasi. import static net.mindview.util.Print.*; interface Igra { boolean poteg(); } interface ProizvoditelNaIgri{ Igra zemiIgra(); } class Dama implements Igra { private Dama(){} private int potezi = 0; private static final int POTEZI = 3; public boolean poteg() { print("Dama poteg " + poteg); return ++potezi != POTEZI; } } public static ProizvoditelNaIgri proizvoditel = new ProizvoditelNaIgri() { public Igra zemiIgra() { return new Dama(); } } class Sah implements Igra {] private Sah() private int potezi = 0; private static final int POTEZI = 4;

Vnatre{ni klasi

339

public boolean poteg() { print("Sah poteg " + potezi); return ++potezi != POTEZI; } } public static ProizvoditelNaIgri = new ProizvoditelNaIgri public Igra zemiIgra() { return new Sah(); } } public class Igri { public static void igrajIgra(IgraFactory factory) { Igra s = proizvoditel.zemiIgra(); while(s.poteg()) ; } public static void main(String[] args) { igrajIgra(new ProizvoditelNaIgri()); igrajIgra(new ProizvoditelNaIgri()); } } /* Rezultat: Dama poteg 0 Dama poteg 1 Dama poteg 2 Sah poteg 0 Sah poteg 1 Sah poteg 2 Sah poteg 3 *///:~

Ne zaboravajte go sovetot od krajot na prethodnoto poglavje: najprvin pravite klasi, a ne interfejsi. Ako proektot bara interfejs, toa }e go znaete, bidej}i potrebata od nego }e bide o~igledna. Vo sprotivno, nemojte da gi vnesuvate interfejsite vo igra ako ne morate. Ve`ba 16: (1) Modificirajte go re{enieto na Ve`ba 18 od poglavjeto Interfejsi koristej}i anonimni vnatre{ni klasi. Ve`ba 17: (1) Modificirajte go re{enieto na Ve`ba 19 od poglavjeto Interfejsi koristej}i anonimni vnatre{ni klasi.

Vgnezdeni klasi Ako ne vi treba vrska pome|u objekt od vnatre{nata klasa i objekt od nadvore{nata klasa, toga{ mo`ete vnatre{nata klasa da ja proglasite za stati~na. Taa voobi~aeno se narekuva vgnezdena klasa.2 Za da go razberete zna~eweto na kvalifikatorot static koga e primenet na vnatre{na klasa, setete se deka objektot od obi~na vnatre{na klasa implicitno ja ~uva referencata na objekt od nadvore{nata klasa {to go sozdala. Koga velite

340

Da se razmisluva vo Java

Brus Ekel

deka vnatre{nata klasa e stati~na, toa ne va`i. Vgnezdenata klasa zna~i deka: 1. Za pravewe na objekti od vgnezdenata klasa ne e potreben objekt od nadvore{nata klasa. 2. Od objekt na vgnezdenata klasa ne mo`ete da pristapuvate na objekt od nadvore{nata klasa. Vgnezdenite klasi se razli~ni od obi~nite vnatre{ni klasi vo u{te eden pogled. Poliwata i metodite vo obi~nite vnatre{ni klasi mo`e da bidat samo na nadvore{noto nivo od klasata, odnosno nestati~nata vnatre{na klasa ne mo`e da ima stati~ni podatoci, stati~ni poliwa nitu stati~ni vnatre{ni klasi. Sepak, vgnezdenite klasi mo`at seto toa da go sodr`at:

2 Pribli`no sli~no na vgnezdenite klasi vo S++, osven {to tie klasi ne mo`at da pristapuvaat do privatnite ~lenovi kako vo Java //: vnatresniklasi/Pratka11.java // Vgnezdeni klasi (staticni vnatresni klasi). public class Pratka11 { private static class PratkaSodrzina implements Sodrzina { private int i = 11; public int value() { return i; } } protected static class PDestinacija implements Destinacija { private String oznaka; private ParcelDestinacija(String kade) { oznaka = kade; } public String procitajOznaka() { return oznaka; } // Vgnezdenite klasi mozat da sodrzat drugi staticni elementi: public static void f() {} static int x = 10; static class DrugoNivo { public static void f() {} static int x = 10; } } public static Destinacija destinacija(String s) { return new PDestinacija(s); } public static Sodrzina sodrzina() { return new PSodrzina(); } public static void main(String[] args) {

Vnatre{ni klasi

341

Sodrzina s = sodrzina(); Destinacija d = destinacija("Tanzanija"); } } ///:~

Vo metodot main(), ne e potreben nitu eden objekt od Pratka11. Namesto toa upotrebuvate normalna sintaksa za izbirawe na stati~en ~len za da gi povikate metodite {to vra}aat referenci na objektite na klasite Sodrzina i Destinacija. Kako {to vidovte vo prethodniot del od ova poglavje, vo obi~na (nestati~na) vnatre{na klasa, vrskata kon objektot od nadvore{nata klasa se postignuva preku specijalnata referenca this. Edna vgnezdena klasa nema specijalna referenca this, poradi {to e analogna na stati~en metod. Ve`ba 18: (1) Napravete klasa {to sodr`i vgnezdena klasa. Vo metodot main(), napravete primerok od vgnezdenata klasa. Ve`ba 19: (2) Napravete klasa koja {to sodr`i vnatre{na klasa koja i samata sodr`i svoja vnatre{na klasa. Povtorete go ova so koristewe vgnezdeni klasi. Obrnete vnimanie na imiwata na datotekite .class {to gi pravi preveduva~ot.

Klasite vo interfejsite Normalno, vo interfejsot ne mo`ete da pi{uvate kakov bilo kod, no edna vgnezdena klasa mo`e da bide del od interfejs. Koja bilo klasa {to ja smestuvate vo eden interfejs e avtomatski stati~na i javna. Bidej}i klasata e stati~na, taa ne gi prekr{uva pravilata za interfejsi- vgnezdenata klasa samo se smestuva vo imenskiot prostor na interfejsot. Mo`ete duri da go realizirate opkru`uva~kiot interfejs vo vnatre{nata klasa, i toa na ovoj na~in: //: vnatresniklasi/KlasaVoInterfejs.java // {main: KlasaVoInterfejs$Test} public interface KlasaVoInterfejs { void zdravo(); class Test implements KlasaVoInterfejs { public void zdravo() { System.out.println("Zdravo!"); } public static void main(String[] args) { new Test().zdravo(); } } } /* Rezultat: Zdravo! *///:~

342

Da se razmisluva vo Java

Brus Ekel

Pogodno e da vgnezdite klasa vo interfejs toga{ koga sakate da napravite zaedni~ki kod koj }e treba da se koristi so site razli~ni realizacii na toj interfejs. Na po~etokot od ovaa kniga predlo`iv smestuvawe na metodot main() vo sekoja klasa za nejzino testirawe. Manata na vakviot pristap e dodadenata koli~ina na preveduvan kod koj morate da go vle~ete naokolu. Ako toa pretstavuva problem, mo`ete da koristite vgnezdeni klasi za da go ~uvate va{iot testira~ki kod: //: innerclasses/ZaTestiranje.java // Smestuvanje na kod za testiranje vo staticna vnatresna klasa. // {main: ZaTestiranje$Tester} public class ZaTestiranje { public void f() { System.out.println("f()"); } public static class Tester { public static void main(String[] args) { ZaTestiranje t = new ZaTestiranje(); t.f(); } } } /* Rezultat: f() *///:~

Ova proizveduva oddelna klasa imenuvana ZaTestiranje$Tester (za da ja izvr{ite programata, napi{ete java ZaTestiranje$Tester, no vo Unix/Linux go pretvorate znakot $ vo izlezna sekvenca). Ovaa klasa mo`ete da ja koristite za testirawe, no ne morate da ja vklu~ite vo gotov proizvod. Pred da spakuvate se, samo izbri{ete ja ZaTestiranje$Tester.class. Ve`ba 20: (1) Napravete interfejs koj sodr`i vgnezdena klasa. Realizirajte go ovoj interfejs i napravete primerok od vgnezdenata klasa. Ve`ba 21: (2) Napravete interfejs {to sodr`i vgnezdena klasa {to ima stati~en metod {to gi povikuva metodite od va{iot interfejs i gi prika`uva rezultatite. Realizirajte go va{iot interfejs i prosledete primerok od va{ata realizacija na metodot.

Pristapuvawe kon nadvore{nosta pove}ekratno vgnezdeni klasi

od

Bez razlika na toa kolku dlaboko vnatre{nata klasa e vgnezdena, taa mo`e transparentno da pristapuva kon site ~lenovi na site klasi vo koi e vgnezdena, kako {to se gleda vo sledniot primer:3 //: vnatresniklasi/PristapPriPovekjekratnoVgnezduvanje.java // Vgnezdenite celnovi mozat da im pristapat na site clenovi // na site nivoa na klasite vo koi se vgnezdeni

Vnatre{ni klasi

343

class PPV { private void f() {} class A { private void g() {} public class B { void h() { g(); f(); } } } } public class PristapPriPovekjekratnoVgnezduvanje { public static void main(String[] args) { PPV ppv = new PPV(); PPV.A ppva = ppv.new A(); PPV.A.B ppvab = ppva.new B(); ppvab.h(); } } ///:~

Mo`ete da vidite deka vo klasata PPV.A.B metodite g() i f() mo`at da bidat povikani bez kakvi bilo kvalifikatori (i pokraj faktot deka se privatni). Ovoj primer isto taka ja poka`uva sintaksata koja e potrebna za gradewe objekti od pove}ekratno vgnezdeni vnatre{ni klasi pri pravewe objekti od razli~ni klasi. Sintaksata .new dodava soodvetna oblast na va`ewe, pa pri povikot za konstruktorot ne morate da go nazna~ite imeto na klasata. 3 U{te edna{ mu se zablagodaruvam na Martin Dener.

Za{to vnatre{ni klasi? Dosega vidovte mnogu sintaksa i semantika koi go opi{uvaat na~inot na koj rabotat vnatre{nite klasi, no ova ne sekoga{ dava odgovor na pra{aweto za{to tie postojat. Zo{to dizajnerite na Java pominale niz tolku pote{kotii za da ja dodadat ovaa su{tinska karakteristika na jazikot? Vnatre{nata klasa voobi~aeno nasleduva klasa ili realizira interfejs, a kodot vo vnatre{nata klasa raboti so objektot od nadvore{nata klasa vo koja bil napraven. Pa bi mo`ele da ka`ete deka vnatre{nata klasa e ne{to nalik na prozorec vo nadvore{nata klasa. Pra{aweto koe zadira vo srceto na vnatre{nite klasi e slednovo: Ako mi treba samo referenca na interfejs, za{to ednostavno ne ja napravam nadvore{na klasa da go realizira toj interfejs? Odgovorot e „Ako toa e se {to vi e potrebno, toga{ taka treba da go napravite.” Spored {to toga{

344

Da se razmisluva vo Java

Brus Ekel

vnatre{nata klasa koja go realizira interfejsot se razlikuva od nadvore{nata klasa koja go realizira toj ist interfejs. Odgovorot e deka ne mo`ete sekoga{ da gi koristite pogodnostite na interfejsite- ponekoga{ morate da rabotite so realizacii. Pa, najva`nata pri~ina za postoeweto na vnatre{nite klasi e slednava: Sekoja vnatre{na klasa mo`e nezavisno od drugite da nasledi implementacija. Ottuka, vnatre{nata klasa ne e ograni~ena so toa {to nadvore{nata klasa ve}e nasledila nekoja realizacija. Bez mo`nosta {to ja ovozmo`uvaat vnatre{nite klasi za istovremeno nasleduvawe na pove}e konkrenti ili apstraktni klasi- nekoi problemi pri proektiraweto i programiraweto bi bile nere{livi. Eden na~in za nabquduvawe na vnatre{nite klasi e kako ostatok od re{enieto na problemot so pove}ekratnoto nasleduvawe. Del od problemot go re{avaat interfejsite, dodeka vnatre{nite klasi efektivno dozvoluvaat „pove}ekratno nasleduvawe na realizacijata.” Toa zna~i deka vnatre{nite klasi efektivno vi dozvoluvaat da nasleduvate pove}e klasi koi ne se interfejsi. Za da go analizirame ova podetaqno, da ja razgledame situacijata vo koja vie imate dva interfejsi koi {to na nekoj na~in mora da bidat realizirani vo ramkite na klasa. Zaradi fleksibilnosta na interfejsite, imate dva izbora: edinstvena klasa ili vnatre{na klasa: //: vnatresniklasi/PovekjekratniInterfejsi.java // Dva nacina na koi edna klasa moze da realizira povekje interfejsi. package vnatresniklasi; interface A {} interface B {} class X implements A, B {} class Y implements A { B napraviB() { // Anonimna vnatresna klasa: return new B() {}; } } public class PovekjekratniInterfejsi { static void zemaA(A a) {} static void zemaB(B b) {} public static void main(String[] args) { X x = new X(); Y y = new Y(); zemaA(x); zemaA(y); zemaB(x); zemaB(y.napraviB());

Vnatre{ni klasi

345

} } ///:~

Pri toa, sekako, se podrazbira deka strukturata na va{ata programa e takva {to dvata na~ini da bidat logi~ni. Voobi~aeno, samata priroda na problemot upatuva na re{enieto dali da koristite edna ili vnatre{na klasa. Vo gorniot primer, od gledna to~ka na realizacijata, re~isi i da nema nikakvi razliki pome|u dvata pristapa. I edniot i drugiot }e funkcioniraat. Me|utoa, ako namesto interfejsot imate apstraktni ili konkretni klasi i ako va{ata klasa nekako mora da gi realizira i dvete, }e morate da upotrebite vnatre{na klasa: //: vnatresniklasi/PovekjekratnaRealizacija.java // Ako se vo prasanje konkretni ili apstraktni klasi, vnatresnite // klasi se edinstven nacin za dobivanje na efektot // ‚povekjekratno nasleduvanje na realizacii‛. package vnatresniklasi; class D {} abstract class E {} class Z extends D { E napraviE() { return new E() {}; } } public class PovekjekratnaRealizacija { static void zemaD(D d) {} static void zemaE(E e) {} public static void main(String[] args) { Z z = new Z(); zemaD(z); zemaE(z.napraviE()); } } ///:~

Ako se nemate sretnato so problemot “pove}ekratno nasleduvawe na realizacija”, sé ostanato bi mo`ele sosem logi~no da go programirate i bez upotreba na vnatre{ni klasi. Ako koristite vnatre{ni klasi, gi dobivate slednive dodatni mo`nosti: 1. Vo eden objekt od nadvore{nata klasa mo`e da imate pove}e primeroci na vnatre{nata klasa, od koi sekoj ~uva sopstvena informacija koja zavisi od informacijata vo objektot od nadvore{nata klasa. 2. Vo edna nadvore{na klasa mo`e da imate nekolku vnatre{ni klasi, od koi sekoja go realizira istiot interfejs ili ja nasleduva istata klasa na razli~en na~in. Primer za ova }e sledi nabrgu.

346

Da se razmisluva vo Java

Brus Ekel

3. Momentot na pravewe objekt na vnatre{na klasa ne e vrzan za praveweto objekt od nadvore{nata klasa. 4. Pri rabota so vnatre{nata klasa nema potencijalno zbunuva~ka relacija „e”; vnatre{nata klasa e poseben entitet. Kako primer, ako vo programata Sekvenca.java ne koristevme vnatre{ni klasi, bi morale da napi{ete „Sekvenca e Selektor” i za opredelena sekvenca bi mo`elo da postoi samo eden Selektor. Bi mo`ele isto taka, da imate u{te eden metod, obratenSelektor(), {to proizveduva Selektor {to se vra}a nazad niz sekvencata. Ovoj vid na fleksibilnost e dostapen samo pri koristewe vnatre{ni klasi. Ve`ba 22: (2) Sekvenca.java.

Realizirajte

metod

obratenSelektor()

vo

datotekata

Ve`ba 23: (4) Napravete interfejs U so tri metoda. Napravete klasa A so metod {to vra}a referenca na U pravej}i anonimna vnatre{na klasa. Napravete vtora klasa V {to sodr`i niza od U. B bi trebalo da ima eden metod {to prifa}a i skladira vo niza referenci na U, vtor metod {to postavuva odredena referenca vo niza (odredena so argumentot na metodot) na vrednost null i tret metod {to se dvi`i niz nizata i gi povikuva metodite od U. Vo metodot main(), napravete grupa od klasata A objekti i eden objekt od klasata B. Popolnete ja B so referenci na U i bile napraveni od objektite od klasata A. Upotrebete ja klasata B za povratni povici vo site objekti od klasata A. Otstranete nekoi referenci na U od objektot B.

Zaklu~oci i povratni povici Zaklu~ok (angliski- closure) e objekt na koj mo`ete da mu pristapite i koj ~uva informacija od oblasta na va`ewe vo koj bil napraven. Od ovaa definicija mo`e da vidite deka vnatre{nata klasa e objektno orientiran zaklu~ok, zatoa {to gi sodr`i delovite od informacijata od objektot od nadvore{nata klasa („oblasta na va`ewe vo koja bil napraven”) i avtomatski ja ~uva referencata na celiot objekt od nadvore{nata klasa vo koja ima dozvola da raboti so site ~lenovi, pa duri i so privatni. Povratnite povici (angliski- callbacks) bea edni od najserioznite argumenti vo prilog na vklu~uvaweto na nekoi vidovi na mehanizmi za poka`uva~i vo Java. So pomo{ na povratnite povici, na nekoj drug objekt se dava del od informacija {to ovozmo`uva podocna da go povika nazad objektot koj mu go upatil povratniot povik. Kako {to }e vidite podocna vo ovaa kniga, ova e mnogu mo}en koncept. Ako povratniot povik se realizira koristej}i poka`uva~, sepak, mora da se potpre na toa deka programerot }e se odnesuva pravilno i deka nema da go zloupotrebi poka`uva~ot. Kako {to dosega vidovte, vo Java se te`nee kon pogolema pretpazlivost, taka {to poka`uva~ite ne se vklu~eni vo jazikot.

Vnatre{ni klasi

347

Zaklu~okot obezbeden od vnatre{nata klasa e dobro re{enie za povraten povik - mnogu pofleksibilen i posiguren od poka`uva~ot . Eve primer: //: vnatresniklasi/PovratniPovici.java // Upotreba na vnatresni klasi za povratni povici package vnatresniklasi; import static net.mindview.util.Print.*; interface MozeDaSeZgolemi { void zgolemi(); } // Mnogu ednostavna, samo realizira interfejs: class Povikana1 implements MozeDaSeZgolemi { private int i = 0; public void zgolemi() { i++; print(i); } } class ZgolemiJaMojata { public void zgolemi() { print("Druga operacija"); } static void f(ZgolemiJaMojata zm) { zm.zgolemi(); } } // Ako vasata klasa mora da go realizira metodot zgolemi() // na nekoj drug nacin, kje morate da upotrebite vnatresna klasa: class Povikana2 extends ZgolemiJaMojata { private int i = 0; public void zgolemi() { super.zgolemi(); i++; print(i); } private class Zaklucok implements MozeDaSeZgolemi { public void zgolemi() { // Specificirajte go metodot od nadvoresnata klasa, bidejki // inaku ke dobiete beskonecna rekurzija: Povikana2.this.zgolemi(); } } MozeDaSeZgolemi zemireferencaZaPovratenPovik() { return new Zaklucok(); } } class Povikuva { private MozeDaSeZgolemi referencaZaPovratenPovik; Povikuva(MozeDaSeZgolemi cbh) { referencaZaPovratenPovik = cbh; } void pocni() { referencaZaPovratenPovik.zgolemi(); } }

348

Da se razmisluva vo Java

Brus Ekel

public class PovratniPovici { public static void main(String[] args) { Povikana1 c1 = new Povikana1(); Povikana2 c2 = new Povikana2(); ZgolemiJaMojata.f(c2); Povikuva povikuva1 = new Povikuva(c1); Povikuva povikuva2 = new Povikuva(c2.zemiReferencaZaPovratenPovik ()); povikuva1.pocni(); povikuva1.pocni(); povikuva2.pocni(); povikuva2.pocni(); } } /* Output: Druga operacija 1 1 2 Druga operacija 2 Druga operacija 3 *///:~

Ova isto taka poka`uva dodatna razlika pome|u realiziraweto na interfejs vo nadvore{na klasa i realiziraweto na interfejs vo vnatre{nata klasa. Vo pogled na pi{uvawe na programata, klasata Povikana1 e o~igledno poednostavno re{enie. Klasata Povikana2 ja nasleduva klasata ZgolemiJaMojata vo ~ii ramki ve}e postoi metodot zgolemi() ~ija zada~a nema nikakva vrska so onie koi {to gi o~ekuvame od interfejsot Zgolemi. Koga klasata Povikana2 ja nasleduvame od klasata ZgolemiJaMojata, nejziniot metod zgolemi() ne mo`e da go redefinirame taka da mo`e da se koristi so intefejsot MozeDaSeZgolemi, pa morate da obezbedite posebna realizacija koristej}i vnatre{na klasa. Isto taka obrnete vnimanie i na toa deka koga pravite vnatre{na klasa, vie ne pro{iruvate nitu go modificirate interfejsot od nadvore{nata klasa. Vo klasata Povikana2, sé osven metodot zemiReferencaZaPovratniotPovik(), e privatno. Za da ovozmo`ite kakva bilo vrska so nadvore{niot svet, neophoden vi e interfejsot MozeDaSeZgolemi. Vo ovoj primer mo`ete da vidite kako interfejsite ovozmo`uvaat kompletno oddeluvawe na interfejsot od realizacijata. Vnatre{nata klasa Zaklucok samo realizira interfejs MozeDaSeZgolemi za da obezbedi povratna vrska kon klasata Povikana2- no sigurno povratna vrska. Sekoj koj {to }e ja dobie referencata na interfejsot MozeDaSeZgolemi mo`e, sekako, samo da go povika metodot zgolemi() i toa e se (za razlika od poka`uva~ot koj bi ovozmo`il potpolna sloboda).

Vnatre{ni klasi

349

Konstruktorot na klasata Povik dobiva referenca na interfejsot MozeDaSeZgolemi (iako referencata za povratniot povik mo`ete da ja prifatite vo koj bilo moment) i potoa, ne{to podocna, da ja upotrebi taa referenca za povratniot povik vo klasata Povikana. Zna~eweto na povratnite povici le`i vo nivnata fleksibilnost, odnosno vo mo`nosta dinami~ki da re{ite koi metodi }e gi povikate pri izvr{uvaweto. Dobivkata od ovaa tehnika }e stane pojasna vo poglavjeto Grafi~ki korisni~ki opkru`uvawa, kade povratnite povici }e bidat nasekade koristeni za realizacija na funkcionalnost na grafi~ko korisni~ko opkru`uvawe (GUI)

Vnatre{ni klasi i skeleti na upravuvawe Kako pokonkreten primer za upotrebata na vnatre{ni klasi mo`e da se primeni postapkata koja }e ja nare~am skelet na upravuvawe (angliskicontrol framework). Skeletot na programata (angliski- application framework) e klasa ili mno`estvo od pove}e klasi koi se proektirani za da re{at odreden problem. Skeletot na programata go primenuvate na toj na~in {to nasleduvate edna ili pove}e klasi i redefinirate nekoi metodi. Kodot koj }e go napi{ete vo redefiniranite metodi se prilagoduva na op{toto re{enie koe go pru`a skeletot na aplikacii za da re{i opredelen problem. Ova e primer od proektniot model Template Method ({ablonski metod) (poglednete vo Thinking in Patterns (with Java) na adresata www.MindView.net). [ablonskiot metod ja sodr`i osnovna struktura na algoritmot; za da ja dovr{i akcijata na toj algoritam, toj povikuva eden ili pove}e metodi koi mo`e da se redefiniraat. Proektniot model go razdeluva ona {to se menuva od ona {to ne se menuva, a vo ovoj slu~aj, ona {to ne se menuva e {ablonskiot metod, a se menuvaat metodite koi mo`e da se redefiniraat.

Skeletot na upravuvawe e poseben tip na skelet na programata ~ija osnovna namena e da odgovori na nastanite. Sistemot ~ija osnovna funkcija e da reagira na nastanite se narekuva sistem so koj upravuvaat nastanite (angliski- event-driven system). Eden od najva`nite problemi pri praveweto programi e grafi~koto korisni~ko opkru`uvawe (GUI), so koe re~isi potpolno se upravuvaat nastanite. Kako {to }e vidite vo poglavjeto Grafi~ko korisni~ko opkru`uvawe, bibliotekata na Java Swing e skelet na upravuvawe koj efikasno go re{ava problemot so grafi~ko korisni~ko opkru`uvawe, pri {to ~esto koristi vnatre{ni klasi.

350

Da se razmisluva vo Java

Brus Ekel

Za da razberete na koj na~in vnatre{nite klasi ovozmo`uvaat ednostavno pravewe i upotreba na skelet na upravuvawe, da go razgledame skeletot na upravuvawe ~ija zada~a e da izvr{i nastani sekoj pat koga se „podgotveni”. Iako terminot „podgotven” mo`e da se odnesuva na {to bilo, vo na{iot slu~aj }e bide baziran na ~asovnikot. Toa {to sledi e skelet na programata {to ne sodr`i opredelena informacija za toa {to i kako kontrolira. Taa informacija se dostavuv za vreme na nasleduvaweto, koga,se realizira delot od algoritmot nare~en akcija().. Prvo }e go definirame interfejsot koj opi{uva kakov bilo upravuva~ki nastan. Toj e napi{an vo oblik na apstraktna klasa, a ne kako vistinski interfejs, zatoa {to negovoto podrazbirano odnesuvawe e da upravuva potpiraj}i se na vremeto, taka {to vo nego mora da bide del od realizacijata: //: vnatresniklasi/upravuvac/Nastan.java // Zaednicki metodi za bilo koj upravuvacki nastan. package vnatresniklasi.upravuvac; public abstract class Nastan { private long nastanVreme; protected final long vremeNaDocnenje; public Nastan(long vremeNaDocnenje) { this.vremeNaDocnenje = vremeNaDocnenje; start(); } public void start() { // Dozvoluva restartiranje nastanVreme = System.nanoTime() + vremeNaDocnenje; } public boolean podgotven() { return System.nanoTime() >= nastanVreme; } public abstract void akcija(); } ///:~

Konstruktorot samo go zabele`uva momentot (mereno od momentot na pravewe na objektot) koga sakate da se izvr{uva Nastan, a potoa go povikuva metodot start(), koja go zema tekovnoto vreme, mu go dodava nemu vremeto na docnewe i taka se dobiva vreme koga }e se slu~i nastanot. Namesto da bide vklu~en vo konstruktorot, metodot start() se tretira kako oddelen metod. Na ovoj na~in , mera~ot na vremeto mo`ete da go restartirate otkako }e se slu~i nastanot, taka {to mo`ete povtorno da go koristite objektot Nastan. Na primer, ako sakate da dobiete nastan koj se povtoruva, dovolno e od va{iot metod akcija() da go povikate metodot start().. Metodot podgotven() vi poka`uva koga e vreme da go izvr{ite metodot akcija(). Sekako, metodot podgotven() mo`e da bide redefiniran vo izvedenata klasa, za izvr{uvaweto na nastanot da bide zasnovano na ne{to drugo, namesto na vremeto.

Vnatre{ni klasi

351

Slednata datoteka go sodr`i vistinskiot skelet na upravuvawe koj upravuva so nastanite i gi povikuva. Objektite od klasata Nastan se ~uvaat vo kontejnerskiot objekt od tipot List (se ~ita „lista na nastani”), za koja }e doznaete pove}e vo poglavjeto ^uvawe na objekti. Za sega, dovolno e da znaete deka metodot add() go dodava Nastan na krajot od List, metodot size() go dava brojot na vlezovi vo List, foreach sintaksata gi pribavuva posledovatelnite nastani od List, a metodot remove() go otstranuva odredeniot Nastan od List. //: vnatresniklasi/upravuvac/Upravuvac.java // Genericki skelet za site upravuvacki sistemi. package vnatresniklasi.upravuvac; import java.util.*; public class Upravuvac { // Klasa od paketot java.util za cuvanje na objektite od klasata Nastan: private List listaNaNastani = new ArrayList(); public void addNastan(Nastan c) { listaNaNastani.add(c); } public void otpocni() { while(listaNaNastani.size() > 0) // Napravete kopija za da ne ja modificirate listata // dodeka gi izbirate elementite od nea: for(Nastan e : new ArrayList(listaNaNastani)) if(e.podgotven()) { System.out.println(e); e.akcija(); listaNaNastani.remove(e); } } } ///:~

Metodot startuvaj() kru`i naokolu niz kopijata na listaNaNastani, baraj}i Nastan koj e podgotven() za startirawe. Za sekoj Nastan koj e podgotven(), se pi{uvaat podatocite koristej}i go objektniot metod toString(), se povikuva metodot akcija() i potoa se otstranuva Nastan od listata.

Sogleduvate li deka ne znaete ni{to za toa {to to~no eden Nastan pravi. Toa e i sr`ta na ovaa postapka- kako „se pravi odvojat rabotite {to se menuvaat od rabotite {to ostanuvaat isti.” Ili, da go iskoristam mojot termin, „vektorot na promena” pretstavuva razli~ni akcii od razli~ni tipovi na objekti od klasata Nastan koja ja definirate prevej}i razli~ni potklasi Nastan. Na ova mesto na scenata stapuvaat vnatre{nite klasi. Tie ovozmo`uvaat dve raboti: 1. Celata realizacija na programata koja go upotrebuva skeletot na upravuvawe mo`ete da ja smestite vo edna klasa, so {to kapsulirate

352

Da se razmisluva vo Java

Brus Ekel

se {to e potrebno za realizacija. Vnatre{nite klasi se upotrebuvaat za da iska`at mnogu razli~ni akcii koi se potrebni za re{avawe na problemot. 2. Vnatre{nite klasi ja pravat ovaa realizacija poednostavna, bidej}i vie ste vo mo`nost lesno da im pristapite na ~lenovite od nadvore{nata klasa. Bez ovaa mo`nost kodot mo`e da stane neprijaten do toj stepen da morate da barate nekoja druga alternativa. Da razgledame edna posebna realizacija na skelet na upravuvawe koj e dizajniran za upravuvawe so funkciite na staklena gradina.4 Sekoja akcija e kompletno razli~na: vklu~uvaweto i isklu~uvaweto na svetlata, vodata i termostatite, yvonewe na yvon~iwata i restartiraweto na sistemot. No skeletot na upravuvawe e dizajniran za lesno razdvojuvawe na ovoj razli~en kod. Vnatre{nite klasi vi ovozmo`uvaat, vo ramkite na edna klasa, da imate pove}e izvedeni verzii na osnovnata klasa, Nastan,. Za sekoj tip na akcija, nasleduvate nova vnatre{na klasa Nastan i go zapi{uvate kontrolniot kod vo realizacijata na metodot akcija(). Kako {to e voobi~aeno za skeletot na upravuvawe, UpravuvanjeSoStaklenataGradina e izvedena od klasata Upravuvac:

klasata

//: vnatresniklasi/UpravuvanjeSoStaklenataGradina.java // So ova se pravi posebna programa za upravuvacki sistem koj se naogja // celiot vo edna klasa. Vnatresnite klasi ovozmozuvaat da kapsulirate // razlicna funkcionalnost za sekoj poseben tip na nastan. import vnatresniklasi.upravuvac.*; public class UpravuvanjeSoStaklenataGradina extends Upravuvac { private boolean svetlo = false; public class VkluciSvetlo extends Nastan { public VkluciSvetlo(long vremeNaDocnenje) { super(vremeNaDocnenje); } public void akcija() { // Tuka treba da e smesten kodot za upravuvanje so hardver // so koj fizicki se vklucuva svetloto. svetlo = true; } public String toString() { return "Svetloto e vkluceno"; } } public class IskluciSvetlo extends Nastan { public IskluciSvetlo(long vremeNaDocnenje) { super(vremeNaDocnenje); } public void akcija() { // Tuka treba da e smesten kodot za upravuvanje so hardver // so koj fizicki se isklucuva svetloto. svetlo = false; } public String toString() { return "Svetloto e iskluceno"; } } private boolean voda = false;

Vnatre{ni klasi

353

public class VkluciVoda extends Nastan { public VkluciVoda(long vremeNaDocnenje) { super(vremeNaDocnenje); } public void akcija() { // Tuka treba da stoi kodot za upravuvanje so hardverot. voda = true; } public String toString() { return "Vodata vo Staklenata gradina e pustena "; } } public class IskluciVoda extends Nastan { public IskluciVoda(long vremeNaDocnenje) { super(vremeNaDocnenje); } public void akcija() { // Tuka treba da stoi kodot za upravuvanje so hardverot. voda = false; } public String toString() { return "Vodata vo Staklenata gradina e zatvorena"; } } private String termostat = "Den"; public class TermostatNokj extends Nastan { public TermostatNokj(long vremeNaDocnenje) { super(vremeNaDocnenje); } public void akcija() { // Tuka treba da stoi kodot za upravuvanje so hardverot. termostat = "Nokj"; } public String toString() { return "Termostatot e na nokjen rezim"; } } public class TermostatDen extends Nastan { public TermostatDen(long vremeNaDocnenje) { super(vremeNaDocnenje); } public void akcija() { // Tuka treba da stoi kodot za upravuvanje so hardverot. termostat = "Den"; } public String toString() { return "Termostatot e na dneven rezim"; } } // Primer za metodot akcija() sto vnesuva // nova akcija vo listata na nastani: public class Zvonce extends Nastan { public Zvonce(long vremeNaDocnenje) { super(vremeNaDocnenje); } public void akcija() { dodajNastan(new Zvonce(vremeNaDocnenje));

354

Da se razmisluva vo Java

Brus Ekel

} public String toString() { vrati "Zvonenje!"; } } public class Restart extends Nastan { private Nastan[] listaNaNastani; public Restart(long vremeNaDocnenje, Nastan[] listaNaNastani) { super(vremeNaDocnenje); this.listaNaNastani = listaNaNastani; for(Nastan e : listaNaNastani) dodajNastan(n); } public void akcija() { for(Nastan e : listaNaNastani) { n.start(); // Povtorno otpocni go sekoj nastan dodajNastan(n); } start(); // Povtorno otpocni so ovoj nastan dodajNastan(this); } public String toString() { return "Restartiranje na sistemot"; } } public static class Zavrsi extends Nastan { public Zavrsi(long vremeNaDocnenje) { super(vremeNaDocnenje); } public void akcija() { System.exit(0); } public String toString() { return "Zavrsuvanje"; } } } ///:~

4 Poradi nekoja pri~ina, re{avaweto na vakov tip na problemi sekoga{ mi pri~inuvalo zadovolstvo. Toj poteknuva od mojata prethodna kniga S++ Inside & Out, me|utoa, Java ovozmo`uva mnogu podobro re{enie.

Obrnete vnimanie na toa deka svetlo, voda i termostat pripa|aat na nadvore{nata klasa UpravuvanjeSoStaklenataGradina, a sepak vnatre{nite klasi mo`at da im pristapat na tie poliwa bez upotreba na kvalifikatori i bez posebna dozvola. Isto taka, metodite akcija() voobi~aeno vklu~uvaat i nekoj vid kontrola vrz hardverot. Pove}eto od klasite izvedeni od klasata Nastan izgledaat sli~no, no Zvonce i Restart se izdvojuvaat. Klasata Zvonce go aktivira yvon~eto i pritoa dodava nov objekt Zvonce na listata so nastani, taka {to malku podocna }e zayvoni povtorno. Obrnete vnimanie na toa deka vnatre{nite klasi re~isi izgledaat kako pove}ekratnoto nasleduvawe: Zvonce i Restart gi imaat site metodi od Nastan i isto taka izgleda deka gi imaat site metodi od nadvore{nata klasa UpravuvanjeSoStaklenataGradina.

Vnatre{ni klasi

355

Klasata Restart dobiva niza od objekti od klasata Nastan koja taa gi dodava na upravuva~ot. Bidej}i Restart e samo u{te eden vid od klasata Nastan, vo metodot Restart.akcija() vo listata isto taka mo`ete da dodadete i objekt od klasata Restart, za da mo`e sistemot od vreme na vreme povtorno da se startira. Slednata klasa go konfigurira sistemot taka {to pravi objekt od klasata UpravuvanjeSoStaklenataGradina i dodava razli~ni vidovi na objekti od klasata Nastan. Ova e primer za proektniot model Command (naredba)- sekoj objekt od klasata listaNaNastani e pobaruvawe kapsulirano kako objekt: //: vnatresniklasi/UpravuvacSoStaklenataGradina.java // Konfigurirajte i startuvajte go sistemot staklena gradina. // {Args: 5000} import vnatresniklasi.upravuvac.*; public class UpravuvacSoStaklenataGradina { public static void main(String[] args) { UpravuvanjeSoStaklenaGradina usg = new UpravuvanjeSoStaklenaGradina(); // Namesto da pisuvate direktno vo programata, na ova mesto bi mozele // da ja vcitate konfiguracijata od tekstualnata datoteka: usg.dodajNastan(usg.new Bell(900)); Nastan[] listaNaNastani = { usg.new TermostatNokj(0), usg.new VkluciSvetlo(200), usg.new IskluciSvetlo(400), usg.new VkluciVoda(600), usg.new IskluciVoda(800), usg.new TermostatDen(1400) }; usg.dodajNastan(usg.new Restart(2000, listaNaNastani)); if(args.length == 1) usg.dodajNastan( new UpravuvanjeSoStaklenaGradina.Terminate( new Integer(args[0]))); usg.run(); } } /* Rezultat: Zvonenje! Termostatot e na nokjen rezim Svetloto e vkluceno Svetloto e ukluceno Vodata vo staklenata gradina e vklucena Vodata vo staklenata gradina e isklucena Termostat e na dneven rezim Restartiranje na sistemot Zavrsuvanje *///:~

Klasata go inicijalizira sistemot, taka {to gi dodava site soodvetni nastani. Nastanot Restart se izvr{uva nekolku pati i sekoj pat ja v~ituva

356

Da se razmisluva vo Java

Brus Ekel

klasata listaNaNastani vo objektot UpravuvanjeSoStaklenataGradina. Ako zadadete broj na milisekundi kako argument na komandnata linija, Restart }e ja zapre programata po tolku milisekundi. (Toa se upotrebuva pri testiraweto.) Sekako, toa mo`e da se postigne i na pofleksibilen na~in- namesto da gi pi{uvame nastanite direktno vo programata, }e ja pro~itame listata na nivnata inicijalizacija direktno od datotekata. Vo edna od ve`bite od poglavjeto Vlezno-izlezen sistem na Java ba{ toa se bara od vas. Ovoj primer bi trebalo da ve uveri vo vrednosta na vnatre{nite klasi, posebno koga se koristi vnatre vo skeletot na upravuvawe. Vo poglavjeto Grafi~ki korisni~ki opkru`uvawa }e vidite kako vnatre{nite klasi ednostavno se upotrebuvaat ednostavno za opi{uvawe akcii od grafi~koto opkru`uvawe. Koga }e go pro~itate i toa poglavje, }e bidete uvereni vo nivnata vrednost. Ve`ba 24: (2) Vo datotekata UpravuvanjeSoStaklenataGradina.java dodadete vnatre{ni klasi Nastan koi vklu~uvaat i isklu~uvaat ventilatori. Konfigurirajte ja datotekata UpravuvanjeSoStaklenataGradina za da gi upotrebuva tie novi objekti od tipot Nastan. Ve`ba 25: (3) Vo datotekata UpravuvanjeSoStaklenataGradina.java nasledete klasa UpravuvanjeSoStaklenataGradina za da dodadete vnatre{ni klasi od tipot Nastan koi vklu~uvaat i isklu~uvaat generatori na vodena parea. Napi{ete nova verzija na programata UpravuvanjeSoStaklenataGradina.java za taa da gi upotrebuva tie novi objekti od tipot Nastan.

Nasleduvawe na vnatre{ni klasi Bidej}i konstruktorot na vnatre{nata klasa mora da bide povrzan so referencata na objektot od nadvore{nata klasa, pri nejzinoto nasleduvawe rabotite malku se kompliciraat. Problemot le`i vo toa {to “tajnata” referenca na objektot od opkru`uva~kata klasa mora da bide inicijalizirana, a sepak vo izvedenata klasa pove}e ne postoi podrazbiran objekt za koj taa bi bila prika~ena. Mora da koristite specijalna sintaksa za da go napravite eksplicitno povrzuvaweto. //: vnatresniklasi/NaslediVnatresna.java //Nasleduvanje na vnatresna klasa. class ImaVnatresna { class Vnatresna {} } public class NaslediVnatresna extends ImaVnatresna.Vnatresna { //! NaslediVnatresna() {} // Ne moze da se preveduva NaslediVnatresna(ImaVnatresna iv) {

Vnatre{ni klasi

357

iv.super(); } public static void main(String[] args) { ImaVnatresna iv = new ImaVnatresna(); NaslediVnatresna ii = new NaslediVnatresna(iv); } } ///:~

Mo`ete da vidite deka NaslediJaVnatresnata ja pro{iruva samo vnatre{nata klasa, ne nadvore{nata. No koga }e dojde vreme za pravewe na konstruktor, podrazbiraniot konstruktor ne vi odgovara, a i ne mo`ete ednostavno da mu prosledite referenca na opkru`uv~kiot objekt. Osven toa, morate da ja koristite sintaksata: ReferencaNaNadvoresnataKlasa.super(); So toa se obezbeduva neophodnata referenca i }e mo`ete da ja prevedete programata. Ve`ba 26:(2) Napravete klasa koja sodr`i vnatre{na klasa koja ima nepodrazbiran konstruktor (onoj koj prima argumenti). Napravete druga klasa koja sodr`i vnatre{na klasa nasledena od prvata vnatre{na klasa.

Dali vnatre{nata klasa mo`e da se redefinira? [to se slu~uva koga pravite vnatre{na klasa, a potoa ja nasleduvate opkru`uva~kata klasa i ja redefinirate vnatre{nata klasa? Se ~ini deka toa bi bil mo}en koncept, no so „redefiniraweto” na vnatre{nata klasa kako taa da e metod od nadvore{nata klasa, vo su{tina ne se postignuva ni{to. //: vnatresniklasi/GolemoJajce.java // Edna vnatresna klasa ne moze da bide redefinirana kako metod. import static net.mindview.util.Print.*; class Jajce { private Zolcka y; protected class Zolcka { public Zolcka() { print("Jajce.Zolcka()"); } } public Jajce() { print("New Jajce()"); y = new Zolcka(); } } public class GolemoJajce extends Jajce { public class Zolcka {

358

Da se razmisluva vo Java

Brus Ekel

public Zolcka() { print("GolemoJajce.Zolcka()"); } } public static void main(String[] args) { new GolemoJajce(); } } /* Rezultat: New Jajce() Jajce.Zolcka() *///:~

Preveduva~ot avtomatski pravi podrazbiran konstruktor koj go povikuva podrazbiraniot konstruktor na osnovnata klasa. So ogled na toa deka se pravi klasata GolemoJajce, bi mo`ele da o~ekuvate deka }e bide povikana „redefiniranata” verzija na klasata Zolcka, no toa ne se slu~uva, kako {to mo`ete da vidite od rezultatot. Ovoj primer poka`uva deka pri nasleduvaweto na nadvore{nite klasi ni{to posebno ne se slu~uva vo vnatre{nite. Dve vnatre{ni klasi se potpolno odvoeni entiteti, sekoja vo svoj imenski prostor. Sepak, mo`no e eksplicitno nasleduvawe na vnatre{nite klasi: //: vnatresniklasi/GolemoJajce2.java // Pravilno nasleduvanje na vnatresni klasi. import static net.mindview.util.Print.*; class Jajce2 { protected class Zolcka { public Zolcka() { print("Jajce2.Zolcka()"); } public void f() { print("Jajce2.Zolcka.f()");} } private Zolcka y = new Zolcka(); public Jajce2() { print("Novo Jajce2()"); } public void vnesiZolcka(Zolcka zz) { z = zz; } public void g() { z.f(); } } public class GolemoJajce2 extends Jajce2 { public class Zolcka extends Jajce2.Zolcka { public Zolcka() { print("GolemoJajce2.Zolcka()"); } public void f() { print("GolemoJajce2.Zolcka.f()"); } } public GolemoJajce2() { vnesiZolcka(new Zolcka()); } public static void main(String[] args) { Jajce2 e2 = new GolemoJajce2(); e2.g(); } } /* Rezultat: Jajce2.Zolcka() Novo Jajce2() Jajce2.Zolcka()

Vnatre{ni klasi

359

GolemoJajce2.Zolcka() GolemoJajce2.Zolcka.f() *///:~

Sega klasata GolemoJajce2.Zolcka eksplicitno ja pro{iruva klasata Jajce2.Zolcka i gi redefinira nejzinite metodi. Metodot vnesiZolcka() ovozmo`uva klasata GolemoJajce2 eden od svoite vnatre{ni objekti od klasata Zolcka da go svede nagore kon referencata z vo klasata Jajce2. Koga metodot g() go povikuva metodot z.f() }e bide upotrebena redefiniranata verzija na metodot f(). Drugiot povik na konstruktorot na osnovnata klasa, Jajce2.Zolcka() e povik od konstruktorot GolemoJajce2.Zolcka. I samite mo`ete da vidite deka pri povikot na metodot g() }e bide povikana redefiniranata verzija na metodot f().

Lokalni vnatre{ni klasi Kako {to spomenavme prethodno, vnatre{nite klasi isto taka mo`at da bidat napraveni vnatre vo blokovite na kodot, voobi~aeno vo vnatre{nosta na teloto na metodot. Edna lokalna vnatre{na klasa ne mo`e da ima specifikator na pristap bidej}i taa ne e del od nadvore{nata klasa, no mo`e da im pristapuva na finalnite promenlivi vo tekovniot blok na kodot i na site ~lenovi od opkru`uva~kata klasa. Eve primer kade se pravi sporedba me|u praveweto na lokalna vnatre{na klasa i na anonimna vnatre{na klasa: //: vnatresniklasi/LokalnaVnatresnaKlasa.java // Chuva sekvenca na objekti. import static net.mindview.util.Print.*; interface Brojac { int next(); } public class LokalnaVnatresnaKlasa { private int broj = 0; Brojac getBrojac(final String ime) { // Lokalna vnatresna klasa: class LokalenBrojac implements Brojac { public LokalenBrojac() { // Lokalna vnatresna class can have a constructor print("LokalenBrojac()"); } public int next() { printnb(ime); // Pristapuvanje kon lokalna finalna return broj++; } } return new LokalenBrojac(); }

360

Da se razmisluva vo Java

Brus Ekel

// Istoto i so anonimnite vnatresni klasi: Brojac getBrojac2(final String ime) { return new Brojac() { // Edna anonimna vnatresna klasa ne moze da ima imenuvan // konstruktor, tuku samo inicijalizator na instanci: { print("Brojac()"); } public int next() { printnb(ime); // Pristap kon lokalna finalna return broj++; } }; } public static void main(String[] args) { LokalnaVnatresnaKlasa lic = new LokalnaVnatresnaKlasa(); Brojac c1 = lic.getBrojac("Lokalna vnatresna "), c2 = lic.getBrojac2("Anonimna vnatresna "); for(int i = 0; i < 5; i++) print(c1.next()); for(int i = 0; i < 5; i++) print(c2.next()); } } /* Rezultat: LokalenBrojac() Brojac() Lokalna vnatresna 0 Lokalna vnatresna 1 Lokalna vnatresna 2 Lokalna vnatresna 3 Lokalna vnatresna 4 Anonimna vnatresna 5 Anonimna vnatresna 6 Anonimna vnatresna 7 Anonimna vnatresna 8 Anonimna vnatresna 9 *///:~

Brojac ja vra}a slednata vrednost vo sekvencata. Realiziran e i kako lokalna klasa i kako anonimna vnatre{na klasa. Dvete klasi se odnesuvaat isto i imaat ednakvi mo`nosti. Bidej}i imeto na lokalnata vnatre{na klasa ne e dostapno nadvor od toj metod, edinstveno opravduvawe za upotrebata na taa klasa namesto anonimna vnatre{na klasa bi bila potrebata za imenuvan konstruktor e i/ili za preklopen konstruktor, bidej}i anonimnata vnatre{na klasa mo`e da ima samo inicijalizacija na instanca. Druga pri~ina za pravewe na lokalni vnatre{ni klasi namesto na anonimni vnatre{ni klasi bi bila potrebata da se napravat pove}e objekti od taa klasa.

Vnatre{ni klasi

361

Identifikatori na vnatre{nite klasi Bidej}i za sekoja klasa postoi datoteka .class vo koja se ~uvaat site informacii za pravewe objekti od toj tip (so pomo{ na tie informacii se dobiva takanare~ena meta klasa- objekt od tipot Class), verojatno pogoduvate deka i za vnatre{nite klasi mora da postoi nivna datoteka .class. Imiwata na tie datoteki/klasi se dobivaat po precizna formula: imeto na nadvore{nata klasa po {to doa|a znakot $, prosleden so imeto na vnatre{nata klasa. Na primer, vo programata LokalnaVnatresnaKlasa.java }e bide napravena slednata datoteka .class: Brojac.class LokalnaVnatresnaKlasa$1.class LokalnaVnatresnaKlasa$1LokalenBrojac.class LokalnaVnatresnaKlasa.klasa Ako vnatre{nite klasi se anonimni, preveduva~ot koristi broevi kako nivnite identifikatori. Ako vnatre{nite klasi se vgnezdeni vo drugi vnatre{ni klasi, se dodavaat soodvetnite imiwa po znakot $ i identifikatorot na nadvore{nite klasi. Na~inot na generirawe na vnatre{nite imiwa e ednostaven i mnogu direkten, no istovremeno i robusten i sposoben da obraboti pove}e situacii.5 Bidej}i toa e standardna tehnika za dodeluvawe na imiwa vo Java, generiranite datoteki se avtomatski nezavisni od platformata. (Zabele`ete deka preveduva~ot na Java gi menuva va{ite vnatre{ni klasi na site mo`ni na~ini so cel da gi osposobi da rabotat.)

Rezime Interfejsite i vnatre{nite klasi se posofisticirani koncepti od onie {to postojat vo objektno-orientiranite jazici. Na primer, nema ni{to sli~no na niv vo S++. Zaedno, tie go re{avaat istiot problem {to S++ se obide da go re{i so pomo{ na pove}ekratnoto nasleduvawe. Sepak, se poka`a deka pove}ekratnoto nasleduvawe vo S++ e prili~no te{ko se upotrebuva, dodeka interfejsite na Java i vnatre{nite klasi se mnogu popristapni. Iako tie mo`nosti se prili~no jasni, nivnata upotreba e pra{awe na proektirawe, nalik na polimorfizmot. So tekot na vremeto se podobro }e gi prepoznavate situaciite vo koi }e treba da koristite interfejs ili vnatre{na klasa, ili ednoto ili drugoto istovremeno. Vo ovoj moment, bi bilo dobro barem da ja poznavate nivnata sintaksa i semantika. Kako {to }e se sre}avate so niv, se pove}e }e gi prifa}ate.

362

Da se razmisluva vo Java

Brus Ekel

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.

5 Od druga strana, $ e metaznak vo komandnoto opkru`uvawena Unix, pa ponekoga{ }e imate problemi pri listaweto na datotakata .class. Ova e malku ~udno, bidej}i kompanijata Sun raboti vo Unix. Pretpostavuvam deka toa pra{awe vo Sun ne go razrabotile, mislej}i deka vie priradno }e se fokusirate na datotekite od izvorniot kod.

Vnatre{ni klasi

363

^uvawe objekti Programata koja {to koristi to~no opredelen broj na objekti so poznati vremetraewa e prili~no ednostavna. Po pravilo, vo programite sekoga{ }e pravite novi objekti vrz osnova na nekoi kriteriumi koi }e bidat poznati za vreme na izvr{uvaweto. Dotoga{, nema da go znaete koli~estvoto, pa duri i to~niot tip na objektite {to vi trebaat. Za da go re{ite ovoj programerski problem, }e treba da napravite opredelen broj na objekti, vo koe bilo vreme, na koe bilo mesto. Zna~i, ne mo`ete da se potprete na pravewe imenuvana referenca za da go ~uva sekoj od va{ite objekti: MojaKlasa referenca

bidej}i nikoga{ nema da znaete kolku objekti navistina }e vi trebaat. Pove}eto jazici obezbeduvaat nekoj na~in za re{avawe na ovoj su{tinski problem. Java ima nekolku na~ini za ~uvawe objekti (odnosno, referenci za objekti). Vo samiot jazik e vgraden tip na niza, za {to spomenavme prethodno, toa e preveduva~ot. Nizata e najefikasen na~in za ~uvawe grupa na objekti, a isto taka taa se prepora~uva za ~uvawe grupa na prosti tipovi. No, edna niza ima fiksna golemina i vo op{t slu~aj, za vreme na pi{uvaweto na programata nema da znaete kolku objekti }e vi trebaat, ili dali }e vi treba posofisticiran na~in za skladirawe na va{ite objekti; zatoa, nizite so fiksna golemina premnogu ograni~uvaat. Bibliotekata java.util ima prili~no kompletno mno`estvo od kontejnerski klasi, ~ii osnovni tipovi se List, Set, Queue (za redovi za ~ekawe) i Map. Ovie tipovi na objekti se poznati i pod imeto klasi na kolekcii, no bidej}i terminot Colection vo bibliotekata na Java se koristi za ozna~uvawe na odredeno podmno`estvo na taa biblioteka, jas }e go koristam poprecizniot termin „kontejner.” Kontejnerite ovozmo`uvaat sofisticirani na~ini za ~uvawe objekti i isto taka mo`ete so nivna pomo{ da re{ite golem broj na problemi. Pokraj ostanatite svoi karakteristiki- na primer Set ~uva samo eden objekt za sekoja vrednost, a Map e asocijativna niza {to vi dozvoluva da povrzuvate edni objekti so drugi objekti- kontejnerskite klasi na Java avtomatski }e ja prilagodat goleminata. Zna~i, za razlika od nizite, vo kontejnerot mo`ete da vnesete proizvolen broj na objekti i nema potreba da se gri`ite za toa kolku golem treba da go napravite kontejnerot za vreme na pi{uvaweto na programata.

364

Da se razmisluva vo Java

Brus Ekel

Iako nemaat direktna poddr{ka preku rezerviran zbor vo Java,1 kontejnerskite klasi se osnovni alatki za programirawe {to zna~ajno ja zgolemuvaat va{ata programerska „mo}nost”. Vo ova poglavje }e se zdobiete so osnovno znaewe za rabotata na bibliotekata na kontejneri vo Java vo sekojdnevnata upotreba. Ovde, }e se fokusirame na kontejnerite {to }e gi koristite vo sekojdnevnoto programirawe. Podocna, vo poglavjeto Detaqno razgleduvawe na kontejnerite, }e nau~ite pove}e za ostanatite kontejnerite i za detalite za nivnata funkcionalnost i upotreba.

Generi~ki klasi i kontejneri za bezbedna rabota so tipovite Pred pojavata na Java SE5, eden od problemite koi {to se javuvaa pri koristewe kontejneri be{e: preveduva~ot vi dozvoluva{e da vnesete tip {to ne odgovara vo kontejnerot. Na primer, da razgledame kontejner od objekti Jabolko, koristej}i go osnovniot kontejner za site nameni, ArrayList. Zasega, mo`e da gledate na ArrayList kako na „niza {to avtomatski se pro{iruva samata.” Koristeweto na ArrayList e mnogu direktno: Napravete eden kontejner, vnesete objekti koristej}i go metodot add() i pristapete im so metodot get(), koristej}i indeks, ba{ kako vo slu~ajot so nizite, no bez sredni zagradi. 2 ArrayList ima i metod size() koj go vra}a momentalniot broj na elementi i so toa ve spre~uva slu~ajno da dojdete do krajot i da predizvikate gre{ka „isklu~ok pri izvr{uvawe” (angliski- runtime exception). Isklu~ocite }e bidat pretstaveni vo poglavjeto Obrabotka na gre{ki so pomo{ na isklu~oci. Vo ovoj primer, Jabolko i Portokal se smestuvaat vo kontajnerot, a potoa se vadat nadvor. Bidej}i vo primerot ne se upotrebeni generi~ki tipovi, preveduva~ot na Java }e ve predupredi za gre{ka. Za da go spre~ime pi{uvaweto na toa predupreduvawe, tuka upotrebivme posebna anotacija od Java SE5. Anotaciite zapo~nuvaat so znakot @ i primaat argument; ova glasi @SuppressWarnings (,,unchecked”), a nejziniot argument poka`uva deka ne sakame pi{uvawe samo na predupreduvaweto ,,unchecked”, koe ka`uva deka ne e jasno koj tip (Jabolko ili Portokal) se dobiva od kontejnerot: 1Vgradena podr{ka za kontejneri imaat mnogu jazici, me|u koi Perl, Python i Ruby. 2Ovde dobro bi do{lo preklopuvawe na operatori. Kontejnerskite klasi vo jazicite S++ i S# proizveduvaat po~ista sintaksa zatoa {to se upotrebuva preklopuvawe na operatori. //: cuvanje/JabolkaIPortokaliBezGenerickiTipovi.java // Ednostaven primer so kontejner (napisan taka da . // preveduvacot dade predupreduvanje. // {ThrowsException}

^uvawe objekti

365

import java.util.*; class Jabolko { private static long brojac; private final long id = brojac++; public long id() { return id; } } class Portokal {} public class JabolkaIPortokaliBezGenerickiTipovi { @SuppressWarnings("unchecked") public static void main(String[] args) { ArrayList jabolka = new ArrayList(); for(int i = 0; i < 3; i++) jabolka.add(new Jabolko()); // Nema precka na jabolkata da im se dodavaat portokali: jabolka.add(new Portokal()); for(int i = 0; i < jabolka.size(); i++) ((Jabolko)jabolka.get(i)).id(); // Portokalot se otkriva duri za vreme na izvrsuvanjeto. } } /* (Startuvajte za da go vidite rezultatot) *///:~

]e nau~ite pove}e za anotaciite na Java SE5 vo poglavjeto Anotacii. Klasite Jabolko i Portokal se razlikuvaat, tie nemaat ni{to zaedni~ko osven toa {to poteknuvaat od klasata Object. (Ne zaboravajte: ako eksplicitno ne ja navedete klasata od koja nasleduvate, avtomatski }e nasledite Object). Bidej}i ArrayList ~uva klasi na Object , vie ne samo {to mo`ete da gi dodadete Jabolko objektite vo kontejnerot koristej}i go ArrayList metodot add(), tuku isto taka mo`ete da dodavate i objekti od klasata Portokal, a pritoa da ne se pobuni preveduva~ot pri preveduvawe ili izvr{noto opkru`uvawe na Java pri izvr{uvawe. Koga sakate da gi pribavite objektite {to spored va{e mislewe se objekti od tipot Jabolko koristej}i go ArrayList metodot get(), }e vi se vrati referenca na Object {to morate da ja konvertirate vo tip Jabolko. Toga{ treba celiot izraz da go zatvorite vo zagradi za da go prisilite ocenuvaweto na konverzijata pred da go povikate metodot id() za klasata Jabolko. Vo sprotivno, }e predizvikate sintaksna gre{ka. Pri izvr{uvawe, koga se obiduvate objektite od tipot Portokal da gi svedete na tip Jabolko, }e dobiete gre{ka vo forma na prethodno spomenatiot isklu~ok. Vo poglavjeto Generi~ki tipovi, }e nau~ite deka praveweto klasi koristej}i soodvetni mehanizmi na Java mo`e da bide mnogu slo`eno. Sepak, primenata na edna{ definiranite generi~ki klasi e prili~no ednostavna. Na primer, za da definirate ArrayList predviden za ~uvawe objekti od tipot

366

Da se razmisluva vo Java

Brus Ekel

Jabolko, pi{uvate ArrayList namesto samo ArrayList. Aglestite zagradi gi opkru`uvaat parametrite na tipot (mo`e da gi ima pove}e), koi go zadavaat tipot (tipovite) {to mo`e da se ~uvaat od taa instanca na kontejnerot. Mehanizmot na generi~ki tipovi u{te za vreme na preveduvaweto ve spre~uva da stavite pogre{en tip na objekt vo kontejnerot.3 Eve go prethodniot primer napraven so pomo{ na generi~ki tipovi: //: cuvanje/JabolkaIPortokaliSoGenerickiTipovi.java import java.util.*; public class JabolkaIPortokaliSoGenerickiTipovi { public static void main(String[] args) { ArrayList jabolka = new ArrayList(); for(int i = 0; i < 3; i++) jabolka.add(new Jabolko()); // Greska koja se pojavuva za vreme na preveduvanjeto: // jabolka.add(new Portokal()); for(int i = 0; i < jabolka.size(); i++) System.out.println(jabolka.get(i).id()); // Koristejki ja sintaksata foreach: for(Jabolko c : jabolka) System.out.println(c.id()); } } /* Rezultat: 0 1 2 0 1 2 *///:~

3 Na krajot od poglavjeto Generi~ki tipovi }e razgledame dali toa e ba{ tolku te`ok problem. Sepak, vo istoto poglavje }e poka`eme deka generi~kite tipovi na Java ovozmo`uvaat po{iroka upotreba od kontejnerite koi se gri`at za bezbedna rabota so tipovite. Sega preveduva~ot }e ve spre~i da stavite objekt od tipot Portokal vo jabolka, pa taa gre{ka }e se pojavi pri preveduvaweto, a ne pri izvr{uvaweto. Obrnete vnimanie i na toa deka ne e potrebno sveduvawe na tipovi koga gi vadite stavkite od List. Bidej}i List znae koj tip go sodr`i, taa go vr{i sveduvaweto koga }e go povikate metodot get(). Ottuka, zaradi generi~kite tipovi, ne samo {to znaete deka preveduva~ot }e go proveri tipot na objekt {to go smestuvate vo kontejnerot, tuku i dobivate po~ista sintaksa koga gi koristite objektite vo kontejnerot.

^uvawe objekti

367

Ovoj primer isto taka poka`uva deka, ako ne vi treba da go koristite indeksot od sekoj element, mo`ete da ja koristite foreach sintaksata za izbor na sekoj element od List. Ne ste ograni~eni so smestuvawe na to~niot tip vo kontejnerot koga go zadavate kako generi~ki parametar. Sveduvaweto nagore raboti so generi~kite tipovi isto taka kako {to raboti so site drugi tipovi. //: cuvanje/GenerickiTipoviISveduvanjeNagore.java import java.util.*; class class class class

GreniSmit extends Jabolko {} Gala extends Jabolko {} Fudzi extends Jabolko {} Breburn extends Jabolko {}

public class GenerickiTipoviISveduvanjeNagore { public static void main(String[] args) { ArrayList jabolka = new ArrayList(); jabolka.add(new GreniSmit()); jabolka.add(new Gala()); jabolka.add(new Fudzi()); jabolka.add(new Breburn()); for(Jabolko c : jabolka) System.out.println(c); } } /* Rezultat: (primerok) GreniSmit@7d772e Gala@11b86e7 Fudzi@35ce36 Breburn@757aef *///:~

Ottuka, vo eden kontejner odreden za ~uvawe objekti od tipot Jabolko, mo`ete da dodavate i podtipovi na klasata Jabolko. Rezultatot (izlezot) go proizveduva podrazbiraniot metod toString() od klasata Object, koja {to go ispi{uva imeto na klasata prosledeno so heksadecimalniot he{ kod na objektot (generiran od strana na metodot hashCode(). He{ kodovite }e gi razgledame detaqno vo poglavjeto Detaqno razgleduvawe na kontejnerite. Ve`ba 1: (2) Napravete nova klasa imenuvana MorskoPrase so ~len int brojNaPrasinja {to e inicijaliziran vo konstruktorot. Dodadete ja klasata na metodot skoka() koj go ispi{uva brojot na morskoto prase i dali toa skoka. Napravete nov kontejner od tipot ArrayList i dodadete nekolku objekti od klasata MorskoPrase vo listata. Sega upotrebete go metodot get() za da se dvi`ite niz listata i da go povikuvate metodot skoka() za sekoj objekt od tipot MorskoPrase. 368

Da se razmisluva vo Java

Brus Ekel

Osnovni poimi Kontejnerskata biblioteka na Java ja vr{i zada~ata „~uvawe na objekti” i ja deli na dva posebni poim, izrazeni vo oblikot na osnovniot interfejs na bibliotekata: 1. Collection (kolekcija): grupa od poedine~ni elementi na koi ~esto se primenuvaat edno ili pove}e pravila. List (lista) mora da gi ~uva elementite po nekoj odreden redosled, Set (mno`estvo) ne mo`e da gi sodr`i onie elementi {to se povtoruvaat, a Queue (red) dava elementi vo redosled odreden od disciplina za ~ekawe (obi~no po istiot redosled po koj se vmetnati elementite). 2. Map (mapa): grupa od parovi objekt-klu~, koja ovozmo`uva da pronao|ate razni vrednosti so pomo{ na klu~. ArrayList vi ovozmo`uva pronao|awe objekt koristej}i broj, pa na nekoj na~in gi povrzuva broevite na objektite. Mapata vi ovozmo`uva isto taka da najdete eden objekt so pomo{ na drug objekt. Taa u{te se narekuva asocijativna niza, bidej}i objektite gi asocira (povrzuva) so drugi objekti, ili re~nik, bidej}i objektot se bara so pomo{ na klu~, kako {to definicijata vo re~nikot se bara so pomo{ na zbor. Mapite se isklu~itelno mo}ni programski alatki. Iako ne e sekoga{ vozmo`no, bi bilo sovr{eno pogolemiot del od va{iot da raboti so tie interfejsi, a edinstvenoto mesto na koe }e go spomenuvate to~niot tip koj go upotrebuvate da bide mestoto na pravewe na instacata. Ottuka, mo`ete da napravite List nalik na ovaa: List jabolka = new LinkedList();

Vodete smetka i za toa deka ArrayList e svedena nagore vo List, {to e sprotivno na na~inot na koj rabotevme vo prethodnite primeri. Namerata za koristewe na ovoj interfejs e slednava: ako posakate da ja promenite va{ata realizacija, se {to }e treba da napravite e da ja promenite na mestoto na pravewe, na sledniov na~in: List jabolka = new LinkedList();

Ottuka, voobi~aeno }e pravite objekt od konkretna klasa, }e go svedete nagore kon soodvetniot interfejs i potoa }e go koristite toj interfejs vo ostatokot od va{iot kod. Ovoj pristap nema da raboti sekoga{, bidej}i nekoi klasi imaat dodatni funkcii. Na primer, LinkedList ima dodatni metodi {to ne se vo interfejsot List, a TreeMap ima metodi {to ne se vo interfejsot Map. Ako treba da gi iskoristite tie metodi, nema da bidete sposobni da sveduvate nagore kon poop{t interfejs.

^uvawe objekti

369

Interfejsot Collection ja obop{tuva idejata za sekvenca- na~in na ~uvawe grupi od objekti. Eve ednostaven primer vo koj Collection (ovde pretstaven so ArrayList) se polni so Integer objekti, a potoa se ispi{uva sekoj element vo rezultantniot kontejner: //: cuvanje/EdnostavnaKolekcija.java import java.util.*; public class EdnostavnaKolekcija { public static void main(String[] args) { Kolekcija c = new ArrayList(); for(int i = 0; i < 10; i++) c.add(i); // Avtomatsko pakuvanje for(Integer i : c) System.out.print(i + ", "); } } /* Rezultat: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, *///:~

Bidej}i vo ovoj primer se iskoristeni samo metodite od interfejsot Collection, koja bilo klasa nasledena od Collection bi rabotela, no ArrayList e najosnovniot tip na sekvenca. Imeto na metodot add() ne tera da pomislime deka toj vo kolekcijata (Collection) dodava nov element. Sepak, vo dokumentacijata vnimatelno e navedeno deka metodot add() „obezbeduva Collection interfejsot da go sodr`i opredeleniot element.” Ova se pravi zaradi Set, {to go dodava elementot samo ako ne e ve}e tamu. So ArrayList, ili bilo koj tip na lista, metodot add() sekoga{ ima zna~ewe „smesti go vnatre”, bidej}i List dozvoluva postoewe na duplikati. Niz site kolekcii mo`e da se pominuva koristej}i ja foreach sintaksata, kako {to e poka`ano tuka. Podocna vo ova poglavje }e nau~ite za eden pofleksibilen koncept nare~en Iterator. Ve`ba 2: (1) Promenete ja programata EdnostavnaKolekcija.java taka {to za s da koristi Set. Ve`ba 3: (2) Promenete ja programata vnatresniklasi/Sekvenca.java taka da mo`ete da i dodadete proizvolen broj na element.

Dodavawe grupa od elementi Postojat uslu`ni metodi vo klasite Arrays i Collections vo paketot java.util koi dodavaat grupi od elementi vo kontejnerot (potklasata na interfejsot Collection) . Metodot Arrays.asList() prima niza ili lista na elementi razdeleni so zapirka (koristej}i promenlivi argumenti) i gi pretvora vo List objekti. Metodot Collections.addAll() zema objekt od interfejsot Collection

370

Da se razmisluva vo Java

Brus Ekel

i niza ili lista so elementi razdeleni so zapirka i gi dodava elementite na Collection. Eve primer {to gi demonstrira dvata metodi, kako i pokonvencionalniot metod addAll() koja ja sodr`at site tipovi na kontejneri: //: holding/DodavanjeNaGrupi.java // Dodavanje na grupa od elementi na objektite od Kolekcija. import java.util.*; public class DodavanjeNaGrupi { public static void main(String[] args) { Kolekcija kolekcija = new ArrayList(Arrays.asList(1, 2, 3, 4, 5)); Integer[] povekjeCeliBroevi = { 6, 7, 8, 9, 10 }; kolekcija.addAll(Arrays.asList(povekjeCeliBroevi)); // Raboti znacajno pobrzo , no na ovoj nacin ne mozete // da napravite objekt od tipot Kolekcija: Kolekcii.addAll(kolekcija, 11, 12, 13, 14, 15); Kolekcii.addAll(kolekcija, povekjeCeliBroevi); // Proizveduva lista ‚podrzana‛ od niza: List list = Arrays.asList(16, 17, 18, 19, 20); list.set(1, 99); // OK – izmenet eden element // list.add(21); // Greska pri preveduvanjeto zatoa sto // na pripadnata niza ne moze da i se promeni goleminata. } } ///:~

Konstruktorot za Collection mo`e da prifati drug Collection koj go upotrebuva za sopstvena inicijalizacija, pa mo`ete da koristite metod Arrays.asList() za da proizvedete vlez za konstruktorot. Sepak, Collections.addAll() raboti mnogu pobrzo, a ednakvo lesno e da se napravi Collection bez elementi i potoa da se povika metodot Collections.addAll(), pa na toj pristap treba da mu se dade prednost. Metodot ~len Collection.addAll() kako argument mo`e da primi samo drug objekt od tipot Collection, pa zatoa ne e fleksibilen kako metodot Arrays.asList() ili metodot Collections.addAll() koi koristat listi so promenlivi argumenti. Isto taka e mo`no da se koristi izlezot od metodot Arrays.asList() direktno, kako List, no vo toj slu~aj toj e pretstaven od nizata, a negovata golemina ne mo`e da se menuva. Ako se obidete na takvata lista da gi dodadete ( add() ) ili izbri{ete ( delete()) elementite vo takva lista, so toa bi se obidele da ja promenite goleminata na nizata, {to za vreme na izvr{uvaweto predizvikuva gre{ka „Unsupported Operation”. Ograni~uvaweto na metodot Arrays.asList() le`i vo toa {to toj samiot samo naga|a koj e rezultantniot tip na List i ne obrnuva vnimanie na toa zo{to mu ja dodeluvate. Ponekoga{ ova predizvikuva problemi:

^uvawe objekti

371

//: cuvanje/KakoNekakvaLista.java // Arrays.asList() samo pogoduva za koj tip se raboti. import java.util.*; class class class class class class

Sneg {} Snezec extends Sneg {} Slab extends Snezec {} Krupen extends Snezec {} Krckav extends Sneg {} Lizgav extends Sneg {}

public class KakoNekakvaLista { public static void main(String[] args) { List snow1 = Arrays.asList( new Krckav(), new Lizgav(), new Snezec()); // // // // // //

Ne moze da se preveduva: List sneg2 = Arrays.asList( new Slab(), new Krupen()); Preveduvacot ke soopsti: found : java.util.List required: java.util.List

// Kolekcii.addAll() nema da se zbuni: List sneg3 = new ArrayList(); Kolekcii.addAll(sneg3, new Slab(), new Krupen()); // Ke dademe navestuvanje so // eksplicitno zadavanje na tip na argumenti: List sneg4 = Arrays.asList( new Slab(), new Krupen()); } } ///:~

Koga se obiduva da go napravi sneg2, metodot Arrays.asList() gi ima samo tipovite od klasata Snezec, taka {to pravi List, a ne List, dodeka metodot Collections.addAll()raboti sovr{eno bidej}i od prviot argument znae koj e celniot tip. Kako {to gledate vo primerot za praveweto na lista sneg4, vo sredinata na metodot Arrays.asList() mo`ete da smestite i „navestuvawe”, za da mu go soop{tite na preveduva~ot vistinskiot tip na celta na rezultantnata lista od tipot List napravena od metodot Arrays.asList(). Toa se narekuva eksplicitno zadavawe na tipot na argumentot. Mapite se poslo`eni, kako {to }e vidite, a i standardnata biblioteka na Java ne ovozmo`uva na~in za nivno avtomatsko inicijalizirawe, osven vo sodr`inite na druga mapa.

372

Da se razmisluva vo Java

Brus Ekel

Ispi{uvawe na sodr`inite na kontejnerite Morate da koristite metod Arrays.toString() za da mo`ete da ja ispi{ete sodr`inata na edna niza, no kontejnerite ispi{uvaat odli~no bez bilo kakva pomo{. Eve primer {to isto taka ve zapoznava so osnovnite kontejneri na Java: //: cuvanje/IspisuvanjeKontejneri.java // Sodrzinata na kontejnerot se ispisuva avtomatski. import java.util.*; import static net.mindview.util.Print.*; public class IspisuvanjeKontejneri { static Kolekcija popolni(Collection kolekcija) { kolekcija.add("rat"); kolekcija.add("macka"); kolekcija.add("mutt"); kolekcija.add("mutt"); return kolekcija; } static Map popolni(Map mapa) { mapa.put("rat", "Misko"); mapa.put("macka", "Mimi"); mapa.put("mutt", "Sharko"); mapa.put("mutt", "Crnka"); return mapa; } public static void main(String[] args) { print(fill(new ArrayList())); print(fill(new LinkedList())); print(fill(new HashSet())); print(fill(new TreeSet())); print(fill(new LinkedHashSet())); print(fill(new HashMap())); print(fill(new TreeMap())); print(fill(new LinkedHashMap())); } } /* Rezultat: [rat, macka, mutt, mutt] [rat, macka, mutt, mutt] [mutt, macka, rat] [macka, mutt, rat] [rat, macka, mutt] {mutt=Crnka, macka=Mimi, rat=Misko} {macka=Mimi, mutt=Crnka, rat=Misko} {rat=Misko, macka=Mimi, mutt=Crnka} *///:~

^uvawe objekti

373

Ova gi poka`uva dvete primarni kategorii vo bibliotekata so kontejneri na Java. Razlikata se bazira na brojot na elementi {to se ~uvaat vo sekoja lokacija vo kontejnerot. Kategorijata Collection samo ~uva po eden element vo sekoja lokacija. Ovaa kategorija gi vklu~uva slednite interfejsi: List, koj ~uva grupa na elementi vo zadaden redosled, Set, koj {to dozvoluva dodavawe samo na eden element so ista vrednost i Queue, koj {to edinstveno vi dozvoluva da vmetnuvate objekti na edniot „kraj” od kontejnerot i da gi otstranuvate objektite od drugiot „kraj” (za potrebite na ovoj primer, ova e samo drug na~in za barawe na sekvenca, pa zatoa ne e poka`an). Edna mapa ~uva dva objekti, klu~ i pridru`ena vrednost, vo sekoja lokacija. Od rezultatot na programata mo`ete da vidite deka podrazbiranoto odnesuvawe {to se odnesuva na ispi{uvaweto (izlez na metodot toString() na sekoj kontejner) proizveduva ~itlivi rezultati. Collection se ispi{uva vo sredni zagradi [], spri {to elementite se razdeleni so zapirka. Mapata se nao|a vo mali zagradi (), pri {to klu~evite i vrednostite {to im se pridru`eni se povrzani so znakot za ednakvost (=) (klu~evite na levata strana, vrednostite na desnata). Prviot metod popolni() raboti so site tipovi na Collection, od koi sekoj go realizira metodot add() za da vklu~i novi elementi. ArrayList i LinkedList se tipovi na List i mo`ete da vidite od rezultatot deka dvete ~uvaat elementi vo ist redosled po koj tie se vneseni. Razlikata pome|u niv ne e samo vo izvedbata na odredeni tipovi na operacii, tuku LinkedList sodr`i pove}e operacii od ArrayList. Ova }e bide razgledano detaqno podocna vo ova poglavje. Hashset.TreeSet i LinkedHashSet se tipovi na kategorijata Set. Izlezot poka`uva deka edno mno`estvo (Set) }e ~uva samo samo po eden primerok od identi~ni predmeti, no isto taka poka`uva deka razli~nite realizacii na mno`estva gi skladiraat elementite razli~no. HashSet gi skladira elementite koristej}i slo`en pristap koj }e go razgledame vo poglavjeto Detaqno razgleduvawe na kontejnerite- zasega e dovolno da se znae deka taa tehnika ovozmo`uva najbrzo vadewe na elementite, iako redosledot na nivnoto skladirawe izgleda besmislen (~esto e va`no samo dali objektot e ~len na odredeno mno`estvo od kategorijata Set, dodeka redosledot na elementi vo toa mno`estvo nema posebno zna~ewe.) Ako e va`en redosledot na skladirawe, mo`ete da koristite TreeSet koj gi ~uva objektite vo raste~ki redosled, ili LinkedHashSet, koj gi ~uva objektite vo redosledot na nivnoto vmetnuvawe. Mapa, (koja isto taka se narekuva i asocijativna niza) vi ovozmo`uva pronao|awe na objekt koristej}i klu~, kako vo ednostavna baza na podatoci. Pridru`eniot objekt se narekuva vrednost. Ako imate Mapa vo koja na imiwata na dr`avite im se pridru`eni imiwata na nivnite glavni gradovi i sakate da doznaete koj e glavniot grad na Gruzija, prebaruvaweto go vr{ite

374

Da se razmisluva vo Java

Brus Ekel

so pomo{ na klu~ „Gruzija”- re~isi i kako da e vo pra{awe indeks na niza. Poradi takvoto odnesuvawe, Mapata prifa}a samo po eden primerok od sekoj klu~. Map.put(kluc, vrednost) vmetnuva vrednosta vo mapata (toa {to sakate da go skladirate) i í pridru`uva klu~ (so ~ija pomo{ }e ja pronajdete taa vrednost). Map.get(kluc) dava vrednost pridru`ena so dadeniot klu~. Vo gorniot primer samo se dodavani parovite klu~-vrednost, a ne se izvr{uva prebaruvawe. Toa }e bide poka`ano podocna. Imajte vo predvid deka ne morate da zadadete (ili voop{to da razmisluvate za) goleminata na Mapa bidej}i taa svojata golemina ja podesuva avtomatski. Isto taka, Mapite znaat samite da ja ispi{uvaat svojata sodr`ina, pri {to se prika`uvaat parovite klu~-vrednost. Vo Mapite klu~evite i vrednostite ne se ~uvaat po istiot redosled vo koj se vmetnati, zatoa {to realizacijata na tipot HashMap upotrebuva mnogu brz algoritam koj go odreduva toj redosled.

Vo primerot se upotrebeni tri osnovni tipovi na Mapi: HashMap, TreeMap i LinkedHashMap. Kako i HashSet, HashMap obezbeduva najbrza tehnika za prebaruvawe i isto taka, ni taa mapa ne gi ~uva svoite elementi vo lesno razbirliv redosled. Vo mapata od tipot TreeMap klu~evite se podredeni vo raste~ki redosled, a vo mapata od tipot LinkedHashMap vo redosledot na vmetnuvawe, pri {to e zadr`ana brzinata na prebaruvawe na tipot HashMap. Ve`ba 4: (3) Napravete generatorska klasa koja vra}a imiwa (kako objekti od tip String) na likovite od va{iot omilen film (Sne`ana i sedumte Xuxiwa ili Vojna na Yvezdite, ne e va`no) sekoj pat koga }e go povikate metodot next() i se vra}a na po~etokot od listata so imiwa na likovi koga }e dojde do nejziniot kraj. Upotrebete go toj generator za popolnuvawe obi~na niza i po eden primerok od tipovite ArrayList, LinkedList, HashSet, LinkedHashSet i TreeSet. Potoa, otpe~atete ja sodr`inata na sekoj od tie kontejneri.

Listi Listite gi ~uvaat elementite vo odreden redosled. Interfejsot List na kategorijata Collection i dodava odreden broj na metodi {to ovozmo`uva vmetnuvawe i otstranuvawe na elementite od sredinata na List . Postojat dva tipa na List: Osnovniot tip ArrayList, koj e odli~en za pristapuvawe na elementite po slu~aen redosled, no e pobaven koga se vmetnuvaat i otstranuvaat elementite od sredinata na List.

^uvawe objekti

375

Tipot LinkedList obezbeduva optimalen sekvencijalen pristap, so eftini vmetnuvawa i otstranuvawa od sredinata na List. LinkedList e relativno baven za slu~aen pristap, no ima pogolemo mno`estvo karakteristiki vo odnos na ArrayList. Vo sledniot primer }e vneseme biblioteka typeinfo.pets, opi{ana vo poglavjeto Podatoci za tipot vo prodol`enieto od ovaa kniga. Taa biblioteka sodr`i hierarhija na klasite Pet (doma{ni milenici) i nekoi alatki za slu~ajno generirawe na Pet objekti. Zasega ne morate da gi znaete site detali, tuku samo deka (1) postoi klasa Pet i razli~ni nejzini podtipovi i deka (2) stati~niot metod Pet.arrayList() go vra}a ArrayList popolnet so slu~ajno izbrani Pet objekti: //: cuvanje/ListaNaKarakteristiki.java import typeinfo.pets.*; import java.util.*; import static net.mindview.util.Print.*; public class ListaNaKarakteristiki { public static void main(String[] args) { Random slucaen = new Random(47); List pets = Pets.arrayList(7); print("1: " + pets); Hamster h = new Hamster(); pets.add(h); // Avtomatski ja podesuva svojata golemina print("2: " + pets); print("3: " + pets.contains(h)); pets.remove(h); // Otstranuvanje na osnova na objekt Pet p = pets.get(2); print("4: " + p + " " + pets.indexOf(p)); Pet cymric = new Cymric(); print("5: " + pets.indexOf(cymric)); print("6: " + pets.remove(cymric)); // Mora da bide tocno opredelen objekt: print("7: " + pets.remove(p)); print("8: " + pets); pets.add(3, new Mouse()); // Vnesi tamu kade sto pokazuva indeksot print("9: " + pets); List sub = pets.subList(1, 4); print("subList: " + sub); print("10: " + pets.containsAll(sub)); Collections.sort(sub); // Sortiranje vo mesto print("sortirana subList: " + sub); // Redosledot ne e vazen vo metodot containsAll(): print("11: " + pets.containsAll(sub)); Collections.shuffle(sub, slucaen); // Izmesaj print("izmesana subList: " + sub); print("12: " + pets.containsAll(sub)); List kopija = new ArrayList(pets); sub = Arrays.asList(pets.get(1), pets.get(4));

376

Da se razmisluva vo Java

Brus Ekel

print("sub: " + sub); kopija.retainAll(sub); print("13: " + kopija); kopija = new ArrayList(pets); // Napravi nova kopija kopija.remove(2); // Otstrani vrz osnova na indeksot print("14: " + kopija); kopija.removeAll(sub); // Samo gi otstranuva objektite odgovaraat print("15: " + kopija); kopija.set(1, new Mouse()); // Zameni element print("16: " + kopija); kopija.addAll(2, sub); // Vnesi lista vo sredinata print("17: " + kopija); print("18: " + pets.isEmpty()); pets.clear(); // Otstrani gi site elementi print("19: " + pets); print("20: " + pets.isEmpty()); pets.addAll(Pets.arrayList(4)); print("21: " + pets); Object[] o = pets.toArray(); print("22: " + o[3]); Pet[] pa = pets.toArray(new Pet[0]); print("23: " + pa[3].id()); } } /* Rezultat: 1: [Rat, Manx, Cymric, Mutt, Pug, Cymric, Pug] 2: [Rat, Manx, Cymric, Mutt, Pug, Cymric, Pug, Hamster] 3: true 4: Cymric 2 5: -1 6: false 7: true 8: [Rat, Manx, Mutt, Pug, Cymric, Pug] 9: [Rat, Manx, Mutt, Mouse, Pug, Cymric, Pug] subList: [Manx, Mutt, Mouse] 10: true sorted subList: [Manx, Mouse, Mutt] 11: true shuffled subList: [Mouse, Manx, Mutt] 12: true sub: [Mouse, Pug] 13: [Mouse, Pug] 14: [Rat, Mouse, Mutt, Pug, Cymric, Pug] 15: [Rat, Mutt, Cymric, Pug] 16: [Rat, Mouse, Cymric, Pug] 17: [Rat, Mouse, Mouse, Pug, Cymric, Pug] 18: false 19: [] 20: true 21: [Manx, Cymric, Rat, EgyptianMau] 22: EgyptianMau

^uvawe objekti

koi

tocno

377

23: 14 *///:~

Za sekoj red od rezultatot da mo`ete da go povrzete so izvorniot kod, vo programata naredbite print se numerirani. Prviot red od rezultatot ja poka`uva originalnata Lista na Pets. Za razlika od niza, List vi ovozmo`uva da dodavate elementi otkako taa }e bide napravena, ili da otstranuvate elementi pri {to avtomatski si ja prilagoduva goleminata. Toa e nejzinata osnovna vrednost: sekvenca koja mo`e da se modificira. Mo`ete da go vidite rezultatot od dodavaweto na Hamster vo redot so rezultat 2 - objektot e dodaden na krajot od listata. Mo`ete da otkriete dali eden objekt e vo listata koristej}i go metodot contains(). Ako sakate da otstranite nekoj objekt, prosledete mu ja negovata referenca na metodot remove(). Isto taka, ako imate referenca na nekoj objekt, mo`ete da go doznaete negoviot indeks (reden broj) vo List koristej}i go metodot indexOf(), kako {to gledate vo redot so rezultat 4. Metodot equals() (del od korenskata klasa Object) se koristi koga ispituvate dali eden element e del od List, kako i za otkrivawe na indeksot na elementot i otstranuvawe element od List so referenca, . Sekoj objekt od tipot Pet se definira kako unikaten objekt, pa duri i da postojat dva objekta od tipot Cymric, ako napravam nov takov objekt i go prosledam na metodot indexOf(), rezultatot }e bide -1 ({to zna~i deka toj nov tip ne e pronajden), pa obidot za otstranuvawe na objektot preku metodot remove() }e rezultira so false, {to zna~i deka otstranuvaweto ne uspealo. Za drugite klasi, metodot equals() mo`e da se definira poinaku. Na primer, objektite od tipot String (znakovnite nizi) se ednakvi ako sodr`inata na dvete znakovni nizi e identi~na. Ottuka, za da nema iznenaduvawa, vodete smetka i za toa deka odnesuvaweto na List se menuva vo zavisnost od metodot equals(). Od redovite 7 i 8 na rezultatot, se gleda deka e uspe{no otstranuvaweto na objekt {to to~no odgovara na eden objekt od List. Vozmo`no e da se vmetne element vo sredinata na List, kako {to gledate vo redot 9 od rezultatot i kodot koj {to mu prethodi, no od toa sledi zaklu~ok: za LinkedList, vmetnuvaweto i otstranuvaweto od sredinata na listata e operacija koja ne ve ~ini mnogu (osven vo ovoj slu~aj, slu~ajniot pristap vo sredinata na listata), no za ArrayList toa e prili~no skapa operacija. Dali toa zna~i deka nikoga{ ne treba da gi vmetnuvate elementite vo sredinata na ArrayList i deka treba da preminete na LinkedList {tom zatreba takvo ne{to? Ne, toa zna~i deka sekoga{ treba da bidete svesni za ovoj problem i za toa deka ako po~nete da pravite mnotu vmetnuvawa vo sredinata na ArrayList i va{ata programa po~ne da zabavuva, mo`ebi za toa e vinovna va{ata realizacija na List (takvite tesni grla najdobro se otkrivaat, kako {to }e vidite na http://MindView.net/Books/BetterJava, so pomo{ na profajler). Optimizacijata e slo`ena rabota i najdobro e da ne rabotite so nea se

378

Da se razmisluva vo Java

Brus Ekel

dodeka ne otkriete deka treba da se gri`ite za toa (iako ne e lo{o da se razbiraat problemite). Metodot subList() slu`i za ednostavno pravewe ise~oci od pogolemi listi, a ova normalno, proizveduva to~en rezultat koga ise~okot mu se prosleduva na metodot containsAll() za taa pogolema lista. Isto taka interesno e da se zabele`i deka redosledot e irelevanten- mo`ete da vidite vo edinaesetiot i dvanaesetiot red deka na rezultatot na metodot containsAll() ne vlijae povikuvaweto na metodot Collections.sort() (za sortirawe) i na metodot Collection.shuffle() (za me{awe na elementite) na podlistata sub. Metodot subList() proizveduva lista povrzana so originalnata lista. Zatoa promenite vo vratenata lista se odrazuvaat i vo originalnata i obratno. Metodot retainAll() vsu{nost ja sproveduva operacijata “presek na mno`estva”. Vo ovoj slu~aj, metodot vo objektot kopija gi zadr`uva site elementi koi {to se isto taka i vo podlistata sub. Povtorno, rezultantnoto odnesuvawe se menuva vo zavisnost od metodot equals(). ^etirinaesetiot red gi ispi{uva rezultatite od otstranuvaweto na elementite vrz osnova na nivnite indeksi, {to e poednostavno otkolku otstranuvawe vrz osnova na referencata od objekt, bidej}i indeksite ve osloboduvaat od gri`ite za odnesuvaweto na metodot equals(). I odnesuvaweto na metodot removeAll() zavisi od metodot equals(). Kako {to i ka`uva negoviot angliski naziv, toj od Listata gi otstranuva site objekti koi mu se prosledeni vo argumentot sub. Metodot set() e prili~no nesre}no imenuvan, poradi mo`na zbrka so klasata Set – tuka podobar termin bi bil „replace” (zameni), bidej}i toj go zamenuva elementot od indeksot (prviot argument) so vtoriot argument. Sedumnaesetiot red na izlezot poka`uva deka za Listite postoi preklopen metod addAll() koj slu`i za vmetnuvawe na nova lista vo sredinata na prvobitnata, namesto obi~noto dodavawe na krajot na prvobitnata so metodot addAll() (koj e del od klasata Collection). Od osumnaesetiot do dvaesetiot red se prika`ani rezultatite od metodite isEmpty i clear(). Dvaeset i vtoriot i dvaeset i tretiot red od izlezot poka`uvaat kako sekoj kontejner (objekt od tipot Collection) so metodot toArray() mo`ete da go konvertirate vo niza. Toj metod e preklopen. Verzijata koja ne prima argumenti vra}a niza od elementi od tipot Object, no ako na preklopenata verzija i prosledite niza na celniot tip, toga{ taa }e napravi niza od toj tip (pod uslov da ja zadovoluva proverkata na tipovite). Ako nizata e prosledena kako argument premal za skladirawe na site objekti vo List (kako {to e ovde slu~aj), metodot toArray() }e napravi nova niza so soodvetna

^uvawe objekti

379

golemina. Pet objektite imaat metod id()- gledate deka e povikan za eden od objektite vo rezultantnata niza. Ve`ba 5: (3) Promenete ja programata ListFeatures.java taka {to }e koristi celi broevi (potsetete se na avtomatskoto pakuvawe) namesto objekti od tipot Pet. Objasnete gi site razliki vo rezultatite. Ve`ba 6: (2) Promenete ja programata ListFeatures.java taka {to }e koristi objekti od tipot String namesto objekti od tipot Pet i objasnete gi site razliki vo rezultatite. Ve`ba 7: (3) Napravete klasa, potoa napravete inicijalizirana niza od objekti od taa klasa. Popolnete so taa niza edna lista. Napravete podmno`estvo od listata so koristewe na metodot subList(), a potoa otstranete go ova podmno`estvo od listata.

Iteratori Vo koj bilo kontejner, mora da postoi na~in za vmetnuvawe elementi i nivno vadewe. Osnovnata zada~a na kontejnerot e da gi ~uva ne{tata. Vo List klasata, metodot add() e eden od na~inite za dodavawe elementi, a metodot get() e eden od na~inite za ~itawe na elementite. Ako po~nete da razmisluvate na povisoko nivo za kontejnerskata biblioteka na Java, se pojavuva eden nedostatok: morate da go znaete to~niot tip na kontejnerot za da go koristite. Ova na prv pogled ne izgleda lo{o, no {to ako napi{ete kod za List i podocna otkriete deka bi bilo pogodno da go primenite istiot kod na Set? Ili, da pretpostavime deka bi sakale od po~etokot da napi{ete del od generi~kiot kod {to ne znae ili voop{to ne mu e bitno so koj tip na kontejner raboti, za da mo`e da se koristi za razli~ni tipovi na kontejneri bez odnovo da go pi{uvate kodot? Konceptot na Iteratorite (u{te eden proekten model) mo`e da se koristi za postignuvawe na ovaa apstrakcija. Iterator e objekt ~ija rabota e da se dvi`i niz niza od objekti i da go izbere sekoj objekt vo taa niza bez programerot klient da znae ili da se gri`i za strukturata na taa niza. Osven toa, eden iterator voobi~aeno se narekuva lesen objekt (angliski- lightweight object), takov koj ne e skap za pravewe. Od taa pri~ina, ~esto }e naiduvate na naizgled ~udni ograni~uvawa za iteratorite; na primer, iteratorot na Java mo`e da se dvi`i samo vo edna nasoka. Nema mnogu ne{ta {to mo`ete da gi napravite so eden iterator osven: 1. Da pobarate od kontejnerot so metodot iterator() da vi go prosledi Iterator, Dobieniot Iterator e spremen da go vrati prviot element od nizata po prviot povik od negoviot metod next(). 2.

380

Da go dobiete sledniot objekt vo nizata so pomo{ na metodot next().

Da se razmisluva vo Java

Brus Ekel

3. Da proverite dali ima u{te objekti vo nizata so pomo{ na metodot hasNext(). 4. Da go otstranite posledniot element, vraten od iteratorot, so pomo{ na metodot remove(). Za da vidite kako toj raboti, povtorno }e ja upotrebime klasata Pet i nejzinite metodi, opi{ani vo poglavjeto Podatoci za tipot: //: cuvanje/EdnostavnaIteracija.java import typeinfo.pets.*; import java.util.*; public class EdnostavnaIteracija { public static void main(String[] args) { List Milenici = Pets.arrayList(12); Iterator it = milenici.iterator(); while(it.hasNext()) { Pet p = it.next(); System.out.print(p.id() + ":" + p + " "); } System.out.println(); // Poednostaven pristap, koga e vozmozno: for(Pet p :milenici) System.out.print(p.id() + ":" + p + " "); System.out.println(); // Eden iterator moze i da otstranuva elementi: it = milenici.iterator(); for(int i = 0; i < 6; i++) { it.next(); it.remove(); } System.out.println(milenici); } } /* Rezultat: 0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug 7:Manx 8:Cymric 9:Rat 10:EgyptianMau 11:Hamster 0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug 7:Manx 8:Cymric 9:Rat 10:EgyptianMau 11:Hamster [Pug, Manx, Cymric, Rat, EgyptianMau, Hamster] *///:~

So eden iterator, nema potreba od toa da se gri`ite za brojot na elementi vo kontejnerot. Za toa se gri`at metodot hasNext() i metodot next(). Za da se dvi`ite napred niz listata ne obiduvaj}i se da go menuvate samiot objekt List, mo`ete da vidite deka sintaksata foreach e popogodna za taa prilika.

^uvawe objekti

381

Iterator isto taka }e go otstrani posledniot element proizveden od metodot next(), {to zna~i deka morate da go povikate metodot next(), pred da go povikate metodot remove().4 Koristeweto kontejner i dvi`eweto niz nego za da se izvr{uvaat operacii nad sekoj element e mnogu mo}na tehnika i }e zabele`ite deka mnogu ~esto se koristi vo ovaa kniga. Da pogledneme sega kako izgleda metodot pecatiSe() koj raboti so site vidovi na kontejneri: //: cuvanje/IteracijaNizSiteVidoviNaKontejneri.java import typeinfo.pets.*; import java.util.*; public class IteracijaNizSiteVidoviNaKontejneri { public static void prikaziSe(Iterator it) { while(it.hasNext()) { Pet p = it.next(); System.out.print(p.id() + ":" + p + " "); } System.out.println(); } public static void main(String[] args) { ArrayList milenici = Pets.arrayList(8); LinkedList mileniciLL = new LinkedList(milenici); HashSet mileniciHS = new HashSet(milenici); TreeSet mileniciTS = new TreeSet(milenici); prikaziSe(milenici.iterator()); prikaziSe(mileniciLL.iterator()); prikaziSe(mileniciHS.iterator()); prikaziSe(mileniciTS.iterator()); } } /* Rezultat: 0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug 7:Manx 0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug 7:Manx 4:Pug 6:Pug 3:Mutt 1:Manx 5:Cymric 7:Manx 2:Cymric 0:Rat 5:Cymric 2:Cymric 7:Manx 1:Manx 3:Mutt 6:Pug 4:Pug 0:Rat *///:~

4 metodot remove() spa|a i vo takanare~enite opcioni metodi (gi ima i pove}e), {to zna~i deka ne mora da gi realiziraat site realizacii na iteratorot. Za toa }e zboruvame detaqno vo poglavjeto Detaqno razgleduvawe na kontejnerite. Kako site standardni kontejneri, bibliotekite na Java realiziraat metod remove(), pa za toa ne morate da se gri`ite (dodeka ne dojdete do spomenatoto poglavje). Obrnete vnimanie deka metodot pecatiSe() ne znae ni{to za tipot na nizata niz koja pominuva, a toa ja poka`uva vistinskata sila na Iteratorot: mo`nosta

382

Da se razmisluva vo Java

Brus Ekel

na razdvojuvawe na operacijata na pominuvawe niz niza od nejzinata struktura. Poradi ovaa pri~ina, ponekoga{ velime deka iteratorite go obedinuvaat pristapot do kontejnerite. Ve`ba 8: (1) Prepravete ja ve`ba 1 taka {to za dvi`ewe niz List upotrebuva Iterator koga }e se povika metodot skokaj(). Ve`ba 9: (4) Izmenete ja programata vnatresniklasi/Sekvenca.java taka {to Sekvenca da raboti so Iteratorot namesto so Selectorot. Ve`ba 10: (2) Izmenete ja ve`ba 9 od poglavjeto Polimorfizam taka {to Glodarite da se ~uvaat vo ArrayList i za dvi`eweto niz Glodarot da se upotrebuva iterator. Ve`ba 11: (2) Napi{ete metod koj upotrebuva Iterator za pominuvawe niz kontejner (objekt od tipot Collection). Ispi{ete ja sodr`inata na site objekti vo kontejnerot so metodot toString(). Popolnete gi objektite so site razli~ni tipovi kontejneri i na sekoj od niv primenete va{ metod.

ListIterator Za listite postoi ponapreden iterator, ListIterator. Dodeka iteratorot mo`e da se dvi`i samo napred, ListIterator e dvonaso~en. Isto taka mo`e da gi proizvede indeksite na prethodnite i slednite elementi vo odnos na mestoto kade toj iterator poka`uva vo listata, kako i da go zameni posledniot element koj go posetil, koristej}i go metodot set(). Mo`ete da proizvedete ListIterator {to poka`uva kon po~etokot na List so povikuvaweto na metodot ListIterator(), a so zadavaweto na argument n (kako vo listIterator(n)) }e napravite ListIterator koj po~nuva poka`uvaj}i na indeksot n vo listata. Eve primer vo koj se poka`ani site navedeni mo`nosti: //: cuvanje/IteracijaNaListi.java import typeinfo.pets.*; import java.util.*; public class IteracijaNaListi { public static void main(String[] args) { List milenici = Pets.arrayList(8); ListIterator it = milenici.listIterator(); while(it.hasNext()) System.out.print(it.next() + ", " + it.nextIndex() + ", " + it.previousIndex() + "; "); System.out.println(); // Nanazad: while(it.hasPrevious()) System.out.print(it.previous().id() + " "); System.out.println(); System.out.println(milenici); it = milenici.listIterator(3);

^uvawe objekti

383

while(it.hasNext()) { it.next(); it.set(Milenici.randomPet()); } System.out.println(milenici); } } /* Rezultat: Rat, 1, 0; Manx, 2, 1; Cymric, 3, 2; Mutt, 4, 3; Pug, 5, 4; Cymric, 6, 5; Pug, 7, 6; Manx, 8, 7; 7 6 5 4 3 2 1 0 [Rat, Manx, Cymric, Mutt, Pug, Cymric, Pug, Manx] [Rat, Manx, Cymric, Cymric, Rat, EgyptianMau, Hamster, EgyptianMau] *///:~

Metodot Pets.randomPet() gi zamenuva site objekti od tipot Pet vo List od lokacijata 3 nanapred. Ve`ba 12: (3) Napravete i popolnete edna celobrojna lista (List). Napravete druga celobrojna lista so istata golemina i upotrebete ListIterator za ~itawe na elementite od prvata lista i nivno vmetnuvawe vo druga lista vo obraten redosled. (Ovaa zada~a bi trebalo da ja re{ite na pove}e na~ini.)

Povrzana Lista I klasata LinkedList realizira osnoven interfejs List kako ArrayList, no nekoi odredeni operacii (kako vmetnuvawe vo sredinata na List i otstranuvawe od nea) gi vr{i so pogolema efikasnost od ArrayList. Od druga strana, pomalku e efikasna za operacii na pristapuvawe na nesekvencijalen redosled. LinkedList isto taka dodava metodi {to ni ovozmo`uvaat da ja koristime kako stek, kako red za ~ekawe (Queue) ili dvostran red za ~ekawe (angliskidouble-ended queue, deque). Nekoi od ovie metodi se psevdonimi (alijasi) ili me|usebni blagi varijacii, za da se dobijat imiwa koi {to se poznati vo ramkite na kontekstot na odredena upotreba (posebno redovite za ~ekawe). Na primer, metodot getFirst() i metodot element() se identi~ni- tie ja vra}aat glavata (prviot element) na listata bez da go otstranat i go generiraat isklu~okot NoSuchElementException ako List e prazna. Metodot peek() e nekoja nivna varijacija koja vra}a vrednost null ako listata e prazna. Identi~ni se i metodite removeFirst() i remove(). Tie prvin ja otstranuvaat, pa ja vra}aat glavata na listata i go generiraat isklu~okot NoSuchElementException ako List e prazna, a nivnata blaga varijacija, metodot poll(), vra}a vrednost null ako listata e prazna.

384

Da se razmisluva vo Java

Brus Ekel

Metodot addFirst() vmetnuva element na po~etokot od listata. Metodot offer() e ist kako i add() i addLast(). Site tie dodavaat element na krajot na listata. Metodot removeLast() go otstranuva i go vra}a posledniot element od listata. Sledi primer za osnovnite sli~nosti i razliki pome|u ovie metodi. Vo nego ne se povtoruva odnesuvaweto poka`ano vo programata MoznostiNaListite.java: //: cuvanje/MetodiNaKlasataLinkedList.java import typeinfo.pets.*; import java.util.*; import static net.mindview.util.Print.*; public class MetodiNaKlasataLinkedList { public static void main(String[] args) { LinkedList milenici = New;l LinkedList(Pets.arrayList(5)); print(milenici); // Identicni: print("milenici.getFirst(): " + milenici.getFirst()); print("milenici.element(): " + milenici.element()); // Gi razlikuva samo reakciite na praznata lista: print("milenici.peek(): " + milenici.peek()); // Identicni; otstranuvaat i vrakjaat prv element: print("milenici.remove(): " + milenici.remove()); print("milenici.removeFirst(): " + milenici.removeFirst()); // Gi razlikuva samo reakciite na praznata lista: print("milenici.poll(): " + milenici.poll()); print(milenici); milenici.addFirst(new Rat()); print("Po addFirst(): " + milenici); milenici.offer(Pets.randomPet()); print("Po offer(): " + milenici); milenici.add(Pets.randomPet()); print("Po add(): " + milenici); milenici.addLast(new Hamster()); print("Po addLast(): " + milenici); print("milenici.removeLast(): " + milenici.removeLast()); } } /* Rezultat: [Rat, Manx, Cymric, Mutt, Pug] milenici.getFirst(): Rat milenici.element(): Rat milenici.peek(): Rat milenici.remove(): Rat milenici.removeFirst(): Manx milenici.poll(): Cymric [Mutt, Pug] Po addFirst(): [Rat, Mutt, Pug]

^uvawe objekti

385

Po offer(): [Rat, Mutt, Pug, Cymric] Po add(): [Rat, Mutt, Pug, Cymric, Pug] Po addLast(): [Rat, Mutt, Pug, Cymric, Pug, Hamster] milenici.removeLast(): Hamster *///:~

Rezultatot od metodot Pets.arrayList() mu go prosleduvame na konstruktorot na listata LinkedList za da ja popolnime. Vo dokumentacijata za interfejsot Queue }e gi vidite metodite element(), offer(), peek(), poll() i remove() koi bea dodadeni na klasata LinkedList so cel taa klasa da bide realizacija na red za ~ekawe. Kompletni primeri za redovi za ~ekawe }e vidite vo ostanatiot del od ova poglavje. Ve`ba 13: (3) Vo primerot vnatresniklasi/UpravuvacSoStaklenaGradina.java, klasata Controller koristi ArrayList. Iskoristete ja namesto nea listata LinkedList i koristete Iterator za kru`ewe niz mno`estvoto nastani. Ve`ba 14: (3) Napravete prazna lista LinkedList. Vo sredinata na listata dodadete Integeri so pomo{ na ListIterator.

Stack Stekot ponekoga{ se narekuva i LIFO kontejner (angliski- last-in, first-out, posledniot koj vleguva, prv izleguva). Toa zna~i deka ona {to posledno }e go stavite na stekot (za toa tradicionalno se koristi operacijata push) prvo morate da go otstranite od nego (za ova pak se koristi operacijata pop). Sketot ~esto se sporeduva so stog seno- poslednata slamka seno koja ja frlate na vrvot od stogot, }e bide prvata {to }e ja zemete. Klasata LinkedList ima metodi koi direktno realiziraat stek, pa namesto da pravite posebna klasa stek, mo`ete da upotrebite povrzana lista. Vo nekoi slu~ai sepak e podobro da se napravi klasa stek: //: net/mindview/util/Stek.java // Pravenje stek od objekti od tipot LinkedList. package net.mindview.util; import java.util.LinkedList; public class Stek { private LinkedList skladiste = new LinkedList(); public void push(T v) { skladiste.addFirst(v); } public T peek() { return skladiste.getFirst(); } public T pop() { return skladiste.removeFirst(); } public boolean empty() { return skladiste.isEmpty(); } public String toString() { return skladiste.toString(); } } ///:~

Ova go pretstavuva najednostavniot mo`en primer za definicija na generi~ka klasa. Toa po imeto na klasata, mu ka`uva na preveduva~ot deka ova }e bide parametiziran tip i deka tipot na parametarot {to }e se 386

Da se razmisluva vo Java

Brus Ekel

zameni so realen tip koga klasata }e bide upotrebena e toa T. Vo su{tina, toa ka`uva „go definirame Stack koj gi ~uva objektite od tip T”. Toj Stack se realizira na povrzana na koja isto taka i e naredeno da go ~uva tipot T. Obrnete vnimanie na toa deka metodot push() go zema objektot T koj go vra}aat metodite peek() i pop(). Metodot peek() go vra}a najvisokiot element bez da go otstrani od vrvot na stekot, dodeka metodot pop() go otstranuva, pa go vra}a. Ako sakate da se ograni~ite samo na funkcionalnosta na stekot, nasleduvaweto ne e ba{ soodvetno, zatoa {to bi proizvelo klasa so site metodi od LinkedList (}e vidite vo poglavjeto Detaqno razgleduvawe na kontejnerite deka takva gre{ka napravile proektantite na bibliotekata Java 1.0 vo klasata java.util.Stack). Eve ednostaven primer za novata klasa Stack: //: cuvanje/StekTest.java import net.mindview.util.*; public class StekTest { public static void main(String[] args) { Stek stek = new Stek(); for(String s : "Moeto kuce ima bolvi".split(" ")) stek.push(s); while(!stek.empty()) System.out.print(stek.pop() + " "); } } /* Rezultat: bolvi ima kuce Moeto *///:~

Ako sakate da ja koristite ovaa klasa Stack vo va{iot kod, }e treba kompletno da go odredite paketot- ili da go promenite imeto na klasata, koga ve}e pravite edna. Vo sprotivno, najverojatno }e se sudrite so Stack vo paketot java.util. Na primer, ako uvezeme vo gorniot primer java.util.*, mora da koristime imiwa na paketi so cel da gi spre~ime takvite sudiri: //: cuvanje/SudirNaStekovi.java import net.mindview.util.*; public class SudirNaStekovi { public static void main(String[] args) { net.mindview.util.Stek stek = new net.mindview.util.Stek(); for(String s : "Moeto kuce ima bolvi".split(" ")) stek.push(s); while(!stek.empty()) System.out.print(stek.pop() + " "); System.out.println(); java.util.Stek stek2 = new java.util.Stek();

^uvawe objekti

387

for(String s : " Moeto kuce ima bolvi ".split(" ")) stek2.push(s); while(!stek2.empty()) System.out.print(stek2.pop() + " "); } } /* Rezultat: bolvi ima kuce Moeto bolvi ima kuce Moeto *///:~

Dvete Stack klasi go imaat istiot interfejs, no nema zaedni~ki Stack interfejs vo paketot java.util - verojatno zatoa {to originalnata, lo{o proektiranata klasa java.util.Stack vo Java 1.0 go prisvoila toa ime. Iako java.util.Stack postoi, LinkedList pravi podobar stek, pa treba da se dade prednost na pristapot ostvaren vo paketot net.mindview.ulit.Stack. Izborot na realizacijata na klasata Stack na koja sakate da i dadete prednost mo`ete da ja kontrolirate preku koristeweto na ekspliciten uvoz: import net,mindview.util.Stack;

Sega sekoja referenca na stekot }e ja izbere verzijata net.mindview.util, a za da ja izberete java.util.Stack, }e ,orate da go upotrebite kompletnoto ime koe go opfa}a i imeto na paketot. Ve`ba 15: (4) Stekovite ~esto se koristat za presmetuvawe na izrazi vo programskite jazici. Presmetajte go sledniot izraz koristej}i go paketot net.mindview.util.Stack, kade „+‟ zna~i „vmetni ja slednata bukva vo stekot,” a „„ zna~i “otstranete go vrvot na stekot i ispi{ete go”: ‚+U+n+c---+e+r+t···+a-+i-+n+t+y---+ -+r+u··+I+e+s---‛

Set Edno mno`estvo ne mo`e da sodr`i pove}e od eden primerok za vrednosta na sekoj objekt. Ako se obidete da dodadete pove}e od eden primerok na ekvivalenten objekt, Set }e go spre~i povtoruvaweto. Najvoobi~aena upotreba za eden Set e testiraweto na ~lenstvo, taka {to ednostavno mo`ete da pra{ate dali eden objekt e vo Set ili ne. Kako rezultat na ova, pretra`uvaweto e edna od najva`nite operacii na Set, pa voobi~aeno }e koristite HashSet realizacija, koja e optimizirana za brzo prebaruvawe. Set ima ist interfejs kako Collection, {to zna~i deka nema dodatni funkcii kako {to ima vo dva razli~ni tipovi na List. Namesto toa, mno`estvoto e isto kako kolekcijata, samo se odnesuva razli~no. (Ova e idealnata upotreba na polimorfizmot i nasleduvaweto: da se izrazat razli~ni odnesuvawa). Edno mno`estvo go odreduva ~lenstvoto vrz osnova na „vrednosta” na objektot. Objasnuvaweto za toa od {to se se sostoi vrednosta na objektot e

388

Da se razmisluva vo Java

Brus Ekel

slo`eno, kako {to }e vidite vo poglavjeto Detaqno razgleduvawe kontejneri. Eve primer {to koristi HashSet za celobrojni (Integer) objekti: //: cuvanje/MnozestvoOdCeliBroevi.java import java.util.*; public class MnozestvoOdCeliBroevi { public static void main(String[] args) { Random slucaen = new Random(47); Set mnozestvoodcelibroevi = new HashSet(); for(int i = 0; i < 10000; i++) mnozestvoodcelibroevi.add(slucaen.nextInt(30)); System.out.println(setOdCB); } } /* Rezultat: [15, 8, 23, 16, 7, 22, 9, 21, 6, 1, 29, 14, 24, 4, 19, 26, 11, 18, 3, 12, 27, 17, 2, 13, 28, 20, 25, 10, 5, 0] *///:~

Vo mno`estvoto se dodadeni deset iljadi slu~ajni broevi pome|u 0 i 29, pa mo`ete da zamislite deka sekoj od tie broevi ima mnogu povtoruvawa. I sepak, mo`ete da zabele`ite deka vo rezultatot se pojavuva samo po eden primerok na sekoja vrednost. Isto taka }e zabele`ite deka broevite vo rezultatot nemaat nekoj smislen redosled. Ova e zatoa {to HashSet za pogolema brzina koristi transformirawe na klu~ot (angliski- hashing) - ova e objasneto vo poglavjeto Detaqno razgleduvawe na kontejnerite. Redosledot koj go odr`uva HashSet se razlikuva od redosledot vo TreeSet ili LinkedHashSet, bidej}i sekoja realizacija gi skladira elementite na razli~en na~in. TreeSet gi ~uva elementite sortirani vo crveno-crna struktura na steblo, dodeka HashSet primenuva transformacija na klu~ot. LinkedHashSet isto taka koristi transformacija na klu~ot zaradi pobrzo prebaruvawe, no naizgled so pomo{ na povrzana lista gi odr`uva elementite vo redosled na vmetnuvawe. Ako sakate rezultatite da bidat podredeni, eden na~in e da koristite TreeSet namesto HashSet: //: holding/UredenoMnozestvoOdCeliBroevi.java import java.util.*; public class UredenoMnozestvoOdCeliBroevi { public static void main(String[] args) { Random slucaen = new Random(47); SortedSet mnozestvocelibroevi = new TreeSet(); for(int i = 0; i < 10000; i++) mnozestvocelibroevi.add(slucaen.nextInt(30)); System.out.println(intset); }

^uvawe objekti

389

} /* Rezultat: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29] *///:~

Edna od naj~estite operacii {to }e gi izveduvate e test za pripadnost na mno`estvo koristej}i go metodot contains(), no postojat i operacii {to }e ve potsetuvaat na Venovite dijagrami koi najverojatno ste gi u~ele vo osnovno u~ili{te: //: cuvanje/OperaciiSoMnozestva.java import java.util.*; import static net.mindview.util.Print.*; public class OperaciiSoMnozestva { public static void main(String[] args) { Set set1 = new HashSet(); Collections.addAll(set1, "A B C D E F G H I J K L".split(" ")); mnozestvo1.add("M"); print("H: " + mnozestvo 1.contains("H")); print("N: " + mnozestvo 1.contains("N")); Set set2 = new HashSet(); Collections.addAll(mnozestvo 2, "H I J K L".split(" ")); print("mnozestvo 2 vo mnozestvo 1: " + mnozestvo 1.containsAll(mnozestvo 2)); mnozestvo 1.remove("H"); print("set1: " + set1); print("mnozestvo 2 vo mnozestvo 1: " + mnozestvo 1.containsAll(mnozestvo 2)); mnozestvo 1.removeAll(mnozestvo 2); print("mnozestvo 2 otstraneto od mnozestvo 1: " + set1); Collections.addAll(set1, "X Y Z".split(" ")); print("'X Y Z' dodaden na mnozestvo 1: " + mnozestvo 1); } } /* Rezultat: H: true N: false mnozestvo2 vo mnozestvo1: true mnozestvo1: [D, K, C, B, L, G, I, M, A, F, J, E] mnozestvo2 vo mnozestvo1: false mnozestvo2 otstranet from mnozestvo1: [D, C, B, G, M, A, F, E] 'X Y Z' dodaden na mnozestvo1: [Z, D, C, B, G, M, A, F, Y, X, E] *///:~

Imiwata na metodot }e gi razberat lesno onie koi razbiraat angliski. Ima u{te nekolku od niv i niv }e gi najdete vo dokumentacijata JDK. Proizveduvaweto lista od edinstveni elementi mo`e da bide sosema korisna. Na primer, da pretpostavime deka sakate da gi ispi{ete site zborovi vo datotekata OperaciiSoMnozestva.java. Za otvorawe i v~ituvawe na

390

Da se razmisluva vo Java

Brus Ekel

datotekata vo Mnozestvo }e ja upotrebime uslu`nata programa net.mindview.TextFile (koja }e ja pretstasvime vo prodol`enieto na knigata) //: cuvanje/EdinstveniZborovi.java import java.util.*; import net.mindview.util.*; public class EdinstveniZborovi { public static void main(String[] args) { Set zborovi = new TreeSet( new TextFile("OperaciiSoMnozestva.java", "\\W+")); System.out.println(zborovi); } } /* Rezultat: [A, B, C, Collections, D, E, F, G, H, HashSet, I, J, K, L, M, N, Rezultat, Ispisuvanje, Mnozestvo, OperaciiSoMnozestva, String, X, Y, Z, add, addAll, added, args, class, contains, containsAll, false, od, cuvanje, import, in, java, main, mindview, net, new, print, public, remove, removeAll, otstranet, mnozestvo1, mnozestvo 2, split, static, to, true, util, void] *///:~

TextFile e nasleden od klasata List. Konstruktorot TextFile ja otvara datotekata i ja razlo`uva na zborovi koi se vo sklad so pravilniot izraz \W+, koj zna~i „edna ili pove}e bukvi” (pravilnite izrazi se pretstaveni vo poglavjeto Stringovi). Rezultatot se predava na konstruktorot TreeSet, koj si ja dodava sodr`inata na List na sebe. Bidej}i se raboti zaTreeSet, rezultatot e podreden. Vo ovoj slu~aj, podreduvaweto se vr{i leksikografski taka {to malite i golemite bukvi se vo oddelni grupi. Ako sakate alfabetsko podreduvawe, na konstruktorot na mno`estvoto TreeSet mo`ete da mu go prosledite komparatorot String.CASE_INSENSITIVE_ORDER Comparator (komparator e objekt {to vospostavuva redosled). //: cuvanje/EdinstveniZboroviAbecedno.java // Abecedno ispisuvanje.. import java.util.*; import net.mindview.util.*; public class EdinstveniZboroviAbecedno{ public static void main(String[] args) { Set zborovi = new TreeSet(String.CASE_INSENSITIVE_ORDER); zborovi.addAll( new TextFile("OperaciiSoMnozestva.java", "\\W+")); System.out.println(zborovi); } } /* Rezultat: [A, add, addAll, added, args, B, C, class, Collections, contains, containsAll, D, E, F, false, from, G, H, HashSet, cuvanje, I, import, in, J, java, K, L, M, main, mindview, N, net, new, Rezultat, Print, public, remove,

^uvawe objekti

391

removeAll, otstranet, Set, mnozestvo1, mnozestvo 2, OperaciiSoMnozestva, split, static, String, to, true, util, void, X, Y, Z] *///:~

Komparatorite }e gi u~ite detaqno vo poglavjeto Nizi. Ve`ba 16: (5) Napravete mno`estvo od samoglaski. Promenete ja programata EdinstveniZborovi.java taka da prebrojuva i da ispi{uva broevi na samoglaski vo sekoj vlezen zbor, kako i vkupniot broj na samoglaski vo vleznata datoteka.

Mapa Mapiraweto (preslikuvaweto) na edni objekti na drugi mo`e da bide isklu~itelno mo}en na~in za re{avawe na programerski problemi. Na primer, da razgledame programa koja treba da ja ispita slu~ajnosta na broevite od Javinata klasa Random. Vo idealen slu~aj, Random bi dala sovr{ena raspredelba na broevi, no za da go testirate ova treba da generirate pove}e slu~ajni broevi i da gi izbroite onie koi {to pripa|aat na razli~ni opsezi. Mapa lesno go re{ava ovoj problem; vo ovoj slu~aj, klu~ot e brojot koj go proizveduva klasata Random, a vrednosta e brojot na pojavuvawa na toj broj: //: cuvanje/StatistickiPodatoci.java // Ednostaven prikaz na rabotata na HashMap. import java.util.*; public class StatistickiPodatoci { public static void main(String[] args) { Random slucaen = new Random(47); Map m = new HashMap(); for(int i = 0; i < 10000; i++) { // Pravenje na broj pomegju 0 i 20: int r = slucaen.nextInt(20); Integer frekvencija = m.get(r); m.put(r, frekvencija == null ? 1 : frekvencija + 1); } System.out.println(m); } } /* Rezultat: {15=497, 4=481, 19=464, 8=468, 11=531, 16=533, 18=478, 3=508, 7=471, 12=521, 17=509, 2=489, 13=506, 9=549, 6=519, 1=502, 14=477, 10=513, 5=503, 0=481} *///:~

Vo metodot main(), avtomatskoto pakuvawe go pretvora slu~ajno generiraniot int vo referenca na objekt od tipot Integer koja mo`e da se stavi vo mapa od tipot HashMap. (Vo kontejnerot ne mo`ete da stavite vrednost na prost tip, tuku samo referenca na objekt). Metodot get() vra}a vrednost null ako klu~ot ne e ve}e vo kontejnerot ({to zna~i deka toj broj 392

Da se razmisluva vo Java

Brus Ekel

bil prv pat pronajden). Vo sprotivno, metodot get() ja proizveduva pridru`enata Integer vrednost za klu~ot, koja se zgolemuva za eden (povtorno, avtomatskoto pakuvawe go uprostuva izrazot, no vsu{nost se izvr{uva pretvorawe vo Integer i od nego). Eve primer {to dozvoluva koristewe na String opis za pronao|awe na Pet objekti. Isto taka poka`ano e kako so metodi containsKey() i containsValue() mo`ete da ispitate dali Map sodr`i odreden klu~, odnosno vrednost: //: cuvanje/MapaNaMilenici.java import typeinfo.pets.*; import java.util.*; import static net.mindview.util.Print.*; public class MapaNaPets { public static void main(String[] args) { Map mapanamilenici = new HashMap(); mapanamilenici.put("Moja Macka", new Cat("Mimi")); mapanamilenici.put("Moe kuce", new Mutt("Sharko")); mapanamilenici.put("Moj hrcak", new Hamster("Sivko")); print(mapanamilenici); Pet kuce = mapanamilenici.get("Moe kuce"); print(kuce); print(mapanamilenici.containsKey("Moe kuce")); print(mapanamilenici.containsValue(kuce)); } } /* Rezultat: {Moja Macka=Cat Mimi, Moj hrcak=Hamster Sivko, Moe kuce=Dog Sharko} Dog Sharko true true *///:~

Mapite, isto kako i nizite i kolekciite, mo`at lesno da se pro{irat na pove}e dimenzii: ednostavno pravite Mapa ~ii vrednosti se na druga Mapa(a vrednostite na tie Mapi mo`e da bidat drugi kontejneri, pa duri i drugi Mapi). Zna~i, mo}nite strukturi na podatoci se pravat mnogu brzo i lesno, so pomo{ na kombinirawe na kontejneri. Na primer, da pretpostavime deka programata treba da sledi li~nosti koi imaat pove}e doma{ni milenicisamo vi treba Map: //: cuvanje/MapaLista.java package cuvanje; import typeinfo.pets.*; import java.util.*; import static net.mindview.util.Print.*; public class MapaLista { public static Map Dr. Bunsen Honeydew Gonzo The Great Phillip J. Fry *///:~

XOM metodite se jasni sami po sebe, a mo`at da se najdat vo XOM dokumentacijata. XOM sodr`i i klasa Serializer koja vo metodot format( ) e upotrebena za pretvorawe na XML vo po~itliv oblik. Ako samo go povikate toXML( ), }e dobiete se nafrleno, pa Serializer e pogodna alatka. I deserijaliziraweto objekti od tip Licnost od XML datoteka e ednostavno: //: xml/Lugje.java // {Bara: nu.xom.Node; Morate da instalirate // XOM biblioteka od http://www.xom.nu } // {RunFirst: Licnost} import nu.xom.*; import java.util.*; public class Lugje extends ArrayList { public Lugje(String imeNaDatoteka) throws Exception { Document doc = new Builder().build(imeNaDatoteka); Elements elementi = doc.getRootElement().getChildElements(); for(int i = 0; i < elementi.size(); i++)

936

Da se razmisluva vo Java

Brus Ekel

add(new Licnost(elementi.get(i))); } public static void main(String[] args) throws Exception { Lugje p = new Lugje("Lugje.xml"); System.out.println(p); } } /* Ispisuvanje: [Dr. Bunsen Honeydew, Gonzo The Great, Phillip J. Fry] *///:~

Konstruktorot na klasata Lugje otvora i ~ita datoteka so metodot Builder.build( ) na XOM, a metodot getChildElements( ) proizveduva lista Elements (toa ne e standardna lista na Java, tuku objekt koj gi ima samo metodite size( ) i get( ) - Harold ne saka{e da gi natera korisnicite da koristat Java SE5, no sepak saka{e da ima kontejner koj ovozmo`uva bezbedna rabota so tipovi). Sekoj Element od taa lista pretstavuva objekt od tip Licnost, pa se predava na drugiot konstruktor na klasata Licnost. Vodete smetka za toa deka morate odnapred da ja znaete strukturata na svojata XML datoteka, no ba{ toa e ~est slu~aj vo ovoj vid na problem. Aka taa struktura ne odgovara na ona {to go o~ekuvate, XOM }e generira isklu~ok. Sekako deka mo`ete da napi{ete i poslo`en kod koj }e go ispita XTM dokumentot namesto bilo {to da pretpostavuva za nego, vo slu~aite koga imate pomalku konkretni informacii za dojdovnata XML struktura. Za ovie primeri da mo`at da se prevedat, }e morate da gi stavite JAR datotekite od XOM distribucijata vo va{ata pateka na klasa. Ova be{e samo kratok voved vo XML programiraweto na Java i so bibliotekata XOM; pove}e informacii pobarajte na www.xom.nu. Ve`ba 31: (2) Na programite Licnost.java i Lugje.java dodajte soodveti informacii za adresata. Ve`ba 32: (4) Koristej}i ja Map i uslu`nata klasa net.mindview.util.TextFile, napi{ete programa koja gi prebrojuva zborovite vo datotekata (kako vtor argument vo konstruktorot na klasata TextFile upotrebete „\\W+“). Rezultatite za~uvajte gi vo oblik na XML datoteka.

Preferences Interfejsot za programirawe aplikacii (API) Preferences e mnogu poblizok do konceptot na trajnost otkolku {to e do serijalizacijata na objekti, zatoa {to informaciite avtomatski gi skladira i vadi od skladi{teto. Me|utoa, mo`e da se primenuva samo na odredeni mali mno`estva na podatoci – na prosti tipovi i znakovni nizi (Strings), a sekoja skladirana znakovna niza ne smee da bide podolga od 8 K (i ne e ba{ mnogu malku, no ne e za seriozna rabota). Kako {to ka`uva imeto, API Preferences slu`i za skladirawe i

Vlezno-izlezen sistem vo Java

937

vadewe parametri koi gi odbral konfiguracijata na programata.

korisnikot

i

postavkite

na

Po`elnite parametri i postavkite se smestuvaat vo mno`estva klu~vrednost (kako mapite), skladirani vo hierarhija na jazli. Iako vo hierarhijata na jazli mo`at da se napravat slo`eni strukturi, obi~no se pravi samo eden jazol nare~en po klasata za koja informaciite se skladiraat vo nego. Eve ednostaven primer: //: vi/PrimerZaPreferences.java import java.util.prefs.*; import static net.mindview.util.Print.*; public class PrimerZaPreferences { public static void main(String[] args) throws Exception { Preferences prefs = Preferences .userNodeForPackage(PrimerZaPreferences.class); prefs.put("Mesto", "Oz"); prefs.put("Obuvki", "Crveni vlecki"); prefs.putInt("Drugari", 4); prefs.putBoolean("Dali ima vesterki?", true); int brojNaUpotrebi = prefs.getInt("UsageCount", 0); brojNaUpotrebi++; prefs.putInt("UsageCount", brojNaUpotrebi); for(String kluc : prefs.keys()) print(kluc + ": "+ prefs.get(kluc, null)); // Sekogas morate da zadadete podrazbirana vrednost: print("Kolku drugari ima Doroti? " + prefs.getInt("Drugari", 0)); } } /* Ispisuvanje: (Primer) Mesto: Oz Obuvki: Crveni vlecki Drugari: 4 Dali ima vesterki?: true UsageCount: 53 Kolku drugari ima Doroti? 4 *///:~

Tuka e upotreben metodot userNodeForPackage( ), a mo`ev da go odberam i systemNodeForPackage( ); izborot donekade e proizvolen, no idejata e „user“ da se upotrebuva za po`elni parametri i postavki na poedine~ni korisnici, a „system“ za konfiguracijata na celata instalacija. Bidej}i metodot main( ) e stati~ki, za identifikacija na jazolot e upotrebena klasata PrimerZaPreferences.class, no vnatre vo nestati~kiot metod obi~no se koristi getClass( ). Kako identifikator na jazolot ne morate da ja koristite tekovnata klasa, no toa e voobi~aena praksa. Otkako }e go napravite jazolot, toj Vi e na raspolagawe za vpi{uvawe ili ~itawe podatoci. Vo prethodniot primer vo jazolot se vpi{ani razli~ni

938

Da se razmisluva vo Java

Brus Ekel

vidovi stavki, a potoa e povikan metodot keys( ). Negov rezultat se klu~evi (angl. keys) vo oblik na znakovna niza (String[ ]), {to poznava~ite na istoimeniot metod od bibliotekata na kolekcii ne bi o~ekuvale. Obratete vnimanie na vtoriot argument na metodot get( ). Ova e podrazbiranata vrednost koja se vra}a kako rezultat dokolku vrednosta za dadeniot klu~ ne se najde. Vo tekot na iteracija niz mno`estvo klu~evi sekoga{ znaete deka nekoja stavka postoi, pa koristewe na null kako podrazbirana vrednost e bezbedno. Obi~no bi zemale nekoj imenuvan klu~, kako vo: prefs.getInt(‚Drugari‛,0));

Vo normalen slu~aj treba da zadadete razumna podrazbirana vrednost. Vsu{nost, ova e eden tipi~en idiom: int brojNaUpotrebi = prefs.getInt(‚UsageCount‛,0); brojNaUpotrebi++; prefs.putInt‛UsageCount‛, brojNaUpotrebi);

Na toj na~in, UsageCount }e bide nula koga prv pat }e ja startuvate programata, no vo drugite startuvawa }e bide razli~en od nula. Koga }e ja startuvate PrimerZaPreferences.java, }e vidite deka UsageCount navistina se zgolemuva za eden sekojpat koga }e se startuva programata. No kade se ~uva toj broj? Nema lokalna datoteka koja bi se pojavila po prvoto startuvawe na programata. API Preferences za da ja zavr{i ovaa rabota koristi soodvetni sistemski resursi, a tie se menuvaat vo zavisnost od operativniot sistem. Vo Windows za toa se upotrebuva registar (bidej}i toj i taka e hierarhija na jazli so parovi klu~-vrednost). Celata poenta e informaciite avtomatski da se skladiraat, a nie da ne morame da se gri`ime za kako toa se pravi vo koj bilo poedine~en sistem. No ima u{te mnogu raboti da se ka`at za Preferences API od ova tuka. Za pove}e detali, razgledajte ja JDK dokumentacijata koja e dovolno razbirliva. Ve`ba 33: (2) Napi{ete programa koja ja prika`uva momentalnata vrednost na imenik nare~en Âosnoven imenik° i vedna{ ve izvestuva ako ima nova vrednost. Koristete Preferences API za za~uvuvawe na vrednosta.

Rezime V/I bibliotekata so tekovi na Java gi zadovoluva osnovnite pobaruvawa: mo`ete da ~itate i pi{uvate preku konzola, datoteka, memoriski blok ili duri preku Internet. So nasleduvaweto mo`ete da kreirate novi tipovi na vlezni i izlezni objekti. Duri mo`ete i da dodavate ednostavna pro{irlivost na onie objekti koi }e gi prifati nekoj tek, so redefinirawe na metodot toString( ) koj e avtomatski povikan koga }e prosledite objekt na metod koj o~ekuva znakovna niza (String) (Ograni~enata Âavtomatska konverzija na tip° na Java).

Vlezno-izlezen sistem vo Java

939

Ima pra{awa koi ostanuvaat neodgovoreni od dokumentacijata i dizajnot na V/I bibliotekata za tekovi. Na primer, }e be{e ubavo da mo`evte da re~ete deka sakate da se isfrli isklu~ok ako se obidete da prezapi{ete ne{to vo datotekata koga ja otvorate za izlez - nekoi sistemi za programirawe vi dozvoluvaat da specifirate deka sakate da otvorite izlezna datoteka, no samo ako taa ve}e ne postoi. Vo Java, izgleda deka treba da koristite objekt od tip File za da doznaete dali ve}e postoi takva datoteka, bidej}i ako ja otvorite kako FileOutputStream ili FileWriter, sekoga{ }e bide prezapi{ana. V/I bibliotekata za tekovi predizvikuva izme{ani ~uvstva; zavr{uva mnogu od rabotata i e prenosna. No ako ve}e ne go razbirate obrazecot na dizajnot na Decorator, dizajnot ne e intuitiven, pa ima dopolnitelni re`iski tro{oci za da nau~i i predava. Isto taka e nepotpolna; na primer, ne bi trebalo da pi{uvam uslu`ni programi kako TextFile (noviot Java SE5 PrintWriter e ~ekor vo pravilna nasoka, no e samo delumno re{enie). Ima{e golemo podobruvawe vo Java SE5: Kone~no be{e dodaden vidot na format za izlezniot rezultat koj prakti~no site drugi jazici otsekoga{ go poddr`uvale. Koga }e go razberete obrazecot na Decorator i koga }e po~nete da ja koristite bibliotekata vo situacii koi ja pobaruvaat nejzinata fleksibilnost, ovoj dizajn }e po~ne da vi koristi, i toga{ cenata na dopolnitelni redovi na kod nema tolku da Vi pre~i. Re{enijata na izbranite ve`bi dadeni se dadeni vo elektronskiot dokument The Thinking in Java Annotaded Solution Guide, koj mo`e da se kupi na adresata www.MindView.net.

940

Da se razmisluva vo Java

Brus Ekel

Nabroeni tipovi Rezerviraniot zbor enum slu`i za pravewe nov tip od ograni~en zbir imenuvani vrednosti; poradi t oj zbor tie vrednosti se tretiraat kako ramnopravni komponenti na programata.62 Nаброените типови накусо ги претставивме во поглавјето Inicijalizacija i ~istewe. Меѓутоа, бидејќи сега разбирате и некои покомплицирани области во Java, можеме подетаqно да ги разгледаме наброените типови (англ. enumerated types) во Java SE5. Ќе видите дека со наброените типови може да се направи и по нешто занимливо, но ова поглавје би требало да ви пружи и подобар увид во другите можности на јазикот кои до сега ги запознавте, како што се генеричките типови и рефлексијата. Ќе научите и уште неколку проектни обрасци.

Osnovni mo`nosti na nabroenite tipovi Kako {to be{e re~eno vo poglavjeto Inicijalizacija i ~istewe, niz listata na enum konstantite mo`ete da iterirate so povik na metodot values() na toj nabroen tip. Metodot values() proizveduva niza od enum konstanti vo redosledot na nivnoto deklarirawe; dobienata niza mo`ete (na primer) da ja upotrebite vo jazolot foreach. Koga }e napravite nabroen tip, preveduva~ot proizveduva na nego pridru`ena klasa. Taa avtomatski ja nasleduva klasata java.lang.Enum, {to £ dava odredeni mo`nosti, koi }e gi vidite vo sledniot primer: //: nabroeni/KlasaEnum.java // Moznosti na klasata Enum import static net.mindview.util.Print.*; enum Odmor { MORE, PLANINA, BANJA } public class KlasaEnum { public static void main(String[] args) { for(Odmor o : Odmor.values()) { print(o + " redenbroj: " + о.ordinal()); printnb(o.compareTo(Odmor.PLANINA) + " "); 62

Pri pi{uvawe na ova poglavie mnogu mi pomogna Џошуа Блох.

Nabroeni tipovi

941

printnb(o.equals(Odmor.PLANINA) + " "); print(o == Odmor.PLANINA); print(o.getDeclaringClass()); print(о.name()); print("----------------------"); } // Pravi nabroen tip od znakovnata niza: for(String o : "BANJA PLANINA MORE".split(" ")) { Odmor odm = Enum.valueOf(Odmor.class, o); print(odm); } } } /* Rezultat: MORE redenbroj: 0 -1 false false class Odmor MORE ---------------------PLANINA redenbroj: 1 0 true true class Odmor PLANINA ---------------------BANJA redenbroj: 2 1 false false class Odmor BANJA ---------------------BANJA PLANINA MORE *///:~

Metodot ordinal() proizveduva cel broj koj go poka`uva redosledot na deklarirawe na sekoja enum instanca, po~nuvaj}i od nulata. Enum instancata sekoga{ mo`ete bezbedno da ja sporeduvate so operatorot ==, i metodite equals() i hashCode() stanuvaat avtomatski napraveni. Klasata Enum realizira interfejs Comparable i zatoa ima sopstven metod compareTo(), a relizira i interfejs Serializable(). So povikuvawe na metodot getDeclaringClass() za enum instanca, }e dobiete seopfatna enum klasa. Metodot name() go dava imeto to~no onaka kako {to bilo deklarirano, a istoto toa go dobivate i so metodot toString(). valueOf() e stati~en ~len na klasata Enum i proizveduva enum instanca koja odgovara na znakovnata niza koja i e prosledena ili pravi isklu~ok dokolku takvata niza ne mo`e da se pronajde.

942

Da se razmisluva vo Java

Brus Ekel

Uvoz na stati~ni ~lenovi vo nabroeniot tip Eve edna varijacija na Inicijalizacija i ~istewe.

programata

Pleskavica.java

od

poglavjeto

//: nabroeni/Lutina.java public enum Lutina { NE, BLAGO, SREDNO, MNOGU, GORI } ///:~

//: nabroeni/Pleskavica.java package nabroeni; import static enumerated.Lutina.*; public class Pleskavica { Lutina degree; public Pleskavica(Lutina stepen) { this.stepen = stepen;} public String toString() { return "Pleskavicata e "+ stepen;} public static void main(String[] args) { System.out.println(new Pleskavica(NE)); System.out.println(new Pleskavica(SREDNO); System.out.println(new Pleskavica(MNOGU)); } } /* Rezultat: Pleskavicata e NE Pleskavicata e SREDNO Pleskavicata e MNOGU *///:~

static import gi voveduva site identifikatori na enum instancite vo lokalniot prostor na imiwa, pa zatoa tie ne mora da bidat potpolni (kvalifikuvani). Dali toa e dobro ili e podobro da se bide konkreten i da se navedat potpolnite imiwa na site enum instanci? Toa verojatno zavisi od slo`enosta na kodot. Preveduva~ot sigurno nema da dozvoli da se upotrebi pogre{en tip i zatoa treba da se potrudite kodot da bide razbirliv za ~itatelot. Vo mnogu situacii i nepotpolnite imiwa }e bidat dovolno razbirlivi, no toa mo`e da se prosudi samo od slu~aj do slu~aj. Vodete smetka za toa deka ovaa tehnika ne e mo`no da se koristi ako enum e definiran vo istata datoteka ili vo paket koj se podrazbira. (Kako {to vo kompanijata Sun ima{e razli~ni mislewa za toa даli toa треба da se dozvoli.)

Nabroeni tipovi

943

Dodavawe metodi vo nabroeniot tip Od nabroenite tipovi ne mo`ete da izdvoite novi potklasi , inaku enum bi se tretiral kako obi~na potklasa. Toa zna~i deka mo`ete da mu dodavate metodi. enum duri mo`e da ima svoj metod main() . Vidovte deka metodot toString(), koj se podrazbira, go naveduva samo imeto na enum instancata. Dokolku sakate da dadete drug opis na nabroeniot tip, mo`ete da napravite konstruktor koj }e opfati dopolnitelni informacii i metodi koi }e davaat poobemen opis, kako vo sledniot primer: //: nabroeni/VesticataOdOz.java // Vesticite od Oz. import static net.mindview.util.Print.*; public enum VesticataOdOz { // Prvo morate da gi definirate instancite, pred metodite: ZAPAD("Gospidjicata Galc, poznata i kako losata vestica od zapad"), SEVER("Glinda, dobrata vestica od sever"), ISTOK("Losata vestica od istok, nositel na crvenite " + "papucka, koja ja zdrobila kucata na Doroti"), JUG("Verojatno dobra, no ja nema"); private String opis; // Na konstruktorot mora da mu se pristapuva paketno ili privatno: private VesticataOdOz(String opis) { this.opis = opis; } public String getDescription() { return opis; } public static void main(String[] args) { for(VesticataOdOz vestica : VesticataOdOz.values()) print(vestica + ": " + vestica.getDescription()); } } /* Rezultat: WEST: Gospodjicata Galc, poznata i kako losata vestica od zapad NORTH: Glinda, dobrata vestica od sever EAST: Losata vestica od istok, nositel na crvenite papucki, koja ja smackala kucata na Doroti SOUTH: Verojatno dobra, no ja nema *///:~

Dokolku imate namera da gi definirate metodite, sekvencata od enum instanci morate da ja zavr{ite so znakot to~ka i zapirka. Isto taka, Java prisiluva vo nabroeniot tip (enum) pred sé da gi definirame instancite. Za vreme na preveduvaweto }e napravite gre{ka ako se obidete da gi definirate instancite po nekoi od metodite ili poliwata. Konstruktorot i metodite imaat ist oblik kako vo voobi~aenite klasi, zatoa {to ova i e obi~na klasa so nekolku ograni~uvawa. Zna~i, so nabrojuvawata mo`ete da pravite skoro sé {to }e posakate (iako, verojatno }e se trudite da ostanat prili~no ednostavni). 944

Da se razmisluva vo Java

Brus Ekel

Iako vo prethodniot primer konstruktorot e privaten, nema{e da ima golema razlika i da primenevte nekoj drug pristap - konstruktor mo`e da se upotrebi samo za pravewe enum instanci koi ste gi deklarirale vo sklop na definicijata na nabroeni tipovi; preveduva~ot nema da dozvoli da go upotrebite za pravewe novi instanci po zavr{uvaweto na taa definicija.

Redefinirawe na enum metodite Sleduva opis na drug na~in na proizveduvawe poinakvi znakovni nizi za nabroenite tipovi. Vo ovoj slu~aj, imiwata na instancite se dobri, no sakame da gi preformatirame za prika`uvawe. Redefiniraweto na metodot toString() za enum e isto kako i redefiniraweto za voobi~aena klasa: //: nabroeni/VselenskiBrod.java public enum VselenskiBrod { IZVIDNIK, TOVAREN, TRANSPORTEN, KRSTARECKI, BOENBROD, MATICEN; public String toString() { String id = name(); String mala = id.substring(1).toLowerCase(); return id.charAt(0) + mala; } public static void main(String[] args) { for(VselenskiBrod s : values()) { System.out.println(s); } } } /* Rezultat: Izvidnik Tovaren Transporten Krstarecki Boenbrod Maticen *///:~

Metodot toString() nabavuva ime za klasata VselenskiBrod so povikuvawe na metodot name(), a nejziniot rezultat go menuva taka {to samo prvata bukva e golema.

Nabroeni tipovi vo naredbite switch Osobeno dobro svojstvo na nabroenite tipovi e na~inot na koj tie mo`at da se upotrebat vo naredbite switch. switch obi~no raboti samo so celobrojni vrednosti, no bidej}i nabroenite tipovi imaat utvrden celobroen redosled, a redniot broj na instancata go dava metodot ordinal() (izgleda deka ne{to

Nabroeni tipovi

945

sli~no raboti preveduva~ot), nabroenite tipovi mo`eme da gi upotrebuvame vo naredbite switch. Iako imeto na enum instancata obi~no morate da go nadopolnite so nejziniot tip, toa ne mora da go pravite vo naredbata case. Vo sledniot primer enum e upotreben za pravewe mala ma{ina na sostojbata: //: nabroeni/Semafor.java // Nabroeni tipovi vo naredbite Switch. import static net.mindview.util.Print.*; // Definicija na nabroeniot tip: enum Signal { ZELENO, ZOLTO, CRVENO, } public class Semafor { Signal svetlo = Signal.CRVENO; public void change() { switch(svetlo) { // Obrnete vnimanie na toa deka vo naredbata case // ne morate da pisuvate Signal.CRVENO: case CRVENO: svetlo = Signal.ZELENO; break; case ZELENO: svetlo = Signal.ZOLTO; break; case ZOLTO: svetlo = Signal.CRVENO; break; } } public String toString() { return "Na semaforot e " + svetlo; } public static void main(String[] args) { Semafor s = new Semafor(); for(int i = 0; i < 7; i++) { print(s); s.change(); } } } /* Rezultat: Na semaforot e CRVENO Na semaforot e ZELENO Na semaforot e ZOLTO Na semaforot e CRVENO Na semaforot e ZELENO Na semaforot e ZOLTO Na semaforot e CRVENO *///:~

Preveduva~ot ne se `ali {to vo ramkite na naredbata switch nema naredba default, no ne zatoa {to zabele`al deka za sekoja instanca na klasata Signal imate naredba case. Nema da se `ali nitu vo slu~aj edna od naredbite case da

946

Da se razmisluva vo Java

Brus Ekel

ja pretvorite vo komentar. Zna~i, sami morate da vnimavate na toa da gi definirate site mo`ni slu~ai. Od druga strana, dokolku od naredbata case povikuvate return, preveduva~ot }e se `ali ako nemate default - duri i ako ste gi definirale site mo`ni vrednosti na nabroeniot tip. Ve`ba 1: (2) Izmenete ja Semafor.java so pomo{ na uvoz na stati~ni ~lenovi taka {to ne }e morate da gi naveduvate potpolnite imiwa na enum instancite.

Misterijata na metodot values() Ve}e rekov deka preveduva~ot gi pravi site enum klasi i deka tie ja nasleduvaat klasata Enum. Меѓутоа, od dokumentacijata na klasata Enum se gleda deka taa nema metod values() , iako nie toj metod ja koristevme. Ima li u{te skrieni metodi? ]e napi{eme mala programa koja toa }e go otkrie so pomo{ na refleksija: //: nabroeni/Refleksija.java // Analiza na nabroenite tipovi so pomos na refleksija. import java.lang.reflect.*; import java.util.*; import net.mindview.util.*; import static net.mindview.util.Print.*; enum Istrazi { TUKA, TAMU } public class Refleksija { public static Set analiziraj(Class enumKlasa) { print("----- Analiza na klasata " + enumKlasa + " -----"); print("Interfejsi:"); for(Type t : enumKlasa.getGenericInterfaces()) print(t); print("Natklasa: " + enumKlasa.getSuperclass()); print("Metodi: "); Set metodi = new TreeSet(); for(Method m : enumKlasa.getMethods()) metodi.add(m.getName()); print(metodi); return metodi; } public static void main(String[] args) { Set metodiIstrazi = analiziraj(Istrazi.class); Set enumMetodi = analiziraj(Enum.class); print("Istrazi.containsAll(Enum)? " + metodiIstrazi.containsAll(enumMetodi)); printnb("Istrazi.removeAll(Enum): "); metodiIstrazi.removeAll(enumMetodi); print(metodiIstrazi); // Prevedi go nanazad kodot za enum: OSIzvrsuvanje.komanda("javap Istrazi");

Nabroeni tipovi

947

} } /* Rezultat: ----- Analiza na klasata class Istrazi ----Interfejsi: Natklasa: class java.lang.Enum Metodi: [compareTo, equals, getClass, getDeclaringClass, hashCode, name, notify, notifyAll, ordinal, toString, valueOf, values, wait] ----- Analiza na klasata class java.lang.Enum ----Interfejsi: java.lang.Comparable interface java.io.Serializable Natklasa: class java.lang.Object Metodi: [compareTo, equals, getClass, getDeclaringClass, hashCode, name, notify, notifyAll, ordinal, toString, valueOf, wait] Istrazi.containsAll(Enum)? true Istrazi.removeAll(Enum): [values] Compiled from "Refleksija.java" final class Istrazi extends java.lang.Enum{ public static final Istrazi TUKA; public static final Istrazi TAMU; public static final Istrazi[] values(); public static Istrazi valueOf(java.lang.String); static {}; } *///:~

Zna~i, odgovorot e deka values() e stati~niot metod koj go dodal preveduva~ot. I metodot valuesOf() e dodaden na klasata Istrazi dodeka e praven enum. Toa malku i zbunuva, zatoa {to postoi i metod valuesOf( ) koj e del od klasata Enum, no toj ima dva argumenta, a dodadeniot metod samo eden. Metodot na interfejsot Set ovde e upotreben samo za pronaѓawe ime za metodite, no ne i na nivnite potpisi, pa po povik na Istrazi.removeAll(Enum) preostanuva samo nizata [values]. Od rezultatite gledate deka preveduva~ot klasata Istrazi ja ozna~il so final, pa od nea ne mo`ete da izveduvate potklasi. Tuka e stati~nata odredba za inicijalizacija koja mo`e da se redefinira (}e go poka`am toa podocna). Poradi bri{eweto (opi{ano vo poglavjeto Generi~ki tipovi), dekompajlerot nema polna informacija za nabroeniot tip (Enum), pa poka`uva deka natklasata od Istrazi e surov Enum, namesto vistinskata Enum. Bidej}i values() e stati~en metod koj vo definicijata enum go vmetnal preveduva~ot, ako nekoj od enum tipovite gi svedete pogore na Enum, metodot values() nema da bide dostapen. Меѓутоа, imajte predvid deka vo klasata Class postoi metod getEnumCostants(), pa duri i ako metodot values()

948

Da se razmisluva vo Java

Brus Ekel

ne e del od interfejsot od Enum, enum instancite sepak mo`ete da gi dobiete so pomo{ na objektot Class: //: nabroeni/SveduvanjeNaEnumNagore.java // Koga nabroeniot tip ce se svede nagore, // metodot values() stanuva nedostapen enum Prebaruvanje { OVAMU, ONAMU } public class SveduvanjeNaEnumNagore { public static void main(String[] args) { Prebaruvanje[] vrdns = Prebaruvanje.values(); Enum e = Prebaruvanje.OVAMU; // Sveduvanje nagore // e.values(); // Enum nema metod values() for(Enum en : e.getClass().getEnumConstants()) System.out.println(en); } } /* Rezultat: OVAMU ONAMU *///:~

Bidej}i metodot getEnumCostants(), pripaѓa na klasata Class, mo`ete da go povikate i za klasi koi nemaat nabroeni tipovi: //: nabroeni/NeEEnum.java public class NeEEnum { public static void main(String[] args) { Class intKlasa = Integer.class; try { for(Object en : intKlasa.getEnumConstants()) System.out.println(en); } catch(Exception e) { System.out.println(e); } } } /* Rezultat: java.lang.NullPointerException *///:~

Metodot vra}a null, pa }e dobiete isklu~ok koga }e se obidete da go dobiete nejziniot rezultat.

Realizira, ne nasleduva Rekov deka site nabroeni tipovi se izvedeni od klasata java.lang.Enum. Bidej}i, Java ne podr`uva pove}ekratno nasleduvawe, toa zna~i deka nabroeniot tip ne mo`ete da go napravite preku nasleduvawe: enum NeEMozno extends Pet { … // Ne raboti

Nabroeni tipovi

949

Меѓутоа, mo`no e da se napravi nabroen tip koj realizira eden ili pove}e interfejsi: //: nabroeni/crtani/EnumRealizacija.java // Nabroeniot tip moze da realizira interfejs package nabroeni.crtani; import java.util.*; import net.mindview.util.*; enum LikOdCrtan implements Generator { FUCA, GRDA, TIKVA, BLESA, SKOKA, LUDA, BOBA; private Random slucaen = new Random(47); public LikOdCrtan next() { return values()[slucaen.nextInt(values().length)]; } } public class EnumRealizacija { public static void printNext(Generator gsb) { System.out.print(gsb.next() + ", "); } public static void main(String[] args) { // Izberete bilo koja instanca: LikOdCrtan lic = LikOdCrtan.BOBA; for(int i = 0; i < 10; i++) printNext(lic); } } /* Rezultat: BOBA, TIKVA, BOBA, GRDA, LUDA, TIKVA, FUCA, LUDA, LUDA, FUCA, *///:~

Rezultatot e malku nevoobi~aen, bidej}i morate da ja imate instancata na nabroeniot tip za da mo`ete za nea da povikate metod. Меѓутоа, LikOdCrtan sega mo`e da go prifati sekoj metod koj ja prima Generator, na primer, metodot printNext(). Ve`ba 2: (2) Namesto da realizirate interfejs, napravete next() so stati~en metod. Koi se prednostite i manite na toj pristap?

Slu~aen izbor Vo mnogu primeri vo ova poglavje neophoden e slu~aen izbor na enum instancite, kako {to ve}e vidovte vo metodot LikOdCrtan.next(). Toa mo`e da go voop{time so pomo{ na generi~ki tipovi i rezultatot da go smestime vo zaedni~ka biblioteka: //: net/mindview/util/NabroeniTipovi.java package net.mindview.util;

950

Da se razmisluva vo Java

Brus Ekel

import java.util.*; public class NabroeniTipovi { private static Random slucaen = new Random(47) ; public static T random(Class ec) return random(ec.getEnumConstans() ) ; } public static T random(T[] vrednosti) { return vrednosti[slucaen.nextInt(vrednosti.leght)] ; } } ///:~

{

Prili~no neobi~nata sintaksa go opi{uva T kako instanca na nekoj nabroen tip. Objektot na taa klasa go pravime pristapen taka {to prosleduvame Class, i zatoa mo`e da se napravi niza enum instanci. Preklopeniot metod random() treba da znae samo deka dobiva T[], bidej}i ne mora da pravi Enum operacii; toj samo slu~ajno izbira nekoj element od nizata. Povratniot tip e tokmu toj nabroen tip. Eve ednostavna proverka na random(): //: nabroeni/ProverkaNaMetodotRandom.java import net.mindview.util.*; enum Aktivnost { SEDENJE, LEZENJE, STOENJE, POTSKOKNUVANJE, TRCANJE, IZBEGNUVANJE, SKOKANJE, PAGJANJE, LETANJE } public class ProverkaNaMetodotRandom { public static void main(String[] args) { for(int i = 0; i < 20; i++) System.out.print(NabroeniTipovi.random(Aktivnost.class) + " "); } } /* Rezultat: STOENJE LETANJE TRCANJE STOENJE TRCANJE STOENJE LEZENJE IZBEGNUVANJE SEDENJE TRCANJE POTSKOKNUVANJE POTSKOKNUVANJE POTSKOKNUVANJE TRCANJE STOENJE LEZENJE PAGJANJE TRCANJE LETANJE LEZENJE *///:~

Iako NabroeniTipovi se mala klasa, }e vidite deka so nejzina zasluga vo ova poglavje spre~uvame prili~na koli~ina duplirawe. Dupliraweto ~esto doveduva do gre{ki, taka {to otstranuvaweto na dupliraweto e korisna rabota.

Upotreba na interfejsot za organizirawe Toa {to ne e mo`no da se nasledi nabroen tip ponekoga{ mo`e da pre~i. Nasleduvaweto nabroen tip e potrebno za zgolemuvawe na elementite na prvobitniot nabroen tip i za pravewe podkategorii so pomo{ na podtipovi.

Nabroeni tipovi

951

Kategorizacija mo`ete da ostvarite so grupirawe elementi vnatre vo interfejsot i pravewe nabroen tip po osnov toj interfejs. Na primer, da pretpostavime deka imame razni klasi hrana koi sakate da gi napravite kako nabroeni tipovi, no sepak sakate sekoja od niv da bide nekoj tip izveden od klasata Hrana. Eve kako izgleda toa: //: nabroeni/meni/Hrana.java // Potkategorizacija na nabroenite tipovi vo interfejsot. package nabroeni.meni; public interface Hrana { enum Predjadenje implements Hrana { SALATA, SUPA, PROLETNI_ROLNICKI; } enum GlavnoJadenje implements Hrana { LAZANJI, PLESKAVICA, PAD_THAI, MESUNKI, PILAV, SARMA; } enum Desert implements Hrana { TIRAMISU, SLADOLED, SVARCVALD_TORTA, OVOSJE, KARAMEL_KREM; } enum Kafe implements Hrana { CRNO_KAFE, KAFE_BEZ_KOFEIN, ESPRESSO, KAFE_SO_MLEKO, CAPPUCCINO, CAJ, BILKOV_CAJ; } } ///:~

Bidej}i nabroeniot tip mo`e da ima samo podtipovi napraveni so realizacija na interfejs, sekoj vgnezden enum realizira opfa}aj}i go interfejsot Hrana. Sega mo`eme da ka`eme deka Âsekoe jadewe e nekoj tip od klasata Hrana°, kako {to tuka gledate: //: nabroeni/meni/VidHrana.java package nabroeni.meni; import static nabroeni.meni.Hrana.*; public class VidHrana { public static void main(String[] args) { Hrana hrana = Predjadenje.SALATA; hrana = GlavnoJadenje.LAZANJI; hrana = Desert.SLADOLED; hrana = Kafe.CAPPUCCINO; } } ///:~

Sveduvaweto nagore na klasata Hrana funkcionira za sekoj enum tip koj go realizira interfejsot Hrana, pa site tie se tipovi na klasata Hrana. Меѓутоа, za rabota so zbirot tipovi interfejsot ne e tolku upotrebliv kako {to e enum. Dokolku sakate da imate Ânabroen tip od drugi nabroeni

952

Da se razmisluva vo Java

Brus Ekel

tipovi°, mo`ete da napravite opfaten enum so po edna instanca za sekoj enum vo klasata Hrana. //: nabroeni/meni/VidHrana.java package nabroeni.meni; import net.mindview.util.*; public enum VidHrana { PREDJADENJE(Hrana.Predjadenje.class), GLAVNOJADENJE(Hrana.GlavnoJadenje.class), DESERT(Hrana.Desert.class), KAFE(Hrana.Kafe.class); private Hrana[] vrednosti; private VidJadenje(Class blokiran = exec.submit(new Runnable() { public void run() { try { // Semaforot sprecuva natamosno izdavanje, // pa povikot se blokira: grupa.izdajObjektNaKoristenje(); } catch(InterruptedException e) { print("izdajObjektNaKoristenje() prekinata"); } } }); TimeUnit.SECONDS.sleep(2); blokiran.cancel(true); // Izlezi od blokiraniot povik print("Vracanje na objektot vo " + lista); for(Debeli f : lista) grupa.primiGoObjektotNazadVoGrupata(f); for(Debeli f : lista) grupa. primiGoObjektotNazadVoGrupata(f); // Drugiot primiGoObjektotNazadVoGrupata // go ignoriram exec.shutdown(); } } /* (Startuvajte za da go vidite rezultatot) *///:~

Vo metodot main() se pravi Grupa objekti od tipot Debeli i mno`estvo ZadaciKoiZemaatResurs koj po~nuva da ja upotrebuva. Potoa ni{kata main() po~nuva da zema objekti od tipot Debeli i da gi vra}a nazad. Koga }e gi zeme site objekti od grupata, Semaphore -ot nema da dozvoli natamo{no izdavawe objekti na koristewe. Zatoa se blokira metodot run() na objektot blokiran i po dve sekundi se povikuva metodot cancel() da izleze od toj objekt od tipot Future. Obrnete vnimanie na toa deka Grupa gi ignorira redundantnite vra}awa na objektite. Vo ovoj primer smetav na toa deka klientot na Grupa sekoga{ }e se seti dobrovolno da gi vrati objektite vo grupata, {to e najednostavno re{enie koga funkcionira. Dokolku ne mo`ete da se potprete na toa, knigata Thinking

Paralelno izvr{uvawe

1161

in Patterns (na adresata www.MindView.net) gi sodr`i natamo{nite istra`uvawa na na~inite na upravuvawe dadeni na koristewe na grupata.

Exchanger Exchanger (razmenuva~) e bariera koja ovozmo`uva meѓusebno da se zamenat objektite na dve zada~i. Koga zada~ite }e vlezat vo bariera, sekoja ima po eden objekt, a koga }e izlezat, imaat objekt koj prethodno go imala druga zada~a. Vakvi razmenuva~i obi~no se koristat koga edna zada~a pravi objekti ~ie proizvodstvo e skapo, a druga zada~a gi tro{i; na toj na~in, mo`at da se napravat pove}e objekti koi se tro{at istovremeno. Za da ja upotrebime klasata Exchanger }e napravime zada~i na proizveduva~ i potro{uva~ koi preku generi~kite tipovi i Generator-ot rabotat so site vidovi objekti, i potoa }e gi primenime na klasata Debeli. Klasite RazmenuvacProizveduvac i RazmenuvacPotrosuvac koristat objekti od tipot List za razmena; sekoja od niv sodr`i Exchanger za ovaa lista List. Koga }e go povikate metodot Exchanger.exchange(), toj ja blokira zada~ata dodeka partnerskata zada~a ne go povika svojot metod exchange(). Koga dvete metodi exchange() }e ja zavr{at svojata rabota, listata od tip List }e bide zameneta: //: paralelno/ExchangerPrimer.java import java.util.concurrent.*; import java.util.*; import net.mindview.util.*; class RazmenuvacProizveduvac implements Runnable { private Generator generator; private Exchanger razmenuvac; private List sklad; RazmenuvacProizveduvac(Exchanger rapro, Generator gen, List sklad) { razmenuvac = rapro; generator = gen; this.sklad = sklad; } public void run() { try { while(!Thread.interrupted()) { for(int i = 0; i < ExchangerPrimer.golemina; i++) sklad.add(generator.next()); // Zameni poln za prazen: sklad = razmenuvac.exchange(sklad); } } catch(InterruptedException e) { // Prifatliv nacin na izlez. } }

1162

Da se razmisluva vo Java

Brus Ekel

} class RazmenuvacProizveduvac implements Runnable { private Exchanger razmenuvac; private List sklad; private volatile T vrednost; RazmenuvacProizveduvac(Exchanger rapot, List sklad){ razmenuvac = rapot; this.sklad = sklad; } public void run() { try { while(!Thread.interrupted()) { sklad = razmenuvac.exchange(sklad); for(T x : sklad) { vrednost = x; // Daj mu vrednost na nadvoresniot svet sklad.remove(x); // OK za CopyOnWriteArrayList } } } catch(InterruptedException e) { // Prifatliv nacin na izlez. } System.out.println("Konecna vrednost: " + vrednost); } } public class ExchangerPrimer { static int golemina = 10; static int odlozuvanje = 5; // Sekundi public static void main(String[] args) throws Exception { if(args.length > 0) golemina = new Integer(args[0]); if(args.length > 1) odlozuvanje = new Integer(args[1]); ExecutorService exec = Executors.newCachedThreadPool(); Exchanger xc = new Exchanger(); List listaNaProizveduvacot = new CopyOnWriteArrayList(), listaNaPotrosuvacot = new CopyOnWriteArrayList(); exec.execute(new RazmenuvacProizveduvac(xc, BasicGenerator.create(Debeli.class), listaNaPotrosuvacot)); exec.execute( new RazmenuvacPotrosuvac(xc, listaNaPotrosuvacot)); TimeUnit.SECONDS.sleep(odlozuvanje); exec.shutdownNow(); } } /* Rezultat: (Primer) Konecna vrednost: Debeli id: 29999 *///:~

Vo metodot main() se pravi eden Exchanger kogo go koristat dvete zada~i i dve listi od tipot CopyOnWriteArrayList za razmena. Ovaa varijanta na Paralelno izvr{uvawe

1163

objektot od tipot List go tolerira povikuvaweto na metodot remove() vo tek na minuvaweto niz listata (ne frla ConcurrentModificationException). RazmenuvacProizveduvac ja popolnuva listata, potoa ja zamenuva polnata lista so prazna koja mu ja prosleduva RazmenuvacPotrosuvac. Klasata Exchanger pravi popolnuvaweto na ednata lista i tro{eweto na drugata da mo`at da se odvivaat istovremeno. Ve`ba 34: (1) Izmenete go ExchangerPrimer.java taka {to namesto klasata Debeli }e upotrebite nekoja svoja.

Simulacija Edna od najzanimlivite i najvozbudlivite primeni na paralelnoto izvr{uvawe e praveweto simulacii. Poradi paralelnosta, sekoja komponenta na simulacijata mo`e da bide posebna zada~a, a poradi toa mnogu polesno e da se programira simulacijata. Mnogu video igri i CGI animacii vo filmovite se simulacii, a porano prika`anite programi TrkaNaKonji.java i RasporeduvacNaStaklenik.java mo`at da se smetaat za simulacii.

Simulacija na {alterski slu`benik Ovaa klasi~na simulacija ja pretstavuva sekoja situacija vo koja objektite se pojavuvaat slu~ajno i za ~ija obrabotka - koja ja pravat slu~aen broj opslu`uva~i, e potrebna slu~ajna koli~ina vreme. Mo`eme da napravime simulacija za da presmetame idealen broj opslu`uva~i. Vo ovoj primer, potrebno e na sekoj klient na bankata da mu se posveti opredeleno vreme, a toa e broj vremenski edinici koi slu`benikot mora da gi potro{i na klientot za da go uslu`i. Koli~inata vreme za pru`awe usluga se razlikuva za sekoj klient i }e ja utvrdime slu~ajno. Osven toa, ne znaeme kolku klienti doaѓaat vo sekoj vremenski interval, pa i toa }e go utvrdime slu~ajno. //: paralelno/simulacijaNaSalterskiSluzbenik.java // So pomos na redovi za cekanje i izvrsuvanje so povece niski. // {Args: 5} import java.util.concurrent.*; import java.util.*; // Za objekti nameneti samo za citanje ne e potrebna sinhronizacija: class Klient { private final int vremeNaUsluzuvanje; public Klient(int tm) { vremeNaUsluzuvanje = tm; } public int dajVremeNaUsluzuvanje() { return vremeNaUsluzuvanje; } public String toString() { return "[" + vremeNaUsluzuvanje + "]"; }

1164

Da se razmisluva vo Java

Brus Ekel

} // Nauci redot klienti da se prikaze: class RedKlienti extends ArrayBlockingQueue { public RedKlienti(int najgolemRed) { super(najgolemRed); } public String toString() { if(this.golemina() == 0) return "[Prazen]"; StringBuilder rezultat = new StringBuilder(); for(Klient klient : this) rezultat.append(klient); return rezultat.toString(); } } // Proizvolno dodavanje klienti vo redot: class GeneratorNaKlienti implements Runnable { private RedKlienti klienti; private static Random slucaen = new Random(47); public GeneratorNaKlienti(redKlienti rp) { klienti = rp; } public void run() { try { while(!Thread.interrupted()) { TimeUnit.MILLISECONDS.sleep(slucaen.nextInt(300)); klienti.put(new Klient(slucaen.nextInt(1000))); } } catch(InterruptedException e) { System.out.println("GeneratorotNaKlienti prekinat"); } System.out.println("GeneratorotNaKlienti zavrsuva"); } } class Sluzbenik implements Runnable, Comparable { private static int brojac = 0; private final int id = brojac++; // Broj klienti usluzeni vo ovaa smena: private int usluzeniKlienti = 0; private RedKlienti klienti; private boolean redotKlientiSeUsluzuva = true; public Sluzbenik(RedKlienti rp) { klienti = rp; } public void run() { try { while(!Thread.interrupted()) { Klient klient = klienti.take(); TimeUnit.MILLISECONDS.sleep( klient.dajVremeNaUsluzuvanje());

Paralelno izvr{uvawe

1165

synchronized(this) { usluzeniKlienti++; while(!redotKlientiSeUsluzuva) wait(); } } } catch(InterruptedException e) { System.out.println(this + "prekinat"); } System.out.println(this + "zavrsuva"); } public synchronized void rabotiNestoDrugo() { usluzeniKlienti = 0; redotKlientiSeUsluzuva = false; } public synchronized void usluzuvajGoRedotKlienti() { assert !redotKlientiSeUsluzuva:"vece usluzuvam: " + this; redotKlientiSeUsluzuva = true; notifyAll(); } public String toString() { return "Sluzbenik " + id + " "; } public String shortString() { return "T" + id; } // Upotrebuva prioriteten red za cekanje: public synchronized int compareTo(Sluzbenik drugi) { return usluzeniKlienti < drugi.usluzeniKlienti ? -1 : (usluzeniKlienti == drugi.usluzeniKlienti ? 0 : 1); } } class rakovoditelNaSluzbenicite implements Runnable { private ExecutorService exec; private RedKlienti klienti; private PriorityQueue rabotatSluzbenici = new PriorityQueue(); private Queue sluzbeniciKoiRabotatNestoDrugo = new LinkedList(); private int periodNaPrilagoduvanje; private static Random slucaen = new Random(47); public RakovoditelNaSluzbenicite(ExecutorService e, RedKlienti klienti, int periodNaPrilagoduvanje) { exec = e; this.klienti = klienti; this. periodNaPrilagoduvanje = periodNaPrilagoduvanje; // Pocni so eden sluzbenik: Sluzbenik sluzbenik = new Sluzbenik(klienti); exec.execute(sluzbenik); rabotatSluzbenici.add(sluzbenik); } public void prilagodiGoBrojotSluzbenici() { // Ova e vsusnost upravuvacki sistem. So menuvanje na broevite // ce gi otkriete nestabilnite rabotni tocki

1166

Da se razmisluva vo Java

Brus Ekel

// na upravuvackiot mehanizam. // Ako redot e predolg, dodaj uste eden sluzbenik: if(klienti.size() / rabotatSluzbenici.size() > 2) { //Ako sluzbenicite se na pauza ili rabotat nesto drugo, // vrati eden nazad: if(sluzbeniciKoiRabotatNestoDrugo.size() > 0) { Sluzbenik sluzbenik = sluzbeniciKoiRabotatNestoDrugo.remove(); sluzbenik.usluzuvajGoRedotKlienti(); rabotatSluzbenici.offer(sluzbenik); return; } // Vo sprotivno napravi (vraboti) nov sluzbenik Sluzbenik sluzbenik = new Sluzbenik(klienti); exec.execute(sluzbenik); rabotatSluzbenici.add(sluzbenik); return; } // Ako redot e dovolno kus, trgni eden sluzbenik: if(rabotatSluzbenici.size() > 1 && klienti.size() / rabotatSluzbenici.size() < 2) premestiEdenSluzbenik(); // Ako voopsto nema red, ni treba samo eden sluzbenikr: if(klienti.size() == 0) while(rabotatSluzbenici.size() > 1) premestiEdenSluzbenik(); } // Daj mu na sluzbenikot druga rabota ili prati go na pauza: private void premestiEdenSluzbenikOne() { Sluzbenik sluzbenik= rabotatSluzbenici.poll(); sluzbenik.rabotiNestoDrugo(); sluzbeniciKoiRabotatNestoDrugo.offer(sluzbenik); } public void run() { try { while(!Thread.interrupted()) { TimeUnit.MILLISECONDS.sleep(periodNaPrilagoduvanje); prilagodiGoBrojotSluzbenici(); System.out.print(klienti + " { "); for(Sluzbenik sluzbenik : rabotatSluzbenici) System.out.print(sluzbenik.shortString() + " "); System.out.println("}"); } } catch(InterruptedException e) { System.out.println(this + "prekinat"); } System.out.println(this + "zavrsuva"); } public String toString() { return "RakovoditelNaSluzbenicite "; } } public class SimulacijaNaSalterskiSluzbenik {

Paralelno izvr{uvawe

1167

static final int NAJGOLEM_DOZVOLEN_RED = 50; static final int PERIOD_NA_PRILAGODUVANJE = 1000; public static void main(String[] args) throws Exception { ExecutorService exec = Executors.newCachedThreadPool(); // Ako redot e predolg, klientite ce si otidat: RedKlienti klienti = new RedKlienti(NAJGOLEM_DOZVOLEN_RED); exec.execute(new GeneratorNaKlienti(klienti)); // Rakovoditelot dodava i trgnuva sluzbenici sprema potrebata: exec.execute(new RakovoditelNaSluzbenicite( exec, customers, PERIOD_NA_PRILAGODUVANJE)); if(args.length > 0) // Opcion argument TimeUnit.SECONDS.sleep(new Integer(args[0])); else { System.out.println("Pritisnete 'Enter' ako sakate da go prekinete izvrsuvanjeto na programata"); System.in.read(); } exec.shutdownNow(); } } /* Rezultat: (Primer) [429][200][207] { T0 T1 } [861][258][140][322] { T0 T1 } [575][342][804][826][896][984] { T0 T1 T2 } [984][810][141][12][689][992][976][368][395][354] { T0 T1 T2 T3 } Sluzbenikot 2 prekinat Sluzbenikot 2 zavrsuva Sluzbenikot 1 prekinat Sluzbenikot 1 zavrsuva RakovoditelotNaSluzbenicite prekinat RakovoditelotNaSluzbenicite zavrsuva Sluzbenikot 3 prekinat Sluzbenikot 3 zavrsuva Sluzbenikot 0 prekinat Sluzbenikot 0 zavrsuva GeneratorotNaKlienti prekinat GeneratorotNaKlienti zavrsuva *///:~

Objektite od tipot Klienti se mnogu ednostavni, bidej}i sodr`at samo edno final int pole. Bidej}i tie objekti nikoga{ ne se menuvaat, tie se samo za ~itawe i ne baraat sinhronizacija nitu modifikator volatile. Osven toa, sekoja zada~a Sluzbenik vo sekoj moment trgnuva od vlezniot red samo po eden objekt od tipot Klient i go uslu`uva dodeka ne zavr{i, pa na sekoj objekt od tipot Klient vo sekoj moment i onaka mu pristapuva samo po edna zada~a. RedKlienti kako mu ka`uva imeto, go so~inuvaat klienti koi ~ekaat da gi uslu`i nekoj objekt od tipot Sluzbenik. Toa e samo objekt od tipot ArrayBlockingQueue so metod toString() koj gi ispi{uva rezultatite vo sakaniot oblik.

1168

Da se razmisluva vo Java

Brus Ekel

Na objektot od tipot RedKlienti mu e pridru`en eden GeneratorNaKlienti koj vo slobodni vremenski intervali dodava klienti vo redot. Sluzbenik-ot zema klienti od objektot od tipot RedKlienti i gi obrabotuva eden po eden, pametej}i go brojot klienti koi gi uslu`il vo tek na odredena smena. Mo`e da mu se pora~a da rabotiNestoDrugo koga nema dovolno klienti i usluzuvajGoRedotKlienti koga }e dojdat mnogu klienti. Slu`benikot koj }e bide vraten na opslu`uvawe na vlezniot red go izbira metodot compareTo(), koja go sporeduva brojot uslu`eni klienti za prioritetniot red za ~ekawe (PriorityQueue) da mo`e avtomatski najmalku optovareniot slu`benik da go stavi napred. RakovoditelNaSluzbenici upravuva so site aktivnosti. Toj gi sledi site slu`benici i nadgleduva {to rabotat klientite. Edna od zanimlivostite na ovaa simulacija e obidot za otkrivawe na optimalen broj slu`benici za dadeniot dotek na klienti. Toa mo`ete da go vidite vo metodot prilagodiGoBrojotSluzbenici() koja e upravuva~ki sistem za dodavawe i otstranuvawe slu`benici na stabilen na~in. Site upravuva~ki sistemi moraat da pazat na stabilnosta; ako na promenata reagiraat prebrzo, }e se izgubi stabilnosta, a ako reagiraat presporo, sistemot }e premine vo eden od ekstremite (red klienti so maksimalna dol`ina, a ne rabotat site dostapni slu`benici ili vraboteni se site slu`benici iako nema klienti). Ve`ba 35: (8) Izmenete ja programata SimulacijaNaSalterskiSluzbenik.java taka {to da gi pretstavuva Web klientite koi pra}aat barawa do odreden broj serveri. Treba da se utvrdi optovaruvaweto koe taa grupa serveri mo`e da go sovlada.

Simulacija na restoran Ednostavniot primer Restoran.java prika`an vo prethodniot del od poglavjeto }e go zbogatam vo ovaa simulacija so dodavawe na pove}e komponenti kako {to se objekti od tipot Naracka i DelOdObrok; pokraj toa, povtorno }e gi upotrebam klasite meni od poglavjeto Nabroeni tipovi. ]e ja pretstavam i Java SE5 klasata SynchronousQueue {to e blokira~ki red za ~ekawe na nultiot interen kapacitet, pa sekoj povik na metodot put() mora da ~eka na svoj povik na metodot take() i obratno. Kako koga na nekoj treba da mu predadete nekoj predmet, a nema masa na koja bi mo`ele da go stavite - }e uspeete edinstveno vo slu~aj toa lice da ja podade rakata kon vas i da go zeme predmetot. Vo ovoj primer, SynchronousQueue pretstavuva prostor neposredno pred restoranskiot gostin, za da se naglasi deka vo sekoj moment mo`e da bide poslu`eno samo edno jadewe. Ostanatite klasi i funkcii vo ovoj primer sleduvaat od strukturata na programata Restoran.java ili pretstavuvaat prili~no neposredno preslikuvawe na operacii od prav restoran:

Paralelno izvr{uvawe

1169

//: paralelno/restoran2/RestoranSoRedovi.java // {Args: 5} package concurrency.restoran2; import enumerated.menu.*; import java.util.concurrent.*; import java.util.*; import static net.mindview.util.Print.*; // Ova se dava na kelnerot, koj toa go predava na gotvacot: class Naracka { // (Objekt za prenos na podatoci) private static int brojac = 0; private final int id = brojac++; private final Gostin gostin; private final Kelner kelner; private final Hrana hrana; public Naracka(Gostin gst, Kelner klnr, Hrana h) { gostin = gst; kelner = klnr; hrana = h; } public Hrana item() { return hrana; } public Gostin dajGoGostinot() { return gostin; } public kelner dajGoKelnerot() { return kelner; } public String toString() { return "Naracka: " + id + " stavka: " + hrana + " za: " + gostin + " serviral: " + kelner; } } // Ova se vraca od gotvacot: class DelOdObrokot { private final Naracka naracka; private final Hrana hrana; public DelOdObrokot(Naracka nar, Hrana h) { naracka = nar; hrana = h; } public Naracka dajJaNarackata() { return naracka; } public Hrana dajJaHranata() { return hrana; } public String toString() { return hrana.toString(); } } class Gostin implements Runnable { private static int brojac = 0; private final int id = brojac++; private final Kelner kelner; // Vo sekoj moment moze da primi samo eden del od obrokot: private SynchronousQueue mestoNaMasata = new SynchronousQueue(); public Gostin(Kelner k) { kelner = k; }

1170

Da se razmisluva vo Java

Brus Ekel

public void posluzi(DelOdObrokot delO) throws InterruptedException { // Blokira samo ako gostinot uste // go jade prethodniot del od obrokot: placeSetting.put(delO); } public void run() { for(Jadenje jadenje : Jadenje.values()) { Hrana hrana = jadenje.randomSelection(); try { kelner.primaJaNarackata(this, hrana); // Blokira dodeka jadenjeto ne se posluzi: print(this + "jade " + mestoNaMasata.take()); } catch(InterruptedException e) { print(this + "ceka na " + jadenje + " prekinat"); break; } } print(this + "izel, zaminuva"); } public String toString() { return "Gostin " + id + " "; } } class Kelner implements Runnable { private static int brojac = 0; private final int id = brojac++; private final Restoran restoran; BlockingQueue primeniNaracki = new LinkedBlockingQueue(); public Kelner(Restoran rest) { restoran = rest; } public void primaJaNarackata(Gostin gst, Hrana hrana) { try { // Ne bi trebalo da blokira zatoa sto se raboti za objekt od tipot // LinkedBlockingQueue koj nema ogranicena golemina: restoran.naracki.put(new Naracka(gst, this, hrana); } catch(InterruptedException e) { print(this + " primiJaNarackata prekinata"); } } public void run() { try { while(!Thread.interrupted()) { // Blokira dodeka ne se podgotvi jadenjeto DekOdObrokot delOdObrokot = primeniNaracki.take(); print(this + "primil " + delOdObrokot + " sto mu posluzuva na gostinot " + delOdObrokot.dajJaNarackata().dajGoGostinot()); delOdObrokot.dajJaNarackata().dajGoGostinot().posluzi(delOdObrokot);

Paralelno izvr{uvawe

1171

} } catch(InterruptedException e) { print(this + " prekinat"); } print(this + " ne e vo smenata"); } public String toString() { return "Kelner " + id + " "; } } class Gotvac implements Runnable { private static int brojac = 0; private final int id = brojac++; private final Restoran restoran; private static Random slucaen = new Random(47); public Gotvac(Restoran rest) { restoran = rest; } public void run() { try { while(!Thread.interrupted()) { // Blokira dodeka ne ja dobie narackata: Naracka naracka = restoran.naracki.take(); Hrana naracanaStavka = naracka.item(); // Vreme za podgotovka na narackata: TimeUnit.MILLISECONDS.sleep(slucaen.nextInt(500)); DelOdObrokot delOdObrokot = new DelOdObrokot(naracka, naracanaStavka); naracka.dajGoKelnerot().primeniNaracki.put(delOdObrokot); } } catch(InterruptedException e) { print(this + " prekinat"); } print(this + " ne e vo smenata"); } public String toString() { return "Gotvac " + id + " "; } } class Restoran implements Runnable { private List kelneri = new ArrayList(); private List gotvaci = new ArrayList(); private ExecutorService exec; private static Random slucaen = new Random(47); BlockingQueue naracki = new LinkedBlockingQueue(); public Restoran(ExecutorService e, int nKelneri, int nGotvaci) { exec = e; for(int i = 0; i < nKelneri; i++) { Kelner kelner = new Kelner(this); kelneri.add(kelner); exec.execute(kelner);

1172

Da se razmisluva vo Java

Brus Ekel

} for(int i = 0; i < nGotvaci; i++) { Gotvac gotvac = new Gotvac(this); gotvaci.add(gotvac); exec.execute(gotvac); } } public void run() { try { while(!Thread.interrupted()) { // Dojde nov gostin; dodeli mu Kelner: Kelner klnr = kelneri.get( slucaen.nextInt(kelneri.size())); Gostin g = new Gostin(klnr); exec.execute(c); TimeUnit.MILLISECONDS.sleep(100); } } catch(InterruptedException e) { print("Restoranot prekinat"); } print("Restoranot se zatvora"); } } public class RestoranSoRedovi { public static void main(String[] args) throws Exception { ExecutorService exec = Executors.newCachedThreadPool(); Restoran restoran = new Restoran(exec, 5, 2); exec.execute(restoran); if(args.length > 0) // Opcion argument TimeUnit.SECONDS.sleep(new Integer(args[0])); else { print("Pritisnete 'Enter' ako sakate da go prekinete izvrsuvanjeto na programata"); System.in.read(); } exec.shutdownNow(); } } /* Rezultat: (Primer) Kelnerot 0 primil PROLETNI_ROLNICKI koi gi posluzuva na Gostinot 1 Gostinot 1 jade PROLETNI_ROLNICKI Kelnerot 3 primil PROLETNI_ROLNICKI koi gi posluzuva na Gostinot 0 Gostinot 0 jade PROLETNI_ROLNICKI Kelnerot 0 primil PLESKAVICA koja ja posluzuva na Gostinot 1 Gostinot 1 jade PLESKAVICA Kelnerot 3 primil PROLETNI_ROLNICKI koi gi posluzuva na Gostinot 2 Gostinot 2 Gostinot jade PROLETNI_ROLNICKI Kelnerot 1 primil SUPA koja ja posluzuva na Gostinot 3 Gostinot 3 jade SUPA Kelnerot 3 primil LOVECKA_GOZBA koja ja posluzuva na Gostinot 0 Gostinot 0 jade LOVECKA_GOZBA

Paralelno izvr{uvawe

1173

Kelnerot 0 primil OVOSJE koe go posluzuva na Gostinot 1 ... *///:~

Edna od mnogu va`nite raboti na koi vo ovoj primer treba da obrnete vnimanie e upravuvaweto so slo`enosta taka {to za komunikacija pomeѓu zada~ite se upotrebeni redovi za ~ekawe. Samata taa tehnika prili~no ja poednostavuva postapkata na paralelnoto programirawe taka {to ja invertira kontrolata: zada~ite ne se obra}aat edna na druga neposredno, tuku edni na drugi ispra}aat objekti preku redovite za ~ekawe. Zada~ata koja primila objekt go obrabotuva i go tretira kako poraka, namesto da go podlo`i na poraka. Dokolku se pridr`uvate na toj na~in na rabota, }e imate mnogu pove}e {ansi da pravite robusni paralelni sistemi. Ve`ba 36: (10) Izmenete go RestoranSoRedovi.java taka {to za sekoja masa da postoi po eden objekt od tipot Naracka. Prepravete ja klasata Naracka vo NalogNaNarackata i dodadete klasa Masa so pove}e Gosti na masata.

Raspredelba na rabotata Sledniot primer e simulacija koja opfa}a pove}e koncepti od ova poglavje. Zamislete robotizirana monta`na linija za avtomobili. Sekoj Avtomobil se proizveduva vo pove}e fazi, po~nuvaj}i od praveweto {asija, preku monta`a na motorot, pogonskiot sistem i trkalata. //: paralelno/ProizvodstvoNaAvtomobili.java // Slozen primer na sorabotka na zadacite. import java.util.concurrent.*; import java.util.*; import static net.mindview.util.Print.*; class Avtomobil { private final int id; private boolean motor = false, pogonskiSistem = false, trkala = false; public Avtomobil(int idn) { id = idn; } // Prazen objekt od tipot Avtomobil: public Avtomobil() { id = -1; } public synchronized int dajId() { return id; } public synchronized void dodajMotor() { motor = true; } public synchronized void dodajPogonskiSistem() { pogonskiSistem = true; } public synchronized void dodajTrkala() { trkala = true; } public synchronized String toString() { return "Avtomobil " + id + " [" + " motor: " + motor + " pogonskiSistem: " + pogonskiSistem + " trkala: " + trkala + " ]"; } }

1174

Da se razmisluva vo Java

Brus Ekel

class RedAvtomobili extends LinkedBlockingQueue {} class PravenjeSasija implements Runnable { private RedAvtomobili redAvtomobili; private int brojac = 0; public PravenjeSasija(RedAvtomobili ra) { redAvtomobili = ra; } public void run() { try { while(!Thread.interrupted()) { TimeUnit.MILLISECONDS.sleep(500); // Napravi sasija: Avtomobil a = new Avtomobil(brojac++); print("Objektot od tip PravenjeSasija napraven " + a); // Vmetni vo redot redAvtomobili.put(a); } } catch(InterruptedException e) { print("Prekinato: PravenjetoSasija"); } print("PravenjetoSasija iskluceno"); } } class Monter implements Runnable { private RedAvtomobili redZaSasija, redZaZavrsna; private Avtomobil avtomobil; private CyclicBarrier bariera = new CyclicBarrier(4); private GrupaRoboti grupaRoboti; public Monter(RedAvtomobili ra, RedAvtomobili rzz, GrupaRoboti gr){ redZaSasija = rzs; redZaZavrsna = rzz; grupaRoboti = gr; } public Avtomobil avtomobil() { return avtomobil; } public CyclicBarrier bariera() { return bariera; } public void run() { try { while(!Thread.interrupted()) { // Blokira dodeka ne se napravi sasijata: avtomobil = redZaSasija.take(); // iznajmi pod naem roboti da rabotat: grupaRoboti.iznajmi(RobotZaMotor.class, this); grupaRoboti.iznajmi(RobotZaPogonskisistem.class, this); grupaRoboti.iznajmi(RobotZaTrkala.class, this); bariera.await(); // Dodeka robotite ne zavrsat // Stavi go avtomobilot vo redZaZavrsna za natamosna obrabotka redZaZavrsna.put(avtomobil); } } catch(InterruptedException e) { print("Izleguvam od niskata Monter so pomos na prekin");

Paralelno izvr{uvawe

1175

} catch(BrokenBarrierException e) { // Sakam da dobijam izvrstuvanje za ova throw new RuntimeException(e); } print("Monterot isklucen"); } } class Izvestuvac implements Runnable { private RedAvtomobil redAvtomobil; public Izvestuvac(RedAvtomobil ra) { redAvtomobil = ra; } public void run() { try { while(!Thread.interrupted()) { print(redAvtomobil.take()); } } catch(InterruptedException e) { print("Izleguvam od niskata Izvestuvac so pomos na prekin"); } print("Izvestuvacot isklucen"); } } abstract class Robot implements Runnable { private GrupaRoboti grupa; public Robot(GrupaRoboti g) { grupa = g; } protected Monter monter; public Robot dodeliMonter(Monter monter) { this.monter = monter; return this; } private boolean angaziraj = false; public synchronized void angaziraj() { angaziraj = true; notifyAll(); } // Ovoj del na metodot run() e razlicen za sekoj robot: abstract protected void pruziUsluga(); public void run() { try { iskluciSe(); // Cekaj dodeka ne bides potreben while(!Thread.interrupted()) { pruziUsluga(); monter.bariera().await(); // Sinhronizacija // Ovaa rabota e zavrsena... iskluciSe(); } } catch(InterruptedException e) { print("Izleguvam od niskata " + this + " so pomos na prekin"); } catch(BrokenBarrierException e) { // Sakam da dobijam izvestuvanje za ova

1176

Da se razmisluva vo Java

Brus Ekel

throw new RuntimeException(e); } print(this + " isklucen"); } private synchronized void iskluciSe() throws InterruptedException { angaziraj = false; monter = null; // Otkaci od objektot Monter // Se vracame vo grupata dostapni: grupa.release(this); while(angaziraj == false) // Iskluci se wait(); } public String toString() { return getClass().getName(); } } class RobotZaMotor extends Robot { public RobotZaMotor(GrupaRoboti grupa) { super(grupa); } protected void pruziUsluga() { print(this + " instalira motor"); monter.avtomobil().dodajMotor(); } } class RobotZaPogonskiSistem extends Robot { public RobotZaPogonskiSistem(GrupaRoboti grupa) { super(grupa); } protected void pruziUsluga() { print(this + " instalira PogonskiSistem"); monter().dodajPogonskiSistem(); } } class RobotZaTrkala extends Robot { public RobotZaTrkala(GrupaRoboti grupa) { super(grupa); } protected void pruziUsluga() { print(this + " instalira Trkala"); monter.avtomobil().dodajTrkala(); } } class GrupaRoboti { // (Necujno) sprecuva identicni stavki: private Set grupa = new HashSet(); public synchronized void add(Robot r) { pool.add(r); notifyAll(); } public synchronized void iznajmi(Class FileChooser aplikacii Mindview Inc. Jnlp aplikacija za izbiranje datoteki Pokazuva otvoranje, citanje i vpisuvanje vo tekstualnata datoteka

1282

Da se razmisluva vo Java

Brus Ekel

///:~

Navedenata datoteka za startuvawe }e ja najdete vo datotekata na izvorniot kod na ovaa kniga (mo`e da se prezeme na adresata www.MindView.net) pod imeto izbiranjedatoteki.jnlp (bez prviot i posledniot red), vo istiot imenik kako JAR arhivata. Kako {to gledate, se raboti za datotekata XML so edna oznaka . Taa ima nekolku podelementi, pomalku ili pove}e jasni sami po sebe. Atributot spec na elementot jnlp mu soop{tuva na klientskiot sistem koja verzija JNLP mo`e da ja startuva aplikacijata. Atributot codebase poka`uva na URL adresata na koja se resursite i datotekite za startuvawe. Tuka poka`uva na imenikot na lokalniot kompjuter, {to e dobar na~in za testirawe na ovaa aplikacija. Se nadevam deka sfa}ate deka taa pateka morate da ja promenite taka {to da poka`uva na soodveten direktoruim na va{iot kompjuter - duri toga{ programata }e se v~ita. Atributot href go specificira imeto na datotekata koja treba da se v~ita. Oznakata information ima razni podelementi koi pru`aat informacii za aplikacijata. Niv gi ~ita administrativnata konzola Java Web Start ili druga na nea ekvivalentna realizacija na JNLP koja ja instalira JNLP aplikacijata i mu ovozmo`uva na korisnikot da ja startuva od komandnata linija, da pravi kratenki itn. Celta na oznakata resources e sli~na na celta na oznakata vo datotekata HTML. Podelementot j2se ja specificira verzijata J2SE potrebna za startuvawe na aplikacijata, a podelementot jar JAR datotekata vo koja klasata e arhivirana. Elementot jar ima atribut download ~ii vrednosti eager odnosno lazy i ka`uvaat na realizacijata na JNLP dali pred startuvaweto na aplikacijata mora da ja v~ita celata arhiva ili ne mora. Atributot application-desc i soop{tuva na realizacijata na JNLP koja klasa e izvr{na klasa (vlezna to~ka) na JAR arhivata. Drug korisen podelement na oznakata jnlp e oznakata security koja vo gornata datoteka ja nema. Eve kako izgleda oznakata security:

Grafi~ki korisni~ki opkru`uvawa

1283



Oznakata security treba da ja imaat aplikaciite vo potpi{anite JAR arhivi. Vo prethodniot primer ne e potrebna zatoa {to na site lokalni resursi im se pristapuva so pomo{ na JNLP uslugite. Poedinostite za ostanatite oznaki pobarajte gi vo specifikacijata na adresa http://java.sun.com/products/javawebstart/dowload-spec.html. Za startuvawe na programata potrebna e stranica za prezemawe koja sodr`i hipertekstualna vrska so .jnlp datotekata. Eve kako taa izgleda (bez prviot i posledniot red): //:! gui/jnlp/izbiranjedatoteki.html Sledete gi upatstvata od JnlpIzbiranjeDatoteki.java za pravenje jnlpfilechooser.jar, a potoa: pritisnete tuka ///:~

Otkako }e ja prezemete aplikacijata, mo`ete da ja konfigurirate so pomo{ na administrativnata konzola. Ako Java Web Start ja koristite vo Windows, pri vtorata upotreba }e mo`ete da napravite kratenka do aplikacijata. Toa odnesuvawe mo`e da se konfigurira. Tuka opi{av samo dve JNLP uslugi, a vo tekovnoto izdanie gi ima sedum. So sekoja od niv se izvr{uva odredena zada~a, kako {to e pe~atewe ili se~ewe i prenesuvawe na clipboard. Pove}e za toa pobarajte na adresata http://java.sun.com.

Paralelnoto izvr{uvawe i Swing Koga programirate vo Swing, rabotite so ni{ki. Toa go vidovte na po~etokot na ova poglavje koga doznavte deka site zada~i treba da se startuvaat so metodot SwingUtilities.invokeLater() na Swing-oviot rasporeduva~. Meѓutoa, faktot {to ne morate eksplicitno da pravite ni{ki (objekti od klasata Thread) zna~i deka problemi so ni{kite mo`at da ve snajdat koga ne se nadevate. Vodete smetka za toa deka ni{kata na Swing-oviot rasporeduva~ sekoga{ postoi i deka site Swing nastani gi obrabotuva vadej}i gi od redot za ~ekawe i izvr{uvaj}i gi edna po edna. Dokolku ne zaboravite na ni{kata na rasporeduva~ot, pomali se {ansite va{ata aplikacija da padne vo zaemna blokada ili uslov za trka. Vo sledniot oddel }e gi razgledame oblastite na izvr{uvaweto so pove}e ni{ki na koi treba da se obrne vnimanie pri rabotata vo Swing.

1284

Da se razmisluva vo Java

Brus Ekel

Dolgotrajni zada~i Edna od osnovnite gre{ki pri programiraweto grafi~ki korisni~ki opkru`uvawa e upotrebata rasporeduva~ za izvr{uvawe na dolgotrajna zada~a. Sleduva ednostaven primer: //: gui/DolgotrajnaZadaca.java // Loso proektirana programa. import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.util.concurrent.*; import static net.mindview.util.SwingKonzola.*; public class DolgotrajnaZadaca extends JFrame { private JButton k1 = new JButton("Startuvaj dolgotrajna zadaca"), k2 = new JButton("Otkazi ja dolgotrajnata zadaca"); public DolgotrajnaZadaca() { b1.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { try { TimeUnit.SECONDS.sleep(3); } catch(InterruptedException e) { System.out.println("Zadacata prekinata"); return; } System.out.println("Zadacata zavrsena"); } }); k2.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { // Da se prekinam? Thread.currentThread().interrupt(); } }); setLayout(new FlowLayout()); add(k1); add(k2); } public static void main(String[] args) { run(new Dolgotrajna zadaca(), 200, 150); } } ///:~

Koga }e go pritisnete k1, ni{kata na rasporeduva~ot po~nuva da ja izvr{uva dolgotrajnata zada~a. ]e vidite deka i toa kop~e nema da stigne da se vrati od pritisnatata polo`ba, bidej}i ni{kata na rasporeduva~ot, koja inaku bi go osve`ila ekranot, e zazemena celi 3 sekundi. A i ni{to drugo ne mo`ete da napravite, npr. da go pritisnete k2, bidej}i programata ne odgovara

Grafi~ki korisni~ki opkru`uvawa

1285

dodeka zada~ata na kop~eto k1 ne zavr{i i ni{kata na rasporeduva~ot povtorno ne stane dostapna. Kodot vo k2 e pogre{en obid problemot da se re{i so prekinuvawe na ni{kata na rasporeduva~ot. Sekako, re{enie e dolgotrajnite procesi da se izvr{uvaat vo posebni ni{ki. Sega }e upotrebime rasporeduva~ od edna ni{ka (Executor) koj povikuvanite zada~i avtomatski gi vmetnuva vo redot za ~ekawe, gi vadi od redot i gi izvr{uva edna po edna: //: gui/DolgotrZadKojaMozeDaSePrekine.java // Dolgotrajni zadaci vo niskite. import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.util.concurrent.*; import static net.mindview.util.SwingKonzola.*; class Zadaca implements Runnable { private static int brojac = 0; private final int id = brojac++; public void run() { System.out.println(this + " startuvana"); try { TimeUnit.SECONDS.sleep(3); } catch(InterruptedException e) { System.out.println(this + " prekinata"); return; } System.out.println(this + " zavrsena"); } public String toString() { return "Zadaca " + id; } public long id() { return id; } }; public class DolgotrZadKojaMozeDaSePrekine extends JFrame { private JButton k1 = new JButton("Startuvaj dolgotrajna zadaca"), k2 = new JButton("Otkazi ja dolgotrajnata zadaca"); ExecutorService izvrsitel = Executors.newSingleThreadExecutor(); public DolgotrZadKojaMozeDaSePrekine() { k1.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { Zadaca zadaca = new Zadaca(); izvrsitel.execute(zadaca); System.out.println(zadaca + " dodadena vo redot za cekanje"); } }); k2.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { izvrsitel.shutdownNow(); // Prejako

1286

Da se razmisluva vo Java

Brus Ekel

} }); setLayout(new FlowLayout()); add(k1); add(k2); } public static void main(String[] args) { run(new DolgotrZadKojaMozeDaSePrekine(), 200, 150); } } ///:~

Ova e podobro, no koga }e go pritisnete kop~eto k2, toa }e go povika metodot shutdownNow() za ExecutorService i taka }e ja otka`e taa zada~a. Dokolku se obidete da dodadete u{te zada~i, }e dobiete isklu~ok. Zna~i, pritisokot na k2 pravi programata da umre. Sakavme da ja otka`eme tekovnata zada~a (i da gi otka`eme zada~ite vo redot za ~ekawe), a ne da ja gasneme celata programa. Potreben ni e ba{ mehanizmot na Java SE5 Callable/Future opi{an vo poglavjeto Paralelno izvr{uvawe. ]e definirame nova klasa MenadzerNaZadacite; taa sodr`i torka koja opfa}a objekt od tipot Callable. Callable e zada~a i objekt od tipot Future koj e rezultat na taa zada~a. Torka e potrebna zatoa {to ni ovozmo`uva da ja sledime prvobitnata zada~a. Za da imame i dopolnitelni informacii so koi Future ne raspolaga. Eve kako toa izgleda: //: net/mindview/util/StavkaNaZadacata.java // Objekt od tipot Future i Callable koj go napravil. package net.mindview.util; import java.util.concurrent.*; public class StavkaNaZadacata { public final Future idna; public final C zadaca; public stavkaNaZadacata(Future idna, C zadaca) { this.future = idna; this.zadaca = zadaca; } } ///:~

Vo bibliotekata java.util.concurrent zada~ata ne e podrazbirano dostapna preku klasata Future, bidej}i taa i ne mora da postoi koga od klasata Future }e go dobiete rezultatot. Tuka zada~ata postoi zatoa {to ja snimivme. MenadzerNaZadacite e staven vo paketot net.mindview.util za da bide dostapen kako uslu`na klasa za op{ta namena: //: net/mindview/util/MenadzerNaZadacite.java // Upravuvanje so redot na zadacite i negovo izvrsuvanje. package net.mindview.util; import java.util.concurrent.*; import java.util.*;

Grafi~ki korisni~ki opkru`uvawa

1287

public class MenadzerNaZadacite extends ArrayList { private ExecutorService exec = Executors.newSingleThreadExecutor(); public void add(C zadaca) { add(new StavkaNaZadacata(exec.submit(zadaca),zadaca)); } public List getResults() { Iterator< StavkaNaZadacata> stavki = iterator(); List rezultati = new ArrayList(); while(stavki.hasNext()) { StavkaNaZadacata stavka = stavki.next(); if(stavka.idna.isDone()) { try { rezultati.add(stavka.idna.get()); } catch(Exception e) { throw new RuntimeException(e); } stavki.remove(); } } return rezultati; } public List purge() { Iterator stavki = iterator(); List rezultati = new ArrayList(); while(stavki.hasNext()) { StavkaNaZadacata stavka = stavki.next(); // Ostavi gi zavrsenite zadaci zaradi izvestuvanje za rezultatite: if(!stavka.idna.isDone()) { rezultati.add("Otkazuvam " + stavka.zadaca); stavka.idna.cancel(true); // Moze da prekine stavki.remove(); } } return rezultati; } } ///:~

MenadzerNaZadacite e lista od tipot ArrayList ~ii stavki se od tipot StavkaNaZadacite. Toj sodr`i i Executor od edna ni{ka, pa koga }e go povikate metodot add() i }e £ prosledite objekt od tipot Callable, toj go ispra}a toj Callable, a rezultiraniot objekt od tip Future }e se skladira zaedno so prvobitnata zada~a. Na toj na~in, ako bilo {to treba da se pravi so taa zada~a, }e imate referenca na nea. Kako ednostaven primer, vo metodot purge() se koristi metodot toString() na taa zada~a. Toa sega }e go upotrebime za upravuvawe so dolgotrajnite zada~i vo na{iot primer: //: gui/DolgotrCallableKojMozeDaSePrekine.java

1288

Da se razmisluva vo Java

Brus Ekel

// Koristenje na Callable objekti za dolgotrjanite zadaci. import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.util.concurrent.*; import net.mindview.util.*; import static net.mindview.util.SwingKonzola.*; class CallableZadaca extends Zadaca implements Callable { public String call() { run(); return "Povratna vrednost od " + this; } } public class DolgotrCallableKojMozeDaSePrekine extends JFrame { private JButton k1 = new JButton("Startuvaj dolgotrajna zadaca"), k2 = new JButton("Otkazi ja dolgotrajnata zadaca"), k3 = new JButton("Daj rezultati"); private MenadzerNaZadacite menadzer = new MenadzerNaZadacite(); public DolgotrCallableKojMozeDaSePrekine() { k1.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { CallableZadaca zadaca = new CallableZadaca(); menadzer.add(zadaca); System.out.println(zadaca + " dodadena vo redot za cekanje"); } }); k2.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { for(String rezultat : menadzer.purge()) System.out.println(rezultat); } }); k3.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { // Primer za povik na metod na klasata Zadaca: for(StavkaNaZadacata tt : menadzer) tt.zadaca.id(); // Ne e potrebna eksplicitna konverzija na tipot for(String rezultat : menadzer.getResults()) System.out.println(rezultat); } }); setLayout(new FlowLayout()); add(k1); add(k2);

Grafi~ki korisni~ki opkru`uvawa

1289

add(k3); } public static void main(String[] args) { run(new DolgotrCallableKojMozeDaSePrekine(), 200, 150); } } ///:~

Kako {to gledate, CallableZadaca pravi isto {to i Zadaca, osven {to go vra}a i rezultatot - vo ovoj slu~aj String identifikatorot na zada~ata. Za re{avawe na istiot problem napi{ani se i ne-Swing uslu`ni klasi (koi ne se ispora~uvaat vo standardnata distribucija na Java). Toa se SwingWorker (}e ja najdete na Web sajtot na Sun) i Foxtrot (na adresata http://foxtrot.sourceforge.net). Dodeka ja pi{uvav knigata, tie klasi ne bea modificirani taka za da go iskoristat Callable/Future mehanizmot na Java SE5. ^esto na krajniot korisnik e dobro da mu se dade nekoj vizuelen znak deka zada~ata se izvr{uva i da se izvesti do kade oti{lo izvr{uvaweto. Toa obi~no se pravi so pomo{ na klasite JProgressBar ili ProgressMonitor. Vo sledniot primer }e upotrebam ProgressMonitor. //: gui/NadziranDolgotrCallable.java // Prikazuvanje na napreduvanjeto na zadacata ProgressMonitors. import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.util.concurrent.*; import net.mindview.util.*; import static net.mindview.util.SwingKonzola.*;

so

pomos

na

klasata

class NadziranCallable implements Callable { private static int brojac = 0; private final int id = brojac++; private final ProgressMonitor monitor; private final static int MAX = 8; public NadziranCallable(ProgressMonitor monitor) { this.monitor = monitor; monitor.setNote(toString()); monitor.setMaximum(MAX - 1); monitor.setMillisToPopup(500); } public String call() { System.out.println(this + " startuvan"); try { for(int i = 0; i < MAX; i++) { TimeUnit.MILLISECONDS.sleep(500); if(monitor.isCanceled()) Thread.currentThread().interrupt(); final int napreduvanje = i;

1290

Da se razmisluva vo Java

Brus Ekel

SwingUtilities.invokeLater( new Runnable() { public void run() { monitor.setProgress(napreduvanje); } } ); } } catch(InterruptedException e) { monitor.close(); System.out.println(this + " prekinat"); return "Rezultat: " + this + " prekinat"; } System.out.println(this + " zavrsen"); return "Rezultat: " + this + " zavrsen"; } public String toString() { return "Zadaca " + id; } }; public class NadziranDolgotrCallable extends JFrame { private JButton k1 = new JButton("Startuvaj dolgotrajna zadaca"), k2 = new JButton("Otkazi ja dolgotrajnata zadaca"), k3 = new JButton("Daj rezultati"); private MenadzerNaZadacite menadzer = new MenadzerNaZadacite(); public NadziranDolgotrCallable() { k1.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { NadziranCallable zadaca = new NadziranCallable( new ProgressMonitor( NadziranDolgotrCallable.this, "Dolgotrajna Zadaca", "", 0, 0) ); menadzer.add(zadaca); System.out.println(zadaca + " dodadena vo redot za cekanje"); } }); k2.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { for(String rezultat : menadzer.purge()) System.out.println(rezultat); } }); k3.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { for(String rezultat : menadzer.getResults()) System.out.println(rezultat); } }); setLayout(new FlowLayout());

Grafi~ki korisni~ki opkru`uvawa

1291

add(k1); add(k2); add(k3); } public static void main(String[] args) { run(new NadziranDolgotrCallable(), 200, 500); } } ///:~

Konstruktorot na klasata NadziranCallable prima objekt od tipot ProgressMonitor kako argument, a negoviot metod call() go a`urira ProgressMonitor na sekoja polovina sekunda. Imajte predvid deka NadziranCallable e posebna zada~a i deka ne bi trebalo neposredno da gi kontrolira vlezno/izleznite operacii, pa na monitor-ot so metodot SwingUtilities.invokeLater() mu podnesov informacii za promenata na stepenot na napreduvaweto. Vo u~ebnikot na Sun za Swing (na adresata http://java.sun.com) e prika`an inakov pristap; tamu se upotrebuva Swing Timer, koj go proveruva statusot na zada~ata i go a`urira monitorot. Ako na monitorot se pritisne kop~eto cancel, metodot monitor.isCanceled() vra}a true. Tuka zada~ata samo go povikuva metodot interrupt() za sopstvenata ni{ka, {to }e dovede vo odredbata catch kade monitor-ot se otka`uva so metodot close(). Ostatokot od kodot e glavno ist kako i porano, osven {to praveweto objekt od tipot ProgressMonitor se odviva vnatre vo konstruktorot na zada~ata NadziranDolgotrCallable. Ve`ba 33: (6) Izmenete ja DolgotrCallableKojMozeDaSePrekine.java taka {to site zada~i da gi izvr{uva paralelno, a ne sekvencijalno.

Vizuelno programirawe so pove}e ni{ki Vo sledniot primer }e napravime Runnable objekt od tipot JPanel (panel) koj se boi sebesi vo razni boi. Aplikacijata e prilagodena taka {to od komandnata linija prima parametri koi ja opredeluvaat goleminata na tabelata za boja i - so metodot sleep() - traeweto na spieweto pomeѓu promenata na boite. Poigrajte si so tie parametri i bi mo`ele da otkriete zanimlivi i mo`ebi neobjasnivi obele`ja na izvr{uvaweto so pove}e ni{ki na va{ata platforma: //: gui/OboeniKutii.java // Vizuelen prikaz na izvrsuvanjeto so povece niski. import javax.swing.*; import java.awt.*; import java.util.concurrent.*; import java.util.*;

1292

Da se razmisluva vo Java

Brus Ekel

import static net.mindview.util.SwingKonzola.*; class ObKut extends JPanel implements Runnable { private int pauza; private static Random rand = new Random(); private Color boja = new Color(0); public void paintComponent(Graphics g) { g.setColor(boja); Dimension golemina = getSize(); g.fillRect(0, 0, golemina.sirocina, golemina.visocina); } public ObKut(int pauza) { this.pauza = pauza; } public void run() { try { while(!Thread.interrupted()) { boja = new Color(rand.nextInt(0xFFFFFF)); //Asinhron povik na metodot paint(), t.e baranje slikata povtorno da se iscrta: repaint(); TimeUnit.MILLISECONDS.sleep(pauza); } } catch(InterruptedException e) { // Prifatliv nacin na izlez } } } public class OboeniKutii extends JFrame { private int brojcelii = 12; private int pauza = 50; private static ExecutorService exec = Executors.newCachedThreadPool(); public OboeniKutii() { setLayout(new GridLayout(brojcelii, brojcelii)); for(int i = 0; i < brojcelii * brojcelii; i++) { ObKut ok = new ObKut(pauza); add(ok); exec.execute(ok); } } public static void main(String[] args) { OboeniKutii kutii = new OboeniKutii(); if(args.length > 0) kutii.brojcelii = new Integer(args[0]); if(args.length > 1) kutii.pauza = new Integer(args[1]); kutii.setUp(); run(kutii, 500, 400); } } ///:~

Grafi~ki korisni~ki opkru`uvawa

1293

OboeniKutii go konfigurira objektot od tip GridLayout taka {to vo sekoja dimenzija ima brojcelii. Potoa dodava soodveten broj ObKut objekti da go popolni toj broj }elii i na sekoj mu prosleduva broj pauzi. Vo metodot main() }e vidite deka pauza i brojcelii imaat podrazbirani vrednosti koi mo`at da se menuvaat so prosleduvawe argumenti na komandnata linija. S¢ se pravi vo klasata ObKut. Taa e izvedena od klasata JPanel i realizira interfejs Runnable, taka {to sekoj objekt od tipot JPanel mo`e da bide nezavisna zada~a. So tie zada~i upravuva grupa ni{ki ExecutorService. Tekovnata boja na }elijata e boja. Boite gi pravi konstruktorot na klasata Color ~ij vlezen argument treba da bide 24-biten broj koj vo ovoj slu~aj go pravime slu~ajno. Metodot paintComponent() e sosema ednostaven; toj samo ja menuva bojata kako }e £ ka`e boja-ta i celiot panel (objekt od tip JPanel) go popolnuva so nea. Vo metodot run() postoi beskone~en kotelec koj na objektot boja mu zadava nova slobodno napravena boja i potoa go povikuva repaint() za da ja poka`e. Potoa taa ni{ka - so primena na metodot sleep() - odi na spiewe, za vreme zadadeno na komandnata linija. Povikot na metodot repaint() vnatre vo metodot run() zaslu`uva vnimanie. Na prv pogled izgleda deka pravime mnogu ni{ki i deka site moraat da se prebrojat. Mo`ebi vi izgleda deka so toa go kr{ime principot vrz osnova na na koj site zada~i treba da se ispratat na rasporeduva~ot, odnosno na redot za ~ekawe. Meѓutoa, tie ni{ki vsu{nost ne go modificiraat deleniot resurs. Koga tie }e go povikaat metodot repaint(), taa ne go prezema prebojuvaweto tuku samo postavuva odreden indikator Âzama~kano°, so {to poka`uva deka taa oblast e kandidat za prebojuvawe koga rasporeduva~ot sledniot pat }e bide podgotven za taa akcija. Zatoa programata ne predizvikuva problemi so ni{kite na Swing. Koga ni{kata na rasporeduva~ot na nastani }e go povika metodot paint(), toj prvo go povikuva paintComponent(), potoa paintBorder() i potoa paintChildren(). Ako vo izvedenata komponenta sakate da go redefinirate metodot paint(), ne zaboravete da ja povikate verzijata na paint() od osnovnata klasa, za da se napravi {to treba. Tokmu zatoa {to ovoj dizajn e prilagodliv i ni{kite se vrzani za sekoj element na panelot, mo`ete da eksperimentirate i da pravite proizvolen broj ni{ki. (Vo praksa, ograni~uvaweto nametnuva broj ni{ki so koi va{ata JVM mo`e da izleze na kraj.) Ovaa programa ovozmo`uva zanimlivo sporeduvawe na performansite, bidej}i mo`e da poka`e golemi razliki vo odnesuvaweto i performansite na razni realizacii na JVM ni{kite i raznite platformi.

1294

Da se razmisluva vo Java

Brus Ekel

Ve`ba 34: (4) Izmenete ja programata OboeniKutii.java taka {to prvo slobodno da prska to~ki (Âyvezdi°) po platnoto, a potoa slobodno da gi menuva boite na tie Âyvezdi°.

Vizuelnoto programirawe i zrnata na Java Dosega vo ovaa kniga vidovte kolku Java e korisna za pi{uvawe pove}ekratno upotrebliv kod. Edinicata kod koja naj~esto mo`e povtorno da se iskoristi e klasa bidej}i se sostoi od karakteristiki (poliwa) i odnesuvawa (metodi) koi mo`at povtorno da se koristat - so kompozicija ili so nasleduvawe. Nasleduvaweto i polimorfizmot se osnovnite principi na objektno orientiranoto programirawe, no koga pi{uvate aplikacija, naj~esto se trudite komponentite da go rabotat tokmu ona {to vie go sakate. Bi sakale da gi ufrlite tie delovi vo svojata programa kako {to elektroin`inerot postavuva ~ipovi na plo~ata. Isto taka, izgleda deka bi trebalo da postoi nekoj drug na~in za zabrzuvawe na vakviot stil na programirawe koj bi mo`el da se nare~e Âsklopuvawe od delovi°. ÂVizuelnoto programirawe° do`ivea svoj uspeh, i toa golem, so Microsoftoviot jazik Visual BASIC (VB). Po nego se pojavi vtorata generacija ~ij najistaknat pretstavnik e Borland-oviot Delphi; toj be{e i najgolemata inspiracija za zrnata na Java. Vo tie programerski alatki komponentite se pretstaveni vizuelno, {to ima smisla, bidej}i tie obi~no prika`uvaat nekoj grafi~ki element, kako {to se kop~e ili pole za tekst. Vsu{nost, takvata vizuelna pretstava e ~esto izgled na komponentata vo programata koja se izvr{uva. Poradi toa del od postapkata vizuelno programirawe podrazbira povlekuvawe na komponentata od paletata i spu{tawe na obrazecot. Alatkata za pravewe aplikacii pi{uva kod dodeka vie gi povlekuvate komponentite, a toj kod predizvikuva pravewe komponenta vo izvr{nata programa. Samoto povlekuvawe na komponentata vo obrazecot ne e dovolno za kompletirawe na programata. ^esto morate da izmenite nekoi nejzini obele`ja, npr. bojata, tekstot koj go sodr`i, bazata na podatoci so koja e povrzana itn. Obele`jata koi mo`at da se izmenat vo tek na proektiraweto se ozna~uvaat kako svojstva (angl. properties). So svojstvata na komponentata mo`ete da rabotite so pomo{ na alatkata za pravewe aplikacii, a koga }e ja napravite programata, svojstvata na komponentite }e bidat snimeni za da mo`at da se rekonstruiraat koga programata }e se startuva. Dosega sigurno se naviknavte na idejata deka objektot nema samo svojstva, tuku i odnesuvawe. Vo tek na proektiraweto, odnesuvaweto na vizuelnata komponenta e delumno pretstaveno so nastanite. Nastan zna~i: ÂEve ne{to

Grafi~ki korisni~ki opkru`uvawa

1295

{to bi mo`elo da £ se slu~i na komponentata°. Obi~no odlu~uvate {to treba da se slu~i po nastanot taka {to go povrzuvate kodot so odreden nastan. Eve isklu~itelno va`en del: alatkata za pravewe aplikacii koristi refleksija za dinami~ko ispituvawe na komponentata i otkrivawe na svojstvata i nastanite koi komponentata gi poddr`uva. Koga toa }e go doznae, mo`e da gi prika`e svojstvata i da ovozmo`i da gi menuvate (so snimawe na sostojbata), no mo`e da gi prika`e i nastanite. Po pravilo, vie dva pati pritisnuvate so gluv~eto, a alatkata za pravewe aplikacii pravi kod i go povrzuva so toj nastan. Vo toj moment treba samo da napi{ete kod koj se izvr{uva koga }e se slu~i nastanot. Zna~i, alatkata za pravewe aplikacii izvr{uva najgolem del od rabotata namesto vas. Poradi toa mo`ete da se skoncentrirate na izgledot na programata i na toa {to taa treba da raboti, a da se potprete na toa deka taa alatka }e izvr{i kompletno povrzuvawe. Alatkite za vizuelno programirawe se isklu~itelno popularni zatoa {to zabele`livo go zabrzuvaat praveweto aplikacii. Toa posebno va`i za korisni~kite opkru`uvawa, no ~esto i za drugi delovi na aplikacijata.

[to e zrno? Koga pravot }e slegne, se gleda deka komponentata e samo blok na kodot koj obi~no e pretstaven vo oblik na klasa. Klu~no pra{awe e mo`nosta na alatkata za pravewe aplikacii da gi otkriva svojstvata i nastanite na taa komponenta. Za da napravi VB komponenta, programerot mora{e da pi{uva prili~no slo`en kod vo koj po~ituval odredeni pravila za otkrivawe na svojstvata i nastanite. Delphi be{e alatka za vizuelno programirawe od vtorata generacija. Toj jazik aktivno go koriste{e vizuelnoto programirawe, pa vizuelnata komponenta mnogu polesno se prave{e. Meѓutoa, izrabotkata na vizuelnite komponenti na najvisoko nivo ja dovede Java i toa so pomo{ na zrnata (angl. Java Beans), bidej}i samoto zrno e klasa. Ne morate da pi{uvate dopolnitelen kod nitu da koristite specijalni pro{iruvawa na jazikot za ne{to da stane zrno. Vsu{nost, treba samo malku da go promenite na~inot na imenuvawe na metodot. Vrz osnova na imeto na metodot, alatkata za pravewe aplikacii znae dali se raboti za svojstvo, nastan ili obi~en metod. Vo dokumentacijata na Java ovie pravila na imenuvawe se pogre{no ozna~eni kako Âproekten obrazec°. Toa e nedorazbirawe, bidej}i proektnite obrasci se dovolen predizvik i bez ovaa zbrka (}e gi najdete vo knigata Thinking in Patterns with Java koja mo`ete da ja prezemete od sajtot www.MindView.net). Zrnata na Java ne se opi{ani so proekten obrazec, tuku samo so pravilata za imenuvawe, i toa prili~no ednostavni:

1296

Da se razmisluva vo Java

Brus Ekel

1. Za nekoe svojstvo da se nare~e xxx, obi~no treba da se napravat dve metodi: getXxx() i setXxx(). Obrnete vnimanie na toa deka prvata bukva pozadi get ili set avtomatski se pretvora vo mala za da se dobie svojstvoto. Tipot {to go vra}a metodot get e ist kako tipot na argumentot na metodot set. Imeto na svojstvoto i tipovite koi gi vra}aat metodite get i set ne moraat da bidat povrzani. 2. Za svojstvo od tipot boolean mo`ete da go koristite prethodniot pristap so metodite get i set, no namesto get mo`ete da koristite is. 3. Obi~nite metodi na zrnata ne gi po~ituvaat prethodnite pravila za dodeluvawe imiwa, no se javni. 4. Za nastanite se koristi pristapot na "priemnik" od bibliotekata Swing. Toa e isto so ona {to ve}e go vidovte: so metodite addBounceListener(BounceListener) i removeBounceListener(BounceListener) se obrabotuva nastanot BounceEvent. Naj~esto vgradenite nastani i priemnici }e gi zadovoluvaat potrebite, no mo`ete da napravite i sopstveni nastani i priemni~ki interfejsi. Ovie soznanija mo`eme da gi iskoristime za pravewe ednostavno zrno: //: frogbean/Frog.java // Obicno Java zrno. package frogbean; import java.awt.*; import java.awt.event.*; class Spots {} public class Frog { private int jumps; private Color color; private Spots spots; private boolean jmpr; public int getJumps() { return jumps; } public void setJumps(int newJumps) { jumps = newJumps; } public Color getColor() { return color; } public void setColor(Color newColor) { color = newColor; } public Spots getSpots() { return spots; } public void setSpots(Spots newSpots) { spots = newSpots; } public boolean isJumper() { return jmpr; } public void setJumper(boolean j) { jmpr = j; } public void addActionListener(ActionListener l) { //... }

Grafi~ki korisni~ki opkru`uvawa

1297

public void removeActionListener(ActionListener l) { // ... } public void addKeyListener(KeyListener l) { // ... } public void removeKeyListener(KeyListener l) { // ... } // "Obicen" javen metod: public void croak() { System.out.println("Ribbet!"); } } ///:~

Prvo uviduvate deka ova e obi~na klasa. Site nejzini poliwa obi~no }e bidat privatni i }e mo`e da im se pristapuva samo preku metodot. Vo sklad so praviloto za imenuvawe, svojstvata se jumps, color, spots i jumper (obrnete vnimanie na promenata na goleminata na prvata bukva na imeto na svojstvoto). Iako imeto na lokalniot identifikator e isto kako imeto na svojstvoto vo prvite tri slu~ai, svojstvoto jumper poka`uva deka imeto na svojstvoto ne e uslov za koristewe to~no opredelen identifikator za lokalnite promenlivi. (Lokalni promenlivi za toa svojstvo duri ne mora ni da postojat.) Nastanite koi gi generira ova zrno se ActionEvent i KeyEvent, {to zaklu~uvame po imiwata na metodite add i remove za rabota so priemnicite. Kone~no, gledate deka obi~niot metod croak() i ponatamu e del od zrnoto zatoa {to e javen, a ne zatoa {to go po~ituva praviloto za dodeluvawe imiwa.

Ispituvawe na zrnata so klasata Introspector Edna od najosetlivite strani na zrnoto se uviduva koga zrnoto go povlekuvate od paletata i go ispu{tate na obrazecot. Alatkata za pravewe aplikacija mora da bide vo sostojba da napravi zrno ({to mo`e da go napravi ako postoi podrazbiran konstruktor) i potoa, bez pristapuvawe na negoviot izvoren kod, da gi oddeli site neophodni informacii za da napravi spisok na svojstvata i blokovite za obrabotka na nastanot. Del od re{enieto }e pronajdete na krajot na poglavjeto Podatoci za tipot: refleksijata na Java ovozmo`uva da se otkrijat site metodi na koja bilo klasa. Toa e sovr{eno za re{avawe na problemite so zrnata bez koristewe dopolnitelni zborovi na jazikot, {to e potrebno vo drugite jazici za vizuelno programirawe. Edna od najva`nite pri~ini za dodavawe refleksija vo Java be{e tokmu poddr`uvaweto na zrnata (iako refleksijata ovozmo`uva

1298

Da se razmisluva vo Java

Brus Ekel

i serijalizacija na objektite i dale~insko povikuvawe na metodite). Zna~i, mo`e da se o~ekuva avtorot na alatkata za pravewe aplikacii da mora da go ispituva sekoe zrno i da gi pregleduva negovite metodi, za da doznae koi se negovite svojstva i metodi. Toa sigurno e mo`no, no proektantite na Java sakaa da obezbedat standardna alatka, ne samo polesno da se koristat zrnata, tuku i da se obezbedi standardiziran na~in za pravewe poslo`eni zrna. Taa alatka e klasata Introspector, a nejzin najva`en metod e staticgetBeanInfo(). Na ovoj metod mu se prosleduva referencata na objektot od klasata Class, a toj iscrpno ja ispituva klasata i vra}a objekt od tipot BeanInfo koj potoa mo`ete da go analizirate za da gi doznaete svojstvata, metodite i nastanite na zrnata. Obi~no ni{to od toa nema da vi bide va`no; najgolemiot broj zrna }e gi koristite gotovi i nema potreba da gi znaete detalite koi se slu~uvaat vo niv. Samo }e gi povlekuvate zrnata na obrazecot, potoa }e gi prilagoduvate nivnite svojstva i }e pi{uvate proceduri za nastanite koi ve interesiraat. Meѓutoa, ve`bata za koristewe na klasata za prika`uvawe na informaciite za zrnoto e zanimliva i pou~na, pa eve ja alatkata koja toa go pravi: //: gui/IspituvanjeNaZrnoto.java // Ispituvanje na Zrnoto so klasata Introspector. import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.beans.*; import java.lang.reflect.*; import static net.mindview.util.SwingKonzola.*; public class IspituvanjeNaZrnoto extends JFrame { private JTextField prasanje = new JTextField(20); private JTextArea rezultati = new JTextArea(); public void print(String s) { rezultati.append(s + "\n"); } public void ispitaj(Class zrno) { rezultati.setText(""); BeanInfo bi = null; try { bi = Introspector.getBeanInfo(zrno, Object.class); } catch(IntrospectionException e) { print("Ne mozam da ispitam " + zrno.getName()); return; } for(PropertyDescriptor d: bi.getPropertyDescriptors()){ Class p = d.getPropertyType(); if(p == null) continue; print("Tip na svojstvoto:\n " + p.getName() + "Ime na svojstvoto:\n " + d.getName()); Method metodZaCitanje = d.getReadMethod(); if(metodZaCitanje != null) print("Metod za citanje:\n " + metodZaCitanje);

Grafi~ki korisni~ki opkru`uvawa

1299

Method metodZaVpisuvanje = d.getWriteMethod(); if(metodZaVpisuvanje != null) print("Metod za vpisuvanje:\n " + metodZaVpisuvanje); print("===================="); } print("Javni metodi:"); for(MethodDescriptor m : bi.getMethodDescriptors()) print(m.getMethod().toString()); print("======================"); print("Podrska za nastanite:"); for(EventSetDescriptor e: bi.getEventSetDescriptors()){ print("Tip na priemnikot:\n " + e.getListenerType().getName()); for(Method lm : e.getListenerMethods()) print("Metod na priemnikot:\n " + lm.getName()); for(MethodDescriptor lmd : e.getListenerMethodDescriptors() ) print("Opis na metodot:\n " + lmd.getMethod()); Method dodavanje= e.getAddListenerMethod(); print("Metod za dodavanje:\n " + dodavanje); Method otstranuvanje = e.getRemoveListenerMethod(); print("Metod za otstranuvanje:\n "+ otstranuvanje); print("===================="); } } class Ispituvac implements ActionListener { public void actionPerformed(ActionEvent e) { String ime = prasanje.getText(); Class c = null; try { c = Class.forName(ime); } catch(ClassNotFoundException ex) { rezultati.setText("Ne mozam da pronajdam " + ime); return; } ispitaj(c); } } public IspituvanjeNaZrnoto() { JPanel p = new JPanel(); p.setLayout(new FlowLayout()); p.add(new JLabel("Polno ime na zrnoto:")); p.add(prasanje); add(BorderLayout.NORTH, p); add(new JScrollPane(rezultati)); Ispituvac isp = new Ispituvac(); prasanje.addActionListener(isp); prasanje.setText("frogbean.Frog"); // Prinudna proverka isp.actionPerformed(new ActionEvent(isp, 0, "")); }

1300

Da se razmisluva vo Java

Brus Ekel

public static void main(String[] args) { run(new IspituvanjeNaZrnoto(), 600, 500); } } ///:~

Celata rabota ja vr{i metodot IspituvanjeNaZrnoto.ispitaj(). Toj prvo se obiduva da napravi objekt na interfejsot BeanInfo, a ako uspee, gi povikuva metodite koi vra}aat informacii za svojstvata na zrnata, metodite i nastanite. Vo metodot Introspector.getBeanInfo() }e zabele`ite drug argument. Toj mu ka`uva na objektot na klasata kade da zapre vo hierarhijata na nasleduvawe. Tuka zapira pred da gi analizira metodite na klasata Object, bidej}i tie ne n¢ interesiraat. Metodot getPropertyDescriptors() vra}a niza objekti od tipot PropertyDescriptor koi gi opi{uvaat svojstvata. Za sekoj deskriptor na svojstvata (objekt od tip PropertyDescriptor) mo`ete da go povikate metodot getPropertyType() za da ja otkriete klasata na objektot koj se prosleduva vnatre i nadvor so pomo{ na metodot na svojstvata. Potoa, za sekoe svojstvo mo`ete da dobiete psevdonim (generiran vrz osnova na imeto na metodot) so pomo{ na metodot getName(), metod za ~itawe so pomo{ na getReadMethod() i metod za vpi{uvawe so pomo{ na getWriteMethod(). Dvete posledni metodi vra}aat objekt od tipot Method koj mo`e da se koristi za povikuvawe na soodvetniot metod na objektot (toa e del od refleksijata). [to se odnesuva do javnite metodi (vklu~uvaj}i gi i metodite na svojstvata), getMethodDescriptors() vra}a niza objekti na klasata MethodDescriptor. Mo`ete da dobiete objekt od tipot Method povrzan so sekoj od tie objekti i da go ispi{ete negovoto ime. [to se odnesuva do nastanite, metodot getEventSetDescriptors() vra}a niza (na {to drugo tuku) na objektite od tipot EventSetDescriptor. Sekoj od niv mo`e da se ispita za da se otkrie klasata na priemnikot, metodot na priemni~kata klasa, kako i metodot za dodavawe i otstranuvawe na priemnikot. Programata IspituvanjeNaZrnoto gi ispi{uva site ovie informacii. Pred izvr{uvaweto, programata go proveruva zrnoto frogbean.Frog. Po eliminirawe na dopolnitelnite, nepotrebni detali, rezultatot izgleda vaka: Tip svojstvo: Color Ime na svojstvoto: color Metod za citanje: public Color getColor() Metod za vpisuvanje: public void setColor(Color) ==================== Tip svojstvo:

Grafi~ki korisni~ki opkru`uvawa

1301

boolean Ime na svojstvoto: jumper Metod za citanje: public boolean isJumper() Metod za vpisuvanje: public void setJumper(boolean) ==================== Tip svojstvo: int Ime na svojstvoto: jumps Metod za citanje: public int getJumps() Metod za vpisuvanje: public void setJumps(int) ==================== Tip svojstvo: frogbean.Spots Ime na svojstvoto: spots Metod za citanje: public frogbean.Spots getSpots() Metod za vpisuvanje: public void setSpots(frogbean.Spots) ==================== Javni metodi: public void setSpots(frogbean.Spots) public void setColor(Color) public void setJumps(int) public boolean isJumper() public frogbean.Spots getSpots() public void croak() public void addActionListener(ActionListener) public void addKeyListener(KeyListener) public Color getColor() public void setJumper(boolean) public int getJumps() public void removeActionListener(ActionListener) public void removeKeyListener(KeyListener) ===================== Podrska za nastanite: Tip priemnik: KeyListener Metod na priemnikot: keyPressed Metod na priemnikot: keyReleased Metod na priemnikot: keyTyped Opis na metodot:

1302

Da se razmisluva vo Java

Brus Ekel

public abstract void keyPressed(KeyEvent) Opis na metodot: public abstract void keyReleased(KeyEvent) Opis na metodot: public abstract void keyTyped(KeyEvent) Metod za dodavanje: public void addKeyListener(KeyListener) Metod za otstranuvanje: public void removeKeyListener(KeyListener) ==================== Tip priemnik: ActionListener Metod na priemnikot: actionPerformed Opis na metodot: public abstract void actionPerformed(ActionEvent) Metod za dodavanje: public void addActionListener(ActionListener) Metod za otstranuvanje: public void removeActionListener(ActionListener) ====================

Ovaa programa gi otkriva najgolemiot del svojstva koi gi gleda klasata Introspector dodeka vrz osnova na zrnoto pravi objekt od tipot BeanInfo. ]e zabele`ite deka tipot na svojstvata i negovoto ime se nezavisni. Obrnete vnimanie na toa deka site bukvi vo imeto na svojstvata se mali. (Edinstveno se otstapuva koga imeto na svojstvoto po~nuva so nekolku posledovatelni golemi bukvi.) Zapametete go i toa deka imiwata na metodite kakvi {to ovde gi gledate (npr. metodite za ~itawe i vpi{uvawe) vsu{nost se dobivaat od objekt od tipot Method koj mo`e da se koristi za povikuvawe na soodvetniot metod. Spisokot javni metodi sodr`i metodi koi ne se povrzani so nekoe svojstvo ili nastan, kakov {to e metodot croak(), no i onie koi se povrzani so svojstva i nastani. Toa se sé metodi na zrna koi mo`ete da gi povikate od programata, a alatkata za pravewe aplikacii mo`e site da gi prika`e dodeka ja pi{uvate programata za da vi ja olesni rabotata. Kone~no, se zabele`uva deka nastanite se potpolno analizirani i razdeleni na interfejsot na priemnikot, negovite metodi i metodite za dodavawe i otstranuvawe na priemnikot. Vo osnova, koga imate objekt od tipot BeanInfo, mo`ete da doznaete s¢ {to e va`no za zrnoto. Mo`ete da gi povikuvate i metodite na zrnoto, duri i ako nemate nikakvi drugi informacii osven ovoj objekt (toa e u{te edna osobina na refleksijata).

Ponapredno zrno Sledniot primer e samo ne{to malku ponapreden, iako e frivolen. Toa e objekt od klasata koj iscrtuva mal krug okolu gluv~eto sekoga{ koga toa }e

Grafi~ki korisni~ki opkru`uvawa

1303

se pomesti. Koga }e go pritisnete tasterot na gluv~eto, zborot Bang! se pojavuva vo sredinata na ekranot i se startuva priemnikot na nastanite. Mo`ete da gi promenite slednite svojstva: goleminata na krugot, bojata, goleminata i zborot koj se pojavuva koga }e se pritisne tasterot na gluv~eto. Objektot BangBean isto taka ima sopstveni metodi addActionListener() i removeActionListener() so ~ija pomo{ mo`ete da go povrzete zrnoto so svojot priemnik koj se startuva koga korisnikot go pritisnuva gluv~eto. Sega ve}e bi trebalo da znaete da ja prepoznaete poddr{kata za svojstvata i nastanite: //: bangbean/BangBean.java // Graficko zrno. package bangbean; import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.io.*; import java.util.*; public class BangBean extends JPanel implements Serializable { private int xm, ym; private int cSize = 20; // Golemina na kruznicata private String text = "Bang!"; private int fontSize = 48; private Color tColor = Color.RED; private ActionListener actionListener; public BangBean() { addMouseListener(new ML()); addMouseMotionListener(new MML()); } public int getCircleSize() { return cSize; } public void setCircleSize(int newSize) { cSize = newSize; } public String getBangText() { return text; } public void setBangText(String newText) { text = newText; } public int getFontSize() { return fontSize; } public void setFontSize(int newSize) { fontSize = newSize; } public Color getTextColor() { return tColor; } public void setTextColor(Color newColor) { tColor = newColor; } public void paintComponent(Graphics g) { super.paintComponent(g); g.setColor(Color.BLACK); g.drawOval(xm - cSize/2, ym - cSize/2, cSize, cSize);

1304

Da se razmisluva vo Java

Brus Ekel

} // Zrnoto dozvoluva samo eden priemnik, a toa e // najednostavniot oblik na upravuvanje so priemnicite: public void addActionListener(ActionListener l) throws TooManyListenersException { if(actionListener != null) throw new TooManyListenersException(); actionListener = l; } public void removeActionListener(ActionListener l) { actionListener = null; } class ML extends MouseAdapter { public void mousePressed(MouseEvent e) { Graphics g = getGraphics(); g.setColor(tColor); g.setFont( new Font("TimesRoman", Font.BOLD, fontSize)); int width = g.getFontMetrics().stringWidth(text); g.drawString(text, (getSize().width - width) /2, getSize().height/2); g.dispose(); // Go povikuva priemnickiot metod: if(actionListener != null) actionListener.actionPerformed( new ActionEvent(BangBean.this, ActionEvent.ACTION_PERFORMED, null)); } } class MML extends MouseMotionAdapter { public void mouseMoved(MouseEvent e) { xm = e.getX(); ym = e.getY(); repaint(); } } public Dimension getPreferredSize() { return new Dimension(200, 200); } } ///:~

Prvo }e zabele`ite deka klasata BangBean realizira interfejs Serializable. Toa zna~i deka alatkata za pravewe aplikacii mo`e da gi v~ita site informacii za zrnoto so pomo{ na serijalizacija, otkako proektantot na programata }e gi podredi vrednostite na svojstvata. Koga zrnoto }e se napravi kako del od izvr{nata aplikacija, snimenite svojstva se rekonstruiraat pa se dobiva to~no ona {to ste proektirale. Vo potpisot na metodot addActionListener() gledate deka toj mo`e da generira isklu~ok TooManyListenerException. Toa zna~i deka nastanot e ednonaso~en, t.e. deka samo eden priemnik se izvestuva za toa deka se slu~il. Obi~no }e

Grafi~ki korisni~ki opkru`uvawa

1305

koristite pove}enaso~ni nastani taka {to za nastanot }e bidat izvesteni pove}e priemnici. Meѓutoa, tuka ve}e vleguvame vo temi koi }e bidat razgledani vo oddelot ÂZrnata na Java i sinhronizacijata°. So ednonaso~niot nastan zasega }e go zaobikolime ovoj problem. Koga }e go pritisnete tasterot na gluv~eto, vo zrnoto se ispi{uva tekst, a ako poleto actionListener ne e null, se pravi nov objekt od tip ActionEvent i mu se ispra}a na priemnikot. Koga }e se pomesti gluv~eto, se pametat negovite novi koordinati i pozadinata ja menuva bojata (so bri{ewe na tekstot koj se naoѓa na pozadinata, kako {to }e vidite). Eve klasa BangBeanTest koja ovozmo`uva testirawe na zrnoto kako aplet ili aplikacija: //: gui/BangBeanTest.java // {Timeout: 5} Vo testiranjeto, otkazi po 5 sekundi package bangbean; import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.util.*; import static net.mindview.util.SwingKonzola.*; public class BangBeanTest extends JFrame { private JTextField txt = new JTextField(20); // Vo tek na testiranjeto se prijavuvaat akcii: class BBL implements ActionListener { private int count = 0; public void actionPerformed(ActionEvent e) { txt.setText("Akcija na zrnoto "+ count++); } } public BangBeanTest() { BangBean bb = new BangBean(); try { bb.addActionListener(new BBL()); } catch(TooManyListenersException e) { txt.setText("Premnogu priemnici"); } add(bb); add(BorderLayout.SOUTH, txt); } public static void main(String[] args) { run(new BangBeanTest(), 400, 500); } } ///:~

Ovaa klasa nema da se koristi koga zrnoto se naoѓa vo razvojno opkru`uvawe, no e korisna kako na~in za brzo testirawe na site zrna. BangBeanTest go stava zrnoto BangBean vo aplet, povrzuvaj}i so nego ednostaven priemnik od tip ActionListener koj go ispi{uva brojot nastani vo tekstualnoto pole 1306

Da se razmisluva vo Java

Brus Ekel

sekoga{ koga }e se slu~i nastanot. Alatkata za izrabotka aplikacii obi~no go pravi najgolemiot del od kodot koj zrnoto go koristi. Koga }e go ispitate ova zrno so klasata IspituvanjeNaZrnoto ili }e go stavite vo razvojno opkru`uvawe koe gi poddr`uva zrnata, }e zabele`ite deka ima mnogu pove}e svojstva i akcii otkolku {to se gleda vo gorniot kod. Pri~ina e toa {to klasata BangBean e izvedena od klasata JPanel, a JPanel e isto taka zrno, pa se prika`uvaat i negovite svojstva i nastani. Ve`ba 35: (6) Pronajdete na Internet i prezemete edna ili pove}e besplatni vizuelni alatki za pravewe grafi~ki korisni~ki opkru`uvawa, ili kupete nekoja. Doznajte {to e neophodno zrnoto BangBean da se vnese i koristi vo toa opkru`uvawe.

Zrnata na Java i sinhronizacijata Sekoga{ koga }e napravite zrno, treba da o~ekuvate deka toa }e raboti vo opkru`uvawe so pove}e ni{ki. Toa zna~i slednoto: 1. Sekoga{ koga e mo`no, site javni metodi na edno zrno treba da se sinhroniziraat. Sekako, so toa predizvikuvate zgolemeni procesorski tro{oci koi gi povlekuva atributot synchronized. Ako tie se neprifatlivi, metodite koi nema da predizvikaat problemi vo kriti~nite delovi na programata mo`at da ostanat nesinhronizirani, no imajte predvid deka sekoga{ toa ne e lesno da se proceni. Obi~no kandidati za toa se mali (kako metodot getCircleSize() vo sledniot primer) i (ili) Âatomi~ni° metodi, pa metodot se izvr{uva za tolku kus period {to objektot ne mo`e da bide izmenet vo tek na izvr{uvaweto. Ako takvite metodi ostanat nesinhronizirani, izvr{uvaweto na celata programa mo`ebi nema zna~itelno da se zabrza. Zatoa site javni metodi na zrnata bi mo`ele da gi sinhronizirate, a rezerviraniot zbor synchronized da go otstranite samo ako znaete deka toa e potrebno i deka taka zna~itelno }e go zabrzate izvr{uvaweto na programata. 2. Pri izvestuvaweto na pove}e priemnici (angl. multicast) za nekoj nastan, morate da pretpostavite deka vo tek na dvi`eweto niz toj spisok nekoi priemnici mo`at da bidat dodadeni, a drugi eliminirani. Lesno e da se napravi prvata to~ka, no pri izveduvawe na vtorata treba malku da se razmisli. Da go zememe primerot na zrnoto BangBean.java pretstaveno vo prethodnoto poglavje. Tamu e izbegnato pra{aweto za koristewe pove}e ni{ki kako {to e zanemaren rezerviraniot zbor synchronized i e izvesten samo eden priemnik (angl. unicast). Eve go toj

Grafi~ki korisni~ki opkru`uvawa

1307

primer, izmenet taka {t da koristi pove}e ni{ki i za nastanite da izvestuva pove}e priemnici: //: gui/BangBean2.java // Bi trebalo svoite zrna da gi pisuvate ovaka, // za da mozat da se izvrsuvaat vo opkruzuvanje so povece niski. import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.io.*; import java.util.*; import static net.mindview.util.SwingKonzola.*; public class BangBean2 extends JPanel implements Serializable { private int xm, ym; private int cSize = 20; // Golemina na kruznicata private String text = "Bang!"; private int fontSize = 48; private Color tColor = Color.RED; private ArrayList actionListeners = new ArrayList(); public BangBean2() { addMouseListener(new ML()); addMouseMotionListener(new MM()); } public synchronized int getCircleSize() { return cSize; } public synchronized void setCircleSize(int newSize) { cSize = newSize; } public synchronized String getBangText() { return text; } public synchronized void setBangText(String newText) { text = newText; } public synchronized int getFontSize(){ return fontSize; } public synchronized void setFontSize(int newSize) { fontSize = newSize; } public synchronized Color getTextColor(){ return tColor;} public synchronized void setTextColor(Color newColor) { tColor = newColor; } public void paintComponent(Graphics g) { super.paintComponent(g); g.setColor(Color.BLACK); g.drawOval(xm - cSize/2, ym - cSize/2, cSize, cSize); } // Ova zrno ima povece priemnici, sto se koristi povece // od izvestuvanjeto na samo eden priemnik // kako sto bese napraveno vo programata BangBean.java: public synchronized void addActionListener(ActionListener l) {

1308

Da se razmisluva vo Java

Brus Ekel

actionListeners.add(l); } public synchronized void removeActionListener(ActionListener l) { actionListeners.remove(l); } // Vnimavajte, ova ne e sinhronizirano: public void notifyListeners() { ActionEvent a = new ActionEvent(BangBean2.this, ActionEvent.ACTION_PERFORMED, null); ArrayList lv = null; // Napravi povrsna kopija na spisokot za slucaj // nekoj da dodade eden priemnik vo tek // na povikuvanjeto drugi priemnici: synchronized(this) { lv = new ArrayList(actionListeners); } // Izvesti gi site metodi priemnici: for(ActionListener al : lv) al.actionPerformed(a); } class ML extends MouseAdapter { public void mousePressed(MouseEvent e) { Graphics g = getGraphics(); g.setColor(tColor); g.setFont( new Font("TimesRoman", Font.BOLD, fontSize)); int width = g.getFontMetrics().stringWidth(text); g.drawString(text, (getSize().width - width) /2, getSize().height/2); g.dispose(); notifyListeners(); } } class MM extends MouseMotionAdapter { public void mouseMoved(MouseEvent e) { xm = e.getX(); ym = e.getY(); repaint(); } } public static void main(String[] args) { BangBean2 bb2 = new BangBean2(); bb2.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { System.out.println("ActionEvent" + e); } }); bb2.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { System.out.println("BangBean2 action");

Grafi~ki korisni~ki opkru`uvawa

1309

} }); bb2.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { System.out.println("More action"); } }); JFrame frame = new JFrame(); frame.add(bb2); run(frame, 300, 300); } } ///:~

Dodavaweto na rezerviraniot zbor synchronized na metodite e mala i lesna izmena. Meѓutoa, uviduvate deka vo metodite addActionListener() i removeActionListener() priemnicite sega se dodavaat na listata i se otstranuvaat od nea za zrnoto da mo`e da ima pove}e priemnici. Se gleda deka metodot notifyListener() ne e sinhroniziran. Nego mo`at istovremeno da go povikaat pove}e ni{ki. Mo`no e i metodite addActionListener() i removeActionListener() da bidat povikani nasred povikot na metodot notifyListener(), {to pretstavuva problem zatoa {to toj metod pominuva niz listata na priemnikot. Za toj problem da se ubla`i, spisokot vnatre vo sinhroniziraniot del na kodot e kloniran so pomo{ na konstruktorot na spisokot na priemnikot ArrayList koj gi kopira elementite na svojot argument, pa se minuva niz klonot. Taka mo`e da se raboti so originalniot spisok na priemnikot, a pri toa da ne se vlijae na metodot notifyListener(). I metodot paintComponent() ne e sinhronizirana. Da se odlu~i dali treba da se redefiniraat metodite ne e lesno kako koga samo se dodavaat sopstveni metodi. Vo ovoj primer se ispostavuva deka metodot paintComponent() navidum dobro raboti, bez ogled dali e sinhroniziran ili ne. No morate da gi zemete predvid i slednite pra{awa: 1. Dali toj metod gi menuva kriti~nite promenlivi vnatre vo objektot? Za da otkriete koi promenlivi se kriti~ni, morate da otkriete dali drugite ni{ki vo programata }e gi ~itaat ili }e im zadavaat vrednosti. (Vo ovoj slu~aj, ~itaweto i zadavaweto skoro sekoga{ se izvr{uva vo sinhroniziranite metodi, pa mo`ete da gi ispitate samo niv.) Metodot paintComponent() nema takvi promeni na sostojbata. 2. Dali metodot zavisi od sostojbite na tie kriti~ni promenlivi? Ako nekoj sinhroniziran metod ja modificira promenlivata koja va{iot metod ja koristi, bi trebalo i nea da ja sinhronizirate. Vrz osnova na toa uviduvate deka promenlivata cSize ja modificiraat sinhroniziranite metodi, pa zatoa metodot paintComponent() bi trebalo da go sinhronizirate. Vo ovoj slu~aj, meѓutoa, mo`ete da se

1310

Da se razmisluva vo Java

Brus Ekel

zapra{ate: Â [to najlo{o mo`e da se slu~i ako sodr`inata na promenlivata cSize se promeni vo tek na izvr{uvaweto na metodot paintComponent()?° Ako zaklu~ite deka toa {to mo`e da se slu~i ne e taka stra{no, a pri toa e i minlivo, mo`ete da go ostavite metodot paintComponent() nesinhroniziran za da izbegnete dopolnitelni re`iski tro{oci koi gi predizvikuva povikuvaweto na sinhroniziraniot metod. 3. Dali verzijata na metodot vo osnovnata klasa e sinhronizirana? Metodot paintComponent() ne e sinhroniziran vo osnovnata klasa. Toa ne e ba{ besprekoren argument tuku samo povod za razmisluvawe. Vo ovoj slu~aj, da re~eme, postoi edno pole (cSize) koe go modificira sinhroniziraniot metod, a nemu mu pristapuva metodot paintComponent(), pa toa mo`e{e da ja promeni situacijata. Imajte predvid, meѓutoa, deka atributot synchronized ne se nasleduva - zna~i, dokolku nekoj metod e sinhroniziran vo osnovnata klasa, toj ne stanuva avtomatski sinhroniziran vo redefiniranata verzija na izvedenata klasa. 4. Metodite paint() i paintComponent() moraat da bidat kolku {to e mo`no pobrzi. Isklu~itelno se prepora~uva koristewe na sé {to od niv gi eliminira re`iskite tro{oci, pa ako smetate deka tie metodi treba da gi sinhronizirate, toa mo`e da bide znak za lo{ proekt. Kodot za testirawe vo metodot main() e poinakov od onoj vo programata BangBeanTest, za da se poka`e sposobnosta na klasata BangBean2 za nastanite da izvestuva pove}e priemnici.

Pakuvawe na zrnoto Pred zrnoto da se uveze vo vizuelnata alatka, mora da se stavi vo standarden paket za zrna, a toa e JAR arhivata koja gi sodr`i site klasi na zrna i manifestot na datoteki. Manifestot na datoteki e tekstualna datoteka so odreden oblik. Za zrnoto BangBean taa datoteka izgleda ovaka: Manifest-Version: 1.0 Name: bangbean/BangBean.class Java-Bean: True

Prviot red go prika`uva brojot na verzijata na manifest datotekata koj, do natamo{no izvestuvawe od kompanijata Sun, iznesuva 1.0. Vtoriot red (praznite redovi se zanemaruvaat) ja naveduva datotekata BangBean.class, a tretiot ka`uva ÂToa e zrno°. Bez tretiot red, alatkata za pravewe na programata ne bi ja prepoznala klasata na zrnoto. Edinstvena nepovolnost e toa {to morate da obezbedite pravilna pateka vo poleto Name:. Ako povtorno ja poglednete programata BangBean.java, }e

Grafi~ki korisni~ki opkru`uvawa

1311

vidite deka se naoѓa vo paketot bangbean (zna~i vo podimenikot bangbean koj ne e vo patekata na klasata), a imeto na manifest datotekata mora da sodr`i informacii za paketot. Osven toa, manifest datotekata morate da ja smestite vo imenikot nad korenot na patekata na paketot, {to vo ovoj slu~aj zna~i deka taa datoteka treba da se smesti vo imenikot nad podimenikot bangbean. Potoa treba da ja povikate programata jar vo istiot imenik vo koj se naoѓa manifest datotekata, kako tuka:

Jar cmf BengBean.jar BengBean.mf bangbean Ova podrazbira deka sakate dobienata JAR datoteka da se vika BangBean.jar i manifest datotekata da se vika BangBean.mf. Mo`ebi se pra{uvate {to se slu~uva so site drugi klasi koi se generiraat pri preveduvawe na programata BangBean.java. Tie zavr{uvaat vo podimenikot bangbean, a }e zabele`ite deka posledniot argument na prethodnata komandna linija e ba{ toj podimenik. Koga na programata jar }e i go dadete imeto na nekoj podimenik, toj go pakuva celiot toj podimenik (vklu~uvaj}i ja, vo ovoj slu~aj, i originalnata datoteka so izvorniot kod na programata BangBean.java; vie mo`ebi }e odlu~ite izvorniot kod da ne go pakuvate zaedno so zrnata). Pokraj toa, ako ja otpakuvate JAR arhivata koja e ba{ napravena, }e otkriete deka manifest datotekata ne se naoѓa vo paketot, tuku programata jar napravila sopstvena datoteka koja delumno se temeli na va{ata, a se vika MANIFEST.MF i se naoѓa vo podimenikot META-INF (kratenka za metainformaciite). Koga }e ja otvorite taa datoteka, }e zabele`ite i deka alatkata jar dodala informacii za digitalniot potpis na sekoja datoteka vo sledniot oblik: Digest-Algorithms: SHA MD5 SHA-Digest: pDpEAG9Naecx8aFtqPU4udsx/00= MD5-Digest: 04NcS1hE3Smnz1p2Hhj6qeg==

Za ova glavno ne morate da vodite smetka, a ako ne{to menuvate, mo`ete samo da ja promenite prvobitnata manifest datoteka i povtorno da ja povikate alatkata jar za da napravite nova arhiva. Vo JAR arhivata mo`ete da dodadete i novi zrna taka {to informaciite za niv }e gi stavite vo manifest datotekata. Dobro e sekoe zrno da se stavi vo sopstven podimenik, zatoa {to koga ja pravite arhivata mo`ete da go arhivirate celiot imenik. Se gleda deka i Frog i BangBean imaat sopstveni podimenici. Koga pravilno }e go smestite zrnoto vo arhivata, mo`ete da go vnesete vo alatkata za izrabotka na programata koja poddr`uva zrna. Na~inot na koj toa se pravi se razlikuva od alatka do alatka, no kompanijata Sun obezbeduva besplatno opkru`uvawe za testirawe na Java zrnata koe se vika BeanBuilder. (Mo`ete da go prezemete od sajtot http://java.sun.com/beans). Za da go smestite

1312

Da se razmisluva vo Java

Brus Ekel

zrnoto vo BeanBuilder, kopirajte ja negovata JAR datoteka vo soodvetniot imenik. Ve`ba 36: (4) Dodadete ja datotekata Frog.class vo manifest datotekata kako {to e prika`ano vo ova poglavje i startuvajte ja programata jar za da napravite JAR arhiva koja gi sodr`i zrnata Frog i BangBean. Potoa od Internet prezemete i instalirajte BeanBuilder ili upotrebete svoja alatka za pravewe programa koja poddr`uva zrna. Dodadete nova arhiva vo toa opkru`uvawe za da mo`ete da gi testirate tie dve zrna. Ve`ba 36: (4) Napravete sopstveno zrno Valve koe sodr`i dve svojstve: logi~ki tip on i celobroen tip level. Napravete manifest datoteka, koristete ja programata jar za da go pakuvate zrnoto, a potoa povikajte go nego vo BeanBuilder ili upotrebete svoja alatka za pravewe programa koja poddr`uva zrna, taka {to }e mo`ete da go testirate.

Poslo`ena poddr{ka za zrnata Gledate kolku e ednostavno da se napravi zrno. Meѓutoa, ne ste ograni~eni samo na ona {to tuka e prika`ano. Arhitekturata na zrnata na Java obezbeduva lesen po~etok, no mo`e da poslu`i i vo poslo`eni situacii koi gi nadminuvaat ramkite na ovaa kniga i }e bidat nakratko izlo`eni. Pove}e detali }e doznaete na sajtot java.sun.com. Svojstvata na zrnata mo`at da se podobrat. Vo prethodniot primer se prika`ani samo poedine~nite svojstva, no mo`no e da se pretstavat i pove}e svojstva vo oblik na niza. Toa se narekuva indeksirano svojstvo. Vie obezbeduvate samo soodvetni metodi (sekako, po~ituvaj}i gi pravilata za dodeluvawe imiwa na metodite), a objektot na klasata Introspector go prepoznava indeksnoto svojstvo taka {to alatkata za pravewe aplikacii mo`e da reagira na soodveten na~in. Svojstvata mo`at da bidat povrzani (angl. bound), {to zna~i da gi izvestuvaat drugite objekti za promenite so pomo{ na nastani od tipot PropertyChangerEvent. Drugite objekti potoa mo`at da odlu~at dali }e se promenat vrz osnova na promenata na zrnoto. Svojstvata mo`at da bidat ograni~eni (angl. constrained), {to zna~i deka drugite objekti mo`at da ja zabranat promenata na nekoe svojstvo ako e neprifatliva. Drugite objekti se izvestuvaat so pomo{ na nastani od tipot PropertyChangerEvent, a mo`at da generiraat isklu~ok od tip PropertyVetoException za da ja spre~at promenata i da gi vratat starite vrednosti. Mo`no e i da se menuva na~inot na pretstavuvawe na zrnoto vo tek na proektiraweto:

Grafi~ki korisni~ki opkru`uvawa

1313

1. Mo`ete da obezbedite namenski spisok na svojstvata za odredeno zrno. Obi~niot spisok na svojstva }e se koristi za site ostanati zrna, no va{iot spisok avtomatski }e se povikuva koga }e se izbira va{eto zrno. 2. Mo`ete da napravite namenska klasa za prilagoduvawe na odredeno svojstvo (taka {to da se koristi obi~niot spisok na svojstva, no koga se menuva specijalno svojstvo, avtomatski }e se povikuva va{ata klasa). 3. Za zrnoto mo`ete da obezbedite namenska klasa od tipot BeanInfo koja dava informacii razli~ni od onie koi gi pravi Introspector. 4. Mo`ete da vklu~uvate i isklu~uvate napreden re`im vo site objekti na klasata FeatureDescriptor za da se razlikuvaat osnovnite i poslo`enite mo`nosti.

Pove}e za zrnata Mnogumina pi{uvaa za zrnata na Java, na primer Elliote Rusty Harold e avtor na knigata JavaBeans (IDG,1998).

Alternativi za Swing Iako bibliotekata Swing GKO e alatka koja ja prepora~uva Sun, toa nikako ne zna~i deka ne postojat i drugi alatki za pravewe grafi~ki korisni~ki opkru`uvawa. Dve va`ni alternativi se Flash na kompanijata Adobe vo koj za pravewe klientski GKO preku Web se koristi Flash-oviot sistem za programirawe Flex, i bibliotekata za otvoren izvoren kod Eclipse Standard Widget Toolkit (SWT) za aplikacii nameneti za персоналните kompjuteri. Zo{to bi koristele alternativi? Za Web klientite mo`e prili~no uverlivo da se tvrdi deka apletite ne uspeale. Iako postoeja od po~etokot i iako za niv mnogu se zboruva{e i vetuva{e, denes e iznenaduvawe koga ~ovek }e naide na Web aplikacija koja koristi apleti. Duri ni Sun ne koristi sekade apleti. Eve primer: http://java.sun.com/developer/onlineTraining/new2java/javamap/intro.html Iako interaktivnata mapa na Java mo`nostite na Sun-oviot sajt e mnogu dobar kandidat za aplet, tie ja napravile vo Flash. Izgleda deka toa e premol~eno priznanie deka apletite ne uspeale. U{te pova`no e toa {to Flash Player e instaliran na preku 98 procenti kompjuterski platformi, pa mo`e da se smeta za prifaten standard. Kako {to }e vidite, sistemot Flex obezbeduva mnogu mo}no opkru`uvawe za programirawe klientski aplikacii, sekako mnogu pojaki od JavaScript, a negoviot izgled i odnesuvawe ~esto se podobri od apletite. Dokolku sepak sakate da koristite apleti, vi

1314

Da se razmisluva vo Java

Brus Ekel

ostanuva da go ubedite klientot od Web da prezeme JRE koj e mnogu pogolem i podolgo se prezema od Flash Player. Za personalnite aplikacii, eden od problemite so Swing e toa {to korisnicite zabele`uvaat deka koristat drug vid aplikacija, bidej}i izgledot i odnesuvaweto na Swing-ovite aplikacii se razlikuva od onie voobi~aenite na персоналните kompjuteri. Korisnicite po pravilo ne sakaat sekoja aplikacija da izgleda i da se odnesuva poinaku; tie se trudat {to pobrgu da ja zavr{at svojata rabota i se trudat site aplikacii da izgledaat i da se odnesuvaat isto. SWT pravi aplikacii koi izgledaat kako mati~ni, a bidej}i taa biblioteka koristi mati~ni komponenti kolku {to e toa mo`no, tie aplikacii obi~no se izvr{uvaat pobrzo od ekvivalentnite Swing aplikacii.

Pravewe klientski Flash Web so pomo{ na Flex Bidej}i lesnata virtuelna ma{ina Flash na kompanijata Adobe e {iroko rasprostraneta, pove}eto luѓe mo`at bez nikakva instalacija da go koristat opkru`uvaweto zasnovano na Flash, a toa }e izgleda i }e se odnesuva isto na site sistemi i platformi.113 Za razvoj na korisni~kite Flash opkru`uvawa za Java aplikaciite, mo`ete da go upotrebite sistemot Flex na kompanijata Adobe. Flex se sostoi od programski model ~ija osnova ja so~inuvaat XML i jazik za pi{uvawe skriptovi, sli~ni na programskite modeli HTML i JavaScript, i robusni biblioteki na komponenti. Za deklarirawe na kontrolnite objekti i upravuvawe so rasporedot na komponentite se koristi sintaksata MXML, a dinami~kite skriptovi se upotrebuvaat za dodavawe kod za obrabotka na nastanite i povikuvawe uslugi, koi korisni~koto opkru`uvawe go povrzuvaat so klasite na Java, modelite podatoci, Web uslugite itn. Flexoviot preveduva~ go preveduva MXML i skriptot na datotekata vo bajtkod. Flash-ovata virtuelna ma{ina na klientskiot kompjuter raboti kako virtuelna ma{ina na Java (JVM) dotolku {to go interpretira prevedeniot bajtkod. Formatot na Flash-oviot bajtkod e nare~en SWF; SWF datotekite gi proizveduva Flex-oviot preveduva~. Vodete smetka za toa deka postoi alternativa na Flex na adresata http://openlaszlo.org; nejziniot izvoren kod e otvoren i strukturite se sli~ni na Flex, pa nekomu mo`e podobro da mu poslu`i. Postojat i drugi alatki za pravewe Flash aplikacii na razli~ni na~ini.

113

Jadroto na materijalot vo ovoj oddel go napravi [on Nevil (Sean Neville).

Grafi~ki korisni~ki opkru`uvawa

1315

Zdravo, Flex Pro~itajte go ovoj MXML kod koj go definira korisni~koto opkru`uvawe (imajte predvid deka prviot i posledniot red gi nema vo kodot {to go prezemate vo paketot na izvorniot kod na ovaa kniga): //: gui/flex/zdravoflex1.mxml

MXML datotekite se XML dokumenti, pa zatoa po~nuvaat so opis na XML verzija i kodirawe; toa se atributi na version i encoding. Krajniot nadvore{en MXML element e Application koj vizuelno se naoѓa na vrvot i e logi~ki kontejner za Flex korisni~koto opkru`uvawe. Vo elementot Application mo`ete da deklarirate oznaki koi pretstavuvaat vizuelni kontroli kako {to e gorniot element Natpis. Kontrolite sekoga{ gi smestuvame vo kontejneri, a kontejnerot pokraj ostanatite mehanizmi go kapsulira i rasporeduva~ot (angl. layout manager) koj upravuva so rasporedot na kontrolite vo kontejnerot. Vo najednostaven slu~aj, kako vo gorniot primer, Application deluva kako kontejner. Podrazbiraniot rasporeduva~ na elementot Application gi smestuva kontrolite vertikalno niz prozorecot, so redosled po koj bile deklarirani. ActionScript e verzija na ECMAScript ili na JavaScript, koja potpolno li~i na Java i gi poddr`uva klasite i strogata proverka na tipovite, kako i dinami~koto pravewe skriptovi. Koga na primerot }e mu dodademe skript, }e vovedeme odnesuvawe. Ovde MXML kontrolata Script go smestuva ActionScript neposredno vo MXML datotekata: //: gui/flex/zdravoflex2.mxml 114

Navedenata adresa pove}e ne e dostapna. Pove}e informacii za MXML }e pronajdete na adresata www.adobe.com/devnet/flex/mxml_as.html.

1316

Da se razmisluva vo Java

Brus Ekel



TextInput kontrolata go prima vnesot na korisnikot, a Natpis (u{te vo tek na vnesot) gi prika`uva vnesenite podatoci. Vodete smetka za toa deka atributot id na sekoja kontrola vo skriptot e dostapen kako ime na promenlivata, pa skript mo`e da gi referencira MXML instancite na oznakite. Vo poleto TextInput gledate deka atributot change e povrzan so funkcijata updateOutput() - zna~i, taa funkcija se povikuva sekoga{ koga }e se slu~i nekoja promena (angl. change).

Preveduvawe na MXML Najdobro e od adresata www.adobe.com/products/flex/trial da ja prezemete besplatnata probna verzija na Flex.115 Toj proizvod postoi vo pove}e izdanija - od besplatni probni do serverski za golemi pretprijatija - a za razvoj na Flex aplikaciite Adobe nudi u{te nekoi alatki. Bidej}i izdanijata postojano se menuvaat, pro~itajte gi poedinostite na Web sajtot na proizvoditelot Adobe. Isto taka, imajte predvid deka mo`ebi }e morate da ja modificirate datotekata jvm.config vo imenikot bin na Flex-ovata instalacija. Za preveduvawe na MXML kodot vo Flash-ov bajtkod imate dve opcii: 1. MXML datoteka mo`ete da ja smestite vo nekoja Java Web aplikacija, pokraj JSP i HTML stranicite vo WAR datotekata, i da dadete za vreme na izvr{uvaweto barawata za .mxml datotekata da se preveduvaat sekoga{ koga bilo koj prelistuva~ }e ja pobara URL adresata na toj MXML dokument. 2. MXML datotekata mo`ete da ja prevedete so pomo{ na Flex-oviot preveduva~ot mxmlc koj se startuva od komandnata linija. Prvata opcija, preveduvawe na Web za vreme na izvr{uvaweto, osven Flex bara i nekoj kontejner servleti (kako {to e Tomcat na Apache). WAR datotekite na kontejnerite servleti moraat da bidat a`urirani so pomo{ na informacii od Flex-ovata konfiguracija, kako {to se mapirawata na servletite dodadeni na deskriptorot web.xml, i moraat da gi opfatat Flexovite JAR datoteki - seto toa se izvr{uva avtomatski koga instalirate Flex. Po konfigurirawe na WAR datotekata, MXML datotekite mo`ete da gi 115

Vnimavajte - treba da prezemete Flex, a ne FlexBuilder , {to e alatka za proektirawe na programata.

Grafi~ki korisni~ki opkru`uvawa

1317

smestite vo Web aplikacija i da ja pobarate URL adresata na toj dokument so koj bilo prelistuva~. Flex }e ja prevede aplikacijata po prvoto takvo barawe, sli~no kako vo modelot na serverskite stanici na Java (JSP), i potoa }e ispora~uva preveden i ke{iran SWF vo HTML {kolkata. Vo vtorata opcija server ne e potreben. SWF datotekite gi pravite so povik na Flex-oviot preveduva~ mxmlc na komandnata linija. Niv mo`ete da gi upotrebite kako {to sakate. Izvr{nata datoteka mxmlc e vo imenikot bin na Flex-ovata instalacija i koga }e ja povikate bez argument, }e ispi{e spisok validni opcii na komandnata linija. Obi~no sajtot na Flex-ovata biblioteka klientski komponenti se zadava kako vrednost na opcijata -flexlib, no vo mnogu ednostavni slu~ai kako {to se dvata prethodni, Flex -oviot preveduva~ }e pretpostavi kade e bibliotekata komponenti. Zatoa prvite dva primera mo`ete da gi prevedete vaka: mxmlc.exe zdravoflex1.mxml mxmlc.exe zdravoflex2.mxml

So toa se proizveduva datotekata zdravoflex2.swf koja mo`e da se startuva vo Flash ili da se smesti vo HTML na nekoj HTTP server. (Po v~ituvaweto na Flash vo prelistuva~ot na Web, ~esto e dovolno dva pati da se pritisne SWF datotekata za da ja startuvate vo prelistuva~ot). Koga }e go startuvate zdravoflex2.swf vo Flash Player }e go vidite slednoto korisni~ko opkru`uvawe: This was not hard to do… Hello! This was not too hard to do… Vo poslo`enite aplikacii mo`ete da gi razdelite MXML i ActionScript taka {to funkciite }e gi referencirate vo nadvore{nite datoteki. Vo MXML upotrebete ja slednata sintaksa za kontrolata Script:

Toj kod ovozmo`uva MXML kontrolite da gi referenciraat funkciite smesteni vo datotekata MojotNadvoresenSkript.as kako da se smesteni vo samata taa MXML datoteka.

MXML i ActionScript MXML e deklarirana stenografija za ActionScript klasite. Za sekoja MXML oznaka postoi istoimena ActionScript klasa. Koga Flex-oviot preveduva~ leksi~ki go analizira (ras~lenuva i razre{uva) MXML, prvo go transformira vo XML i gi v~ituva referenciranite ActionScript klasi, a potoa go preveduva i povrzuva toj ActionScript vo SWF datotekite.

1318

Da se razmisluva vo Java

Brus Ekel

Celata Flex aplikacija mo`ete da ja napi{ete vo samiot ActionScript, a voop{to da ne go upotrebite MXML. Zna~i, MXML ne e neophoden, no e soodveten. MXML obi~no se upotrebuva za deklarirawe na komponentite na korisni~koto opkru`uvawe kako {to se kontejnerite i kontrolite, dodeka ActionScript i Java se koristat za obrabotka na nastanite i ostanatata klientska logika. Imate mo`nost da pravite sopstveni MXML kontroli i da gi referencirate vo ActionScript klasite. Postoe~kite MXML kontejneri i kontroli mo`ete da gi kombinirate vo nov MXML dokument koj mo`e da bide referenciran kako oznaka vo drugite MXML dokumenti. Pove}e informacii za toa pobarajte na Web sajtot na kompanijata Adobe.

Kontejneri i kontroli Vizuelnoto jadro na bibliotekata Flex komponenti e zbir kontejneri koi upravuvaat so rasporedot i nizata kontroli koi odat vo tie kontejneri. Pomeѓu kontejnerite se paneli, vertikalni i horizontalni pravoagolnici, pravoagolnici koi se slo`uvaat kako plo~ki, pravoagolnici koi se {irat kako harmonika, pravoagolnici so vnatre{nata mre`a, tabeli itn. Kontrolite se spravi~ki (angl. widgets) na korisni~koto opkru`uvawe kako {to se kop~iwa, tekstualni poliwa, lizga~i, kalendari, tabeli so podatoci itn. Sega }e napravime Flex aplikacija koja prika`uva i ureduva lista audio datoteki. ]e vidite primeri na kontejneri i kontroli i }e otkriete kako od Flash da gi povrzete so Java. Na po~etok na MXML datotekata }e postavime kontrola DataGrid (koja spaѓa vo posofisticiranite Flex kontroli) vo kontejner od tipot Panel: //: gui/flex/pesni.mxml

Kontejnerot od tip DataGrid sodr`i vgnezdeni oznaki za svojata niza koloni. Sekoj atribut ili vgnezden element na kontrolata odgovara na nekoe

1320

Da se razmisluva vo Java

Brus Ekel

svojstvo, nastan ili kapsuliran objekt na pripaѓa~kata ActionScript klasa. Toj DataGrid ima atribut id ~ija vrednost e tabelaNaPesni, pa ActionScript i MXML oznakite mo`at programski da ja referenciraat taa tabela koristej}i ja tabelaNaPesni kako ime na promenlivata. DataGrid eksponira mnogu pove}e svojstva otkolku {to tuka prika`av; celokupniot API za MXML kontrolite i kontejnerite mo`ete da go najdete na adresata http://livedocs.adobe.com/flex/1/asdocs. Pozadi kontejnerot DataGrid sleduva VBox so element Slika koj ja poka`uva prednata strana na albumot i podatoci za pesnata, kako i so kontrola MediaPlayback za reprodukcija na MP3 datoteka. Vo ovoj primer sodr`inata se emitira vo realno vreme, za da se namali prevedenata SWF datoteka. Dokolku slikite, audio i video datotekite gi vgradite vo Flex aplikacija namesto da gi emitirate vo realno vreme, tie datoteki stanuvaat del od prevedeniot SWF i se ispora~uvaat zaedno so korisni~koto opkru`uvawe; vo toj slu~aj, vo vremeto na izvr{uvawe nema emitirawe vo realnoto vreme na baraweto. Flash pleerot sodr`i vgradeni kodeki za reprodukcija i emitirawe na audio i video datoteki od razni formati vo realno vreme. Flash i Flex gi poddr`uvaat najkoristenite formati na sliki na Web, a Flex umee da gi konvertira datotekite na skalabilnite vektorski grafiki (SVG) vo SWF resursi koi mo`at da se vgradat vo Flex klientite.

Efekti i stilovi Flash pleerot iscrtuva grafika vektorski, pa vo vremeto na izvr{uvawe mo`e da izvr{i mnogu izraziti transformacii. Flex-ovite efekti ovozmo`uvaat da stekneme uvid vo takvite animacii. Efektite se transformacii koi so pomo{ na MXML sintaksa mo`ete da ja primenite na kontrolite i kontejnerite. Oznakata Effect prika`ana vo prethodniot MXML kod proizveduva dva rezultata: prvata vgnezdena oznaka dinami~ki ja zgolemuva slikata koga gluv~eto se naoѓa nad nea, a vtorata dinami~ki ja namaluva koga gluv~eto }e se trgne od nea. Tie efekti se primenuvaat na nastanite na gluv~eto dostapni za kontrolata Slika nare~ena slikaNaAlbumot. Flex ima efekti i za voobi~aenite animacii kako {to se preminite, prebri{uvawata i modulira~kite alfa kanali. Pokraj vgradenite efekti, Flex go poddr`uva i Flash-oviot API za crtawe na navistina inovativni animacii. Podlabokoto istra`uvawe na ovaa tema gi opfa}a grafi~kiot dizajn i animacijata i go nadminuva obemot na ovoj oddel. Flex gi poddr`uva kaskadnite opisi na stilovite (Cascading Style Sheets, CSS), pa zna~i i standardnite stilovi. Ako na MXML datoteka i pridru`ite CSS datoteka, Flex kontrolite }e se pridr`uvaat na tie stilovi. Vo ovoj primer,

Grafi~ki korisni~ki opkru`uvawa

1321

kaskadniot opis na stilovite stiloviNaPesni ja sodr`i slednata CSS deklaracija: //: gui/flex/stiloviNaPesni.mxml .headerText { font-family: Arial, "_sans"; font-size: 16; font-weight: bold; } .boldText { font-family: Arial, "_sans"; font-size: 11; font-weight: bold; } ///:~

Aplikacijata na bibliotekata pesni ja uvezuva taa datoteka i ja upotrebuva preku oznakata Style vo MXML datotekata. Po uvoz na opisite na stilovite, negovite deklaracii mo`at da se primenat na Flex kontrolite vo MXML datotekata. Na primer, deklaracijata boldText od opisot na stilovi ja upotrebuva kontrolata TextArea ~ij identifikator (id) e podatociZaPesnata.

Nastani Korisni~koto opkru`uvawe e ma{ina na sostojbata; toa gi izvr{uva rabotite koga se menuva sostojbata. Vo Flex tie promeni se prijavuvaat so pomo{ na nastanite. Flex-ovata biblioteka klasi sodr`i mno{tvo najrazli~ni kontroli koi poddr`uvaat mno{tvo nastani za site aspekti na dvi`ewe na gluv~eto i koristewe na tastaturata. Za primer, atributot click na elementot Button pretstavuva eden od nastanite dostapni za taa kontrola. Vrednosta dodelena na atributot click mo`e da bide nekoja funkcija ili vmetnat skript. Na primer, vo gornata MXML datoteka elementot ControlBar sodr`i kopceOsveziGiPesnite za osve`uvawe na listata pesni. Od oznakata gledate deka nastanot click predizvikuva povik na metodot uslugaNaPesnite.dajPesni(). Vo toj primer nastanot click na kop~eto Button go referencira RemoteObject (oddale~en objekt) koj odgovara na toj Java metod.

Povrzuvawe so Java Oznakata RemoteObject na krajot na MXML datotekata vospostavuva vrska so nadvore{nata Java klasa gui.flex.uslugaNaPesnite. Spomenatiot Flex klient - so metodot dajPesni() na taa Java klasa - pribavuva podatoci za DataGrid. Za da mo`e da funkcionira, mora da izgleda kako usluga - krajna to~ka so koja klientot mo`e da razmenuva poraki. Uslugata definirana vo oznakata RemoteObject ima atribut source koj go nazna~uva Java klasata na oznakata 1322

Da se razmisluva vo Java

Brus Ekel

RemoteObject i ja specificira ActionScript povratnata funkcija onPesni(), koja }e bide povikana koga Java metodot }e se vrati. Vgnezdenata oznaka method go deklarira metodot dajPesni(), {to toj Java metod go pravi dostapen na ostatokot od Flex aplikacijata. Vo Flex site povici na uslugite se vra}aat asinhrono, preku nastanite koi gi predizvikuvaat tie povratni funkcii. Vo slu~aj na gre{ka, istiot RemoteObject prika`uva dijalog na trevoga. Metodot dajPesni() sega mo`eme da go povikame od Flash so pomo{ na ActionScript: uslugaNaPesnite . dajPesni();

Poradi konfiguracijata na MXML so toa }e bide povikan metodot dajPesni() vo klasata UslugaNaPesnite: //: gui/flex/UslugaNaPesnite.java package gui.flex; import java.util.*; public class UslugaNaPesnite { private List pesni = new ArrayList(); public UslugaNaPesnite() { popolniProbniPodatoci(); } public List dajPesni() { return pesni; } public void dodajPesna(Pesna pesna) { pesni.add(pesna); } public void otstraniJaPesnata(Pesna pesna) { pesni.remove(pesna); } private void popolniProbniPodatoci() { dodajPesna(new Pesna("Chocolate", "Snow Patrol", "Final Straw", "sp-final-straw.jpg", "chocolate.mp3")); dodajPesna(new Pesna("Koncert br. 2 vo E-dur", "Hilary Hahn", "Bach: violinski koncert", "hahn.jpg", "bachviolina2.mp3")); dodajPesna(new Pesna("'Round Midnight", "Wes Montgomery", "The Artistry of Wes Montgomery", "wesmontgomery.jpg", "roundmidnight.mp3")); } } ///:~

Sekoj objekt od tipot Pesna e samo kontejner na podatoci: //: gui/flex/Pesna.java package gui.flex; public class Pesna implements java.io.Serializable { private String naslov; private String izveduvac; private String album; private String urlSlikiNaAlbumot; private String urlNosaciNaZvukot; public Pesna() {}

Grafi~ki korisni~ki opkru`uvawa

1323

public Pesna(String naslov, String izveduvac, String album, String urlSlikiNaAlbumot, urlNosaciNaZvukot) { this.ime = ime; this.izveduvac = izveduvac; this.album = album; this.urlSlikiNaAlbumot = urlSlikiNaAlbumot; this.urlNosaciNaZvukot = urlNosaciNaZvukot; } public void setAlbum(String album) { this.album = album;} public String getAlbum() { return album; } public void setUrlSlikiNaAlbumot (String urlSlikiNaAlbumot) { this. urlSlikiNaAlbumot = urlSlikiNaAlbumot; } public String getUrlSlikiNaAlbumot() { return urlSlikiNaAlbumot;} public void setIzveduvac(String izveduvac) { this.izveduvac = izveduvac; } public String getIzveduvac() { return izveduvac; } public void setNaslov(String naslov) { this.naslov = naslov; } public String getNaslov() { return naslov; } public void setUrlNosaciNaZvukot(String urlNosaciNaZvukot) { this.urlNosaciNaZvukot = urlNosaciNaZvukot; } public String getUrlNosaciNaZvukot() { return urlNosaciNaZvukot; } } ///:~

Pri inicijalizacija na aplikacijata ili koga }e go pritisnete kopceOsveziGiPesnite se povikuva metodot dajPesni(), a po vra}aweto, se povikuva ActionScript za popolnuvawe na tabelata tabelaNaPesni. Sleduva listingot ActionScript koj sodr`i Script kontrola na MXML datotekata: //: gui/flex/skriptNaPesnite.as function dajPesni() { uslugaNaPesnite.dajPesni(); } function izberiPesna(nastan) { var pesna = tabelaSoPesni.getItemAt(nastan.itemIndex); prikaziPodatociZaPesnata(pesna); } function prikaziPodatociZaPesnata(pesna) { podatociZaPesnata.tekst = pesna.naslov + newline; podatociZaPesnata.tekst += pesna.izveduvac + newline; podatociZaPesnata.tekst += pesna.album + newline; slikaNaAlbumot.source = pesna.urlSlikiNaAlbumot; pleerZaPesni.contentPath = pesna.urlNosaciNaZvukot; pleerZaPesni.visible = true; }

1324

Da se razmisluva vo Java

Brus Ekel

function onPesni(pesni) { tabelaSoPesni.dataProvider = pesni; } ///:~

Za da go obrabotime izborot na }eliite DataGrid, atributot na nastanite cellPress go dadavame na deklaracijata na elementot DataGrid vo MXML datotekata:

cell Press="izberiPesna(nastan)" Koga korisnikot }e pritisne pesna vo tabelata DataGrid }e go povika metodot izberiPesna() vo gorniot ActionScript.

Modeli podatoci i povrzuvawe na podatocite Kontrolite mo`at neposredno da povikuvaat uslugi, a povratnite povici na ActionScript nastanite davaat prilika programski da gi a`urirate vizuelnite kontroli koga uslugite }e gi vratat podatocite. Iako skriptot za a`urirawe na kontrolite e ednostaven, znae da stane obemen i zamoren, a negovite funkcii se tolku voobi~aeni {to Flex avtomatski upravuva so toa odnesuvawe taka {to gi povrzuva podatocite. Vo svojot najednostaven oblik, povrzuvaweto na podatocite i ovozmo`uva na kontrolata podatocite da gi referencira neposredno namesto so nekoj {ablonski kod da gi kopira podatocite vo kontrolata. Pri a`urirawe na podatocite, avtomatski se a`urira i kontrolata koja gi referencira, bez nikakva intervencija na programerot. Infrastrukturata na Flex to~no odgovara na nastanite na promena na podatocite i gi a`urira site kontroli koi se povrzani so tie podatoci. Ova e ednostaven primer na sintaksa na povrzuvawe na podatocite:

Podatocite gi povrzuvate koga }e gi smestite referencite vo golemi zagradi. Seto vnatre vo tie golemi zagradi Flex go smeta za izraz koj treba da se presmeta. Vrednosta na prvata kontrola, na elementot Slider (lizga~), ja prika`uva druga kontrola - edno tekstualno pole. So promena na vrednosta na lizga~ot, svojstvoto tekst na tekstualnoto pole avtomatski se a`urira. Na toj na~in, programerot ne mora da gi obrabotuva nastanite na promena na vrednosta na elementot Slider za da go a`urira tekstualnoto pole. Ima i posofisticirani kontroli, kako {to se Tree (steblo) i DataGrid vo aplikacijata na bibliotekata na pesnite. Tie kontroli imaat svojstvo dataprovider koe go olesnuva povrzuvaweto so kolekcijata podatoci. Grafi~ki korisni~ki opkru`uvawa

1325

ActionScript funkcijata na onPesni() prika`uva kako metodot UslugaNaPesnite.dajPesni() e povrzan so svojstvoto dataprovider na Flex-oviot element DataGrid. Kako {to e deklarirano vo oznakata RemoteObject na MXML datotekata, taa povratna funkcija ja povikuva ActionScript koga Java metodot }e se vrati. Posofisticirana primena na poslo`en model podatoci, kako {to e intranet aplikacijata koja upotrebuva objekti za prenos na podatoci (Data Transfer Objects) ili dostavuva~i na poraki ~ii podatoci se uskladeni so poslo`eni {emi, mo`e da pottikne natamo{no razdeluvawe na izvorot na podatoci od kontrolata. Vo razvojot na Flex programata, toa razdeluvawe go postignuvame so deklarirawe na objektot na Âmodelot°, {to e generi~ki MXML kontejner na podatoci. Toj model ne sodr`i logika. Toj e ekvivalenten na objektot za prenos na podatoci kakov se sretnuva pri razvojot na intranet programite i na soodvetni strukturi vo ostanatite programski jazici. Po toj model, gi povrzuvame podatocite na kontrolite so modelot i istovremeno modelot gi povrzuva svoite svojstva so vlezovite i izlezite na uslugi. So toa izvorite na podatoci, uslugite, se razdeluvaat od vizuelnite potro{uva~i na podatoci, so {to se olesnuva koristeweto na obrazecot model-prikaz-kontroler (Model-View-Controller, MVC). Vo pogolemite, posofisticirani aplikacii, po~etnoto zgolemuvawe na slo`enosta poradi vmetnuvawe na modelot, ~esto se isplatuva zatoa {to se dobiva MVC aplikacija so jasno razdeleni podatoci od kontrolite. Osven Java objektite, Flex so pomo{ na kontrolata Web Service odnosno Http Service znae da pristapuva i na Web uslugite ~ija osnova ja so~inuva SOAP t.e. RESTful na HTTP uslugite. Pristapuvaweto na site uslugi podle`i na bezbednosni ograni~uvawa na proverka na identitetot.

Izgradba i primena Vo prethodnite primeri mo`evme da se izvle~eme bez indikatorot -flexlib na komandnata linija, no za da ja sprovedeme ovaa programa, so indikatorot flexlib morame da go spegificirame mestoto na datotekata flex-config.xml. Slednata komanda odgovara na mojata instalacija, a vie }e morate da ja modificirate vo sklad so sopstvenata konfiguracija. (Komandata se pi{uva vo eden red koj poradi dol`inata prodol`uva i vo sledniot): //:! gui/flex/build-command.txt mxmlc -flexlib C:/"Programa Files"/Adobe/Flex/jrun4/servers/default/flex/ WEB-INF/flex pesni.mxml ///:~

Taa komanda }e izgradi aplikacija vo oblik na SWF datoteka koja mo`ete da ja prika`ete vo prelistuva~ot na Web, no bidej}i vo datotekata za distribucija na kodot na ovaa kniga nema ni MP3 datoteka nitu JPG slika, koga }e ja startuvate aplikacijata nema da ~uete nitu edna pesna nitu }e gi

1326

Da se razmisluva vo Java

Brus Ekel

vidite obvivkite na albumite, tuku samo osnovnata struktura (angl. framework). Pokraj toa, morate da konfigurirate nekoj server za od Flex aplikacijata da mo`ete da komunicirate so Java datotekite. Flex-oviot proben paket opfa}a i server JRun, a nego po instalacijata na Flex mo`ete da go startuvate ili koristej}i menija na operativniot sistem, ili od komandnata linija:

j run -start default Proverete dali serverot e uspe{no startuvan taka {to vo prelistuva~ot Web }e otvorite http://localhost:8700/samples i }e prika`ete razni primeroci (angl. samples). Toa e dobar na~in za zapoznavawe na mo`nostite na Flex. Namesto aplikacijata da ja preveduvate na komandnata linija, mo`ete da ja prevedete so posredstvo na serverot. Toa se pravi taka {to izvornite datoteki na pesnite, CSS opisite na stilovi itn. }e gi smestite vo imenikot jrun4/servers/default/flex i }e im pristapite vo Web prelistuva~ot so otvorawe na adresata http://localhost:8700/flex/songs.mxml. Morate da ja konfigurirate i stranata na Java i stranata na Flex za da mo`ete da ja startuvate aplikacijata. Java: prevedenite datoteki Pesna.java i UslugaNaPesnite.java smestete gi vo imenikot WEB.INF/classes. Sprema specifikacijata J2EE, toa e mesto za WAR klasite. Drug na~in bi bil datotekite da gi pretvorite vo JAR arhivi i da gi smestite vo imenikot WEB.INF/lib. Tie mora da se naoѓaat vo imenik ~ija struktura se sovpaѓa so soodveten Java paket. Ako koristite JRun server, datotekite treba da gi smestite vo imenicite jrun4/servers/default/flex/WEBINF/classes/gui/flex/Pesna.class i jrun4/servers/default/flex/WEBINF/slasses/gui/flex/UslugaNaPesnite.class. Potrebni vi se i datoteki na sliki i MP3 audio datoteki koi }e bidat dostapni vo Web aplikacijata. (Za JRun korenski imenik na aplikacijata e jrun4/servers/default/flex.). Flex: od bezbednosni pri~ini, Flex ne mo`e da im pristapi na Java objektite dokolku toa ne mu go dozvolite taka {to }e ja modificirate datotekata flexconfig.xml. Za JRun serverot taa treba da se naoѓa vo imenikot jrun4/servers/default/flex/WEB-INF/flex/flex/-config.xml. Pronajdete ja stavkata vo taa datoteka i nejziniot oddel ; }e ja vidite slednata promena: * Grafi~ki korisni~ki opkru`uvawa

1327

--> (* --> Za da dozvolite pristap na site izvorni datoteki otstranete gi znacite koi od stavkata pravat komentar, taka {to da glasi * . Zna~eweto na ovaa i drugite stavki e opi{ano vo dokumentite za konfigurirawe na Flex. Ve`ba 37: (3) Izgradete go goreprika`aniot Âednostaven primer na sintaksa za povrzuvawe na podatocite°. Ve`ba 38: (4) Vo datotekata na kodot na ovaa kniga koja mo`e da se prezeme od Web nema ni MP3 nitu JPG datoteki navedeni vo programata UslugaNaPesnite.java. Najdete nekoja slika i pesna (MP3 odnosno JPG datoteka), izmenete ja programata UslugaNaPesnite.java taka {to }e gi sodr`i i imiwata na tie datoteki, prezemete ja od Web probnata verzija na Flex i izgradete ja gorenavedenata aplikacija.

Izrabotka SWT aplikaciii Kako {to ve}e ka`av, Swing site IO komponenti gi pravi piksel po pilsel pa zatoa mo`at da postojat site sakani komponenti, bez obzir na toa dali lokalniot operativen sistem gi ima ili gi nema. SWT gi koristi mati~nite komponenti ako OS gi ima, a go pravi samo ona {to OS go nema. Se dobiva aplikacija koja na korisnikot mu li~i na mati~na, a ~esto e i pobrza od ekvivalentnata Swing programa. Pokraj toa, SWT-iot programski model e poednostaven od Swing-oviot, {to e po`elno vo pove}eto primeni.116 Bidej}i SWT go zaposluva mati~niot OS kolku {to e toa mo`no, toj avtomatski mo`e da gi iskoristi mo`nostite na operativniot sistem koi na Swing mu se nedostapni - da re~eme, Windows go poddr`uva Âiscrtuvaweto 116

Kris Grajndstaf (Chris Grindstaff) mnogu mi pomogna pri preveduvaweto na SWT primerite i izborot informacii za SWT.

1328

Da se razmisluva vo Java

Brus Ekel

to~ki pomali od pikselot°, so koi na LCD ekranite pojasno se prika`uvaat fontovite. SWT znae da pravi duri i apleti. Ovoj oddel ne e seopfaten uvod vo SWT, tuku samo ovozmo`uva da go probate i da vidite kolku se razlikuva od Swing. ]e vidite deka ima mnogu elementi (widgeti) i deka tie prili~no lesno se koristat. Poedinostite mo`ete da gi prou~uvate vo seopfatnata dokumentacija i mnogute primeri dostapni na adresata www.eclipse.org. Za programiraweto vo SWT ve}e postojat pove}e knigi, a se pi{uvaat i novi.

Instalirawe SWT Za SWT aplikaciite potrebno e da prezemete i instalirate SWT biblioteka na proektot Eclipse. Izberete nekoj od preslikanite serveri na sajtot www.eclipse.org/downloads/. Sledete gi vrskite do tekovniot build na Eclipse i pronajdete ja komprimiranata datoteka ~ie ime zapo~nuva so swt i go sodr`i imeto na va{ata platforma (na primer, win32). Vo taa datoteka }e najdete swt.jar. Datotekata swt.jar najlesno }e ja instalirate dokolku ja smestite vo imenikot jre/lib/ext (zatoa {to vo toj slu~aj nema da morate da ja menuvate svojata pateka na klasite). Koga }e ja dekomprimirate bibliotekata SWT, mo`ebi }e najdete u{te datoteki koi treba da se instaliraat na mesta soodvetni za va{ata platforma. Na primer, Win32 distribucijata opfa}a i DDL datoteki koi treba da se smestat nekade vo java.library.path. (Obi~no taa pateka e ednakva na onaa koja ja opi{uva sistematskata promenliva PATH, no vistinskata vrednost java.library.path mo`ete da ja doznaete so pomo{ na programata object/ShowProperties.java). Koga toa }e go napravite, bi trebalo da mo`ete transparentno da preveduvate i startuvate SWT aplikacii, kako site drugi Java programi. Dokumentacijata za SWT se prezema posebno. Druga mo`nost e da instalirate programa za ureduvawe na tekstot na Eclipse; toj gi opfa}a i SWT i SWT dokumentacijata koja mo`ete da ja prika`ete so pomo{ na Eclipse-oviot sistem za pomo{.

Zdravo, SWT Da zapo~neme so najednostavnata mo`na aplikacija vo stilot Âzdravo na site°: //: swt/ZdravoSWT.java // {Requires: org.eclipse.swt.widgets.Display; Morate // da instalirate SWT biblioteka od sajtot http://www.eclipse.org } import org.eclipse.swt.widgets.*; public class ZdravoSWT {

Grafi~ki korisni~ki opkru`uvawa

1329

public static void main(String [] args) { Display prikaz = new Display(); Shell skolka = new Shell(prikaz); skolka.setText("Zdravo, SWT!"); // Na naslovnata lenta skolka.open(); while(!skolka.isDisposed()) if(!prikaz.readAndDispatch()) prikaz.sleep(); prikaz.dispose(); } } ///:~

Dokolku go prezemate izvorniot kod na ovaa kniga, }e vidite deka komentarskata direktiva ÂRequires° zavr{uva vo Ant datotekata build.xml; kako preduslov potrebno e pravewe podimenik swt; site datoteki koi uvezuvaat org.eclipse.swt baraat da instalirate SWT biblioteka od sajtot www.eclipse.org. Klasata Display upravuva so vrskata pomeѓu SWT i operativniot sistem - taa e del od Mostot pomeѓu operativniot sistem i SWT. Klasata Shell e glaven prozorec na najvisoko nivo; vo nea se gradat site ostanati komponenti. Koga }e go povikate metodot setText(), negoviot argument se pretvora vo natpis na naslovnata lenta na prozorecot. So metodot open() na klasata Shell go prika`uvate toj prozorec, a so toa i aplikacijata. Dodeka Swing go krie od programerot kotelecot za obrabotka na nastanite, SWT go primoruva eksplicitno da go napi{e. Na vrvot na toj kotelec proverete dali {kolkata e otka`ana - toa vi pru`a prilika da vmetnete kod za ~istewe. No toa zna~i deka osnovnata ni{ka main() e istovremeno i ni{ka na korisni~koto opkru`uvawe. Vo Swing pozadi scenata se pravi druga ni{ka za obrabotka na nastanite, no vo SWT nastanite na korisni~koto opkru`uvawe gi obrabotuva glavnata ni{ka, t.e. ni{ka na metodot main(). Bidej}i se podrazbira postoewe samo na edna ni{ka a ne na dve, ne{to pomalku verojatno e deka korisni~koto opkru`uvawe }e go zatrupate so ni{ki. Imajte predvid deka zada~ite ne morate da gi ispra}ate na ni{kata na korisni~koto opkru`uvawe kako vo Swing. Ne samo {to za toa se gri`i SWT, tuku toj frla isklu~ok ako se obidete widgetot da go obrabotite vo pogre{na ni{ka. Meѓutoa, dokolku za dolgotrajni operacii morate da napravite novi ni{ki, nastanite treba da gi ispra}ate kako vo Swing. Za toa SWT ima tri metodi koi mo`at da se povikuvaat za objekt od tipot Display: asyncExec(Runnable), syncExec(Runnable) i timerExec(int,Runnable). Vo toj moment va{ata glavna ni{ka main() treba da go povika metodot readAndDispatch() za objektot Display (toa zna~i deka aplikacijata mo`e da ima samo eden objekt od tipot Display). Metodot readAndDispatch() vra}a true

1330

Da se razmisluva vo Java

Brus Ekel

dokolku vo redot za ~ekawe ima pove}e nastani koi ~ekaat na obrabotka. Vo toj slu~aj, treba vedna{ povtorno da go povikate. Meѓutoa, ako nema raboti koi ~ekaat na izvr{uvawe, povikajte ja metodot sleep() na objektot Display za da pri~ekate nekoe kuso vreme pred povtorno da go povikate redot za ~ekawe. Koga izvr{uvaweto na programata }e se zavr{i, morate eksplicitno da go povikate metodot dispose() na objektot Display. SWT ~esto bara eksplicitno ~istewe na resursite na pripaѓa~kiot operativen sistem, koi inaku mo`at i da nedostasuvaat. Slednata programa pravi pove}e Shell objekti za da poka`e deka {kolkata (objekt od tipot Shell ) e glaven prozorec: //: swt/skolkiteSeGlavniProzorci.java import org.eclipse.swt.widgets.*; public class skolkiteSeGlavniProzorci { static Shell[] skolki = new Shell[10]; public static void main(String [] args) { Display prikaz = new Display(); for(int i = 0; i < skolki.length; i++) { skolki[i] = new Shell(prikaz); skolki[i].setText("skolka #" + i); skolki[i].open(); } while(!skolkiteSeIscisteni()) if(!prikaz.readAndDispatch()) prikaz.sleep(); prikaz.dispose(); } static boolean skolkiteSeIscisteni() { for(int i = 0; i < skolki.length; i++) if(skolki[i].isDisposed()) return true; return false; } } ///:~

Koga }e ja startuvate ovaa programa, }e dobiete deset glavni prozorci. Poradi na~inot na koj programata e napi{ana, ako zatvorite koj bilo od tie prozorci, }e gi zatvorite i site ostanati. I SWT koristi rasporeduva~i - razli~ni od onie vo Swing, no isti vo princip. Vo sledniot nezna~itelno poslo`en primer na {kolkata }e i go dodademe tekstot na rezultatot od metodot System.getProperties(): //: swt/SvojstvaNaKlasataDisplay.java import org.eclipse.swt.*; import org.eclipse.swt.widgets.*; import org.eclipse.swt.layout.*; import java.io.*;

Grafi~ki korisni~ki opkru`uvawa

1331

public class SvojstvaNaKlasataDisplay { public static void main(String [] args) { Display prikaz = new Display(); Shell skolka = new Shell(display); skolka.setText("Svojstva na klasata Display"); skolka.setLayout(new FillLayout()); Text tekst = new Text(skolka, SWT.WRAP | SWT.V_SCROLL); StringWriter svojstva = new StringWriter(); System.getProperties().list(new PrintWriter(svojstva)); tekst.setText(svojstva.toString()); skolka.open(); while(!skolka.isDisposed()) if(!prikaz.readAndDispatch()) prikaz.sleep(); prikaz.dispose(); } } ///:~

Vo SWT site widget-i moraat da imaat roditelski objekt od op{t tip Composite koj morate da mu go prosledite na widget-ot kako prv argument. Toa go gledate vo konstruktorot na klasata na koj prv argument mu e skolka-ta. Skoro site konstruktori primaat i indikatorski argument so pomo{ na koj mo`ete da zadadete proizvolen broj direktivi vo vrska so stilot, vo zavisnost od toa {to bara widget-ot. Site direktivi vo vrska so stilot se podlo`uvaat na logi~ka disjunkcija po bitovite (operator), kako vo prethodniot primer. Pri pravewe na Text() objektot dodadov indikatori na stilot koi go prekr{uvaat tekstot (angl. wrap) i avtomatski mu dodavaat vertikalna lenta za pridvi`uvawe (angl. scroll bar), ako treba. ]e vidite deka vo SWT mnogu {to se pravi so pomo{ na konstruktorot; mnogu atributi na widget-ot e te{ko ili nemo`no da se menuvaat osven so pomo{ na konstruktorot. Vo dokumentacijata na widget-oviot konstruktor sekoga{ morate da proverite koi indikatori se dozvoleni. Na{ite konstruktori baraat indikatorski argument duri i koga vo dokumentacijata nemaat nitu eden Âdozvolen indikator°. So toa se ovozmo`uva idnoto pro{iruvawe, a interfejsot da ne se menuva.

Izbegnuvawe na redundantnost Pred da prodol`ime, }e navedeme {to morate da napravite vo sekoja SWT aplikacija. Vo SWT sekoga{ morate da napravite prikaz t.e. objekt od klasata Display, od toj prikaz da napravite {kolka t.e. objekt od klasata Shell, da napi{ete kotelec readAndDispatch() itn. Sekako, vo nekoi posebni slu~ai toa ne morate da go pravite, no tie se tolku retki, za da se isplati da se sobere celiot kod vo edna programa i da se izbegne povtoruvaweto, kako {to za Swing napravivme vo programata net.mindview.util.SwingKonzola.

1332

Da se razmisluva vo Java

Brus Ekel

]e ja naterame sekoja aplikacija da se usoglasi so interfejsot: //: swt/util/SWTAplikacija.java package swt.util; import org.eclipse.swt.widgets.*; public interface SWTAplikacija { void createContents(Composite roditel); } ///:~

Na aplikacijata £ se predava objekt od tipot Composite (~ija potklasa e Shell), so pomo{ na koj aplikacijata so metodot createContents() mora da ja napravi celata svoja sodr`ina. Vo soodveten moment, SWTKonzola.run() go povikuva metodot createContents(), ja zadava goleminata na {kolkata vo sklad so argumentot koj korisnikot go prosledil na metodot run(), ja otvora taa {kolka, go startuva kotelecot na nastani i na kraj ja otstranuva taa {kolka koga programata }e zavr{i so rabota: //: swt/util/SWTKonzola.java package swt.util; import org.eclipse.swt.widgets.*; public class SWTKonzola { public static void run(SWTAplikacija swtApl, int sirocina, int visocina) { Display prikaz = new Display(); Shell skolka = new Shell(prikaz); skolka.setText(swtApl.getClass().getSimpleName()); swtApp.createContents(skolka); skolka.setSize(sirocina, visocina); skolka.open(); while(!skolka.isDisposed()) { if(!prikaz.readAndDispatch()) prikaz.sleep(); } prikaz.dispose(); } } ///:~

Pokraj ve}e navedenoto, so toa na naslovnata lenta se ispi{uva imeto na klasata na koja i pripaѓa SWTAplikacija-ta i zadava vrednost na parametrite sirocina i visocina za {kolkata od tip Shell. ]e napi{eme varijacija na programata SvojstvaNaKlasataDisplay.java koja so pomo{ na objekt od tipot SWTKonzola go prika`uva sistemskoto opkru`uvawe: //: swt/PrikaziSistemskoOpkruzuvanje.java import swt.util.*; import org.eclipse.swt.*; import org.eclipse.swt.widgets.*; import org.eclipse.swt.layout.*;

Grafi~ki korisni~ki opkru`uvawa

1333

import java.util.*; public class PrikaziSistemskoOpkruzuvanje implements SWTAplikacija { public void createContents(Composite roditel) { roditel.setLayout(new FillLayout()); Text tekst = new Text(roditel, SWT.WRAP | SWT.V_SCROLL); for(Map.Entry stavka: System.getenv().entrySet()) { tekst.append(stavka.getKey() + ": " + stavka.getValue() + "\n"); } } public static void main(String [] args) { SWTKonzola.run(new PrikaziSistemskoOpkruzuvanje(), 800, 600); } } ///:~

SWTKonzola }e ni ovozmo`i da se skoncentrirame na zanimlivite aspekti na aplikacijata, namesto na kodot koj se povtoruva. Ve`ba 39: (4) Izmenete ja programata SvojstvaNaKlasataDisplay.java taka {to da ja upotrebuva klasata SWTKonzola. Ve`ba 40: (4) Izmenete ja programata PrikaziSistemskoOpkruzuvanje.java taka {to da ne ja upotrebuva klasata SWTKonzola.

Menija ]e gi prika`eme osnovnite menija taka {to sledniot primer }e go uvidi sopstveniot kod i }e go razdeli na zborovi, a potoa so niv }e gi popolni menijata: //: swt/Menija.java // Zabava so menijata. import swt.util.*; import org.eclipse.swt.*; import org.eclipse.swt.widgets.*; import java.util.*; import net.mindview.util.*; public class Menija implements SWTAplikacija { private static Shell skolka; public void createContents(Composite roditel) { skolka = roditel.getShell(); Menu linija = new Menu(skolka, SWT.BAR); skolka.setMenuBar(linuja); Set zborovi = new TreeSet( new TextFile("Menija.java", "\\W+")); Iterator it = zborovi.iterator(); while(it.next().matches("[0-9]+")) ; // Pomini pozadi broevite. MenuItem[] stavkaNaMenito = new MenuItem[7];

1334

Da se razmisluva vo Java

Brus Ekel

for(int i = 0; i < stavkaNaMenito.length; i++) { stavkaNaMenito[i] = new MenuItem(linija, SWT.CASCADE); stavkaNaMenito[i].setText(it.next()); Meni podmeni = new Menu(skolka, SWT.DROP_DOWN); stavkaNaMenito[i].setMenu(podmeni); } int i = 0; while(it.hasNext()) { addItem(linija, it, stavkaNaMenito[i]); i = (i + 1) % stavkaNaMenito.length; } } static Listener priemnik = new Listener() { public void handleEvent(Event e) { System.out.println(e.toString()); } }; void addItem(Meni linija, Iterator it, MenuItem stavkaNaMenito) { MenuItem stavka = new MenuItem(stavkaNaMenito.getMenu(),SWT.PUSH); stavka.addListener(SWT.Selection, priemnik); stavka.setText(it.next()); } public static void main(String[] args) { SWTKonzola.run(new Menus(), 600, 200); } } ///:~

Menito (objekt od tipot Menu) mora da bide smesteno vo nekoja {kolka t.e. objekt od tipot Shell, a natklasata Composite ovozmo`uva taa {kolka da ja nabavite so metodot get.Shell(). TextFile e del od paketot net.mindview.util i e opi{ana vo prethodniot del na knigata; ovde so zborovi se popolnuva zbir od tipot TreeSet, pa nivniot poredok }e bide ureden. Po~etni elementi se brojki, koi potoa se otfrlaat. So pomo{ na tekot na zborovite im se davaat imiwa na menijata od najvisoko nivo vo lentata na menija, potoa se pravat podmenija i se popolnuvaat so zborovi sé dodeka gi ima. Kako odgovor na izborot na stavki na menijata, priemnikot (objekt od tipot Listener) samo go ispi{uva toj nastan taka {to da mo`ete da go vidite vidot informacii koi gi sodr`i. Koga }e ja startuvate programata, }e vidite deka tie informacii go opfa}aat i natpisot na menijata, pa vrz osnova na nego mo`ete da go napravite odgovorot na menijata - ili za sekoe meni }e napravite poseben priemnik ({to e pobezbedno vo pogled na internacionalizacijata).

Grafi~ki korisni~ki opkru`uvawa

1335

Prozor~iwa so karti~ki, kop~iwa i nastani SWT ima bogat zbir kontroli koi se narekuvaat spravi~ki ili widget-i (angl. widgets). Osnovnite widget-i se navedeni vo dokumentacijata za org.eclipse.swt.widgets, a onie poslo`enite vo dokumentacijata od org.eclipse.swt.custom. ]e prika`eme nekolku osnovni widget-i taka {to pove}e komponenti }e smestime vo okna so karti~ki. ]e vidite kako se pravat objekti od tipot Composite (sli~no kako Swing-ovite JPanel-i) za stavkite da se smestat vo drugi stavki. //: swt/OknoSoKarticki.java // Smestuvanje na SWT komponentite vo okna so karticki. import swt.util.*; import org.eclipse.swt.*; import org.eclipse.swt.widgets.*; import org.eclipse.swt.events.*; import org.eclipse.swt.graphics.*; import org.eclipse.swt.layout.*; import org.eclipse.swt.browser.*; public class OknoSoKarticki implements SWTAplikacija { private static TabFolder imenik; private static Shell skolka; public void createContents(Composite roditel) { skolka = roditel.getShell(); roditel.setLayout(new FillLayout()); imenik = new TabFolder(skolka, SWT.BORDER); labelTab(); directoryDialogTab(); buttonTab(); sliderTab(); scribbleTab(); browserTab(); } public static void labelTab() { TabItem karticka = new TabItem(imenik, SWT.CLOSE); karticka.setText("Natpis"); // Tekst na kartickata karticka.setToolTipText("Kus natpis"); Label natpis = new Label(imenik, SWT.CENTER); natpis.setText("Tekst na natpisot"); karticka.setControl(natpis); } public static void directoryDialogTab() { TabItem karticka = new TabItem(imenik, SWT.CLOSE); karticka.setText("Dialog vo imenikot"); karticka.setToolTipText("Izberete imenik");

1336

Da se razmisluva vo Java

Brus Ekel

final Button kopce = new Button(imenik, SWT.PUSH); kopce.setText("Izberete imenik"); kopce.addListener(SWT.MouseDown, new Listener() { public void handleEvent(Event e) { DirectoryDialog dd = new DirectoryDialog(skolka); String pateka = dd.open(); if(pateka != null) kopce.setText(pateka); } }); karticka.setControl(kopce); } public static void buttonTab() { TabItem karticka = new TabItem(imenik, SWT.CLOSE); karticka.setText("Kopcinja"); karticka.setToolTipText("Razni vidovi kopcinja"); Composite kompozita = new Composite(imenik, SWT.NONE); kompozita.setLayout(new GridLayout(4, true)); for(int dir : new int[]{ SWT.UP, SWT.RIGHT, SWT.LEFT, SWT.DOWN }) { Button kopce = new Button(kompozita, SWT.ARROW | dir); kopce.addListener(SWT.MouseDown, priemnik); } newButton(kompozita, SWT.CHECK, "Pole za potvrda"); newButton(kompozita, SWT.PUSH, "Obicno kopce"); newButton(kompozita, SWT.RADIO, "Radio-kopce"); newButton(kompozita, SWT.TOGGLE, "Preklopno kopce"); newButton(kompozita, SWT.FLAT, "Ramno kopce"); karticka.setControl(kompozita); } private static Listener priemnik = new Listener() { public void handleEvent(Event e) { MessageBox poraka = new MessageBox(skolka, SWT.OK); poraka.setMessage(e.toString()); poraka.open(); } }; private static void newButton(Composite kompozita, int tip, String natpis) { Button kopce = new Button(compozita, tip); kopce.setText(natpis); kopce.addListener(SWT.MouseDown, priemnik); } public static void sliderTab() { TabItem karticka = new TabItem(imenik, SWT.CLOSE); karticka.setText("Lizgaci i lenti za napreduvanje"); karticka.setToolTipText("Lizgac povrzan so lentata za napreduvanje"); Composite kompozita = new Composite(imenik, SWT.NONE); kompozita.setLayout(new GridLayout(2, true)); final Slider lizgac =

Grafi~ki korisni~ki opkru`uvawa

1337

new Slider(kompozita, SWT.HORIZONTAL); final ProgressBar napreduvanje = new ProgressBar(kompozita, SWT.HORIZONTAL); lizgac.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent nastan) { napreduvanje.setSelection(lizgac.getSelection()); } }); karticka.setControl(kompozita); } public static void scribbleTab() { TabItem karticka = new TabItem(direktprium, SWT.CLOSE); karticka.setText("Za skrabanje"); karticka.setToolTipText("Ednostavna grafika: crtanje"); final Canvas platno = new Canvas(imenik, SWT.NONE); PriemnikNaGluvcetoZaSkrabanje pgs= new PriemnikNaGluvcetoZaSkrabanje (); platno.addMouseListener(pgs); platno.addMouseMoveListener(pgs); karticka.setControl(platno); } private static class PriemnikNaGluvcetoZaSkrabanje extends MouseAdapter implements MouseMoveListener { private Point tocka = new Point(0, 0); public void mouseMove(MouseEvent e) { if((e.stateMask & SWT.BUTTON1) == 0) return; GC grafKontekst = new GC((Canvas)e.widget); grafKontekst.drawLine(tocka.x, tocka.y, e.x, e.y); grafKontekst.dispose(); updatePoint(e); } public void mouseDown(MouseEvent e) { azurirajJaTockata(e); } private void azurirajJaTockata(MouseEvent e) { tocka.x = e.x; tocka.y = e.y; } } public static void browserTab() { TabItem karticka = new TabItem(imenik, SWT.CLOSE); karticka.setText("citac"); karticka.setToolTipText("citac na Web"); Browser citac = null; try { citac = new Browser(imenik, SWT.NONE); } catch(SWTError e) { Label natpis = new Label(imenik, SWT.BORDER); natpis.setText("Neuspesna inicijalizacija na citacot"); karticka.setControl(natpis); } if(citac != null) { citac.setUrl("http://www.mindview.net");

1338

Da se razmisluva vo Java

Brus Ekel

karticka.setControl(citac); } } public static void main(String[] args) { SWTKonzola.run(new OknoSoKarticki(), 800, 600); } } ///:~

Tuka metodot createContents() zadava raspored i potoa povikuva metodi koi pravat razli~ni vidovi karti~ki. Tekstot na sekoja karti~ka se zadava so metodot setText() (pokraj toa, na karti~kite mo`ete da pravite kop~iwa i crte`i), a za sekoja e zadaden i nejziniot prira~en tekstualen opis. Na krajot na sekoj metod se povikuva setControl() koja sekoja kontrola napravena vo metodot ja smestuva vo prostorot za dijalogot na taa karti~ka. Metodot labelTab() prika`uva ednostaven tekstualen natpis. Metodot directoryDialogTab() sodr`i kop~e koe go otvora standarden objekt od tipot DirectoryDialog, vo koj korisnikot go izbira imenikot. Rezultatot na toj metod se prika`uva kako tekst na toa kop~e. Metodot buttonTab() prika`uva razni osnovni kop~iwa. Metodot sliderTab() go povtoruva primerot od prethodniot del na poglavjeto vo koj lizga~ot se vrzuva so lenta za prika`uvawe na napreduvaweto. Metodot scribbleTab() {egovito gi prika`uva grafi~kite mo`nosti. Programata za crtawe e napravena so pomo{ na nekolku redovi od kodot. Kone~no, metodot browserTab() ja poka`uva silata na SWT komponentata Browser - toa e potpoln prelistuva~ na Web vo edna komponenta.

Grafika Ova e Swing programa Sinusoida.java prevedena vo SWT: //: swt/Sinusoida.java // Swing programata Sinusoida.java prevedena vo SWT. import swt.util.*; import org.eclipse.swt.*; import org.eclipse.swt.widgets.*; import org.eclipse.swt.events.*; import org.eclipse.swt.layout.*; class CrtajSinusoida extends Canvas { private static final int FAKTORNASKALATA = 200; private int ciklusi; private int tocki; private double[] sinusi; private int[] tck; public CrtajSinusoida(Composite roditel, int stil) { super(roditel, stil); addPaintListener(new PaintListener() {

Grafi~ki korisni~ki opkru`uvawa

1339

public void paintControl(PaintEvent e) { int maksimalnaSirocina = getSize().x; double hcekor = (double)maksimalnaSirocina / (double)tocki; int maksimalnaVisocina = getSize().y; tck = new int[tocki]; for(int i = 0; i < tocki; i++) tck[i] = (int)((sinusi[i] * maksimalnaVisocina / 2 * .95) + (maksimalnaVisocina / 2)); e.grafKontekst.setForeground( e.prikaz.getSystemColor(SWT.COLOR_RED)); for(int i = 1; i < tocki; i++) { int x1 = (int)((i - 1) * hcekor); int x2 = (int)(i * hcekor); int y1 = tck[i - 1]; int y2 = tck[i]; e.grafKontekst.drawLine(x1, y1, x2, y2); } } }); setCycles(5); } public void zadajCiklusi(int noviCiklusi) { ciklusi = noviCiklusi; tocki = FAKTORNASKALATA * ciklusi * 2; sinusi = new double[tocki]; for(int i = 0; i < tocki; i++) { double radiani = (Math.PI / FAKTORNASKALATA) * i; sinusi[i] = Math.sin(radiani); } redraw(); } } public class Sinusoida implements SWTAplikacija { private CrtajSinusoida sinusi; private Slider lizgac; public void createContents(Composite roditel) { roditel.setLayout(new GridLayout(1, true)); sinusi = new CrtajSinusoida(roditel, SWT.NONE); sinusi.setLayoutData( new GridData(SWT.FILL, SWT.FILL, true, true)); sinusi.setFocus(); lizgac = new Slider(roditel, SWT.HORIZONTAL); lizgac.setValues(5, 1, 30, 1, 1, 1); lizgac.setLayoutData( new GridData(SWT.FILL, SWT.DEFAULT, true, false)); lizgac.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent nastan) { sinusi.zadajCiklusi(lizgac.getSelection()); } });

1340

Da se razmisluva vo Java

Brus Ekel

} public static void main(String[] args) { SWTKonzola.run(new Sinusoida(), 700, 400); } } ///:~

Kako {to JPanel vo Swing e osnovnata podloga (povr{ina) za crtawe, taka vo SWT toa e objekt od tipot Canvas, t.e. Âplatno° (angl. canvas). Ako ovaa verzija na programata ja sporedite so Swing verzijata, }e vidite deka metodot CrtajSinusoida e skoro identi~na. Vo SWT grafi~kiot kontekst grafKontekst se dobiva od objektot na nastani koj se prosleduva na priemnikot PaintListener, a vo Swing objektot od tip Graphics neposredno se prosleduva na metodot paintComponent(). No operaciite koi se izvr{uvaat nad grafi~kiot objekt se ednakvi, a identi~en e i metodot zadajCiklusi(). Za metodot createContents() potrebno e ne{to pove}e kod otkolku za Swing verzijata za rasporeduvawe na komponentite i podgotovka na lizga~ot i negoviot priemnik, no osnovnite operacii koi se izvr{uvaat pak se pribli`no ednakvi.

Paralelno izvr{uvawe vo SWT Iako AWT/Swing se izvr{uva vo edna ni{ka, lesno e toa da se naru{i i da se proizvede programa koj se izvr{uva nedeterministi~ki. Vo su{tina, prikazot ne smeete da go ispi{uvate so pomo{ na pove}e ni{ki, inaku tie }e po~nat da se sudiraat na neverojatni na~ini. SWT ne go dozvoluva toa - }e frli isklu~ok koga }e se obidete prikazot da go ispi{ete so pomo{ na pove}e ni{ki. So toa se spre~uva neiskusnite programeri da napravat gre{ka i taka vo programata da vnesat Âbuba~ka° koja te{ko se otkriva. Ova e Swing programa OboeniKutii.java prevedena vo SWT: //: swt/OboeniKutii.java // SWT prevod na Swing programot OboeniKutii.java. import swt.util.*; import org.eclipse.swt.*; import org.eclipse.swt.widgets.*; import org.eclipse.swt.events.*; import org.eclipse.swt.graphics.*; import org.eclipse.swt.layout.*; import java.util.concurrent.*; import java.util.*; import net.mindview.util.*; class ObKut extends Canvas implements Runnable { class PriemnikZaIscrtuvanjeNaObKut implements PaintListener { public void paintControl(PaintEvent e) {

Grafi~ki korisni~ki opkru`uvawa

1341

Color boja = new Color(e.prikaz, bBoja); e.grafKontekst.setBackground(boja); Point golemina = getSize(); e.grafKontekst.fillRectangle(0, 0, golemina.x, golemina.y); boja.dispose(); } } private static Random pseudoSlucaenBroj = new Random(); private static RGB newColor() { return new RGB(pseudoSlucaenBroj.nextInt(255), pseudoSlucaenBroj.nextInt(255), pseudoSlucaenBroj.nextInt(255)); } private int pauza; private RGB bBoja = newColor(); public ObKut(Composite roditel, int pauza) { super(roditel, SWT.NONE); this.pauza = pauza; addPaintListener(new PriemnikZaIscrtuvanjeNaObKut()); } public void run() { try { while(!Thread.interrupted()) { bBoja = newColor(); getDisplay().asyncExec(new Runnable() { public void run() { try { redraw(); } catch(SWTException e) {} // Isklucokot SWTException ne preci koga roditelot // e zavrsen na ponisko nivo na izvrsuvanje. } }); TimeUnit.MILLISECONDS.sleep(pauza); } } catch(InterruptedException e) { // Prifatliv nacin na izlez } catch(SWTException e) { // Prifatliv nacin na izlez: roditelot // zavrsen na ponisko nivo na izvrsuvanje. } } } public class OboeniKutii implements SWTAplikacija { private int brojcelii = 12; private int pauza = 50; public void createContents(Composite roditel) { GridLayout tabela = new GridLayout(brojcelii, true); tabela.horizontalSpacing = 0; tabela.verticalSpacing = 0; roditel.setLayout(tabela); ExecutorService exec = new DaemonThreadPoolExecutor(); for(int i = 0; i < (brojcelii * brojcelii); i++) {

1342

Da se razmisluva vo Java

Brus Ekel

final ObKut ok = new ObKut(roditel, pauza); ok.setLayoutData(new GridData(GridData.FILL_BOTH)); exec.execute(ok); } } public static void main(String[] args) { OboeniKutii kutii = new OboeniKutii(); if(args.length > 0) kutii.brojcelii = new Integer(args[0]); if(args.length > 1) kutii.pauza = new Integer(args[1]); SWTKonzola.run(kutii, 500, 400); } } ///:~

Kako vo prethodniot primer, so iscrtuvaweto se upravuva taka {to se pravi objekt od tipot PaintListener so metodot paintControl() koja se povikuva koga SWT ni{kata e podgotvena da ja iscrta komponentata. Toj priemnik od tipot PaintListener se prijavuva (se registrira) vo konstruktorot na klasata ObKut. Vo ovaa verzija na programata ObKut zna~itelno se razlikuva metodot run() koj metodot za iscrtuvawe redraw() ne mo`e da go povika neposredno, tuku mora da ja isprati na metodot asyncExec() na objektot od tipot Display, {to go pravi pribli`no kako metodot SwingUtilities.invokeLater(). Dokolku takviot povik go zamenite so neposreden povik na metodot redraw(), }e vidite deka programata }e zastane. Koga }e ja startuvate prethodnata programa, }e vidite deka vo prozorecot povremeno se pojavuvaat nekakvi mali horizontalni linii. Toa e posledica na faktot {to SWT ne e podrazbirano duplo baferiran kako Swing. Toa pojasno }e go zabele`ite koga Swing verzijata }e ja startuvate naporedno so SWT verzijata. Kodot za duplo baferirawe na SWT mo`ete sami da go napi{ete; primeri za toa }e najdete na Web sajtot www.eclipse.org. Ve`ba 41: (4) Izmenete ja swt/OboeniKutii.java taka {to da po~nuva so prskawe na to~kite (Âyvezdi~ki°) po platnoto, na koi potoa boite slobodno im se menuvaat.

Sporedba na SWT i Swing Od ovoj kus voved te{ko e da se stekne potpolna slika, no bi trebalo barem da po~nete da uviduvate deka SWT vo mnogu situacii ovozmo`uva pi{uvawe poednostaven kod otkolku Swing. Meѓutoa, programiraweto grafi~ki korisni~ki opkru`uvawa vo SWT sepak e poslo`eno, pa pri~inite za koristeweto na SWT verojatno treba da bidat slednite: prvo, da mu se ovozmo`i na korisnikot potransparentno do`ivuvawe pri koristeweto na va{ata aplikacija (bidej}i taa izgleda / se odnesuva kako ostanatite

Grafi~ki korisni~ki opkru`uvawa

1343

aplikacii na platformata), i vtoro, dokolku e va`na brzinata na reagirawe koja ja nosi SWT. Vo sprotivno, soodveten izbor verojatno e Swing. Ve`ba 42: (6) Izberete nekoj od Swing primerite koj vo ovoj oddel ne be{e preveden i prevedete go vo SWT.(Zabele{ka: ova e dobra doma{na zada~a za celoto oddelenie, bidej}i vodi~ot ne gi sodr`i re{enijata.)

Zaklu~ok Od site biblioteki vo Java, bibliotekata na grafi~ki opkru`uvawa pretrpe najgolemi promeni. AWT na Java 1.0 e ~esto kritikuvan kako eden od najlo{ite koj nekoga{ se pojavil, i iako ovozmo`uva{e izrabotka na prenoslivi programi, dobienoto grafi~ko korisni~ko opkru`uvawe be{e Âpodednakvo isto na site platformi°. Be{e so ograni~eni mo`nosti i nesmasno, a se koriste{e pote{ko od mati~nite alatki za razvoj na aplikacija dostapna za razni platformi. Koga vo Java 1.1 se vovedoa noviot model na nastani i zrnata na Java, sostojbata se podobri: sega e mo`no da se napravat komponenti na grafi~koto opkru`uvawe koi lesno se prevlekuvaat vo alatkite za vizuelno pravewe aplikacii. Osven toa, modelot na nastani i zrna se poka`a jasno deka se vodelo smetka za lesnotijata na programiraweto i odr`uvaweto na kodot ({to ne be{e o~igledno vo bibliotekata AWT na Java 1.0). Meѓutoa, duri koga se pojavija klasite JFC/Swing, rabotata be{e zavr{ena. So komponentite na bibliotekata Swing, programiraweto grafi~ki opkru`uvawa prenoslivi na razni platformi stana relativno bezbolno. Prava revolucija se odigra vo oblasta na alatkite za pravewe aplikacii. Ako sakate da se podobri nekoja komercijalna alatka za pravewe aplikacii, morate da dr`ite palci i da se nadevate deka avtorite na opkru`uvaweto }e vi go dadat ona {to go sakate. Java e otvoreno opkru`uvawe, {to zna~i deka dozvoluva konkurentski opkru`uvawa za pravewe aplikacii i poddr`uva takov pristap. Za da tie alatki koj bilo gi zeme predvid, tie mora da gi poddr`uvaat Java zrnata. Toa podrazbira otvoreno igrali{te: ako se pojavi podobra alatka za pravewe aplikacii, pove}e nema da morate da ja koristite onaa koja do toga{ ste ja koristele, tuku mo`ete da preminete na nova i so toa da ja zgolemite produktivnosta. Vakov vid konkurentsko opkru`uvawe za vizuelnite alatki porano ne postoe{e, a pazarot koj na ovoj na~in }e se formira mo`e da dade samo pozitivni rezultati vo pogled na produktivnosta na programerot. Ova poglavje treba{e da ve vovede vo osnovite na programiraweto na GKO i da vi gi prika`e osnovnite tehniki za prili~no lesno pronaoѓawe sopstven pat niz bibliotekata. Ona {to dosega go vidovte verojatno }e zadovoli dobar del od va{ite potrebi pri proektiraweto korisni~ki opkru`uvawa. Meѓutoa, Swing, SWT i Flash/Flex mo`at i mnogu pove}e od toa, bidej}i

1344

Da se razmisluva vo Java

Brus Ekel

sodr`at potpoln asortiman alatki za grafi~ki opkru`uvawa. Verojatno postoi na~in da postignete skoro s¢ {to mo`ete da zamislite.

Resursi Mre`nite prezentacii na Ben Galbraith na www.galbraiths.org/presentasions ubavo gi objasnuvaat i Swing i SWT.

adresata

Re{enijata na odbranite ve`bi se dadeni vo elektronskiot dokument The Thinking in Java Annotated Solution Guide, koj mo`e da kupi na sajtot www.MindView.com.

Grafi~ki korisni~ki opkru`uvawa

1345

A: Dodatoci Ovaa kniga ima pove}e dodatoci, pomeѓu koi se sodr`inite, seminarite i uslugite dostapni na Web sajtot MindView. Tie dopolnuvawa se opi{ani vo ovoj dodatok za da mo`ete da procenite dali tie mo`at da vi koristat. Obrnete vnimanie na toa deka seminarite obi~no se dr`at javno, no mo`at da se odr`uvaat i privatno, na va{iot sajt, samo za va{iot personal.

Dodatoci koi mo`at da se prezemat od Internet Kodot za ovaa kniga mo`ete da go prezemete na adresata www.MindView.net. Opfateni se i Ant build datotekite i drugi datoteki za poddr{ka neophodni za uspe{no avtomatizirano preveduvawe i pakuvawe na programata i izvr{uvawe na primerite od ovaa kniga. Osven toa, nekoi delovi na knigata se prefrleni i vo elektronski oblik. Vo niv se obraboteni temite: Klonirawe na objektot Prosleduvawe i vra}awe na objektot Analiza i proektirawe Delovi na drugi poglavija od tretoto izdanie na knigata Da se misli na Java koi ne bea dovolno relevantni za da bidat objaveni vo ~etvrtoto izdanie na ovaa kniga.

Da se misli na jazikot C: osnova za Java Na sajtot www.MindView.net mo`ete besplatno da go prezemete seminarot Thinking in C. Prezentacijata ja smisli Chuck Allison, a ja razvi kompanijata MindView. Se raboti za multimedijalen Flash kurs koj dava uvod vo sintaksata, operatorite i funkciite na jazikot C, na osnova na koi e napravena Java. Vodete smetka za toa deka na kompjuterot na koj sakate da go startuvate seminarot Thinking in C morate da imate instalirano Flash Player (koj mo`ete besplatno da go prezemete od sajtot www.adobe.com).

1346

Da se razmisluva vo Java

Brus Ekel

Seminar Thinking in Java Mojata kompanija (MindView, Inc) dr`i petdnevni javni i privatni seminari za obuka niz neposredno iskustvo, ~ija osnova ja pravi materijalot na ovaa kniga. Ovoj seminar (~ie prethodno ime be{e Hands-On Java) e na{ glaven voveden seminar i osnova za ponaprednite seminari. Sekoja lekcija ja so~inuva odbran materijal od oddelno poglavje. Potoa sleduva period na ve`bawe pod nadzor, koga na sekoj student mu se posvetuva poedine~no vnimanie. Na sajtot www.MindView.net }e pronajdete informacii za rasporedot i mestoto na odr`uvawe, svedo~ewa na biv{ite studenti i razni drugi poedinosti.

CD so seminar Hands-On Java CD-to Hands-On Java e napraveno vrz osnova na ovaa kniga, a sodr`i pro{irena verzija na materijalot od seminarot Thinking in Java. Barem delumno }e iskusite kako e da se bide na seminar a pri toa da ne patuvate i pla}ate kotizacija. Sekoe poglavje na ovaa kniga e pretstaveno na CD so soodveten zvu~en zapis na edno predavawe i so soodvetni slajdovi koi sleduvaat. Jas go osmisliv seminarot i go izgovaram tekstot na predavaweto na CD-to. Materijalot e vo Flash format i mo`e da bide reproduciran na sekoja platforma koja podr`uva Flash Player. CD-to Hands-On Java mo`ete da go kupite preku sajtot www.MindView.net, a tamu se nao|aat i probnite primeri koi mo`at da se prezemat besplatno.

Seminar Thinking in Objects Ovoj seminar pretstavuva objektno orientirano programirawe videno so o~ite na proektantot. Se ispituva postapkata na razvoj i izgradba na sistemot, prvenstveno fokusiraj}i se na Âpobrzi° ili °polesni" metodi, osobeno so metodite na Ekstremno programirawe (XP, eXtreme Programming). Gi pretstavuvam metodologiite voop{to, malite alatki kako {to e tehnikata na planirawe so pomo{ na indeksni karti~ki (opi{ana vo knigata Planning Extreme Programming, Beck&Fowler, Addison-Wesley, 2001), karti~kite za proektirawe objekti, programiraweto parovi, planiraweto iteracii, testiraweto edinici, avtomatiziranata izgradba na programi, kontrolata na izvorniot kod i sli~ni temi. Kursot opfa}a i eden XP proekt koj go razvivame edna nedela. Ako zapo~nuvate nekoj proekt i bi sakale da upotrebuvate objektno orientirani tehniki na proektirawe, mo`eme va{iot proekt da go upotrebime kako primer i do krajot na sedmicata da napravime prva gruba verzija na re{enieto.

A: Dodatoci

1347

Na sajtot www.MindView.net }e pronajdete informacii za rasporedot i mestoto na odr`uvawe, svedo~ewa na biv{i studenti i razni drugi poedinosti.

Thinking in Enterprise Java Ovaa kniga e nastanata od nekoi ponapredni poglavja od porane{nite izdanija na knigata Da se misli na Java. Toa ne e vtoriot tom na Da se misli na Java, tuku fokusirano objasnuvawe na ponaprednite temi za programirawe za delovna primena. Momentalno e dostapna (vo nekoj oblik, verojatno s¢ u{te se razviva) kako besplaten elektronski dokument koj mo`e da se prezeme od sajtot www.MindView.net. Bidej}i se raboti za posebna kniga, taa se pro{iruva sekoga{ koga e potrebno da se opfati nekoja nova tema. Celta e ista kako onaa vo knigata Da se misli na Java: - da se dade mnogu razbirliv uvod vo osnovnite tehnologii na programiraweto za delovna primena, za da ~itatelot bide spremen za ponapredni obrabotki na tie temi. Pomeѓu obrabotenite temi se nao|aat i slednive: Uvod vo programirawe za delovni potrebi Mre`no programirawe so pomo{ na priklu~nici i kanali Dale~insko povrzuvawe na metodite (RMI, Remote Method Invocation) Povrzuvawe so bazite na podatoci Uslugi na imenuvawata i uslugi na imenikot Servleti Serverski stranici na Java (JSP) Oznaki, JSP fragmenti i jazik za izrazite Avtomatizirawe na praveweto korisni~ki interfejsi Zrnata na Java vo delovnite primeni XML Web uslugi Avtomatsko testirawe Tekovnata sodr`ina na knigata Thinking in Enterprise Java mo`ete da ja prezemete na sajtot www.MindView.net.

Thinking in Patterns (with Java) Eden od najva`nite pridonesi vo proektiraweto objektno orientirani programi se Âproektnite obrasci° ~ij razvoj e hronolo{ki opi{an vo knigata Design Patterns, koja ja napi{aa Gamma, Helm, Johnson i Vlissides (Addison-Wesley, 1995). Taa kniga opi{uva 23 op{ti klasi problemi i nivnite programski re{enija, napi{ani prvenstveno na C++. Knigata Design Patterns stana klu~en, skoro zadol`itelen izvor na OOP programerite. Knigata

1348

Da se razmisluva vo Java

Brus Ekel

Thinking in Patterns gi pretstavuva osnovnite poimi na proektnite obrasci na primeri od Java. Toa ne e prost prevod na knigata Design Patterns na Java, tuku edna nova perspektiva dadena od stanovi{te na Java. Ne se zanimava samo so 23-te klasi~ni obrasci, tuku, po potreba, i so drugi idei i tehniki za re{avawe na problemite. Nastanata e kako posledno poglavje na prvoto izdanie na knigata Da se misli na Java. Kako {to se razvivale ideite, stanalo jasno deka za niv e potrebna posebna kniga. Vo vreme na pi{uvawe na ovoj tekst taa s¢ u{te se razviva, no materijalot od nea e obrabotuvan i prerabotuvan vo mnogu prezentacii na seminarot Objects & Patterns (koj sega e podelen na seminarite Designing Objects & Systems i Thinking in Patterns). Pove}e informacii za taa kniga pobarajte na adresata www.MindView.net.

Seminar Thinking in Patterns Ovoj seminar e razvien od seminarot Objects & Patterns (Objekti & obrasci) koj Bill Venners i jas go dr`evme vo izminative nekolku godini. Toj stana preop{iren, pa go podelivme na dva: ovoj i prethodno spomnatiot Designing Objects & Systems (Proektirawe na objekti i sistemi). Seminarot strogo se dr`i do materijalot i na~inot na pretstavuvawe na materijalot od knigata Thinking in Patterns, pa sodr`inata na seminarot najdobro }e ja zapoznaete od taa kniga, koja mo`ete da ja prezemete od sajtot www.MindView.net. Vo dobar del od prezentacijata se naglasuva procesot na evolucija na proektot - od po~etnoto re{enie, preku logikata i evolucijata na re{enieto do posoodveten dizajn. Posledniot prika`an proekt (simulacija na recikla`a na smet) evoluira{e so tek na vremeto i negoviot razvoj mo`e da poslu`i kako prototip za na~inot na koj mo`e da nastane va{iot dizajn: kako adekvatno re{enie na odreden problem, koe evoluira vo prilagodlivo re{enie na celata klasa problemi. Ovoj seminar }e vi pomogne: zna~ajno da ja zgolemite prilagodlivosta na svoite proekti; da go dizajnirate proektot taka da bide pro{irliv i pove}ekratno upotrebliv; da ostvarite podobra komunikacija za proektite taka {to }e go koristite jazikot na obrascite. Po sekoja lekcija sleduva niza ve`bi koi gi re{avate so pomo{ na obrasci. ]e bidete vodeni vo tek na pi{uvaweto na programite vo koi se primenuvaat konkretni obrasci kako re{enie na programskite problemi.

A: Dodatoci

1349

Na sajtot www.MindView.net mo`ete da pronajdete informacii za rasporedot i mestoto na odr`uvawe, svedo~ewa na biv{i studenti i razni drugi poedinosti.

Konsultacii i revizii na dizajnite Mojata kompanija pru`a i konsalting uslugi, mentorska rabota i revizii na dizajnite i realizaciite koi go olesnuvaat vodeweto na proektot niz celiot negov ciklus na razvoj; seto toa mo`ete da go dobiete i za prviot proekt na va{eto pretprijatie. Pove}e informacii za poedinostite i vremeto na dostapnost na tie uslugi pobarajte na adresata www.MindView.net.

1350

Da se razmisluva vo Java

Brus Ekel

B: Resursi Софтвер Razvojniot programski paket na Java (angl. Java Development Kit, JDK) mo`e da se prezeme od sajtot http://java.sun.com. Duri i ako odlu~ite da koristite razvojno opkru`uvawe od drugi proizveduva~i, sekoga{ e dobro JDK da se ima pri raka ako naidete na ne{to {to bi mo`elo da bide gre{ka na preveduva~ot. JDK e standard, pa gre{kite vo preveduva~ot na toj paket glavno se poznati. HTML dokumentacijata na razvojniot programski paket za Java e na sajtot http://java.sun.com. U{te ne sum prona{ol referenten prira~nik za standardnite Java biblioteki koj ne be{e zastaren ili so dovolna koli~ina informacii. Iako HTML dokumentacijata na kompanijata Sun e Âizdup~ena° so mali gre{ki i ponekoga{ e tolku {tura {to e neupotrebliva, barem gi sodr`i site klasi i metodi. Luѓeto ~esto na po~etokot imaat otpor kon koristeweto na Web resursite bidej}i pove}e sakaat pi{ani knigi, no vredi da se vlo`i malku trud toa da se nadmine i da se navikne na HTML dokumentite, barem zatoa {to pregledot e popotpoln otkolku vo koja bilo kniga. No, ako ne mo`ete da sfatite za {to se raboti vo upatstvata na Web, pobarajte pe~ateni knigi.

Programi za ureduvawe tekst i alatki za pravewe aplikacii Vo ovaa oblast vladee zdrava konkurencija. Mnogu raboti se besplatni (a onie {to ne se, naj~esto mo`at besplatno da se isprobaat), pa najdobro e da isprobate pove}e alatki i da ja najdete onaa {to vi odgovara. Eve nekoi od niv: JEdit e besplatna programa za ureduvawe tekst ~ij avtor e Slava Pestov. Napi{ana e na Java, pa dopolnitelna korist e {to mo`ete da ja vidite na delo ovaa Java aplikacija za personalni kompjuteri. Ovaa programa za ureduvawe tekst ima mnogu softverski dodatoci, od koi najgolem del gi napi{ale ~lenovite na zaednicata na korisnici na Java. Prezemete od adresata www.jedit.org. NetBeans, Sun-ova besplatna alatka za pravewe aplikacii koja mo`e da se prezeme od www.netbeans.org. Proektirana za pravewe GKO so prevlekuvawe (drag and drop) na komponentite, za ureduvawe na kodot, otkrivawe i otstranuvawe na gre{ki itn.

B: Resursi

1351

Eclipse, proekt na otvoren izvoren kod koj, meѓu drugite, go podr`uva IBM. Platformata Eclipse e osnova koja mo`e da se pro{iruva, pa nad nea mo`ete da pravite sopstveni samostojni aplikacii. Del od toj proekt e SWT bibliotekata opi{ana vo poglavjeto Grafi~ki korisni~ki opkru`uvawa. Prezemete od adresata www.Eclipse.org. IDEA na kompanijata IntelliJ, omilen komercijalen proizvod na pove}e programeri na Java, od koi mnogumina tvrdat deka IDEA e sekoga{ ~ekor-dva pred Eclipse, mo`ebi i zatoa {to IntelliJ ne ja sozdava i alatkata za pravewe aplikacii i platformata za razvoj, tuku samo ona prvoto. Probnata verzija mo`ete besplatno da ja prezemete od adresata www.jetbrains.com.

Knigi Efikasno programirawe na Java, Joshua Bloch (Mikro knjiga, 2004). Zadol`itelna lektira. Ja napi{al ~ovek koj ja ima popraveno Java bibliotekata na kolekcii. Pi{uvano po ugled na klasikot Effective C++ , napi{an od Scott Meyer. Core Java 2, sedmo izdanie, Horstmann & Cornell, vo dva toma (Prentice Hall, 2005). Golema, seopfatna, prva kniga koja ja zemam vo raka koga }e mi pritrebaat odgovori. Vi ja prepora~uvam ovaa kniga koga }e ja pro~itate Da se misli na Java i }e posakate da prejdete na povisoko nivo. The Java Class Libraries: An Annotated Reference, Patrick Chan i Rosana Lee (Addison-Wesley, 1997). Za `al, zastarena i rasprodadena. Takva treba{e da bide i Sun-ovata HTML dokumentacija na razvojniot programski paket za Java: so dovolno opisi za da bide upotrebliva. Obemna e, skapa, a ni kvalitetot na primerite ne me zadovoluva. Sepak, mo`e da vi poslu`i koga }e padnete vo nevolja, a izgleda deka se navedeni podetaqni objasnuvawa otkolku vo pove}eto drugi knigi. Meѓutoa, Core Java 2 ima poa`urni objasnuvawa na pove}e komponenti na bibliotekata. Java Network Programming, vtoro izdanie, Eliotte Rusty Harold (O'Reilly, 2000). Ne go razbirav umre`uvaweto vo Java (odnosno, umre`uvaweto voop{to, {to se odnesuva na toa) sé dodeka ne ja pronajdov ovaa kniga. Smetam deka i Web sajtot na avtorot na knigata, Café au Lait, pru`a stimulativen, stru~en i aktuelen pogled na podobruvawata vo Java , neoptovaren so obvrski kon koj bilo proizveduva~. Poradi redovnite a`urirawa, sajtot e vo tek so novinite vo Java koi se pojavuvaat mnogu brzo. Posetete go sajtot www.cafeaulait.org. Design Patterns, Gamma, Helm, Johnson & Vlissides (Addison-Wesley, 1995). Originalna kniga koja go zapo~na razgleduvaweto na proektnite obrasci i koja se spomenuva na pove}e mesta vo ovaa kniga. Refactoring to Patterns, Joshua Karievsky (Addison-Wesley, 2005). Ja spojuva prerabotkata na programata (Âpovtornata podelba na prosti faktori°) i

1352

Da se razmisluva vo Java

Brus Ekel

proektnite obrasci. Najvreden aspekt na ovaa kniga e toa {to poka`uva kako ponatamu da se razvie proektot na koristewe proektni obrasci po potreba. The Art of UNIX Programming, Eric Raymond (Addison-Wesley, 2004). Iako Java e jazik za pi{uvawe programi koi se izvr{uvaat na site platformi, Unix/Linux treba da se znae poradi dominacijata na Java na serverite. Eric-ovata kniga e odli~en uvod vo istorijata i filozofijata na ovoj operativen sistem. Zanimlivo ~etivo i za onie koi samo sakaat da doznaat ne{to za korenite na informatikata.

Analiza i proektirawe Extreme Programming Explained, vtoro izdanie, Kent Beck so pomo{ na Cynthia Andres (Addison-Wesley, 2005). Otsekoga{ ~uvstvuvav deka mora da postoi mnogu poinakva, mnogu podobra postapka za razvivawe na programata i mislam deka XP i prijde mnogu blizu. Edinstvena kniga koja ostavi sli~en vpe~atok na mene be{e Peopleware (opi{ana vo prodol`enie) koja prete`no se bavi so opkru`uvaweto i opstanokot vo delovniot svet. Extreme Programming Explained zboruva za programiraweto i od toj agol nabquduva mnogu {to, duri i najnovite postignuvawa. Avtorite duri tvrdat deka slikite se vo red sé dodeka ne minuvate mnogu vreme nabquduvaj}i gi i spremni se da gi isfrlat. (]e zabele`ite deka na knigata ne se naoѓa Âpe~at UML°). Re{avav dali }e rabotam za nekoja kompanija isklu~ivo po osnov toa dali koristat XP. Mala kniga, kusi poglavija koi lesno se ~itaat, a teraat na razmisluvawe. ]e po~nete da zamisluvate deka rabotite vo takva atmosfera i }e vi se otvorat novi vidici. UML nakuso, Martin Fowler, vtoro izdanie (Mikro knjiga, 2004). Koga prv pat }e se sretnete so jazikot UML, }e se upla{ite bidej}i ima mnogu dijagrami i detali. Spored Fowler, pogolem del od toa e nepotreben i toj }e vi go objasni ona osnovnoto. Za pove}eto proekti potrebno e da poznavate samo nekolku alatki za crtawe dijagrami, a celta na Fowler e da dobie dobra programa, a ne da se gri`i za toa kao stignal do nea. Ubava, tenka, ~itliva kniga; prva koja treba da ja nabavite ako sakate da go razberete UML. Domain-Driven Design, Eric Evans (Addison-Wesley, 2004). Se zanimava so modelot na domen kako prvenstveno obele`je na postapkata na proektiraweto. Po osnov sopstvenoto iskustvo uvidov deka toa premestuvawe na akcentot e va`no, zatoa {to im pomaga na programerite da ostanat na vistinskoto nivo na apstrakcija. The Unified Software Development Process, Ivar Jacobsen, Grady Booch i James Rumbaugh (Addison-Wesley, 1999). Bev potpolno siguren deka ovaa kniga voop{to nema da mi se dopadne. Izgleda{e kako da gi ima site obele`ja na dosaden fakultetski u~ebnik. No, prijatno se iznenadiv: na mnogu malku prostor se sre}avaat objasnuvawa za koi mo`e da se pomisli deka i na

B: Resursi

1353

avtorite ne im se jasni. Pogolemiot del od knigata ne samo {to e jasen, tuku e i prijaten. Najdobro od sé e {to pogolemiot del od objasnuvawata se prili~no prakti~ni. Toa sepak ne e Extreme Programming (i ne e tolku jasna vo pogled na testirawata), no isto taka e i del od UML mena`erijata: duri i ako XP ne vi se dopaѓa, pove}eto programeri imaat usvoeno stav ÂUML e dobar° (bez obzir na nivnoto vistinsko nivo na iskustvo so nego). Na krajot i vie }e morate da se ka~ite na toj voz. Mislam deka ovaa kniga e najdobra za prou~uvawe na UML, i bi trebalo da ja pro~itate ako po Fowler-ovata kniga UML nakuso posakate da doznaete pove}e detali. Pred da se odlu~ite za koj bilo metod , korisno e da se posovetuvate so nekoj koj ne saka da ve ubedi da ja koristite. ^esto se slu~uva nekoj metod da se usvoi, a pri toa da ne se razbira {to to~no navistina se bara od nego ili koi prednosti }e se ostvarat. Drugi ja koristat, {to izgleda kako dovolno privle~na pri~ina. Luѓeto imaat edna ~udna osobina: ako sakaat da veruvaat deka ne{to }e gi re{i nivnite problemi, toa i }e go probaat. (Toa e eksperimentirawe, {to e dobro.) Meѓutoa, ako ne gi re{at svoite problemi, mo`ebi }e gi udvojat svoite napori i na cel glas }e objavat deka otkrile ne{to bleskavo. (Toa e nepriznavawe na realnosta, {to ne e dobro.) Mo`ebi e pouka deka nema da bidete osameni, ako nagovorite nekoi drugi luѓe da se iska~at na istiot brod, duri i ako toj brod ne odi nikade (ili tone). Ova ne zna~i deka nitu edna metodologija ne vodi nikade, tuku deka treba da bidete opremeni so mentalni alatki koi }e vi pomognat da ostanete na nivo na eksperimentirawe (ÂOva ne raboti: ajde da probame ne{to drugo°.), a da izbegnuvate odrekuvawe. (ÂToa vsu{nost i ne e problem. Sé e prekrasno, ne morame ni{to da menuvame°.). Mislam deka slednite knigi , ako gi pro~itate pred da izberete nekoj metod, }e vi gi obezbedat tie alatki. Software Creativity, Robert Glass (Prentice Hall, 1997). Ova e najdobrata kniga koja ja razgleduva perspektivata na celiot problem so metodologijata. Toa e zbirka kusi trudovi koj Glass gi pi{uval, ponekoga{ gi dobival i od drugi (eden od sorabotnicite e P.J.Plauger), a koi go izrazuvaat negovoto dolgogodi{no razmisluvawe i prou~uvawe na ovaa tema. Dovolno se zabavni, a dolgi samo kolku {to e potrebno da go ka`at ona {to e neophodno. Isto taka, trudovite ne se samo prazna prikazna; nudat stotici referenci na drugi trudovi i istra`uvawa. Site programeri i menaxeri bi trebalo da ja pro~itaat ovaa kniga pred da trgnat na lizgaviot teren na metodologijata. Software Runaways: Monumental Sofware Disasters, Robert Glass (Prentice hall, 1997). Odli~na osobina na ovaa kniga e {to na glas go govori ona za {to ne se zboruva: tolku proekti ne samo {to propadnaa, tuku propadnaa spektakularno. Zaklu~iv deka pove}eto programeri mislat: ÂToa mene ne mo`e da mi se slu~i° (ili ÂNe mo`e da se slu~i povtorno°) i smetam deka toa ne e dobro. Ako imate na um deka ne{to mo`e da trgne naopaku, vo mnogu podobra polo`ba ste da napravite sé da raboti.

1354

Da se razmisluva vo Java

Brus Ekel

Peopleware, vtoro izdanie, Tom DeMarco i Timothy Lister (Dorset House, 1999). Ovaa kniga morate da ja pro~itate. Ne samo {to e zabavna, taa }e go potrese va{iot svet i }e gi uni{ti va{ite pretpostavki. Iako avtorite se proektanti na softveri, ovaa kniga e posvetena na proektite i timovite voop{to. Meѓutoa, fokusot e staven na va`nosta na luѓeto i nivnite potrebi, a ne na tehnologijata i nejzinite potrebi. Avtorite govorat za pravewe opkru`uvawa vo koi luѓeto }e bidat zadovolni i produktivni, a ne donesuvaat pravila koi luѓeto bi trebalo da gi po~ituvaat za da bidat soodvetni delovi na ma{inata. Mislam deka ovoj stav najmnogu pridonese za toa programerite da se potsmevaat na usvojuvaweto na XYZ metodot i da prodol`at da rabotat kako {to otsekoga{ rabotele. Secrets of Consulting: A Guide to Giving & Getting Advice Successful, Gerard M. Weinberg (Dorset House, 1985). Izvonredna kniga, edna od najdobrite koi sum gi pro~ital. Sovr{ena e dokolku se obiduvate da rabotite kako konsultant ili pla}ate konsultanti i ne ste zadovolni so nivnite rezultati. Od kusite poglavja ispolneti so prikazni i anegdoti u~ete kako da dojdete do su{tinata so najmalku napor. Pro~itajte go i prodol`enieto More Secrets of Consulting objaveno 2002. Ili koja bilo druga Weinberg-ova kniga. Complexity, M. Mitchell Waldrop (Simon & Schuster, 1992). Knigata gi opi{uva sostanocite na grupa nau~nici od razli~ni struki vo gradot Santa Fe vo Meksiko, koi raspravale za razli~ni problemi koi vo nivnite disciplini ne se re{eni (berzata vo ekonomijata, postanokot na `ivotot vo biologijata, zo{to luѓeto go rabotat toa {to go rabotat vo sociologijata itn). So soo~uvawe na gledi{tata na fizikata, ekonimijata, hemijata, matematikata, informatikata, sociologijata i drugite nauki, razvien e multidisciplinaren pristap na tie problemi. Meѓutoa, pova`no e toa {to po~nalo da se razmisluva na drug na~in za spomnatite, mnogu slo`eni problemi: so oddale~uvawe od matemati~kiot determinizam i iluzijata deka mo`e da se napi{e ravenka koja go predviduva odnesuvaweto, i so pribli`uvaweto do stavot deka prvo treba da se nabquduva i da se bara nekoja pravilnost, a potoa da se imitira na site mo`ni na~ini. (Knigata, na primer, go dokumentira pojavuvaweto na genetskite algoritmi.) Smetam deka vakviot na~in na razmisluvawe e korisen zatoa {to uka`uva na na~inite na upravuvawe so sé poslo`enite softverski proekti.

Jazikot Python Learning Python, vtoro izdanie, Mark Lutz David i Ascher (O'Reilly, 2003). Ubav uvod za programerite na mojot omilen jazik, koj odli~no ja sledi Java. Knigata sodr`i i kus uvod vo Jython koj ovozmo`uva kombinirawe na Java i Python vo ista programa (interpretatorot na jazikot Jython pravi ~ist bajtkod na Java , pa ne vi e potrebno ni{to posebno za toa da go postignete). Obedinuvaweto na ovie dva jazika vetuva golemi mo`nosti.

B: Resursi

1355

Spisok na moite knigi Nabroeni se po redosledot na objavuvawe, no nekoi se rasprodadeni. Computer Interfacing with Pascal & C (objavena samostojno vo ku}ata Eisys imprint, 1998. Mo`e da se najde samo na sajtot www.MindView.net. Uvod vo elektronikata od vremeto koga operativniot sistem CP/M be{e kral, a DOS po~etnik. Koristev jazici od visoko nivo, a ~esto i paralelen priklu~ok na smeta~ot za izveduvawe razni proekti vo elektronikata. Knigata e sostavena od moite kolumni od Micro Cornucopiae, prvoto i najdobro spisanie za koe sum pi{uval. Za `al, Micro C e zgasnat mnogu pred da se pojavi Internet. Pi{uvaweto na ovaa kniga za mene be{e mnogu ubavo iskustvo. Using C++ (Osborne/McGraw-Hill, 1989). Edna od prvite knigi za jazikot C++. Pove}e ne se pe~ati i zameneta e so nejzinoto vtoro izdanie, ~ie ime e C++ Inside & Out. C++ Inside & Out (Osborne/McGraw-Hill, 1993). Kako {to rekov, ova e vsu{nost vtoro izdanie na Using C++. Jazikot C++ vo ovaa kniga e dosta to~no opi{an, no knigata e od 1992 g. pa napi{ana e knigata Thinking in C++ za da ja zameni. Pove}e za ovaa kniga mo`ete da doznaete na sajtot www.MindView.net, od kade mo`ete da go prezemete i izvorniot kod. Thinking in C++, prvo izdanie (PrenticeHall, 1995). Od spisanieto Software Development Magazine ja ima dobieno nagradata ÂPotstrek na godinata°. Thinking in C++, vtoro izdanie, Volume I (PrenticeHall, 2000). Mo`e da se prezeme od sajtot www.MindView.net. A`urirana vo sklad so kone~niot standarden jazik. Thinking in C++, vtoro izdanie, Volume II, pi{uvano zaedno so Chuck Allison (PrenticeHall,2003). Mo`e da se prezeme od sajtot www.MindView.net. Black Belt C++, the Master's Collection, Bruce Eckel, urednik (M&T Books,1994). Rasprodadena. Zbirka trudovi od razni stru~waci za C++ zasnovana na nivnite prezentacii na konferencijata Software Development, so koja pretsedavav. Obvivkata na ovaa kniga me natera vo idnina da gi kontroliram site korici na moite knigi. Thinking in Java, prvo izdanie (Prentice Hall, 1998). Prvoto izdanie na ovaa kniga osvoi nagrada za produktivnost na spisanieto Software Development Magazine, nagrada za najdobra kniga po izbor na urednicite na spisanieto Java Developer' Journal i nagrada za najdobra kniga po izbor na ~itatelite na JavaWorld. Mo`e da se prezeme od sajtot www.MindView.net.

1356

Da se razmisluva vo Java

Brus Ekel

Thinking in Java, vtoro izdanie (Prentice Hall, 2000). Ova izdanie osvoi nagrada za najdobra kniga po izbor na urednicite na spisanieto JavaWorld. Mo`e da se prezeme od sajtot www.MindView.net. Thinking in Java, treto izdanie (Prentice Hall, 1998). Ova izdanie osvoi nagrada na spisanieto Software Development Magazine za kniga - potstrek na godinata, kako i drugi nagradi navedeni na zadnata korica. Mo`e da se prezeme od sajtot www.MindView.net.

B: Resursi

1357

Spisok na termini koristeni vo knigata avtomatizirano preveduvawe i pakuvawe, izgradba na programata build avtomatsko pakuvawe autoboxing alatka za obrabotka na anotacii annotation processing tool, apt alias, psevdonim alias analizator na programski jazici scaner bit indikator bit flag blok za obrabotka na isklu~ocite exception handler blok za povici invocation handler brava lock zaemna blokada deadlock zaemno isklu~iva brava mutex zaemno isklu~uvawe mutual exclusion visoko spregnat highly coupled nadovrzuvawe (vsinxiruvawe) nanazad backward chaining vnatre{na klasa inner class

1358

Da se razmisluva vo Java

Brus Ekel

vonredna (isklu~itelna) sostojba exceptional condition vremenska oznaka (pe~at na vremeto) time stamp vremensko odlo`uvawe timeout vrzuvawe binding vrzuvawe pri izvr{uvaweto runtime binding vrzuva~ka funkcija stub v~ituva~ na klasite class loader generirawe isklu~oci, frlawe isklu~oci throwing an exception granica bound dale~insko povikuvawe na metodot Remote Method Invocation, RMI da se isprati submit da se is~isti clean up datoteka preslikana vo memorijata memory-mapped file dvostran red za ~ekawe double-ended queue, deque dvrednost rvalue dinami~ko vrzuvawe dynamic binding dinami~ka oblast na memorijata heap dnevnik, zapisnik log

B: Resursi

1359

dodelliv assignable dokumentaciona oznaka doc tag edinica za preveduvawe compilation unit, translation unit edini~no testirawe unit testing ednokratno otkrivawe na tipot single dispatching eksplicitna konverzija casting element, sprava widget zazemenost so ~ekawe busy waiting zadocneto vrzuvawe late binding zaklu~ok closure zapisnik, dnevnik log za{titna bariera (ognen yid) firewall zgasnat terminated zrna na Java Java Beans identifikator handle identifikacija na tipot vo vreme na izvr{uvaweto run-time type identification, RTTI izvr{itel executor izgradba na programata, avtomatizirano

1360

Da se razmisluva vo Java

Brus Ekel

imenski prostor namespace informacija za tipovite pri izvr{uvaweto run-time type information, RTTI integrirano razvojno opkru`uvawe Integrated Development Environment , IDE isklu~iva brava exclusive lock isklu~ok exception isklu~ok vo tek na izvr{uvaweto runtime exception ispis na stekot stack trace ispiten blok try block isprevrteno shuffled istekuvawe na memorijata memory leak klu~ za he{irawe hash code komplet alatki za apstraktni prozorci Abstract Window Toolkit, AWT konstruktor constructor konstruktor bez argumenti no-arg constructor konverzija so fa}awe capture conversion kooperativno programirawe so pove}e ni{ki cooperative multithreading kostur na programata, struktura na programata application framework la`en objekt mock object

B: Resursi

1361

leksema token lenta na napreduvaweto progress bar lesen objekt light-weight object lesna trajnost lightweight persistence lizga~ slider literal na klasata class literal lokalen metod native method meka referenca soft reference mehanizam na brzo otka`uvawe fail-fast miksin mixin mrzliva procena lazy evaluation nabroen tip enumerated type nadvore{no nadovrzuvawe external chaining najdamne{no koristewe least-recently-used, LRU natklasa superclass nasleduvawe inheritance neproveren isklu~ok unchecked exception ni{ka thread

1362

Da se razmisluva vo Java

Brus Ekel

ni{ka na izvr{uvawe thread of execution ni{ka za otprema na nastanite event dispatch thread oblast na va`nost scope objekt ~len member object obrabotka na isklu~ocite exception handling odredi{te target oznaka label oznaka na krajot end sentinel oznaka na tipot type tag operator na pridvi`uvaweto shift operator opkru`uvawe za brzo razvivawe aplikacii Rapid Application Ddevelopment, RAD opseg range otse~ok slice paralelnost, paralelna rabota concurrency pateka na klasata clas path podelena brava shared lock podobjekt subobject poka`uva~ na stekot stack pointer

B: Resursi

1363

posrednik proxy posredni~ka programa (me|uprograma) middleware povrzuva~ linker povraten povik callback povrzano zaklu~uvawe hand-over-hand locking, lock coupling povr{no kopirawe shallow copy povik vgraden direktno vo kodot inline call prazno finalno pole blank final preveduvawe i pakuvawe build predupreduva~ko preeptive prekinuvawe termination preklopuvawe na operatorite operator overloading priemnik listener prilagodliv izgled i odnesuvawe pluggable look & feel prira~en sovet tool tip pri~ina cause pove}ekratno otkrivawe na tipot multiple dispatching pove}eprogramski multitasking

1364

Da se razmisluva vo Java

Brus Ekel

program za v~ituvawe loader programirawe od klientskata strana client-side programming programirawe od serverskata strana server-side programming prodol`uvawe resumption prodol`uvawe so dodavawe nuli zero extension prodol`uvawe so za~uvuvawe na znacite sign extension profajler profiler psevdonim, alias alias rakovoditel so slu~kata event handler rano vrzuvawe early binding rasporeduva~ layout manager redefinirawe overriding red za ~ekawe queue red za ~ekawe na nastanite event queue sveduvawe nadolu downcasting sveduvawe nadolu koe go ~uva tipot type-safe downcast sveduvawe nagore upcasting servisna ni{ka daemon thread

B: Resursi

1365

sistem so koj upravuvaat nastanite event-driven system sklad , skladi{te pool svojstvo property slaba referenca weak reference sobira~ na smetot garbage collector sobira~ so kopirawe copy collector sostojba na zavr{uvawe termination condition specifikator na pristapot access specifier sporeden efekt side effect sporedliv comparable sprava, element widget standardna biblioteka na {abloni Standard Template Library, STL status na prekinatost interrupted status steblo tree sudar, kolizija collision struktura na programata, kostur na programata application framework tek na podatocite stream torka tuple

1366

Da se razmisluva vo Java

Brus Ekel

traen objekt persistent object transformirawe na klu~ot, he{irawe hashing uslov za trka race condition fantomska referenca phantom reference frlawe isklu~ok, generirawe isklu~ok throwing an exception he{irawe, transformirawe na klu~ot hashing cevka pipe ~ita~ na klasite class browser ~uvana oblast guarded region {ablon template

B: Resursi

1367

1368

Da se razmisluva vo Java

Brus Ekel

Indeks ! != ·63

@Test, ·746 @Test, za @Unit, ·735 @TestObjectCleanup, oznaka za alаtkata @Unit, ·759 @TestObjectCreate, za @Unit, ·756 @throws, ·52 @Unit, ·762;63

&

upotreba, ·54 @version, ·54

& ·69 && ·67 &= ·72

. .NET ·35 .new sintaksa 240

[ [], operator na indeksirawe, ·73

^ ^, ·73 ^=, ·73

.this sintaksa ·238

@ @,simbol za anotacii, 710 @author, ·58

I I, ·68 I=, ·65;·62·75·345 II, ·76

@Deprecated, anotacija, 702 @deprecated, Javadoc oznaka, ·52 @docRoot, ·50 @inheritDoc, ·51 @interface, i rezerviraniot zbor extends, 738 @link, ·57

+ +, ·73 konverzija vo operatorot +, ·74

@Override, ·742

<

@param, ·53

, ·958

Allison, Chuck, ·251·649·944;616;459

>=, ·15

allocate( ), 1003;264

> >, ·616

allocateDirect( ), 520

> > =, ·568

anga`irawe, Teorija na raste~koto, 771 anonimna vnatre{na klasa, 108;504;186

A

generi~ka, 938

abecedno ureduvawe, 159;145·162; abstract (apstraktna) klasa, 976 nasleduvawe od apstraktnite klasi, ·977·1011 rezerviran zbor, ·946 vo odnos na interfejsot, 1019

i kôd upravuvan od tabela, ·610;·278; anotacija, ·872 apt, alatka za obrabotka, ·283·586; dozvoleni tipovi na elementite, ·280·309·585;·562;555 elementi, 682

AbstractButton, 931

marker na anotaciite, ·509

AbstractSequentialList, ·229·235·307

podrazbirana vrednost, ·780

AbstractSet, ·307 ActionEvent, 954 ActionListener, ·276 ActionScript, za Adobe Flex, 1009·1014 Adapter, proekten obrazec, ·980

podrazbirani elementite, 65 procesor, ·65

vrednosti

procesor koj raboti refleksija, 275·278;·596 apstrakcija, 833

po

na

osnov

adapteri na priemnikot, ·67

apt, alatka za obrabotka na anotaciite, ·838 add( ), metod na klasata ArrayList, argument 826 finalen, ·838 32·700 addActionListener, 934 konstruktor, ·296·448;·450·495 adapterski metod, ·949

addChangeListener, ·134 addListener, ·21

kovarijantni tipovi na argumenti, 69

listi na promenlivi parametri (nepoznat broj i tip na argumentite), Adobe Flex, 3·12·1043·1050 69 zaklu~uvawe za tipovite generi~ki Adobe, proizvoditel na sistemot Flex, argumenti, ·166 681 agentski orientirano programirawe, argumenti so promenliva dol`ina, 667 681 i generi~ki metodi, 667 agregacija, 295 Arnold, Ken, 467 aktivni objekti, vo paralelnoto ArrayBlockingQueue, ·278 izvr{uvawe, ·561 alatka za prika`uvawe, za Swing, ArrayList, lista, ·900 82;·71 add( ), metod, ·16·74 al~ni kvantifikatori, ·761;771;763 Adler32, ·66;·356;135

Da se razmisluva vo Java

Brus Ekel

upotreba, 159

get( ), metod, ·8·74 size( ), 156·168·195;219;·199;206;170 Arrays 22

metod, binarni 16

asList( ), ·15 binarySearch( ), 1002

brоеви 679 broevi, ispi{uvawe, ·660 operatori, ·661

binarySearch( ), ·341·663·665 uslu`en metod za pretvorawe na sekvencata ili nizata vo kontejner, BitSet, ·663·668 ·958 Bloch, Jochua, ·860 asCharBuffer( ), 1017 BlockingQueue, 955;·966;942·958 asocijativna niza, ·1002;·1003;·1017 blok za obrabotka na isklu~ocite, drugo ime za mapaта, 1048 ·959·966 aспектно orientirano programirawe blok za povici, ·657 (AOP), ·914 assert , i @Unit, 74;·79;76

blokirawe i metod available( ), ·659

AtomicLong, ·196;193;26;26;·196;196;·196

vo programite izvr{uvawe, ·679 Booch, Grady, 791;793

AtomicReference, ·644

boolean, ·37

AtomicInteger, 562·635

atomska operacija, 82; 76; 76;76;82;76 atomska konverzija na tipovite, 185 atomsko pakuvawe, 121·725·823·836 i generi~ki tipovi, 668;799 available(), ·872·887

za

paralelno

algebra, ·37 i eksplicitna konverzija tipovite, ·70;·348;·646;440·464 operatori koi ne rabotat logi~ki argumenti, ·805 vo odnos na C i C++, 807

na so

Borland-ov Delphi, ·648·943;262

B

BoxLayout, ·60

Brian-ovo pravilo za sinhronizacija, 630 barawe .class datoteki vo tek na bravi 50 v~ituvaweto, ·91;76;·83;·70;·72 eksplicitni vo paralelnoto barawe, vo OOP, 1002 izvr{uvawe, ·1023 bafer, nio, ·14

BASIC, Microsoft Visual BASIC, 1017

optimisti~ko zaklu~uvawe, 105

bezusloven skok, ·949

natprevar za, vo paralelnoto izvr{uvawe ·634, 647 vo paralelnoto izvr{uvawe, ·27;497;92;404;82;498 break, rezerviran zbor, 404

biblioteka 99

bri{ewe, 316;323;316

BasicArrowButton, 402;·465·480;·500;·404 BeanInfo, namenska klasa, ·135 Beck,Kent, ·296·448;·450·495

vo generi~kiot kôd, ·743 avtorot vo odnos na programerot klient, 99 broewe referenci, sobirawe proekt, 830 otpadoci, 328·351

Indeks

broevi, binarni, ·266

CharArrayReader, 19;·145

Budd, Timothy, 679

CharArrayWriter, 666

BufferedInputStream, ·663

CharBuffer, 262

BufferedOutputStream, ·663

CharSequence, interfejs, ·14;·59;153;165;·12

BufferedReader, ·682

Charset, 509·530

BufferedWriter, ·375

checkedCollection(), ·29·278·302·634;275

ButtonGroup, ·683

CheckedInputStream, ·280;·642;

ByteArrayInputStream, 965

checkedList( ), 568;·584

ByteArrayOutputStream, 322·347;·351

checkedMap( ) ·608;150

ByteBuffer, 506

CheckedOutputStream, 967 checkedSet( ), 96

C

checkedSortedMap( ) ·268·429·739·805

C#, programski jazik, ·699

checkedSortedSet( ), 55

C++, 506

Checksum, klasi, 823

obrabotka na isklu~oci, 506

Chiba, Shigeru, Dr., 219

Standardna biblioteka na {abloni Class, 934 (Standard Template Library, STL), ·699 forName( ), ·558·589·594 {abloni, 506 generi~ki referenci na klasite, CachedThreadPool, 506 ·559·589 getCanonicalName( ), ·558·591 Callable, paralelno izvr{uvawe, 506 case, naredba, 700

getClass( ), 557

CASE_INTENSIVE_ORDER, String Comparator, ·793·795 cast(), ·17;·219;159;251·649·944;·156·146

getConstructors( ), 467;466

catch ·960;·395·717·829;·396·953;·398;·324;·421;· 398;·421; fa}awe isklu~oci, ·791

getSimpleName( ), 54

getInterfaces( ), 146 getMethods( ), 183 getSupeclass( ), ·1003 isAssignableFrom(), ·21·165;·213;·214;·

fa}awe na bilo koj isklu~ok, 395

isInstance( ), 699

rezerviran zbor, 791

isInterface(), ·931;·637;·831;·994;872;826;

razdeluvawe na zborovite, vo newInstance( ), ·598·921·925 paralelnoto izvr{uvawe, ·216·405 objekt od tipot Class, ·921 razdeluvawe, razdeluvawe na postapka za pravewe objekti, zborovite, ·408 ·637;·921·933 cevka, ·148 referenci, i xokeri, ·870 i vlezno/izlezni operacii, referenci, i ograni~uvawa, 152 175;121;122;·334 Chain of Responsibility, proekten RTTI so pomo{ objekt od tipot Class, obrazec, ·681 80

Da se razmisluva vo Java

Brus Ekel

ClassCastException, 10

~ista supstitucija, ·617

ClassNotFoundException, 351;·942

~istewe ·18

classpath, sistemska ·183;·183;·236;·355 clear( ), nio, 1017

promenliva,

izvr{uvawe, ·697

close( ), ·107;·251;·816;340·341;·341 collection, ·1043 Collections, klasa ·29;275;275;535;·616 fill( ), ·281;·921;275

i sobira~ na otpadoci, 766

enumeration(

proverka na sostojbata na zavr{uvawe so metodot finaliza( ), ·665 ), so finally, ·660;663 ~ita~ na klasite, ·665 ~itawe na standardniot vlezen tek, ·661·664 ~len ·878

metod addAll( ), 914 unmodifiableList( ), 798 Command, proekten obrazec, 99

funkcija na ~lenkite, 684

Comparable, interfejs, ·487

inicijalizatori, 356·434·470

Comparator, interfejs, ·264

objekt, ·512

compareTo( ), vo paketot ~uvana oblast, vo obrabotkata na java.lang.Comparable, 20·162 isklu~ocite, ·26·193 ConcurrentHashMap, 166;·83;·83 ConcurrentLinkedQueue, 501

D

ConcurrenModificationException ·555 izbegnuvawe so pomo{ na klasata CopyOnWriteArrayList, ·900·921 Condition, klasa vo paralelnoto izvr{uvawe, ·921 continue, rezerviran zbor, 12 Coplien, Jim, {ablonski obrazec neobi~no se povtoruva, ·883 CopyOnWriteArrayList, ·402;·504;483 za

paralelnoto

crtawe na pano vo Swing, ·501;·501 crtawe vo Swing, ·885

DataInput, 104 DataInputStream, 146·155 DataOutput, 714

koj DataOutputStream, 714 datoteka ·699

CopyOnWriteArraySet, 32·700 CountDownLatch, izvr{uvawe, ·839 CRC32, ·1023

DatagramChanell, 115;·421;·170

dijalozi, ·889 File, klasa, ·887 File.list( ), ·172·512 gubewe na podatocite na izleznata datoteka, gre{ki i praznewe na baferot, ·1002 JAR arhiva, 1049

obele`ja, ·290·595 CSS (kaskadni opisi na stilovite), i Adobe Flex, preslikana vo memorijata, CyclicBarrier, za paralelnoto ·195;170;22 izvr{uvawe, 811 zaklu~uvawe, ·214;·163;·213;·213

^ Indeks

datoteka na klasata, analiza, ·229; 235; 448

decode( ), {ema na kodirawe, 805;442

imenik ·688;·688

Decorator, proekten obrazec, ·120·121

i paketi, 607

default, rezerviran zbor vo naredbata switch, 182;27 defaultReadObject( ), 981;984;970

listawe, ·727;·743;·

defaultWriteObject( ), ·279

pravewe imenici i pateki, 142 disjunkcija, ·641 (‫)׀׀‬, ·739

DeflaterOutputStream, 878

dispose( ), ·457·645;737

Delayed, ·878

dodeluvawe objekti, DelayQueue, za paralelno izvr{uvawe, 70;589·612;·605;·604;604 ·153;·655;647 dodeluvawe vrednosti, ·70;·70 delegirawe, ·752;752 dokumentacija, ·497;·463 Delphi, na kompanijata Borland, 942 komentari i vgradena delewe, 982 dokumentacija, 800 DeMarco, Tom, ·67 dostavuva~ na poraki, idiom, 313;313; dosti`ni objekti otpadoci, 823 double ·943;·264;950;

deque, dvostran red za ~ekawe, ·11;·55 destruktor, ·833;·74 Java go nema, 752;·757 dijagram ·290 dijagrami na nasleduvawe klasite, ·95 nasleduvawe, ·182·215;·405

marker (d ili D) na literalot, na ·831;340;331 do-while, ·898 drugiot komplement, ·677 dvokratno otkrivawe na tipot, 804

za rabota so datotekite, 967 ramka 538;·214;193·196;423;·584;·506 Dijkstra, Edsger, 26·196

so pomo{ na mapata EnumMap, ·805 dvostran red za, ·281·452 D vrednost, 75

dim, 26·196

za

~ekawe

(deque),

X

dinami~ka 947 bezbednost na tipovite kontejneri, ·964 posrednik, ·535;·189

sobirawe

i rabota so pove}e ni{ki, ·1003

dijalog 978 okno so jazi~iwa, 515·524

i

i xokeri ·156·169·215;·769;·233;168 i Class reference, 199

na nadtipovi, 77;77 promena na odnesuvaweto so pomo{ neograni~eni, ·214 na kompozicija, 93 vo generi~kite tipovi, ·708;·712 proverka na tipovite vo Java, ·158;·432 sintaksa za zbirna inicijalizacija E na nizite, 684 vrzuvawe, 445 East , BorderLayout, ·411

Da se razmisluva vo Java

Brus Ekel

e, relacija, 239·414·446·666;255

·1018;1018

i sveduvawe nagore, 199·473

Erlang, programski jazik, ·681

relacija na nasleduvawe, ·637

EventSetDescriptor, 72;·74

vo odnos na relaciite e-kako, ·71

Echanger, klasa vo paralelnoto izvr{uvawe, ·947 Executor (izvr{itel), paralelno izvr{uvawe, ·668 ExecutorService, ·573·935

e-kako, relacija, ·1017 edinica za preveduvawe, ·448 ednakvost ·419 = =, ·236 ednakvost na objektite, ·299 ednokratno otkrivawe na tipot, 655;984;·647·657·664;·647;·668;·147 ;696;·693 ednosmerna (nastan), ·680 efikasnost, ·657 i nizite, ·665 i finalnost, ·657

extends, rezerviran zbor, 938 i @interface, 183 i interfejs, 95 rezerviran zbor, ·97;100;138;139 Externalizable, 365;365;363;365 alternativa za, 363 Extreme Programming (XP), ·364

eksplicitno zadavawe tipovi na argumentite na generi~kite metodi, F ·697 Façade, ·75 eksponencijalen zapis, ·647 Factory Method, proekten obrazec, 128 else, rezerviran zbor, ·342 faktor na optovaruvawe, na objekti encode( ), {ema za kodirawe, ·659 od tipot HashMap ili HashSet, 145·350·1048 endian ·341·663 false, 264 big endian, ·663·668 FeatureDescriptor, ·18;23 little endian, 325 Fibonacci, 526 entrySet( ), metod na interfejsot Map, Field, klasa za refleksija, 800 ·657 enum. Vidi nabroeni tipovi ·659 FIFO (prv izleguva onoj koj prv EnumMap, ·663

vlegol), ·808 FileChannel, ·808

EnumSet, ·223·442;

FileDescriptor, 120·121;·175;·123;·177;·638

Enumeration, ·663

namesto indikatori, 120·177·343; equals( ), ·175·177;·341; i hashCode( ), ·148

FileInputReader, ·199·446·453·459·496 FileInputStream, ·786;275;459;·610;·275; FileLock, ·276;296;581

i strukturite na podatocite so FilenameFilter, 1005 FileNotFoundException, 667 transformirani klu~evi, ·805 redefinirawe za HashMap, ·737 FileOutputStream, 398 uslovi za pravilno definirawe, FileReader, 680

Indeks

FileWriter, 324·397 fillInStackTrace( ), 960

sistem na 264·937;·938 flip( ), nio, ·699

kompanijata

Adobe,

filozofi, koi ve~eraat, primer za vzaemna blokada vo paralelnoto float ·699 izvr{uvawe, 421 vistina i nevistina vo FilterInputStream, 306 sporeduvaweto broevi so podvi`na zapirka, 316 FilterOutputStream, 1007 marker (F) na literalot, 316 FilterReader, 398 FlowLayout, ;720 FilterWriter, 1007 Flyweight, proekten obrazec, ·21;·180 final, 421 for, rezerviran zbor, 608 final (finalno), 1007 foreach, 598·602·608;·605;·589;611;·612 argument, 1007 i Adapterski metod, ·605·608;602; i efikasnost, 1007 i interfejs Iterable, ·598·629 i privatnost, 1007 i Iterable, ·293·589·626 i referenci na objektite, 968 format ·629·642 i stati~nost, 398 preciznost, ·288 klasi, 976 prika`uvawa znakovni nizi, ·74 metod, 398 specifikatori, 158 metodi, 1007 format( ), 931 podatoci, 1049 Formatter, 985 prazni finalni poliwa, ·949 forName( ), 985 rezerviran zbor, ·833 FORTRAN, programski jazik, ·667; stati~ni prosti tipovi, Fowler, Martin, ·960 830·833·914·936 finalize( ), ·101 funkcija ·598·630 direktno povikuvawe, 264·937

funkcija na ~lenkite, 80·93

i nasleduvawe, ·983;·978

redefinirawe, ·408

finally, ·70 i konstruktori, ··70 i return, 374 mana, ·948 ne se izvr{uva vo slu~aj na servisni ni{ki, ·948·1001 rezerviran zbor, 1028 FixedThreadPool, 823 Flex ·378 OpenLaslo, alternativa za Flex, ·316

Da se razmisluva vo Java

funkcija za transformirawe klu~evite (he{ funkcija), ·861 funkciski objekt, ·960

na

funkciski programski jazici, ·427 Future, ·18;·179·222;20;

G Gec-ov test, za izbegnuvawe sinhronizacijata, 69;·828 Generator, 1017

na

Brus Ekel

vnatre{ni klasi, ·287·289·302;·288;·288 popolnuvawe na kontejnerite (podtipovi na klasata Colletion), ·421 generirawe isklu~oci, ·246 generi~ki tipovi ·450 get( ), metod na klasata ArrayList, op{ti nameni, ·134

anonimni vnatre{ni klasi, ·699

HashMap, realizacija na klasata Map, 1048 argumenti so promenliva dol`ina i vo interfejsot Colletion nema metod generi~ki metod, ·21·156·165·168·193;·732;·189;206 get( ), ·946;972 getBeanInfo( ), ·1015;147;·149;702 ;439; bri{ewe, ·630

getBytes( ), 76;937;357;54;

Class referenci, 190;·134;·170;400;

getCanonicalName( ), ·884

xokerski argumenti na nadtipovite, ·186 eksplicitna konverzija po pat na generi~kata klasa, 243;245;270;264; eksplicitno zadavawe tipovi argumenti na generi~kite metodi, ·657 granici, ·662·663

getChannel( ), ·1002 getClass( ), ·54 getConstructor( ), ·55 getConstructors( ), 356·434·470 getenv( ), ·793 getenv( ), metod, ·960;942

i kontejneri za bezbedna rabota so getEventSetDescriptors( ), ·960·965 tipovite, ·253;·132;16 getInterfaces( ), ·973·976 instanceof, naredba, ·410;497;411;405 getMethodDescriptors( ), ·967 isInstance( ), ·984;·136 getmethods( ), ·961·978 isklu~oci, ·1051 getName( ), ·981;972 koi neobi~no se povtoruvaat, getPropertyDescriptors( ), ·11·/662 ·733;439;·20·158· getPropertyType( ), 54 konkretizacija, /662 getReadMethod( ), ·937 kontravarijansa, ·851;820 getSelectedValues( ), ·984

metodi, 854 najednostavna definicija na klasata, ·1005 neograni~en xokerski argument, ·423 niza generi~ki objekti, ·214;·180;·181;·24 osnoven uvod, 413 oznaka na tipot, 813 preklopuvawe, 411;·472 primer na struktura, 398 samoograni~eni tipovi, ·215 testirawe za ·448·571;·306;·305

Indeks

@Unit,

getSimpleName( ), ·946;972 getState( ), ·125 getSuperclass( ), ·963 getWriteMethod( ), ·968 Glass, Robert, ·972·976 Goetz, Brian, ·972·977 goto, nepostoewe na taa naredba vo Java, ·960·972·976·977·978 grafi~ko korisni~ko opkru`uvawe (GUI), ·989 grafika ·820 Graphics , klasa, ·970

granici 70 i Class referenci, ·959·978·1001 natklasa i Class referencite, ·977

na {to da se obrne vnimanie pri pi{uvawe sopstven metod, ·145;145;146 HashMap, ·291

samoograni~eni generi~ki tipovi, HashSet, realizacija na zbirot Set, ·987 287;703 vo generi~kite tipovi, ·960·966 Hashtable, ·660 gre{ka ·946·969 hasNext( ), metod nа класата Iterator, ·663 obrabotka so pomo{ na isklu~oci, heksadecimalno, ·872 ·987 Holub, Allen, ·598·601·630 oporavok, ·970 HTML vo Swing komponentite, prijavuvawe, ·945 ·294·589·626·627 prijavuvawe na gre{ki vo knigata, ·283·290·299·586 ·943·961 standarden izlezen tek za gre{kite, I ·964 GridBagLayout, ·958 IdentityHashMap, 968;·967 GridLayout, ·778

if-else naredba, ·275·278·283·586·968;·620;634 ikoni i klasata Icon, 954;·950;953

Grindstaff, Chris, 395 grupa ni{ki, 629

IllegalAccessException, 1049

grupa objekti, 938;976

IllegalMonitorStateException, ·586

grupi, na regularniot izraz, 629

ima, relacija, ·399·410;74;74;74;73

GUI 629

relacija na kompozicijata, 688 grafi~ki korisni~ki interfejs, ImageIcon, ·935 ·101 razvojni opkru`uvawa na GUI, ime ·630 101;101 pravewe edinstveni imiwa na GZIPInputStream, 26·193·196 paketite, 395 GZIPOutputStream, 515·524 pолno, ·148;191·400;·190 sudirawe pri kombinirawe на interfesiте, ·250;48 sudiri, 914;831;·829;·927

H Harold, Elliotte Rusty, 166

ime na klasata, otkrivawe datotekata na klasata, ·833 imenski prostori, 696·697

XOM, XML biblioteka, 602 hashCode( ), ·76

vo

implements, rezerviran zbor, 75 recept za pi{uvawe pristoen metod, import, rezerviran zbor, ·319 ·135;·536 hashCode( ) ·70 indeksirawe, operator, 82;·73;71;82 equals( ) ··70 i strukturi na podatoci transformirani klu~evi, 295;·561

indeksirano svojstvo, ·833;·74 so indexOf( ), metod na klasata String, ·987

Da se razmisluva vo Java

Brus Ekel

indikator, koristewe EnumSet namesto, ·602 InflaterInputStream, ·65

na

zbirot

rezerviran zbor, 19 Integer ·625 parseInt( ), ·1002

inicijalizacija ·65

класа за обвиткување, 466

na ~len na klasаta, 747

interfejs ·864

i nasleduvawe, 1018 i v~ituvawe na klasite, 169

i enum, ·162

i generi~kiот kod, ·509 inicijalizacija na instancata, i nasleduvawe, 656 ·702·1015 inicijalizacija so konstruktori vo i razdeluvawe od realizacijata, tek na nasleduvaweto i ·976 kompozicijata, inicijalizacija na poliwata vo ·275·278·296;739;·596;·628 interfejsite, 431 inicijalizacija na nestati~ni interfejs na osnovnata klasa, ·67 instanci, ·607 klasi vgnezdeni vnatre, ·829 inicijalizacija na nizi, ·694 privatni, kako vgnezdeniте inicijalizacija so pomo{ na interfejsi, ·37 konstruktori, 665 rezerviran zbor interface, ·1011; inicijalizatori na ~lenoviте, 762 sudir na imiwata pri kombinirawe klasi, ·375 na interfejsite, 540 mrzliva, ·371 sveduvawe nagore na interfejsot, 16 на promenliviте vo 296;625 osnovna klasa, 67·697

metodite,

poliwa na klasata, 206;·18;20

vo odnos na апstraktnata klasa, 752;·757 vo odnos na realizacijata, ·261

vgnezduvawe na interfejsot vo klasata i vo drugite klasi, ·230 redosled na inicijalizacijata, ·638 za objektot, ·67 stati~ni, 693 zaedni~ki interfejs, ·259 inicijalizirawe na izvedenata klasa, internacionalizacija, vo I/О 972;977 bibliotekata, ·799 InputStream, 970 interrupt( ) 828 InputStreamReader, 17 paralelno izvr{uvawe, ·1018 instanca 442·571·617 rabota so pove}e ni{ki, 1020 inicijalizacija na instancata, ·763 Introspector, 1020 inicijalizacija na nestati~niте in`inering na bajtkodot, instanci, ·761 146;150;·233;·148;398 klasi, ·163;·66;·520;·210; Javassist, ·146 instanceof, ·419 I/О 83 dinami~ko ispituvawe na tipot na available( ), 75 objektot so isInstance( ) namesto so instanceof, ·1007 biblioteka, ·257 i generi~kiте tipovi, 761·791·989

Indeks

biblioteka za komprimirawe, 237 blokirawe na metodite available( ), ·942 BufferInputStream, ·/·679

i

GZIPInputStream, 583 GZIPOutputStream, ·82;·71 InflaterInputStream, 204;· InputStream, ·128·190·211

BafferOutputStream, 1018

inputStreamReader, 726

BafferReader, ·/·679

internacionalizacija, 153

BafferWriter, 120;135

izlez, ·678

BafferArrayInputStream, 960;398

pomeѓu zada~ite, realizirani so pomo{ na cevki, ·657·658 karakteristiki na datotekite, cevkovodi, ·679;·854;679;679;694 ·662·663 CharArrayReader, 108·115 koi mo`at da se prekinuvaat, 92 cevka, ·288

CharArrayWriter, 947

lesna trajnost, ·109;·

CheckedInputStream, ·70

LineNumberInputStream, 110;499;

CheckedOutputStream, ·71

LineNumberReader, 178;·

close( ), 860

listawe na imenikot, ·109;114;

DataInput, 1015

mark( ), ·169·356;·

DataInputStream, ·45

mkdirs( ), ·81;·178

DataOutput, 426

mre`en vlez/izlez, 270;23;

DataOutputStream, 426

novi O/I klasi , 202;·178

DeflaterOutputStream, ·331

ObjectOutputStream, 202;·178

imenik, pravewe imenici i pateki, 74 Externalizable, 74

OutputStream, ·146;153;153;·148;146·155;·50;·180 OutputStreamwriter, 978·983

File, klasa, ·16;66;·536;65;

PipedInputStream, 978

File.list( ), 895

PipedOutputStream, 509·530

FileDescriptor, ·15

PipedReader, 439

FileInputReader, ·704

PipedWriter, 984

FileInputStream, ·74 FilenameFilter, ·76 FileOutputStream, ·16;15;222; FileReader, ·1053

prenaso~uvawe na standardniot vlez/izlez, ·373 primeri na ednostavna upotreba, ·608 PrintStream, ·189;694;·616;913

FileWriter, 67·17;16

PrintWriter, ·715;·703

FilterInputStream, 1018

PushbackInputStream, ·638

FilterOutputStream, ·677

PushbackReader, ·878

FilterReader, 833

RandomAccessFile, ·657

FilterWriter, ·64;·169;·

read( ), 672

Da se razmisluva vo Java

Brus Ekel

readDouble( ), ·657 reader, ·657·659

ZipOutputStream, ·678

readObject( ), /·876

isAssignableFrom( ), metod na klasata Class, ·790 iscrpuvawe na memorijata, re{enie so pomo{ na referenci, 867 isDaemon( ), 19

renameTo( ), ·1049

isInstance( ), ·15;·943;1048;16;·393

readExternal( ), ·663·876 readLine( ), ·663·876

reset( ), 987

i generi~ki tipovi, 986

seek( ), ·262

isInterface( ), ·84·92

SequenceInputStream, ·25

Iterable ·1003;·1017;·1017;1017;1017;·1017

Serializable, 895 setErr(PrintStream), ·84 setIn(InputStream), ·949 setOut(Printstream), 374

i foreach, ·1017 Iterable, interfejs, ·1007 i foreach sintaksa, ·1017 Iterator, klasa, ·222

na standardniot vlezen tek, ·69

hasNext( ), metod, ·638;585

StreamTokenizer, ·69

next( ), metod, ·422

StringBufferr, ·69 StringBufferrInputStream, ·69 StringReader, 722 StringWriter, ·69 System.err, ·69 System.in, 15 System.out, 70;·84;183;185;·126;43 tipi~ni U/I konfiguracii, ·395 transient, rezerviran zbor, 363 vlez, 323·325 Unicode ·661 upravuvawe so postapkata serijalizirawe, ·663·668·669;·5·672 write( ), 809

Iterator, proekten obrazec, ·20·145·153·154;·222;·146 izgled i odnesuvawe, 24·214 promenliv, ·660 isklu~ok ·663 blok try, 291;444 blok za obrabotka, ·1;3;6;35 blok za obrabotka isklu~oci, 398 ~uvana oblast, 398 Error, klasa, 374;374;·374;374 Exception , ·275·290·299·593;620;·872 FileNotFoundException, 300 na fillInStackTrace( ), 398

klasa,

finaly, 827

writeDouble( ), ·889

generi~ki na kôd, 418

writeExternal( ), ·300·593

generirawe isklu~oci, 966

writeObject( ), ·20·145·153·155·180

gubewe na isklu~okot, mana, 541

Writer, 16

hierarhii na klasi, 732

ZipEntry, 677

fa}awe na bilo koj isklu~ok, 296

ZipInputStream, 799

fa}awe isklu~oci, ·312

Indeks

i konstruktori, ·664·665·671·680

izvoren kôd, 665

i konzola, 464

napomena za za{tita na avtorskite prava, ·822 izvr{uvawe na Java programot, 850

i nasleduvaweto, ·638 i paralelnost, 657;681 konstruktori, 670 izmenuvawe na mestoto na nastanok na isklu~ok, ·657·662·663 neprovereni, 708 NullPointerException, 675 obrabotka, 343·663·668·676 obrabotka na isklu~ocite, 704;·712 ograni~uvawa, ·929

izvr{uvawe na programot operativniot sistem od Java, 317

na

J Jacobsen, ·539;·336;108;212·504;·114;442 JApplet, ·20

Ivar,

menija, ·165;·1002 JAR, 684

povtorno generirawe isklu~oci, ·360 pravewe sopstveni, /·677

arhiva, ·76

jar arhiviте i promenlivaта classpath, ·961 prodol`uvawe, uslu`en program, ·752

prekinuvawe ili ·832·856 pretvorawe na proverenite vo Java 1048 neprovereni isklu~oci, ·145 AWT, 54 prijavuvawe na isklu~ocite po pat bajtkod, 196;193 na zapisnik, 65;183;395;45;·70 i aparati za prika`uvawe Internet printStackTrace( ), 123 na TV, 216;·395 problemi pri proektiraweto, ·638 Java Web Start, ·331·351 pronao|awe sli~ni isklu~oci, 128 Java virtuelna ma{ina (JVM), ·65 proveren, ·418·419· Java osnovni klasi (JFC/Swing), ·65 RuntimeException, ·373 javni seminari za Java, ·892 specifikacija, 414 preveduvawe i izvr{uvawe na Throwable, klasa, 370 programot, 802 tipi~ni upotrebi na isklu~ocite, JavaBeans, da se vidat zrnata na Java, 250;·249 ·630 javac, ·946 try, ·467 vlan~eni isklu~oci, 70

javadoc, ·562;·634

vlan~uvawe, 374

javap, preveduva~ nanazad, 839

vonredna sostojba, 1009·1014

Javassist, 665·671

zapi{uvawe, 950

Java standardna biblioteka, 500

ispra}awe poraki, 656 izvedena klasa, 14 izvedeni tipovi, ·17

Da se razmisluva vo Java

i bezbedno izvr{uvawe so pove}e ni{ki, 895 JButton, 10;·1043 Swing, ·17

Brus Ekel

JCheckBox, 445 JCheckBoxMenuItem, ·20·158·949 JComboBox, ·520

K

JComponent, ·657·664

kanal, 808

JDialog ·703·708·711·719·1011;·712;·712

kapacitet, na objektite HashMap ili HashSet, ·986 kapsulirawe, ·16

menija, 715;·711;708;·714;·714;714

od

tip

JDK 1.1 I/O tekovi, upotreba na refleksijata za ·275·278·293·589;·456;·626 poni{tuvawe, ·697 JDK, prevzemawe i instalirawe, 976 kaskadni opisi na stilovite (CSS), JFC, osnovni klasi na Java (Swing), 963 ·638 i Adobe Flex, ·10 JFileChooser, ·677 JFrame, 961 menija, ·677 JIT, preveduva~i ba{-koga-treba,, 946 JLabel, 976 JList, ·677 JMenu, 961 JMenuBar, 22·197;393 JMenuItem, 76 JNLP, Java Network Launch Protocol, 73 join( ), rabota so pove}e ni{ki, 976 JOptionPane, 635 Joy, Bill, 64·70·114 JPanel, 77 JPopupMenu, 864 JProgressBar, 48 JRadioButton, ·79 JScrollPane, 67·17 JSlider, ·1055 JTablePane, ·900 JTextArea, 978 JTextField, 752 JTextPane, ·806 JToggleButton, ·161 JUnit, problemi so, ·276 JVM (Java virtuelna ma{ina) 630

Indeks

keySet( ), 15 kinewe na vrskata, polimorfizam, ·600 klasa, ·592

po

pat

anonimna vnatre{na ·557;295;634;295 apstraktna klasa, 12;·12

na

klasa,

avtori, 947 ~ita~, 146;·16;·15 dijagrami na nasleduvaweto, ·180 ekvivalentnost, instanaceof/isInstance( ), ·322·348 finalni klasi, 20·145·153

i

hierarhii na klasite i obrabotka na isklu~ocite, ·226·371 inicijalizacija, 369 inicijalizacija na ~lenovite, 766 inicijalizacija i v~ituvawe na klasite, ·290·291·642;·444 inicijalizacija na poliwata, 675 inicijalizirawe na klasa, 14 izvedena klasa, ·214 javna klasa preveduvawe, 747 literal klasi, 980

i

izvedenata

edinici

za

metodi, ·223;·183;131;·131; nasleduvawe od apstraktni klasi, ·646

nasleduvawe na vnatre{nata klasa, ·937;·994;·957;·985;·949 850 klient, programer, ·728;104 osnovna klasa, ·226·234·526·547·558·559·648·65 konjunkcija ·798 3·743·889 nad bitovite, ·829;·1015;· podatoci, ·/·657 logi~ka (&&), ·904 podobjekt, ·663 kod 555 povrzuvawe, izvoren, ·318·675 ·634;·355;·81;·64·81;·369;355;·421; podelba i smestuvawe, ·675 primerok, ·657 pristap, ·657

povtorna upotreba, ·675

privatna vnatre{na klasa, ·357

standardi na programiraweto, ·676

stil na programiraweto, 723 redosled na inicijalizacijata, ·663·666 kod bez zaklu~uvawe, vo paralelnoto rezerviran zbor class, ·663 izvr{uvawe, 723 kod upravuvan od tabela, 970 stati~ni vnatre{ni klasi, 347 stil na pravewe na klasite, 144 v~ituvawe, 515·524 vgnezdena klasa (stati~na vnatre{na klasa), ·949 vgezduvawe vo interfejsot, ·431 vnatre{na klasa, ·59;158

i anonimni 741;·616 kolekcija, ·820

vnatre{ni

klasi,

na klasata, ·833 popolnuvawe so pomo{ na Generator, 264·408·475· spisok metodi za, ·440·464

vnatre{nata klasa i pravata na uslu`ni metodi, ·122 pristap, ·170·179 vnatre{nata klasa i sveduvaweto kolekcii, parametar, ·317 nagore, ·16 komanda na akcijata, 80 vnatre{nata klasa i Swing, 214;24 kombinirani listi, ·778;258;·169 vnatre{nata klasa i komentari i vgradena dokumentacija, redefinirawtoe, ·67 823 vnatre{nata klasa i rezerviraniot kompatibilnost 116 zbor super, ·787 vertikalna, vnatre{na klasata i identifikatorite i .class datotekite, 823;·851;·813;·860;809;·850 migraciska, 812 ·171;270;169 vnatre{na klasata, vo metodite i komplet alatki za apstraktni oblastite na va`ewe, ·169;404 prozorci (Abstract Window Toolkit, vnatre{na klasata, vgnezduvawe vo AWT), 315 proizvolnata oblast na va`ewe, 487 komponenta, i Java zrna, ·323 upatuvawe na objektot na nadvore{nata klasa od vnatre{nata kompozicija, ·315 i dinami~ka promena na klasa, 850 odnesuvaweto, 889 pove}ekratno vgnezdena, 1018 i proektirawe, 866 klasa, v~ituva~,

Da se razmisluva vo Java

Brus Ekel

kombinirawe na kompozicijata i povratna vrednost, ·663 nasleduvaweto, ·809 povikuvawe od drugi konstruktori, vo odnos na nasleduvaweto, 629 18·1048 komprimirawe, biblioteka za, 961 povikuvawe na konstruktorot na osnovnata klasa so argumentite, komunicira~ki sekvencijalni 169;·778 procesi (CSP), ·1011 redosled na povikuvaweto na konferencija za razvoj na softverite, konstruktorot so nasleduvawe, ·635 166;·359 stati~ka odredba na konkretizacijata i generi~kite konstruktorot, ·584 tipovi, ·1043 stati~ki metodi, 583 konsalting i obuka {to ja pru`a kontejner, ·584

MindView,Inc. , 681 konstanta ·1057 grupi konstantni vrednosti, 681 posredni konstanti i String, 711

ispituvawe na performansite, ·27;·181;·193;·225; klasa, 264·937;822 sporedba so nizata, 723

pri preveduvaweto, 146

vklopuvawe na konstantata, kontejneri ·631 bez zaklu~uvawe, ·631 ·598·600·629 konstruktor, ·294·589·592·626 koi brzo otka`uvaat, 183 argumenti, ·71 osnovno odnesuvawe, 725·729 bez argumenti, ·177·334;·316

za bezbedna rabota so tipovite i generi~ki tipovi, ·137·520;452 klasi, kontravarijansa i generi~ki kôd, 5·855 kontrola na pristapot, 96;·125;48;137

Constructor, klasa za refleksija, 697 i anonimni ·442·455·461 i finaly, ·79

vnatre{ni

i obrabotka na isklu~ocite, konverzija ·624·641 avtomatska, ·266 450;22;·347·437;18;22;·515 i paralelno izvr{uvawe, 399 pro{iruva~ka, 122 i polimorfizam, 399 stesnuva~ka, 714 i preklopuvawe, ·21;18·1048

konverzija na tipovite, ·775 inicijalizacija na instancata, asSubclass( ), ·1002 ·69;76;69;·69 i generi~ki tipovi, 1002;938 inicijalizacija vo tek na nasleduvaweto i kompozicijata, 489 i prosti tipovi, ·826·833·836 konstruktor na osnovnata klasa, operatori, 860 ·824 po pat na generi~kata klasa, 860 nivo na pristap na avtomatski napraveniot podrazbiran konverzija na vremenskite edinici, konstruktor, 399 860 podrazbiran, 99 konzola, ·1050 odnesuvawe na polimorfnite ispra}awe isklu~oci na, ·598·640 metodi vo konstruktorot, ·1011 Swing alatka za prika`uvawe vo

Indeks

net.mindview.util.SwingKonzola, ·638

lenta na napreduvawe, 418

kopirawe na nizata, ·704

lepak, na rasporeduva~ BoxLayout, 966

kop~e ·989

LIFO (posledniot {to vleguva, prv izleguva), 541 LineNumberInputSream, 732

pravewe sopstveno, 947 radio-kop~e, Swing, ·94 korisni~ki interfejs, 83 grafi~ki korisni~ki interfejs (GUI), 402;·483;487;489 koe brzo regira, realizacija so pomo{ na ni{ki, 982 kostur na upravuvawe i vnatre{nite klasi, ·833 kovarijantni, 657;681 nizi, 670 povratni tipovi, 670 tipovi na argumentite, 670 kriewe na realizacijata, 708 kriti~en oddel i sinhroniziran blok, 704;·712 kvantifikator ·657·662·663 nenasiten, posesiven, ·761 so regularen izraz, ·720 rezerviran, ·720

LineNumberReader, 296 linija na napreduvawe, ·312 LinkedBlockingQueue, ·664·665·671·680 LinkedHashMap, 464 LinkedHashSet, realizacija na zbirot Set, ·638 LinkedList, vlan~ena lista, 657;681 List, klasa, 670 sporeduvawe na performansite, ·657·662·663 ureduvawe i prebaruvawe, 708 lista 675 grafi~ki listi, 343·663·668·676 paѓa~ka lista, 704;·712 Lister, Timothy, ·929 ListIterator, ·360 literal /·677 double, ·832·856 float, ·145 na klasata, 65;183;395;45;·70

L

long, 123

lesen ·76

na vrednosta, ·638

objekt, ·’427

little endian, 128

trajnost, latentni tipovi, 77

lizga~, ·418·419·951·1005;·1003;350; logaritmi, prirodni, ·373

la`en objekt, ·701

logi~ka 414

leksikografsko ureduvawe, ·699

konjunkcija, 370

vo odnos na abecednoto ureduvawe, ·699 length 300

disjunkcija, ·630

~len na nizata, 398

operator i presmeuvawe, ·467 operatori, 70

za nizite, 827

lokalna 374

Da se razmisluva vo Java

nepotpolno

Brus Ekel

vnatre{na klasa, 1009·1014

metaanotacii, ·946

promenliva, 950

Metapodatoci, ·562;·634

long 656

Method, 839

i rabota so pove}e ni{ki, 14 marker (L) na literal-ot, ·17

klasa za refleksija, 665·671 MethodDescriptor, 500

LRU, algoritam na najdamne{noto metod 895 koristewe , 665 alatka za pronaoѓawe, 10;·1043 Ivrednost, ·822 dodavawe metodi na programot, ·17 finalna, 445

M

generi~ka, ·20·158·949

main( ), 317

inicijalizacija na promenlivite vo JAR metodite, ·520 pojava na psevdonimi pri povikuvawe na metodite, ·657·664 polimorfni povici na metodite, EnumMap, ·539;·336;108;212 ·703·708·711·719 iscrpno istra`uvawe, ·20 odnesuvawe na polimorfnite vo konstruktorot, sporeduvawe na performansite, metodi 715;·711;708;·714;·714;714 ·165;·1002 preklopuvawe, Map.Entry, 684 ·275·278·293·589;·456;·626 MappedByteBuffer, ·76 primena na metodot vrz sekvencata, mark( ), ·961 976 privatna, 963 marker na anotacii, ·752 manifest na datotekite, datotekite, ·325 Map, klasa, ·325

za

ma{ini na sostojbata i nabroenite tipovi, 1048 matcher( ), metod za pronaoѓ awe regularen izraz, 54 matches( ), metod na klasata String, 196;193 matemati~ki operatori, 216;·395·960;405;·419;419;·960;·405; ·419;·393;·405 Math.random( ), metod na raste~kiot rezultat, ·331·351 Math.random( ), metod za generirawe slu~ajni broevi, ·65 mehanizam za raspredelba na procesorskoto vreme, ·65 meni ·892 JDialog, JApplet, JFrame, 802 JPopupMenu, 250;·249

razlikuvawe na preklopenite metodi, ·677 redefinirawe na privatnite, 961 rekurzivna, ·677 stati~na, 946 vgraduvawe na povikot na metodot direktno vo kodot, 976 vnatre{ni klasi vo metodite i oblastite na va`ewe, ·677 vrzuvawe na povicite na metodite, 961 za{titeni metodi, 22·197;393 Meyer, Jeremy, 76 Meyers, Scott, 73 Microsoft Visual BASIC, 976 migraciska kompatibilnost, 635 mikrosporeduvawe na performansite,

Indeks

64·70·114

na~in na pi{uvawe na ·322·348 nad bitovite 20·145·153

miksin, 77 mkdirs( ), 864 mnemonici (skratenici tastaturata), 48 mno`ewe, ·79

na

kodot,

disjunkcija, ·226·371 isklu~iva disjunkcija XOR (^), 369 konjukcija, 766

modulo, 67·17

negacija ~, ·290·291·642;·444

mo`nost za povtorno koristewe, operator na disjunkcijata (‫)׀‬, 675 ·1055 nadtipovi, xokerski argumenti, 14 monitor, za paralelno izvr{uvawe, najdamne{no koristeno ·900 (algoritam,LRU), ·214 Mono, 978 namaluvawe, operator, 747 mre`a objekti, 752 naпomena za za{titita na avtorskite mre`en vlez/izlez, ·806 prava, izvoren kôd, 980 mrzliva inicijalizacija, ·161 nasleduvawe, ·223;·183;131;·131; MXML, vlezen format na Adobe Flex, dijagram, ·646 ·276 dijagrami na nasleduvaweto klasi, mxmcl, preveduva~ za Adobe Flex, 630 850 i finalize( ), ·226·234·526·547·558·559·648·65 N 3 i finalnost, ·/·657 nabroeni tipovi, 808 dodavawe metodi, ·986 grupi konstantni jazicite C i C++, ·16 i interfejsi, ·697

vrednosti

i generi~ki kôd, ·663 vo

i ma{ini na sostojbata, ·638 i naredba switch, ·10 i nasleduvawe, 15 i sloboden izbor, ·600 i proekten obrazec Chain of Responsibility, ·592 i uvoz stati~ni ~lenovi, ·557;295;634;295 i pove}ekratno otkrivawe na tipot, 12;·12 metodi koi se menuvaat vo zavisnost od konstantata (na nabroeniot tip), 947 rezerviran zbor enum, 146;·16;·15 values( ), ·180

Da se razmisluva vo Java

i nabroeni tipovi, ·634;·355;·81;·64·81;·369;355;·421; i rezerviraniot zbor synchronized , ·657 inicijalizacija i nasleduvawe, ·657 kombinirawe na kompozicijata i nasleduvaweto, ·357 od apstraktnite klasi, ·663·666 sporeduvawe na potpolnoto nasleduvawe i pro{iruvaweto, ·663 proektirawe na metodite vo sporedba so redefiniraweto, 347 proektirawe so pomo{ na nasleduvawe, 144 pro{iruvawe na interfejsot so pomo{ na nasleduvawe, 515·524 pro{iruvawe na klasata vo tek, ·949 specijalizacija, ·431

Brus Ekel

vo odnos na kompozicijata, ·59;158 na vnatre{nite klasi, ·170·179

i prekin, ·440·464 kanal, ·122

performansi, ·317 pove}ekratno nasleduvawe vo ni{ka 80 jazicite C++ i Java, ·16 nasleduvawe na pove}ekratna bezbednost, standardna realizacija, 214;24 biblioteka, ·778;258;·169 natklasa, ·67 grupa, 823 ograni~uvawe, ·787

Java

interrupt( ), 116

negacija, logi~ka (!), ·171;270;169

isDaemon(), 823;·851;·813;·860

neobi~no povtoruvawe ·169;404

lokalen sklad na ni{ki, 812

generi~ki tipovi, 487

mehanizam za raspredelba na procesorskoto vreme, 315 {ablonski obrazec vo jazikot C++, notufyAll( ), ·323 850 neograni~en xokerski argument vo prioritet, ·315 generi~kiot kôd, 1018 resume( ) i vzaemna blokada, 889 nepodr`ani metodi, vo Java sostojbi, 866 kontejnerite, ·937;·994;·957;·985;·949 stop( ) i vzaemna blokada, ·809·889 nepotpolno presmetuvawe i logi~kite suspend( ) i vzaemna blokada 629 operatori, ·728;104 vo odnos na zada~ata, terminologija, nepravilna niza, ·798 961 neprekinatost, vo paralelnoto wait( ), ·1011 izvr{uvawe, niza 166;·359 ·829;·1015;·860;·839;·830;637;1015;8 72;829 asocijativna niza, ·1043 nepromenlivost, ·904 na generi~kite objekti, 681 nepromenlivost, kako kolekcijata ili inicijalizacija, ·1057 mapata da se napravi nepromenliva, kako prvoklasni objekti, 681 555 neprovereni isklu~oci, ·318·675 kopirawe na nizite, 711 pretvorawe na proverenite vo, ·675

kovarijansa, 146

net.mindview.util.SwingKonzola, ·675

lenght, ~len, ·598·600·629

Neville, Sean, ·676

nepravilen, ·294·589·592·626

new, operator, 723

ne e iterabilen, ·71

i niza prosti tipovi, 723 newInstance( ), 970

objektite, ·177·334;·316 sporeduvawe na elementite, 697

refleksija, 741;·616

sporeduvawe na nizite, next( ), metod na klasata Iterator, ·820 ·442·455·461 sporeduvawe so kontejnerot, ·79 nio, ·833 baffer, 264·408·475·616·696·842·919·923

Indeks

na prostite 450;22;·347·437;18;22;·515

tipovi,

proverka na granicite, 399 sintaksa na dinami~kite agregatni inicijalizacii, 399 pove}edimenzionalni, ·21;18·1048 vra}awe, ·69;76;69;·69 North, BorderLayout, 489 notifyAll( ), ·824 notifyListeners( ), 399 novi I/O klasi, 99

postapka na pravewe, ·1002 pravewe, 1002;938 serijalizirawe, ·826·833·836 na tipot Class, 860 wait( ) i notifyAll( ), 860 objekt za prenos na podatocite, 860 objekt za prenos na podatocite (idiom Prenositel), ·1050 oblast na va`ewe ·598·640

vgnezduvawe na vnatre{nata klasa vo slobodni oblasti na va`ewe, ·638 null, ·663 vnatre{nite klasi vo metodite i Null iterator, proekten obrazec, oblastite na va`ewe, ·704 18·1048 oblik ·989 Null objekt, proekten obrazec, 169;·778 primer, 947 NullpointerException, ·635 primer, i prepoznavawe na tipot vo vreme na izvr{uvawe, ·94 O oddel, kriti~en oddel i obvrzuva~ko proveruvawe na sinhroniziran blok, 83 odzemawe, 402;·483;487;489 stati~kite tipovi, 583 ObjectOutputStream, ·584 ograni~eni svojstva, 982 n-torka, ·1011

objekt, ·27·181·193;·225;·394;·248

okno so jazi~iwa, ·833 brava za paralelno izvr{uvawe, opkru`uvawa koi brzo 264·937;822 657;681 ~len, 723 oktalno, 670 dodeluvawe objekti so kopirawe na OOP 670 referencite, ·631 osnovni obele`ja, 670 equals( ), ·631 osnovni koncepti, 708 finalen, 183 getClass( ), 725·729

reagiraat,

protokol, 704;·712

Simula-67, programski jazik, hashCode( ), metod na korenskata ·657·662·663 klasa Object, ·137·520;452 zamenlivost, ·761 interfejs za, 5·855 opcioni metodi , vo Java kontejnerite, ednakvost, 96;·125;48;137 ·761 ednakvost vo odnos na ednakvosta na OpenLaszlo, alternativa za Flex, ·720 referencite, ·624·641 operacija, atomska, ·720 mre`a objekti, ·266 operativen sistem, nizite se prvoklasni objekti, 122 159;145·162;·432;·245 objektno orientirano izvr{uvawe na programot od Java, programirawe, 714 976 pojava na psevdonimi, ·775

Da se razmisluva vo Java

Brus Ekel

operator na ozna~enoto pomestuvawe inicijalizacija, ·872 nadesno (>>), ·977·1011 interfejs, operator na pomestuvaweto nalevo ·283·586;·276;·276;·276 (), 316;323;316 podatoci ·743

PriorityBlockingQueue, ’830

finalni, 328·351

proizveduva~ot potro{uva~, 159

inicijalizacija na stati~nite, ·266

propu{teni signali, 16 ScheduledExecutor, ·660

prosti tipovi podatoci i kako se upotrebuvaat so operatori, 679 podelba i smestuvawe na kodot, ·663

semafor, ·661

podobjekt, ·663

ReadWriteLock, 679

Da se razmisluva vo Java

Brus Ekel

podrazbiran konstruktor, ·682

pove}ekratno nasleduvawe, 262

dobiva isto nivo na pristap kako vo jazicite C++ i Java, ·14;·59; klasa, ·375 pove}ekratno vgnezdena klasa, pravewe, ·683 509;·530 podrazbiran paket, 965 pove}eprogramska rabota, ·29;·278;·302;·634; 275; potpira~i, na rasporeduva~ot pove}esmerni ·280;·642; BoxLayout, 322·347;·351 poka`uva~, go nema vo Java, 506 polimorfizam, 506 i konstruktori, 506 i pove}ekratno otkrivawe na tipot, ·699 odnesuvawe na polimorfnite metodi vo konstruktorot, 506 polo`ba, apsolutna, pri rasporeduvawe na Swing komponentite, 506 poliwa, inicijalizacija vo interfejsite, ·699 pole za potvrda, 506

nastan, i zrnata na Java, 568;·584 povrzano svojstvo, ·608;150 povrzuvawe, na klasata, 967 povraten povik, 96 i na vnatre{nata ·268·429·739·805 prazni finalni poliwa, 55

klasa,

praznewe na baferite na izleznite datoteki, 823 prefrluvawe, na kontekstot vo paralelnoto izvr{uvawe, 219 preduslovi za razbirawe na knigata, 934 pomestuvawe na sodr`inata vo Swing, Preferences, API, ·558·589·594 506 povtorna podelba na prosti faktori, prefiksno namaluvawe, ·559·5891047 506 prefiksno zgolemuvawe, ·558·591 povtorna upotreba na kodot, 700 prekinuvawe ili prodol`uvawe, povtorno generirawe na isklu~ok, obrabotka na isklu~ocite, 557 ·793·795 preklopuvawe 467;466 povtorno transformirawe na na generi~kite metodi, 146 klu~evite (he{irawe), ·17; i konstruktori, 183 pomalo ili ednakvo (
View more...

Comments

Copyright ©2017 KUPDF Inc.
SUPPORT KUPDF