PROGRAMIRANJE U JAVI

Size: px
Start display at page:

Download "PROGRAMIRANJE U JAVI"

Transcription

1 JAVA PROGRAMSKI JEZIK JAVA Java je programski jezik visoke razine koji se može okarakterizirati sljedećim buzzwordima: Jednostavan Objektno orijentiran Distribuiran Interpretiran Robustan Siguran Neovisan o arhitekturi Prenosiv Visokih performansi Višenitan Dinamičan U već ini programskih jezika program je potrebno ili kompajlirati ili interpretirati kako bi se mogao izvršavati na vašem računalu. Programski jezik Java donekle je neobič an jer se program napisan u njemu treba i kompajlirati i interpretirati. Java kompajlerom program se prvo prevodi u privremeni jezik zvan Java bytecodes, tj. niz kodova neovisan o platformi, pa kasnije interpretira. Interpreter čita i izvršava svaku Java bytecode instrukciju na rač unalu. Kompajliranje se izvršava samo jednom, a interpretiranje svaki put kada se program izvrši. Sljedeća slika ilustrira ovaj rad: Java bytecodeovi predstavljaju niz strojnih instrukcija za zamišljeni stroj nazvan Java Virtual Machine (Java VM). Svaki Java interpreter predstavlja implementaciju Java virtualnog stroja. Java bytecodeovi pomažu u ostvarivanju ideje»napiši jednom, pokreni svugdje«. Svoj program možete kompajlirati u byte kodove na bilo kojoj platformi koja ima Java kompajler. Byte kodovi mogu biti pokrenuti na bilo kojoj implementaciji Java virtualnog stroja. To znač i da se, dok god rač unalo posjeduje Java VM, program napisan u programskom jeziku Java može izvršavati kako na Windowsima 2000, tako i na Solaris radnim stanicama ili na imac-u. JAVA PLATFORMA Platforma predstavlja hardversko ili softversko okruženje u kojem se program izvršava. Već smo spomenuli neke poznatije platforme kao što su Windows 2000, Linux, Solaris, i MaxOS. Već ina se platformi može opisati kao kombinacija operativnog sustava i hardvera. Java platforma se razlikuje od većine drugih platformi po tome što je to isključ ivo softverska platforma koja se pokreće iznad svih drugih hardverski-baziranih platformi. Java platforma sastoji se od dva dijela: 1

2 Java Virtualnog Stroja (Java Virtual Machine Java VM) Java Aplikacijskog Programskog Sučelja ( Java Application Programming Interface - Java API) Ve ć ste se upoznali s Java VM-om koji je baza Java platforme, a postoji za različ ite hardverski bazirane platforme. Java API predstavlja veliki skup gotovih softverskih komponenti koje omoguć avaju mnoge korisne mogućnosti, kao što su npr. grafič ki (GUI) widgeti. Java API je grupiran u biblioteke povezanih klasa i sučelja; ove biblioteke u Java svijetu poznatije su kao paketi packages. Sljedeć a slika prikazuje program pokrenut na Java platformi. Java API i virtualni stroj izoliraju program od hardvera. Native kôd je kôd koji se, jednom kompajliran, može izvršavati na točno određ enoj hardverskoj platformi. Kao platformski neovisno okruženje, Java platforma može bit malo sporija od native kôda. Pa ipak, pametni kompajleri, dobro ugođ eni interpreteri i just-in-time bytecode kompajleri mogu donijeti performanse bliske performansama native kôda bez gubitka prenosivosti. KAKO JAVA MOŽE PROMIJENITI VAŠ ŽIVOT? Iako programeri iz SUN-a ne obećavaju slavu, sreću ili posao ako nauč ite programirati u Javi, ipak ćete najvjerojatnije izrađ ivati bolje programe uz manje truda nego u drugim jezicima. Dečki vjeruju da će vam Java pomoći u sljedećem: Brz poč etak Iako je programski jezik Java moć an objektno-orijentiran jezik, lagan je za učenje, posebno programerima ve ć upoznatim s C-om ili C++-om. Pisanje manje kôda Usporedbom programa (broj klasa, broj metoda, itd.) može se pokazati da programi napisani u Javi mogu biti do č etiri puta manji nego isti programi u C++-u. Pisanje boljeg kôda Programski jezik Java potič e dobru praksu pisanja koda, a njegov garbage collector pomaže izbjegavanju memory leakova. Njegova objektna orijentiranost, arhitektura JavaBeans-a te proširivi API velikih mogućnosti omoguć ava iskorištavanje prije napisanog kôda (code reuse) i pisanje programa s manje bugova. Brže razvijanje programa Razvoj programa u Javi može biti i dvostruko brži u usporedbi s pisanjem istih programa u C++-u. Kako? Tako što pišete manje linija kôda i pišete u jednostavnijem programskom jeziku nego što je C++. Izbjegavanje ovisnosti o platformi Izbjegavanjem upotrebe biblioteka napisanih u drugim jezicima svoj program možete zadržati 100% prenosivim. Napiši jedan put, pokreni svugdje Zato što se 100% Pure Java programi kompajliraju u bytecode neovisan o stroju, mogu se pokrenuti na bilo kojoj Java platformi. 2

3 Lakša isporuka softvera Appleti se vrlo jednostavno mogu nadograditi na centralnom serveru. Appleti iskorištavaju prednost svojstva koje dozvoljava uč itavanje novih klasa»u letu«, bez ponovnog kompajliranja cijelog programa. ŠTO SE MOŽE NAPRAVITI JAVOM? Najčešći tip programa napisanih u programskom jeziku Java su appleti ( applets) i aplikacije (applications). Surfajući Webom, ve ć ste se vjerojatno susreli s appletima. Applet je program koji poštuje određene konvencije koje mu dopuštaju pokretanje unutar browsera koji imaju Java VM. Međ utim, programski jezik Java ne postoji samo za pisanje slatkih, zabavnih Web appleta. Općeniti jezik visoke razine kao što je Java također predstavlja i moć nu softversku platformu u kojoj se može napisati i mnogo drugih tipova programa. Aplikacija predstavlja samostalni program koji se izvršava direktno na Java platformi. Specijalni tip aplikacija poznat kao poslužitelj (server) poslužuje klijente na mreži. Primjeri servera su Web server, proxy server, mail server i print server. Drugi specijalizirani program je tzv. servlet. Servlet bi bio nešto kao applet koji se izvršava na strani servera. Java Servleti su popularan izbor za izgradnju interaktivnih Web aplikacija kao zamjena za CGI skripte. Servleti su slič ni appletima po tome što su to runtime dodaci aplikacijama. Pa ipak, umjesto da se pokreću u browseru, servleti se izvršavaju unutar Java Web servera. Kako se uz pomo ć API-ja mogu napraviti ovakvi programi? API omoguć ava izradu softverskih komponenti širokog spektra funkcionalnosti uz pomo ć tzv. paketa. Svaka puna implementacija Java platforme daje vam slijedeće mogućnosti: Osnove objekte, stringove, threadove, brojeve, ulaz i izlaz, podatkovne strukture, sistemska svojstva, datum i vrijeme, itd. Applete set konvencija koje appleti moraju poštovati. Programiranje mreža URL-ove, TCP (Transmission Control protocol), UDP (User Datagram Protocol) sockete, i IP (Internet Protocol) adrese. Internacionalizaciju Pomo ć pri izradi programa lokaliziranih za korisnike širom svijeta. Programi se mogu automatski prilagoditi korisnikovim lokalnim postavkama i prikazati u odgovarajućem jeziku. Sigurnost Sigurnost niske i visoke razine, uključujući elektronič ke potpise, upravljanje javnim i privatnim ključevima, kontrolu pristupa i certifikate. Softverske komponente Poznate pod imenom JavaBeans TM, mogu se priključ iti postojećim komponentnim arhitekturama. Serijalizacija objekata Dozvoljava komunikaciju preko udaljenog poziva funkcija Remote Method Invocation (RMI) Java Database Connectivity (JDBC TM ) Omoguć ava jedinstven pristup širokom spektru relacijskih baza podataka. Java platforma također ima API-je za 2D i 3D grafiku, accessibility (pomo ć ljudima s ogranič enjima u komunikaciji), servere, suradnju, telefoniju, govor, animaciju i mnoge druge. Sljedeća slika prikazuje dijelove Java 2 SDK-a (Software Development Kita). 3

4 PRVI PROGRAM U JAVI - HelloWorld Kako izgleda (skoro) najjednostavnija aplikacija napisana u Javi? Evo kôda: /** * HelloWorldApp klasa implementira aplikaciju * koja ispisuje "Hello World" na standardnom izlazu. */ class HelloWorldApp { public static void main(string[] args) { System.out.println("Hello World!); // Prikazi string KOMENTARI U JAVA KODU Podebljani karakteri u sljedećem listingu su komentari: /** * HelloWorldApp klasa implementira aplikaciju * koja ispisuje "Hello World" na standardnom izlazu. */ class HelloWorldApp { public static void main(string[] args) { System.out.println("Hello World!); // Prikazi string Java podržava tri tipa komentara: /* komentar */ Kompajler će ignorirati sve što se nalazi između /* i */. /** dokumentacija */ 4

5 Ovo označ ava dokumentacijski komentar. Kompajler ignorira ovaj kometar isto kao što ignorira komentar /* i */. JDK javadoc alat može iskoristiti ovakve komentare i automatski pripremiti dokumentaciju kôda. // komentar Kompajler ignorira sve od // do kraja linije. DEFINIRANJE KLASE Prva podebljana linija u slijedećem listingu počinje definicijski blok klase. /** * HelloWorldApp klasa implementira aplikaciju * koja ispisuje "Hello World" na standardnom izlazu. */ class HelloWorldApp { public static void main(string[] args) { System.out.println("Hello World!); // Prikazi string Klasa (class) osnovni građ evni blok objektno orijentiranog jezika kao što je Java predstavlja predložak koji opisuje podatke i ponašanje instanci (instances) te klase. Instanciranje klase je naziv za kreiranje objekta koji izgleda kao i druge instance iste klase. Podaci pridruženi klasi ili objektu smješteni su u varijable (variables); ponašanje pridruženo klasi ili objektu implementira se metodama (methods). Metode su slič ne funkcijama ili procedurama u proceduralnim jezicima kao što je C. Jedan programerski primjer klase je pravokutnik. Klasa pravokutnik bi sadržavala varijable koje spremaju poziciju pravokutnika, njegovu širinu i visinu. Klasa takođ er može sadržavati i metodu koja računa površinu pravokutnika. Instanca klase pravokutnik sadrži podatke o toč no određenom pravokutniku, kao što je npr. ova stranica teksta ili pod vaše sobe. U Javi, najjednostavniji oblik definicije klase je: class imeklase {... Ključna rije č class počinje definiciju klase kojoj je ime imeklase. Varijable i metode klase smještene su unutar vitičastih zagrada kojima poč inje i završava blok klase. Aplikacija "HelloWorld" nema varijabli, a ima samo jednu metodu zvanu main. METODA main Prva podebljana linija na donjem listingu počinje definiciju main metode: /** * HelloWorldApp klasa implementira aplikaciju * koja ispisuje "Hello World" na standardnom izlazu. */ class HelloWorldApp { public static void main(string[] args) { 5

6 System.out.println("Hello World!); // Prikazi string Svaka Java aplikacija mora sadržavati main metodu čiji potpis ( method signature) izgleda ovako: public static void main(string[] args) Potpis metode main sadrži tri modifikatora: public označava da metoda main može biti pozvana od strane bilo kojeg objekta. static označava da je metoda main tzv. metoda klase, tj. statička metoda ( class method). void označava da main metoda ne vraća nikakvu vrijednost. KAKO SE POZIVA main METODA main metoda u Javi slična je funkciji main u C-u i C++-u. Java interpreter poč inje s izvršavanjem vaše aplikacije pozivom main metode. Nakon toga main metoda zove druge metode potrebne za izvršavanje vaše aplikacije. Ako pokušate pozvati Java interpreter nad klasom koja nema main metodu, interpreter ć e odbiti pokretanje vašeg programa i ispisat će pogrešku sličnu ovoj: In class NoMain: void main(string argv[]) is not defined ARGUMENTI main METODE Kao što se može vidjeti iz slijedećeg komadića kôda, main metoda prihvać a jedan argument niz elemenata tipa String. public static void main(string[] args) Ovaj niz predstavlja mehanizam pomoću kojeg pokretač ki sistem predaje informacije vašoj aplikaciji. Svaki string u nizu zove se argument komandne linije (command-line argument). HelloWorld aplikacija ignorira svoje argumente. KORIŠTENJE KLASA I OBJEKATA Ovo poglavlje objašnjava kako HelloWorld aplikacija koristi klase i objekte. Buduć i da je HelloWorld aplikacija jedan od najjednostavnijih Java programa koje možete napisati (a koji nešto i rade), u njemu nije potrebno definirati niti jednu klasu osim HelloWorldApp. Naravno, većina programa koje ćete napisati bit ć e mnogo kompleksnija i zahtjevat će pisanje drugih klasa. HelloWorld aplikacija ipak koristi drugu klasu klasu System koja je dio Java API-ja. Klasa System omogućava sistemski neovisan pristup sistemski ovisnim funkcionalnostima. 6

7 Podebljani kôd u sljedećem listingu ilustrira korištenje statičke varijable out i metode println. /** * HelloWorldApp klasa implementira aplikaciju * koja ispisuje "Hello World" na standardnom izlazu. */ class HelloWorldApp { public static void main(string[] args) { System.out.println("Hello World!); // Prikazi string KORIŠTENJE STATIČKIH METODA I VARIJABLI Pogledajmo prvi segment izraza: System.out.println("Hello World!"); System.out predstavlja puno ime out varijable klase System. Primjetite da aplikacija nikad ne instancira klasu System i da je out referenciran direktno iz imena klase. To je zato što je out statič ka varijabla (class variable) varijabla pridružena klasi, a ne instanci klase. Metode pridružene klasi se zovu slično statič ke metode (class methods). Za pristup statič koj varijabli ili metodi, potrebno je spojiti ime klase i ime metode ili varijable točkom ("."). KORIŠTENJE METODA I VARIJABLI Metode i varijable koje nisu statičke metode ili statičke varijable zovu se metode instance (instance methods) i varijable instance (instance variables). Iako je varijabla out statička varijabla, ona se odnosi na instancu PrintStream klase (klase unutar Java development okruženja), a koja implementira standardni izlaz. Kada se klasa System učita u aplikaciju, ona instancira novi objekt klase dodjeljuje ga varijabli out. Donji poziv je stoga poziv instance metode: PrintStream i System.out.println("Hello World!"); Kao što vidite, pozivanje instance metoda i dohvaćanje instance varijabli slič no je pozivanju statičkih metoda i dohvaćanju statičkih varijabli. Za pridruživanje reference na objekt ( out) i imena instance metode ili varijable (println) koristi se točka ("."). Java kompajler dozvoljava višestruko pridruživanje referenci klasa i instance metoda i varijabli, što rezultira konstrukcijama kao što je ona u primjeru: System.out.println("Hello World!"); Ova linija kôda prikazuje "Hello World!" na standardnom izlazu aplikacije (ekranu monitora). 7

8 ZAKLJUČAK Statičke metode ili statičke varijable pridružene su određ enoj klasi. Sistem alocira samo jednu statičku varijablu po klasi, bez obzira koliko njezinih instanci postoji. Statič ke varijable i metode moguće je dohvatiti preko imena klase. Instance metode ili instance varijable pridružene su određ enom objektu (instanci klase). Svaki put kad kreirate objekt, novi objekt dobiva kopiju svake instance varijable definirane u klasi. Instance varijablama i metodama pristupa se preko imena objekta. 8

9 KONCEPTI OBJEKTNO-ORIJENTIRANOG PROGRAMIRANJA Ako nikada prije niste pisali programe u objektno-orijentiranom jeziku, prije nego poč nete s pisanjem kôda trebali bi se upoznati s nekim konceptima takvog tipa programiranja. Potrebno je shvatiti što je objekt, što je klasa, u kakvom su odnosu objekti i klase te kako objekti međusobno komuniciraju uz pomo ć poruka. Sljedeć ih nekoliko poglavlja opisuje koncepte objektno-orijentiranog programiranja. Posljednje poglavlje pokazuje kako se ovi koncepti prenose u kôd. ŠTO JE OBJEKT? Objekti su klju č razumijevanja objektno-orijentirane tehnologije. Ako se osvrnete oko sebe, vidjet ćete mnoge primjere objekata realnog svijeta: svog psa, svoj stol, televizor, bicikl. Ovi objekti dijele dvije karakteristike svi imaju stanje i ponašanje. Na primjer, psi imaju stanje (ime, boju, vrstu) i ponašanje (lajanje, dohvać anje štapa i mahanje repom). Bicikli imaju stanje (trenutnu brzinu, brzinu vrtnje pedala, dva kotača, broj brzina) i ponašanje (koč enje, ubrzavanje, usporavanje, promjenu brzine). Softverski objekti modelirani su prema objektima stvarnog svijeta na nač in da i oni imaju stanje i ponašanje. Softverski objekti drže svoje stanje u jednoj ili više varijabli. Varijabla je promjenjiva vrijednost koja ima ime. Softverski objekti implementiraju svoje ponašanje uz pomo ć metoda. Metoda je funkcija (podrutina) pridružena objektu. Definicija: Objekt je skup varijabli i pridruženih metoda. Objekti stvarnog svijeta mogu se predstaviti softverskim objektima. Stvarni psi mogu se predstaviti softverskim objektima u programu za animaciju, kao što se i stvarni bicikl može predstaviti softverskim objektom u programu koji kontrolira vježbu na elektronič kom biciklu. Softverski objekti mogu se koristiti i za modeliranje apstraktnih koncepata. Na primjer, događ aj (event) je zajednič ki objekt korišten u GUI prozorskim sustavima za predstavljanje akcije pritiskanja puceta miša ili tipke na tipkovnici. Slijedećom se ilustracijom najčešće vizualno prikazuje izgled softverskog objekta: Sve što softverski objekt zna (stanje) i sve što može č initi (ponašanje) predstavljeno je varijablama i metodama unutar objekta. Softverski objekt koji modelira vaš stvarni bicikl imat 9

10 će tako varijable koje č uvaju trenutno stanje bicikla: njegovu brzinu 10 km/h, broj okretaja pedala 90 o/min, i trenutnu brzinu 5. Ove varijable su formalno poznate kao varijable objekta (instance variables) zato što drže stanje za točno određeni bicikl, a u objektno- orijentiranoj tehnologiji, određeni objekt zove se instanca (instance). Slijedeća slika prikazuje bicikl kao softverski objekt: Pored varijabli, softverski bicikl imat će metode za koč enje, promjenu brzine vrtnje pedala i promjenu brzina. Ove metode formalno se zovu metode objekta (instance methods) zato što provjeravaju ili mijenjaju stanje točno određenog bicikla. Objektni dijagram pokazuje da varijable sač injavaju centar, ili jezgru, objekta. Metode okružuju i skrivaju jezgru objekta od drugih objekata u programu. Pakiranje varijabli objekta unutar zaštitničkog položaja njegovih metoda naziva se učahurenje ili enkapsulacija ( encapsulation). Iako ova slika predstavlja idealno stanje objekta, u praksi, zbog određ enih razloga, objekt može izložiti svoje varijable okolini ili sakriti neke od metoda. U programskom jeziku Java moguć e je odrediti jedan od č etiri razine pristupa svakoj varijabli ili metodi objekta. Razina pristupa određuje koji će objekti i klase moći pristupiti varijablama ili metodama. Iako je učahurenje jednostavna ideja, ona omogućuje dvije osnovne prednosti programerima: Modularnost Izvorni kod objekta može se pisati i održavati neovisno o izvornom kodu drugih objekata. Takođ er, objekt se može jednostavno slati drugim objektima u sistemu. (Svoj bicikl možete posuditi nekome i on ć e i dalje raditi) Skrivanje informacija Objekt ima javno suč elje koje drugi objekti mogu koristiti kako bi komunicirali s njime. S druge strane, objekt može imati privatne informacije i metode koje se mogu bilo kada promijeniti, a da se time ne utič e na druge objekte koji o njemu ovise. (Nije potrebno da razumijete mehanizam promjene brzina da biste promijenili brzinu) ŠTO JE PORUKA? Objekt sam za sebe i nije previše koristan. Nasuprot tome, objekt se najčešć e javlja kao komponenta već eg programa ili aplikacije koja sadrži mnogo drugih objekata. Kroz međudjelovanje ovih objekata, programeri postižu već u funkcionalnost i kompleksnije ponašanje. Bicikl koji visi na kuki u garaži nije ništa nego komad željeza i gume sam po sebi bicikl nije sposoban ni za kakvu aktivnost. Koristan postaje tek onda kada drugi objekt (vi) počne djelovati na njega (pedalu). Softverski objekti međusobno komuniciraju uz pomo ć poruka ( messages). Kada objekt A poželi da objekt B izvrši neku od B-ovih metoda, objekt A poslat će poruku objektu B. 10

11 Ponekad objekt koji prima poruku treba više informacija kako bi nešto napravio; npr. kad poželite promijeniti brzinu na svom biciklu, morate odrediti željenu brzinu. Ove se informacije prenose s porukama kao parametri (parameters). Slijedeća slika prikazuje tri komponente koje sačinjavaju poruku: 1. Objekt kome je poruka namijenjena (YourBicycle) 2. Ime metode koju treba izvršiti (changegears) 3. Parametri potrebni metodi (lowergear) Ove tri komponente imaju dovoljno informacija kako bi objekt koji prima poruku izvršio što se od njega traži. Poruke omogućuju dvije važne prednosti: Ponašanje objekta izraženo je preko njegovih metoda, tako da slanje poruka (osim direktnog pristupa varijablama) podržava svaku moguću interakciju izmeđ u objekata. Objekti ne trebaju biti u istom procesu, čak ni na istom rač unalu kako bi slali i primali poruke jedan drugome. ŠTO JE KLASA? U stvarnom svijetu, mnogo je objekata istog tipa. Na primjer, vaš bicikl je samo jedan od mnogo takvih bicikala na svijetu. U objektno-orijentiranoj terminologiji kaže se da je vaš bicikl instanca (instance) klase objekata poznatih kao bicikl. Bicikli imaju neko stanje (trenutnu brzinu, brzinu vrtnje pedala, dva kotača) i ponašanje (promjenu brzine, kočenje). Međ utim, stanje nekog bicikla neovisno je (i najčešće različito) od stanja nekog drugog bicikla. Prilikom gradnje bicikla, proizvođači izrađuju mnogo bicikala po istom nacrtu. U objektno-orijentiranom softveru također je moguć e imati mnogo objekata istog tipa pravokutnike, podatke o zaposlenicima, video zapise itd. Softverski nacrt po kojem se kreiraju softverski objekti zove se klasa (class). 11

12 Definicija: Klasa je nacrt ili prototip koji definira varijable ili metode zajednič ke svim objektima određenog tipa. Klasa za bicikl deklarirat će varijable potrebne za č uvanje trenutne brzine, trenutne brzine okretanja pedala itd., i to za svaki objekt klase bicikl. Klasa će takođ er deklarirati i implementirati metode koje omogućuju vozaču promjenu brzina, koč enje i promjenu brzine vrtnje pedala. Nakon kreiranja klase za bicikl, možete kreirati po želji mnogo objekata klase bicikl. Kreiranjem instance klase, sistem će alocirati dovoljno memorije za č uvanje objekta i njegovih varijabli. Svaka instanca dobit će vlastitu kopiju svih varijabli objekta definiranih u klasi. Pored varijabli objekta, klase mogu definirati i varijable klase (class variables). Varijabla klase sadrži informacije koje dijele sve instance klase. Na primjer, pretpostavite da svi bicikli imaju isti broj brzina. U tom slučaju definiranje varijable objekta koja bi č uvala broj brzina bilo bi neekonomič no svaka bi instanca imala svoju vlastitu kopiju te varijable, ali bi vrijednost tih varijabli bila ista. U takvim se sluč ajevima varijabla deklarira kao varijabla klase, pa sve instance dijele takvu varijablu. Ako jedan objekt promijeni varijablu, promijenit ć e je za svaki objekt istog tipa. Klase također mogu deklarirati i metode klase ( class methods). Metode klase mogu se direktno pozvati nad klasom, dok se poziv metoda objekta obavlja nad određenom instancom klase. OBJEKTI PROTIV KLASA Vjerojatno se primijetili da klase i objekti izgledaju vrlo slično. I zbilja, razlika izmeđ u objekata i klasa nekome je izvor konfuzije. U stvarnom svijetu je oč ito da klase i objekti koje opisuju nisu isto: nacrt bicikla nije bicikl. Pa ipak, malo je teže razlikovati klase i objekte u softverskom svijetu. Ovo se dešava dijelom zato što su softverski objekti elektronič ki modeli objekata iz stvarnog svijeta, tj. predstavljaju prilično apstraktne pojmove. Izvor pomutnje nekad je i č esta (ali pogrešna) praksa da se termin "objekt" upotrebljava i za klase i za instance klasa. ŠTO JE NASLJEĐIVANJE? Općenito govoreći, objekti su definirani uz pomo ć klasa. O objektu znate mnogo ako znate njegovu klasu. Objektno-orijentirani sistemi dozvoljavaju definiranje klasa pomoć u drugih klasa. Na primjer, planinski bicikl, trkać i bicikl i bicikl dvosjed su vrste bicikala, a u objektnoj terminologiji to zovemo podklasama (subclasses) klase bicikala. 12

13 Svaka podklasa nasljeđuje ( iherits) stanje (u formi različ itih deklaracija varijabli) od svoje nadklase. Planinski bicikli, trkać i bicikli i bicikli dvosjedi dijele neka stanja: broj okretaja u minuti, brzinu i sl. Također svaka podklasa nasljeđ uje i metode svoje nadklase. Navedeni bicikli dijele neka ponašanja: kočenje i promjenu brzine vrtnje pedala, na primjer. Međutim, podklase nisu ogranič ene stanjima i ponašanjima svoje nadklase. Podklase mogu i dodati varijable i metode onima koje naslijede od svoje nadklase. Planinski bicikl ima npr. dodatni set brzina. Podklase također mogu nadvladati ( override) naslijeđene metode i omoguć iti specijalizirane implementacije tih metoda. Npr. ako imate planinski bicikl s dodatnim setom brzina, nadvladat ćete metodu "promijeni brzinu" tako da voza č može upotrijebiti i nove brzine. Nasljeđivanje nije ograničeno na jednu razinu. Stablo nasljeđivanja ili hijerarhija klasa ( class hierarchy) mogu biti po volji duboki. Metode i varijable nasljeđ uju se prema dolje kroz sve razine. Općenito vrijedi, što je klasa niže u hijerarhiji, njezino ponašanje je specijaliziranije. Klasa Object nalazi se na vrhu hijerarhije klasa i svaka klasa je njezin nasljednik (direktni ili indirektni). Varijabla tipa Object može sadržavati referencu na bilo koji objekt, kao što je instanca neke klase ili niza. Object omoguć ava ponašanja koja su potrebna za sve objekte koji se izvršavaju na Java Virtualnom Stroju. Na primjer, sve klase nasljeđuju metodu klase Object tostring, koja vraća tekstualnu reprezentaciju objekta. Nasljeđivanje nudi slijedeće prednosti: Podklase omogućuju specijalizirana ponašanja zajednič kih elemenata nadklase. Kroz upotrebu nasljeđ ivanja, programeri mogu mnogo puta ponovo upotrijebiti kôd napisan u nadklasi. Programeri mogu implementirati nadklase zvane abstraktne klase (abstract classes) koje definiraju generič ka ponašanja. Apstraktna klasa definira, a može i djelomično implementirati ponašanje, ali je već ina klase nedefinirana i neimplementirana. Drugi programeri popunjavaju detalje u specijaliziranim podklasama. 13

14 ŠTO JE SUČELJE (INTERFACE)? U hrvatskom, sučelje je uređ aj ili sistem kojeg nepovezani objekti upotrebljavaju kako bi komunicirali. Po ovoj definiciji, daljinski upravlja č je interface izmeđ u vas i televizora, hrvatski jezik je interface između dvije osobe, itd. Unutar programskog jezika Java, interface je uređ aj kojeg nepovezani objekti koriste kako bi međ usobno komunicirali. Interface je vjerojatno najslič niji protokolu (dogovoru o ponašanju). Drugi objektno-orijentirani jezici imaju funkcionalnost interfacea, ali ih zovu interface protokolima. Kada klasa implementira interface, ona se slaže da ć e implementirati sve metode definirane u interfaceu. Interface se može koristiti za definiranje protokola ponašanja koje može biti implementirano u bilo kojoj klasi unutar hijerarhije klasa. Interfacei su korisni zbog sljedećeg: Ističu sličnosti među nepovezanim klasama Deklariraju metoda koje jedna ili više klasa moraju implementirati Klijentu se otkriva interface objekta, a ne cijela klasa. 14

15 OSNOVE JEZIKA Program koji slijedi (BasicsDemo) zbraja brojeve od 1 do 10 i prikazuje rezultat. public class BasicDemo { public static void main(string[] args) { int sum = 0; for (int current=1; current<=10; current++) { sum += current; System.out.println("Sum = " + sum); Izlaz iz ovog programa je: Sum = 55 Čak i mali program kao što je ovaj koristi mnoge od tradicionalnih mogućnosti Jave, uključujuć i varijable, operatore i izraze za kontrolu toka programa. Kôd možda trenutno izgleda pomalo misteriozno, ali u ovom poglavlju naučit ćete sve osnovno što je potrebno da bi ga razumjeli. VARIJABLE Objekt čuva svoje stanje u varijablama. Definicija: Varijabla je promjenjivi podatak kojeg dohvaćamo njezinim identifikatorom. Za svaku varijablu potrebno je odrediti njezino ime i tip. Ime varijable mora biti dozvoljeni identifikator (identifier) neograničeni niz Unicode karaktera koji poč inju slovom. Kada želite pristupiti podacima koje varijabla sadržava koristite se njezinim imenom. Tip varijable određ uje koje vrijednosti ona može sadržavati i koje operacije mogu nad njom biti izvršene. Da bi varijabli dali ime i tip morate napisati deklaraciju (declaration) varijable, koja izgleda ovako: type name Osim imena i tipa varijable koje eksplicitno zadajete, varijabla ima i svoj doseg (scope). Doseg varijable je dio kôda u kojem se varijabli može pristupiti pomoć u njezinog jednostavnog imena. Doseg varijable implicitno je zadan lokacijom deklaracije varijable, tj. mjestom na kojem je deklaracija navedena u odnosu na ostatak kôda. Sljedeći program (MaxVarijablesDemo), prikazan dolje, deklarira osam varijabli različ itih tipova unutar main metode. Deklaracije varijabli su podebljane. public class MaxVarijablesDemo { public static void main(string args[]) { // cijeli brojevi byte largestbyte = Byte.MAX_VALUE; short largestshort = Short.MAX_VALUE; int largestinteger = Integer.MAX_VALUE; 15

16 long largestlong = Long.MAX_VALUE; // realni brojevi float largestfloat = Float.MAX_VALUE; double largestdouble = Double.MAX_VALUE; // drugi osnovni tipovi char achar = 'S'; boolean aboolean = true; // prikaži ih sve System.out.println("Najveća byte vrijednost je " + largestbyte); System.out.println("Najveća short vrijednost je " + largestshort); System.out.println("Najveća integer vrijednost je " + largestint); System.out.println("Najveća long vrijednost je " + largestlong); System.out.println("Najveća float vrijednost je " + largestfloat); System.out.println("Najveća double vrijednost je " + largestdouble); if(character.isuppercase(achar)) { System.out.println("Karakter " + achar + " je veliko slovo."); else { System.out.println)"Karakter " + achar + " je malo slovo."); System.out.println("Vrijednost od aboolean je " + aboolean); Izlaz prethodnog programa je: Najveća byte vrijednost je 127 Najveća short vrijednost je Najveća integer vrijednost je Najveća long vrijednost je Najveća float vrijednost je e+38 Najveća double vrijednost je e+308 Karakter S je veloko slovo. Vrijednost od aboolean je true U sljedećim poglavljima elaborirat ćemo različite aspekte varijabli, uključujuć i tipove podataka, imena, doseg, inicijalizaciju i konač ne varijable. Prethodni primjer koristi dvije stvari s kojima možda još niste upoznati, a koje ć e biti objašnjene kasnije nekoliko konstanti s imenom MAX_VALUE i if-else izraz. Svaka MAX_VALUE konstanta definirana je u jednoj od numeričkih klasa Java platforme i predstavlja najveć u vrijednost koju možete dodijeliti varijabli tog numeričkog tipa. 16

17 TIPOVI PODATAKA Svaka varijabla mora imati tip podatka. Tip podataka varijable određ uje vrijednosti koje varijabla može sadržavati i operacije koje se nad njom mogu vršiti. Na primjer, u MaxVariablesDemo programu, deklaracija int largestinteger deklarira da je varijabla largestinteger cjelobrojnog tipa (int). Cijeli brojevi (integers) mogu sadržavati samo cjelobrojne vrijednosti (pozitivne i negativne). Nad njima se mogu vršiti aritmetič ke operacije, kao što je zbrajanje. Java razlikuje dvije kategorije tipova podataka osnovne tipove (primitives) i reference (reference). Varijabla osnovnog tipa sadrži jednu vrijednost odgovarajuće velič ine i formata za taj tip broj, karakter ili logičku vrijednost. Na primjer, cijeli broj ( int) zauzima 32 bita podataka u formatu poznatom kao komplement broja dva, vrijednost char tipa zauzima 16 bitova formatiranih kao Unicode, itd. Tablica osnovnih tipova podataka Ključna riječ Opis Veličina/Format cijeli brojevi byte Cijeli broj duljine bajta 8-bita/komplement broja dva short Kratki cijeli broj 16-bita/komplement broja dva int Cijeli broj 32-bita/komplement broja dva long Dugi cijeli broj 64-bita/komplement broja dva realni brojevi float Realni broj jednostruke preciznosti 32-bita/IEEE 754 double Realni broj dvostruke preciznosti 64-bita/IEEE 754 drugi tipovi char Jedan znak (karakter) 16-bita/Unicode karakter boolean Logička vrijednost true ili false U drugim programskim jezicima (kao što je C) format i velič ina osnovnih tipova podataka može ovisiti o platformi na kojoj se program izvršava. Nasuprot tome, programski jezik Java toč no određuje velič inu i format svojih primitivnih tipova pa ne morate brinuti o sistemskim ovisnostima. Konstantne osnovne vrijednosti (tzv. literal) možete pisati direktno u kôdu. Na primjer, ako trebate dodijeliti vrijednost 4 nekoj cjelobrojnoj varijabli, to možete učiniti ovako: int cijelibroj = 4; Znamenka 4 je konstantna cjelobrojna vrijednost. Evo nekih primjera konstantnih vrijednosti za različite osnovne tipove: Konstantna vrijednost (literal) Tip podatka 178 int 8864L long double D double F float 26.77e3 double 'c' char true boolean false boolean 17

18 Općenito govoreći, niz znamenki bez decimalne točke kompajler ć e smatrati cijelim brojem (int). long cijeli broj možete specificirati stavljanjem slova 'L' ili 'l' poslije broja. Veliko slovo se preporučuje buduć i da se teže može zamijeniti sa znamenkom '1'. Niz znamenki s decimalnom točkom smatra se double tipom. Ako želite konstantu float tipa, potrebno je staviti slovo 'F' ili 'f' poslije broja. Znakovnom konstantom smatra se bilo koji Unicode karakter između jednostrukih navodnika. Dvije jedine boolean konstante su true i false. Nizovi, klase i interfacei su tzv. reference tipovi (reference types). Vrijednost varijable koja je tipa reference, za razliku od osnovnog tipa, predstavlja referencu na (ili adresu od) vrijednosti ili seta vrijednosti predstavljenih varijablom. Referenca se u drugim jezicima zove pokaziva č (pointer) ili memorijska adresa. Java ne podržava eksplicitnu upotrebu adresa koja je moguć a u drugim jezicima. Umjesto toga koriste se imena varijabli. IMENA VARIJABLI Program dohvaća vrijednost varijable preko njezinog imena. U primjeru MaxVariablesDemo program koristi ime largestbyte za prikazivanje varijable. Ime, kao što je largestbyte, koje se sastoji od jednog identifikatora, zove se jednostavno ime (simple name). Jednostavna imena se razlikuju od kvalificiranih imena (qualified names), koje klasa upotrebljava za pristup varijablama nekog drugog objekta ili klase. U Javi, sljedeći uvjeti moraju biti zadovoljeni za jednostavna imena: Ime mora biti neki od dozvoljenih identifikatora. Identifikator je neogranič en niz Unicode karaktera koji počinje slovom. Ime ne smije biti ključna rije č, logička konstanta ( true ili false) ili rezervirana rije č null. Ime mora biti jedinstveno unutar svog dosega. Varijabla može imati isto ime kao i neka druga varijabla koja je deklarirana unutar drugog dosega. U nekim sluč ajevima varijable mogu dijeliti isto ime ako su deklarirane unutar ugniježdenog bloka kôda. (Ovo će biti pokriveno u slijedećem poglavlju.) Po dogovoru: Imena varijabli poč inju malim slovom, a imena klasa velikim slovom. Ako se ime varijable sastoji od više od jedne riječi, riječi se spajaju, a svaka rije č poč inje velikim slovom, kao: ispointvisible. Underscore karakter (_) možete koristiti bilo gdje unutar imena, ali se po dogovoru koristi samo za odvajanje riječ i u konstantama (zato što su sva slova u imenu konstanti po konvenciji velika). 18

19 DOSEG (SCOPE) VARIJABLE Doseg varijable je regija programa unutar koje se varijabla može dohvatiti pomoć u svog jednostavnog imena. Doseg također određ uje kada sistem alocira i uništava memoriju varijable. Doseg se razlikuje od vidljivosti, koja se odnosi samo na varijable članove i određ uje da li varijabla može biti upotrijebljena izvan klase unutar koje je deklarirana. Vidljivost se dodjeljuje pomoću modifikatora pristupa. Lokacija deklaracije varijable unutar vašeg programa uspostavlja njezin doseg i stavlja ga u jednu od ove četiri kategorije: varijabla član ( member variable) lokalna varijabla (local variable) parametar metode (method parameter) parametar exception-handlera (exception-handler parameter) Varijabla član je č lan klase ili objekta. Deklarirana je unutar klase ali izvan metoda ili konstruktora. Doseg varijable člana je cijela deklaracija klase. Međutim, deklaracija č lana treba biti smještena prije nego se upotrijebi u inicijalizacijskom izrazu članova. Lokalna varijabla se deklarira unutar bloka kôda. Opć enito, doseg lokalne varijable širi se od njezine deklaracije do kraja bloka kôda u kojem je varijabla deklarirana. U MaxWariablesDemo programu sve su varijable deklarirane unutar main metode kao lokalne varijable. Doseg svake varijable u tom programu traje od deklaracije varijable do kraja main metode prve zatvorene vitičaste zagrade u kôdu programa. Parametri su formalni argumenti metoda ili konstruktora i koriste se za prosljeđ ivanje vrijednosti metodama i konstruktorima. Doseg parametra je cijelo tijelo metode ili konstruktora kojem je parametar argument. Parametri exception-handlera su slič ni parametrima, ali su argumenti exception handlera, a ne metode ili konstruktora. Doseg exception-handler parametra je blok kôda izmeđ u { i koji slijede catch izraz. O exception handlerima bavit ćemo se više u jednom od slijedeć ih poglavlja. 19

20 Promotrimo slijedeći primjer: if (...) { int i = 17;... System.out.println("Vrijednost od i = " + i ); // pogrešno! Posljednja linija se neće kompajlirati budući da je lokalna varijabla i izvan svog dosega. Doseg od i je blok kôda između { i. Varijabla i više ne postoji nakon završne zagrade. Ili se deklaracija varijable mora premjestiti izvan if bloka ili poziv metode println mora biti stavljen unutar if bloka. INICIJALIZACIJA VARIJABLI Lokalne varijable i varijable članovi mogu se inicijalizirati (postaviti na poč etne vrijednosti) unutar izraza dodjeljivanja na mjestu deklaracije. Tip podatka varijable mora odgovarati tipu podatka vrijednosti koja se varijabli dodjeljuje. U programu MaxVariablesDemo varijable su inicijalizirane na mjestu deklaracije (podebljano): // cijeli brojevi byte largestbyte = Byte.MAX_VALUE; short largestshort = Short.MAX_VALUE; int largestinteger = Integer.MAX_VALUE; long largestlong = Long.MAX_VALUE; // realni brojevi float largestfloat = Float.MAX_VALUE; double largestdouble = Double.MAX_VALUE; // drugi osnovni tipovi char achar = 'S'; boolean aboolean = true; Parametri metoda i parametri exception handlera ne mogu se inicijalizirati na ovaj nač in. Vrijednost parametra postavlja pozivatelj metode. KONAČNE VARIJABLE (FINAL VARIABLES) Varijabla se može u bilo kojem dosegu deklarirati kao konačna ( final). Vrijednost konač ne varijable ne može se više promijeniti nakon što se postavi na neku poč etnu vrijednost. Takve su varijable slične konstantama u nekim drugim jezicima. Da bi deklarirali konačnu varijablu, upotrijebite ključnu rije č final unutar deklaracije varijable, a prije njezinog tipa: final int afinalvar = 0; Prethodni izraz deklarira konačnu varijablu i inicijalizira je. Svaki slijedeć i pokušaj dodjeljivanja nove vrijednosti varijabli afinalvar rezultirat ć e kompajlerskom pogreškom. Inicijalizacija lokalne konačne varijable može se odgoditi: 20

21 final int blankfinal;... blankfinal = 0; Konačna lokalna varijabla koja je deklarirana, ali nije još inicijalizirana zove se prazna konač na varijabla (blank final). I za takve varijable vrijedi da se, jednom kada ih inicijalizirate, njihova vrijednost više ne može promijeniti. ZAKLJUČAK O VARIJABLAMA Prilikom deklaracije varijable, eksplicitno se određ uje njezino ime i tip. Java razlikuje dvije kategorije tipova podataka osnovne i reference. Osnovni tip sadrži vrijednost. Lokacija deklaracije varijable implicitno postavlja njezin doseg, koji određ uje dio kôda u kojem se varijabli može pristupiti pomoću njezinog jednostavnog imena. Postoje č etiri kategorije dosega: doseg varijabli č lanova, doseg lokalnih varijabli, doseg parametara i doseg parametara exception-handlera. Inicijalna vrijednost varijable može se pridružiti varijabli unutar njezine deklaracije uz pomoć operatora dodjeljivanja (=). Varijabla se može deklarirati da bude konačna. Vrijednost konač ne varijable ne može se promijeniti nakon inicijalizacije. 21

22 OPERATORI Operator izvršava funkciju nad jednim, dva ili tri operanda. Operator koji zahtjeva samo jednog operanda zove se unarni operator (unary operator). Na primjer, ++ je unarni operator koji uveć ava vrijednost svog operanda za 1. Operator koji zahtjeva dva operanda zove se binarni operator (binary operator). Na primjer, = je binarni operator koji dodjeljuje vrijednost desnog operanda lijevom operandu. I konačno, ternarni operator ( ternary operator) je onaj koji zahtjeva tri operanda. Programski jezik Java ima samo jedan ternarni operator?:, koji je skrać ena verzija if-else izraza. Unarni operatori mogu biti prefiksni ili postfiksni. Prefiksna notacija znač i da se operator navodi ispred svog operanda. operator op // prefiksna notacija Postfiksna notacija znači da se operator navodi iza svog operanda. op operator // postfiksna notacija Svi binarni operatori upotrebljavaju infiksnu notaciju, koja znači da operator stoji operanada. izmeđ u op1 operator op2 // infiksna notacija Ternarni operator je također infiksan; svaka komponenta operatora nalazi se između operanada: op1? op2 : op3 // infiksna notacija Pored izvršavanja operacija, operator vraća vrijednost. Vrijednost koju vrać a ovisi o operatoru i tipu operanada. Na primjer, aritmetički operatori, koji izvršavaju osnovne aritmetič ke operacije kao što je dodavanje i oduzimanje, vraćaju brojeve rezultat aritmetič ke operacije. Tip podatka kojeg vraća aritmetič ki operator ovisi o tipu njegovih operanada: Ako zbrajate dva cijela broja, dobit ćete cijeli broj. Operatori se dijele u ove kategorije: Aritmetički operatori Relacijski i uvjetni operatori Operatori pomaka i logički operatori Operatori dodjeljivanja Ostali operatori ARITMETIČKI OPERATORI Programski jezik Java podržava razne aritmetič ke operatore za realne i cijele brojeve. Ovi operatori su + (zbrajanje), - (oduzimanje), * (množenje), / (dijeljenje) i % (modul). 22

23 Sljedeća tablica prikazuje binarne aritmetičke operacije u Javi: Operator Upotreba Opis + op1 + op2 Zbraja op1 i op2 - op1 op2 Oduzima op2 od op1 * op1 * op2 Množi op1 s op2 / op1 / op2 Dijeli op1 s op2 % op1 % op2 Računa ostatak dijeljenja op1 s op2 Ovdje je primjer (ArithmeticDemo) koji definira dva cijela broja i dva realna broja dvostruke preciznosti te koristi pet aritmetičkih operatora za izvršavanje različ itih aritmetičkih operacija. Ovaj program također upotrebljava + za spajanje stringova. Aritmetičke operacije su podebljane: public class ArithmeticDemo { public static void main(string[] args) { // nekoliko brojeva int i = 37; int j = 42; double x = ; double y = 7.22; System.out.println("Vrijednosti varijabli..."); System.out.println(" i = " + i); System.out.println(" j = " + j); System.out.println(" x = " + x); System.out.println(" y = " + y); // Zbrajanje brojeva System.out.println("Zbrajanje..."); System.out.println(" i + j = " + (i+j)); System.out.println(" x + y = " + (x+y)); // Oduzimanje brojeva System.out.println("Oduzimanje..."); System.out.println(" i j = " + (i-j)); System.out.println(" x y = " + (x-y)); // Množenje brojeva System.out.println("Množenje..."); System.out.println(" i * j = " + (i*j)); System.out.println(" x * y = " + (x*y)); // Dijeljenje brojeva System.out.println("Dijeljenje..."); System.out.println(" i / j = " + (i/j)); System.out.println(" x / y = " + (x/y)); // Računanje ostatka dijeljenja System.out.println("Računanje ostatka..."); System.out.println(" i % j = " + (i % j)); System.out.println(" x % y = " + (x%y)); // Miješanje tipova System.out.println("Miješanje tipova..."); System.out.println(" j + y = " + (j+y)); System.out.println(" i * x = " + (i*x)); 23

24 Izlaz ovog programa je: Vrijednosti varijabli... i = 37 j = 42 x = y = 7.22 Zbrajanje... i + j = 79 x + y = Oduzimanje... i j = -5 x y = Množenje... i * j = 1554 x * y = Dijeljenje... i / j = 0 x / y = Računanje ostatka... i % j = 37 x % y = Miješanje tipova... j + y = i * x = Primijetite da je prilikom neke aritmetič ke operacije u kojoj je jedan operand cijeli broj, a drugi operand realni broj rezultat realni broj. Cijeli broj se implicitno pretvara u realni broj neposredno prije izvršenja operacije. Sljedeć a tablica rezimira tipove podataka koje vraćaju aritmetič ki operatori ovisno o tipu operanada. Potrebne konverzije izvršavaju se prije nego se izvrši operacija. Tip rezultata long int double float Tip operanada Ni jedan od operatora nije float ili double; barem je jedan operator long Ni jedan od operatora nije float ili double; nijedan operand nije long Barem jedan operand je double Barem jedan operand je float; nijedan nije double Pored binarne forme operatora + i -, svaki od ovih operatora ima svoju unarnu verziju koja izvodi sljedeće operacije: Operator Upotreba Opis + +op Pretvara op u int ako je op byte, short ili char - -op Aritmetički negira op Dva skraćena aritmetič ka operatora su ++ koji uvećava operand za 1 (increment) i -- koji umanjuje operand za 1 (decrement). I ++ i -- mogu se nać i ispred (kao prefiks) ili iza (kao postfiks) svog operanda. U prefiksnoj verziji izraz ++op/--op izrač unava se na osnovu vrijednosti operanda poslije uveć anja/umanjenja. U postfiksnoj verziji, vrijednost izraza izračunava se na osnovu vrijednosti operanda prije inkrementa/dekrementa. 24

25 Sljedeći program ( SortDemo) koristi ++ dvaput i -- jedan put. public class SortDemo { public static void main(string[] args) { int[] arrayofints = {32, 87, 3, 589, 12, 1076, 2000, 8, 622, 127; for(int i = arrayofints.length; --i>=0;) { for(int j = 0; j<i; j++) { if(arrayofints[j] > arrayofints[j+1]) { int temp = arrayofints[j]; arrayofints[j]=arrayofints[j+1]; arrayofints[j+1] = temp; for(int i=0; i<arrayofints.length; i++) { System.out.print(arrayOfInts[i] + " "); System.out.println(); Ovaj program stavlja 10 cjelobrojnih vrijednost u niz fiksne duljine te ih zatim sortira. Program deklarira niz arrayofints, kreira ga i stavlja deset cjelobrojnih vrijednosti u nega. Program također upotrebljava arrayofints.length kako bi dohvatio broj elemenata niza. Pojedinačni elementi niza dohvaćaju se sljedeć om notacijom - arrayofints[index] gdje je index cijeli broj koji označ ava poziciju elementa unutar niza. Primijetite da indeksi počinju od 0. Izlaz iz programa je lista brojeva sortiranih od najmanjeg do najvećeg. Pogledajmo kako SortDemo program koristi operator -- za kontrolu vanjske od dviju ugniježdenih petlji. Evo izraza koji kontrolira vanjsku petlju: for(int i = arrayofints.length; --i >= 0; ) {... for izraz objasnit ćemo u jednom od slijedeć ih poglavlja. Ono što je ovdje važno je podebljani kôd, koji nastavlja for petlju sve dok je vrijednost od --i već a ili jednaka nuli. Upotreba prefiksne verzije od -- znači da ć e posljednja iteracija ove petlje nastupiti kada je i jednak 0. Ako promijenimo kôd uz upotrebu postfiksne verzije od --, posljednja iteracija ove petlje izvršit će se kada je i jednak -1, što nije korektno u našem programu budući da se i upotrebljava kao indeks niza, a indeksi počinju od 0. Druge dvije petlje u programu koriste postfiksnu verziju operatora ++. U oba slučaja, upotrijebljena verzija ne utiče na rezultat, budući da se vrijednost izraza ne koristi. Kada se vrijednost ovakvog izraza ne koristi ni za što, po dogovoru se preferira postfiksna verzija. 25

26 RELACIJSKI I UVJETNI OPERATORI Relacijski operatori uspoređuju dvije vrijednosti i određuju odnos međ u njima. Na primjer,!= vraća true ako su dva operanda različita. Donja tablica prikazuje relacijske operatore: Operator Upotreba Vraća true ako > op1 > op2 je op1 veći od op2 >= op1 >= op2 je op1 veći ili jednak op2 < op1 < op2 je op1 manji od op2 <= op1 <= op2 je op1 manji ili jednak op2 == op1 == op2 su op1 i op2 jednaki!= op1!= op2 su op1 i op2 različiti Relacijski se operatori č esto upotrebljavaju uz uvjetne operatore radi kreiranja kompleksnijih izraza. Java podržava šest uvjetnih operatora - pet binarnih i jedan unarni, kao u sljedeć oj tablici: Operator Upotreba Vraća true ako && op1 && op2 su i op1 i op2 true op1 op2 su op1 ili op2 true!!op je op false & op1 & op2 su i op1 i op2 true op1 op2 su ili op1 ili op2 true ^ op1 ^ op2 ako su op1 i op2 različiti, tj. ako je jedan od operanada true, ali ne oba Promotrimo jedan od operatora - && koji izvršava uvjetnu I (AND) operaciju. Sljedeć a linija kôda koristi moguć nost operatora && za provjeru da li su oba uvjeta zadovoljena, tj. da li je indeks između granica. Utvrđuje da li je indeks veći ili jednak nuli i manji od NUM_ENTRIES (neka prethodno definirana konstantna vrijednost). 0 <= index && index < NUM_ENTRIES Primijetite da se nekada vrijednost drugog operanda nikada ne procjenjuje. Na primjer: (numchars < LIMIT) && (...) Operator && će vratiti true samo ako su oba operanda true. Stoga, ako je numchars veći ili jednak konstanti LIMIT, lijevi operand od && je false i vrijednost cijelog izraza zna se i bez procjene desnog operanda. U takvom slučaju interpreter će ignorirati desni operand. Ovo je važna posljedica, budući da možete očekivati da je npr. neka funkcija koju pozivate u desnom operandu pozvana, a nije. Kada su oba operanda tipa boolean, operator & se ponaša isto kao i &&. Isto vrijedi i za i. Međutim, kada su operandi brojevi, & i izvršavaju operacije nad njihovim bitovima. OPERATORI POMAKA I LOGIČKI OPERATORI 26

27 Operator pomaka (shift operators) izvršava operacije nad bitovima tako što bitove prvog operanda pomiče udesno ili ulijevo. Ova tablica prikazuje operatore pomaka u Javi: Operator Upotreba Operacija >> op1 >> op2 pomiče bitove od op1 udesno za op2 mjesta << op1 >> op2 pomiče bitove od op1 ulijevo za op2 mjesta >>> op1 >>> op2 pomiče bitove od op1 udesno za op2 mjesta (unsigned - bez predznaka) Svaki operator pomič e bitove lijevog operanda za broj mjesta zadan desnim operatorom. Pomak se dešava u smjeru označenom samim operatorom. Npr. slijedeći izraz pomič e bitove broja 13 udesno za jednu poziciju: 13 >> 1; Binarna reprezentacija broja 13 je Rezultat operacije pomaka je 1101 pomaknut udesno za jedno mjesto - 110, tj. decimalno 6. Lijevi bitovi dopunjavaju se nulama. Sljedeća tablica prikazuje četiri operatora u Javi koji omogućuju operacije nad bitovima svojih operanada. Operator Upotreba Operacija & op1 & op2 i (and) op1 op2 ili (or) ^ op1 ^ op2 ekskluzivno ili (xor) ~ ~op komplement Kada su operandi brojevi, operacija & izvršava AND funkciju na odgovarajućim bitovima svakog operanda. AND funkcija postavlja rezultantni bit na 1 ako su odgovarajući bitovi u oba operanda 1, kao u tablici: op1 op2 Rezultat Pretpostavimo da AND-ate vrijednosti 13 i 12 (13 & 12). Rezultat ove operacije je 12 jer je binarna reprezentacija broja , a binarna reprezentacija broja Kada su operandi brojevi, operator izvršava operaciju ILI (OR), a operator ^ operaciju EKSKLUZIVNO ILI (XOR). Evo i tablice za operaciju ILI: op1 op2 Rezultat Ekskluzivno ili znači da će rezultat operacije bili 1 samo ako su pripadni bitovi operanada različiti. U suprotnom je rezultat 0. 27

28 op1 op2 Rezultat Konačno, operator komplementa mijenja vrijednosti svakog bita operanda na način ako je bit 1, rezultat je 0 i ako je bit 0, rezultat je 1. Pored ostalog, operatori nad bitovima korisni su za definiranje tzv. zastavica (flags). Umjesto definiranja više boolean varijabli istog skupa, moguće je definirati jednu jedinu varijablu, npr. flags, u kojoj će svaki bit predstavljati jedno stanje (true ili false). Kasnija provjera stanja zastavica jednostavno se svode na provjeru pojedinih bitova varijable flags. Evo kako se to radi u praksi: static final int VISIBLE = 1; static final int DRAGGABLE = 2; static final int SELECTABLE = 4; static final int EDITABLE = 8; int flags = 0; Za postavljanje "visible" flaga možete upotrijebiti slijedeći izraz: flags = flags VISIBLE; Za provjeru vidljivosti možete napisati: if( (flags & VISIBLE) == VISIBLE) {... OPERATORI DODJELJIVANJA Za dodjeljivanje jedne vrijednosti drugoj koristi se osnovni operator =. U Javi postoji i nekoliko drugih operatora dodjeljivanja koji omogućavaju kraće pisanje nekih često korištenih operacija. Ako želite dodati broj varijabli i rezultat potom spremiti u istu varijablu to ćete učiniti ovako: i = i + 2; Ovaj izraz možete kraće pisati uz upotrebu operatora +=, kao ovdje: i += 2; Prethodne dvije linije koda su istovjetne. Sljedeća tablica prikazuje skraćene operatore dodjeljivanja i njihove duže ekvivalente: Operator Upotreba Ekvivalentno += op1 += op2 op1 = op1 + op2 -= op1 -= op2 op1 = op1 - op2 28

29 *= op1 *= op2 op1 = op1 * op2 /= op1 /= op2 op1 = op1 / op2 %= op1 %= op2 op1 = op1 % op2 &= op1 &= op2 op1 = op1 & op2 = op1 = op2 op1 = op1 op2 ^= op1 ^= op2 op1 = op1 ^ op2 <<= op1 <<= op2 op1 = op1 << op2 >>= op1 >>= op2 op1 = op1 >> op2 >>>= op1 >>>= op2 op1 = op1 >>> op2 DRUGI OPERATORI Sljedeća tablica prikazuje ostale operatore u Javi: Operator Opis?: Skraćena verzija if-else izraza [] Koristi se za deklariranje nizova, kreiranje nizova i pristup elementima niza. Koristi se za formiranje kvalificiranih imena ( params ) Odvaja listu parametara odvojenih zarezima ( type ) Pretvara vrijednost u neki tip (cast) new Kreira novi objekt ili niz instanceof Određuje da li je prvi operand instanca drugog operanda SKRAĆENI IF-ELSE IZRAZ Operator?: je uvjetni operator koji se koristi kao skraćena verzija op1? op2 : op3?: operator vraća op2 ako je op1 true, ili vraća op3 ako je op1 false. if-else izraza: OPERATOR [ ] Uglate zagrade koriste se za deklariranje nizova, kreiranje nizova i pristup određ enom elementu niza. Evo primjera deklaracije niza: float[] arrayoffloats = new float[10]; Prethodni kod deklarira niz koji može držati deset realnih (float) brojeva. Evo kako pristupiti sedmom elementu niza: arrayoffloats[6]; Indeksi niza počinju od nule. OPERATOR. 29

30 Pomoću operatora točka (.) pristupa se članovima objekta ili klase. OPERATOR () Prilikom deklariranja ili zvanja metode, argumenti metode navode se izmeđ u ( i ). () predstavlja praznu listu argumenata. OPERATOR (type) Pretvara (tzv. cast) vrijednost u neki tip podataka. OPERATOR new Operator new se koristi za kreiranje novih objekata ili novih nizova. Evo primjera kreiranja novog cijelog broja iz Integer klase (nalazi se u java.lang paketu). Integer aninteger = new Integer(10); OPERATOR instanceof instanceof operator provjerava da li je prvi operand instanca drugog. op1 instanceof op2 op1 mora biti ime objekta, a op2 ime klase. 30

31 IZRAZI, ISKAZI I BLOKOVI Varijable i operatori predstavljaju osnovne građevne blokove programa. Kombinirajuć i konstante, varijable i operatore dobivaju se izrazi - dijelovi kôda koji izračunavaju i vrać aju vrijednosti. Neki izrazi mogu se uobličiti u iskaze - kompletne jedinice izvršavanja. Grupirajuć i iskaze unutar vitičastih zagrada dobivaju se blokovi kôda. IZRAZI (EXPRESSIONS) Izrazi čine korisni rad programa. Pored ostalih stvari, izrazi se upotrebljavaju za prorač une i dodjeljivanje vrijednosti varijablama te za pomo ć kontroli toka programa. Posao izraza je dvostruk: izvršavanje proračuna elemenata izraza i vraćanje vrijednosti tog proračuna. Definicija: Izraz je niz varijabli, operatora i poziva metoda koji rezultira jedinstvenom vrijednošću. Kako je pokazano u prethodnom poglavlju, operatori vrać aju vrijednost, tako da upotreba operatora predstavlja jednostavni izraz. U izvatku iz MaxVariablesDemo programa istaknuti su neki izrazi: // Ostali osnovni tipovi char achar = 'S'; boolean aboolean = true; // Prikaži ih sve System.out.println("Najveća byte vrijednost je " + largestbyte);... if(character.isuppercase(achar)) {... Svaki od ovih izraza izvršava operaciju i vraća vrijednost. Izraz Akcija Vraćena vrijednost achar = 'S' Dodijeli karakter 'S' char varijabli achar Vrijednost od achar nakon dodjeljivanja ('S') "Najveća byte Spaja string "Najveća byte String "Najveća byte vrijednost je " + vrijednost je " i vrijednost vrijednost je 127" largestbyte Character.isUpperCase( achar) od largestbyte Poziv metode isuppercase Povratna vrijednost metode - true Tip vraćene vrijednosti izraza ovisi o elementima upotrijebljenim u izrazu. Izraz achar = 'S' vraća karakter budući da operator dodjeljivanja vrać a vrijednost istog tipa kao što su mu operandi, a achar i 'S' su karakteri. Programski jezik Java dozvoljava konstruiranje kompliciranijih izraza i iskaza od raznih manjih izraza dok god se topovi podataka u jednom dijelu izraza slažu s tipovima izraza u drugom. Evo i primjera kompliciranijeg izraza: 31

32 x * y * z U gornjem primjeru redoslijed izračuna nije bitan buduć i da je rezultat množenja neovisan o redu množenja. Međutim to nije istina za sve izraze. na primjer, slijedeći izraz će se drukč ije izračunati ovisno o tome da li se prvo primijeni zbrajanje ili dijeljenje. x + y / 100 Za izbjegavanje nedefiniranosti mogu se koristiti zagrade ( i ). Npr: (x + y) / 100 Ako se eksplicitno ne navede red po kojem želite izvršiti operacije kompliciranijih izraza, red se određuje prioritetom ( precedence) operatora unutar izraza. Operatori s već im prioritetom izračunavaju se prvi. Na primjer, operator dijeljenja ima već i prioritet od operatora zbrajanja. Stoga su sljedeća dva izraza istovjetna: x + y / 100 x + (y / 100) Prilikom pisanja složenih izraza preporuč uje se upotreba zagrada za operatore koji se trebaju izvršiti prvi, budući da to kôd čini lakšim za čitanje i održavanje. Sljedeć a tablica pokazuje prioritet operatora. Što je operator viši u tablici, viši mu je prioritet. Operatori višeg prioriteta rač unaju se prije operatora s relativno nižim prioritetom. Operatori u istom retku imaju isti prioritet. postfiksni operatori []. (params) expr++ expr-- unarni operatori ++expr --expr +expr -expr ~! kreiranje i cast-anje new (type)expr množenje * / % zbrajanje + - pomak << >> >>> relacijski < > <= >= instanceof jednakost ==!= AND & XOR ^ OR logički AND && logič ki OR uvjetni? : dodjeljivanje = += -= *= /= %= &= ^= = <<= >>= >>>= Kada se u istom izrazu nađu operatori istog prioriteta, mora postojati pravilo po kojem se računaju. Svi binarni operatori osim operatora dodjeljivanja se računaju s lijeva nadesno. Operator dodjeljivanja se računa s desna nalijevo. 32

33 ISKAZI (STATEMENTS) Iskazi su ekvivalentni rečenicama u prirodnim jezicima. Iskaz formira kompletnu jedinicu kôda za izvođenje. Sljedeći tipovi izraza mogu se učiniti iskazom ako se izraz završi točka-zarezom (;) Izrazi dodjeljivanja Bilo koja upotreba ++ ili -- Poziv metode Izraz kreiranja objekta Ovi tipovi iskaza zovu se engleski expression statements. Evo nekih primjera: avalue = ; avalue++; System.out.println(aValue); Integer integerobject = new Integer(4); Pored ovih iskaza, postoje još dva tipa. Deklaracijski iskaz (declaration statement) deklarira varijablu. Takve smo vidjeli do sada više puta: double avalue = ; Iskaz kontrole toka (control flow statement) kontrolira slijed kojim će se iskazi izvršavati. Primjer iskaza kontrole toka su for-petlja i if iskaz. BLOKOVI Blok (block) predstavlja grupu od nula ili više iskaza između vitič astih zagrada i može se koristiti bilo gdje, gdje je dozvoljeno korištenje jednog iskaza. Sljedeć i primjer pokazuje dva bloka u MaxVariablesDemo programu, od kojih svaki sadrži jedan iskaz. if(character.isuppercase(achar)) { System.out.println("Karakter " + achar + " je veliko slovo."); else { System.out.println("Karakter " + achar + " je malo slovo."); ZAKLJUČAK Izraz č ini niz varijabli operatora i poziva metoda koji se pretvaraju u jedinstvenu vrijednost. Složeni izrazi mogu se stvarati spajanjem jednostavnih izraza dok god su tipovi podataka koje zahtijevaju svi operatori u složenom izrazu korektni. Kod složenih izraza eksplicitno se može utjecati na redoslijed računanja upotrebom zagrada. Ako zagrade ne postoje, Java će prorač unati složeni izraz slijedom kojeg diktira prioritet operatora. Iskaz predstavlja samostalnu jedinicu izvršavanja i završava toč ka-zarezom (;). postoje tri tipa iskaza - iskazi s izrazima, iskazi deklaracija i iskazi kontrole toka. Nula ili više iskaz može se grupirati u blok kôda uz pomo ć vitičastih zagrada. 33

34 ISKAZI KONTROLE TOKA Program pišete, pišuć i iskaze u datoteku. Bez iskaza kontrole toka, interpreter bi izvršavao zadane iskaze redoslijedom kojim se nalaze u datoteci - s lijeva nadesno, odozgo nadolje. Iskaze kontrole toka možete upotrijebiti za uvjetno izvršavanje iskaza, za ponavljanje izvršavanja bloka iskaza i za druge izmjene normalnog, sekvencijalnog toka izvršavanja. Na primjer, u sljedećem komadiću koda, if-iskaz uvjetno izvršava System.out.println iskaz unutar vitičastih zagrada, ovisno o vrijednosti koju vraća Character.isUpperCase(aChar): char c;... if(character.isuppercase(achar)) { System.out.println("Karakter " + achar + " je veliko slovo."); Programski jezik java omogućava nekoliko iskaza kontrole toka navedenih u donjoj tablici: Tip iskaza Ključne riječi ponavljanje while, do-while, for donošenje odluke if-else, switch-case obrada iznimki (exception handling) try-catch-finnaly, throw grananje break, continue, label:, return U poglavljima koja slijede, primijetit ćete da slijedeća notacija predstavlja opć eniti oblik iskaza kontrole toka: detalji iskaza kontrole toka { iskaz(i) Tehnički, vitičaste zagrade nisu potrebne ako blok sadržava samo jedan iskaz. Međ utim, preporučljivo ih je uvijek upotrebljavati budući da je kôd jednostavniji za č itanje, a prilikom izmjene kôda smanjuje se mogućnost pogreške. while I do-while PETLJA While iskaz se koristi za neprekidno izvršavanje bloka iskaza dok je zadani uvjet istinit (true). Općenita sintaksa while iskaza je: while(expression) { statement While iskaz izračunava izraz u zagradama koji mora vrać ati boolean vrijednost. Ako je vrijednost izraza true, tada while iskaz izvršava iskaz (ili blok iskaza) koji slijedi. while iskaz nastavlja provjeru izraza i izvršava blok sve dok izraz ne vrati false. 34

35 Sljedeći primjer ( WhileDemo) koristi while iskaz kako bi prošao kroz karaktere stringa, dodajući svaki karakter stringa na kraj drugog stringa dok ne naiđe na slovo g. public class WhileDemo { public static void main(string[] args) { String copyfromme = "Kopiraj ovaj string dok ne naiđeš " + "na slovo 'g'"; StringBuffer copytome = new StringBuffer(); int i = 0; char c = copyfromme.charat(i); while(c!= 'g') { copytome.append(c); c = copyfromme.charat(++i); System.out.println(copyToMe); Izlaz ovog programa je: Kopiraj ovaj strin. do- U Javi postoji i drugi iskaz sličan while iskaza je: do { statement(s) while(expression); while iskazu - do-while iskaz. Općenita sintaksa Umjesto izračuna izraza na vrhu petlje, do-while rač una izraz na njenom dnu. Stoga se iskazi unutar do-while petlje izvršavaju barem jedan put. Evo i prethodnog programa prepisanog tako da koristi do-while. public class WhileDemo { public static void main(string[] args) { String copyfromme = "Kopiraj ovaj string dok ne naiđeš " + "na slovo 'g'"; StringBuffer copytome = new StringBuffer(); int i = 0; char c = copyfromme.charat(i); do { copytome.append(c); c = copyfromme.charat(++i); while(c!= 'g') System.out.println(copyToMe); Izlaz ovog programa je: Kopiraj ovaj strin. 35

36 for PETLJA for petlja omogućava jednostavan način iteriranja preko ranga nekih vrijednosti. Opć eniti oblik for petlje je: for(initialization; termination; increment) { statement Izraz initialization inicijalizira petlju - izvršava se samo jedan put na poč etku petlje. Izraz termination određuje kada će se petlja prekinuti. Ovaj se izraz računa na poč etku svake iteracije petlje. Kada izraz postane false, petlja se prekida. Konačno, izraz increment je izraz koji se poziva nakon svakog prolaska kroz petlju. Sve su ove komponente opcionalne. U biti, kako bi napisali beskonačnu petlju, dovoljno je izostaviti sva tri izraza. for( ; ; ) { Često se for petlje koriste za iteriranje nad elementima niza, ili karaktera u stringu. Sljedeć i primjer koristi for petlju za iteriranje nad elementima niza i ispisuje ih. public class ForDemo { public static void main(string[] args) { int[] arrayofints = { 32, 87, 3, 589, 12, 1076, 2000, 8, 622, 127; for(int i = 0; i < arrayofints.length; i++) { System.out.print(arrayOfInts[i] + " "); System.out.println(); Izlaz ovog programa je: Primijetite da možete deklarirati lokalnu varijablu unutar inicijalizacijskog izraza for petlje. Doseg ove varijable proteže se od njezine deklaracije do kraja bloka vođenog for petljom tako da se može upotrebljavati u termination i increment izrazima takođ er. Ako varijabla koja kontrolira for petlju nije potrebna van petlje, tada ju je najbolje ovako inicijalizirati. Imena i, j i k najčešće se koriste za kontrolu for petlji; njihovo deklariranje unutar inicijalizacijskog izraza ograničava njihov život i smanjuje pogreške. if/else ISKAZI if iskaz omoguć ava vašem programu selektivno izvršavanje iskaza na osnovu nekog kriterija. Na primjer, pretpostavimo da vaš program ispisuje neke informacije ovisno o vrijednosti boolean varijable zvane DEBUG. Ako je DEBUG true, vaš program ispisuje informaciju, npr. vrijednost varijable. U suprotnom, program preskače na sljedeć i iskaz. Segment kôda koji ovo implementira može izgledati ovako: if (DEBUG) { System.out.println("DEBUG: x = " + x); 36

37 Ovo je najjednostavnija verzija if izraza. Blok koji slijedi if izvršit ć e se ako je uvjet istinit. Općenito to izgleda ovako: if (expression) { statement(s) Što ako želite izvršiti različiti set iskaza ako je izraz false? Tada ćete koristiti else iskaz. Promotrite sljedeći primjer. Pretpostavimo da program treba izvršiti različ ite akcije ovisno o tome da li je korisnik kliknuo na OK puce ili neko drugo u prozoru s porukom o nekom upozorenju. Vaš program može to učiniti upotrebom if iskaza za kojim slijedi else iskaz. if (response == OK) { // kôd kojeg treba izvršiti ako je pritisnut OK else { // kôd kojeg treba izvršiti ako je pritisnut Cancel Else blok koda se izvršava ako je if izraz false. Druga forma else iskaza je else if, a izvršava iskaz na osnovu drugog izraza. If iskaz može imati po volji mnogo pripadnih else if iskaza, ali samo jedan else. Sljedeć i program dodjeljuje ocjenu na bazi broja bodova u testu. 5 za 90% bodova ili više, B za 80% bodova ili više, itd. public class IfElseDemo { public static void main(string [] args) { int testscore = 76; int grade; if(testscore >= 90) { grade = 5; else if(testscore >= 80) { grade = 4; else if(testscore >= 70) { grade = 3; else if(testscore >= 60) { grade = 2; else { grade = 1; System.out.println("Grade = " + grade); Izlaz iz ovog programa je: Grade = 3; Možda ste primijetili da vrijednost od testscore može zadovoljiti više od jednog izraza u složenom if iskazu: 76 >= 70 i 76 >= 60. Međutim, sistem procesira složenu if komandu i nailazi na izraz koji je zadovoljen, izvršavaju se pripadni iskazi i kontrola potom izlazi van if iskaza bez računanja uvjeta koji slijede. Programski jezik Java podržava operator?:, koji predstavlja skraćenu verziju primjer, if iskaz iz jednog od prethodnih primjera: if iskaza. Na 37

38 if(character.isuppercase(achar)) { System.out.println("Karakter " + achar + " je veliko slovo."); else { System.out.println("Karakter " + achar + " je malo slovo"); može se prepisati upotrebom?: operatora: System.out.println("Karakter " + achar + " je " + (Character.isUpperCase(aChar)? "veliko" : "malo") + "slovo."); switch ISKAZ Switch iskaz se koristi za uvjetno izvršavanje iskaza ovisno o nekom cjelobrojnom izrazu. Sljedeći primjer deklarira cijeli broj - month č ija bi vrijednost trebala sadržavati mjesec u datumu. Program ispisuje ime mjeseca u ovisnosti o vrijednosti month varijable, uz upotrebu switch iskaza. public class SwitchDemo { public static void main(string[] args) { int month = 8; switch(month) { case 1: System.out.println("Siječanj"); break; case 2: System.out.println("Veljača"); break; case 3: System.out.println("Ožujak"); break; case 4: System.out.println("Travanj"); break; case 5: System.out.println("Svibanj"); break; case 6: System.out.println("Lipanj"); break; case 7: System.out.println("Srpanj"); break; case 8: System.out.println("Kolovoz"); break; case 9: System.out.println("Rujan"); break; case 10: System.out.println("Listopad"); break; case 11: System.out.println("Studeni"); break; case 12: System.out.println("Prosinac"); break; switch iskaz računa izraz unutar zagrada (u ovom slučaju vrijednost od month) i izvršava pripadni case iskaz. Stoga je izlaz iz programa: Kolovoz. Naravno, switch iskaz se uvijek može implementirati uz pomo ć ekvivalentnog if-else iskaza. O programerovoj procjeni ovisi da li će upotrijebiti if iskaz ili switch iskaz. Odluka se najčešće donosi ovisno o čitljivosti i drugim faktorima. if iskaz se može koristiti za donošenje odluka ovisno o rangu vrijednosti ili uvjeta, dok switch iskaz može donositi odluke samo na osnovu jedne cjelobrojne vrijednosti. Drugi interesantni dio switch iskaza je break iskaz koji se pojavljuje nakon svakog case iskaza. Svaki break iskaz prekida switch iskaz i izvršavanje programa se nastavlja sa prvim iskazom koji slijedi nakon switch bloka. break iskaz je neophodan jer će bez njih case iskaz nastaviti s izvršavanjem sljedećeg case iskaza. Evo kako to svojstvo može biti i korisno: 38

39 public class SwitchDemo2 { public static void main(string[] args) { int month = 2; int year = 2000; int numdays = 0; switch (month) { case 1: case 3: case 5: case 7: case 8: case 10: case 12: numdays = 31; break; case 4: case 6: case 9: case 11: numdays = 30; break; case 2: if ( ((year % 4 == 0) && (year % 100!= 0)) (year % 400 == 0) ) numdays = 29; else numdays = 28; break; System.out.println("Broj dana = " + numdays); Izlaz iz programa je: Broj dana = 29 Tehnički, posljednji break nije potreban buduć i da bi izvršavanje programa ionako ispalo iz switch iskaza. Međutim, uvijek se preporučuje upotreba break-a i za posljednji case iskaz za slučaj da je kasnije potrebno dodati još case iskaza. Ovo omoguć ava lakšu modifikaciju kôda i manje pogrešaka. Na koncu, možete upotrijebiti default iskaz na kraju switch-a radi obrade svih vrijednosti koje nisu eksplicitno obrađene u jednom od case iskaza. public class SwitchDemo { public static void main(string[] args) { int month = 8; switch(month) { case 1: System.out.println("Siječanj"); break; case 2: System.out.println("Veljača"); break; case 3: System.out.println("Ožujak"); break; case 4: System.out.println("Travanj"); break; case 5: System.out.println("Svibanj"); break; case 6: System.out.println("Lipanj"); break; 39

40 case 7: System.out.println("Srpanj"); break; case 8: System.out.println("Kolovoz"); break; case 9: System.out.println("Rujan"); break; case 10: System.out.println("Listopad"); break; case 11: System.out.println("Studeni"); break; case 12: System.out.println("Prosinac"); break; default: System.out.println("Hej, ovo nije valjan " + "mjesec!"); break; 40

41 ISKAZI OBRADE IZNIMKI (EXCEPTION HANDLING STATEMENTS) Radi lakše obrade pogreški Java podržava mehanizam poznat kao iznimke (exceptions). Kada nastupi pogreška, program baca iznimku (exception throwing). To znač i da se normalni tok programa prekida, a runtime okruženje pokušava pronaći tzv. exception handler - blok koda koji je sposoban obraditi određ eni tip pogreške. U exception handleru se program treba pokušati oporaviti od pogreške ili, ako zaključi da to nije moguće, omogućiti što nježniji prekid rada. Tri se iskaza koriste za obradu iznimki: try iskaz predstavlja blok iskaza unutar kojeg iznimka može biti bačena. catch iskaz, koji mora biti pridružen try iskazu, predstavlja blok iskaza koji je u stanju obraditi određeni tip iznimke. Iskazi unutar catch bloka izvršit ć e se ako nastupi određeni tip iznimke unutar try bloka. finally iskaz, koji također mora biti pridružen try iskazu, predstavlja blok iskaza koji se izvršavaju bez obzira na to da li je ili nije pogreška nastupila unutar try bloka. Ovo je općenita forma ovih iskaza: try { statement(s) catch (exceptiontype name) { statement(s) catch (exceptiontype2 name) { statement(s) finally { statement(s) Opis različitih tipova iznimki, hijerarhija exception klasa te drugi faktori u obradi iznimki bit ć e detaljno obrađeni u lekciji Obrada pogreški uz pomo ć iznimki. ISKAZI GRANANJA (BRANCHING STATEMENTS) Programski jezik Java podržava tri iskaza grananja: break iskaz continue iskaz return iskaz Iskaz break i iskaz continue mogu se upotrebljavati sa ili bez labele. Labela (label) predstavlja identifikator iskaza, iza kojeg slijedi dvotočka (:). labelname: somejavastatement; Primjer labele unutar programa dan je u sljedećem poglavlju. 41

42 ISKAZ break Iskaz break ima dva oblika: bez labele i s labelom. Oblik break iskaza bez labele vidjeli ste ve ć u primjeru upotrebe switch iskaza. Kako je tamo rečeno, break bez labele prekida switch iskaz unutar kojeg se nalazi, a kontrola toka se prenosi na iskaz koji slijedi neposredno nakon switch-a. Ova forma break iskaza se koristi i za prekidanje for, while i do-while petlji. Sljedeći primjer ( BreakDemo), sadrži for petlju koja traži određ enu vrijednost unutar niza: public class BreakDemo { public static void main(string[] args) { int[] arrayofints = { 32, 87, 3, 589, 12, 1076, 2000, 8, 622, 127 ; int searchfor = 12; int i = 0; boolean foundit = false; for ( ; i < arrayofints.length; i++) { if (arrayofints[i] == searchfor) { foundit = true; break; if (foundit) { System.out.println("Pronađen "+searchfor+ "na mjestu " + i); else { System.out.println(searchfor + "nije u nizu"); Iskaz break prekida for petlju kada je vrijednost pronađ ena. Kontrola toka premješta se na prvi iskaz nakon for petlje. Izlaz iz ovog programa je: Pronađen 12 na mjestu 4. Oblik break iskaza bez labele koristi se za prekid switch, for, while i do-while iskaza unutar kojeg se break iskaz nalazi. Oblik s labelom koristi se za prekid vanjskog iskaza, označenog tom labelom. Sljedeći je program ( BreakWithLabelDemo) slič an prethodnom, ali traži vrijednost u dvodimenzionalnom nizu. Dvije ugniježdene for petlje upotrebljene su za pretraživanje niza. Kada se pronađe vrijednost, break iskaz prekida for petlju označ enu labelom search. public class BreakWithLabelDemo { public static void main(string[] args) { int[][] arrayofints = { { 32, 87, 3, 589, { 12, 1076, 2000, 8, { 622, 127, 77,

43 int searchfor = 12; ; int i = 0; int j = 0; boolean foundit = false; search: for ( ; i < arrayofints.length; i++) { for (j = 0; j < arrayofints[i].length; j++) { if (arrayofints[i][j] == searchfor) { foundit = true; break search; if (foundit) { System.out.println("Pronađen je " + searchfor + " na mjestu " + i + ", " + j); else { System.out.println(searchfor + " nije u nizu"); Izlaz ovog programa je: Pronađen je 12 na mjestu 1, 0 Pazite! Iskaz break prekida labelom označ eni iskaz; on ne prenosi tok izvršavanja na labelu. Kontrola toka se prenosi na iskaz koji neposredno slijedi nakon označ ene (prekinute) petlje - iskaza. ISKAZ CONTINUE Iskaz continue koristi se za preskakanje trenutne iteracije for, while i do-while petlje. Ovakav oblik continue iskaza preskače ostatak pripadne petlje i vraća se na njezin poč etak. Sljedeći program ( ContinueDemo), putuje string spremnikom i provjerava svako slovo. Ako promatrani karakter stringa nije slovo p, continue iskaz će preskoč iti ostatak petlje i nastaviti sa sljedećim karakterom. Ako je pronađen p, program će uvećati broja č p-ova i pretvoriti p u veliko slovo. public class ContinueDemo { public static void main(string[] args) { StringBuffer searchme = new StringBuffer( "peter piper picked a peck of pickled peppers"); int max = searchme.length(); int numps = 0; for (int i = 0; i < max; i++) { //interested only in p's 43

44 if (searchme.charat(i)!= 'p') continue; //process p's numps++; searchme.setcharat(i, 'P'); System.out.println("Found " + numps + " p's in the string."); System.out.println(searchMe); Evo i izlaza ovog programa: Found 9 p's in the string. Peter PiPer Picked a Peck of Pickled Peppers Oblik continue iskaza s labelom preskače trenutnu iteraciju neke vanjske petlje označ ene zadanom labelom. Primjer (ContinueWithLabelDemo) koristi ugnježdene petlje za traženje podstringa unutar drugog stringa. Dvije ugnježdene petlje su potrebne; jedna za iteriranje uzduž podstringa i jedna za iteriranje uzduž stringa po kojem se traži. Ovaj program koristi labelirani oblik continue iskaza kako bi izašao iz unutrašnje petlje. public class ContinueWithLabelDemo { public static void main(string[] args) { String searchme = "Look for a substring in me"; String substring = "sub"; boolean foundit = false; int max = searchme.length() - substring.length(); test: for (int i = 0; i <= max; i++) { int n = substring.length(); int j = i; int k = 0; while (n--!= 0) { if (searchme.charat(j++)!= substring.charat(k++)) { continue test; foundit = true; break test; System.out.println(foundIt? "Found it" : "Didn't find it"); Evo i izlaza programa: Found it ISKAZ return 44

45 Posljednji od Javinih iskaza grananja je iskaz return. return se koristi za izlaz iz trenutne metode. Kontrola toka se vraća na iskaz koji je slijedio pozivu metode. return iskaz ima dva oblika: onaj koji vraća vrijednost i onaj koji to ne čini. Za vrać anje vrijednosti potrebno je staviti vrijednost (ili izraz koji računa vrijednost) poslije ključne riječi return, npr.: return ++count; Tip vrijednosti koju vraća return mora se slagati s tipom podataka koji je naveden kao tip povratne vrijednosti metode. Kod metoda deklariranih kao void, koristi se oblik koji ne vraća vrijednost: return; ZAKLJUČAK O ISKAZIMA KONTROLE TOKA Za kontrolu toka programa, programski jezik Java ima tri oblika petlje, if-else iskaz i switch iskaz, iskaze obrade iznimki i iskaze grananja. PETLJE while petlju koristit ć ete za ponavljanje bloka iskaza sve dok je neki boolean izraz istinit. Vrijednost tog boolean izraza se izračunava na početku petlje: while (boolean expression) { statement(s) do-while petlju također ć ete koristiti za ponavljanje bloka izraza dok je neki boolean izraz istinit. Vrijednost izraza se proračunava na kraju petlje, pa se iskazi unutar do-while bloka izvršavaju barem jedan put: do { statement(s) while(expression); for petlja ponavlja blok iskaza, a uključ uje inicijalizacijski izraz, izraz prekida i izraz uvećavanja. for(initialization; termination; increment) { statement(s) ISKAZI DONOŠENJA ODLUKA Programski jezik Java ima dva iskaza za donošenje odluka: if-else i switch. Opć enitiji iskaz od ta dva je if iskaz; switch se koristi za donošenje odluka na osnovu cjelobrojne vrijednosti. Dolje je najjednostavniji oblik if iskaza čiji se blok koda izvršava ako je boolean izraz istinit: if(boolean expression) { statement(s) 45

46 Slijedi primjer if iskaza s pripadnim else iskazom. if iskaz izvršava prvi blok ako je boolean izraz istinit; u suprotnom izvršava drugi blok: if(boolean expression) { statement(s) else { statement(s) else-if konstrukcija se koristi za konstruiranje složenih if iskaza: if(boolean expression) { statement(s) else if(boolean expression 2) { statement(s) else if(boolean expression 3) { statement(s) else { statement(s) Iskaz switch procjenjuje cjelobrojni izraz i izvršava odgovarajući case iskaz. switch(integer expression) { case integer expression: statement(s) break;... default: statement(s) break; ISKAZI OBRADE IZNIMKI Iskazi try, catch i finally korsite se za obradu iznimki. try { statement(s) catch (exceptiontype name) { statement(s) catch (exceptiontype name) { statement(s) finally { statement(s) ISKAZI GRANANJA Neki iskazi grananja mijenjaju tok programa uz pomo ć labela. Labelom se zadaje ime iskazu: statementname: somejavastatement; 46

47 Oblik break iskaza bez labele koristi se za prekidanje switch, for, while i do-while iskaza kojem break pripada. break; Oblik break iskaza s labelom koristi se za prekid vanjskih switch, for, while i do-while iskaza imenovanih navedenom labelom. break label; Iskaz continue prekida trenutnu iteraciju unutrašnje petlje i vraća se na procjenu logič kog izraza koji kontrolira petlju. continue; Oblik continue iskaza s labelom prekida trenutnu iteraciju petlje imenovane navedenom labelom: continue label; Iskaz return se koristi za prekid trenutne metode. return; U funkcijama koje vraćaju neku vrijednost svom pozivatelju, koristi se oblik nekom vrijednošću: return iskaza s return value; 47

48 OSNOVE OBJEKATA Tipični Java program kreira mnogo objekata koji međusobno komuniciraju šaljuć i poruke. Kroz ovo međ udjelovanje Java program može implementirati GUI, pokrenuti animaciju ili slati i primati podatke po mreži. Jednom kada objekt obavi posao za koji je kreiran, automatski se č isti iz memorije (garbage-collecting), a njegovi se resursi oslobađ aju kako bi ih mogli koristiti drugi objekti. Ovdje je primjer (CreateObjectDemo) koji kreira tri objekta: objekt Point i dva objekta Rectangle. public class CreateObjectDemo { public static void main(string[] args) { // create a point object and two rectangle objects Point origin_one = new Point(23, 94); Rectangle rect_one = new Rectangle(origin_one, 100, 200); Rectangle rect_two = new Rectangle(50, 100); // display rect_one's width, height, and area System.out.println("Width of rect_one: " + rect_one.width); System.out.println("Height of rect_one: " + rect_one.height); System.out.println("Area of rect_one: " + rect_one.area()); // set rect_two's position rect_two.origin = origin_one; // display rect_two's position System.out.println("X Position of rect_two: " + rect_two.origin.x); System.out.println("Y Position of rect_two: " + rect_two.origin.y); // move rect_two and display its new position rect_two.move(40, 72); System.out.println("X Position of rect_two: " + rect_two.origin.x); System.out.println("Y Position of rect_two: " + rect_two.origin.y); Nakon kreiranja objekata program ih koristi i ispisuje neke informacije o njima. Evo izlaza programa: Width of rect_one: 100 Height of rect_one: 200 Area of rect_one: X Position of rect_two: 23 Y Position of rect_two: 94 X Position of rect_two: 40 Y Position of rect_two: 72 48

49 U ovom poglavlju iskoristit ć emo ovaj primjer radi opisivanja životnog ciklusa objekta unutar programa. Tako ćete nauč iti kako pisati programe koji kreiraju i koriste objekte te kako ih sistem briše. KREIRANJE OBJEKATA Kao što znate, klasa predstavlja nacrt objekta; objekti se kreiraju iz klasa. Ovi iskazi uzeti iz prethodnog primjera kreiraju objekte: Point origin_one = new Point(23, 94); Rectangle rect_one = new Rectangle(origin_one, 100, 200); Rectangle rect_two = new Rectangle(50, 100); Prva linija kreira objekt iz Point klase, a druga i treća kreiraju po objekt iz Svaki iskaz ima tri dijela: Rectangle klase. 1. Deklaracija - Deklaracije varijabli podebljane su u prethodnom listingu i služe za pridruživanje tipa podataka nekom imenu. 2. Instanciranje - Operator new je Java operator koji kreira novi objekt (alocira memorijski prostor za njega). 3. Inicijalizacija - Iza operatora new slijedi konstruktor. Npr. Point(23, 94) predstavlja poziv konstruktora klase Point. Konstruktor inicijalizira novi objekt. DEKLARIRANJE REFERENCE Iz poglavlja Varijable naučili ste da se varijabla deklarira ovako: type name Ovo obavještava kompajler o tome da ćete koristiti ime name za pristup podatku čiji je tip Pored osnovnih tipova podataka, kao što su int i boolean, klase i interfacei su takođ er tipovi. Stoga, za deklariranje verijable koja se odnosi na objekt, kao tip varijable navodi se ime klase ili interfacea. U prethodnom primjeru imena klasa Point i Rectangle koriste se kao tipovi za deklariranje varijabli. Point origin_one = new Point(23, 94); Rectangle rect_one = new Rectangle(origin_one, 100, 200); Rectangle rect_two = new Rectangle(50, 100); Deklaracije ne kreiraju nove objekte. Kôd Point origin_one ne kreira novi Point objekt ve ć samo deklarira varijablu origin_one (tzv. referencu), koja se korisiti za pristup objektu tipa Point. Referenca je inicijalno prazna. Prazna referenca je poznata kao null referenca (null reference). type. 49

50 Kako bi kreirali objekt, morate ga instancirati uz pomo ć operatora new. INSTANCIRANJE OBJEKTA Operator new instancira klasu alocirajući memoriju za novi objekt. Operator new zahtjeva samo jedan, postfiksni argument: poziv konstruktora. Ime konstruktora jednako je imenu klase koja se instancira. Konstruktor postavlja početno stanje novog objekta. Operator new vraća referencu na objekt koji se kreira. Najčešć e se ta referenca odmah i pridružuje varijabli prikladnog tipa. Ako se referenca ne pridruži varijabli, objektu neć e više biti moguće pristupiti. INICIJALIZIRANJE OBJEKTA Evo kôda za klasu Point: public class Point { public int x = 0; public int y = 0; // A constructor! public Point(int x, int y) { this.x = x; this.y = y; Ova klasa sadrži samo jedan konstruktor. Konstruktor se može prepoznati kao metoda koja ima isto ime kao i klasa kojoj pripada, a ne vraća podatke (ne navodi se čak ni ključna rije č void). Konstruktor klase Point uzima dva cjelobrojna argumenta, kao što je deklarirano u kodu (int x, int y). Sljedeći iskaz prosljeđuje brojeve 23 i 94 kao vrijednosti ovim argumentima: Point origin_one = new Point(23, 94); Efekt prethodne linije može se predstaviti sljedećom slikom: Evo i koda za Rectangle klasu koja sadrži četiri konstruktora: public class Rectangle { public int width = 0; public int height = 0; public Point origin; // Cetiri konstruktora 50

51 public Rectangle() { origin = new Point(0, 0); public Rectangle(Point p) { origin = p; public Rectangle(int w, int h) { this(new Point(0, 0), w, h); public Rectangle(Point p, int w, int h) { origin = p; width = w; height = h; // Metoda za pomicanje pravokutnika public void move(int x, int y) { origin.x = x; origin.y = y; // Metoda za racunanje povrsine pravokutnika public int area() { return width * height; Svaki konstruktor omogućava postavljanje početnih vrijednosti za različ ite aspekte pravokutnika: poziciju; širinu i visinu; svo troje; ili niti jedno. Ako klasa ima višestruke konstruktore, svi će oni imati isto ime, ali različiti broj argumenata ili argumente različ itih tipova. Java platforma razlikuje konstruktore po broju argumenata i njihovom tipu. Kada Java dođe do sljedećeg koda, zna da treba pozvati konstruktor u Rectangle klasi koji prihvać a argument tipa Point iza kojeg slijede dva cjelobrojna argumenta. Rectangle rect_one = new Rectangle(origin_one, 100, 200); Ovaj poziv postavlja varijablu origin (referencu) tako da pokazuje na objekt klase Point na kojeg ve ć pokazuje referenca origin_one. Kôd također postavlja width na 100 i height na 200. U tom će trenutku postojati dvije reference na isti Point objekt! 51

52 Višestruke reference mogu pokazivati na isti objekt. Sljedeć e linije koda pozivaju konstruktor koji zahtjeva dva cjelobrojna argumenta za width i height. Ako prouč ite kôd unutar konstruktora, vidjet ćete da kreira novi Point objekt čije su member varijable x i y inicijalizirane na nulu. Rectangle rect_two = new Rectangle(50, 100); Konstruktor klase Rectangle korišten u sljedećem iskazu ne uzima niti jedan argument ( tzv. no-argument constructor): Rectangle rect = new Rectangle(); Ako klasa eksplicitno ne deklarira niti jedan konstruktor, Java platforma ć e automatski omogućiti poziv no-argument konstruktora, zvanog default konstruktor, koji ne radi ništa. Znači, sve klase imaju bar jedan konstruktor. KORIŠTENJE OBJEKATA Jednom kada kreirate objekt, vjerojatno ćete ga poželjeti i upotrijebiti - zahtjevat ć ete informacije od njega, željet ćete promijeniti njegovo stanje ili ga natjerati da izvrši neku akciju. Objekte možete koristiti na dva načina: 1. Pristupajući njegovim varijablama. 2. Zvanjem njegovih metoda. REFERENCIRANJE VARIJABLE OBJEKTA Ovo je općeniti oblik dugog imena varijable (tzv. objectreference.variablename qualified name): Jednostavno ime se može koristiti za pristup varijablama instance unutar dosega varijable, tj. unutar klase. Kôd koji pristupa varijabli instance izvana mora koristiti dugo ime. Na primjer, kôd u CreateObjectDemo klasi nalazi se van kôda Rectangle klase. Stoga, da bi pristupili varijablama origin, width i height unutar Rectangle objekta koji se zove rect_one, CreateObjectDemo klasa mora koristiti imena rect_one.origin, rect_one.width i rect_one.height, respektivno. Program koristi ova imena za prikaz širine i visine rect_one pravokutnika. System.out.println("Width of rect_one: " + rect_one.width); System.out.println("Height of rect_one: " + rect_one.height); Ako pokušate koristiti jednostavna imena width i height iz koda u CreateObjectDemo klasi to neće imati smisla - te varijable postoje samo unutar objekta, pa ć e takav pokušaj rezultirati kompajlerskom pogreškom. 52

53 Kasnije program koristi sličan kôd za prikaz informacija o rect_two pravokutniku. Svaki objekti istog tipa ima svoju kopiju varijabli objekta. Stoga, svaki Rectangle objekt ima svoje varijable origin, width i height. Prvi dio kvalificiranog imena varijable, objectreference, mora biti referenca na objekt. Osim imena reference, moguće je koristiti i bilo koji izraz koji vrać a referencu na objekt. Podsjetite se da operator new vraća referencu na objekt. Tako biste mogli iskoristiti vrać enu vrijednost new operatora za pristup varijablama novog objekta: int height = new Rectangle().height; Ovaj iskaz kreira novi Rectangle objekt i odmah uzima njegovu visinu. U biti, iskaz izrač unava podrazumijevanu visinu pravokutnika. Primjetite da nakon što se ovaj iskaz izvrši, program više nema referencu na kreirani Rectangle, budući da ju nikad ne sač uva u nekoj varijabli. Objekt je nereferenciran i Java platforma oslobađa njegove resurse. O PRISTUPU VARIJABLAMA Direktan pristup varijablama izvan objekta se ne preporučuje, budući da je moguć e postaviti varijable na vrijednosti koje nemaju smisla. Na primjer, upotrebnom klase Rectangle moguć e je kreirati pravokutnik čije su širina i visina negativne. Idealno, umjesto dopuštanja direktnog pristupa varijablama, klasa treba omoguć iti metode kroz koje je moguć e ispitati ili mijenjati varijable. Ove metode osiguravaju da vrijednosti varijabli imaju smisla za objekte tog tipa. Stoga bi klasa Rectangle trebala imati metode setwidth, setheight, getwidth i getheight za postavljanje i uzimanje širine i visine. Metode za postavljanje varijabli bi prijavie pogrešku ako bi pozivatelj pokušao postaviti visinu i širinu na negativne vrijednosti. Druga prednost upotrebe metoda umjesto direktnog pristupa varijablama je što je kasnije moguć e promijeniti tip i imena varijabli klase bez da klijenti koji ju koriste moraju mijenjati svoj kôd. Međutim, u praktič noj primjeni, ponekad ima smisla dopustiti direktan pristup varijablama objekta. Na primjer, i klasa Point i klasa Rectangle dozvoljavaju slobodan pristup svojim varijablama-članovima deklarirajući ih kao javne - public. Zato su ove klase male i jednostavne. Programski jezik Java omogućava kontrolu pristupa elementima klase kojom je moguć e odrediti kako druge klase mogu ili ne mogu pristupiti njezinim varijablama. Klasa može zaštiti svoje varijable od direktne manipulacije od strane drugih objekata. Promjene takvih varijabli č inile bi se uz pomo ć poziva odgovarajućih metoda. Ako klasa omoguć ava pristup svojim varijablama, može se pretpostaviti da te varijable možete mijenjati bez loših posljedica. Također, uč inivši varijablu dostupnom, ta varijabla postaje dio API-ja klase što znač i da njen pisac ne bi kasnije trebao mijenjati njezin tip ili ime. POZIVI METODA OBJEKTA Kvalificirana imena se koriste i za pristup metodama objekta. Za formiranje kvalificiranog imena metode potrebno je spojiti ime metode s referencom na objekt uz pomo ć toč ke (.). Poslje imena metode, unutar zagrada, navode se argumenti metode. Ako metoda ne traži nikakve argumente, koriste se prazne zagrade. 53

54 ili objectreference.methodname(argumentlist); objectreference.methodname(); Klasa Rectangle ima dvije metode: area za računanje površine pravokutnika i move za promjenu pozicije pravokutnika. Ovdje je dio CreateOjectDemo koda koji poziva ove dvije metode: System.out.println("Area of rect_one: " + rect_one.area());... rect_two.move(40, 72); Prvi iskaz poziva metodu area objekta rect_one i prikazuje rezultate. Druga linije pomič e rect_two jer metoda move dodjeljuje nove vrijednosti varijablama origin.x i origin.y. Kao i s varijablama objekta, objectreference mora biti referenca na objekt. Možete koristiti ime varijable, ali možete koristiti bilo koji izraz koji vraća referencu na objekt. Operator new vraća referencu na objekt, pa se ta vrijednost može koristiti za zvanje metoda objekta. new Rectangle(100, 50).area() Izraz new Rectangle(100, 50) vraća referencu na objekt tipa Rectangle. Neke metode, kao što su area, vraćaju vrijednost. Poziv metode koja vrać a vrijednost može se koristiti kao dio izraza. Vrać ena vrijednost može se dodijeliti varijabli, koristiti za donošenje odluka ili za kontrolu petlje. Ovaj kôd dodjeljuje vrijednost koju vraća funkcija area varijabli: int areaofrectangle = new Rectangle(100, 50).area(); Zapamtite, izvođenje metode nad određ enim objektom je isto što i slanje poruke tom objektu. U ovom slučaju, objekt nad kojim je pozvana metoda area je objekt kojeg je vratio konstruktor. O PRISTUPU METODAMA Sve metode u klasama Point i Rectangle deklarirane su kao public, pa ih se može pozvati iz bilo koje druge klase. Ponekad je potrebno da klasa ogranič i (ili zabrani) pristup svojim metodama. Na primjer, klasa može imati metodu koju samo njezine podklase smiju pozvati. Klasa koristi isti mehanizam za pristup svojim metodama i varijablama. ČIŠĆENJE OBJEKATA KOJI SE NE KORISTE Neki objektno orijentirani jezici zahtjevaju od programera da prati sve objekte koje je kreirao i da ih eksplicitno uništi nakon što mu više nisu potrebni. Eksplicitno upravljanje memorijom je naporno i podložno pogreškama. Java platforma dozvoljava kreiranje po volji mnogo objekata (ogranič eno, naravno, vašim sistemom), bez da morate brinuti o njihovom uništavanju. Java runtime okruženje automatski briše objekte kada zaključ i da se više ne upotrebljavaju. Ovaj se proces zove sakupljanje smeća ( garbage collection). 54

55 Objekt postaje kandidat za sakupljanje smeć a kada nema više referenci koje pokazuju na taj objekt. Reference koje su sadržane u varijablama najčešće se otpuštaju kada varijabla izađ e iz svog dosega. Također je moguć e eksplicitno poništiti referencu postavljanjem varijable na specijalnu vrijednost - null. Zapamtite da program može imati višestruke reference na isti objekt; tek kada se otpuste sve reference na objekt, on postaje kandidat za skupljanje smeća. GARBAGE COLLECTOR Java runtime okruženje sadrži garbage collector koji periodički oslobađ a memoriju što ju zauzimaju objekti koji se više ne koriste. Garbage collector svoj posao obavlja autoamtski, iako ga, u nekim situacijama, možete pokrenuti i ručno pozivom gc metode u System klasi, npr. nakon dijela koda koji kreira veliku količinu smeć a ili prije dijela koda koji zahtjeva mnogo memorije. FINALIZACIJA Prije nego objekt bude očišćen, garbage collector daje objektu mogućnost da poč isti za sobom kroz poziv objektove finalize metode. Ovaj se proces zove finalizacija (finalization). Većina programera ne treba brinuti o implementiranju finalize metode. U rijetkim ć e slučajevima programer, ipak, poželjeti implementirati finalize metodu kako bi oslobodio resurse, kao što su native peers, koji nisu pod kontrolom garbage collectora. Metoda finalize je član Object klase - bazne klase u hijerarhiji klasa Java platforme i superklasa svih klasa. Klasa može nadvladati (override) finalize metodu kako bi obavila finalizaciju objekata svog tipa. Ako nadvladate finalize metodu, posljednju stvar koju vaša metoda treba obaviti je poziv super.finalize metode. ZAKLJUČAK O KREIRANJU I KORIŠTENJU OBJEKATA Objekti se iz klasa kreiraju upotrebom operatora new. Operator new vrać a referencu na objekt koji je kreiran. Nakon toga se referenca objekta dodjeljuje varijabli ili direktno koristi. Klasa kontrolira pristup svojim varijablama i metodama uz pomo ć mehanizma kontrole pristupa. Varijablama objekta i njegovim metodama koji su dostupni i van klase u kojoj su deklarirani moguće je pristupiti uz pomo ć kvalificiranih imena. Kvalificirano ime varijable objekta izgleda ovako: objectreference.variablename Kvalificirana imena metoda izgledaju ovako: ili objectreference.methodname(argumentlist) objectreference.methodname() 55

56 Garbage collector automatski č isti nekorištene objekte. Objekt je nekorišten od onog trenutka kad u programu više ne postoje reference na njega. Referenca na objekt se eksplicitno može poništiti postavljanjem varijable koja drži referencu na null. KARAKTERI I STRINGOVI Java platforma sadrži tri klase koje se mogu koristiti sa znakovnim podacima. Character - klasa č ije instance mogu sadržavati jednu znakovnu vrijednost. Ova klasa također definiria i priručne metode kojima je moguće manipulirati jedno- znakovnim podatkom. String - Klasa za rad s nepromjenjivim podacima koji sadrže više karaktera. StringBuffer - Klasa za spremanje i manipulaciju promjenjivim podacima sačinjenih od više karaktera. KARAKTERI (ZNAKOVI) Objekt tipa Character sadrži jednu znakovnu vrijednost. Objekt Character tipa koristi se umjesto osnovnog tipa char kada je potreban objekt, npr. kada se znakovna vrijednost prosljeđ uje metodi koja mijenja vrijednost ili kada se smješta u neku podatkovnu strukturu koja zahtjeva objekt, kao što je vektor. Sljedeći primjer, CharacterDemo, kreira nekoliko Character objekata i prikazuje neke informacije o njima. Kôd koji se odnosi na Character klasu je prikazan podebljano: public class CharacterDemo { public static void main(string args[]) { Character a = new Character('a'); Character a2 = new Character('a'); Character b = new Character('b'); int difference = a.compareto(b); if (difference == 0) { System.out.println("a is equal to b."); else if (difference < 0) { System.out.println("a is less than b."); else if (difference > 0) { System.out.println("a is greater than b."); System.out.println("a is " + ((a.equals(a2))? "equal" : "not equal") + " to a2."); System.out.println("The character " + a.tostring() + " is " + (Character.isUpperCase(a.charValue())?"upper" :"lower") + "case."); Sljedi izlaz iz ovog programa: a is less than b. a is equal to a2. The character a is lowercase. 56

57 Program CharacterDemo poziva sljedeće konstruktore i metode Character klase: Character(char) Jedini konstruktor Character klase, koji kreira Character tako da sadrži vrijednost iz argumenta. Jednom kreiranom Character objektu vrijednost koju sadrži ne može biti promijenjena. compareto(character) Metoda objekta koja uspoređuje vrijednosti koje sadrže dva Character objekta: objekta nad kojim je metoda pozvana (a u primjeru) i argumenta metode (b u primjeru). Ova metoda vraća cijeli broj ovisno o tome je li vrijednost trenutnog objekta već a od, jednaka, ili manja od vrijednosti sadržane u argumentu. Slovo je već e od drugog slova ako je njegova numerička vrijednost veća. equals(object) Metoda objekta koja uspoređuje vrijednost trenutnog objekta s vrijednošć u drugog objekta. Ova metoda vraća true ako su vrijednosti sadržane u oba objeka jednake. tostring() Metoda objekta koja pretvara objekt u string. Rezultantni string je duljine jednog karaktera i sadrži vrijednost trenutnog Character objekta. charvalue() Metoda objekta koja vraća vrijednost vrijednosti. Character objekta u obliku osnovne char isuppercase(char) Metoda klase koja određuje da li je osnovna char vrijednost veliko slovo. Ovo je jedna od mnogih metoda klase Character koja ispituje znakovni podatak ili manipulira njime. ZAŠTO DVIJE STRING KLASE? Java platforma ima dvije klase, String i StringBuffer, koje spremaju višeznakovne podatke i manipuliraju njima. Klasa String napravljena je za stringove čije se vrijednosti neć e mijenjati. Na primjer, ako pišete metodu koja zahtjeva string podatke i metoda ne namjerava promijeniti string ni na koji način, tada ćete proslijediti objekt tipa String toj metodi. Klasa StringBuffer postoji za stringove koji ć e se mijenjati; string bufferi koriste se kada znate da će se vrijednost znakovnih podataka promijeniti, npr. prilikom čitanja teksta iz datoteke. Buduć i da su stringovi konstantni, rad s njima je efikasniji nego upotreba string buffera. Zato je važno upotrebljavati stringove kad god je to moguće. Slijedi primjer zvan StringsDemo, koji izvrć e znakove stringa. Ovaj program koristi i string i string buffer. public class StringsDemo { public static void main(string[] args) { String palindrome = "Dot saw I was Tod"; int len = palindrome.length(); StringBuffer dest = new StringBuffer(len); for (int i = (len - 1); i >= 0; i--) { dest.append(palindrome.charat(i)); 57

58 System.out.println(dest.toString()); Izlaz iz ovog programa je: dot saw I was tod KREIRANJE STRINGOVA I STRING BUFFERA String se najčešće kreira na osnovu neke string konstante - niza karaktera međ u dvostrukim navodnicima. Na primjer, kada naiđe na sljedeć u string konstantu, Java platforma kreira String objekt čija je vrijednost Gobbledygook. "Gobbledygook" StringDemo program koristi ovu tehniku za kreiranje stringa na kojeg pokazuje referenca palindrome: String palindrome = "Dot saw I was Tod"; Kreirati String objekte možete kao i bilo koji drugi Java objekt: korsiteći new operator i konstruktor. Klasa String ima nekoliko konstruktora kojima možete postaviti poč etnu vrijednost stringa iz različitih izvora, kao što su niz karaktera, niz bajtova ili string buffer. Evo primjera kreiranja stringa iz niza karaktera: char[] helloarray = {'h', 'e', 'l', 'l', 'o'; String hellostring = new String(helloArray); System.out.println(helloString); Posljednja linija koda prikazuje: hello. Za kreiranje string buffera potrebno je uvijek koristiti new. StringsDemo program kreira string buffer koristeći konstruktor koji postavlja kapacitet spremnika: String palindrome = "Dot saw I was Tod"; int len = palindrome.length(); StringBuffer dest = new StringBuffer(len); Ovaj kôd kreira string buffer inicijalnog kapaciteta jednakog duljini stringa na kojeg pokazuje referenca palindrome. 58

59 PRISTUPNE METODE (ACCESSOR METHODS) DULJINA STRINGA Metode kojima se može saznati informacija o objektu poznate su kao pristupne metode (accessor methods). Jedna pristupna metoda koju možete koristiti i sa stringovima i sa string bufferima je metoda length, koja vrać a broj karaktera sadržanih u stringu ili string bufferu. Nakon što se izvrše sljedeće dvije linije koda, varijabla len će sadržavati broj 17: String palindrome = "Dot saw I was Tod"; int len = palindrome.length(); Pored length, StringBuffer klasa ima i metodu capacity, koja vraća količ inu prostora alociranog za string buffer. Kapacitet string buffera u primjeru StringsDemo nikad se ne mijenja, iako se duljina stringa povećava za 1 u svakoj iteraciji petlje. Sljedeć a slika prikazuje kapacitet i duljinu dest stringa nakon što je u njega dodano devet znakova. Duljina string buffera je broj znakova koji sadrži, a kapacitet string buffera je broj znakova koji je alociran. Klasa String nema capacity metodu, jer se string ne može mijenjati. INDEKS KARAKTERA U STRINGU ILI STRING BUFFERU Znak na određ enom indeksu unutar stringa ili string buffera možete dobiti upotrebom metode charat. Indeks prvog znaka je 0; indeks posljednjeg je length()-1. Na primjer, sljedeć i kod uzima znak iz stringa na indeksu 9: String anotherpalindrome = "Niagara. O roar again!"; char achar = anotherpalindrome.charat(9); Indeksi počinju nulom, pa je karakter na indeksu 9 - 'O'. Ako želite dobiti više od jednog karaktera iz stringa ili string buffera, možete koristiti substring metodu. Metoda substring ima dvije verzije, kao u tablici: Metoda String substring(int) String substring(int, int) Opis Vrać a novi string koji je podstring ovog stringa ili string buffera. Prvi cjelobrojni argument je indeks prvog karaktera. Drugi cjelobrojni argument je indeks posljednjeg karaktera+1. Duljina podstringa je stoga drugi broj minus prvi broj. Ako drugi broj nije prisutan, znač i da se podstring proteže do kraja originalnog stringa. 59

60 Sljedeć i kod iz Niagara palindroma uzima podstring koji se proteže od indeksa 11 do indeksa 15: String anotherpalindrome = "Niagara. O roar again!"; String roar = anotherpalindrome.substring(11, 15); JOŠ PRISTUPNIH METODA ZA String KLASU Pored length i charat accessora koje ste upoznali u prethodnom poglavlju, String klasa implementira dvije metode koje vraćaju poziciju karaktera ili stringa unutar stringa: indexof i lastindexof. Indexof metoda pretražuje string od početka, a lastindexof od kraja stringa unatrag. Ove metode se često koriste uz metodu substring. Sljedeć a klasa ilustrira korištenje lastindexof i substring metoda za izoliranje različitih dijelova imena datoteke. // This class assumes that the string used to initialize // fullpath has a directory path, filename, and extension. // The methods won't work if it doesn't. public class Filename { private String fullpath; private char pathseparator, extensionseparator; public Filename(String str, char sep, char ext) { fullpath = str; pathseparator = sep; extensionseparator = ext; public String extension() { int dot = fullpath.lastindexof(extensionseparator); return fullpath.substring(dot + 1); public String filename() { int dot = fullpath.lastindexof(extensionseparator); int sep = fullpath.lastindexof(pathseparator); return fullpath.substring(sep + 1, dot); public String path() { int sep = fullpath.lastindexof(pathseparator); return fullpath.substring(0, sep); 60

61 Evo i malog programa koji konstruira Filename objekt i zove njegove metode: public class FilenameDemo { public static void main(string[] args) { Filename myhomepage = new Filename("/home/mem/index.html", '/', '.'); System.out.println("Extension = " + myhomepage.extension()); System.out.println("Filename = " + myhomepage.filename()); System.out.println("Path = " + myhomepage.path()); Evo i izlaza iz programa: Extension = html Filename = index Path = /home/mem Metoda extension koristi lastindexof radi lociranja posljednjeg pojavljivanja toč ke (.) u imenu datoteke. Pomoću vrijednosti koju vraća lastindexof, metoda substring ć e dohvatiti ekstenziju datoteke, tj. podstring od toč ke do kraja stringa. Ovaj kôd pretpostavlja da ime datoteke sadrži točku; kad ime datoteke ne bi sadržavalo točku, tada bi lastindexof vratila -1, a substring metoda bi bacila iznimku StringIndexOutOfBoundsException. Dok metode u gornjem primjeru koriste samo jednu verziju lastindexof metode, klasa String podržava četiri različite verzije i indexof i lastindexof metode. Te č etiri verzije rade ovako: indexof(int character) lastindexof(int character) Vraća index prvog(posljednjeg) pojavljivanja specificiranog karaktera. indexof(int character, int from) lastindexof(int character, int from) Vraća indeks prvog (posljednjeg) pojavljivanja specificiranog karaktera, s poč etkom traženja od specificiranog indeksa unaprijed (unatrag). indexof(string string) lastindexof(string string) Vraća indeks prvog (posljednjeg) pojavljivanja specificiranog stringa. indexof(string string, int from) lastindexof(string string, int from) Vraća indeks prvog (posljednjeg) pojavljivanja specificiranog stringa, tražeć i unaprijed (unatrag) od specificiranog indeksa. ZA StringBuffer KLASU Pored length i charat metoda, StringBuffer također ima i metodu capacity. Ta se metoda razlikuje od metode length jer vraća količ inu prostora trenutno alociranog za StringBuffer, a ne količinu iskorištenog prostora. 61

62 MIJENJANJE STRING BUFFERA Metoda reverseit koristi append metodu StrignBuffer-a za dodavanje karaktera na kraj odredišnog stringa: dest. public class ReverseString { public static String reverseit(string source) { int i, len = source.length(); StringBuffer dest = new StringBuffer(len); for (i = (len - 1); i >= 0; i--) dest.append(source.charat(i)); return dest.tostring(); Ako prilikom dodavanja karaktera StringBuffer više nema slobodnog mjesta u alociranoj memoriji, alocirat će dodatnu memoriju. Buduć i da je alokacija memorije relativno skupa operacija (u smislu brzine), svoj kôd možete učiniti efikasnijim inicijalizirajuć i kapacitet StringBuffer-a na neki razumnu vrijednost, tako minimizirajuć i broj realociranje memorije. Metoda reverseid konstruira StringBuffer s poč etnim kapacitetom jednakim duljini izvorišnog stringa, čineći tako kasniju realokaciju nepotrebnom. Postoji nekoliko append metoda koje dodaju stringu podatke različ itih tipova, kao što su float, int, boolean, pa čak i Object. Podaci se pretvaraju u String prije nego operacija dodavanja nastupi. UMETANJE KARAKTERA Povremeno ćete poželjeti umetnuti podatke u stredinu jedne od insert metoda. Evo i primjera: StringBuffer-a. To se čini uz pomoć StringBuffer sb = new StringBuffer("Drink Java!"); sb.insert(6, "Hot "); System.out.println(sb.toString()); Ovaj kod ispisuje: Drink Hot Java! Indeks u insert metodi je indeks karaktera prije kojeg želite umetnuti podatak. POSTAVLJANJE KARAKTERA Još jedna korisna StringBuffer metoda je setcharat, koja zamjenjuje karakter na određenoj lokaciji u StringBuffer-u karakterom navedenim u argumentu. 62

63 PRETVARANJE OBJEKATA U STRINGOVE METODA tostring Često je prikladno ili potrebno pretvoriti objekt u String buduć i da ga želite poslati metodi koja prihvaća samo String vrijednosti. Metoda reverseid, korištena prije u lekciji koristi tostring metodu StringBuffer-a koja vraća String objekt iz StringBuffer-a. public class ReverseString { public static String reverseit(string source) { int i, len = source.length(); StringBuffer dest = new StringBuffer(len); for (i = (len - 1); i >= 0; i--) dest.append(source.charat(i)); return dest.tostring(); Sve klase nasljeđuju metodu tostring iz klase Objekt, a mnoge od ovih klasa ovu metodu i prepisuju kako bi omoguć ili implementaciju koja ima smisla za tu klasu. Na primjer "type wrapper" klase - Character, Integer, Boolean i druge prepisuju tostring kako bi omogućili jednostavno dobivanje String reprezentacije objekta. METODA valueof Radi jednostavnosti, String klasa ima metodu klase - valueof. Ova se metoda može koristiti za pretvaranje varijabli različitih tipova u Stringove. Na primjer, za ispis vrijednosti broja pi: System.out.println(String.valueof(Math.PI)); PRETVARANJE STRINGOVA U BROJEVE Klasa String ne omoguć ava niti jednu metodu za pretvaranje stringova u realne brojeve, cijele brojeve ili druge numeričke tipove. Međutim, četiri "type wrapper" klase ( Integer, Double, Float i Long) imaju statičku metodu valueof koja pretvara String u objekt tog tipa. Evo malog primjera valueof metode klase Float. String pistring = " "; Float pi = Float.valueOf(piStr); STRINGOVI I JAVA KOMPAJLER Java kompajler interno koristi String i StringBuffer klase za manipulaciju string konstantama i spajanje stringova. 63

64 STRING KONSTANTE (LITERAL STRINGS) U Javi se string konstante navode između dvostrukih navodnika: "Hello World!" String konstante se mogu upotrebljavati svagdje gdje i String objekt. Na primjer System.out.println prihvaća argument tipa String, pa je moguće upotrijebiti String konstantu na mjestu argumenta. System.out.println("Might I add that you look lovely today."); String metode mogu se pozvati direktno nad string konstantom. int len = "Goodbye Cruel World".length(); Budući da kompajler automatski kreira novi String objekt za svaku string konstantu na koju naiđe, moguće je koristiti string konstantu za inicijaliziranje String-a. String s = "Holla Mundo"; Gornja konstrukcija je ekvivalentna, ali efikasnija od donje, u kojoj se kreiraju dva String-a umjesto jednog. String s = new String("Hola Mundo"); Kompajler kreira prvi string kada naiđ e na konstantu new String. "Hola Mundo", a drugi kada naiđ e na SPAJANJE STRINGOVA I + OPERATOR U Javi se operator + može koristiti za spajanje Stringova: String cat = "cat"; System.out.println("con" + cat + "enation"); Ovo može izgledati donekle nedosljedno budući da String-ovi ne mogu biti mijenjani. Međutim, interno kompajler koristi StringBuffer-e za implementiranje spajanja. Gornji se primjer kompajlira u: String cat = "cat"; System.out.println(new StringBuffer().append("con").append(cat).append("enation").toString( )); + operator za dodavanje vrijednosti String-u, a koje nisu String- Takođ er možete koristiti ovi. System.out.println("Java's Number " + 1); Kompajler pretvara vrijednost 1 u String objekt prije nego izvrši operaciju spajanja. 64

65 NIZOVI Niz je struktura koja sadrži višestruke vrijednosti istog tipa. Duljina niza se uspostavlja prilikom kreiranja niza (runtime). Nakon kreiranja, niz postaje struktura fiksne duljine. Element niza je jedna od vrijednosti unutar niza, a pristupa joj se pomoću njezine pozicije. Ako želite spremiti podatke različitih tipova u jednu strukturu ili trebate strukturu č ija se veličina dinamič ki može mijenjati, trebate umjesto niza korisiti implementaciju klase Collection, kao što je Vector. KREIRANJE I KORIŠTENJE NIZOVA Ovdje je jednostavni program (ArrayDemo) koji kreira niz, stavlja neke vrijednosti u nj i prikazuje ih. public class ArrayDemo { public static void main(string[] args) { int[] anarray; // declare an array of integers anarray = new int[10]; // create an array of integers // assign a value to each array element and print for (int i = 0; i < anarray.length; i++) { anarray[i] = i; System.out.print(anArray[i] + " "); System.out.println(); DEKLARIRANJE REFERENCE NA NIZ Ova linija koda iz primjera deklarira varijablu koja će sadržavati niz. int[] anarray; Kao deklaracije varijabli drugih tipova, deklaracija niza imaju dvije komponente: tip niza i ime niza. Tip niza se piše kao type[], gdje je type tip podataka koje ć e niz sadržavati. Primjer koristi int[], pa će niz anarray biti korišten za držanje cjelobrojnih podataka. Ovdje su deklaracije nizova koje drže druge tipove podataka: 65

66 float[] anarrayoffloats; boolean[] anarrayofbooleans; Object[] anarrayofobjects; String[] anarrayofstrings; Kao i deklaracija varijabli drugih tipova, deklaracija nizovne varijable ne alocira memoriju. Niz se mora kreirati eksplicitno uz pomo ć new operatora. Sljedeć i iskaz u programu alocira niz koji može sadržavati deset cjelobrojnih elemenata i dodjeljuje niz varijabli anarray deklariranoj ranije. anarray = new int[10]; Općenito, prilikom kreiranja niza, koristi se new operator, tip podataka koje ć e niz sadržavati i željeni broj elemenata niza unutar uglatih zagrada. new elementtype[arraysize] Kad bi se new iskaz ispustio, kompajler bi ispisao pogrešku i kompajliranje ne bi prošlo: ArrayDemo.java:4: Variable anarray may not have been initialized. PRISTUPANJE ELEMENTU NIZA Nakon što je memorija alocirana za niz, program dodjeljuje vrijednosti elementima niza: for (int i = 0; i < anarray.length; i++) { anarray[i] = i; System.out.print(anArray[i] + " "); Ovaj dio koda prikazuje kako se elementu niza pristupa uz pomo ć uglatih zagrada. Vrijednost između zagrada je indeks elementa kojem se želi pristupiti. Primjetite da indeksi počinju od 0. KAKO SAZNATI VELIČINU NIZA Kako bi saznali veličinu niza, potrebno je napisati: arrayname.length Pazite: Programeri često znaju pogriještiti i iza length staviti prazne zagrade. Ovo ne radi, budući da length nije metoda ve ć property kojeg Java platforma ima za sve nizove. INICIJALIZIRANJE NIZA U Javi je moguće kreirati niz uz pomo ć poznatih konstantnih vrijednosti. Na primjer: boolean[] answers = {true, false, true, true, false; 66

67 Duljina niza je određena brojem vrijednosti u vitičastim zagradama. NIZOVI OBJEKATA Nizovi mogu čuvati, osim osnovnih tipova i reference. Takav se niz kreira na isti nač in kao i niz osnovnih tipova. Evo malog programa koji kreira niz što sadrži tri stringa, pa ih zatim ispisuje malim slovima. public class ArrayOfStringsDemo { public static void main(string[] args) { String[] anarray = { "String One", "String Two", "String Three" ; for (int i = 0; i < anarray.length; i++) { System.out.println(anArray[i].toLowerCase()); Ovaj program kreira i popunjava niz u istom iskazu. Međ utim, niz možete kreirati bez inicijalnog stavljanja objekata u nj. Promotrite ovaj kôd: String[] anarray = new String[5]; Nakon što se izvrši ova linija koda, niz zvan anarray postoji i ima dovoljno mjesta za 5 string objekata. Međ utim, niz još ne sadrži niti jedan string. Prazan je. Program mora eksplicitno kreirati stringove i staviti ih u niz. Ovo može izgledati očito, međutim mnogi poč etnici smatraju da prethodna linija koda kreira niz od pet praznih stringova. Stoga napišu sljedeće, što ć e generirati NullPointerException: String[] anarray = new String[5]; for (int i = 0; i < anarray.length; i++) { // ERROR: the following line gives a runtime error System.out.println(anArray[i].toLowerCase()); NIZOVI NIZOVA Nizovi mogu sadržavati nizove. ArrayOfArraysDemo kreira niz i koristi inicijalizator kako bi ga popunio sa četiri pod-niza. public class ArrayOfArraysDemo { public static void main(string[] args) { String[][] cartoons = { { "Flintstones", "Fred", "Wilma", "Pebbles", "Dino", { "Rubbles", "Barney", "Betty", "Bam Bam", { "Jetsons", "George", "Jane", "Elroy", "Judy", "Rosie", "Astro", 67

68 { "Scooby Doo Gang", "Scooby Doo", "Shaggy", "Velma", "Fred", "Daphne" ; for (int i = 0; i < cartoons.length; i++) { System.out.print(cartoons[i][0] + ": "); for (int j = 1; j < cartoons[i].length; j++) { System.out.print(cartoons[i][j] + " "); System.out.println(); Primjetite da su pod-nizovi različitih duljina. Imena pod-nizova su cartoons[1], itd. cartoons[0], Kao i s nizovima objekata, morate eksplicitno kreirati pod-nizove unutar nizova. Pa, ako ne upotrijebite inicijalizator, možete napisati i ovakav kôd: public class ArrayOfArraysDemo2 { public static void main(string[] args) { int[][] amatrix = new int[4][]; // populate matrix for (int i = 0; i < amatrix.length; i++) { amatrix[i] = new int[5]; //create sub-array for (int j = 0; j < amatrix[i].length; j++) { amatrix[i][j] = i + j; // print matrix for (int i = 0; i < amatrix.length; i++) { for (int j = 0; j < amatrix[i].length; j++) { System.out.print(aMatrix[i][j] + " "); System.out.println(); Prilikom kreiranja niza morate odrediti duljinu primarnog niza. Duljine pod-nizova ostaju neodređene dok ih se ne kreira. 68

69 KOPIRANJE NIZOVA Metoda klase System - arraycopy efikasno kopira podatke iz jednog niza u drugi. Metoda arraycopy zahtjeva navođenje pet argumenata: public static void arraycopy(object source, int srcindex, Object dest, int destindex, int length) Dva argumenta tipa Object predstavljaju niz iz kojeg i niz u kojeg podatke treba kopirati. Pomoću ostala tri cjelobrojna argumenta navodi se poč etna pozicija u izvornom i odredišnom nizu i broj elemenata koje treba kopirati. Ovaj crtež ilustrira kako se kopiranje izvršava: Sljedeći program ( ArrayCopyDemo) koristi arraycopy za kopiranje nekih elemenata iz copyfrom niza u copyto niz. public class ArrayCopyDemo { public static void main(string[] args) { char[] copyfrom = { 'd', 'e', 'c', 'a', 'f', 'f', 'e', 'i', 'n', 'a', 't', 'e', 'd' ; char[] copyto = new char[7]; System.arraycopy(copyFrom, 2, copyto, 0, 7); System.out.println(new String(copyTo)); Pozivom metode arraycopy poč inje kopiranje elemenata niza od drugog elementa izvorišnog niza (element 'c'). Metoda arraycopy stavlja kopirane elemente u odredišni niz poč evši od njegovog prvog elementa (indeks 0). Kopira se 7 elemenata 'c', 'a', 'f', 'f', 'e', 'i' i 'n'. Efektivno arraycopy metoda uzima "caffein" iz "decaffeinated" na ovaj način: 69

70 Primjetite da odredišni niz mora biti alociran prije poziva arraycopy i mora biti dovoljno velik da primi podatke koji se kopiraju. ZAKLJUČAK O NIZOVIMA Niz je podatkovna struktura fiksne duljine koja može sadržavati višestruke objekte istog tipa. Niz može sadržavati bilo koji tip objekta, uključujuć i druge nizove. Za deklariranje niza, koristite tip objekta kojeg niz može sadržavati i uglate zagrade. Duljina niza mora biti određ ena prilikom kreiranja niza. Za kreiranje niza može se koristiti operator new ili inicijalizatior niza. Jednom kreiran, niz ne može mijenjati velič inu. Za dohvaćanje duljine niza koristi se atribut length. Elementu unutar niza može se pristupiti preko njegovog indeksa. Indeksi poč inju nulom, a završavaju indeksom jednakim duljini niza manje jedan. Za kopiranje niza koristi se statička metoda System klase - arraycopy. 70

71 KLASE I NASLJEĐIVANJE U ovom poglavlju ćemo vidjeti kako koncepte iz lekcije programiranja prenijeti u praktičnu primjenu. Koncepti objektno-orijentiranog KREIRANJE KLASA Sada kad znamo kako kreirati i koristiti objekte te kako se objekti č iste iz memorije, vrijeme je da pokažemo kako napisati klase iz kojih se objekti kreiraju. Ovo poglavlje prikazuje osnovne komponente klase kroz primjer koji implementira last-in-first-out (LIFO) stek. Sljedeć a slika prikazuje klasu i strukturu koda. Ova implementacija steka koristi objekt, Vector, za spremanje svojih elemenata. Vektor je niz objekata koji može rasti i samostalno alocirati prostor za nove objekte. Stack klasa koristi ovu klasu za spremanje svojih elemenata, ali i uvodi LIFO ogranič enje nad vektorom - tj. dozvoljava samo dodavanje elemenata na vrh steka i uzimanje elemenata sa vrha steka. 71

72 DEKLARACIJA KLASE Prethodna slika prikazuje dvije osnovne komponente koje č ine implementaciju klase: deklaraciju klase i tijelo klase. Deklaracija klase deklarira ime klase i druge njezine atribute. Deklaracija klase za klasu Stack je jednostavna i označava da je klasa public i da je njezino ime Stack. Često je ovakva jednostavna deklaracija sve što ćete trebati. Međ utim, deklaracija klase može reći i više o klasi, npr. ime njezine nadklase te da li može biti naslijeđena. TIJELO KLASE Tijelo klase slijedi deklaraciju klase i smješteno je unutar vitič astih zagrada. Tijelo klase sadrži deklaracije svih varijabli objekta i varijabli klase (zajedno zvane varijable č lanovi). Pored toga, tijelo klase sadrži deklaraciju i implementaciju svih metoda objekta i metoda klase (zajedno zvanih - metode). KONSTRUKTORI KLASE Klasa može sadržavati jednog ili više konstruktora koji omoguć avaju inicijalzaciju objekta kreiranog iz klase. Ovo poglavlje prikazuje kako napisati konstruktor. DEKLARIRANJE VARIJABLI ČLANOVA Stanje klase se predstavlja njezinim varijablama. Varijable č lanovi (member variables) deklariraju se unutar tijela klase. Tipič no se deklariraju prije deklaracije metoda, iako ovo nije uvjet. classdeclaration { member variable declarations method declarations Za deklariranje varijabli koje su članovi klase, deklaracija mora biti unutar tijela klase, ali unutar tijela metode. Varijable deklarirane unutar metoda su lokalne varijable te metode. ne IMPLEMENTIRANJE METODA Kao što znate, objekti implementiraju svoje ponašanje uz pomo ć metoda. Drugi objekti mogu pitati objekt da izvrši neku akciju uz pomo ć poziva njegovih metoda. Ovo poglavlje govori o svemu što trebate znati o pisanju metoda za vaše Java klase. U Javi se metode klase deklariraju unutar tijela klase za koju metoda implementira ponašanje. Tipično se metode klase deklariraju poslje varijabli klase iako ovo nije uvjet. 72

73 KONTROLA PRISTUPA ČLANOVIMA KLASE Varijable članovi i metode su zajedno poznate kao članovi ( members). Prilikom deklaracije člana Java klase, moguće je dopustiti ili onemoguć iti objektima drugih tipova pristup tim članovima kroz upotrebu specifikatora pristupa ( access specifiers). ČLANOVI INSTANCE I ČLANOVI KLASE Java klasa sadrži dva različita tipa članova: članove instance ( instance members) i č lanove klase (class members). Ovo poglavlje pokazuje kako deklarirati oba tipa članova i kako ih koristiti. 73

74 DEKLARACIJA KLASE Lijeva strana sljedeće slike prikazuje moguć e komponente deklaracije klase redosljedom kojim bi se trebali navesti u deklaraciji klase. Desna strana opisuje njihovu svrhu. Komponente koje moraju biti navedene unutar deklaracije su ključna rije č class i ime klase (prikazani podebljano). Ostale komponente su opcionalne, a svaka je navedena u zasebnoj liniji ("extends Super" predstavlja jednu komponentu). Kosa slova označ avaju identifikatore kao što su ime klase ili interfacea. Ako eksplicitno ne deklarirate opcionalne elemente, Java kompajler će smatrati da je vaša klasa ne-public, ne-abstract i ne-final podklasa klase Object te da ne implementira niti jedan interface. public abstract final class NameOfClass extends Super implements Interfaces { ClassBody Klasa je javno dostupna Klasa se ne može instancirati Klasa ne može biti nasljeđena Ime klase Nadklasa klase Interfacei koje klasa implementira public Podrazumijevano ponašanje klase je da može biti korištena samo od strane drugih klasa u istom paketu. Modifikatorom public deklarira se klasa koju druge klase mogu koristiti, neovisno o paketu unutar kojeg se nalaze. abstract Deklarira da klasa ne može biti instancirana. final Deklarira da klasa ne može biti nasljeđena. class NameOfClass Ključna rije č class govori kompajleru da je ovo deklaracija klase i da je ime klase NameOfClass. extends Super Ključna rije č extends označava da je ova klasa podklasa klase Super. implements Interfaces Ako vaša klasa implementira jedan ili više interfacea tada ćete navesti ključnu riječ implements iza koje ć e slijediti lista imena implementiranih interfacea (odvojenih zarezima). 74

75 TIJELO KLASE Tijelo klase sadrži sav kôd potreban u životu objekta kreiranog iz te klase: konstruktore za inicijalizaciju novih objekata, deklaracije varijabli koje predstavljaju stanje klase i njezinih objekata, metode koje implementiraju ponašanje klase i njezinih objekata, i u rijetkim slučajevima, finalize metodu koja omogućava čišć enje objekta nakon što je završio svoj posao. Varijable i metode zajedno se zovu članovi ( members). Primjetite: Konstruktori nisu metode. Niti su članovi. Klasa Stack definira jednu varijablu člana u svom tijelu za čuvanje elemenata steka - Vector items. Također definira jedan konstruktor (no-argument konstruktor) i tri metode: push, pop i isempty. KONSTRUKTORI Sve Java klase imaju konstruktore koji se koriste za inicijalizaciju novih objekata tog tipa. Konstruktor ima isto ime kao i klasa. Na primjer, ime konstruktora klase Stack je Stack, ime konstruktora klase Rectangle je Rectangle, itd. Klasa Stack definira samo jedan konstruktor: public Stack() { items = new Vector(10); Klasa može imati po volji mnogo konstruktora, a svi ć e oni imati isto ime. Evo i jednog konstruktora koji također može biti definiran za klasu Stack. Ovaj konstruktor postavlja početnu veličinu steka ovisno o parametru konstruktora: public Stack(int initialsize) { items = new Vector(initialSize); Oba konstruktora imaju isto ime, Stack, ali različ ite parametre. Kompajler razlikuje ove konstruktore ovisno o broju parametara i njihovim tipovima. Tipič no, konstruktor koristi argumente za inicijalizaciju stanja novog objekta. Prilikom kreiranja objekta birajte konstruktor čiji argumenti najbolje odražavaju nač in na koji želite inicijalizirati novi objekt. Ovisno o broju i tipu argumenata koje prosljeđujete konstruktoru, kompajler ć e odrediti koji konstruktor pozvati. Kada napišete sljedeć u liniju koda kompajler zna da treba upotrijebiti konstruktor koji prima jednu cjelobrojnu vrijednost: new Stack(10); Slično, kada napišete sljedeć i kôd, kompajler bira no-argument konstruktor ili podrazumijevani (default) konstruktor: 75

76 new Stack(); Prilikom pisanja klase, nije potrebno navesti njezin konstruktor. Podrazumijevani konstruktor je automatski dostupan za bilo koju klasu koja nema konstruktora. Podrazumijevani konstruktor ne radi ništa, pa, ako želite izvršiti neki oblik inicijalizacije, trebate napisati neki konstruktor (ili više njih) za svoju klasu. Konstruktor za podklasu Thread (dolje u kodu) izvršava animaciju, postavlja neke podrazumijevane vrijednosti, kao što je brzina okvira i broj sličica, pa zatim učitava te sličice. class AnimationThread extends Thread { int framespersecond; int numimages; Image[] images; AnimationThread(int fps, int num) { super("animationthread"); this.framespersecond = fps; this.numimages = num; this.images = new Image[numImages]; for (int i = 0; i <= numimages; i++) {... // Load all the images Primjetite da tijelo konstruktora izgleda kao i tijelo metode; sadrži deklaracije lokalnih varijabli, petlje i druge iskaze. Međutim, jedna linija u AnimationThread konstruktoru koju ne možete vidjeti u metodi je: super("animationthread"); Ova linija poziva konstruktor nadklase AnimationThread klase, a to je konstruktor klase Thread. Ovaj konstruktor uzima String koji postavlja ime threada. Vrlo č esto konstruktor podklase poziva konstruktor svoje nadklase kako bi iskoristio njegov inicijalizacijski kôd. Nekad klase moraju pozvati konstruktor svoje nadklase kako bi objekt korektno radio. Poziv konstruktora superklase mora biti prvi iskaz u konstruktoru podklase, tj. objekt mora prvo izvršiti inicijalizaciju viših razina. Uz pomo ć modifikatora pristupa u deklaraciji konstruktora moguć e je odrediti koji objekti mogu kreirati instance vaše klase: private Nijedna druga klasa ne može instancirati vašu klasu. Vaša klasa može sadržavati public metode klase (ponekad se nazivaju factory metode), a te metode mogu konstruirati objekt i vratiti ga, ali to ne može niti jedna druga klasa. protected Samo podklase i klase u istom paketu mogu kreirati instance. public Sve klase mogu kreirati instance vaše klase bez modifikatora 76

77 Samo klase unutar istog paketa mogu konstruirati instance vaše klase. DEKLARIRANJE VARIJABLI ČLANOVA Stack koristi sljedeću liniju kôda za definiranje jedine varijable člana. private Vector items; Ova linija deklarira varijablu člana ( member variable), a ne lokalnu varijablu buduć i da se deklaracija nalazi unutar tijela klase, ali izvan metode ili konstruktora. Deklarirana varijabla član zove se items, a njezin tip podatka je Vector. Ključna rije č private označ ava items kao privatnog člana. To znači da joj može pristupiti samo kôd napisan unutar Stack klase. accesslevel static final transient volatile type name Označava razinu pristupa ovom članu Deklarira člana klase Označava da je varijabla konstanta Varijabla je tranzijentna Varijabla je volatile Tip i ime varijable Ovo je relativno jednostavna deklaracija varijable č lana, ali deklaracije mogu biti i kompleksnije. Osim tipa, imena i razine pristupa možete navesti i druge atribute, npr. da li je varijabla varijabla klase ili varijabla instance ili da li je konstanta. Svaka komponenta deklaracije varijable člana je ovdje je još malo razlrađena: accesslevel Dopušta kontrolu pristupa varijabli članu uz korištenje jedne od č etiri razine pristupa: public, protected, package i private. Pristup metodama se kontrolira na isti način. static Deklarira varijablu kao varijablu klase. Ova se ključna rije č upotrebljava i za deklariranje metoda klase. final Indicira da se vrijednost ovog člana ne može mijenjati. Sljedeć a deklaracija varijable definira 23 konstantu s imenom AVOGADRO, čija je vrijednost Avogadrov broj (6.022 * 10 ) i ne može biti mijenjana: final double AVOGADRO = 6.022e23; Ako vaš program pokuša promijeniti vrijednost konačne varijable nastupit ć e kompajlerska pogreška. Po konvenciji, imena konstantnih varijabli pišu se velikim slovima. transient Oznaka transient nije u potpunosti određena Java Language Specifikacijom, ali se koristi u serijalizaciji objekata za označavanje varijabli članova koje se ne serijaliziraju. volatile Ključna rije č volatile se koristi za sprječavanje kompajlera u izvršavanju određ enih optimizacija na č lanu. Ovo je napredna Java osobina, koju koristi mali broj Java programera i izlazi van dometa ove skripte. type Kao i druge varijable i varijable č lanovi moraju imati tip. Mogu se koristiti primitivni tipovi kao što su int, float ili boolean ili reference tipovi, kao što su nizovi, imena objekata ili interfacea. name 77

78 Ime varijable člana može biti bilo koji legalni Java identifikator i, po konvenciji, poč inje malim slovom. Nije dozvoljeno deklarirati više od jedne varijable č lana s istim imenom unutar iste klase, ali podklase mogu imati varijablu č lana koja se zove isto kao i neka varijabla njezine nadklase. Pored toga, varijabla č lan i metoda mogu imati isto ime. Na primjer, u Javi je sljedeći kôd legalan: public class Stack { private Vector items; // a method with same name as a member variable public Vector items() {... IMPLEMENTIRANJE METODA Ova slika prikazuje kôd push metode klase Stack. Ova metoda stavlja objekt u argumentu na vrh steka i vraća ga. Kao i klasa, metoda ima dva osnovna dijela: deklaraciju metode i tijelo metode. Deklaracija metode definira atribute metode, kao što su razina pristupa, tip povratne vrijednosti, ime i argumente, kako je ovdje ilustrirano: DEKLARACIJA METODE Deklaracija metode mora sadržavati bar ime i tip povratne vrijednosti: returntype methodname() {... Ovo je vrlo jednostavna deklaracija metode. Metode imaju i mnoge druge atribute kao što su argumenti, razina pristupa itd. Ovo poglavlje ć e pokriti ove teme, kao i proširiti deklaraciju metode ilustriranu prije u tekstu. 78

79 PROSLJEĐIVANJE INFORMACIJA METODI Najčešće korištena komponenta metode su njezini parametri. Slič no funkcijama u drugim programskim jezicima, Java metode prihvać aju ulaz od pozivatelja metode kroz njezine parametre. Parametri metodi daju informacije koje se nalaze van njezinog dosega. TIJELO METODE Tijelo metode je mjesto gdje nastupaju akcije metode; tijelo metode može sadržavati bilo koji skup legalnih Java instrukcija koje implementiraju metodu. DETALJI DEKLARACIJE METODE Deklaracija metode omoguć ava kompajleru, runtime sistemu i drugim klasama i objektima mnogo informacija o metodi. Tu nije uključeno samo ime metode, ve ć i tip podatka kojeg metoda vraća, broj i tip argumenata koje metoda prihvać a, te koje druge klase i objekti mogu zvati metodu. Iako ovo može zvučati više kao pisanje romana, a ne jednostavno deklariranje metode, već ina atributa metode može se deklarirati implicitno. Jedini potrebni elementi deklaracije metode su ime metode, tip podatka kojeg vrać a i par oblih zagrada. Ova slika prikazuje elemente deklaracije metode. accesslevel Razina pristupa za ovu metodu static Definira metodu kao metodu klase abstract Metoda nije implementirana final Metoda ne može biti nadvladana (overriden) native Metoda je implementirana u drugom programskom jeziku synchronized Metoda zahtjeva monitor kako bi radila returntype methodname Tip povratnog podatka i ime metode ( paramlist ) Lista argumenata throws exceptions Iznimke koje baca ova metoda Ovi su elementi pobliže objašnjeni u tekstu koji slijedi: accesslevel Kao i kod varijabli članova, kontrola pristupa metodi iz drugih klasa vrši se pomoć u jedne od četiri razine pristupa: public, protected, package i private. static Kao i kod varijabli članova, static deklarira ovu metodu kao metodu klase. abstract Apstraktne metode nemaju implementaciju i moraju biti članovi apstraktne klase. final Konačna metoda ne može biti prepisana u podklasi. native Ako imate već i broj korisnih funkcija napisanih u drugom programskom jeziku kao što je C, možda ć ete ih poželjeti upotrijebiti i u svojim Java programima. Metode implementirane u 79

80 drugim jezicima zovu se native metode i dekalriraju su kao takve uz pomo ć native ključ ne riječi. sychronized Pozivanje metoda iz više threadova istovremeno podrazumijeva i da te metode vrše određ ene operacije nad istim podacima. Takve se metode mogu deklarirati kao synchronized kako bi se sačuvao integrited podataka u multy-threaded okruženju. returntype Java zahtjeva da eksplicitno navedete tip podatka kojeg metoda vrać a. Ako vaša metoda ne vraća vrijednost, trebate upotrijebiti ključnu rije č void kao tip. methodname Ime metode može biti bilo koji legalni Java identifikator. ( paramlist ) Informacije se prosljeđuju metodama kroz njezine argumente. [throws exceptions] Ako vaša metoda baca neke iznimke, tada treba navesti tipove tih exceptiona. VRAĆANJE VRIJEDNOSTI IZ METODE Deklariranje tipa povratnog podatka metode vrši se unutar deklaracije metode. Unutar tijela metode koristi se operator return za vrać anje vrijednosti. Svaka metoda koja nije deklarirana kao void mora sadržavati iskaz return. Klasa Stack deklarira metodu isempty, koja vrać a boolean: public boolean isempty() { if (items.size() == 0) return true; else return false; Tip kojeg vraća return mora se slagati s tipom navedenim u deklaraciji metode; ne možete vratiti objekt tipa Object iz metode koja deklarirane tako da vraća int. Metoda isempty vraća boolean vrijednost true ili false, ovisno o rezultatu testa. Kompajlerska pogreška nastupa ako pokušate napisati metodu kojoj vraćena vrijednost ne odgovara navedenom tipu. Metoda isempty vraća primitivni tip podatka. Metode takođ er mogu vratiti i reference. Na primjer, Stack deklarira pop metodu koja vraća referencu na Object: public synchronized Object pop() { int len = items.size(); Object obj = null; if (len == 0) throw new EmptyStackException(); obj = items.elementat(len - 1); items.removeelementat(len - 1); return obj; Kad metoda vraća objekt, kao što to čini pop, klasa vraćenog objekta mora biti ili toč no navedena klasa ili njezina podklasa. Ovo može bti izvor konfuzije, pa zato promotrimo ovu osobinu nešto bliže. Pretpostavimo da imate hijerarhiju klasa u kojoj je ImaginaryNumber podklasa klase java.lang.number, koja je, s druge strane, podklasa klase Object: 80

81 Sad pretpostavimo da imate metodu deklariranu tako da vraća Number: public Number returnanumber() {... Metoda returnanumber može vratiti i ImaginaryNumber, ali ne i Object. To je zato što je ImaginaryNumber također i Number, budući da je podklasa klase Number. Međutim, Object nije nužno Number, također može biti i String ili neki drugi tip. Osim osnovnih tipova i referenci, kao tip povratnog podatka može se navesti i ime nekog interfacea. U tom slučaju, objekt koji se vraća mora implementirati navedeni interface. IME METODE Java podržava preopterećivanje ( overloading) imena metoda, tj. moguć nost da više metoda dijeli isto ime. Na primjer, pretpostavimo da pišete klasu koja ispisuje različ ite tipove podataka (stringove, integere, itd.) na nekoj crtač oj površini. Potrebno je napisati metodu koja zna iscrtati svaki tip podatka. U drugim je jezicima potrebno smisliti različ ito ime za svaku metodu, na primjer, drawstring, drawinteger, drawfloat, itd. U Javi možete koristiti isto ime za sve te metode, ali proslijediti različ ite parametre svakoj metodi. Tako u svojoj klasi koja iscrtava podatke, možete deklarirati više metoda s imenom draw, od kojih svaka prima različ iti tip parametra: class DataRenderer { void draw(string s) {... void draw(int i) {... void draw(float f) {... Preopterećene metode se razlikuju po broju i tipu argumenata koji se prosljeđ uju metodi. U primjeru koda, draw(string s) i draw(int i) su različ ite i jedinstvene metode zato što zahtjevaju različite tipove argumenata. Nije moguć e deklarirati više od jedne metode s istim imenom i istim brojem i tipom argumenata zato što ih kompajler ne može razlikovati. Tako su draw(string s) i draw(string t) identične i njihovo ć e deklariranje rezultirati kompajlerskom pogreškom. Klasa može nadvladati (override) metodu svoje nadklase. Overridana metoda mora imati isto ime, isti tip povratnog podatka i istu listu parametara kao i metoda koju nadvladava. 81

82 PROSLJEĐIVANJE INFORMACIJA METODI Broj argumenata metode i njihov tip deklariraju se prilikom pisanja metode. Takođ er se deklarira i tip i ime svakog argumenta u zaglavlju metode. Na primjer, sljedeć a metoda izračunava mjeseč nu ratu stambenog kredita u ovisnosti o iznosu pozajmice, kamati, duljini zajma (broju kamatnih razdoblja) i budućoj vrijednosti zajma (pretpostavka je da je buduć a vrijednost zajma jednaka nuli, jer ste ga na koncu i otplatili). double computepayment(double loanamt, double rate, double futurevalue, int numperiods) { double I, partial1, denominator, answer; I = rate / 100.0; partial1 = Math.pow((1 + I), (0.0 - numperiods)); denominator = (1 - partial1) / I; answer = ((-1 * loanamt) / denominator) - ((futurevalue * partial1) / denominator); return answer; Ova metoda uzima četiri argumenta: iznos kredita, kamatnu stopu, buduć u vrijednost i broj razdoblja. Prva tri su realni brojevi dvostruke preciznosti, a četvrti je cijeli broj. Kao kod ove metode, skup argumenata bilo koje metode je zarezima odijeljena lista deklaracija varijabli gdje je svaka deklaracija varijable par tip/ime: type name Kao što se vidi iz tijela metode, ime argumenta se koristi svugdje gdje je potrebno dohvatiti njegovu vrijednost. TIPOVI ARGUMENATA U Javi je metodi moguće proslijediti bilo koji tip podatka. Ovo uključ uje osnovne tipove, kao što su double, float i int te reference tipove kao što su objekti i nizovi. Dolje je primjer factory metode koja prihvaća niz argumenata. U tom primjeru, metoda kreira novi Polygon objekt i inicijalizira ga iz liste Point objekata. Point je klasa koja sadrži x i y koordinate. static Polygon polygonfrom(point[] listofpoints) {... Za razliku od nekih drugih jezika, metode se ne mogu prosljeđivati kao parametri, ali je moguć e proslijediti objekt i zatim pozvati metode tog objekta. IMENA ARGUMENATA Ime argumenta se navodi unutar deklaracije argumenta neke Java metode. Ovo se ime koristi unutar tijela metode za dohvaćanje vrijednosti argumenta. 82

83 Argument metode može imati isto ime kao i neka od varijabli članova. Ako je to sluč aj, tada se kaže da argument sakriva varijablu člana. Argumenti koji skrivaju varijable članove se č esto koriste u konstruktoru za inicijalizaciju klase. Na primjer, promotrite slijedeć u klasu i njezin konstruktor: class Circle { int x, y, radius; public Circle(int x, int y, int radius) {... Klasa Circle ima tri varijable člana: x, y i radius. Pored toga, konstruktor klase prihvać a tri argumenta od kojih svaki dijeli ime s nekom varijablom. Ime argumenta sakriva ime varijable člana, pa se korištenje x, y ili radius varijable unutar tijela konstruktora odnosi na argumente, a ne na varijable č lanove. Za pristup skrivenim varijablama članovima morate koristiti ključnu rije č this: class Circle { int x, y, radius; public Circle(int x, int y, int radius) { this.x = x; this.y = y; this.radius = radius; Ime argumenta metode ne može biti isto kao i ime nekog drugog argumenta iste metode, ne može biti isto imenu neke lokalne varijable unutar metode niti imenu parametra nekog catch iskaza unutar iste metode. PROSLJEĐIVANJE PO VRIJEDNOSTI (PASS BY VALUE) Argumenti se u Java metode prosljeđ uju po vrijednosti. Kada je pozvana, metoda prima vrijednosti varijabli. Kada je argument primitivnog tipa, prosljeđivanje po vrijednosti znač i da metoda ne može mijenjati njezinu vrijednost. Kada je argument reference tipa, pass-by-value znač i da metoda ne može izmijeniti referencu objekta, ali može pozvati metode objekta i mijenjati varijable objekta nad kojima ima dopušten pristup. Ovo je č esto izvor nedoumice - programer napiše metodu koja pokušava promijeniti vrijednost jednog od svojih argumenata, a metoda ne radi onako kako se od nje oč ekuje. Pogledajmo takvu metodu i način na koji ju treba promijeniti tako da č ini ono što je programer prvenstveno zamislio. Promotrimo niz Java izraza koji trebaju primiti trenutnu boju Pen objekta u nekoj grafič koj aplikaciji:... int r = -1, g = -1, b = -1; pen.getrgbcolor(r, g, b); System.out.println("red = " + r + ", green = " + g + ", blue = " + b); 83

84 ... U trenutku kada se pozove getrgbcolor metoda, varijable r, g i b imaju vrijednost -1. Pozivatelj očekuje da metoda getrgbcolor vrati red, green i blue vrijednosti trenutne boje u r, g i b varijablama. Međutim, Java runtime prosljeđuje metodi vrijednosti varijabli (-1), a ne reference na r, g i b varijable, što je potpuno jednako ovakvom pozivu metode: getrgbcolor(-1, -1, -1). Kada kontrola uđe u getrgbcolor metodu, argumenti dolaze unutar svog dosega (alociraju se) i inicijaliziraju na vrijednosti proslijeđene metodi: class Pen { int redvalue, greenvalue, bluevalue; void getrgbcolor(int red, int green, int blue) { red = redvalue; green = greenvalue; blue = bluevalue; Ova metoda neće raditi kako možda oč ekujete. Kada kontrola dođe do println iskaza u gornjem kodu, argumenti metode getrgbcolor više neć e postojati. Stoga i promjene izvršene na njima nemaju utjecaj na varijable r, g i b, koje su još uvijek jednake -1. Prosljeđivanje varijabli po vrijednosti dozvoljava prorameru određ enu sigurnost: Metode ne mogu slučajno promijeniti varijable koje su van dosega metode. Međutim, često ć ete poželjeti napisati metodu koja može promijeniti jednog ili više argumenata. Metoda getrgbcolor je upravo takva metoda. Pozivatelj želi da metoda vrati tri vrijednosti kroz svoje argumente. Međ utim, ovako napisana metoda ne može vratiti vrijednost kroz svoje argumente, a povratna vrijednost (vrijednost koju vraćamo uz pomo ć return iskaza) može biti samo jedna. Znač i, pitanje je kako metoda može vratiti više od jedne vrijednosti ili promijeniti varijablu van svog dosega? Kako bi metoda mogla izmijeniti svoj argument, argument mora biti referenca. Objekti i nizovi se također prosljeđ uju po vrijednosti, ali je vrijednost objekta referenca! Zato se dešava da se objekti koji su reference tipa prosljeđ uju kao reference. Odatle i ime. Reference na objekt su adrese objekta u memoriji. Zato, argument metode pokazuje na istu memorijsku lokaciju kao i varijabla koju je pozivatelj proslijedio kao parametar. Prepišimo zato getrgbcolor metodu tako da č ini ono što želimo. Prvo, moramo uvesti novi tip objekta - RGBColor, koji sadržava vrijednosti red, green i blue: class RGBColor { public int red, green, blue; Sada možemo prepisati metodu getrgbcolor tako da prihvaća objekt argument te preko njega vraća vrijednosti za red, green i blue: RGBColor kao class Pen { int redvalue, greenvalue, bluevalue; void getrgbcolor(rgbcolor acolor) { acolor.red = redvalue; acolor.green = greenvalue; 84

85 acolor.blue = bluevalue; I konačno, prepišimo poziv funkcije:... RGBColor pencolor = new RGBColor(); pen.getrgbcolor(pencolor); System.out.println("red = " + pencolor.red + ", green = " + pencolor.green + ", blue = " + pencolor.blue);... Promjene koje metoda getrgbcolor napravi nad RGBColor objektom utječ u na objekt kreiran u pozivu funkcije zato što imena pencolor (u pozivu funkcije) i acolor (u getrgbcolor metodi) pokazuju na isti objekt. TIJELO METODE U primjeru koda koji slijedi, tijelo metode isempty i metode pop prikazani su podebljano. class Stack { static final int STACK_EMPTY = -1; Object[] stackelements; int topelement = STACK_EMPTY;... boolean isempty() { if (topelement == STACK_EMPTY) return true; else return false; Object pop() { if (topelement == STACK_EMPTY) return null; else { return stackelements[topelement--]; Pored ostalih elemenata Jave (kao jezika), u tijelu metode je moguće koristiti ključnu riječ this, koja se odnosi (je referenca) članova trenutnog objekta. Trenutni objekt je objekt č ija je metoda pozvana. Ključna rije č super se može koristiti za pristup č lanovima nadklase trenutnog objekta koji su skriveni ili nadvladani (overriden). Takođ er, tijelo metode može sadržavati deklaracije varijabli koje su lokalne toj metodi. this Tipično, unutar tijela metode moguće je direktno pristupati objektovim varijablama č lanovima. Međutim, budući da ime argumenta može biti jednako imenu neke varijable č lana potrebno ih je nekako razlikovati. 85

86 Na primjer, sljedeći konstruktor za HSBColor klasu inicijalizira neke varijable objekta ovisno o argumentima proslijeđ enim konstruktoru. Svaki argument konstruktora ima isto ime kao i odgovarajuća varijabla član čiju početnu vrijednost argument sadrži. class HSBColor { int hue, saturation, brightness; HSBColor (int hue, int saturation, int brightness) { this.hue = hue; this.saturation = saturation; this.brightness = brightness; Korištenje ključne riječi this u konstruktoru je potrebno radi razlikovanja argumenta hue od varijable člana hue (isto vrijedi i za ostale argumente). Pisanje hue = hue; nema smisla. Argumenti metoda imaju prioritet i skrivaju varijable č lanove istog imena. Zato se za pristup varijabli članu mora eksplicitno naglasiti da se želi pristupiti varijabli objekta, a to se č ini uz upotrebu this ključne riječi. Neki programeri uvijek koriste ključnu rije č this kada pristupaju varijabli č lanu (bez obzira na to postoji li istoimeni argument ili lokalna varijabla). Ovakva praksa smanjuje moguć nost pogrešaka koje mogu nastati zbog istoimenih varijabli. Ključna rije č this se takođ er koristi za poziv objektovih metoda. Ponovo vrijedi da je ovo potrebno samo ako postoji neka nejasnoća u imenu metode, a č esto se koristi i kako bi se namjera koda učinila jasnijom. super Ako metoda skriva jednu od varijabli č lanova svoje nadklase, skrivenoj se varijabli može pristupiti uz upotrebu ključne riječi super. Slič no, ako vaša metoda prepisuje (override) neku od metoda svoje nadklase, skrivena se metoda može pozvati pomoću ključne riječi super. Promotrimo ovu klasu: class ASillyClass { boolean avariable; void amethod() { avariable = true; i njezinu podklasu koja skriva varijablu avariable i prepisuje amethod. class ASillierClass extends ASillyClass { boolean avariable; void amethod() { avariable = false; super.amethod(); System.out.println(aVariable); System.out.println(super.aVariable); 86

87 Prvo amethod postavlja avariable (onu deklariranu u ASillierClass klasi koja svojim imenom skriva onu deklariranu u ASillyClass) na false. Zatim amethod poziva prepisanu metodu pomoću iskaza: super.amethod(); Ovo postavlja skrivenu verziju varijable avariable (onu deklariranu u ASillyClass klasi) na true. Zatim metoda ispisuje vrijednosti obje verzije avariable: false true LOKALNE VARIJABLE Unutar tijela metode, moguć e je deklarirati više varijabli za lokalnu upotrebu unutar te metode. Ove varijable su lokalne varijable i žive samo za vrijeme izvšavanja metode. Ova metoda deklarira varijablu i koja se koristi za iteriranje nad elementima niza koji je argument metode. Object findobjectinarray(object o, Object[] arrayofobjects) { int i; // local variable for (i = 0; i < arrayofobjects.length; i++) { if (arrayofobjects[i] == o) return o; return null; Nakon što metoda završi s radom, i više ne postoji. KONTROLA PRISTUPA ČLANOVIMA KLASE Jedna od prednosti klasa je što klase mogu zaštititi svoje č lanove od pristupa iz drugih objekata. Zašto je ovo bitno? Pretpostavimo da pišete klasu koja predstavlja upit nad bazom podataka što sadrži razne tajne informacije, na primjer podake o zaposlenicima. Za neke informacije i upite sadržane u klasi je OK da im pristupaju drugi objekti u sistemu. Drugi upiti sadržani u klasi su tu samo za privatnu upotrebu unutar klase. Oni podržavaju operacije nad klasom, ali ne bi smjeli biti korišteni od strane objekata drugog tipa. U Javi se razina pristupa elementima klase (varijablama i metodama) određ uje prilikom njihove deklaracije. Java podržava različite razine pristupa varijablama č lanovima i metodama: private, protected, public i package. Sljedeća tablica prikazuje razine pristupa koje omogućava svaki modifikator: Modifikator klasa podklasa package svijet private protected 87

88 public package Prva kolona govori da li elementi klase mogu pristupiti drugim elementima iste klase. Kao što vidite, klasa uvijek može pristupiti svojim č lanovima. Druga kolona govori da li podklase ove klase (ovisno o tome u kojem su paketu) imaju pristup njezinim članovima. Treć a kolona govori da li klase u istom paketu mogu pristupati č lanovima ove klase (bez obzira na njihov odnos - klasa/podklasa/nadklasa). Četvrta kolona govori o tome da li sve klase mogu pristupiti članu. Pogledajmo svaku razinu pristupa nešto detaljnije. PRIVATE Najrestriktivnija pristupna razina je private. Članu koji je deklariran kao private moguć e je pristupiti samo iz članova klase u kojoj je definiran. Ovo uključ uje varijable koje sadrže informacije koje bi, ako im se pristupi izvana, mogle staviti objekt u nekonzistentno stanje, ili metode koje, kad bi bile pozvane izvana, mogu narušiti stanje objekta ili programa, Privatni članovi su tajne koje nikad ne otkrivate drugima. Ovdje je dana klasa koja sadrži jednu privatnu varijablu člana i jednu privatnu metodu: class Alpha { private int iamprivate; private void privatemethod() { System.out.println("privateMethod"); Objekti tipa Alpha mogu ispitati ili promijeniti varijablu iamprivate i pozvati privatemethod, ali objekti drugih tipova to ne mogu. Na primjer, Beta klasa definirana ovdje: class Beta { void accessmethod() { Alpha a = new Alpha(); a.iamprivate = 10; a.privatemethod(); // illegal // illegal ne može pristupiti iamprivate varijabli ili pozvati privatemethod metodu objekta Alpha. Kad jedna od klasa pokuša pristupiti varijabli za koju nema pravo pristupa, kompajler ć e ispisati poruku o pogrešci sličnu sljedećoj i odbit će prevesti vaš program: Beta.java:9: Variable iamprivate in class Alpha not accessible from class Beta. a.iamprivate = 10; // illegal ^ 1 error Također, ako vaš program pokuša pristupiti metodi kojoj nema pravo pristupa kompajler ć e prijaviti pogrešku kao što je ova: Beta.java:12: No method matching privatemethod() found in class Alpha. 88

89 1 error a.privatemethod(); // illegal Novi programeri u Javi mogu se zapitati da li Alpha objekt može pristupiti privatnim članovima drugog Alpha objekta, kao što je ilustrirano sljedeć im primjerom. Pretpostavimo da Alpha klasa sadrži metodu objekta koja uspoređuje trenutni Alpha objekt (this) s drugim objektom ovisno o njihovim iamprivate varijablama: class Alpha { private int iamprivate; boolean isequalto(alpha anotheralpha) { if (this.iamprivate == anotheralpha.iamprivate) return true; else return false; Ovo je potpuno legalno. Objekti istog tipa imaju pristup privatnim č lanovima drugog objekta. To slijedi iz činjenice da se ograničenja pristupa zadaju nad klasom, a ne nad objektom. PROTECTED Sljedeć i modifikator pristupa, koji dozvoljava klasi, njezinim podklasama i svim klasama u istom paketu pristup članovima klase, je protected. Protected pristup se koristi kada vam odgovara da klasa koja naslijedi vašu klasu može pristupiti č lanu, ali vam ne odgovara da to mogu i druge klase. Protected članovi slič ni su obiteljskim tajnama - nije vas briga zna li cijela obitelj i par prijatelja kojima vjerujete, ali ne želite da znaju svi ostali. Za deklariranje protected člana koristi se ključna rije č protected. Prvo pogledajmo kako protected modifikator utječe na klase unutar istog paketa. Pretpostavimo ovu verziju Alpha klase u kojoj su sada članovi deklarirani unutar istog paketa nazvanog Greek, a imaju jednu protected varijablu i jednu protected metodu: package Greek; public class Alpha { protected int iamprotected; protected void protectedmethod() { System.out.println("protectedMethod"); Sad pretpostavimo da je kao dio Greek paketa deklarirana i klasa Gamma (koja nije podklasa klase Alpha). Klasa Gamma može legalno pristupiti protected članovima klase Alpha - varijabli iamprotected i metodi protectedmethod. package Greek; class Gamma { void accessmethod() { Alpha a = new Alpha(); a.iamprotected = 10; a.protectedmethod(); // legal // legal 89

90 Ovo je prilično očito. Zato uvedimo i novu klasu, Delta, koja nasljeđuje klasu Alpha, ali živi u drugom paketu - Latin. Klasa Delta može pristupiti i iamprotected varijabli i protectedmethod metodi, ali samo na objektima tipa Delta ili njezinim podklasama. Klasa Delta ne može pristupiti iamprotected ili protectedmethod č lanovima objekata tipa Alpha. Evo i primjera: package Latin; import Greek.*; class Delta extends Alpha { void accessmethod(alpha a, Delta d) { a.iamprotected = 10; // illegal d.iamprotected = 10; // legal a.protectedmethod(); // illegal d.protectedmethod(); // legal Ako je klasa podklasa neke druge klase i nalazi se u istom paketu kao i klasa s protected članom, tada klasa nema pristup protected članu. PUBLIC Najlakši modifikator pristupa je svakako public. Bilo koja klasa, u bilo kojem paketu imat ć e pristup članu klase koji je deklariran kao public. Kao public se deklariraju samo oni č lanovi kojima pristup izvana ne može proizvesti neželjene rezultate. Ovdje nema osobnih ni obiteljskih tajni; ovdje se radi o stvarima za koje ne brinete da li netko drugi zna za njih. Za deklariranje javnog člana koristi se ključna rije č public. Na primjer: package Greek; public class Alpha { public int iampublic; public void publicmethod() { System.out.println("publicMethod"); Prepišimo našu Beta klasu još jedan put u paketu u kojem nije Alpha i napravimo ju takvom da bude potpuno neovisna (da nije podklasa) o klasi Alpha: package Roman; import Greek.*; class Beta { void accessmethod() { Alpha a = new Alpha(); a.iampublic = 10; a.publicmethod(); // legal // legal 90

91 Kao što vidite iz gornjeg primjera, Beta sasvim legalno može pristupati iampublic varijabli Alpha klase i sasvim legalno može pozvati publicmethod metodu. PACKAGE Package pristup je pristup kojeg Java dodjeljuje č lanu ako mu se eksplicitno ne postavi razinu pristupa. Ova razina pristupa dopušta klasama u istom paketu u kojem je i vaša klasa pristup njezinim č lanovima. Ova razina pristupa pretpostavlja da su klase u istom paketu povjerljivi prijatelji. To je razina povjerenja kao ona koju imate prema svojim najbližim prijateljima, ali ne i svima u obitelji. Na primjer, ova verzija Alpha klase deklarira jednu varijablu i jednu metodu s package razinom pristupa. Alpha živi u Greek paketu: package Greek; class Alpha { int iampackage; void packagemethod() { System.out.println("packageMethod"); Klasa Alpha može pristupiti i varijabli iampackage i metodi packagemethod. Pored toga, sve klase definirane unutar istog paketa u kojem je Alpha takođ er imaju pristup ovim članovima. Pretpostavimo da su i Alpha i Beta deklarirani kao članovi Greek paketa: package Greek; class Beta { void accessmethod() { Alpha a = new Alpha(); a.iampackage = 10; a.packagemethod(); // legal // legal Beta može legalno pristupiti iampackage i packagemethod članovima. ČLANOVI INSTANCE I ČLANOVI KLASE Ako deklarirate varijablu člana kao što je class MyClass { float afloat; afloat u MyClass klasi: deklarirali ste varijablu instance. To znači da ć e svaki put kada kreirate instancu klase, runtime sistem kreirati i jednu kopiju svake varijable instance. 91

92 Varijable instance predstavljaju kontrast varijablama klase (koje se deklariraju uz upotrebu static modifikatora). Po klasi se alocira samo jedna varijable klase bez obzira na broj kreiranih instanci te klase. Sistem alocira memoriju za varijable klase kada prvi put naiđ e na klasu. Sve instance dijele istu kopiju varijabli klase. Varijablama klase se može pristupiti preko njihove klase ili preko objekata nastalih iz te klase. Metode su slič ne: vaše klase mogu imati metode instance i metode klase. Metode instance vrše operacije nad varijablama trenutnog objekta, ali i nad varijablama klase. Metode klase, s druge strane, ne mogu pristupiti varijablama instance. Metode klase se pozivaju nad klasom. Za pozivanje metode klase ne morate imati instancu te klase. Ako drukčije ne odredite, član deklariran unutar klase je č lan instance. Klasa definirana dolje ima jednu varijablu instance - cijeli broj x i dvije metode instance x i setx: class AnIntegerNamedX { int x; public int x() { return x; public void setx(int newx) { x = newx; Svaki put kad instancirate novi objekt iz klase, automatski se kreira i kopija svake od varijabli instance. Ove kopije pripadaju novom objektu. Tako, svaki put kad instancirate novi AnIntegerNamedX objekt iz klase, dobit ćete novu kopiju varijable x koja je pridružena vašem novokreiranom objektu. Sve instance klase dijele istu implementaciju metode instance; sve instance od AnIntegerNamedX dijele istu implementaciju od x i setx. Primjetite da obje metode, x i setx, pristupaju varijabli x preko njezinog imena. "Ali", možete se zapitati, "ako sve instance klase AnIntegerNamedX dijele istu implementaciju metoda x i setx, zar to nije nejasno?" Odgovor je "ne"! Unutar metoda instance, varijabla instance odgovara varijabli instance trenutnog objekta, pa unutar x i setx metoda, x biva ekvivalentan this.x. Objekti izvan AnIntegerNamedX koji žele pristupiti x-u moraju to učiniti kroz određ enu instancu AnIntegerNamedX klase. Pretpostavimo da je ovaj komadi ć kôda unutar druge metode objekta. On kreira dva različita objekta tipa AnIntegerNamedX, postavlja njihove x vrijednosti na različite vrijednosti i prikazuje ih:... AnIntegerNamedX myx = new AnIntegerNamedX(); AnIntegerNamedX anotherx = new AnIntegerNamedX(); myx.setx(1); anotherx.x = 2; System.out.println("myX.x = " + myx.x()); System.out.println("anotherX.x = " + anotherx.x());... Primjetite da kôd koristi setx za postavljanje vrijednosti od myx, a objektu anotherx postavlja vrijednost direktno. Bilo kako bilo, kôd pristupa različitim kopijama varijable x: jednoj koju sadrži myx objekt i drugoj koju sadrži anotherx objekt. Izlaz ovog programa je zato: myx.x = 1 92

93 anotherx.x = 2 Vidi se da svaka instanca klase AnIntegerNamedX ima svoju vlastitu kopiju varijable instance x i svaki x ima različitu vrijednost. Ako je to poželjno, prilikom deklariranja, varijablu člana možete uč initi varijablom klase umjesto varijable instance. Slič no, možete odrediti da metoda pripada klase, a ne njezinoj instanci. Sistem kreira samo jednu kopiju varijable klase prvi put kad primjeti klasu u kojoj je varijabla definirana. Sve instance te klase dijele istu kopiju varijable klase. Metode klase mogu pristupati jedino varijablama klase - one ne mogu pristupiti varijablama instance. Kako bi odredili da je varijabla član varijabla klase, koristit ćete ključnu rije č static. Na primjer, promijenimo klasu AnIntegerNamedX, tako da x varijabla postane varijabla klase: class AnIntegerNamedX { static int x; public int x() { return x; public void setx(int newx) { x = newx; Sada bi isti kôd od maloprije, koji kreira dvije instance AnIntegerNamedX klase, postavlja njihove x vrijednosti i zatim ih prikazuje, proizveo različiti rezultat: myx.x = 2 anotherx.x = 2 Izlaz je različit zato što je x sada varijabla klase, pa postoji samo jedna kopija ove varijable koju dijele sve instance AnIntegerNamedX klase, uključujući myx i anotherx. Varijable klase se koriste za podatke od kojih vam treba samo jedna kopija i koji moraju biti dostupni svim objektima koji nasljeđ uju klasu unutar koje je varijabla deklarirana. Na primjer, varijable klase se često koriste (skupa s ključnom riječi final) za definiranje konstanti; što je mnogo efikasnije nego da takve varijable budu varijable instance. Slič no, prilikom deklariranja metode, možete odrediti da metoda bude metoda klase. Metode klase mogu pristupati samo varijablama klase. Kako bi neku metodu proglasili metodom klase, koristit ćete se ključnom riječ ju static unutar deklaracije metode. Promijenimo AnIntegerNamedX klasu tako da njezina varijabla x ponovo bude instance varijabla, a njezine dvije metode postanu metode klase: class AnIntegerNamedX { int x; static public int x() { return x; static public void setx(int newx) { x = newx; Ako pokušate kompajlirati ovaj kôd, kompajler će prijaviti pogrešku sličnu ovoj: 93

94 AnIntegerNamedX.java:4: Can't make a static reference to nonstatic variable x in class AnIntegerNamedX. return x; ^ Ovo se dešava zato što metode klase ne mogu pristupiti varijablama instance. Popravimo AnIntegerNamedX tako da x bude varijabla klase: class AnIntegerNamedX { static int x; static public int x() { return x; static public void setx(int newx) { x = newx; Sada će se gornji kôd kompajlirati, pa ć e isti program kojeg smo imali prije, a koji kreira dvije instance AnIntegerNamedX varijable, postavlja njihove x vrijednosti i zatim ih ispisuje proizvesti ovakav izlaz: myx.x = 2 anotherx.x = 2 Još jedna razlika između članova instance i članova klase je ta što su č lanovi klase dostupni iz klase same. Tj., nije potrebno instancirati klasu kako bi pristupili njezinim č lanovima. Prepišimo kôd od prije tako da pristupa x i setx metodama direktno iz AnIntegerNamedX klase:... AnIntegerNamedX.setX(1); System.out.println("AnIntegerNamedX.x = " + AnIntegerNamedX.x());... Primjetite da nije potrebno kreirati myx i anotherx. Možete postaviti x i dohvatiti x direktno iz klase AnIntegerNamedX. Ovo nije moguće sa č lanovima instance jer njima pristupate isključivo preko objekta. Članovima klase se može pristupiti i preko objekta i preko klase same. INICIJALIZIRANJE ČLANOVA INSTANCE I KLASE Za postavljanje inicijalnih vrijednosti članova klase mogu se koristiti inicijalizatori: class BedAndBreakfast { static final int MAX_CAPACITY = 10; boolean full = false; Ovo radi za članove osnovnih tipova. Ponekad, ovo č ak radi i za kreiranje nizova i objekata. Ali ovaj oblik inicijalizacije ima ograničenja: 94

95 1. Inicijalizatori mogu izvršavati samo incijalizacije koje se mogu izraziti u iskazu dodjeljivanja, 2. Inicijalizatori ne mogu zvati niti jednu metodu koja može baciti exception, 3. Ako inicijalizator zove metodu koja baca runtime exception, tada se ne može oporaviti od pogreške. Ako tebate izvrišiti inicijalizaciju koja ne može biti uč injena unutar inicijalizatora zbog jednog od njegovih ogranič enja, tada inicijalizacijski kôd morate staviti negdje drugdje. Za inicijaliziranje članova klase inicijalizacijski kôd morate smjestiti u statič ki inicijalizacijski blok. Za inicijaliziranje članova instance, inicijalizacijski kôd morate staviti u konstruktor. KORIŠTENJE STATIČKOG INICIJALIZACIJSKOG BLOKA Ovdje je primjer statičkog inicijalizacijskog bloka: Resurs errorstrings mora biti inicijaliziran u statič kom inicijalizacijskom bloku. To je stoga jer je potrebno izvršiti oporavak od pogreške ako traženi resurs nije pronađen. Također, buduć i da je errorstrings č lan klase, nema smisla inicijalizirati ga u konstruktoru. Kako je pokazano u gornjem primjeru, statički inicijalizacijski blok počinje ključnom rječju static i predstavlja normalni Javin blok koda smješten unutar vitičastih zagrada. Klasa može imati po volji mnogo statič kih inicijalizacijskih blokova koji mogu postojati bilo gdje unutar tijela klase. Runtime sistem garantira da će se statič ki inicijalizacijski blokovi i statič ki inicijalizatori pozvati redosljedom (lijevo-na-desno, odozgo-na-dolje) kojim se nalaze u izvornom kodu. INICIJALIZIRANJE ČLANOVA INSTANCE Ako želite inicijalizirati varijablu instance, a to iz jednog od razloga navedenih prije ne možete učiniti unutar deklaracije varijable, tada ć ete inicijalizacijski kôd staviti unutar konstruktora klase. Pretpostavite da je errorstrings iz prethodnog primjera varijabla instance, a ne varijabla klase. Tada ćete koristiti sljedeći kôd za njezinu inicijalizaciju: import java.util.resourcebundle; class Errors { ResourceBundle errorstrings; 95

96 Errors() { try { errorstrings = ResourceBundle. getbundle("errorstrings"); catch (java.util.missingresourceexception e) { // error recovery code here Kôd koji inicijalizira errorstrings je sada u konstruktoru klase. Ponekad klasa sadrži mnogo konstruktora i svaki konstruktor dopušta pozivatelju postavljanje inicijalnih vrijednosti za različ ite varijable instance novog objekta. Na primjer, java.awt.rectangle ima ova tri konstruktora: Rectangle(); Rectangle(int width, int height); Rectangle(int x, int y, int width, int height); No-argument konstruktor ne dopušta pozivatelju postavljanje inicijalnih vrijednosti, a druga dva konstruktora dopuštaju pozivatelju postavljanje inicijalnih vrijednosti za velič inu ili za poziciju i veličinu pravokutnika. Budući da sve varijable moraju biti inicijalizirane, tada klase najčešć e imaju jedan općeniti konstruktor koji č ini sav posao. Drugi konstruktori pozivaju ovaj konstruktor i daju mu ili vrijednosti svojih parametara ili neke podrazumijevane vrijednosti. Na primjer, evo jedne moguće implementacije ova tri Rectangle kontruktora (pretpostavite da su x, y, width i height imena varijabli instance koje treba inicijalizirati). Rectangle() { this(0,0,0,0); Rectangle(int width, int height) { this(0,0,width,height); Rectangle(int x, int y, int width, int height) { this.x = x; this.y = y; this.width = width; this.height = height; Java podržava inicijalizacijske blokove instanci, koji se mogu koristiti umjesto ovog. Međ utim, one su namijenjene korištenju unutar anonimnih klasa, koje ne mogu deklarirati konstruktore. Pristup koji koristi konstruktore opisan ovdje je bolji iz ovih razloga: Sav inicijalizacijski kôd je na jednom mjestu, što ga čini č itljivijim i lakšim za održavanje, Podrazumijevane vrijednosti se moraju obraditi eksplicitno, Konstruktori su široko prihvaćeni u Java zajednici, uključujuć i relativno nove Java programere, dok inicijalizatori instanci nisu i mogu prouzroč iti konfuziju onima koji čitaju vaš kôd. 96

97 NASLJEĐIVANJE Prisjetite se iz prethodnog poglavlja da pomoću extends deklarirate vašu klasu kao podklasu neke druge klase. Java ne podržava višestruko nasljeđivanje, pa je moguć e nasljediti samo jednu nadklasu. Iako je iz deklaracije klase dopušteno izostaviti stavku extends, vaša klasa ć e ipak imati svoju nadklasu. Štoviše, svaka Java klasa ima jednu i samo jednu direktnu nadklasu. Ovo nas vodi do logičnog pitanja: "Gdje sve počinje?" Kako je naznačeno na sljedeć oj slici, osnovna klasa iz koje su izvedene sve druge klase zove se klasa Object i definirana je u java.lang paketu. Klasa Object definira i implementira ponašanje koje je potrebno svakoj klasi u Java sistemu. To je najopć enitija od svih klasa. Njezine direktne podklase i druge klase blizu vrha hijerarhije implementiraju općenita ponašanja, a klase bliže dnu hijerarhije nač injene su kako bi podržale specijalizirana ponašanja. Definicija: Podklasa (subclass) je klasa koja proširuje (extends) drugu klasu. Podklasa nasljeđuje stanje i ponašanje svojih "predaka". Termin nadklasa ( superclass) odnosi se na direktnog pretka, kao i na njegove pretke. Sljedeće poglavlje, Razumijevanje nasljeđ ivanja, govori o različitim problemima uključ enim u proširenje bilo koje klase, npr. koje članove klasa nasljeđuje, koje č lanove može prepisati ili skriti, a koje ne može. Poglavlje koje slijedi, Biti potomak klase Object, opisuje što sve klase nasljeđuju iz Object klase i kako ove klase mogu implementirati nasljeđenu funkcionalnost. 97

98 RAZUMIJEVANJE NASLJEĐIVANJA Podklasa nasljeđ uje varijable i metode svoje nadklase i svih svojih predaka. Podklasa može koristiti ove č lanove takve kakvi su definirani u njezinim nadklasama, a može i sakriti varijable članove ili prepisati metode. KOJE ČLANOVE PODKLASA NASLJEĐUJE? Pravilo: Podklasa nasljeđuje sve č lanove svoje nadklase koji su toj podklasi dostupni osim ako podklasa eksplicitno skriva varijablu č lana ili prepisuje metodu. Primjetite da konstruktori nisu članovi i ne nasljeđuju se. Sljedeća lista prikazuje članove koje podklasa nasljeđuje: Podklase nasljeđuju public i protected članove nadklase. Podklase nasljeđuju članove nadklase koji nemaju određ ene razine pristupa, sve dok se podklasa nalazi u istom paketu kao i nadklasa. Podklase ne nasljeđuju člana svoje nadklase ako podklasa deklarira č lana istog imena. U slučaju da se radi o varijablama, varijabla č lan u podklasi skriva varijablu člana svoje nadklase. U sluč aju da se radi o metodama, metoda u podklasi prepisuje (overrides) metodu nadklase. SKRIVANJE VARIJABLI ČLANOVA? Kako je ranije spomenuto, varijable č lanovi definirani u podklasi skrivaju istoimene varijable članove svoje nadklase. Iako je ova osobina Java jezika moć na i prikladna u mnogim situacijama, može biti i izvor pogrešaka. Zato prilikom imenovanja varijabli č lanova budite oprezni i sakrijte samo one varijable članove koje zbilja i želite sakriti. Jedna interesantna osobina varijabli članova je da klasa može pristupiti varijabli č lanu preko svoje nadklase. Promotrite ovaj par nadklasa/podklasa: class Super { Number anumber; class Subbie extends Super { Float anumber; Varijabla anumber u Subbie klasi skriva anumber varijablu Super klase, ali skrivenoj varijabli ipak možete pristupiti uz pomo ć ključne riječi super koja metodi dozvoljava dohvaćanje skrivenih varijabli i prepisanih metoda njezine nadklase: super.anumber 98

99 PREPISIVANJE METODA Sposobnost podklase da prepiše (override) metodu svoje nadklase dozvoljava klasi nasljeđ ivanje ponašanja njezine nadklase i njegovu izmjenu ili nadomještanje drugim ponašanjem. Na primjer, sve klase su nasljednici klase Object. Klasa Object sadrži metodu tostring, koja vraća String objekt koji sadrži ime klase i njezin hash kôd. Već ina, a možda i sve, klase željet će prepisati ovu metodu i ispisati nešto što ima smisla za tu klasu. Promijenimo ve ć dani primjer Stack klase i prepišimo tostring metodu. Izlaz metode tostring trebao bi biti tekstualna reprezentacija objekta. Za Stack klasu bi to bila lista članova na stacku. public class Stack { private Vector items; // code for Stack's methods and constructor not shown // overrides Object's tostring method public String tostring() { int n = items.size(); StringBuffer result = new StringBuffer(); result.append("["); for (int i = 0; i < n; i++) { result.append(items.elementat(i).tostring()); if (i < n-1) result.append(","); result.append("]"); return result.tostring(); Tip povratnog podatka, ime metode te broj i tip parametara metode moraju odgovarati onima u prepisanoj metodi. Metoda može imadi različ itu stavku thro, sve dok ne deklarira tipove podataka koji nisu deklarirani u throws stavki prepisane metode. Razina pristupa metodi može biti i veća od razine pristupa prepisane metode, ali ne i manja. Na primjer, protected metoda u nadklasi može biti deklarirana kao public u podklasi, ali ne i kao private. POZIVANJE PREPISANE METODE Ponekad nećete željeti u potpunosti prepisati metodu ve ć joj samo dodati neku funkcionalnost. Kako bi to ostvarili, pozvat ćete prepisanu metodu uz upotrebu ključne riječi super. Na primjer, super.overriddenmethodname(); 99

100 METODE KOJE PODKLASA NE MOŽE PREPISATI Podklasa ne može prepisati metode koje su u nadklasi deklarirane kao final metode. Ako pokušate nasljediti final metodu, kompajler će prikazati poruku o pogrešci slič nu ovoj i odbit će prevesti vaš program: FinalTest.java:7: Final methods can't be overridden. Method void iamfinal() is final in class ClassWithFinalMethod. void iamfinal() { ^ 1 error METODE KOJE PODKLASA MORA PREPISATI Podklasa mora prepisati metode koje su u nadklasi deklarirane kao abstract metode, ili i podklasa mora biti deklarirana kao apstraktna. BITI NASLJEDNIK KLASE Object Klasa Object nalazi se na vrhu hijerarhije klasa Java platforme. Svaka klasa u Javi je nasljednik, direktni ili indirektni, klase Object. Ova klasa definira osnovno stanje i ponašanje koje moraju imati svi objekti, kao što je sposobnost uspoređ ivanja s drugim objektom, pretvaranje u string, č ekanje na uvjetnu varijablu, obavještavanje drugih objekata da je uvjetna varijabla promijenjena i vraćanje klase objekta. Vaše klase mogu prepisati sljedeće metode klase Object. Metode equals i hashcode su u jednoj liniji budući da moraju biti prepisane zajedno. clone equals/hashcode finalize tostring Vaša klasa ne može prepisati ove metode klase Object (jer su to final metode): getclass notify notifyall wait METODA clone Metoda clone se koristi za kreiranje kopije postojeć eg objekta. Za kreiranje kopije potrebno je napisati: acloneableobject.clone(); 100

101 Implementacija metode clone provjerava da li objekt nad kojim je clone pozvan implementira Cloneable interface i baca CloneNotSupportedException iznimku ako ne implementira. Primjetite da sama klasa Object ne implementira Cloneable iterface, pa podklase klase Object koje ne implementiraju ovaj interface nije moguće kopirati. Ako objekt nad kojim je pozvana clone metoda implementira Cloneable interface, implementacija clone metode u Object klasi kreira novi objekt istog tipa kao što je originalni objekt i inicijalizira varijable članove novog objekta na vrijednosti koje imaju odgovarajuć e varijable objekta koji se kopira. Najjednostavniji način na koji svoju klasu možete učiniti Cloneable je da u njezinu deklaraciju dodate implements Cloneable. Za neke klase je podrazumijevano ponašanje clone metode klase Object sasvim dovoljno. Druge klase mogu poželjeti prepisati clone metodu. Uzmimo u obzir Stack klasu koja sadrži referencu na Vector objekt. Kada bi se Stack oslonio na implementaciju clone metode klase Object, tada bi originalni stack i njegov klon imali reference na isti vektor. Promjena jednog stacka bi tako mijenjala i stack njegovog klona, što nije poželjno ponašanje. Ovdje je bolja implementacija clone metode za našu Stack klasu, koja klonira vektor kako bi osigurala da originalni stack i njegov klon ne pokazuju na isti vektor: public class Stack implements Cloneable { private Vector items; // code for Stack's methods and constructor not shown protected Object clone() { try { Stack s = (Stack)super.clone(); // clone the stack s.items = (Vector)items.clone(); // clone the vector return s; // return the clone catch (CloneNotSupportedException e) { // this shouldn't happen because Stack is Cloneable throw new InternalError(); Implementacija clone metode klase Stack je relativno jednostavna: ona poziva super.clone kojeg Stack nasljeđuje od klase Object, a koja kreira i inicijalizira instancu korektnog tipa. U tom ć e trenutku originalni stack i njegov klon imati referencu na isti vektor. Zatim metoda klonira vektor. Budite oprezni! clone metoda ne bi nikad smjela koristiti operator new za kreiranje klona i nikad ne bi smjela zvati konstruktore. Umjesto toga, metoda mora zvati super.clone metodu, koja kreira objekt odgovarajuć eg tipa i dozvoljava hijerarhiji nadklasa izvršavanja kopiranja potrebnog za dobijanje pravilnog klona. METODE equals I hashcode Metode equals i hashcode moraju se prepisati zajedno. 101

102 Metoda equals uspoređuje dva objekta i vraća true ako su jednaki. Metoda equals implementirana u klasi Object koristi funkciju identiteta za određ ivanje jednakosti objekata (ako su uspoređeni objekti zbilja isti objekt, metoda vraća true). Međutim, za neke klase, dva različ ita objekta istog tipa mogu se smatrati jednakima ako sadrže jednake informacije. Promotrite ovaj kôd koji uspoređuje dva cijela broja, one i anotherone: Integer one = new Integer(1), anotherone = new Integer(1); if (one.equals(anotherone)) System.out.println("objects are equal"); Ovaj program prikazuje poruku objects are equal iako reference one i anotherone pokazuju na dva različita objekta. Ovi se objekti smatraju jednakima buduć i da sadrže istu cjelobrojnu vrijednost. Vaše klase bi trebale prepisati equals metodu ako vam ne odgovara njezino podrazumijevano ponašanje. Ako ju odlučite prepisati, tada morate prepisati i hashcode metodu. Vrijednost koju vraća hashcode metoda je cijeli broj koji mapira objekt u hash tablicu. Objekt mora uvijek proizvoditi isti hash kôd. Pisanje "korektne" hash funkcije je jednostavno - uvijek vratite isti hash kôd za isti objekt. S druge strane, pisanje "efikasne" hash funkcije, one koja omogućuje pravilnu distribuciju hash kodova, je teško i izlazi van okvira ovog teksta. Hash funkcija za neke klase je relativno očita. Na primjer, očiti hash kôd Integer objekta je njegova cjelobrojna vrijednost. METODA finalize Klasa Object ima i metodu finalize koja služi za čišć enje resursa koje zauzima objekt neposredno prije nego ga uništi garbage collector. finalize metodu sistem poziva automatski i u većini slučajeva nije ju potrebno prepisati. METODA tostring tostring metoda klase Object vraća String reprezentaciju objekta. Metoda tostring može se koristiti s System.out.println metodom za prikazivanje tekstualnih reprezentacija objekata, kao što je ovaj primjer koji prikazuje tekstualnu reprezentaciju trenutnog threada: System.out.println(Thread.currentThread().toString()); String reprezentacija objekta u potpunosti ovisi o objektu. String reprezentacija Integer objekta je cjelobrojna vrijednost prikazana kao tekst. String reprezentacija Thread objekta sadrži različ ite atribute o threadu, kao što su njegovo ime i prioritet. Na primjer, prethodna linija koda prikazuje sljedeću informaciju: Thread[main,5,main] Metoda tostring je vrlo korisna u fazi debuggiranja. Zato ju je vrlo pametno prepisati gotovo za svaku klasu koju napišete. 102

103 METODA getclass Metoda getclass je final metoda koja vrać a runtime reprezentaciju klase objekta. Ova metoda vraća objekt tipa Class. Jednom kad dobijete Class objekt, iz njega možete dobiti različ ite informacije o klasi, kao što je njezino ime, njezinu nadklasu i imena interfacea koje implementira. Sljedeć a metoda prikazuje ime klase objekta: void PrintClassName(Object obj) { System.out.println("The Object's class is " + obj.getclass().getname()); Jedna priručna upotreba Class objekta je kreiranje nove instance klase bez znanja o kojoj se klasi radi u trenutku kompajliranja. Sljedeći primjer kreira novu instancu iste klase kao i obj, a koja može biti bilo koja klasa koja nasljeđuje Object (što znači da može biti bilo koja klasa): Object createnewinstanceof(object obj) { return obj.getclass().newinstance(); Primjetite: Ako ve ć znate ime klase, Class objekt možete dobiti iz tog imena. Dvije linije prikazane ovdje su ekvivalentni načini dobijanja Class objekta za String klase: String.class ili Class.forName("String") Prva je efikasnija. METODE notify, notifyall i wait Nije moguće prepisati notify ni notifyall metodu, kao ni tri verzije wait metode. To je zato što su to metode kritične za sinkronizaciju threadova. Korištenje ovih metoda bit ć e prikazano u poglavlju o threadovima. PISANJE KONAČNIH KLASA I METODA Svoju klasu možete deklarirati kao konačnu ( final), tj. zabraniti da vaša klasa ima podklase. Postoje (bar) dva razloga zašto biste to mogli poželjeti učiniti: radi poveć anja sigurnosti sistema i radi razloga dobrog objektno-orijentiranog dizajna. Sigurnost: Jedan mehanizam kojeg hackeri koriste radi napadanja sistema je kreiranje podklasa koje se onda koriste kao zamjena za originalne klase. Podklasa izgleda kao originalna klasa, ali može činiti bitno različ ite stvari, npr. neku štetu ili pristupati privatnim informacijama. Kako 103

104 bi spriječili ovakve napade, svoje klase možete deklarirati kao konačne i tako onemogućit i kreiranje njihovih podklasa. Klasa String u java.lang paketu je final klasa iz upravo ovakvog razloga. Ova je klasa toliko vitalna za rad kompajlera i interpretera da Java mora garantirati da kad god metoda ili objekt koristi String dobija upravo java.lang.string, a ne neki drugi string. Ovo osigurava da stringovi nemaju č udna, nekonzistentna, nepoželjna i nepredvidljiva ponašanja. Dizajn: Klasu također možete poželjeti proglasiti konač nom radi razloga objektno-orijentiranog dizajna. Jednostavno ako mislite da je vaša klasa "savršena", tj. da, konceptualno, ne bi trebala imati podklasa. Ključna rije č final koristi se unutar deklaracije klase za deklariranje finalne klase. Na primjer, ako svoju (savršenu) klasu ChessAlgorithm želite proglasiti konač nom, njezina bi deklaracija trebala izgledati ovako: final class ChessAlgorithm {... Bilo koji pokušaj nasljeđivanja ChessAlgorithm klase rezultirat ć e kompajlerskom pogreškom kao što je ova: Chess.java:6: Can't subclass final classes: class ChessAlgorithm class BetterChessAlgorithm extends ChessAlgorithm { ^ 1 error KONAČNE METODE Ako umjesto klase želite od prepisivanja zaštititi samo pojedine metode, tada možete iskoristiti mogućnost da u dekalraciji metode upotrebom ključne riječi final zabranite njezino prepisivanje u podklasama. Kao što je maloprije pokazano, klasa Object č ini upravo ovo: neke od njezinih metoda su final metode, a neke nisu. Metodu ćete proglasiti konač nom ako se njezina implementacija ne bi smjela mijenjati i ako je njezino ponašanje kritič no za konzistentno stanje objekta. Na primjer, umjesto da svoju klasu ChessAlgorithm učinite konačnom, možda ćete poželjeti konačnom uč initi njezinu metodu nextmove: class ChessAlgorithm {... final void nextmove(chesspiece piecemoved, BoardLocation newlocation) {

105 PISANJE APSTRAKTNIH KLASA I METODA Ponekad klasa koju definirate predstavlja neki apstraktni koncept i, kao takva, ne bi smjela biti instancirana. Uzmite npr. hranu u realnom svijetu. Jeste li ikada vidjeli instancu hrane? Ne. Umjesto toga vidjeli ste instance mrkve, jabuke ili č okolade. Hrana predstavlja apstraktni koncept za sve stvari koje možemo jesti. Zato postojanje instance hrane nema smisla. Slično, u objektno orijentiranom programiranju apstraktne koncepte modelirate bez moguć nosti kreiranja njihovih instanci. Na primjer, klasa Number u java.lang paketu predstavlja apstraktni koncept brojeva. Klasa Number ima smisla samo kao nadklasa klasama kao što su Integer i Float, od kojih svaka implementira određ ene tipove brojeva. Klasa kao što je Number, koja predstavlja apstraktni koncept i ne može biti instancirana, zove se apstraktna klasa. Apstraktna klasa je klasa koja služi samo da bi bila nasljeđena. Za deklariranje klase kao apstraktne koristi se ključna rije č abstract prije ključne riječ i class u deklaraciji klase: abstract class Number {... Ako pokušate instancirati apstraktnu klasu, kompajler će prikazati pogrešku sličnu ovoj: AbstractTest.java:6: class AbstractTest is an abstract class. It can't be instantiated. new AbstractTest(); ^ 1 error APSTRAKTNE METODE Apstraktna klasa može sadržavati apstraktne metode, tj. metode koje nemaju implementaciju. Na ovaj način, apstraktne klase mogu definirati cijeli programski interface, dajuć i svojim podklasama deklaracije svih metoda potrebnih za implementiranje tog programskog interfacea. Međ utim, apstraktne klase mogu ostaviti neke ili sve implementacijske detalje tih metoda svojim podklasama. Pogledajmo primjer kreiranja apstraktne klase s apstraktnim metodama. U objektnoorijentiranoj aplikaciji za crtanje, moguć e je crtati kružnice, pravokutnike, linije, Bezierove krivulje, itd. Svaki od ovih grafič kih objekata dijeli neka stanja (poziciju, okvirni pravokutnik) i ponašanje (pomakni, skaliraj, iscrtaj). Moguće je iskoristiti ove slič nosti i deklarirati ih u jednoj roditeljskoj klasi - GraphicObject. Međutim, grafički objekti bitno se razlikuju na mnogo načina: iscrtavanje kružnice je prilič no različito od iscrtavanja pravokutnika. Grafič ki objekti ne mogu dijeliti ove tipove stanja ili 105

106 ponašanja. S druge strane, svi grafič ki objekti moraju znati kako iscrtati sebe same. Ovo je savršena situacija za izradu apstraktne klase. Prvo ćete deklarirati apstraktnu klasu, GraphicObject, kako bi osigurali varijable č lanove i metode koje će dijeliti sve podklase, kao što su trenutna pozicija i moveto metoda. GraphicObject također će deklarirati apstraktne metode, kao što je draw, a koje moraju implementirati sve podklase. GraphicObject će izgledati ovako: abstract class GraphicObject { int x, y;... void moveto(int newx, int newy) {... abstract void draw(); Svaka ne-apstraktna klasa klase GraphicObject, kao što su Circle i Rectangle, morat ć e implementirati draw metodu: class Circle extends GraphicObject { void draw() {... class Rectangle extends GraphicObject { void draw() {... Apstraktne klase ne moraju nužno imati apstraktne metode. Ali svaka klasa koja ima apstraktne metode ili ne implementira apstraktne metode svoje nadklase mora biti deklarirana kao apstraktna. IMPLEMENTIRANJE UGNIJEŽDENIH KLASA Java dopušta implementiranje klasa koje su č lanovi druge klase. Takve klase se zovu ugniježdene klase (nested classes): class EnclosingClass{... class ANestedClass {... Definicija: Ugniježdena klasa je klasa koja je član druge klase. Ugniježdene klase se koriste u određenim relacijama izmeđ u dviju klasa. Klasu biste trebali definirati unutar druge klase kada ona ima smisla samo unutar te klase ili kad se oslanja na tu klasu u svom funkcioniranju. Na primjer, tekst kursor ima smisla samo u kontekstu određ ene tekstualne komponente. 106

107 Kao član neke klase, ugniježdena klasa ima posebnu privilegiju: Ima neogranič en pristup članovima te klase, čak i u slučaju kada su deklarirani kao private. Međ utim, ova privilegija i nije baš posebna. Ona je u potpunosti u skladu sa značenjem private i drugih modifikatora pristupa. Modifikatori pristupa ograničavaju pristup č lanovima klasa izvan klase. Ugniježdena klasa se nalazi unutar druge klase, pa ima neograničen pristup njezinim članovima. Kao i drugi članovi, ugniježdena klasa može biti deklarirana kao static (ili ne). Statič ka ugniježdena klasa se zove uporavo tako: statička ugniježdena klasa ( static nested class), dok se ne-statička ugniježdena klasa zove unutrašnja klasa ( inner class). Ovo je ilustrirano sljedeć im kodom: class EnclosingClass{... static class AStaticNestedClass {... class InnerClass {... Kao i kod statič kih metoda i varijabli, ugniježdena klasa je pridružena klasi unutar koje je definirana. Kao i metode klase, statič ke ugniježdene klase ne mogu direktno pristupati varijablama instance niti nestatičkim metodama, ve ć ih mogu koristiti samo ako imaju referencu na odgovarajući objekt. Ako je unutrašnja klasa pridružena instanci klase u kojoj je definirana, tada ima direktan pristup varijablama i metodama instance. Također, buduć i da je unutrašnja klasa pridružena instanci, ona sama ne smije definirati nikakve statičke članove. Kako bi vam pomogli razlikovati termine ugniježdene i unutrašnje klase, promislite o njima na sljedeći način. Termin "ugniježdena klasa" odražava sintaktičku relaciju izmeđ u dviju klasa, tj. sintaktič ki, kôd jedne klase nalazi se unutar druge. Nasuprot tome, termin "unutrašnja klasa" odražava relaciju izmeđ u instanci dviju klasa. Promotrite sljedeće klase: class EnclosingClass {... class InnerClass {... Zanimljiva osobina relacije ovih dviju klasa nije to što je InnerClass sintaktič ki definirana unutar EnclosingClass klase, ve ć što instanca InnerClass klase može postojati samo unutar instance EnclosingClass klase i ima direktan pristup njezinim varijablama i metodama instance. Na ugniježdene klase obaju tipova možete naići u Java API-ju. Međutim, već ina klasa koje vi napišete bit će unutrašnje klase. 107

108 Definicija: Unutrašnja klasa (inner class) je ugniježdena klasa č ije instance postoje unutar instance klase koja ju sadrži, a ima direktan pristup članovima instance te klase. DRUGE ČINJENICE O UGNIJEŽDENIM KLASAMA Kao i druge klase, ugniježdene klase mogu se deklarirati kao abstract ili final. Znač enje ovih dvaju modifikatora je isto kao i za druge klase. Također, modifikatori pristupa - private, public, protected i package mogu se koristiti za ogranič avanje pristupa ugniježdenim klasama, kao što se koriste i za druge klase. Bilo koja ugniježdena klasa (ne samo anonimna) može biti deklarirana u bilo kojem bloku koda. Ugniježdena klasa deklarirana unutar metode ili nekog manjeg bloka koda ima pristup bilo kojoj konačnoj lokalnoj varijabli unutar dosega. UNUTRAŠNJE KLASE Kako bi stekli bolju predodžbu o unutrašnjim klasama i za kakve zadatke su dobre, ponovno pogledajmo primjer Stack klase. Pretpostavimo da ovoj klasi poželite dodati svojstvo koje dopušta drugoj klasi numeriranje i pristupanje elementima stacka uz korištenje interfacea definiranog u java.util.enumeration paketu. Ovaj interface sadrži deklaracijuu dviju metoda: public boolean hasmoreelements(); public Object nextelement(); Interface Enumeration definira interface pomoću kojeg je moguće proć i preko svih elemenata neke kolekcije: while (hasmoreelements()) nextelement() Kad bi klasa Stack sama implementirala Enumeration interface, tada ne biste mogli ponovo pokrenuti petlju i enumerirati sadržaj više od jednom. Takođ er, ne biste mogli imati dvije enumeration petlje u isto vrijeme. Zato Stack ne bi trebala implementirati Enumeration. Umjesto toga treba definirati pomoćnu klasu koja bi taj posao trebala činiti za Stack. Pomoćna klasa mora imati pristup elementima Stack-a. Takođ er mora biti sposobna pristupiti im direktno zato što javni interface klase Stack podržava samo LIFO pristup. To je situacija u kojoj unutrašnja klasa predstavlja pravi izbor. Ovdje je dana implementacija Stack klase koja definira pomoćnu klasu (zvanu adapter klasa) za enumeriranje svojih elemenata: public class Stack { private Vector items;...//code for Stack's methods and constructors not shown... public Enumeration enumerator() { return new StackEnum(); 108

109 class StackEnum implements Enumeration { int currentitem = items.size() - 1; public boolean hasmoreelements() { return (currentitem >= 0); public Object nextelement() { if (!hasmoreelements()) throw new NoSuchElementException(); else return items.elementat(currentitem--); Primjetite da StackEnum klasa pristupa direktno items varijabli Stack klase. Unutrašnje klase se koriste primarno u implementaciji adapter klasa kao što je ova u primjeru. Ako planirate obrađivati evente iz AWT-a, tada ćete morati znati koristiti adapter klase, buduć i da ih event-handling mehanizam iz AWT-a intenzivno koristi. ANONIMNE KLASE Unutrašnja klasa se može definirati bez imena. Evo ponovljenog primjera Stack klase, gdje se za enumerator koristi anonimna klasa. public class Stack { private Vector items;...//code for Stack's methods and constructors not shown... public Enumeration enumerator() { return new Enumeration() { int currentitem = items.size() - 1; public boolean hasmoreelements() { return (currentitem >= 0); public Object nextelement() { if (!hasmoreelements()) throw new NoSuchElementException(); else return items.elementat(currentitem--); Anonimne klase mogu učiniti kôd teškim za čitanje. Trebali biste ogranič iti njihovu upotrebu samo na vrlo male klase (s jednom ili dvije metode) i na one č ija je upotreba lako razumljiva (kao u adapter klasama u AWT -u). 109

110 INTERFACE-I I PAKETI Ovo poglavlje razrađ uje osobine programskog jezika Java koje vam pomažu u upravljanju relacijama između klasa koje nisu u odnosu unutar hijerarhije klasa. Prvo ćete nauč iti kako napisati i koristiti interface kao protokol u komunikaciji između ubjekata. Drugo, naučit ć ete kako spojiti interface-ove i klase u pakete. KREIRANJE INTERFACE-A ŠTO JE INTERFACE? Interface definira protokol ponašanja kojeg može implementirati bilo koja klasa u hijerarhiji klasa. Interface definira skup metoda, ali ih ne implementira. Klasa koja implementira interface, slaže se da će implementirati sve metode definirane u interfaceu, a time se slaže o određ enom ponašanju. Definicija: Interface predstavlja imenovani skup metoda (bez implementacije). Interface također može definirati konstante. Buduć i da je interface jednostavna lista neimplementiranih, i stoga apstraktnih, metoda, možete se zapitati kako se interface razlikuje od apstraktnih klasa. Razlika je značajna: Interface ne može implementirati niti jednu metodu, dok apstraktna klasa može. Klasa može implementirati mnogo interfacea, ali smije imati samo jednu nadklasu. Interface nije dio hijerarhije klasa. Klase koje nisu u odnosu mogu implementirati isti interface. Postavimo primjer kojeg ć emo koristiti kroz ovo poglavlje. Pretpostavimo da ste napisali klasu koja može promatrati cijene dionica koje dolaze preko nekog izvora podataka. Ova klasa dopušta drugim kasama de se prijave i kasnije budu obaviještene o tome kad se cijena neke dionice promijeni. Prvo, vaša klasa, koju ćemo zvati StockMonitor, ć e implementirati metodu koja drugim objektima dopušta prijavljivanje: public class StockMonitor { public void watchstock(stockwatcher watcher, String tickersymbol, double delta) {... Prvi argument ove metode je StockWatcher objekt. StockWatcher je ime interfacea čiji ć ete kod upoznati u sljedećem poglavlju. Ovaj interface deklarira jednu metodu: valuechanged. Objekt koji želi biti obaviješten o promjeni dionica mora biti instanca klase koja implementira ovaj interface i stoga implementira valuechanged metodu. Druga dva argumenta osiguravaju simbol dionice kojeg treba promatrati i iznos promjene kojeg promatra č smatra dovoljno zanimljivim da bi o njemu bio obaviješten. Kada StockMonitor klasa detektira zanimljivu promjenu, poziva valuechanged metodu promatrača. 110

111 WatchStock metoda osigurava, kroz tip podatka svog prvog argumenta da svi registrirani objekti implementiraju valuechange metodu. Ovdje ima smisla koristiti interface kao tip podatka buduć i da je samo bitno da registranti implementiraju određenu metodu. Da je StockMonitor klasa koristila ime klase kao tip podatka, to bi na umjetan način utjecalo na relacije među klasama. Buduć i da klasa može imati samo jednu nadklasu, također bi oranič ilo i tip objekata koji mogu koristiti ovu uslugu. Koristeć i interface, registrirani objekti mogu biti bilo što - Applet ili Thread na primjer, tako dozvoljavajući bilo kojoj klasi bilo gdje u hijerarhiji klasa korištenje ove usluge. DEFINIRANJE INTERFACE-A Donja slika prikazuje definiciju interfacea koja se sastoji od dvije komponente: deklaracije interface i tijela interfacea. Deklaracija interface deklarira različ ite atribute interfacea, kao što su njegovo ime i da li proširuje druge interfaceove. Tijelo interfacea sadrži deklaracije konstanti i metoda. Interface prikazan na gornjoj slici je StockWatcher interface spomenut u prethodnom poglavlju. Ovaj interface deklarira tri konstante, koje su simboli promatranih dionica. Ovaj interface također deklarira, ali ne implementira, metodu valuechanged. Klase koje implementiraju ovaj interface osiguravaju implementaciju te metode. DEKLARACIJA INTERFACEA Sljedeća slika prikazuje sve moguće komponente deklaracije interfacea: public interface InterfaceName Extends SuperInterface { InterfaceBody Čini ovaj interface javno dostupnim. Zadaje ime interfacea Navodi nad-interfaceove interfacea Dva elementa koja su nužna u deklaraciji interfacea su ključna rije č interface i ime interfacea. Modifikator pristupa public označ ava da interface može koristiti bilo koja klasa u bilo kojem paketu. Ako ne označite svoj interface kao public, tada ć e biti dostupan samo klasama definiranim u istom paketu u kojem se nalazi interface. Deklaracija interfacea može imati još jednu komponentu: listu nad-interfacea. Interface može proširiti druge interfaceove, isto kao što klasa može proširiti drugu klasu. Međ utim, dok klasa može proširiti samo jednu klasu, interface može proširiti bilo koji broj interfacea. Lista nadinterfacea je lista interfacea koje proširuje novi interface odvojenih zarezima. 111

112 TIJELO INTERFACEA Tijelo interfacea sadrži deklaracije svih metoda koje interface uključ uje. Iza deklaracije metode u interfaceu slijedi točkazarez. Sve metode deklarirane u interfaceu implicitno su public i abstract. Interface, pored deklaracija metoda, može sadržavati deklaracije konstanti. Sve konstantne vrijednosti definirane u interfaceu su implicitno public, static i final. Deklaracije članova u interfaceu spreč avaju korištenje nekih deklaracijskih modifikatora; nije moguće koristiti transient, volatile ili synchronized u deklaraciji č lana interfacea. Također, nije moguće koristiti ni private i protected modifikatore. IMPLEMENTIRANJE INTERFACEA Klasa koja implementira interface odgovara protokolu kojeg definira interface. Kako bi deklarirali klasu koja implementira neki interface, potrebno je u deklaraciju klase uključ iti implements stavku. Budući da klasa može implementirati više od jednog interfacea, ključ nu rije č implements može slijediti lista interfacea odvojenih zarezima. Po dogovoru: implements stavku slijedi extends stavka, ako ova postoji. Ovdje je dan djelomični primjer appleta koji implementira StockWatcher interface: public class StockApplet extends Applet implements StockWatcher {... public void valuechanged(string tickersymbol, double newvalue) { if (tickersymbol.equals(sunticker)) {... else if (tickersymbol.equals(oracleticker)) {... else if (tickersymbol.equals(ciscoticker)) {... Primjetite da ova klasa koristi kosntante definirane u StockWatcher-u, sunticker i oracle-ticker. Klase koje implementiraju interface nasljeđ uju konstante definirane u interfaceu, pa te klase mogu koristiti jednostavna imena za pristupanje konstantama. Bilo koja druga klasa može koristiti konstante interfacea uz korištenje kvalificiranog imena, kao što je: StockWatcher.sunTicker Kad klasa implementira interface, u principu potpisuje ugovor. Ili klasa mora implementirati sve metode deklarirane u interfaceu i njegovim nadinterfaceima, ili klasa mora biti deklarirana kao apstraktna. Ime metode, broj i tip njezinih argumenata moraju se slagati s imenom metode, brojem i tipom argumenata u interfaceu. StockApplet implementira StockWatcher interface, tako da applet osigurava implementaciju valuechanged metode. Metoda može osvježavati prikaz dionica na ekranu ili na neki drugi način koristiti ovu informaciju. 112

113 KORIŠTENJE INTERFACEA KAO TIPA Definiranjem interfacea definirate novi tip podataka. Imena interfacea zato se mogu koristiti na mjestima gdje koristite bilo koji drugi tip podataka. Prosjetite se da je tip podatka prvog argumenta watchstock metode u StockMonitor klasi StockWatcher: public class StockMonitor { public void watchstock(stockwatcher watcher, String tickersymbol, double delta) {... Samo instanca klase koja implementira interface može biti dodijeljena referenci č iji je tip ime interfacea. Tako se samo instance klasa koje implementiraju StockWatcher interface mogu registrirati za primanje obavijesti o promjeni vrijednosti dionica. StockWatcher objekti garantirano imaju valuechanged metodu. UPOZORENJE! INTERFACE-I NE MOGU RASTI Pretpostavimo da želite dodati neku funkcionalnost u StockWatcher. Na primjer, pretpostavimo da želite dodati metodu koja izvještava o trenutnoj vrijednosti dionica, bez obzira da li je vrijednost promijenjena: public interface StockWatcher { final String sunticker = "SUNW"; final String oracleticker = "ORCL"; final String ciscoticker = "CSCO"; void valuechanged(string tickersymbol, double newvalue); void currentvalue(string tickersymbol, double newvalue); Međutim, ako napravite ovu promjenu, sve klase koje implementiraju stari StockWatcher interface neće se moći kompajlirati buduć i da ne implementiraju sve elemente novog interfacea. Rješenje je biti što pažljiviji prije objavljivanja samog interfacea, ili kasnije kreiranje novih interfacea koji proširuju stare interfaceove. public interface StockTracker extends StockWatcher { void currentvalue(string tickersymbol, double newvalue); S ovakvim novim interfaceom, programeri mogu i dalje programirati s nepromijenjenim klasama ili ih nadograditi tako da podržavaju novi interface. 113

114 ZAKLJUČAK O KREIRANJU INTERFACE-OVA Interface definira protokol u komunikaciji izmeđ u dva objekta. Definicija interfacea sastoji se od deklaracije i tijela interfacea. Tijelo interfacea sadrži deklaracija, ali ne i implementacije, skupa metoda. Interface takođ er može sadržavati definicije konstanti. Klasa koja implementira interface mora implementirati sve metode deklarirane u interfaceu. Ime interfacea može se koristiti kao novi tip podataka. 114

115 KREIRANJE I KORIŠTENJE PAKETA Kako bi vaše klase uč inili lakšim za pronalaženje i korištenje, kako bi izbjegli konflikte u imenovanju i kontroli prostupa, programeri grupiraju povezane klase i interfaceove u pakete. Definicija: Paket (package) je skup povezanih klasa i interfacea koji omoguć uje zaštitu pristupa i upravljanje prostorom imena (namespace). Klase i interfacei koji su dio Java platforme, članovi su različ itih paketa koji grupiraju klase po njihovoj funkciji: osnovne klase su u paketu java.lang, klase za č itanje i pisanje (ulaz i izlaz) su u java.io, itd. I vi također možete svoje klase i interfaceove staviti u pakete. Pogledajmo jedan skup klasa i prouč imo zašto biste ih poželjeli staviti u paket. Pretpostavimo da ste napisali grupu klasa koje predstavljaju kolekciju grafič kih objekata, kao što su kružnice, pravokutnici, linije i točke. Također ste napisali interface, Draggable, kojeg klase implementiraju ako ih korisnik može biti pomicati mišem. //in the Graphic.java file public abstract class Graphic {... //in the Circle.java file public class Circle extends Graphic implements Draggable {... //in the Rectangle.java file public class Rectangle extends Graphic implements Draggable {... //in the Draggable.java file public interface Draggable {... Ove biste klase i interfaceove trebali zapakirati u paket zbog nekoliko razloga: Vi i drugi programeri možete jednostavno odrediti da su ove klase i interfacei povezani. Vi i drugi programeri znat ćete gdje pronać i klase i interfaceove koji osiguravaju grafičke funkcije. Imena vaših klasa neć e biti u konfliktu s imenima klasa u drugim paketima, budući da paket kreira novi namespace. Unutar paketa klasama možete dozvoliti neograničen pristup č lanovima drugih klasa, a klasama van paketa ga ograničiti. KREIRANJE PAKETA Za kreiranje paketa dovoljno je staviti neku klasu ili interface u taj paket. Da biste to uč inili, stavite iskaz package na vrh datoteke s izvornim kodom u kojem je definirana klasa ili 115

116 interface. Na primjer, sljedeći kôd nalazi se u izvornoj datoteci Circle.java i stavlja Circle klasu u graphics paket: package graphics; public class Circle extends Graphic implements Draggable {... Klasa Circle je public član graphics paketa. Iskaz package mora se uključ iti na vrhu svake izvorne datoteke koja definira klasu ili interface unutar graphics paketa. Isti biste iskaz trebali zato staviti i u Rectangle.java datoteku: package graphics; public class Rectangle extends Graphic implements Draggable {... Doseg package iskaza je cijela izvorna datoteka, pa su sve klase i interface-i definirani u Circle.java i Rectangle.java datotekama također članovi graphics paketa. Ako višestruke klase stavite u jednu izvornu datoteku, samo jedna klasa može biti public, i mora imati isto ime kao i osnovni dio izvorne datoteke. Samo javni č lanovi paketa su dostupni i izvan paketa. Ako ne navedete iskaz package, vaša klasa ili interface bit ć e dio podrazumijevanog paketa (default package), a to je paket koji nema ime. Općenito govoreć i, podrazumijevani paket koristi se samo za male ili privremene aplikacije ili na poč etku razvoja. U suprotnom, paketi i interface-i bi trebali pripadati imenovanim paketima. IMENOVANJE PAKETA Budući da ima mnogo programera koji širom svijeta pišu klase i interfaceove koristeć i Javu kao programski jezik, vrlo je vjerojatno da će dva programera upotrijebiti isto ime za dvije različ ite klase. U biti, prethodni primjer čini upravo to: definira Rectangle klasu, a klasa istog imena ve ć postoji u java.awt paketu. Pa ipak, kompajler dozvoljava objema klasama da imaju isto ime. Zašto? Zbog toga što se nalaze u različ itim paketima, a kvalificirano ime svake klase uključuje i ime paketa. To znači da je kvalificirano ime Rectangle klase u graphics paketu graphics.rectangle, a kvalificirano ime Rectangle klase u java.awt paketu java.awt.rectangle. Ovo opć enito radi dobro sve dok dva nezavisna programera ne naprave dva paketa istog imena. Što može spriječiti ovakav problem? Dogovor. Po dogovoru: Tvrtke koriste inverzno ime svoje Internet domene u imenu njihovih paketa, kao što je ovo: com.company.package. Neke tvrtke često izostavljaju com u imenu paketa. Koliziju imena koja se može desiti unutar jedne tvrtke takođ er je potrebno riješiti dogovorom unutar tvrtke, možda uključ ivanjem regije ili imena projekta nakon imena tvrtke, na primjer: com.company.region.package. 116

117 KORIŠTENJE ČLANOVA PAKETA Samo public č lanovi paketa su dostupni i izvan paketa u kojem su definirani. Za korištenje javnih package članova izvan paketa, morate učiniti jedno od sljedećeg: Dohvaćati člana uz pomo ć njegovog dugog (kvalificiranog) imena Uvesti člana paketa Uvesti cijeli paket Svaki od ovih načina prikladan je za različitu situaciju, kako je objašnjeno u sljedeć im poglavljima. DOHVAČANJE ČLANA PAKETA PREKO IMENA Do sada, primjeri u ovom tekstu dohvaćali su klase i interfaceove pomoć u njihovog jednostavnog imena, kao što je Rectangle i StockWatcher. Jednostavno ime č lana paketa može se koristiti u kodu kojeg pišete unutar istog paketa ili ako je paket tog člana uvezen. Međutim, ako pokušate koristiti člana iz različ itog paketa a taj paket nije uvezen, tada morate koristiti članovo kvalificirano ime, koje uključ uje ime paketa. Ovo je kvalificirano ime Rectangle kalse deklarirane u graphics paketu iz prethodnog primjera: graphics.rectangle Možete koristiti ovo dugo ime za kreiranje graphics.rectangle objekta: graphics.rectangle myrect = new graphics.rectangle(); Kroz praksu ć ete vidjeti da je korištenje dugih imena zgodno za jedno korištenje ili dva, ali vrlo je vjerojatno da će vam uskoro dosaditi pisanje graphics.rectangle. Također ć e i vaš kôd izgledati vrlo neuredno i teško za čitanje. U takvim sluč ajevima možete jednostavno uvesti člana. UVOZ ČLANA PAKETA Kako bi uvezli određenog člana u vašu trenutnu datoteku, morete staviti import iskaz na početku vaše datoteke prije bilo koje definicije klase ili interfacea, ali nakon package iskaza, ako ovaj postoji. Za uvođenje Circle klase iz graphics paketa kreiranog u prethodnom poglavlju učinili biste ovo: import graphics.circle; Sada Circle klasu možete dohvaćati uz pomo ć njezinog jednostavnog imena: Circle mycircle = new Circle(); Ovo dobro radi ako koristite samo nekoliko č lanova graphics paketa. Ali, ako koristitite mnogo klasa i interfacea iz ovog paketa, možete uvesti cijeli paket. 117

118 UVOZ CIJELOG PAKETA Za uvoz svih klasa i interfaceova koje sadrži određ eni paket, koristite se import iskazom sa zvjezdicom (*). import graphics.*; Sada možete dohvatiti bilo koju klasu ili interface iz graphics paketa pomoć u njihovog kratkog imena: Circle mycircle = new Circle(); Rectangle myrectangle = new Rectangle(); Zvjezdica u import iskazu može se koristiti samo za određ ivanje uvoza svih klasa unutar paketa. Nije moguće koristiti zvjezdicu za uvoz nekog podskupa klasa paketa. Na primjer, sljedeć e ne uvozi samo klase graphics paketa koje počinju slovom A: import graphics.a*; // does not work Umjesto toga, ovo generira kompajlersku pogrešku. Uz pomo ć import iskaza, možete uvesti ili samo jednog člana paketa ili cijeli paket. Radi lakšeg korištenja, Java automatski uvozi tri paketa: Podrazumijevani paket (paket bez imena). java.lang paket. Trenutni paket. NEJASNOĆE OKO IMENA Ako nekim slučajem član jednog paketa dijeli isto ime s č lanom drugog paketa i oba paketa su uvezena, svakog od tih članova morat ćete dohvaćati pomoć u njegovog dugog imena. Na primjer, prethodni primjer definira klasu imena Rectangle u graphics paketu. java.awt paket također sadrži Rectangle klasu. Ako uključite i graphics i java.awt paket, ova deklaracija je nejasna: Rectangle rect; U tim situacijama morate biti određeniji i koristiti dugo ime č lana, kako bi jasno rekli na koju Rectangle klasu mislite: graphics.rectangle rect; UPRAVLJANJE IZVORNIM I CLASS DATOTEKAMA Mnoge implementacije Java platforme oslanjaju se na hijerarhijski datoteč ni sistem radi upravljanja izvornim i class datotekama iako to ne zahtjeva The Java Language Specification. Strategija je ovakva: Stavite izvorni kod klase ili interfacea u tekstualnu datoteku č ije ime je jednostavno ime klase ili interfacea, a č iji je nastavak.java. Zatim stavite izvornu datoteku u direktorij č ije ime odražava ime paketa kojem klasa ili interface pripada. Na primjer, izvorni 118

119 kôd Rectangle klase bio bi u datoteci imena Rectangle.java, a datoteka bi bila u direktoriju graphics. Direktorij graphics može biti bilo gdje u file sistemu. Slika prikazuje kako ovo radi: Kvalificirano ime člana paketa i ime staze do datoteke su paralelni: class name pathname to file graphics.rectangle graphics/rectangle.java Kao što se možda sijeć ate, po dogovoru tvrtka koristi inverzno ime svoje Internet domene u imenu paketa. Izmišljena tvrtka čije je Internet ime taranis.com bi ispred imena svih svojih paketa stavljala com.taranis. Svaka komponenta imena paketa odgovara imenu poddirektorija. Tako, ako Taranis ima graphics paket koji sadrži Rectangle.java izvornu datoteku, ona bi bila smještena unutar niza poddirektorija kao na slici: Kada kompajlirate izvornu datoteku, kompajler će kreirati različ itu class datoteku za svaku klasu i interface definiran u njoj. Osnovno ime izlazne datoteke je ime klase ili interfacea, a njezina ekstenzija je.class: Kao i.java datoteka,.class datoteka takođ er treba biti u nizu direktorija koji odražavaju ime paketa. Međ utim, ne mora biti u istom direktoriju u kojem je izvorna datoteka. Svoje izvorne i class direktorije možete organizirati odvojeno: 119

120 Ovako svoj class direktorij možete dati na korištenje drugim programerima bez da im otkrivate svoje izvorne datoteke. Zašto biste se uopć e brinuli oko direktorija i imena datoteka? Izvornim i class datotekama je potrebno upravljati na način da ih kompajler i interpreter mogu pronaći. Kad kompajler naiđ e na novu klasu tijekom kompajliranja vašeg programa, mora biti sposoban pronać i definiciju te klase. Slično, kada interpreter naiđ e na novu klasu prilikom rada vašeg programa, mora biti sposoban pronać i klasu kako bi pronašao njezine metode i sl. I kompajler i interpreter traže klase u svakom direktoriju ili ZIP datoteci izlistanoj u vašem class pathu. Definicija: class path je uređ en popis direktorija ili ZIP datoteka u kojima se traže class datoteke. Svaki direktorij izlistan u class pathu je direktorij najviše razine u kojem se nalaze package direktoriji. Iz direktorija najviše razine, ovisno o imenu paketa i klase, kompajler i interpeter mogu konstruirati ostatak staze. Na primjer, class path stavka u strukturi direktorija prikazanoj na prethodnom dijagramu uključila bi classes, ali ne com ili bilo koji od direktorija ispod com. I kompajler i interpeter konstruirat ć e ime staze do.class datoteke uz pomo ć punog imena paketa. Kompajler i interpreter pretražit ć e trenutni direktorij i ZIP datoteku koja sadrži platformske Java class datoteke. Drugim riječ ima, trenutni direktorij i class datoteke Java platforme nalaze se automatski u vašem class pathu. Većina, ako ne i sve, klase mogu se pronać i na ove dvije lokacije. U nekim slučajevima, međutim, možda ćete morati postaviti svoj class path. ZAKLJUČAK O KREIRANJU I KORIŠTENJU PAKETA Za kreiranje paketa potrebno je u nj staviti klasu ili interface. Kako bi stavili klasu ili interface u paket, morate staviti package iskaz kao prvi iskaz u vašoj izvornoj datoteci. Ime staze izvornih i class datoteka vaše klase ili interfacea odraž ava ime vašeg paketa. Za korištenje klase ili interfacea koji se nalaze u drugom paketu, imate tri mogućnosti: Korištenje dugog imena klase ili interfacea Uvođenje klase ili interfacea Uvođenje cijelog paketa u kojem se nalaze željene kalse ili interfacei. Možda ćete trebati postaviti svoj class path tako da kompajler i interpreter mogu pronać i izvorne i class datoteke za vaše klase i interfaceove. 120

121 OBRADA POGREŠKI POMOĆU IZNIMKI Pogreške nastaju u računalnim programima i nešto su što se ne može izbjeć i. Postavlja se pitanje što učiniti nakon što nastupi pogreška. Kako ju obraditi? Tko je treba obraditi? Može li se program od nje oporaviti ili treba jednostavno prekinuti s radom? ŠTO JE IZNIMKA? Termin iznimka (exception) je kraća verzija fraze iznimni događaj ( exceptional event). Može se definirati ovako: Definicija: Iznimka je događaj koji ometa prirodni tok izvršavanja programa. Mnogi tipovi pogreški mogu prouzroč iti iznimke - problemi nastali zbog ozbiljnih hardverskih pogreški, kao što je kvar hard diska, pa do jednostavnih programskih pogreški, kao što je pokušaj dohvać anja elementa niza van granica niza. Kada u Java metodi nastupi takva pogreška, metoda kreira objekt iznimku i predaje ga runtime sistemu. Objekt iznimka sadrži informacije o iznimci, uključujuć i njezin tip i stanje programa u trenutku kada je nastupila. Runtime sistem je odgovoran za pronalaženje koda koji ć e obraditi pogrešku. U terminologiji Jave, kreiranje objekta iznimke i njegovo predavanje runtime sistemu zove se bacanje iznimke (throwing an exception). Nakon što metoda baci iznimku, runtime sistem će pokušati pronać i nekoga tko može obraditi iznimku. Skup moguć ih "nekoga" koji mogu obraditi iznimku je skup metoda u call stacku metode u kojoj je nastupila pogreška. Runtime sistem pretražuje call stack unatrag, poč evši od metode u kojoj je metoda nastupila, dok ne pronađe metodu koja sadrži odgovarajuć i kôd za obradu iznimke (exception handler). Exception handler je odgovarajući ako tip bač ene iznimke odgovara tipu iznimke koju exception handler može obraditi. Tako iznimka isplivava kroz call stack dok se ne pronađe odgovarajuć i exception handler. Za odabrani exception handler se kaže da hvata (catch) iznimku. Ako runtime sistem pri pretraživanju call stacka ne pronađe odgovarajuć i exception handler, prekinut će izvršavanje vašeg programa. Korištenjem iznimki za obradu pogreški, Java programi imaju sljedeć e prednosti nad tradicionalnim tehnikama obrade pogreški: Prednost 1: Odvajanje koda koji obrađuje pogreške od "regularnog" koda Prednost 2: Propagiranje pogreški kroz call stack Prednost 3: Grupiranje tipova pogreški i njihovo razlikovanje 121

122 PREDNOST 1: ODVAJANJE KODA KOJI UPRAVLJA POGREŠKAMA OD "REGULARNOG" KODA U tradicionalnom programiranju, detekcija pogreški, prijavljivanje i njihova obrada č esto vodi do konfuznog "špageti" koda. Na primjer, pretpostavimo da imate funkciju koja uč itava cijelu datoteku u memoriju. U pseudo-kodu bi vaša funkcija mogla izgledati ovako: readfile { open the file; determine its size; allocate that much memory; read the file into memory; close the file; Na prvi pogled ova funkcija izgleda jednostavno, ali ignorira ove potencijalne pogreške: Što se dešava ako datoteka ne može biti otvorena? Što se dešava ako duljina datoteke ne može biti određena? Što se dešava ako ne može biti alocirano dovoljno memorije? Što se dešava ako dođe do pogreške u čitanju? Što se dešava ako datoteka ne može biti zatvorena? Za odgovor na ova pitanja unutar readfile funkcije, morate dodati prilič no koda za detekciju pogreške, njezinu obradu i izvještavanje. Vaša će funkcija na koncu vjerojatno izgledati slič no ovome: errorcodetype readfile { initialize errorcode = 0; open the file; if (thefileisopen) { determine the length of the file; if (gotthefilelength) { allocate that much memory; if (gotenoughmemory) { read the file into memory; if (readfailed) { errorcode = -1; else { errorcode = -2; else { errorcode = -3; close the file; if (thefiledidntclose && errorcode == 0) { errorcode = -4; else { errorcode = errorcode and -4; else { errorcode = -5; return errorcode; 122

123 Uz pomo ć ugrađ ene detekcije pogreški, vaših originalnih sedam linija koda (podebljanih) narasle su na 29 linija koda - tj. za faktor od gotovo 400%! Što je još gore, toliko je koda koji detektira pogreške i obrađ uje pogreške, da se orginalnih 7 linija koda potpuno izgubilo u tom mnoštvu. I logični je tok programa također izgubljen, pa je vrlo teško reć i da li radi što bi trebao: Da li se datoteka zbilja zatvori ako funkcija ne uspije alocirati dovoljno memorije? Još je teže osigurati pravilno izvršavanje koda, ako ga poželite promijeniti nakon tri mjeseca. Mnogi programeri "rješavaju" ovaj problem ignorirajuć i ga - pogreške se "prijavljuju" kad se program sruši. Java omoguć ava elegantno rješenje problema: iznimke. Iznimke dopuštaju pisanje glavnog toka vašeg koda na jednom, a bavljenje iznimnim sluč ajevima na drugom mjestu. Kad bi vaša readfile funkcija koristila iznimke umjesto tradicionalne obrade pogreški, izgledala bi ovako: readfile { try { open the file; determine its size; allocate that much memory; read the file into memory; close the file; catch (fileopenfailed) { dosomething; catch (sizedeterminationfailed) { dosomething; catch (memoryallocationfailed) { dosomething; catch (readfailed) { dosomething; catch (fileclosefailed) { dosomething; Iznimke vas, naravno, ne rješavaju truda u detektiranju, prijavljivaju i obradi pogreški, ali vam dozvoljavaju odvajanje tih detalja od glavne logike programa. Pored toga, program nam je narastao za oko 250%, pa to usporedite s 400% iz prethodnog primjera. PREDNOST 2: PROPAGIRANJE POGREŠKI UZ CALL STACK Druga prednost iznimki je moguć nost propagiranja prijave pogreške uz call stack (stek poziva metoda). Pretpostavite da je readfile metoda č etvrta metoda u nizu ugniježdenih poziva metoda koje je pozvao vaš glavni program: method1 zove method2, koja zove method3, koja konačno zove readfire. method1 { call method2; method2 { call method3; method3 { call readfile; 123

124 Pretpostavimo da je method1 jedina metoda koju zanimaju pogreške koje nastupaju unutar readfire metode. Tradicionalne tehnike obavještavanja o pogreškama prisiljavaju method2 i method3 da propagira podatke o pogrešci koje vraća readfire uz call stack dok konač no ne dođu do method1 - jedine metode koju zanimaju. method1 { errorcodetype error; error = call method2; if (error) doerrorprocessing; else proceed; errorcodetype method2 { errorcodetype error; error = call method3; if (error) return error; else proceed; errorcodetype method3 { errorcodetype error; error = call readfile; if (error) return error; else proceed; Kako ste nauč ili prije, Java runtime sistem pretražuje call stack unatrag kako bi pronašao metodu koja se zanima za određ enu iznimku. Java metoda može ignorirati bilo koju iznimku koja je bačena unutar nje, tako dozvoljavajuć i hvatanje iznimke metodama koje se nalaze na višem mjestu u call stacku. Tako samo metode koje brinu o pogreškama moraju brinuti o njihovom detektiranju. method1 { try { call method2; catch (exception) { doerrorprocessing; method2 throws exception { call method3; method3 throws exception { call readfile; Međutim, kao što vidite iz pseudo-koda, ignoriranje pogreški zahtjeva određ eni napor u metodama "srednje razine". Bilo koja metoda koja može biti bač ena unutar metode, predstavlja dio javnog interfacea i mora biti specificirana u throws sekciji. Tako metoda informira svog pozivatelja o iznimkama koje može baciti, pa pozivatelji mogu inteligentnije i konciznije odlučiti što učiniti s tim iznimkama. 124

125 Primjetite opet razliku u velič ini koda. Kôd koji koristi iznimke kompaktniji je i lakši za razumijevanje. PREDNOST 3: GRUPIRANJE TIPOVA POGREŠKI I RAZLIKOVANJE POGREŠKI Pogreške često padaju u određ enu kategoriju ili grupu. Na primjer, zamislite grupu iznimki od kojih svaka predstavlja određ eni tip pogreške koja može nastupiti prilikom manipuliranja nizom: indeks je izvan granica niza, element koji se želi umetnuti u niz je pogrešnog tipa ili element koji se traži nije u nizu. Dalje, možete zamisliti da neke neke metode žele obraditi sve iznimke koje padaju unutar ove kategorije (sve iznimke nizova), a druge metode možda žele obraditi baš određenu iznimku (npr. samo iznimku lošeg indeksa). Buduć i da su sve iznimke unutar Java programa objekti, grupiranje i kategorizacija iznimki predstavlja prirodnu posljedicu hijerarhije klasa. Java iznimke moraju biti instance Throwable klase ili bilo koji nasljednik Throwable klase. Svaka klasa koja nema podklase (leaf klasa) predstavlja specifični tip iznimke, a svaka klasa s jednom ili više podklasa ( node klasa) predstavlja grupu povezanih iznimki. Na primjer, u sljedećem dijagramu, ArrayException je podklasa Exception klase i ima tri podklase. InvalidIndexException, ElementTypeException i NoSuchElementException su leaf klase. Svaka predstavlja specifič ni tip pogreške koji može nastupiti kad se manipulira nizom. Jedan od nač ina na koji metoda može uhvatiti iznimke je da uhvati samo one koje su instance leaf klase. Na primjer, exception handler koji obrađuje samo InvalidIndexException ima ovakav catch iskaz: catch (InvalidIndexException e) {... ArrayException je node klasa i predstavlja bilo koju pogrešku koja može nastupiti prilikom manipuliranja nizom, uključujuć i i pogreške predstavljene nekom od njezinih podklasa. Metoda može uhvatiti iznimku ovisno o njezinoj grupi ili općenitom tipu određ ivanjem nadklase iznimke u catch iskazu. Na primjer, za hvatanje svih iznimki nizova, exception handler bi izgledao ovako: catch (ArrayException e) {

126 Ovaj handler bi uhvato i iznimke tipa InvalidIndexException, ElementTypeException i NoSuchElementException. Ispitujući parametar e, moguće je precizno saznati tip bač ene iznimke. Čak je moguće uhvatiti i bilo koju iznimku kao u donjem primjeru: catch (Exception e) {... Exception handleri koji su previše općeniti, kao ovaj prikazan gore, mogu uč initi vaš kôd podložnim pogreškama, buduć i da takav kôd hvata i iznimke koje ne želite. U pravilu se pisanje općenitih exception handlera ne preporučuje. PRVI SUSRET S JAVA IZNIMKAMA Sljedeća poruka o pogrešci je jedna od dvije slične poruke koje ć ete vidjeti ako pokušate kompajlirati klasu InputFile (dalje u tekstu), budući da InputFile klasa sadrži pozive metoda koje bacaju iznimke: InputFile.java:8: Warning: Exception java.io.filenotfoundexception must be caught, or it must be declared in throws clause of this method. in = new FileReader(filename); ^ Jave programski jezik zahtjeva da metode ili uhvate ili navedu sve provjeravane iznimke koje mogu biti bačene unutar dosega te metode. Ako kompajler naiđ e na metodu, kao što je ova u InputFile klasi, koje ne zadovoljava ove zahtjeve, prijavit će pogrešku i odbit ć e prevesti program. Pogledajmo InputFile detaljnije. Klasa InputFile je ovojnica FileReader klase i osigurava metodu, getword, za čitanje riječi s trenutne pozicije u čitaču. // Note: This class won't compile by design! import java.io.*; public class InputFile { private FileReader in; public InputFile(String filename) { in = new FileReader(filename); public String getword() { int c; StringBuffer buf = new StringBuffer(); do { c = in.read(); if (Character.isWhitespace((char)c)) return buf.tostring(); else buf.append((char)c); 126

127 while (c!= -1); return buf.tostring(); Kompajler ć e ispisati pogrešku zbog podebljane linije u gornjem kodu. Ta linija kreira novi FileReader objekt i koristi ga za otvaranje datoteke čije je ime argument FileReader konstruktora. Što bi FileReader trebao uč initi ako datoteka ne postoji? To, naravno, ovisi o tome što program koji koristi FileReader želi. Implementatori FileReader ne znaju što bi InputFile klasa željela učiniti ako datoteka ne postoji. Treba li FileReader ubiti program? Treba li pokušati s drugim imenom datoteke? Treba li kreirati datoteku toga imena? Buduć i da nema načina na koji bi FileReader klasa mogla izabrati sluč aj koji vrijedi za svakog korisnika ove klase, odabran je način da u takvom sluč aju baci iznimku. Ako datoteka imenovana u argumentu FileReader konstruktora ne postoji, konstruktor ć e baciti iznimku java.io.filenotfoundexception. Bacajući iznimku, FileReader dopušta metodi pozivatelju obradu pogreške na najprikladniji mogući način. Kao što se vidi iz koda, InputFile klasa u potpunosti ignorira č injenicu da konstruktor klase FileReader može baciti iznimku. Međutim, kako je utvrđ eno prije, Java zahtjeva da metoda ili uhvati ili navede sve provjerene iznimke koje mogu biti bač ene unutar dosega metode. Budući da InputFile klasa ne č ini ni jedno od to dvoje, kompajler odbija kompajliranje programa. Pored prije pokazane poruke o pogrešci, vidjet ćete i još jednu vrlo sličnu poruku: InputFile.java:15: Warning: Exception java.io.ioexception must be caught, or it must be declared in throws clause of this method. while ((c = in.read())!= -1) { Metoda InputFile klase, getword, čita podatke iz FileReader-a otvorenog u konstruktoru InputFile klase. Budući da InputFile klasa niti hvata niti navodi java.io.ioexception iznimku koju može baciti read metoda FileReader klase, kompajler odbija kompajliranje. Na ovom mjestu imate dvije mogućnosti. Ili u odgovarajućim metodama InputFile klase uhvatiti ove iznimke ili dopustiti drugim metodama na call stacku njihovo hvatanje. Primjer ispravnog programa: import java.io.*; public class InputFileDeclared { private FileReader in; public InputFileDeclared(String filename) throws FileNotFoundException { in = new FileReader(filename); public String getword() throws IOException { int c; StringBuffer buf = new StringBuffer(); 127

128 do { c = in.read(); if (Character.isWhitespace((char)c)) return buf.tostring(); else buf.append((char)c); while (c!= -1); return buf.tostring(); ZAHTJEV "UHVATI ILI NAVEDI" (CATCH OR SPECIFY) Metoda mora ili hvatati ili odrediti sve provjeravane iznimke koje mogu biti bač ene unutar dosega metode. UHVATI (CATCH) Metoda će uhvatiti ako osigura exception handler za taj tip iznimke. NAVEDI (SPECIFY) Ako metoda odluč i ne uhvatiti iznimku, tada mora eksplicitno naglasiti da može baciti tu iznimku. Zašto projektanti Jave ovo zahtjevaju? Zato što iznimka koju može baciti metoda predstavlja dio javnog interfacea metode: pozivatelji metode moraju znati koji tip iznimke metoda može baciti kako bi na pravi način odlučili što učiniti ako takva iznimka nastupi. PROVJERAVANE IZNIMKE (CHECKED EXCEPTIONS) Java ima različite tipove iznimki, uključujuć i I/O iznimke, runtime iznimke i iznimke koje sami kreirate. U ovoj raspravi interesantne su nam runtime iznimke. Runtime iznimke su iznimke koje mogu nastupiti unutar Java runtime sistema. Ovo uključuje aritmetič ke iznimke (npr. dijeljenje s nulom), iznimke pointera (npr. pokušaj pristupa null referenci), i iznimke indeksa (pokušaj pristupa elementu niza preko indeksa koji je prevelik ili premali). Runtime iznimke mogu nastupiti bilo gdje u programu i mogu biti vrlo brojne. Cijena provjere runtime iznimki često nadilazi prednost njihovog hvatanja ili navođ enja. Stoga kompajler ne zahtjeva da uhvatite ili navedete runtime iznimku, iako to možete uč initi. Provjeravane iznimke (checked exceptions) su iznimke koje nisu runtime iznimke, a kompajler ih provjerava (tj. provjerava da li ih hvatate ili navodite). Neki ovo smatraju rupom u Javinom mehanizmu obrade iznimki, pa se programeri č esto nalaze pred iskušenjem da sve iznimke učine runtime iznimkama, što nije preporučljivo. 128

129 IZNIMKE KOJE MOGU BITI BAČENE UNUTAR DOSEGA METODE Ovaj naslov može na prvi pogled izgledati očitim: samo potražite throw stavku. Međ utim, ovaj iskaz uključuje više od iznimki koje mogu biti bačene direktno od strane metode: klju č je u frazi unutar dosega. Ova fraza uključuje bilo koju iznimku koja može biti bač ena dok je kontrola toka unutar metode, tj: Iznimke koje su bačene direktno iz metode pomoću throw iskaza. Iznimke koje su bačene indirektno iz metode pozivom drugih metoda. PRIMJER: LISTA BROJEVA Sljedeći primjer definira i implementira klasu klasa Java paketa, a koje mogu baciti iznimke. ListOfNumbers koja poziva dvije metode iz // Note: This class won't compile by design! // See ListOfNumbersDeclared.java or ListOfNumbers.java // for a version of this class that will compile. import java.io.*; import java.util.vector; public class ListOfNumbers { private Vector victor; private static final int size = 10; public ListOfNumbers () { victor = new Vector(size); for (int i = 0; i < size; i++) victor.addelement(new Integer(i)); public void writelist() { PrintWriter out = new PrintWriter(new FileWriter("OutFile.txt")); for (int i = 0; i < size; i++) out.println("value at: " + i + " = " + victor.elementat(i)); out.close(); Po konstrukciji, ListOfNumbers kreira Vector koji sadrži deset Integer elemenata sa sekvencijalnim vrijednostima 0 do 9. Klasa ListOfNumbers takođ er definira metodu imena writelist koja ispisuje listu brojeva u tekstualnu datoteku zvanu OutFile.txt. Metoda writelist poziva dvije metode koje mogu baciti iznimke. Prvo, sljedeć a linija pokreće konstruktor FileWriter klase koji baca IOException ako datoteka ne može biti otvorena: out = new PrintWriter(new FileWriter("OutFile.txt")); 129

130 Drugo, metoda elementat klase Vector baca ArrayIndexOutOfBoundsException ako je indeks premali (negativan broj) ili prevelik (veći od broja elemenata). out.println("value at: " + i + " = " + victor.elementat(i)); Ako pokušate kompajlirati ListOfNumbers klasu, kompajler ć e ispisati pogrešku o iznimci koju baca FileWriter konstruktor, ali neć e prikazati pokrešku o iznimci koju baca elementat. To je stoga što je iznimka koju baca FileWriter konstruktor (IOException) provjeravana iznimka (checked exception), a iznimka koju baca elementat metoda (ArrayIndexOutOfBoundsException) runtime iznimka. HVATANJE I OBRADA IZNIMKI Sad kad ste se upoznali s ListOfNumbers klasom i mjestima unutar klase gdje iznimke mogu biti bačene, možete naučiti kako pisati exception handlere za hvatanje i obradu ovih iznimki. Tri sekcije koje slijede pokrivaju tri komponente exception handlera - try, catch i finally blokove. try BLOK Prvi korak u konstruiranju exception handlera je zatvaranje iskaza koji mogu baciti iznimku u try blok: try { Java statements Dio koda nazvan Java statements sastavljen je od jedne ili više legalnih Java iskaza koji mogu baciti iznimku. Za konstruiranje exception handelra za writelist metodu ListOfNumbers klase, trebate zatvoriti iskaze koji bacaju iznimku u try block. Postoji više od jednog nač ina kako se ovo može učiniti. Možete staviti svaki iskaz koji može baciti iznimku unutar vlastitog try bloka ili sve writelist iskaze unutar istog try bloka i dodijeliti mu višestruke exception handlere. Sljedeći listing koristi jedan try iskaz za cijelu metodu zato što je kôd tako lakši za čitanje. PrintWriter out = null; try { System.out.println("Entering try statement"); out = new PrintWriter( new FileWriter("OutFile.txt")); for (int i = 0; i < size; i++) out.println("value at: " + i + " = " + victor.elementat(i)); 130

131 Iskaz try nadgleda iskaze unutar sebe i definira doseg dodijeljenih mu exception handlera. Drugim riječima, ako nastupi iznimka unutar try iskaza, iznimka će biti obrađ ena unutar odgovarajućeg exception handlera pridruženog tom try iskazu. try iskaz mora imati pridružen bar jedan catch blok ili jedan finally blok. catch BLOK Kako ste naučili na prethodnoj stranici, try iskaz definira doseg pridruženih exception handlera. Exception handler se pridružuje try iskazu osiguravajući jedan ili više catch blokova direktno iza try bloka: try {... catch (... ) {... catch (... ) { Ne smije biti nikakvog koda između kraja oblik catch iskaza je: try iskaza i početka prvog catch (SomeThrowableObject variablename) { Java statements catch iskaza. Opć eniti Kao što vidite, catch iskaz zahtjeva jedan formalni argument. Argument catch iskaza izgleda kao argument deklaracije metode. Tip argumenta, SomeThrowableObject, deklarira tip iznimke koju handler može obraditi i mora biti ime klase koja nasljeđuje Throwable klasu definiranu u java.lang paketu. U Java programu, bacanje iznimke nije ništa drugo nego bacanje objekta, a samo objekti izvedeni iz Throwable mogu biti bačeni. variablename je ime pomoću kojeg exception handler može pristupiti uhvać enom objektu (iznimci). Na primjer, exception handleri writelist metode (prikazane kasnije) zovu getmessage metodu iznimke koristeći objekt imena e: e.getmessage() Varijablama instance i metodama iznimke pristupate na jednaki nač in kao i varijablama i metodama drugih objekata. getmessage je metoda koju osigurava Throwable klasa, a koja ispisuje dodatne informacije o pogrešci koja je nastupila. Klasa Throwable takođ er implementira dvije metode za ispunjavanje i ispis sadržaja call stacka kad nastupi iznimka. Podklase Throwable klase mogu dodati druge metode i varijable instance. catch blok sadrži niz legalnih Java iskaza. Ovi iskazi izvršavaju se ako je pozvan exception handler. Runtime sistem poziva exception handler ako je on prvi exception handler na call stacku kojem odgovara tip bačene iznimke. writelist metoda iz ListOfNumbers klase koristi dva exception handlera za svoj try iskaz - po jedan handler za ArrayIndexOfBoundsException i IOException. try {

132 catch (ArrayIndexOutOfBoundsException e) { System.err.println("Caught ArrayIndexOutOfBoundsException: " + e.getmessage()); catch (IOException e) { System.err.println("Caught IOException: " + e.getmessage()); HVATANJE VIŠE TIPOVA IZNIMKI POMOĆU JEDNOG HANDLERA Java dozvoljava pisanje općenitih exception handlera koji obrađ uju više tipova iznimki. Java iznimke su Throwable objekti; oni su instance Throwable klase ili neke podklase Throwable klase. Brojne klase izvedene iz Throwable čine hijerarhiju Throwable klasa. Vaš exception handler može biti napisan tako da obrađ uje bilo koju klasu iznimki koja nasljeđuje Throwable. Ako napišete handler za "leaf" klasu (klasu koja nema podklase), napisali ste specijalizirani handler. Ako napišete handler za "node" klasu (klasu s podklasama), napisali ste općeniti handler. Promijenimo writelist metodu još jedan put, samo, ovaj put ju napišimo tako da obrađ uje i IOExceptions i ArrayIndexOutOfBoundsExceptions. Najbliži zajednič ki predak ovih klasa je Exception klasa, pa exception handler izgleda ovako: try {... catch (Exception e) { System.err.println("Exception caught: " + e.getmessage()); Klasa Exception nalazi se prilično visoko u hijerarhiji Throwable klasa. Pored IOException i ArrayIndexOutOfBoundsException tipova ovaj ć e exception handler hvatati i brojne druge tipove. Općenito govoreć i, vaši bi exception handleri trebali biti što je moguće više specijalizirani. Handleri koji hvataju većinu ili sve iznimke su najčešć e beskorisni za oporavak od pogreški, buduć i da handler ionako mora odrediti koji je tip iznimke nastupio kako bi odredio najbolju strategiju oporavka. 132

133 finally BLOK Konačni korak u postavljanju exception handlera je osiguranje mehanizma za čišć enje stanja metode prije dopuštanja prelaska kontrole toka na drugi dio programa. Ovo se č ini zatvaranjem cleanup koda unutar finally bloka. Blok try writelist metode otvara PrintWriter. Program bi trebao zatvoriti stream prije nego kontrola napusti writelist metodu. Ovo ponekad predstavlja problem budući da try blok writelist metode ima tri mogućnosti izlaska: 1. Iskaz new FileWriter je bacio IOException. 2. Iskaz victor.elementat(i) je bacio ArrayIndexOutOfBoundsException. 3. Sve je uspjelo i try blok je normalno završio. Runtime sistem uvijek izvršava iskaz unutar finally bloka neovisno o tome što se desi unutar try bloka. finally blok writerlist metode, čisti i zatvara PrintWriter: finally { if (out!= null) { System.out.println("Closing PrintWriter"); out.close(); else { System.out.println("PrintWriter not open"); DA LI JE finally ISKAZ ZBILJA POTREBAN? Isprva, potreba za finally iskazom možda nije odmah vidljiva. Programeri č esto pitaju "Da li je finally iskaz zbilja potreban ili je samo šeć er za moju Javu?" U biti, C++ programeri sumnjaju u potrebu finally iskaza buduć i da ga C++ ni nema. C++ programeri su bigtime looseri! Oč igledno ne znaju ni što im je potrebno, a što ne. Nadalje, kakav manijak može program doživljavati ovako intimno?! "Moja Java"?! Definitivno psihijatrijski slučaj! Potreba za finally iskazom nije očita dok ne promotrite sljedeće: kako će se PrintWriter u writelist metodi zatvoriti ako ne osigurate exception handler za ArrayIndexOutOfBoundsException i ta iznimka nastupi? Odgovor je da PrintWriter neće biti zatvoren ako ova iznimka nastupi, a writelist nema finally iskaz. Finally blok omogućuje smanjivanje umnožavanje koda: try {... out.close(); // don't do this; it duplicates code catch (ArrayIndexOutOfBoundsException e) { out.close(); // don't do this; it duplicates code System.err.println("Caught ArrayIndexOutOfBoundsException: " + e.getmessage()); catch (IOException e) { System.err.println("Caught IOException: " + e.getmessage()); 133

134 Dupliciranje koda, kad se koristi samo catch iskaz, čini kôd težim za č itanje i podložnijim pogreškama prilikom njegovih kasnijih izmjena. Na primjer, dodate li kôd try bloku koji može baciti novi tip iznimke, morate se sjetiti da trebate zatvoriti PrintWriter unutar novog exception handlera. SPAJANJE ISKAZA OBRADE IZNIMKI Prethodno poglavlje opisuje kako konstruirati try, catch i finally blokove koda za writelist primjer. Kada se sve ove komponente stave zajedno, writelist metoda izgleda ovako: public void writelist() { PrintWriter out = null; try { System.out.println("Entering try statement"); out = new PrintWriter( new FileWriter("OutFile.txt")); for (int i = 0; i < size; i++) out.println("value at: " + i + " = " + victor.elementat(i)); catch (ArrayIndexOutOfBoundsException e) { System.err.println("Caught ArrayIndexOutOfBoundsException: " + e.getmessage()); catch (IOException e) { System.err.println("Caught IOException: " + e.getmessage()); finally { if (out!= null) { System.out.println("Closing PrintWriter"); out.close(); else { System.out.println("PrintWriter not open"); Ovaj try blok ima tri mogućnosti izlaska. SCENARIO 1: NASTUPA IOException Iskaz new FileWriter("OutFile.txt") može pasti iz mnogo razloga: korisnik nema dozvolu pisanja nad datotekom ili direktorijem, datoteč ni sistem je pun ili direktorij datoteke ne postoji. Ako nastupi bilo koja od ovih situacija, konstruktor klase FileWriter bacit ć e IOException. Nakon što je bačen IOException, runtime sistem ć e zaustaviti izvršavanje try bloka i pokušati locirati exception handler koji može obraditi IOException. Potraga počinje na vrhu call stacka. Kad nastupi iznimka, konstruktor klase FileWriter je na vrhu call stacka. Međutim, konstruktor FileWritera nema prikladni exception handler, pa 134

135 runtime sistem provjerava sljedeću metodu u call stacku - metoda ima dva exception handlera. writelist metodu. writelist Runtime sistem provjerava handlere writelist metode redosljedom kojim su navedeni u nakon try iskaza. Argument prvog exception handlera je ArrayIndexOutOfBoundsException, ali bačena iznimka je IOException. Zato runtime sistem nastavlja s traženjem. Argument drugog exception handlera je IOException, što odgovara tipu iznimke bač ene u konstruktoru FileWritera i može se legalno dodijeliti njegovom argumentu. Stoga runtime sistem izvršava ovaj handler, koji ispisuje poruku na ekranu: Caught IOException: OutFile.txt Nakon što je exception handler izvršen, runtime sistem dodjeljuje kontrolu finally bloku. U ovom scenariju PrintWriter nikad nije otvoren, pa je out==null i neć e biti zatvoren. Nakon što finally blok završi, program će nastaviti s prvim iskazom nakon finally bloka. Kompletan izlaz iz ListOfNumbers programa kad nastupi IOException je ovo: Entering try statement Caught IOException: OutFile.txt PrintWriter not open SCENARIO 2: NASTUPA ArrayIndexOutOfBoundsException Ovaj scenario je isti kao i prvi osim što nastupa različita pogreška tijekom izvršavanja try bloka. U ovom scenariju, argument dodijeljen elementat metodi je van granica, tj. ili je manji od 0 ili je veći od veličine niza. Kad iznimka nastupi, runtime sistem prekida izvšravanje try bloka i pokušava locirati exception handler prikladan ArrayIndexOutOfBoundsException-u. Nakon što je pronađ en i izvršen odgovarajući exception handler, runtime sistem će proslijediti kontrolu finally bloku. U ovom scenariju, PrintWriter je otvoren, pa će ga finally iskaz zatvoriti. Nakon što finally blok završi s izvršavanjem, program će nastaviti s prvim iskazom nakon finally bloka. Kompletan izlaz programa kod ovog tipa iznimke bit će: Entering try statement Caught ArrayIndexOutOfBoundsException: 10 >= 10 Closing PrintWriter SCENARIO 3: try BLOK ZAVRŠAVA NORMALNO U ovom scenariju, svi iskazi unutar try bloka izvršavaju se uspješno i ne bacaju iznimke. Izvršavanje se nastavlja u finally bloku, koji zatvara PrintWriter. Nakon finally bloka program nastavlja s prvim iskazom koji mu slijedi. 135

136 Izlaz ovog programa kad ne nastupi iznimka je: Entering try statement Closing PrintWriter KAKO BACITI IZNIMKU? ISKAZ throw Sve Java metode koriste throw iskaze za bacanje iznimki. Iskaz throw zahtjeva jedan argument: throwable objekt. Throwable objekti u Javi su instance ili podklase Throwable klase. Ovo je primjer throw iskaza: throw somethrowableobject; Ako bacite objekt koji nije moguće baciti, kompajler ć e odbiti kompajliranje vašeg programa i prikazati poruku sličnu ovoj: testing.java:10: Cannot throw class java.lang.integer; it must be a subclass of class java.lang.throwable. throw new Integer(4); Pogledajmo iz bližega throw iskaz. Sljedeć a metoda je uzeta iz klase koja implementira stack. Metoda pop uklanja prvi element sa stacka i vraća ga: public Object pop() throws EmptyStackException { Object obj; if (size == 0) throw new EmptyStackException(); obj = objectat(size - 1); setobjectat(size - 1, null); size--; return obj; Ova metoda provjerava ima li elemenata na stacku. Ako je stack prazan, tada pop instancira novi EmptyStackException objekt i baca ga. Klasa EmptyStackException definirana je u java.util paketu. 136

137 KLASA Throwable I NJEZINE PODKLASE Kao što ste naučili, možete baciti samo objekte koji su izvedeni iz Throwable klase. Ovo uključuje direktne nasljednike (tj. objekte koji direktno nasljeđuju Throwable klasu) kao i indirektne nasljednike (objekti koji su izvedeni iz djece ili unučadi Throwable klase). Ovaj dijagram prikazuje hijerarhiju Throwable klase i njezine najbitnije podklase: Dva direktna nasljednika Throwable klase su Error i Exception. POGREŠKE (ERRORS) Prilikom pogreške kod dinamič kog linkanja ili neke "jake" pogreške unutar virtualnog stroja, virtualni stroj bacit će Error. Tipični Java programi ne bi trebali hvatati Error-e. IZNIMKE (EXCEPTIONS) Klasa Exception ima mnoge nasljednike. Ovi nasljednici indiciraju različ ite tipove iznimki. Jedna podklasa Exception klase ima specijalno znač enje u Java jeziku - to je RuntimeException. RUNTIME IZNIMKE Klasa RuntimeException predstavlja iznimke koje mogu nastupiti unutar Java virtualnog stroja (u runtimeu), npr. NullPointerException. Cijena provjere ovakvih pogreški č esto nadilazi prednosti njihovog hvatanja. Budući da je jako teško hvatati sve runtime iznimke, kompajler dopušta da prođu neuhvać ene i nenavedene. Paketi u Javi definiraju nekoliko RuntimeException klasa. Ove se iznimke mogu hvatati kao i bilo koje druge iznimke, međutim metoda ne treba navesti da baca RuntimeException. Moguće je kreirati i vlastite RuntimeException podklase. 137

138 KREIRANJE VLASTITIH IZNIMKI Prilikom dizajniranja paketa Java klasa koje međusobno surađuju znač ajno vrijeme biste trebali provesti i u projektiranju iznimki koje vaše klase mogu baciti. Pretpostavimo da pišete klasu koja sadrži povezanu listu i da tu klasu planirate distribuirati kao freeware. Pored ostalih metoda, vaša linked list klasa imat će ove metode: objectat(int n) - vraća objekt na n-toj poziciji u listi firstobject() - vraća prvi objekt u listi. indexof(object n) - pretražuje listu u potrazi za određenim Object elementom i vraća njegovu poziciju ŠTO MOŽE POĆI PO ZLU? Budućio da će mnogi programeri koristiti vašu klasu, možete biti sigurni da ć e ju mnogi pokušati koristiti na nepravilan način. Takođ er i sasvim legitimni pozivi metoda vaše povezane liste mogu rezultirati nedefiniranim rezultatima. S druge strane, vi želite da vaša klasa bude što robusnija i da s pogreškama čini nešto smisleno. Najbolji način da to uč inite je korištenjem iznimki. Svaka od metoda vaše povezane liste može baciti iznimku pod određenim uvjetima. Na primjer, objectat - Baca iznimku ako je indeks elementa manji od 0 ili već i od broja objekata u listi. firstobject - Baca iznimku ako lista ne sadrži objekte. indexof - Baca iznimku ako objekt prosljeđen metodi nije u listi. BIRANJE TIPA IZNIMKE ZA BACANJE Suočeni s izborom tipa iznimke koju želite baciti, imate dva izbora: 1. Koristiti iznimku koju je napisao netko drugi. 2. Napisati svoju vlastitu. U pisanje exception klasa trebali biste se upustiti ako odgovorite s "da" na bilo koje od sljedeć ih pitanja: Da li trebate tip iznimke koji nije predstavljen iznimkama danim u Java razvojnom okruženju? Da li bi korisnicima pomoglo ako trebaju razlikovati vašu iznimku od one koju bacaju klase drugih proizvođača? Da li vaš kôd baca biše od jedne povezane iznimke? Ako koristite tuđu iznimku, da li ć e korisnicima biti dostupna, tj. da li bi vaš paket trebao biti neovisan o drugim paketima? Vaša klasa može baciti višestruke iznimke i bilo bi prikladno sve iznimke bač ene u klasi uhvatiti jednim exception handlerom. Sljedeći dijagram prikazuje jednu moguću hijerarhiju klasa iznimki vaše povezane liste: 138

139 LinkedListException je roditeljska klasa svih moguć ih iznimki koje vaša klasa može baciti. Korisnici vaše klase mogu napisati jedan exception handler koji obrađuje sve vaše iznimke: catch (LinkedListException) {... ili napisati specijalizirane handlere za svaku podklasu klase LinkedListException. BIRANJE NADKLASE Gornji dijagram ne određuje nadklasu LinkedListException klase. Kao što znate, Java iznimke moraju biti instance ili nasljednici Throwable klase, pa možda poželite napraviti LinkedListException podklasom klase Throwable. Međutim, java.lang paket osigurava dvije njezine podklase koje dalje dijele tip problema koji može nastati u Java programu: Error i Exception. Većina appleta i aplikacija bacit će objekte koji su Exception tipa (Error je rezerviran za ozbiljne pogreške koje nastupaju duboko u sistemu). Teoretski, bilo koja podklasa klase Exception može se koristiti kao roditeljska klasa LinkedListException klase. Međutim, kratkim pregledom ovih klasa vidjet ć ete da su ili suviše specijalizirane ili u potpunosti nepovezane sa smislom LinkedListException klase. Stoga biste trebali napraviti LinkedListException tako da nasljeđuje Exception. Budući da runtime iznimke ne trebaju biti navedene u throws stavci metode, mnogi se programeri pitaju: "Nije li lakše ako sve svoje iznimke napravim tako da nasljeđ uju RuntimeException?". Ono što bi trebalo biti pravilo je da vaša klasa ne bi trebala naslijediti RuntimeException osim ako zbilja ne predstavlja runtime iznimku. DOGOVOR OKO IMENOVANJA Dobra je praksa dodati rije č "Exception" na kraj klasa koje nasljeđ uju (direktno ili indirektno) Exception klasu. Slično, klase koje nasljeđuju Error klasu trebale bi završavati rječ ju "Error". 139

140 NITI (THREADOVI) ŠTO JE THREAD? Svi su programeri upoznati s pisanjem sekvencijalnih programa, tj. programa kod kojih svaki ima poč etak, sekvencu instrukcija i kraj. U bilo koje doba tijekom izvršavanja programa postoji samo jedna linija koda koja se izvršava. Nit (thread) je slična prethodno opisanom sekvencijalnom programu. Jedan thread takođ er ima poč etak, sekvencu instrukcija, i kraj i u bilo koje vrijeme tijekom izvršavanja threada postoji samo jedno mjesto izvršavanja. Međ utim, sam thread nije program; on se ne može izvršavati samostalno. Umjesto toga, thread se pokreće unutar programa. Definicija: Thread predstavlja jedan sekvencijalni tok izvršavanja unutar programa. Ne postoji ništa novo u konceptu samo jednog threada. Nova je moguć nost istovremenog pokretanja više threadova (koji rade različite zadatke) unutar jednog programa. HotJava Web browser predstavlja primjer višenitne (multithreaded) aplikacije. Unutar tog browsera moguće je šetati po stranici dok se istovremeno dohvać a (downloada) neki applet ili slika, dok svira neka glazba, dok se vrti animacija ili dok se stranica ispisuje na pisaču. Buduć i da predstavlja sekvencijalni tok izvršavanja, thead mora imati svoje vlastite resurse (npr. stack izvršavanja ili programski broja č). Umjesto pojma thread, č esto se koristi i pojam execution context. 140

141 KORIŠTENJE Timer i TimerTask KLASA Ovdje je dan primjer korištenja timera za ponavljano izvršavanje nekog zadatka: import java.util.timer; import java.util.timertask; /** * Simple demo that uses java.util.timer to schedule a task to execute * once 5 seconds have passed. */ public class Reminder { Timer timer; public Reminder(int seconds) { timer = new Timer(); timer.schedule(new RemindTask(), seconds*1000); class RemindTask extends TimerTask { public void run() { System.out.println("Time's up!"); timer.cancel(); //Terminate the timer thread public static void main(string args[]) { System.out.println("About to schedule task."); new Reminder(5); System.out.println("Task scheduled."); Kad pokrenete primjer, prvo ćete vidjeti ovo: Task scheduled. Pet sekundi kasnije, vidjet ćete ovo: Time's up! Ovaj jednostavni program ilustrira osnovne korake implementacije i rasporeda izvršavanja zadataka pomoću timer threada. To su: Implementirajte svoju podklasu klase TimerTask. Metoda run treba sadržavati kôd koji izvršava neki zadatak. U ovom primjeru podklasa se zove RemindTask. Kreirajte thread instancirajući Timer klasu. Instancirajte objekt koji predstavlja zadatak za izvršavanje (new RemindTask()). Postavite timer zadatak za izvršavanje. Ovaj primjer koristi schedule metodu sa zadatkom kao prvim argumentom i vremenom č ekanja u milisekundama (5000) kao drugim argumentom. Drugi način upravljanja zadatkom je određ ivanje 141

142 vremena kad bi se zadatak trebao izvršiti. Na primjer, sljedeć i kôd izvršava zadatak u 11:01 p.m.: //Get the Date corresponding to 11:01:00 pm today. Calendar calendar = Calendar.getInstance(); calendar.set(calendar.hour_of_day, 23); calendar.set(calendar.minute, 1); calendar.set(calendar.second, 0); Date time = calendar.gettime(); timer = new Timer(); timer.schedule(new RemindTask(), time); ZAUSTAVLJANJE TIMER THREADA Ako drukčije ne navedete, program nastavlja izvođ enje sve dok se izvršavaju njegovi timer threadovi. Thread timer se može zaustaviti na četiri načina: Pozivom metode cancel nad timerom. Ovo možete uč initi iz bilo kojeg mjesta u programu, pa i iz timerove run metode. Napravite timer thread "demonom" (daemon) na ovaj način: new Timer(true). Ako u programu ostanu samo deamon threadovi, program će izaći. Nakon što svi zadaci završe, uništite sve reference na Timer objekt. Kao posljediva, thread od timera će se prekinuti. Pozovite metodu System.exit, koja ć e prekinuti izvršavanje programa (i njegovih threadova). Naš primjer koristi prvi način i poziva cancel metodu iz run metode. Označ avanje timer threada demonom ne bi radilo buduć i da program treba nastaviti s radom dok se zadatak izvršava. Ponekad, timer threadovi nisu jedini threadovi koji mogu onemogućiti program da izađ e onda kad se to očekuje. Na primjer, koristite li AWT, č ak i samo zato da biste odsvirali jedan beep, AWT automatski kreira ne-demon thread koji drži program živim. Sljedeć a promjena Reminder primjera dodaje beep, što povlači za sobom dodavanje poziva System.exit metode kako bi program završio.... public class ReminderBeep {... public ReminderBeep(int seconds) { toolkit = Toolkit.getDefaultToolkit(); timer = new Timer(); timer.schedule(new RemindTask(), seconds*1000); class RemindTask extends TimerTask { public void run() { System.out.println("Time's up!"); toolkit.beep(); //timer.cancel(); //Not necessary because we call System.exit System.exit(0); //Stops the AWT thread (and everything else) 142

143 ... PONAVLJANJE ZADATKA Ovdje je primjer kako korištenjem timera izvršiti neki zadatak jednom u sekundi. public class AnnoyingBeep { Toolkit toolkit; Timer timer; public AnnoyingBeep() { toolkit = Toolkit.getDefaultToolkit(); timer = new Timer(); timer.schedule(new RemindTask(), 0, //initial delay 1*1000); //subsequent rate class RemindTask extends TimerTask { int numwarningbeeps = 3; public void run() { if (numwarningbeeps > 0) { toolkit.beep(); System.out.println("Beep!"); numwarningbeeps--; else { toolkit.beep(); System.out.println("Time's up!"); //timer.cancel(); //Not necessary because we call System.exit everything else)... System.exit(0); Ovakav bi program izbacio sljedeći izlaz: //Stops the AWT thread (and Task scheduled. Beep! Beep! // jednu sekundu nakon prvog beepa Beep! // jednu sekundu nakon drugog beepa Time's up! // jednu sekundu nakon trećeg beepa Ovaj program koristi verziju schedule metode s tri argumenta kojom određ uje da bi se zadatak trebao izvršavati jednom u sekundi, poč evši odmah. Ovdje su sve Timer metode kojima možete pokrenuti ponavljajuće izvršavanje zadataka: schedule(timertask task, long delay, long period) schedule(timertask task, Date time, long period) scheduleatfixedrate(timertask task, long delay, long period) 143

144 scheduleatfixedrate(timertask task, Date firsttime, long period) Metode schedule koriste se kada je bitno glatko izvršavanje zadataka, a scheduleatfixedrate metode kad je bitnija sinkronizacija s vremenom. Prethodni primjer koristi schedule metodu, što znači da će se beepovi č uti s bar jednom sekundom razmaka. Ako jedan beep zakasni zbog nekog razloga, svi slijedeći beepovi će biti odgođ eni. Ako odlučimo da bi ovaj program trebao izaći za točno tri sekunde nakon prvog beepa, č ak iako bi to značilo da dva beepa mogu nastupiti u krać em razmaku (zbog bilo kojeg razloga) - trebamo koristiti scheduleatfixedrate metodu. VIŠE INFORMACIJA O TIMERIMA Opisani primjeri su vrlo jednostavni, tj č ine vrlo malo i rade samo s podacima kojima se sigurno pristupa iz više threadova ili su privatni tom threadu. Dok god vaš timer task koristi samo thread-safe API - kao što su metode u Timer klasi, implementiranje Timera je relativno jednostavno, Međ utim, ako vaša timer implementacija koristi dijeljene resurse, kao što su podaci na drugom mjestu u programu, trebate biti oprezni. O ovom ćete nauč iti više u poglavlju Sinkronizacija threadova. PODEŠAVANJE METODE run Thread klase Metoda run određuje što će thread raditi. Njezin kôd implementira ponašanje threada. Klasa Thread implementira generički thread, koji ne radi ništa, tj. implementacija run metode je prazna. Budući da ovo i nije previše korisno, Thread klasa definira API koji dopušta Runnable objektima mnogo interesantniju run metodu. Postoje dvije metode kako napisati run metodu threada: Nasljeđivanje Thread klase i prepisivanje run metode Implementiranje Runnable interfacea NASLJEĐIVANJE Thread KLASE Prvi način na koji možete odrediti što će thread raditi je napraviti klasu koja nasljeđuje Thread klasu (ona je sama Runnable objekt) i prepisati run metodu tako da nešto i čini. Na primjer: public class SimpleThread extends Thread { public SimpleThread(String str) { super(str); 144

145 public void run() { for (int i = 0; i < 10; i++) { System.out.println(i + " " + getname()); try { sleep((long)(math.random() * 1000)); catch (InterruptedException e) { System.out.println("DONE! " + getname()); Prva metoda u SimpleThread klasi je konstruktor koji uzima String kao svoj jedini argument. Ovaj konstruktor je implementiran tako da zove konstruktor svoje nadklase i jedino je interesantan zbog toga što postavlja ime threada. Sljedeća metoda u SimpleThread klasi je run metoda. Metoda run je srce svakog threada i mjesto na kojem je definirana akcija koju izvršava thread. Metoda run SimpleThread klase sadrži for petlju i iterira deset puta. U svakoj iteraciji metoda prikazuje broj iteracije i ime threada, zatim spava sluč ajan broj milisekundi (maksimalno 1000). Nakon što petlja završi, izspisuje DONE! zajedno s imenom threada. Neka druga klasa TwoThreadsDemo ima main metodu koja kreira dva SimpleThread threada: jednog s imenom "Jamaica" i drugog s imenom "Fiji". public class TwoThreadsDemo { public static void main (String[] args) { new SimpleThread("Jamaica").start(); new SimpleThread("Fiji").start(); U main metodi se threadovi i pokreću odmah po kreiranju korištenjem Izlaz iz programa bit će sličan ovom: 0 Jamaica 0 Fiji 1 Fiji 1 Jamaica 2 Jamaica 2 Fiji 3 Fiji 3 Jamaica 4 Jamaica 4 Fiji 5 Jamaica 5 Fiji 6 Fiji 6 Jamaica 7 Jamaica 7 Fiji 8 Fiji 9 Fiji 8 Jamaica DONE! Fiji 9 Jamaica DONE! Jamaica start metode. 145

146 Primjetite kako se izlaz svakog threada ispreplić e s izlazom iz drugog. To je zato što se oba threada izvršavaju istovremeno. Sada pogledajmo drugi primjer, applet Clock, koji koristi druge tehnike za određivanje metode Threada. run IMPLEMENTIRANJE Runnable INTERFACEA Applet Clock prikazuje trenutno vrijeme i osvježava prikaz svake sekunde. Kôd koji osvježava prikaz sata pokrenut je u svom vlastitom threadu. Applet Clock koristi drugu tehniku za određivanje run metode svog threada. Umjesto nasljeđivanja Thread klase, Clock implementira Runnable interface (i stoga implementira run metodu tog interfacea). Clock zatim kreira thread i daje sebe samog kao argument Thread konstruktora. Na ovaj način, Thread dobija run metodu objekta koji mu je proslijeđ en konstruktoru. import java.awt.graphics; import java.util.*; import java.text.dateformat; import java.applet.applet; public class Clock extends Applet implements Runnable { private Thread clockthread = null; public void start() { if (clockthread == null) { clockthread = new Thread(this, "Clock"); clockthread.start(); public void run() { Thread mythread = Thread.currentThread(); while (clockthread == mythread) { repaint(); try { Thread.sleep(1000); catch (InterruptedException e){ // the VM doesn't want us to sleep anymore, // so get back to work public void paint(graphics g) { // get the time and convert it to a date Calendar cal = Calendar.getInstance(); Date date = cal.gettime(); // format it and display it DateFormat dateformatter = DateFormat.getTimeInstance(); g.drawstring(dateformatter.format(date), 5, 10); // overrides Applet's stop method, not Thread's public void stop() { clockthread = null; 146

147 Metoda run vrti se dok browser ne zatraži prekid. U svakoj iteraciji petlje, sat se ispisuje. Metoda paint određuje koje je vrijeme, formatira vrijeme na način određ en sistemom i prikazuje ga. ODLUKA O KORIŠTENJU Runnable INTERFACEA Sad kad ste vidjeli ova dva načina za pisanje run metode Java threada, postavlja se pitanje kada koristiti jedan, a kada drugi nač in? Postoje dobri razlozi za odabir prvog, kao i za odabir drugog, međutim, za većinu slučajeva, uključujući Clock applet, neka vas vodi ovo pravilo: Pravilo: Ako vaša klasa mora biti podklasa neke druge klase (npr. podklasa Applet-a), treba implementirati Runnable interface. Kako bi se pokrenula u Java browseru, Clock klasa mora biti podklasa Applet klase. Pored toga, Clock applet treba thread kako bi kontinuirano osvježavao svoj prikaz bez da smeta procesu unutar kojeg je pokrenut. Budući da java ne podržava višestruko nasljeđivanje, Clock klasa ne može biti podklasa i Thread i Applet klase. Stoga Clock klasa mora koristiti Runnable interface. ŽIVOTNI VIJEK THREADA Sljedeći dijagram prikazuje stanja Java threada unutar njegovog života. Slika takođ er ilustrira metode koje se uzrokuju prijelaz u drugo stanje, Ova slika nije potpun dijagram konač nog stanja, ve ć pregled najinteresantnijih dijelova života threada. KREIRANJE THREADA Aplikacija unutar koje se pokreće applet zove posjeti stranicu s appletom. start metodu appleta u trenutku kad korisnik public void start() { if (clockthread == null) { clockthread = new Thread(this, "Clock"); clockthread.start(); Nakon što se izvrši podebljani iskaz, clockthread prelazi u New Thread stanje. Kad je thread u ovom stanju, predstavlja gotovo prazan Thread objekt; nema sistemskih resursa koji su za 147

148 njega alocirani. Dok je thread u ovom stanju, jedino što možete uč initi je pokrenuti thread. Poziv bilo koje metode osim start metode bacit će IllegalThreadStateException. Prvi argument thread konstruktora mora implementirati Runnable interface i osigurati run metodu threadu. Drugi argument je ime threada. POKRETANJE THREADA Sada promotrite sljedeću liniju koda: public void start() { if (clockthread == null) { clockthread = new Thread(this, "Clock"); clockthread.start(); Metoda start kreira sistemske resurse potrebne za izvršavanje threada i poziva run metodu threada. Nakon što start metoda završi, thread je pokrenut. U biti, situacija je malo složenija. Thread koji je pokrenut je u Runnable stanju. Mnoga računala imaju jedan procesor, što č ini nemoguć im "istovremeno" izvršavanje threadova. Java runtime sistem zato implementira raspored po kojem se procesor dijeli između svih aktivnih threadova. Drugim riječ ima, aktivni thread u određenim trenucima nije aktivan i čeka na svoj red na CPU. Pogledajmo još jednom run metodu klase Clock: public void run() { Thread mythread = Thread.currentThread(); while (clockthread == mythread) { repaint(); try { Thread.sleep(1000); catch (InterruptedException e){ // the VM doesn't want us to sleep anymore, // so get back to work Metoda run vrti se dok je uvjet clockthread == mythread istinit. Ovaj uvjet je detaljnije objašnjen u poglavlju o zaustavljanju threada. Unutar petlje, applet se iscrtava i zatim upada u sleep stanje za vrijeme jedne sekunde (1000 milisekundi). Metoda repaint bezuvjetno poziva paint metodu, koja osvježava zonu appleta. Metoda paint uzima trenutno vrijeme, formatira ga i prikazuje: public void paint(graphics g) { // get the time and convert it to a date Calendar cal = Calendar.getInstance(); Date date = cal.gettime(); // format it and display it DateFormat dateformatter = DateFormat.getTimeInstance(); 148

149 g.drawstring(dateformatter.format(date), 5, 10); PRIVREMENO ZAUSTAVLAJNJE THREADA Thread se privremeno zaustavlja (Not Runnable stanje na slici) kad nastupi jedna od sljedeć ih situacija: Pozvana je sleep metoda. Thread je pozvao wait metodu kako bi pričekao da se nešto dogodi. Thread je blokiran na Ulazno/Izlaznoj funkciji. ClockThread u Clock appletu privremeno se zaustavlja kada metoda pozove sleep: public void run() { Thread mythread = Thread.currentThread(); while (clockthread == mythread) { repaint(); try { Thread.sleep(1000); catch (InterruptedException e){ // the VM doesn't want us to sleep anymore, // so get back to work Tijekom sekunde za vrijeme koje clockthread spava, thead ne troši procesorsko vrijeme. Nakon što protekne sekunda, thread ponovo postaje aktivan (Runnable na slici), i, kad procesor postane dostupan, počinje s izvršavanjem. Za svaki ulaz u Not Runnable stanje postoji određeni i različit put koji vrać a thread u Runnable stanje. Na primjer, ako je thread stavljen u stanje spavanja, tada treba proći određ eni broj milisekundi prije nego ponovo postane Runnable. Ovdje su navedeni svi nač ini izlaska iz Not Runnable stanja: Ako thread upadne u stanje spavanja, mora proći određeni broj milisekundi. Ako thread čeka na uvjet, tada drugi objekt mora obavijestiti thread koji č eka da je nastupila promjena (pozivom notify ili notifyall). Ako je thread blokiran ulazno/izlaznom operacijom, tada ta operacija mora završiti. ZAUSTAVLJANJE THREADA Thread se ne zaustavlja kao i applet (pozivom metode). Umjesto toga, thread prestaje s radom kada završi njegova run metoda. Na primjer, while petlja u ovoj run metodi je konač na petlja koja će nakon stote iteracije završiti: public void run() { int i = 0; while (i < 100) { i++; System.out.println("i = " + i); 149

150 Thread umire prirodno kada petlja završi i kada tok izvršavanja izađe iz run metode. Pogledajmo kako Clock applet upravlja svojom smrć u. Ovu tehniku možete koristiti i u svojim appletima: public void run() { Thread mythread = Thread.currentThread(); while (clockthread == mythread) { repaint(); try { Thread.sleep(1000); catch (InterruptedException e){ // the VM doesn't want us to sleep anymore, // so get back to work Izlazno stanje run metode je izlazno stanje while petlje buduć i da poslje ove petlje nema više koda: while (clockthread == mythread) { Ovo stanje označava da će petlja izaći kad trenutni thread ne bude jednak clockthread-u. Kada će se to desiti? Kad napustite stranicu, aplikacija u kojoj se applet pokrenuo poziva njegovu stop metodu. Ova metoda postavlja clockthread na null, tako označavajući da želi da glavna petlja u run metodi završi s radom: public void stop() { clockthread = null; // applets' stop method Ako ponovo posjetite stranicu, start metoda će se pozvati ponovo i sat ć e se pokrenuti ponovo u novom threadu. METODA isalive API za Thread klasu uključuje i metodu s imenom isalive. Ova metoda vraća true ako je thread pokrenut i ako nije zaustavljen. Ako isalive metoda vrati false, tada znate da je thread ili u New Thread stanju ili je Dead (mrtav). Nije moguć e razlikovati ova dva stanja, kao što nije moguće razlikovati niti Runnable i Not Runnable stanje. PRIORITET THREADOVA 150

151 U prethodnom smo poglavlju tvrdili da se threadovi izvršavaju istovremeno. Dok je konceptualno ovo istina, u praksi obično nije. Već ina kompjuterskih konfiguracija ima jedan CPU, pa se threadovi izvršavaju jedan po jedan na takav nač in da dobijamo iluziju istovremenosti. Izvršavanje više threadova na jednom CPU-u, u određ enom redosljedu, zove se scheduling (raspoređivanje). Java podržava vrlo jednostavan, deterministič ki scheduling algoritam poznat kao fixed priority scheduling. Ovaj algoritam raspoređ uje threadove ovisno o njihovom relativnom prioritetu. Kad se kreira Java thread, on nasljeđ uje prioritet threada koji ga je kreirao. Prioritet threada se može izmijeniti nakon što je kreiran uz pomo ć metode setpriority. Prioriteti threada su cijeli brojevi od MIN_PRIORITY do MAX_PRIORITY (konstante definirane u Thread klasi). Što je veći broj, to je veći i prioritet. U bilo koje vrijeme, kad više threadova č eka na izvršenje, runtime sistem ć e izabrati aktivni thread s najvišim prioritetom. Samo kad se taj thread zaustavi ili postane neaktivan zbog nekog razloga, počet ć e se izvršavati threada nižeg prioriteta. Ako na izvršavanje čeka više threadova istog prioriteta, izabrat će se neki po round-robin principu. Izabrani thread će nastaviti s izvršavanjem dok se ne zadovolji jedan od uvjeta: Thread višeg prioriteta postane aktivan. run metoda završi. Na sistemima koji podržavaju dijeljenje vremena, ako istekne threadov vremenski odsječak. Nakon toga se kontrola predaje drugom threadu itd. Scheduling algoritam Java runtime sistema je također i preventivan ( preemptive). Ako se u bilo koje vrijeme pokrene thread takvog prioriteta da je već i od prioriteta trenutno aktivnih threadova, runtime sistem će prijeć i s izvršavanjem na ovaj thread. Za taj novi thread se kaže da blokira (preempt) druge threadove. Pravilo: U bilo kojem vremenu, izvršava se thread samo najvećeg prioriteta. Međ utim, thread scheduler može za izvršavanje izabrati i thread nižeg prioriteta kako bi izbjegao gladovanje (starvation). Zbog ovog razloga, koristite prioritete samo radi razloga upravljanja efikasnošć u threadova. Nemojte se na prioritete osloniti za korektno izvršavanje algoritama. UTRKA THREADOVA Thread s ovakvom run metodom se zove sebič ni thread: public int tick = 1; public void run() { while (tick < ) tick++; While petlja u ovoj metodi je takva da kad jednom scheduler odabere ovaj thread za izvršavanje, thread nikad neć e dobrovoljno prepustiti kontrolu CPU-a drugom threadu, tj. thread će se nastaviti dok se while petlja ne prekine prirodno ili dok thread ne bude nadvladan drugim threadom višeg prioriteta. U nekim situacijama, postojanje sebičnih threadova ne uzrokuje nikakve probleme buduć i da threadovi višeg prioriteta nadvladavaju threadove sebičnih. Međ utim, u drugim situacijama, threadovi s CPU pohlepnim run metodama, mogu prouzročiti da drugi threadovi č ekaju dugo vremena prije nego dobiju šansu za utrku. 151

152 DIJELJENJE VREMENA Neki se sistemi, kao što su Windows 95/NT, bore protiv sebič nih threadova strategijom poznatom kao dijeljenje vremena (time-slicing). Time-slicing nastupa kada postoje dva ili više aktivnih threadova jednakog (i ujedno trenutno najvišeg) prioriteta, na primjer dva threada s ovakvom run metodom: public void run() { while (tick < ) { tick++; if ((tick % 50000) == 0) System.out.println("Thread #" + num + ", tick = " + tick); Ova metoda sadrži petlju koja uvećava cijeli broj threada i broj tickova. tick i svakih tickova ispisuje ID Kad pokrenete ovakav program na time-sliced sistemu, vidjet ć ete kako se poruke oba threada isprepliću: Thread #1, tick = Thread #0, tick = Thread #0, tick = Thread #1, tick = Thread #1, tick = Thread #1, tick = Thread #0, tick = Thread #0, tick = Thread #1, tick = Thread #0, tick = Thread #0, tick = Thread #1, tick = Thread #1, tick = Thread #0, tick = Thread #0, tick = Thread #1, tick = Ovaj izlaz je takav budući da sistemi s dijeljenjem vremena dijele CPU na vremenske odsječ ke i iterativno ih dodjeljuju svakom od threadova s jednakim i najvišim prioritetom. Ovakav sistem dozvoljava svakom od ovih threadova jedan vremenski odsječ ak u kojem bivaju pokrenuti, sve dok jedan od threadova ne završi s radom ili dok ih ne prekine drugi thread višeg prioriteta. Primjetite da dijeljenje vremena ne garantira koliko često i u kojem redosljedu ć e threadovi biti pokrenuti. Kad se program pokrene na sistemu koji nema dijeljenje vremena, prvo ć ete vidjeti poruke jednog threada, pa za njima porkue drugog: Thread #0, tick = Thread #0, tick = Thread #0, tick = Thread #0, tick = Thread #0, tick =

153 Thread #0, tick = Thread #0, tick = Thread #0, tick = Thread #1, tick = Thread #1, tick = Thread #1, tick = Thread #1, tick = Thread #1, tick = Thread #1, tick = Thread #1, tick = Thread #1, tick = Ovo je zato što na sistemima koji ne dijele vrijeme sistem bira jedan od threadova s jednakim i najvišim prioritetom i dozvoljava mu izvršavanje dok ne napusti CPU (ili zaspe ili završi posao) ili dok ga ne nadvlada drugi thread višeg prioriteta. Primjetite: Java ne implementira (i stoga ne garantira) dijeljenje vremena. Međ utim, neki sistemi na kojima možete pokrenuti Java programe, ga podržavaju. Zato se vaši programi ne bi trebali osloniti na dijeljenje vremena jer to može prouzročiti različite rezultate na različ itim sistemima. Kao što zamišljate, pisanje CPU-intenzivnog koda može imati negativne posljedice na druge threadove pokrenute u istom procesu. Opć enito, trebali biste pisati threadove koji se "lijepo ponašaju" i dobrovoljno periodič no predaju CPU drugim threadovima. U praksi se nikad ne biste trebali oslanjati na dijeljenje vremena. Thread može dobrovoljno prepustiti CPU bez da ode u mod spavanja i bez da poduzima neke druge drastične mjere, korištenjem yield metode. Ova metoda daje drugim threadovima istog prioriteta priliku da rade. Ako ne postoji aktivni thread istog prioriteta, tada se yield ignorira. SINKRONIZIRANJE THREADOVA Postoje mnoge interesantne situacije kod kojih odvojeni, istovremeno aktivni threadovi dijele podatke i pri tom moraju uzeti u obzir stanje i aktivnosti drugih threadova. Jedan skup programskih situacija koje su poznate kao proizvođa č/potroša č gdje proizvođa č generira tok podataka kojeg konzumira potroša č. Na primjer, nek jedan thread (proizvođa č ) upisuje podatke u datoteku, dok drugi thread (potroša č) č ita podatke iz iste datoteke. Ili, dok upisujete znakove preko tipkovnice, thread proizvođa č stavlja događaje pritiska tipki u red događaja, a potrošački thread čita događ aje iz istog reda. Oba od ovih primjera koriste istovremene threadove koji dijele zajednič ki resurs: prvi dijeli datoteku, drugi dijeli red događaja. Buduć i da dijele isti resurs, moraju se nekako sinkronizirati. PRIMJER PROIZVOĐAČ/POTROŠAČ 153

154 Proizvođa č generira cijeli broj između 0 i 9 (uključivo), sprema ga u CubbyHole objekt i ispisuje generirani broj. Kako bi sinkronizacijski problem bio interesantniji, proizvođa č spava slučajan broj milisekundi (između 0 i 100) prije ponavljanja petlje koja generira brojeve: public class Producer extends Thread { private CubbyHole cubbyhole; private int number; public Producer(CubbyHole c, int number) { cubbyhole = c; this.number = number; public void run() { for (int i = 0; i < 10; i++) { cubbyhole.put(i); System.out.println("Producer #" + this.number + " put: " + i); try { sleep((int)(math.random() * 100)); catch (InterruptedException e) { Potroša č konzumira sve cijele brojeve iz public class Consumer extends Thread { private CubbyHole cubbyhole; private int number; CubbyHole objekta što brže može. public Consumer(CubbyHole c, int number) { cubbyhole = c; this.number = number; public void run() { int value = 0; for (int i = 0; i < 10; i++) { value = cubbyhole.get(); System.out.println("Consumer #" + this.number + " got: " + value); Producer i Consumer u ovom primjeru dijele podatke preko zajedničkog CubbyHole objekta. Primjetit ćete da ni Producer ni Consumer ne čine ništa kako bi osigurali da Consumer dobija svaku proizvedenu vrijednost jednom i samo jednom. Sinkronizacija ovih dvaju threadova nastupa na nižoj razini unutar get i put metoda CubbyHole objekta. Pretpostavimo za trenutak da ova dva threada ne č ine ništa radi sinkronizacije i pogledajmo potencijalne probleme koji mogu nastati u toj situaciji. Jedan problem koji se nameće je kada je Producer brži od Consumer-a, pa generira dva broja prije nego Consumer ima šansu konzumirati prvog. Stoga će Consumer preskoč iti broj, pa bi izlaz u takvom slučaju bio: Consumer #1 got: 3 Producer #1 put: 4 154

155 Producer #1 put: 5 Consumer #1 got: 5 Drugi problem koji se može pojaviti je kada je Consumer brži od Producer-a i troši istu vrijednost dvaput. U ovakvoj situaciji, Consumer bi ispisivao istu vrijednost dvaput i možda bi proizveo ovakav izlaz:... Producer #1 put: 4 Consumer #1 got: 4 Consumer #1 got: 4 Producer #1 put: 5... U oba je slučaja rezultat netočan. Ono što želite je da Consumer dobije svaki broj kojeg proizvede Producer točno jedan put. Problemi kao ovi najčešće se zovu uvjeti utrke ( race conditions). Oni izlaze iz vešestrukih, asinkrono izvođ enih threadova koji pokušavaju pristupiti istom objektu u isto vrijeme, a dobijaju krivi rezultat. Uvjeti utrke u proizvođa č/potroša č primjeru sprečavaju se tako što se proizvođač evo spremanje novog cijelog broja u CubbyHole sinkronizira s potrošačevim uzimanjem broja iz CubbyHole objekta. Potroša č mora trošiti svaki cijeli broj točno jedan put. Aktivnosti Producer i Consumer objekata moraju biti sinkronizirane na dva nač ina. Prvo, dva threada ne smiju simultano pristupati CubbyHole objektu. U Javi se to čini zaključ avanjem objekta. Kad je objekt zaključ an, bilo koji thread koji pokuša pozvati sinkroniziranu metodu tog objekta bit će blokiran dok se objekt ne otključa. I drugo, dva threada moraju izvesti jednostavno koordiniranje. To znači, Producer mora na neki način javiti Consumer-u da je vrijednost spremna, a Consumer mora na neki nač in obavijestiti Producera da je uzeo vrijednost. Thread klasa osigurava kolekcijom metoda - wait, notify i notifyall pomo ć pri čekanju threadova na određ eno stanje i njihovom obavještavanju kada se stanje promijeni. GLAVNI PROGRAM Evo i male samostalne Java aplikacije koja kreira CubbyHole objekt, proizvođača ( Producer) i potrošača ( Consumer), i zatim pokreće Producer-a i Consumer-a. public class ProducerConsumerTest { public static void main(string[] args) { CubbyHole c = new CubbyHole(); Producer p1 = new Producer(c, 1); Consumer c1 = new Consumer(c, 1); p1.start(); c1.start(); 155

156 IZLAZ Ovdje je izlaz ProducerConsumerTest aplikacije: Producer #1 put: 0 Consumer #1 got: 0 Producer #1 put: 1 Consumer #1 got: 1 Producer #1 put: 2 Consumer #1 got: 2 Producer #1 put: 3 Consumer #1 got: 3 Producer #1 put: 4 Consumer #1 got: 4 Producer #1 put: 5 Consumer #1 got: 5 Producer #1 put: 6 Consumer #1 got: 6 Producer #1 put: 7 Consumer #1 got: 7 Producer #1 put: 8 Consumer #1 got: 8 Producer #1 put: 9 Consumer #1 got: 9 ZAKLJUČAVANJE OBJEKTA Segmenti koda unutar programa koji pristupaju istom objektu iz različ itih threadova zovu se kritični odsječci ( critical sections). U Javi, critical section može biti blok koda ili metoda, a označava se ključnom riječi synchronized. Java platforma tako zna kojem objektu treba pridružiti bravu (lock). U primjeru proizvođa č/potroša č, put i get metode CubbyHole objekta su kritični odsječ ci. Consumer ne bi trebao pristupiti CubbbyHole-u dok ga mijenja Producer, niti bi ga Producer trebao mijenjati dok Consumer dohvaća vrijednost. Stoga put i get metode u CubbyHole klasi trebaju biti označene ključnom rječju synchronized. Ovdje je kostur koda CubbyHole klase: public class CubbyHole { private int contents; private boolean available = false; public synchronized int get() {... public synchronized void put(int value) {... Sistem pridružuje jedinstvenu bravu svakoj instanci CubbyHole objekta. Kad god kontrola uđ e u sinkroniziranu metodu, thread koji je pozvao metodu zaključava objekt č ija je metoda 156

157 pozvana. Drugi threadovi koji pozovu neku sinkroniziranu metodu istog objekta upadaju u stanje čekanja dok se objekt ne otključa. Stoga, kad Producer pozove put metodu objekta CubbyHole, on zaključava CubbyHole, tako da za vrijeme izvršavanja put metode Consumer ne može pozvati get metodu istog objekta: public synchronized void put(int value) { // CubbyHole locked by the Producer.. // CubbyHole unlocked by the Producer Kad program izađe iz put metode, Producer otključava CubbyHole. Slično, kad Consumer pozove get metodu, zaključava Producer-a u pozivanju put metode: CubbyHole i tako spreč ava public synchronized int get() { // CubbyHole locked by the Consumer... // CubbyHole unlocked by the Consumer Zaključavanje i otključ avanje brave je automatsko i atomizirano (ne može biti prekinuto nekim drugim threadom). Ovako se objekti osiguravaju od uvjeta utrke, tj. osigurava se integritet podataka. PONOVNO ZAKLJUČAVANJE Java dozvoljava threadu zaključavanje ve ć zaključane brave (tzv. reentrant locks). Ovakvo zaključavanje je bitno budući da eliminira mogućnost da thread zaključa samog sebe. Pretpostavite ovakvu klasu: public class Reentrant { public synchronized void a() { b(); System.out.println("here I am, in a()"); public synchronized void b() { System.out.println("here I am, in b()"); Reentrant sadrži dvije sinkronizirane metode: a i b. Prva sinkronizirana metoda - a zove drugu sinkroniziranu metodu - b. Kada kontrola uđe u metodu a, trenutni thread podiže bravu Reentrant objekta. Sada, a zove b i budući da je b također sinkronizirana metoda, thread pokušava ponovo podić i istu bravu. Budući da Java podržava reentrant lockove, ovo radi. Izlaz ovog programa je zato: here I am, in b() here I am, in a() 157

158 U sistemima koji ne podržavaju reentrant zaključavanje, ova bi sekvenca metoda prouzroč ila deadlock. UPOTREBA METODA notifyall i wait CubbyHole sprema svoju vrijednost u privatnoj varijabli članu zvanoj contents. CubbyHole ima drugu privatnu varijablu člana, available, koja je boolean. Ova je varijabla true kada je vrijednost stavljena, ali još nije dohvaćena, a false kad je vrijednost uzeta, ali još nije stavljena slijedeća. Evo jedna moguća implementacija put i get metoda: public synchronized int get() { // won't work! if (available == true) { available = false; return contents; public synchronized void put(int value) { // won't work! if (available == false) { available = true; contents = value; Ovako implementirane, ove metode neće raditi! Pogledajte get metodu. Što ć e se dogoditi ako Producer nije još stavio ništa u CubbyHole, a available je false? get neće uč initi ništa. Slično, ako Producer pozove put prije nego je Consumer uzeo vrijednost, put neće uč initi ništa. Ono što zbilja želite je da Consumer čeka dok Producer ne stavi nešto u CubbyHole, a Producer mora obavijestiti Consumer-a kad je to učinio. Slično, Producer mora č ekati dok Consumer uzme vrijednost prije nego ju zamijeni novom. Dva threada moraju se bolje koordinirati, pa zato mogu koristiti wait i notifyall metode klase Object. Ovdje je nova implementacija get i put metoda koje č ekaju obavijesti i obavještavaju jedna drugu o svojim aktivnostima. public synchronized int get() { while (available == false) { try { // wait for Producer to put value wait(); catch (InterruptedException e) { available = false; // notify Producer that value has been retrieved notifyall(); return contents; public synchronized void put(int value) { while (available == true) { try { // wait for Consumer to get value wait(); 158

159 catch (InterruptedException e) { contents = value; available = true; // notify Consumer that value has been set notifyall(); Kôd u get metodi vrti se dok Producer ne proizvede novu vrijednost. Svaki put kroz prolazak petlje, get poziva wait metodu. Metoda wait oslobađa lock kojeg je držao Consumer na CubbyHole objektu (tako dozvoljava Producer-u da uzme lock i ubaci novu vrijednost u CubbyHole) i zatim čeka na obavijest od Producer-a. Kada Producer stavi nešto u CubbyHole, obavještava Consumer-a pozivom metode notifyall. Tada Consumer izlazi iz stanja čekanja, available postaje true, petlja izlazi i get metoda vrać a vrijednost u CubbyHole. Metoda put radi na sličan način, čeka Consumer thread da uzme trenutnu vrijednost prije nego što dozvoli Producer-u da proizvede novu. Metoda notifyall budi sve threadove koji čekaju na određeni objekt (u ovom sluč aju CubbyHole). Probuđeni threadovi natječ u se za bravu. Jedan ju thread dobija, a ostali se vraćaju na čekanje. Klasa Object također definira notify metodu, koja slobodno budi jedan od threadova koji čekaju ovaj objekt. Klasa Object ne sadrži samo wait u obliku kakvom je upotrebljena u našem primjeru, ve ć i još dvije wait metode: wait(long timeout) - koja čeka na obavijest, a izlazi i u slučaju kad prođ e timeout period (zadan u milisekundama). wait(long timeout, int nanos) - čeka na notifikaciju, a izlazi i u sluč aju da prođe timeout milisekundi plus nanos nanosekundi. IZBJEGAVANJE IZGLADNJIVANJA I DEADLOCKA Filozofi za večerom čest su primjer koji se koristi za ilustriranje različ itih problema koji mogu nastupiti kad se više sinkroniziranih threadova natječe za ograničene resurse. Prič a ide ovako: Pet filozofa sjede za okruglim stolom. Ispred svakog od filozofa nalazi se zdjela riže. Između svakog para filozofa nalazi se jedan štapi ć. Prije nego filozof može uzeti zalogaj riže mora uzeti dva štapić a - jedan sa svoje lijeve i drugi sa svoje desne strane. Filozofi moraju pronaći neki način dijeljenja štapić a tako da svi jedu. Stanje koje se zove deadlock nastupa kada svaki od filozofa uzme svoj lijevi štapi ć i čeka na to bude spušten njemu desni. Najbolji izbor u programima je onemogućiti deadlock umjesto da to č inite metodom pokušaj/pogreška. Detekcija deadlocka je komplicirana i izlazi van okvira ovog teksta. Najjednsotavniji pristup u izbjegavanju deadlocka je uključivanje redosljeda pomoć u uvjetnih varijabli. Npr. u problemu gladnih filozofa, možemo primijeniti pravilo numeriranjem štapić a od 1 do 5 i inzistiranjem da filozofi uzmu prvo štapić e s nižim brojem. Filozof koji se nalazi između štapića 1 i 2 i filozof koji sjedi između štapića 1 i 5 moraju uzeti prvo štapi ć broj 1. Onaj 159

160 koji ga uzme prije, slobodno može uzeti drugoga. Tko god ne dobije štapi ć 1 mora č ekati na prvog filozofa da ga spusti. Deadlock tako nije mogu ć. GRUPIRANJE THREADOVA Svaki Java thread je č lan grupe threadova. Grupe threadova osiguravaju mehanizam prikupljanja više threadova u jedan objekt i manipuliranje tim threadovima odjednom. Na primjer, možete pokrenuti ili zaustaviti sve threadove unutar grupe pozivom samo jedne metode. Grupe threadova u Javi implementirane su ThreadGroup klasom iz java.lang paketa. Runtime sistem stavlja thread u grupu tijekom konstruiranja threada. Kad kreirate thread, možete ili dopustiti runtime sistemu da stavi novi thead u neku podrazumijevanu grupu ili eksplicitno odrediti novu grupu. Nakon kreiranja, thread postaje stalni č lan grupe - nije ga više moguće premjestiti u drugu grupu. PODRAZUMIJEVANA GRUPA THREADOVA Ako kreirate novi thread bez da odredite njegovu grupu u konstruktoru, runtime sistem ć e automatski staviti novi thread u istu grupu u kojoj se nalazi i thread koji kreira novi thread. Prilikom pokretanja aplikacije, Java sistem kreira ThreadGroup imena main. Dok drukč ije ne odredite, svi će novi threadovi biti č lanovi main grupe. Mnogi programeri ignoriraju grupe threadova. One su potrebne samo kad radite s velikim brojem threadova, a trebate nač in na koji ćete ih jednostavno kontrolirati. 160

161 I/O: ČITANJE I PISANJE Vrlo često program treba uč itati informacije iz nekog vanjskog izvora ili poslati informacije nekoj vanjskom odredištu. Informacije mogu biti svugdje: u datoteci, na disku, negdje na mreži, u memoriji ili u drugom programu. PREGLED I/O STREAMOVA Za uč itavanje informacija, program otvara tôk (stream) na izvoru informacija (datoteci, memoriji, socketu) i čita informacije sekvencijalno, kao što je pokazano na slici: Slič no, program može slati informacije nekom eksternom odredištu tako da otvori tôk prema odredištu i sekvencijalno upisuje informacije, kao na slici: Bez obzira odakle podaci dolaze ili kamo odlaze i bez obzira na tip informacija, algoritmi za sekvencijalno čitanje i pisanje podataka su u osnovi jednaki: Čitanje otvori stream dok ima informacija čitaj informaciju zatvori stream Pisanje otvori stream dok ima informacija piši informaciju zatvori stream Paket java.io sadrži kolekciju stream klasa koje podržavaju ove algoritme za č itanje i pisanje. Da bi koristio ove klase, program treba uvesti java.io paket. Stream klase su podijeljene u dvije hijerarhije klasa, ovisno o tipu podataka (karakteri ili bajtovi) nad kojima operiraju. 161

162 TOKOVI KARAKTERA Reader i Writer su apstraktne nadklase tokova karaktera u java.io paketu. Reader osigurava API i djelomičnu implementaciju za čitače ( readers) - tokove koji č itaju 16-bitne karaktere, dok Writer osigurava API i djelomičnu implementaciju za pisače ( writers) - tokove koji pišu 16-bitne karaktere. Podklase Reader i Writer klasa implementiraju specijalizirane tokove i podijeljene su u dvije kategorije: one koje č itaju iz ili pišu u izvore/ponore podataka (prikazani sivo na sljedeć im slikama) i one koji izvršavaju neku vrstu procesiranja (prikazani u bijelom). Većina programa bi trebala koristiti čitače i pisače za č itanje i pisanje tekstualnih informacija. Razlog tome je što oni mogu obraditi bilo koji karakter u Unicode skupu karaktera, dok su streamovi bajtova ograničeni na ISO-Latin 1 8-bitne bajtove. 162

163 TOKOVI BAJTOVA Za č itanje i pisanje 8-bitnih bajtova, programi bi trebali koristiti tokove bajtova, nasljednike InputStream i OutputStream klasa. InputStream i OutputStream osiguravaju API i djelomičnu implementaciju za ulazne tokove ( input streams) i izlazne tokove (output streams) 8-bitnih bajtova. Ovi se tokovi tipično koriste za č itanje i pisanje binarnih podatka kao što su slike i zvukovi. Dvije od ovih klasa ObjectInputStream i ObjectOutputStream koriste se za serijalizaciju objekata. Kao i kod Reader i Writer klasa, podklase klasa InputStream i OutputStream omoguć avaju specijalizirane U/I operacije koje padaju u dvije kategorije: izvore/ponore podataka (data sinks) koji su na slici osjenčeni sivo i procesirajuće tokove (neosjenčeni). RAZUMIJEVANJE U/I NADKLASA Reader i InputStram definiraju slične API-je, ali za različ ite tipove podataka. Na primjer, Reader sadrži ove metode za čitanje karaktera i nizova karaktera: int read() int read(char cbuf[]) int read(char cbuf[], int offset, int length) InputStream definira iste metode, ali za čitanje bajtova i nizova bajtova: int read() int read(byte cbuf[]) int read(byte cbuf[], int offset, int length) Također, i Reader i InputStream osiguravaju metode za označ avanje lokacije u streamu, za preskakanje ulaza i resetiranje trenutne pozicije. 163

164 Writer i OutputStream su slične na isti način. Writer definira ove metode za pisanje karaktera i nizova karaktera: int write(int c) int write(char cbuf[]) int write(char cbuf[], int offset, int length) OutputStream definira iste metode, ali za bajtove: int write(int c) int write(byte cbuf[]) int write(byte cbuf[], int offset, int length) Svi tokovi - čitači, pisač i, ulazni tokovi i izlazni tokovi - automatski se otvaraju prilikom kreiranja. Bilo koji tôk se može eksplicitno zatvoriti pozivom njegove close metode. Tôk može implicitno zatvoriti i garbage collector, što se i događa ako objekt više nije referenciran. KORIŠTENJE TOKOVA Sljedeća tablica prikazuje java.io tokove i opisuje što rade. Primjetite da u mnogo sluč ajeva java.io sadrži tokove karaktera i tokove bajtova koji izvršavaju isti tip U/I operacije, ali za različite tipove podataka. U/I TOKOVI Tip ulaza/izlaza Memorija Pipe File Tokovi CharArrayReader CharArrayWriter ByteArrayInputStream ByteArrayOutputStream StringReader StringWriter StringBufferInputStream PipedReader PipedWriter PipedInputStream PipedOutputStream FileReader FileWriter FileInputStream FileOutputStream Opis Ovi se tokovi koriste za čitanje i pisanje u momoriji. Ovakvi se tokovi kreiraju nad postojećim nizovima i zatim koriste metode za čitanje i pisanje, za čitanje i pisanje po nizu. StringReader se koristi za čitanje karaktera iz Stringova u memoriji. Koristite StringWriter za pisanje u String. StringWriter sakuplja karaktere u privremeni StringBuffer i zatim ih konvertira u String. StringBufferInputStream je sličan StringReaderu, s tim da čita bajtove iz StringBuffera. Implementira ulazne i izlazne komponente cijevi (pipe-a). Pipeovi se koriste za usmjeravanje izlaza jednog threada u ulaz drugoga. Sa zajedničkim imenom file streamovi, ovi tokovi se koriste za čitanje i posanje u datoteke. 164

165 Spajanje Serijalizacija objekata N/A SequenceInputStream N/A ObjectInputStream ObjectOutputStream N/A Pretvaranje podataka DataInputStream DataOutputStream LineNumberReader Prebrojavanje LineNumberInputStream Čitanje unaprijed Ispis Buffering Filtriranje PushbackReader PushbackInputStream PrintWriter PrintStream BufferedReader BufferedWriter BufferedInputStream BufferedOutputStream FilterReader FilterWriter FilterInputStream FilterOutputStream Spaja višestruke ulazne tokove u jedan ulazni tôk. Koristi se za serijalizaciju objekata. Čitanje i pisanje osnovnih tipova podataka u o stroju neovisnom formatu. Služi za brojanje linija prilikom čitanja. Ovi tokovi imaju tzv. pushback spremnik. Ovo pomaže kod slučajeva gdje je prilikom čitanja datoteke ponekad potrebno saznati nekoliko sljedećih bajtova kako bi odlučili što dalje. Sadrže prikladne metode za ispis. Ovo su najjednostavniji tokovi za pisanje, pa ćete vrlo često oviti druge tokove oko ovih. Bufferirani tokovi čitaju i pišu podatke baferirano tako da su uglavnom efikasniji od sličnih nebaferiranih streamova. Ove apstraktne klase definiraju interface za filtriranje podataka. Par čitač/pisač koji čini most između binarnih i karakter tokova. Pretvaranje između bajtova i karaktera InputStreamReader OutputStreamWriter InputStreamReader čita podatke iz InputStream-a i pretvara ih u karaktere koristeći podrazumijevano kodiranje karaktera ili kodiranje određeno imenom. OutputStreamWriter pretvara karaktere u bajtove, koristeći podrazumijevano kodiranje ili kodiranje zadano imenom i zatim piše ove bajtove u OutputStream. Ime podrazumijevanog kodiranja može se dobiti pozivom System.getProperty("file.encoding"). 165

166 KAKO KORISTITI TOKOVE DATOTEKA Tokovi datoteka su vjerojatno tokovi najjednostavniji za razumijevanje. FileReader, FileWriter, FileInputStream i FileOutputStream čitaju ili pišu u datoteku. Datoteč ni tok možete kreirati iz imena datoteke, File objekta ili iz FileDescriptor objekta. Sljedeći program, Copy, koristi FileReader i FileWriter za kopiranje sadržaja datoteke s imenom farrago.txt u datoteku s imenom outagain.txt: import java.io.*; public class Copy { public static void main(string[] args) throws IOException { File inputfile = new File("farrago.txt"); File outputfile = new File("outagain.txt"); FileReader in = new FileReader(inputFile); FileWriter out = new FileWriter(outputFile); int c; while ((c = in.read())!= -1) out.write(c); in.close(); out.close(); Ovaj je program vrlo jednostavan. On otvara FileReader na farrago.txt datoteci i otvara FileWriter na outagain.txt. program čita karaktere iz čitač a, dok god ima podataka na ulazu i upisuje ove karaktere u pisa č. Kad nema više podataka na ulazu, program zatvara čita č i pisa č. Ovo je kôd kojeg program koristi za kreiranje čitača iz datoteke: File inputfile = new File("farrago.txt"); FileReader in = new FileReader(inputFile); Ovaj kôd kreira objekt File koji predstavlja imenovanu datoteku u file sistemu. File je pomoćna klasa iz java.io paketa. Program Copy koristi ovaj objekt samo za kontrukiranje čitača iz ove datoteke. Pored toga, program može koristiti inputfile za dobijanje dodatnih informacija o datoteci, kao što je njezino puno ime. Nakon što pokrenete program, trebali biste pronaći istovjetnu kopiju farrago.txt datoteke u datoteci outagain.txt u istom direktoriju. Zapamtite da FileReader i FileWriter čitaju i pišu 16-bitne karaktere. Međutim, več ina file sistema je bazirana na 8-bitnim bajtovima. Ovi tokovi kodiraju karaktere prilikom čitanja/pisanja prema podrazumijevanoj shemi kodiranja karaktera. Za određ ivanje neke druge sheme kodiranje, trebate konstruirati OutputStreamWriter na FileOutputStream-u i odrediti kodiranje. 166

167 KAKO KORISTITI CIJEVI (PIPE-OVE) Cijevi se koriste za preusmjeravanje izlaza jednog threada u ulaz drugog. PipedReader i PipedWriter (i njihovi odgovarajući binarni ekvivalenti PipedInputStream i PipedOutputStream) imeplementiraju komponente ulaza i izlaza pipe-a. Zašto je ovo korisno? Pretpostavite da postoji klasa koja implementira različ ite korisne manipulacije stringovima, kao što su sortiranje i promjena redosljeda teksta. Bilo bi lijepo ako bi izlaz jedne od ovih metoda mogao biti iskorišten kao ulaz druge tako da možete povezati niz metoda u jednu cjelinu koja vrši funkciju neke više razine. Na primjer, možete izvrnuti svaku rije č u listi, sortirati riječ i, i zatim izvrnuti svaku rije č ponoo kako bi kreirali listu riječi koje se rimuju. Bez pipe tokova, program bi negdje trebao spremiti rezultate (npr. u datoteku) izmeđ u svakog koraka, ako što je prikazano ovdje: S pipe tokovima, izlaz jedne metode može biti preusmjeren u drugu, kao na ovoj slici: Pogledajmo program, RhymingWords, koji implementira funkcionalnost predstavljenu prethodnom slikom. Ovaj program koristi PipedReader i PipedWriter za spajanje ulaza i izlaza reverse i sort metoda radi kreiranja liste riječ i koje se rimuju. Program se sastoji iz nekoliko klasa. Prvo, pogledajmo sekvencu koja poziva reverse i sort metode iz main metode: FileReader words = new FileReader("words.txt"); Reader rhymingwords = reverse(sort(reverse(words))); Unutrašnji poziv reverse metode uzima FileReader, koji je otvoren nad datotekom words.txt, a koja sadrži listu riječi. Povratna vrijednost reverse metode prosljeđ uje se sort, metodi čija se povratna vrijednost prosljeđuje drugom pozivu metode reverse. Pogledajmo reverse metodu; sort metoda je slična i razumljiva ako razumijete reverse. public static Reader reverse(reader src) throws IOException { BufferedReader in = new BufferedReader(source); PipedWriter pipeout = new PipedWriter(); PipedReader pipein = new PipedReader(pipeOut); 167

168 PrintWriter out = new PrintWriter(pipeOut); new ReverseThread(out, in).start(); return pipein; Podebljani iskazi kreiraju oba kraja cijevi - PipedWriter i PipedReader - i spajaju ih konstruirajući PipedReader "na" PipedWriteru. Što god se upiše u PipedWriter može se proč itati iz PipedReader-a. Spoj čini cijev, kao na slici: Metoda reverse pokreće ReverseThread koji piše svoj izlaz u PipedWriter i vrać a PipedReader svom pozivatelju. Metoda sort je potpuno ista osim što kreira i pkreće SortThread. KAKO OVITI (TO WRAP) STREAM? Metoda reverse sadrži još jedan interesantan dio: u biti, dva iskaza: BufferedReader in = new BufferedReader(source);... PrintWriter out = new PrintWriter(pipeOut); Kôd otvara BufferedReader na source objektu, koji je drugi reader drugog tipa. Ovo u biti ovija (wraps) source u BufferedReader. Program čita iz BufferedReader-a, koji č ita iz source-a. Program ovo čini kako bi mogao koristiti readline metodu BufferedReader-a. Slič no, PipedWriter je ovijen u PrintWriter, tako da program može koristiti println metodu klase PrintWriter. Tokovi se vrlo često na ovaj način ovijaju i kombiniraju. KAKO SPOJITI DATOTEKE? SequenceInputStream kreira jedan ulazni tok iz više ulaznih izvora. Program u primjeru Concatenate, koristi ovu klasu za implementiranje utility-ja koji spaja datoteke redom kojim su navedene u komandnoj liniji. Ovo je kontrolna klasa Concatenate programa: import java.io.*; public class Concatenate { public static void main(string[] args) throws IOException { ListOfFiles mylist = new ListOfFiles(args); SequenceInputStream s = new SequenceInputStream(mylist); int c; 168

169 while ((c = s.read())!= -1) System.out.write(c); s.close(); Prvo se kreira ListOfFiles objekt s imenom mylist, koji se inicijalizira iz argumenata komandne linije. Objekt mylist je Enumeration objekt kojeg SequenceInputStream klasa koristi za dobijanje novog InputStreama kad je to potrebno: import java.util.*; import java.io.*; public class ListOfFiles implements Enumeration { private String[] listoffiles; private int current = 0; public ListOfFiles(String[] listoffiles) { this.listoffiles = listoffiles; public boolean hasmoreelements() { if (current < listoffiles.length) return true; else return false; public Object nextelement() { InputStream in = null; if (!hasmoreelements()) throw new NoSuchElementException("No more files."); else { String nextelement = listoffiles[current]; current++; try { in = new FileInputStream(nextElement); catch (FileNotFoundException e) { System.err.println("ListOfFiles: Can't open " + nextelement); return in; ListOfFiles implementira Enumeration interface. Nakon kreiranja SequenceInputStream objekta, main metoda č ita iz stream-a bajt po bajt. Kad zatreba InputStream iz novog izvora, SequenceInputStream zove metodu nextelement Enumeration objekta za dobijanje sljedeć eg InputStream-a. ListOfFiles kreira FileInputStream objekte na lijeni način. To znač i da kad god SequenceInputStream pozove nextelement, ListOfFiles otvara FileInputStream na sljedećem imenu i vrać a stream. Kad ListOfFiles nema 169

170 više elemenata, nextelement vraća null, i poziv metode read klase SequenceInputStrem vrać a -1 i tako indicira kraj ulaza. 170

171 PISANJE APPLETA Java applet je program koji se pridržava skupa konvencija koje mu dozvoljavaju pokretanje unutar Java-kompatibilnog browsera. Kôd vrlo jednostavnog HelloWorld appleta izgledao bi ovako: import java.applet.applet; import java.awt.graphics; public class HelloWorld extends Applet { public void paint(graphics g) { g.drawstring("hello world!", 50, 25); java.applet paket sadrži klase neophodne za izradu appleta. Paket java.awt sadrži najčešć e korištene klase Abstract Window Tooklita (AWT-a), koji osigurava funkcionalnost grafič kog korisničkog sučelja (Graphical user interface - GUI). Svaki applet nasljeđuje Applet klasu. Ova mu klasa omoguć ava odgovaranje na osnovne zahtjeve browsera, npr. inicijalizaciju ili pokretanje appleta. Svaki applet mora implementirati jednu od init, start ili paint metode. Naš applet implementira paint metodu koja mu omoguć ava iscrtavanje na ekranu, tj. preciznije iscrtavanje pozdravnog stringa "Hello World" na koordinatama (50,25). Koordinatni sistem appleta poč inje na koordinatama (0,0) u njegovom gornjem lijevom kutu. PREGLED APPLETA Kao što smo rekli, svaki applet se implementira kreiranjem podklase Applet klase. Sljedeć a slika prikazuje hijerarhiju nasljeđivanja Applet klase. Ovom hijerarhijom je uvelike određ eno što applet može učiniti i kako to čini. JEDNOSTAVNI APPLET 171

Osnove programskog jezika C# Čas 4. Nasledjivanje 2. deo

Osnove programskog jezika C# Čas 4. Nasledjivanje 2. deo Osnove programskog jezika C# Čas 4. Nasledjivanje 2. deo Nasledjivanje klasa Modifikator new class A { public virtual void F() { Console.WriteLine("I am A"); } } class B : A { public override void F()

More information

PREDMET. Osnove Java Programiranja. Čas JAVADOC

PREDMET. Osnove Java Programiranja. Čas JAVADOC PREDMET Osnove Java Programiranja JAVADOC Copyright 2010 UNIVERZITET METROPOLITAN, Beograd. Sva prava zadržana. Bez prethodne pismene dozvole od strane Univerziteta METROPOLITAN zabranjena je reprodukcija,

More information

PROGRAMIRANJE. Amir Hajdar

PROGRAMIRANJE. Amir Hajdar PROGRAMIRANJE Amir Hajdar Teme 2 Klase i objekti u Javi Primjer kroz klasu Krug Atributi i metode Inicijalizacija objekata (konstruktori) Polymorphism Statičke varijable i metode This Klase i objekti u

More information

VRIJEDNOSTI ATRIBUTA

VRIJEDNOSTI ATRIBUTA VRIJEDNOSTI ATRIBUTA Svaki atribut (bilo da je primarni ključ, vanjski ključ ili običan atribut) može i ne mora imati ograničenja na svojim vrijednostima. Neka od ograničenja nad atributima: Null / Not

More information

Osnove programskog jezika C# Čas 5. Delegati, događaji i interfejsi

Osnove programskog jezika C# Čas 5. Delegati, događaji i interfejsi Osnove programskog jezika C# Čas 5. Delegati, događaji i interfejsi DELEGATI Bezbedni pokazivači na funkcije Jer garantuju vrednost deklarisanog tipa. Prevodilac prijavljuje grešku ako pokušate da povežete

More information

Programiranje III razred

Programiranje III razred Tehnička škola 9. maj Bačka Palanka Programiranje III razred Naredbe ciklusa for petlja Naredbe ciklusa Veoma često se ukazuje potreba za ponavljanjem nekih naredbi više puta tj. za ponavljanjem nekog

More information

Učitati cio broj n i štampati njegovu recipročnu vrijednost. Ako je učitan broj 0, štampati 1/0.

Učitati cio broj n i štampati njegovu recipročnu vrijednost. Ako je učitan broj 0, štampati 1/0. Kontrolne naredbe Primjeri: Opšti oblik razgranate strukture (if sa ) if (uslov) Naredba 1 ili blok naredbi1 Naredba 2 ili blok naredbi2 Učitati broj x i štampati vrijednost double x, z; Scanner in=new

More information

PARALELNO PROGRAMIRANJE

PARALELNO PROGRAMIRANJE Predavanje 09 Odjel za matematiku 1 PARALELNO PROGRAMIRANJE POSIX threadovi za C++ Predavanje 09 Odjel za matematiku 2 Programske niti (thread) unutar procesa Danas ćemo se upoznati s POSIX thread bibliotekom

More information

Svi Java tipovi imaju ekvivalentan tip u jeziku Scala Većina Scala koda se direktno preslikava u odgovarajući Java konstrukt

Svi Java tipovi imaju ekvivalentan tip u jeziku Scala Većina Scala koda se direktno preslikava u odgovarajući Java konstrukt Funkcionalno programiranje Interoperabilnost jezika Scala i Java Prevođenje u Java bajt kod Svi Java tipovi imaju ekvivalentan tip u jeziku Scala Većina Scala koda se direktno preslikava u odgovarajući

More information

CSS CSS. selector { property: value; } 3/20/2018. CSS: Cascading Style Sheets

CSS CSS. selector { property: value; } 3/20/2018. CSS: Cascading Style Sheets CSS CSS CSS: Cascading Style Sheets - Opisuje izgled (appearance) i raspored (layout) stranice - Sastoji se od CSS pravila, koji defini[u skup stilova selector { property: value; 1 Font face: font-family

More information

Prva recenica. Druga recenica.

Prva recenica. Druga recenica. Algoritmi i programiranje Predavanje 4 METODE LOKALNE, GLOBALNE VARIJABLE I KONSTANTE METODA je imenovani izdvojeni slijed naredbi koji rješava određeni zadatak i po potrebi se poziva jednom ili više puta

More information

Uputa: Zabranjeno je koristiti bilo kakva pomagala. Rje²enja pi²ete desno od zadatka. Predajete samo ovaj list.

Uputa: Zabranjeno je koristiti bilo kakva pomagala. Rje²enja pi²ete desno od zadatka. Predajete samo ovaj list. Ime i prezime: Asistent: Predava : Programiranje (C) 1. kolokvij 14. 4. 2003. 1. 2. 3. 4. 5. 6. 7. Uputa: Zabranjeno je koristiti bilo kakva pomagala. Rje²enja pi²ete desno od zadatka. Predajete samo ovaj

More information

Programske paradigme Funkcionalna paradigma

Programske paradigme Funkcionalna paradigma Programske paradigme Funkcionalna paradigma 1. čas: Uvod u funkcionalno programiranje. Programski jezik Haskel. Upoznavanje sa razvojnim okruženjem. Tipovi podataka. Funkcionalno programiranje Stil u programiranju

More information

VB komande. Programiranje 1

VB komande. Programiranje 1 VB komande Programiranje 1 Zadatak 1: Sastaviti program koji se sastoji iz jedne ListBox kontrole, jedne Textbox kontrole i dva komandna dugmeta. Klikom na prvo komandno dugme umeće se u ListBox sadržaj

More information

GUI - događaji (Events) i izuzeci. Bojan Tomić

GUI - događaji (Events) i izuzeci. Bojan Tomić GUI - događaji (Events) i izuzeci Bojan Tomić Događaji GUI reaguje na događaje (events) Događaj je neka akcija koju korisnik programa ili neko drugi izvrši korišćenjem perifernih uređaja (uglavnom miša

More information

Naredbe za kontrolu toka

Naredbe za kontrolu toka Naredbe za kontrolu toka Naredbe za kontrolu toka Nakon odslušanog bit ćete u stanju: objasniti semantiku naredbi za kontrolu postupaka navesti sintaksu naredbi if, if-else i case u programskom jeziku

More information

String. String. Kreiranje string objekta pomoću string literala (konstanti) Kreiranje string objekta

String. String. Kreiranje string objekta pomoću string literala (konstanti) Kreiranje string objekta String string ili znakovni niz (string) nije niz znakova u Javi su stringovi klase String paketa java.lang!!! Usporedba: char gf = G ; Niz znakova String char [] gf = { G, e, o, d, e, t, s, k, i ; String

More information

VDSL modem Zyxel VMG1312-B10A/B30A

VDSL modem Zyxel VMG1312-B10A/B30A VDSL modem Zyxel VMG1312-B10A/B30A Default Login Details LAN IP Address http://192.168.2.1 User Name user Password 1234 Funkcionalnost lampica Power lampica treperi kratko vrijeme nakon uključivanja modema,

More information

Windows Server 2012, VDI Licenciranje najprodavanijeg servera, što je novo, VDI licenciranje. Office 2013 / Office 365

Windows Server 2012, VDI Licenciranje najprodavanijeg servera, što je novo, VDI licenciranje. Office 2013 / Office 365 Windows 8 Licenciranje, razlike u verzijama Windows Server 2012, VDI Licenciranje najprodavanijeg servera, što je novo, VDI licenciranje Serverski proizvodi Server 2012, System centar 2012, SQL 2012, Sharepoint

More information

Vežbe - XII nedelja PHP Doc

Vežbe - XII nedelja PHP Doc Vežbe - XII nedelja PHP Doc Dražen Drašković, asistent Elektrotehnički fakultet Univerziteta u Beogradu Verzija alata JavaDoc za programski jezik PHP Standard za komentarisanje PHP koda Omogućava generisanje

More information

Microsoft Hyper-V Server 2016 radionica EDU IT Pro, Zagreb,

Microsoft Hyper-V Server 2016 radionica EDU IT Pro, Zagreb, Microsoft Hyper-V Server 2016 radionica EDU IT Pro, Zagreb, 13.04.2017. Podešavanje Hyper-V Servera 2016 za RSAT upravljanje Dario Štefek Lokacije za preuzimanje: Microsoft Hyper-V Server 2016 https://www.microsoft.com/en-us/evalcenter/evaluate-hyper-v-server-2016

More information

pojedinačnom elementu niza se pristupa imeniza[indeks] indeks od 0 do n-1

pojedinačnom elementu niza se pristupa imeniza[indeks] indeks od 0 do n-1 NIZOVI Niz deklarišemo navođenjemtipa elemenata za kojim sledi par srednjih zagrada[] i naziv niza. Ako je niz višedimenzionalni između zagrada[] se navode zarezi, čiji je broj za jedan manji od dimenzija

More information

Programiranje Programski jezik C. Sadržaj. Datoteke. prof.dr.sc. Ivo Ipšić 2009/2010

Programiranje Programski jezik C. Sadržaj. Datoteke. prof.dr.sc. Ivo Ipšić 2009/2010 Programiranje Programski jezik C prof.dr.sc. Ivo Ipšić 2009/2010 Sadržaj Ulazno-izlazne funkcije Datoteke Formatirane datoteke Funkcije za rad s datotekama Primjeri Datoteke komunikacija između programa

More information

Uputstvo za korišćenje logrotate funkcije

Uputstvo za korišćenje logrotate funkcije Copyright AMRES Sadržaj Uvod 3 Podešavanja logrotate konfiguracionog fajla 4 Strana 2 od 5 Uvod Ukoliko je aktivirano logovanje za RADIUS proces, može se desiti da posle određenog vremena server bude preopterećen

More information

b) program deljiv3; uses wincrt; var i:integer; begin i:=3; while i<100 do begin write(i:5); i:=i+3; end; end.

b) program deljiv3; uses wincrt; var i:integer; begin i:=3; while i<100 do begin write(i:5); i:=i+3; end; end. NAREDBA CIKLUSA SA PREDUSLOVOM WHILE 1.Odrediti vrednosti s i p nakon izvrsenja sledecih naredbi za dato a=43, a=34, a=105 program p1; var a,s,p:integer; write('unesite a:');readln(a); p:=a; s:=0; while

More information

Upute za postavljanje Outlook Expressa

Upute za postavljanje Outlook Expressa Upute za postavljanje Outlook Expressa Prije postavljanja klijenata morate obavezno obaviti prvu prijavu na web mail kako bi aktivirali vaš račun na novom sustavu. Ukoliko niste obavili prvu prijavu, nećete

More information

PITANJA ZA II KOLOKVIJUM NASLJEĐIVANJE, VIRTUELNE FUNKCIJE I POLIMORFIZAM

PITANJA ZA II KOLOKVIJUM NASLJEĐIVANJE, VIRTUELNE FUNKCIJE I POLIMORFIZAM PITANJA ZA II KOLOKVIJUM NASLJEĐIVANJE, VIRTUELNE FUNKCIJE I 1. Definicija svake klase sadrzi kljucnu rec iza koje se navodi ime klase: class public extends 2. Kada je funkcija clanica definisana izvan

More information

Informatika Uvod u C#,.NET Framework i Visual Studio... nastavak...

Informatika Uvod u C#,.NET Framework i Visual Studio... nastavak... Informatika Uvod u C#,.NET Framework i Visual Studio... nastavak... Prof. dr. sc. Tomislav Pribanić Izv. prof. dr. sc. Vedran Podobnik Doc. dr. sc. Marija Seder Sveučilište u Zagrebu Fakultet elektrotehnike

More information

Uvod u programiranje - vežbe. Kontrola toka izvršavanja programa

Uvod u programiranje - vežbe. Kontrola toka izvršavanja programa Uvod u programiranje - vežbe Kontrola toka izvršavanja programa Naredbe za kontrolu toka if, if-else, switch uslovni operator (?:) for, while, do-while break, continue, return if if (uslov) naredba; if

More information

Uvod u Javu. Programski jezik Java Izvršavanje Java programa BlueJ razvojno okruženje Elementi Jave Tipovi podataka Prvi programi

Uvod u Javu. Programski jezik Java Izvršavanje Java programa BlueJ razvojno okruženje Elementi Jave Tipovi podataka Prvi programi 2 Uvod u Javu Programski jezik Java Izvršavanje Java programa BlueJ razvojno okruženje Elementi Jave Tipovi podataka Prvi programi 12 Java i objektno orijentirano programiranje Programski jezik Java Krajem

More information

Vidljivost TipPovratneVrednosti ImeFunkcije (NizParametara) { TeloFunkcije }

Vidljivost TipPovratneVrednosti ImeFunkcije (NizParametara) { TeloFunkcije } 1. FUNKCIJE I STRUKTRUE PROGRAMA Složeni problemi lakše se rašavaju ako se podele na manje celine koje mogu nezavisno da se rešavaju. Rešenje celokupnog složenog problema dobija se kombinovanjem rešenja

More information

24/03/2018. Deklaracija promenljivih. Inicijalizacija promenljivih. Deklaracija i inicijalizacija promenljivih

24/03/2018. Deklaracija promenljivih. Inicijalizacija promenljivih. Deklaracija i inicijalizacija promenljivih Deklaracija promenljivih Inicijalizacija promenljivih Deklaracija promenljive obuhvata: dodelu simboličkog imena promenljivoj i određivanje tipa promenljive (tip određuje koja će vrsta memorijskog registra

More information

Veliki računski zadaci mogu se razbiti u manje delove i time se omogućava ljudima da iskoriste ono što su neki drugi već uradili, umesto da počinju

Veliki računski zadaci mogu se razbiti u manje delove i time se omogućava ljudima da iskoriste ono što su neki drugi već uradili, umesto da počinju Staša Vujičić Čas 9 Veliki računski zadaci mogu se razbiti u manje delove i time se omogućava ljudima da iskoriste ono što su neki drugi već uradili, umesto da počinju sve od početka. Odgovarajuće funkcije

More information

Uvod, varijable, naredbe, petlje

Uvod, varijable, naredbe, petlje 8. JavaScript Uvod, varijable, naredbe, petlje M. Zekić-Sušac 1 Što je JavaScript? JavaScript je najpopularniji skriptni jezik na Internetu kojeg podržavaju svi poznatiji preglednici (Internet Explorer,

More information

UPUTSTVO ZA KORIŠĆENJE NOVOG SPINTER WEBMAIL-a

UPUTSTVO ZA KORIŠĆENJE NOVOG SPINTER WEBMAIL-a UPUTSTVO ZA KORIŠĆENJE NOVOG SPINTER WEBMAIL-a Webmail sistem ima podršku za SSL (HTTPS). Korištenjem ovog protokola sva komunikacija između Webmail sistema i vašeg Web čitača je kriptovana. Prilikom pristupa

More information

dr. sc.. Josip Musić Originalne slideove izradio:

dr. sc.. Josip Musić Originalne slideove izradio: Uvod u programiranje Programiranje 1 (450) Poglavlje 1 Uvod u računala, Microsoft.NET i VB.NET (dio 2 od 2): Pregled.NET platforme dr. sc.. Josip Musić jmusic@fesb.hr 1 Originalne slideove izradio: Teo

More information

Programiranje III razred

Programiranje III razred Tehnička škola 9. maj Bačka Palanka Programiranje III razred Konverzija tipova Konverzija tipova Prilikom komunikacije aplikacije sa korisnikom, korisnik najčešće unosi ulazne podatke koristeći tastaturu.

More information

Sberbank Business Online na Mozilla FireFox

Sberbank Business Online na Mozilla FireFox Sberbank Business Online na Mozilla FireFox Verzija 1.6 Srpanj 2016. Sberbank d.d. Stranica 1 SADRŽAJ 1 INSTALACIJA... 2 2 POKRETANJE MOZILLE FIREFOX... 3 2.1 IMPORT SECURITY MODULA... 4 2.2 AUTOMATSKI

More information

Push(3,&S) 3 1 S Uvijek trebamo paziti da ne zovemo Pop nad praznim stogom.

Push(3,&S) 3 1 S Uvijek trebamo paziti da ne zovemo Pop nad praznim stogom. tog (tack) tog je posebna vrsta liste: od svih operacija dozvoljeno je ubacivanje, brisanje i gledanje sadržaja elementa samo na jednom kraju liste koji zovemo vrh stoga. tog zovemo i lifo last in first

More information

Uputstvo za podešavanje mail klijenta

Uputstvo za podešavanje mail klijenta Uputstvo za podešavanje mail klijenta 1. Podešavanje Thunderbird mail klijenta 1.1 Dodavanje mail naloga Da biste podesili Vaš mail klijent (u ovom slučaju Thunderbird) da prima i šalje mail-ove potrebno

More information

RAČUNARSKI PRAKTIKUM II

RAČUNARSKI PRAKTIKUM II Prirodoslovno-matematički fakultet Matematički odsjek Sveučilište u Zagrebu RAČUNARSKI PRAKTIKUM II Predavanje 07 - Uvod u PHP 4. svibnja 2015. Sastavio: Zvonimir Bujanović PHP PHP Interpretirani skriptni

More information

PROGRAMIRANJE. Teme. Packages Reference objekata Inheritance nasljeđivanje Exceptions. Amir Hajdar

PROGRAMIRANJE. Teme. Packages Reference objekata Inheritance nasljeđivanje Exceptions. Amir Hajdar PROGRAMIRANJE Amir Hajdar Teme 2 Packages Reference objekata Inheritance nasljeđivanje Exceptions Packages API Application Programmer Interface Sve klase ponuđene u sklopu Java jezika, uključujući i kompajler

More information

OBJEKTNO ORIJENTISANO PROGRAMIRANJE

OBJEKTNO ORIJENTISANO PROGRAMIRANJE OBJEKTNO ORIJENTISANO PROGRAMIRANJE PREDAVANJE 12: NASLEĐIVANJE Miloš Kovačević Đorđe Nedeljković 1 /17 OSNOVNI KONCEPTI - Statički i dinamički tipovi podataka - Prepisivanje metoda superklase - Polimorfizam

More information

Sadržaj predavanja 02. Cjelobrojni tip podataka(1/3) Cjelobrojni tip podataka(2/3) Cjelobrojni tip podataka(3/3) prec(short) prec(int) prec(long) int

Sadržaj predavanja 02. Cjelobrojni tip podataka(1/3) Cjelobrojni tip podataka(2/3) Cjelobrojni tip podataka(3/3) prec(short) prec(int) prec(long) int Sadržaj predavanja 02 Cjelobrojni tip podataka(1/3) Cjelobrojni tip podataka Realni tip podataka Aritmetički operatori Izrazi Operatori inkrement i dekrement Kontrola toka programa Naredba za jednostruki

More information

Numeričke metode i praktikum

Numeričke metode i praktikum Numeričke metode i praktikum Aleksandar Maksimović IRB / 23/03/2006 / Str. 1 vektori Vektor u 3D prostoru. C: int v1[3]; v1[0]=a;v1[1]=b;v1[2]=c; Fortran: INTEGER V1(3) V1(1)=a V1(2)=b V1(3)=c Skalarni

More information

Binarne hrpe. Strukture podataka i algoritmi VJEŽBE 26. siječnja / 133

Binarne hrpe. Strukture podataka i algoritmi VJEŽBE 26. siječnja / 133 Binarne hrpe Potpuno binarno stablo binarno stablo u kojem svaki čvor koji nije list ima točno 2 nasljednika. Binarna hrpa potpuno binarno stablo u kojem svaki čvor koji nije list ima veću ključnu vrijednost

More information

Računarske osnove Interneta (SI3ROI, IR4ROI)

Računarske osnove Interneta (SI3ROI, IR4ROI) Računarske osnove terneta (SI3ROI, IR4ROI) Vežbe MPLS Predavač: 08.11.2011. Dražen Drašković, drazen.draskovic@etf.rs Autori: Dražen Drašković Naučili ste na predavanjima MPLS (Multi-Protocol Label Switching)

More information

OSNOVE PROGRAMIRANJA

OSNOVE PROGRAMIRANJA OSNOVE PROGRAMIRANJA Struktura aplikacije Visual Basica Za svaku formu u aplikaciji postoji pripadajuci modul forme (.frm) koji sadrži njen programski kod Modul forme sadži event procedure - dijelovi koda

More information

VHDLPrimeri Poglavlje5.doc

VHDLPrimeri Poglavlje5.doc 5. VHDL opis kola koja obavljaju osnovne aritmetičke funkcije Sabirači Jednobitni potpuni sabirač definisan je tablicom istinitosti iz Tabele 5.1. Tabela 5.1. cin a b sum cout 0 0 0 0 0 0 0 1 1 0 0 1 0

More information

KLASIFIKACIJA JELENA JOVANOVIĆ. Web:

KLASIFIKACIJA JELENA JOVANOVIĆ.   Web: KLASIFIKACIJA JELENA JOVANOVIĆ Email: jeljov@gmail.com Web: http://jelenajovanovic.net PREGLED PREDAVANJA Šta je klasifikacija? Binarna i više-klasna klasifikacija Algoritmi klasifikacije Mere uspešnosti

More information

Mašinska vizija. Dr Nenad Jovičić tnt.etf.rs/~mv

Mašinska vizija. Dr Nenad Jovičić tnt.etf.rs/~mv Mašinska vizija Dr Nenad Jovičić 2017. tnt.etf.rs/~mv Linearne 2D geometrijske transformacije 2D geometrijske transformacije Pretpostavka: Objekti u 2D prostoru se sastoje iz tačaka i linija. Svaka tačka

More information

Java. Ugnježdeni tipovi IMI PMF KG OOP 09 AKM. najveći deo teksta je preuzet sa slajdova Prof. Dragana Milićeva (ETF Bg) namenjenih pedmetu OOP2

Java. Ugnježdeni tipovi IMI PMF KG OOP 09 AKM. najveći deo teksta je preuzet sa slajdova Prof. Dragana Milićeva (ETF Bg) namenjenih pedmetu OOP2 Java IMI PMF KG OOP 0 AKM 1 Ugnježdeni tipovi najveći deo teksta je preuzet sa slajdova Prof. Dragana Milićeva (ETF Bg) namenjenih pedmetu OOP2 Ugneždeni tipovi IMI PMF KG OOP 0 AKM 2 Unutrašnje klase

More information

JavaScript i HTML DOM

JavaScript i HTML DOM 4. vježbe iz WEB programiranja četvrtak, 22. ožujka 2012. JavaScript 1. dio JavaScript i Što je DOM? Kako JS koristi DOM? Pristup elementima dokumenta Promjena i učitavanje vrijednosti tagova Primjer 1.

More information

Primjer ispisuje rečenicu "Dobro dosli na brzi tecaj C-a" na ekranu

Primjer ispisuje rečenicu Dobro dosli na brzi tecaj C-a na ekranu Osnove programiranja p. 1/27 Brzi tečaj C-a Primjer ispisuje rečenicu "Dobro dosli na brzi tecaj C-a" na ekranu Programiranje se sastoji od nekoliko koraka - pisanje programa u tekstualnom editoru (joe,

More information

UNIVERZITET U BEOGRADU ELEKTROTEHNIČKI FAKULTET

UNIVERZITET U BEOGRADU ELEKTROTEHNIČKI FAKULTET UNIVERZITET U BEOGRADU ELEKTROTEHNIČKI FAKULTET Katedra za elektroniku Računarska elektronika Grupa br. 11 Projekat br. 8 Studenti: Stefan Vukašinović 466/2013 Jelena Urošević 99/2013 Tekst projekta :

More information

16. Sigurnije programiranje

16. Sigurnije programiranje 16. Sigurnije programiranje 16.1 Pretvorba tipova Pretvorba realnog broja u cijeli broj se može izvršiti naredbama: int i; double d; ili: i = (int) d; i = int(d); U cilju bolje kontrole pretvorbe tipova

More information

NIZOVI.

NIZOVI. NIZOVI LINKOVI ZA KONZOLNI C# OSNOVNO http://www.mycity.rs/net/programiranje-u-c-za-osnovce-i-srednjoskolce.html http://milan.milanovic.org/skola/csharp-00.htm Niz deklarišemo navođenjem tipa elemenata

More information

Uvod u relacione baze podataka

Uvod u relacione baze podataka Uvod u relacione baze podataka Ana Spasić 5. čas 1 Podupiti, operatori exists i in 1. Izdvojiti imena i prezimena studenata koji su položili predmet čiji je identifikator 2001. Rešenje korišćenjem spajanja

More information

Uputa za instaliranje programske potpore za operativni sustav WINDOWS

Uputa za instaliranje programske potpore za operativni sustav WINDOWS ZABA SignErgy Desktop aplikacija Uputa za instaliranje programske potpore za operativni sustav WINDOWS SADRŽAJ 1. UVOD 3 2. PODRŽANI OPERATIVNI SUSTAVI 3 3. PROGRAMSKI PREDUVJETI ZA INSTALACIJU PROGRAMSKE

More information

PITANJA ZA II KOLOKVIJUM KLASE I OBJEKTI

PITANJA ZA II KOLOKVIJUM KLASE I OBJEKTI PITANJA ZA II KOLOKVIJUM KLASE I OBJEKTI 1. Enkapsulacija je podataka. skrivanje apstrakcija nasledivanje 2. Unutar deklaracije klase navode se: definicije funkcija clanica prototipovi (deklaracije) funkcija

More information

Jezik Baze Podataka SQL. Jennifer Widom

Jezik Baze Podataka SQL. Jennifer Widom Jezik Baze Podataka SQL SQL o Jezik koji se koristi u radu sa relacionim bazama podataka o Nije programski jezik i manje je kompleksan. o Koristi se isključivo u radu za bazama podataka. o SQL nije case

More information

Sveučilište u Zagrebu Fakultet strojarstva i brodogradnje. WEB programiranje HTML & CSS

Sveučilište u Zagrebu Fakultet strojarstva i brodogradnje. WEB programiranje HTML & CSS Sveučilište u Zagrebu Fakultet strojarstva i brodogradnje WEB programiranje HTML & CSS Autor/i: Juraj Benić 2018 1. Zadatak Kreirati stranicu kojoj će naslov biti Zadatak 1. i veličina teksta 20px te staviti

More information

6. SWITCH IZRAZ I PETLJE

6. SWITCH IZRAZ I PETLJE 6.. Switch izraz i petlje 6. SWITCH IZRAZ I PETLJE SADRŽAJ 1. switch izraz (kontrolna struktura) 2. while petlja. 3. do-while petlja. for petlja. Kontrola izvršavanja petlje - break i continue naredbe

More information

Marko Milošević.

Marko Milošević. Marko Milošević marko643@gmail.com marko.milosevic@pmf.edu.rs ESPB 8 Bodovanje Domaći Kolokvijumi 2x10 2x20 Završni ispit 40 Konsultacije sreda 13-14 četvrtak 16-17 Šabloni dizajna (Design Patterns) Metrika

More information

Programiranje 1 Programski jezik C 2. čas. Mirko Spasić

Programiranje 1 Programski jezik C 2. čas. Mirko Spasić Programiranje 1 Programski jezik C 2. čas Mirko Spasić Operatori U C-u postoji veliki broj operatora. Mogu biti unarni (imaju jedan argument) i binarni (dva argumenta). Unarni operatori mogu biti prefiksni

More information

SVEUČILIŠTE U MOSTARU FAKULTET PRIRODOSLOVNO-MATEMATIČKIH I ODGOJNIH ZNANOSTI BAZE PODATAKA 2. Doc.dr.sc. GORAN KRALJEVIĆ BAZE PODATAKA 2 1

SVEUČILIŠTE U MOSTARU FAKULTET PRIRODOSLOVNO-MATEMATIČKIH I ODGOJNIH ZNANOSTI BAZE PODATAKA 2. Doc.dr.sc. GORAN KRALJEVIĆ BAZE PODATAKA 2 1 SVEUČILIŠTE U MOSTARU FAKULTET PRIRODOSLOVNO-MATEMATIČKIH I ODGOJNIH ZNANOSTI BAZE PODATAKA 2 Doc.dr.sc. GORAN KRALJEVIĆ BAZE PODATAKA 2 1 Baze podataka 2 Web: http://www.fpmoz.ba/gkraljevic Pitanja, primjedbe,

More information

4.1 Učitavanje podatka tipa string Učitavanje brojčanih vrijednosti Rad sa dinamičkim objektima... 7

4.1 Učitavanje podatka tipa string Učitavanje brojčanih vrijednosti Rad sa dinamičkim objektima... 7 Java zadaci Zadaci 1. Priprema novog projekta... 1 2. Organizacija klasa u fajlove... 2 3. Ispis vrijednosti u konzolni prozor... 3 4. Učitavanje vrijednosti sa konzolnog prozora... 4 4.1 Učitavanje podatka

More information

Izrada VI laboratorijske vježbe

Izrada VI laboratorijske vježbe Izrada VI laboratorijske vježbe 1. Programirati proceduru koja se aktivira sa Standard palete alatki klikom na button Fajlovi. Prilikom startovanja procedure prikazuje se forma koja sadrži jedan list box

More information

Backup i Restore C particije ili Windowsa sa NORTON-om

Backup i Restore C particije ili Windowsa sa NORTON-om BRZO KOPIRANJE I RESTAURIRANJE DISKOVA (programski paket Norton SystemWorks) OBJAŠNJENJE Backup i Restore C particije ili Windowsa sa NORTON-om Je li vam se nekada srušio operativni sustav ili pokvario

More information

Prirodno-matematički fakultet u Nišu Departman za fiziku. dr Dejan S. Aleksić Programiranje u fizici

Prirodno-matematički fakultet u Nišu Departman za fiziku. dr Dejan S. Aleksić Programiranje u fizici Programiranje u fizici Prirodno-matematički fakultet u Nišu Departman za fiziku dr Dejan S. Aleksić Programiranje u fizici 7-8 Definicija, inicijalizacija promenljivih 2/21 u C-u Program napisan u programskog

More information

modifier returnvaluetype methodname(list of parameters) { // Method body; }

modifier returnvaluetype methodname(list of parameters) { // Method body; } Početna grupa, 28.11.2015. Metodi 1. Metodi opšti oblik metoda: modifier returnvaluetype methodname(list of parameters) // Method body; 2. Ime metoda: početno slovo je malo, a zatim slijede slova, cifre

More information

Objektno orijentirano programiranje. Auditorne vježbe

Objektno orijentirano programiranje. Auditorne vježbe Objektno orijentirano programiranje Auditorne vježbe Elektrotehnički fakultet Osijek Kneza Trpimira 2b 31000 Osijek www.etfos.hr 1. UVOD U C++ 1.1 Strukturno programiranje i C++ U programiranju danas dominiraju

More information

[] znači opciono; znači ili. Strana 3 od 5

[] znači opciono; znači ili. Strana 3 od 5 Database Programming with SQL kurs 2017 database design and programming with sql students slajdovi 2-1 Columns Characters and Rows Concatenation (pridruživanje) stanje povezanosti kao kod lanca; unija

More information

Blokovska struktura C++ programa ima četiri razine:

Blokovska struktura C++ programa ima četiri razine: Blokovska struktura C++ programa ima četiri razine: 1. razina datoteke (temeljna kompilacijska jedinica) 2. razina definicije (tijela) funkcije 3. razina bloka kontrolnih struktura (sekvenca, iteracija,

More information

NEKE OBJEKTNE OSOBINE ORACLE PL/SQL 9i JEZIKA (usporedba sa OOPL jezicima C++, Eiffel i Java)

NEKE OBJEKTNE OSOBINE ORACLE PL/SQL 9i JEZIKA (usporedba sa OOPL jezicima C++, Eiffel i Java) NEKE OBJEKTNE OSOBINE ORACLE PLSQL 9i JEZIKA (usporedba sa OOPL jezicima C++, Eiffel i Java) SAŽETAK Oracle korporacija je 1997. godine objavila Oracle 8.0 verziju baze i nazvala ju objektnorelacijskom.

More information

VMware Workstation. VMwareWorkstation ESX ($) (vmotion, DRS, HA, Storage vmotion) vcenter Server ($) Server. Guest OS

VMware Workstation. VMwareWorkstation ESX ($) (vmotion, DRS, HA, Storage vmotion) vcenter Server ($) Server. Guest OS VMware Workstation ESX ($) vcenter Server ($) (license manager) Server hardware (vmotion, DRS, HA, Storage vmotion) ESXi (freeware) (ESXi freeware is managed by the Virtual Infrastructure (or vsphere)

More information

Sveučilište u Zagrebu PMF Matematički odsjek. Mreže računala. Vježbe 08. Zvonimir Bujanović Slaven Kožić Vinko Petričević

Sveučilište u Zagrebu PMF Matematički odsjek. Mreže računala. Vježbe 08. Zvonimir Bujanović Slaven Kožić Vinko Petričević Sveučilište u Zagrebu PMF Matematički odsjek Mreže računala Vježbe 08 Zvonimir Bujanović Slaven Kožić Vinko Petričević Uvod: (X)HTML i CSS Na ovim i idućim vježbama naučit ćemo osnove jezika za opisivanje

More information

KINEMATIČKA ANALIZA MEHANIZAMA INDUSTRIJSKIH ROBOTA KORIŠTENJEM PROGRAMSKOG JEZIKA MATLAB

KINEMATIČKA ANALIZA MEHANIZAMA INDUSTRIJSKIH ROBOTA KORIŠTENJEM PROGRAMSKOG JEZIKA MATLAB 10 th International Scientific Conference on Production Engineering DEVELOPMENT AND MODERNIZATION OF PRODUCTION KINEMATIČKA ANALIZA MEHANIZAMA INDUSTRIJSKIH ROBOTA KORIŠTENJEM PROGRAMSKOG JEZIKA MATLAB

More information

Događaj koji se javlja u toku izvršenja programa i kvari normalno izvršenje. Kada se desi izuzetak, sistem pokušava da pronađe način da ga obradi.

Događaj koji se javlja u toku izvršenja programa i kvari normalno izvršenje. Kada se desi izuzetak, sistem pokušava da pronađe način da ga obradi. Obrada izuzetaka Šta je izuzetak? Događaj koji se javlja u toku izvršenja programa i kvari normalno izvršenje. Kada se desi izuzetak, sistem pokušava da pronađe način da ga obradi. Prosleđuje izuzetak,

More information

var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); begin ListBox1.Items.LoadFromFile('d:\brojevi.

var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); begin ListBox1.Items.LoadFromFile('d:\brojevi. 1 PANEL komponenta kontejnerska, slična GropBox. Roditeljska komponenta za komp. postavljene na nju. Zajedno se pomeraju. Caption svojstvo za naziv; Alighment pomera svojstvo Caption levo i desno; Align

More information

Broj Pitanje Bodovi 1. Navedi osnovne razloge uvođenja objektno orjentiranog pristupa? 2. Što je klasa u programskom jeziku?

Broj Pitanje Bodovi 1. Navedi osnovne razloge uvođenja objektno orjentiranog pristupa? 2. Što je klasa u programskom jeziku? Veleučilište u Rijeci Poslovni odjel Ispit iz OOT I - Grupa A 28.6.2008 Stručni studij informatike Ime i prezime: JMBAG: Bod/ocj: Broj Pitanje Bodovi 1. Navedi osnovne razloge uvođenja objektno orjentiranog

More information

PKI Applet Desktop Application Uputa za instalaciju programske potpore

PKI Applet Desktop Application Uputa za instalaciju programske potpore 1 SADRŽAJ 1. UVOD 3 2. PODRŽANI OPERATIVNI SUSTAVI 3 3. PROGRAMSKI PREDUVJETI ZA INSTALACIJU PROGRAMSKE POTPORE 3 4. INSTALACIJA PROGRAMSKE POTPORE 3 5. DEINSTALACIJA PROGRAMSKE POTPORE 6 2 1. Uvod PKI

More information

Iskočni okviri (eng. popup boxes)

Iskočni okviri (eng. popup boxes) 9. JavaScript 2.dio Iskočni okviri, funkcije, petlje, događaji M. Zekić-Sušac 1 Iskočni okviri (eng. popup boxes) U JavaScriptu mogu se koristiti 3 vrste iskočnih okvira: Upozoravajući okviri (eng. alert

More information

NAPREDNO I OBJEKTNO ORIJENTIRANO PROGRAMIRANJE

NAPREDNO I OBJEKTNO ORIJENTIRANO PROGRAMIRANJE NAPREDNO I OBJEKTNO ORIJENTIRANO PROGRAMIRANJE Objektno orijentirani jezici Kod proceduralnih jezika podaci su pasivan element. OO jezici imaju i proceduralne i neproceduralne elemente, procedure i podaci

More information

Case Study Hrvatska pošta: Korisničko iskustvo iz snova. Tomislav Turk Samostalni sistem inženjer, Combis d.o.o. Zagreb,

Case Study Hrvatska pošta: Korisničko iskustvo iz snova. Tomislav Turk Samostalni sistem inženjer, Combis d.o.o. Zagreb, Case Study Hrvatska pošta: Korisničko iskustvo iz snova Tomislav Turk Samostalni sistem inženjer, Combis d.o.o. Zagreb, 27.12.2018. Sadržaj Hrvatska pošta prije projekta Izazovi projekta Tehnologije korištene

More information

Računarski praktikum 4

Računarski praktikum 4 Sveučilište u Zagrebu PMF Matematički odjel Klase i objekti Računarski praktikum 4 Vježbe 08 Matko Botinčan Vinko Petričević Krunoslav Puljić 6.11.2007. Računarski praktikum 4 - Vježbe 07 2 Proceduralni

More information

namespace spojneice { public partial class Form1 : Form { public Form1() { InitializeComponent(); }

namespace spojneice { public partial class Form1 : Form { public Form1() { InitializeComponent(); } Spojnice using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.IO;

More information

Strukture Klase i OOP

Strukture Klase i OOP Strukture Klase i OOP Strukture (tip struct) Podatkovni tip struct Derivirani - izvedeni podatkovni tip stvara ga programer grupa logički povezanih podataka različitih podatkovnih tipova (npr. char, int,

More information

JAVA PROGRAMIRANJE 1

JAVA PROGRAMIRANJE 1 JAVA PROGRAMIRANJE 1 1. Uvod 1. Uvod - kako početi programirati u JAVA jeziku Cilj ovog poglavlja je napisati i pokrenuti jednostavnije Java programe. SADRŽAJ 1. O predmetu. 2. Programi i programski jezici.

More information

Razvoj hibridnih mobilnih aplikacija pomoću PhoneGap platforme

Razvoj hibridnih mobilnih aplikacija pomoću PhoneGap platforme INFOTEH-JAHORINA Vol. 12, March 2013. Razvoj hibridnih mobilnih aplikacija pomoću PhoneGap platforme Igor Dujlović Elektrotehnički fakultet Banja Luka Banja Luka, BiH dujlovic@gmail.com Zoran Đurić Elektrotehnički

More information

Objektno orjentirano programiranje

Objektno orjentirano programiranje Objektno orjentirano programiranje Predavanje 4 Objektno orijentirani koncepti Konstruktori Metoda koja se poziva prilikom stvaranja novog objekta Svojstveni su OO programiranju Imaju isto ime kao i klasa

More information

Programski jezik JAVA PREDAVANJE

Programski jezik JAVA PREDAVANJE Programski jezik JAVA PREDAVANJE 8 2018 www.etf.ac.me Polja za potvrdu i Radio tasteri Polja za potvrdu i radio tasteri nijesu uzajamno isključivi, što znači da ako imate pet polja za potvrdu u jednom

More information

EL E E L M E EN E T N I PRO R GR G A R M A SKO K G G JEZ E I Z KA A C# C PROF DR SAŠA BOŠNJAK

EL E E L M E EN E T N I PRO R GR G A R M A SKO K G G JEZ E I Z KA A C# C PROF DR SAŠA BOŠNJAK ELEMENTI PROGRAMSKOG JEZIKA C# PROF DR SAŠA BOŠNJAK 1.Linija menija i torba sa alatima (Menu Bar and Toolbar) Menu File Edit View Website Build Debug Format Tools Test Analyze Windows Help Opis Sadrži

More information

Objektno orijentirano programiranje. Auditorne vježbe

Objektno orijentirano programiranje. Auditorne vježbe Objektno orijentirano programiranje Auditorne vježbe Elektrotehnički fakultet Osijek Kneza Trpimira 2b 31000 Osijek www.etfos.hr 1. Uvod u C# C# (CSharp) je nastao u tvrtki Microsoft i razvijen je od strane

More information

for i:=2 to n do if glasovi[i]>max then begin max:=glasovi[i]; k:=i {*promenljiva k ce cuvati indeks takmicara sa najvise glasova *} end;

for i:=2 to n do if glasovi[i]>max then begin max:=glasovi[i]; k:=i {*promenljiva k ce cuvati indeks takmicara sa najvise glasova *} end; {*Na Evroviziji je ucestvovalo n izvodjaca. Koji od njih je osvojio najvise glasova publike?*} program Evrovizija; glasovi:array[1..50] of integer; max,k:integer; writeln('unosi se broj izvodjaca:'); writeln('unose

More information

OUR KNOWLEDGE FOR YOUR SUCCESS. Iskustva u razvoju i implementaciji ADF aplikacije

OUR KNOWLEDGE FOR YOUR SUCCESS. Iskustva u razvoju i implementaciji ADF aplikacije Iskustva u razvoju i implementaciji ADF aplikacije Sadržaj Opis aplikacije za AZ Mirovinski Fond Internacionalizacija aplikacije Integracija sa Oracle Reports Iskorištenje postojeće PL/SQL logike Kreiranje

More information

2. Linijska algoritamska struktura

2. Linijska algoritamska struktura Univerzitet u Nišu Građevinsko-arhitektonski fakultet Informatika 2 2. Linijska algoritamska struktura Milica Ćirić Blokovi za prikaz algoritma Algoritam se vizuelno može prikazati pomoću blok dijagrama,

More information

Nizovi. Programiranje 1

Nizovi. Programiranje 1 Nizovi Programiranje 1 VB Nizovi Zamislite da imate 10,000 šešira i da morate svakome od njih dati jedinstvenu oznaku. Kako biste to napravili? Bilo bi razumno svakom šeširu dati njegov broj. Sada možete

More information

Sintaksa VHDL jezika - podsjetnik -

Sintaksa VHDL jezika - podsjetnik - Sintaksa VHDL jezika - podsjetnik - -- Učitavanje biblioteka library ; -- Import all the declarations in a package use ..all; -- Import a specific declaration

More information

VIŠESTRUKO NASLJEĐIVANJE - SAN ILI JAVA 8?

VIŠESTRUKO NASLJEĐIVANJE - SAN ILI JAVA 8? VIŠESTRUKO NASLJEĐIVANJE - SAN ILI JAVA 8? SAŽETAK Višestruko nasljeđivanje klasa je dosta dugo vremena neopravdano držano kao kompleksno i nepotrebno. Vjerojatno je jedan od glavnih razloga taj što je

More information