Šta je Java? Java je objektno orijentisani jezik razvijen od strane kompanije Sun Microsystems 1991. godine, kao deo projekta koji je za cilj imao da razvije softver za elektronske ureĎaje (televizore, video rekordere i sl.). Upravo zbog toga, Java je morala da bude jednostavna, brza, efikasna, pouzdana i lako prenosiva sa jednog ureĎaja na drugi. Ove osobine su je učinile idealnom za distribuciju izvršnih programa preko WWW, kao i za razvoj softvera koji je nezavisan od platforme na kojoj se izvršava. Java je doživela posebnu ekspanziju kada je 1994. godine napravljen prvi web browser, HotJava, koji je mogao da izvršava Java aplete (posebne programe namenjene za izvršavanje u okviru čitača).
Karakteristike Jave • Jednostavna Sintaksa Jave se oslanja na programske jezike C i C++, meĎutim ona je daleko jednostavnija od njih. U Javi nema pokazivača, nizovi su realni objekti, upravljanje memorijom je automatsko.
• Objektno
orijentisana
Pruža mogućnost za kreiranje fleksibilnih, modularnih programa. Kao i većina objektno orijentisanih jezika, Java uključuje biblioteke klasa koje obezbeĎuju rad sa osnovnim tipovima podataka, ulazom i izlazom, osnovnim Internet protokolima, kontrolama za kreiranje korisničkog interfejsa i dr.
• Nezavisna
od
platforme
Programi pisani u Javi se lako prenose sa jednog kompjutera ili ureĎaja na drugi, bez obzira na različito radno okruženje tih ureĎaja. Jedini preduslov je da je na ureĎaju na kome se program izvršava instaliran interpreter za Javu, nazvan JVM (Java Virtual Machine).
• Pogodna
za
rad
u
mrežnom
okruženju
Koristi se u većini elektronskih ureĎaja (TV, VCR, mobilni telefoni, računari)
• Podržava
konkurentno
programiranje
Pomoću niti (threads), Java programi mogu da izvršavaju više zahteva istovremeno.
• Podržava Unicode
Java Platforma Platforma je hardversko i/ili softversko okruženje u kome se program izvršava. Neke od poznatih platformi (radnih okruženja) su svakako Microsoft Windows, Linux, Solaris OS i Mac OS. Većina ovih platformi može biti opisana kao kombinacija operativnog sistema i odgovarajućeg hardvera. Java platforma se razlikuje od ostalih po tome što je to u stvari samo softver koji se izvršava na višem nivou od operativnih sistema. Java platforma se sastoji od dve komponente:
Java virtuelne mašine (JVM) Java API (Java Application Programming Interface) Programi pisani u drugim programskim jezicima bivaju prevedeni kompajlerom u mašinski kod kompjutera na kome se izvršavaju. Ove instrukcije su specifične za sistem, pa takvi programi funkcionišu samo na istim sistemima. Java programi nakon kompajliranja prelaze u tzv. bytecode. Da bi bajtkod mogao da se izvrši na nekom računaru, neophodno je da na njemu postoji interpreter za Javu, nazvan Java Virtual Machine. JVM prevodi bajtkod u kod koji može da se izvršava na odgovarajućem hardveru.
JVM je dostupna u različitim operativnim sistemima (Microsoft Windows, Solaris OS, Linux, Mac OS). Java API je velika kolekcija unapred definisanih klasa i komponenti. Ove klase se nalaze u standardnim paketima Jave, o kojima će biti reči kasnije. Njihova upotreba obezbeĎuje veću funkcionalnost i efikasnost programa. Zajedno, Java API i JVM na odreĎeni način izoluju program od hardvera na kome se izvršava.
Obzirom da su Java programi nezavisni od platforme baziranoj na hardveru, ali da se oslanjaju na Java platformu, oni mogu biti sporiji nego programi pisani na jezicima kao što je C. MeĎutim, razvoj kompajlera i virtuelne mašine idu ka tome da se ova razlika u brzini izvršavanja što više smanji bez ugrožavanja dobrih karakteristika Jave, kao što je njena prenosivost.
Vrste programa u Javi Java je prvenstveno postala popularna zahvaljujući posebnim programima, tzv. apletima (applets). Aplet je program koji se izvršava u okviru Web strane i vrlo često se koristi za pravljenje dinamičkih, interaktivnih web sajtova. Apleti su pisani u Javi i mogu da se izvršavaju u bilo kom čitaču koji podržava Javu, uključujući Netscape’s Navigator i Internet Explorer. Aplikacija je samostalan program za rešavanje jednog ili skupa problema, koji se izvršava nezavisno.
Obzirom da se Java apleti izvršavaju unutar browser-a, oni imaju pristup prozoru u kome se browser nalazi, grafičkom sadržaju i dogaĎajima. Java aplikacije takoĎe mogu da kreiraju i koriste ovakve strukture, ali mogu da budu napravljene i bez grafičkih elemenata (npr. pokretanje iz komandne linije). Jedan isti program može da radi i kao aplet i kao aplikacija. Najveća razlika u funkcionisanju apleta i aplikacija je u tome što za funkcionisanje apleta postoji odreĎen skup ograničenja. Imajući u vidu da aplet može biti učitan sa Interneta i izvršen u browseru na klijentovom računaru, ovaj skup ograničenja je neophodan kako bi se sačuvala bezbednost korisnika.
Apleti ne mogu da čitaju ili pišu po sistemu fajlova korisnika Apleti ne mogu da komuniciraju ni sa jednim serverom, sem sa onim sa koga su učitani Apleti ne mogu da pokreću druge programe na korisnikovom sistemu
Nekoliko korisnih Internet adresa http://java.sun.com – sajt kompanije Sun Microsystems namenjen Java programerima na kojima možete da pronaĎete sve novosti vezane za razvoj Jave, tutorijale, primere koda i dr. http://www.java.com - sajt zabavnog karaktera na kome možete da učitate gotove besplatne Java aplikacije http://en.wikipedia.org/wiki/Java_(programming_language) – članak koji ukratko opisuje osnovne elemente Jave, ali u kome postoji puno drugih linkova za one koji žele da saznaju više. Dostupno je i izdanje na srpskom jeziku. http://javaboutique.internet.com – sajt na kome, pored članaka i tutorijala, postoji i velika kolekcija gotovih Java apleta http://www.oreilly.com/pub/topic/java - spisak knjiga specijalizovanih za odreĎene oblasti u Java programiranju http://www.javasvet.net – Internet portal na srpskom jeziku namenjen Java programerima http://www.wdvl.com/Authoring/Tutorials/web_programming.html - tutorijali iz različitih oblasti web programiranja, izmeĎu ostalih ovde imate i tutorijale za Javu i JavaScript
Materijali vezani uz ovu lekciju: - Test java api (application programming interface) - Java API (Application Programming Interface) (PDF dokument)
Java Core API Java API se sastoji od niza unapred definisanih klasa, metoda i promenljivih koje mogu biti korišćene u Java programima. Sve ove klase su grupisane u pakete (packages). Tokom godina razvoja Jave, ova biblioteka klasa je rasla i danas su dostupne različite kolekcije ovih paketa. Svaki od njih je namenjen izvršavanju jedne grupe zadataka, pa tako postoje API koji se odnose na rad sa bazama, zvukom, grafikom itd. Ovde će biti opisan tzv. Java Core API, osnovni skup klasa koji je raspoloživ na svakoj Java platformi. Ove klase se nalaze u java paketu. Programiranje korišćenjem gotovih klasa je ponekad neophodno, a vrlo često dobar izbor koji garantuje da će kod biti efikasan. Zato je neophodno da se svaki Java programer što detaljnije upozna sa Java API i mogućnostima koje one pružaju. Ovih klasa ima mnogo, ali bavljenje njima i otkrivanje novih nikada nije uzaludan posao. Dokumentacija o Java API adresi http://java.sun.com/reference/api/
je
dostupna
na
Internetu
na
java.lang – Java Language paket U okviru ovog paketa nalaze se osnovne klase koje se odnose na sam programski jezik i koje obezbeĎuju programsko okruženje za Javu. On uključuje klase koje služe za reprezentaciju brojeva (Integer, Character, Float i dr.) niski znakova (String) i objekata (Object), kao i klase pomoću kojih se rukuje kompajliranjem, izvršavanjem programa, sigurnosti i konkurentnim programiranjem.Java.lang paket je importovan automatski u svaki Java program. java.util – Utility paket Ovaj paket sadrži nekoliko korisnih klasa koje se veoma često koriste, jer pružaju mogućnost za manipulisanje različitim strukturama podataka. Neke od njih su: BitSet klasa – koristi se za čuvanje i manipulaciju relativno dugačkih nizova bitova Date klasa – koristi se za čuvanje i manipulaciju datuma i vremena, a sadrži i metode za konverziju datuma u string i obrnuto Random klasa – koristi se kao generator slučajnih brojeva Vector klasa – koristi se za čuvanje nizova objekata različitog tipa java.net Ovaj paket sadrži uobičajene klase koje se koriste u mrežnom programiranju, uključujući klaseSocket i URL (koja obezbeĎuje pristup dokumentima na Internetu). java.io – Input/Output paket U okviru ovog paketa nalaze se klase za čitanje i pisanje u tokove (streams), uključujući i standardni input i output (tastatura i monitor). TakoĎe, ovde se nalaze klase za čitanje i pisanje fajlova. java.awt – Abstract Windows Toolkit paket Ovaj paket sadrži mnoštvo klasa koje predstavljaju grafičke komponente karakteristične za Windows okruženje, a pomoću kojih je moguće napraviti grafički korisnički interfejs (Menu, Button,Font, CheckBox, Color i dr.), kao i klase za manipulaciju dogaĎajima i procesiranje slika. java.applet – Applet paket Ovaj paket sadrži klase pomoću kojih se kreiraju apleti. java.sql Ovaj paket sadrži različite klase i metode koje obezbeĎuju pristup i procesiranje podataka iz nekog izvora, obično iz relacione baze podataka. java.beans Sadrži klase neophodne za razvoj komponenata baziranim na JavaBeans arhitekturi (beans).
Kao što je napomenuto, Java Core API su raspoložive na svakoj verziji JVM. Različita radna okruženja za programiranje u Javi, kao što su Jbuilder ili J++, imaju i dodatne klase čije korišćenje u programima može da pruži veću funkcionalnost i efikasnost programa. Iako te klase mogu da budu od koristi, sa njihovim korišćenjem treba biti veoma oprezan. Moguće je da one ne budu dostupne korisniku, ukoliko se eksplicitno ne uključe u program. Ovo je posebno važno za aplete, obzirom da se od njih očekuje da se izvršavaju na bilo kojoj platformi. Jedino se za klase unutar java paketa garantuje da će biti raspoložive u svakom browser-u i u svakom Java okruženju. Primer koda napisanog u Javi U sledećem primeru je prikazan kod u kome se koriste neke od unapred definisanih klasa iz Java API. public class MojaKlasa { public MojaKlasa() { } public static void main(String[] args) { System.out.println ("Pozdrav za sve Java programere"); } Pozivanje metoda println() klase System
}
Iako klasa System nigde u samom programu nije definisana, kao ni metod println() koji se poziva, ovaj program će biti iskompajliran bez greške i izvršen na bilo kom računaru. Svaka JVM ima u sebi definiciju ovog metoda. Naredba import Definicije klasa i metoda java.lang paketa bivaju automatski uključeni u kod prilikom kompajliranja. Svi ostali paketi moraju da budu uvezeni u program pomoću naredbe import. Ova naredba daje informaciju kompajleru gde da traži definiciju klasa koje se koriste u kodu. Ukoliko neki paket ne bi bio importovan, i dalje bi bilo moguće pristupiti njegovim klasama, ali na drugačiji način. Pogledajte sledeći primer: import java.applet.*; import java.awt.*; import java.awt.geom.*; /* Applet koji prikazuje trougao. */ public class Triangle extends Applet{ public void paint(Graphics g){ Graphics2D g2 = (Graphics2D) g; Line2D.Double line1 = new Line2D.Double(150,100,200,210); g2.draw(line1); Line2D.Double line2 = new Line2D.Double(200,210,100,210); g2.draw(line2);
Line2D.Double line3 = new Line2D.Double(100,210,150,100); g2.draw(line3); } } Klasa Graphics2D je deo paketa java.awt. Ukoliko taj paket ne bi bio uvezen u program pomoću naredbe import, ovoj klasi bi bilo moguće pristupiti navoĎenjem cele putanje: java.awt.Graphics2D. Naravno da ovo nije dobro rešenje, jer bi pisanje programa i njegova čitljivost bili znatno otežani, a samim tim i mogućnost greške veća. Druga bitna činjenica je da naredba import java.awt.* uvodi samo klase ovog paketa, a ne i njegove podpakete. Zbog toga je neophodna i naredba import java.awt.geom.*, ukoliko želimo da koristimo klase paketa geom. U vezi sa naredbom import treba napomenuti i sledeće. Ova naredba uvodi samo tzv. javne klase (public), i to samo one koje se koriste u programu. To znači da će program biti preveden u bajtkod bez greške, ali ne i da će sigurno biti izvršen na korisnikovom računaru. Ukoliko Java platforma na korisnikovom računaru ne sadrži taj paket, program neće moći da se izvrši. Zbog toga prilikom distribucije programa treba voditi računa o tome koje klase program koristi. O ovome će biti više reči kasnije. Naziv jedinice: Promenljive i tipovi podataka
Materijali vezani uz ovu lekciju: - Test promenljive i tipovi podataka - Promenljive i tipovi podataka (PDF dokument)
Primitivni tipovi podataka U programskom jeziku Java postoji osam primitivinih tipova podataka. Ovi tipovi su ugraĎeni u sistem i nezavisni su od platforme na kojoj se program izvršava. U sledećoj tabeli prikazani su nazivi primitivnih tipova, veličina memorije koju zauzimaju i raspon u kome mogu da se kreću vrednosti. Veličina
Raspon
byte
8 bitova
od -128 do 127
short
16 bitova
od -32,768 do 32,767
int
32 bita
od -2,147,483,648 do 2,147,483,647
long
64 bita
od -9223372036854775808 do 9223372036854775807
float
32 bita
Jednostruka preciznost po IEEE 754 standardu
double
64 bita
Dvostruka preciznost po IEEE 754 standardu
char
16 bitova
Bilo koji Unicode karakter
boolean
1 bit
true ili false
Tip
Tabela 1. Primitivni tipovi u Javi
Kao što se vidi iz tabele, Java ima četiri celobrojna tipa. Koji od njih će se koristiti za neku promenljivu zavisi od toga koji raspon vrednosti očekujete da će biti smeštene u njoj. Treba voditi računa o tome da ako pokušate da u promenljivu smestite broj van opsega koji odgovara njenom tipu, vrednost će biti smanjena (po apsolutnoj vrednosti) do prve dostupne za taj tip, bez ikakvog obaveštenja ili prijavljivanja greške. Tipovi float i double odgovaraju standardu IEEE 754, internacionalnom standardu za definisanje brojeva sa pokretnim zarezom i njihovom aritmetikom. Tip boolean može imati vrednosti true ili false. Ovaj tip nije broj, kao u C-u, niti može biti tako tretiran u programu (npr. prilikom testiranja vrednosti). Bitno je da primetite da su svi nazivi primitivnih tipova napisani malim slovima. O tome treba voditi računa, jer u Javi postoje klase sa istim imenima, ali sa velikim prvim slovom (npr. Integer, Float i sl.). Primitivni tip boolean se razlikuje od klase Boolean.
Promenljive Promenljive su lokacije u memoriji u kojima je moguće čuvati neke vrednosti. Svaka promenljiva ima svoje ime, tip i vrednost. Pre nego što upotrebite promenljivu u kodu neophodno je da je deklarišete. Deklaracije promenljivih se sastoje od tipa i imena promenljive: int String float mesecnaZarada;
mojeGodine; mojeIme;
Deklaracije promenljivih možete da stavite bilo gde u okviru programa, mada je praksa da se promenljive deklarišu na početku bloka u kome se koriste.
Pogledajte sledeći primer: public int String boolean ... }
static
void
main
(String
args[])
{ brojac; naslov; prodato;
PRVO SE DEKLARIŠU PROMENLJIVE... A POTOM SLEDI OSTATAK KODA Ukoliko se deklariše nekoliko promenljivih istog tipa, moguće je deklarisati ih jednom naredbom. Tako, umesto int int int mojaTezina;
mojeGodine; mojaVisina;
moguće je napisati int mojeGodine, mojaVisina, mojaTezina;
Prilikom deklaracije promenljive moguće je dodeliti joj i početnu vrednost. Ovaj postupak se naziva inicijalizacija. Na primer:
String mojeIme = "Vesna";
Java razlikuje nekoliko vrsta promenljivih: lokalne, klasne i instancne. Lokalne promenljive su promenljive deklarisane u okviru nekog metoda na prethodno opisani način. One su vidljive samo unutar bloka u kome su deklarisane. O klasnim i instancnim promenljivim biće više reči kasnije. Lokalne promenljive moraju da se inicijalizuju pre nego što se koriste. Klasne i instancne promenljive nemaju ovo ograničenje.
Imenovanje promenljivih Kao i u svakom programskom jeziku, i u Javi postoji odreĎen niz pravila i konvencija za imena promenljivih.
Ime promenljive može biti bilo koji validan identifikator, pri čemu treba imati na umu da Java razlikuje mala i velika slova. Iako su identifikatori koji počinju sa "$" ili "_" ispravni, po konvenciji imena promenljivih bi trebala da uvek počnu slovom. TakoĎe, smatra se da znak za dolar ne treba koristiti uopšte unutar imena. Prilikom odabira imena za promeljivu, uvek treba koristiti reči koje imaju značenje i koje na neki način opisuju veličinu koja se čuva u toj promenljivoj. To doprinosi boljoj čitljivosti koda i veoma je korisno, pogotovo kada na razvoju istog softvera rade timovi ljudi. Tako je uvek bolje nazvati promenljivu npr. visina nego v, ili iznos umesto i. Ukoliko se ime promenljive sastoji iz jedne reči, ovu reš bi trebalo pisati malim slovima. Ukoliko se ime sastoji iz više reči, tada svako početno slovo svake reči, sem prve, bi trebalo da je veliko. Na primer, dobro je koristiti sledeća imena: iznosKamate, iznosKredita
Klasni tipovi Promenljive u Javi mogu biti klasnog tipa, tj. deklarisane tako da čuvaju instance neke odreĎene klase. Na primer: String Font osnovniFont;
prezimeStudenta;
Svaka od ovih promenljivih može da sadrži instancu klase koja je imenovana deklaracijom, ali isto tako i bilo koju podklasu (o klasama će više reči biti kasnije). Ova osobina je veoma korisna. Na primer, ukoliko imamo definisanu klasu Vozilo i podklase Automobil, Avion, Autobus i sl., tada promenljiva tipa Vozilo može da sadrži instance bilo koje od ovih klasa. TakoĎe, promenljiva tipa Object može da sadrži bilo koji objekat.
Podrazumevane vrednosti Već je napomenuto da lokalnim promenljivim mora da bude dodeljena vrednost pre nego što se upotrebe, dok klasne i instancne promenljive nemaju ovo ograničenje. Ovim promenljivim se inicijalne vrednosti dodeljuju automatski. Ipak, oslanjanje na ove vrednosti smatra se lošom programerskom praksom. U sledećoj tabeli su date podrazumevane vrednosti za različite tipove podataka. Tip podataka
Podrazumevana vrednost promenljive
byte
0
short
0
int
0
long
0L
float
0.0f
double
0.0d
char
'\u0000'
String (ili bilo koji objekat)
null
boolean
false
Tabela 2. Podrazumevane vrednosti Naziv jedinice: Naredbe i kontrolne strukture
Materijali vezani uz ovu lekciju: - Test naredbe i kontrolne strukture - Naredbe i kontrolne strukture (PDF dokument)
Naredbe Naredbe u programskom jeziku Java su, grubo rečeno, ekvivalentne sa rečenicama u prirodnom jeziku. Naredba čini jednu kompletnu jedinicu izvršavanja programa. Na primer:
brzina = 25.3; // naredba dodele brojRata++; // naredba povećanja System.out.println("Java programiranje"); // poziv metoda Autor noviAutor = new Autor(); // kreiranje objekta
Primetite da na kraju svake naredbe stoji znak ";". Naredbama se smatra i deklarisanje promenljivih, kao i naredbe za kontrolu toka programa, o kojima će biti više reči kasnije.
Blokovi Blok je grupa od nekoliko naredbi koje su smeštene izmeĎu velikih zagrada {}. Blokovi mogu biti smešteni bilo gde u telu programa, na mestima gde je dozvoljena upotreba naredbi. class PrimerBlok { public static void main(String[] args) { boolean povecaj= true; int a = 10; if (povecaj) { // početak prvog bloka a++; System.out.println("Uvecana vrednost iznosi " + a); } // kraj prvog bloka else { // početak drugog bloka System.out.println("Vrednost nije uvećana"); } // kraj drugug bloka } }
Komentari Komentarisanje koda se smatra dobrom programerskom praksom. Java koristi tri tipa komentara: jednolinijski (//), višelinijski (/* i */) i Javadoc komentari (/** i */).
//jednolinijski komentar /* višelinijski komentar Sve u okviru ovog bloka se ignoriše od strane kompajlera Možete da ubacite koliko god želite linija teksta izmeĎu ova dva taga */ /** višelinijski komentar koji Javadoc može da pročita i ubaci u HTML dokumentaciju */ /* Nemojte da pokušavate /* da na ovaj način */ /** ugnjezdite višelinijske komentare */ jer će doći do greške prilikom kompajliranja */
Javadoc je alat pomoću koga možete brzo da napravite dokumentaciju za svoj projekat. Ubacivanje Javadoc komentara u programski kod dok radite na njemu pomaže da kasnije dokumentaciju uradite brže i efikasnije pomoću ovog alata.
Kontrola toka programa Naredbe se po pravilu izvršavaju onim redom kojim su napisane. Kontrole toka programa omogućavaju promenu toka izvršavanja ili uslovno izvršavanje delova programa.
if-then-else naredba Ova naredba proverava neki zadati uslov i u slučaju da je on tačan izvršava jedan blok naredbi, a u slučaju da nije, izvršava se drugi blok naredbi. Uslov koji se proverava mora biti tipa boolean.
if (odgovor == 123) { System.out.println("Tacno!"); } else { System.out.println("Netacno!"); }
U gornjem primeru proverava se vrednost promenljive odgovor. Ako je ona jednaka vrednosti 123, ispisuje se "Tacno", a ako nije izvršava se drugi blok i ispisuje reč „Netacno". Ova naredba može biti i bez else dela, samo sa jednom granom koja se izvršava ako je uslov tačan. Na primer:
if (odgovor == 123) { System.out.println("Tacno!"); }
U ovom slučaju poruka će biti ispisana samo ako je odgovor tačan. Ako nije, neće biti preduzeto ništa. Naredba if sa samo jednom granom može biti zapisana i kraće. Tako bi prethodni primer mogao da bude zapisan na sledeći način:
if (odgovor == 123) System.out.println("Tacno!"); Često je potrebno nekoliko puta uzastopno proveravati neke uslove. Pogledajte sledeći primer u kome se izračunava ocena koju je student dobio na kolokvijumu na osnovu broja bodova. class Ocena { public static void main(String[] args) { int brojBodova = 74; int ocena; if (brojBodova >= 90) { ocena = 10; } else if (brojBodova >= 80) { ocena = 9; } else if (brojBodova >= 70) { ocena = 8; } else if (brojBodova >= 60) { ocena = 7; } else if (brojBodova >= 50) { ocena = 6; } else { ocena = 5; } System.out.println("Ocena = " + ocena); } }
Poruka koju će program da ispiše u ovom primeru je Ocena = 8. Iako vrednost promenljive brojBodova zadovoljava dva uslova, 74 >= 70 i 74 >= 60, kada je jednom zadovoljen uslov, ostali se neće proveravati.
switch naredba Ova naredba grananja izračunava neki izraz i na osnovu dobijene vrednosti izvršava deo koda koji toj vrednosti odgovara. Pogledajte sledeći primer koda, koji ispisuje imena dana u nedelji na osnovu rednog broja dana. class DanUNedelji { public static void main(String[] args) { int dan = 5; switch (dan) { case 1: System.out.println("Ponedeljak"); break; case 2: System.out.println("Utorak"); break; case 3: System.out.println("Sreda"); break; case 4: System.out.println("Cetvrtak"); break; case 5: System.out.println("Petak"); break; case 6: System.out.println("Subota"); break; case 7: System.out.println("Nedelja"); break; default: System.out.println("Pogresan redni broj!"); break; }
} }
Nakon izvršavanja ovog programa, biće ispisana reč "Petak". Telo switch naredbe naziva se i switch blok. U okviru ovog bloka svaka naredba je označena sa jednom ili više case oznaka ili oznakom default. Switch naredba izračunava vrednost nekog izraza i prelazi na izvršavanje linije koda koja je obeležena tom vrednošću. U vezi sa tim treba napomenuti sledeće. Kod if naredbe izvršava se samo jedna od grana. Dakle, ako je uslov tačan izvršiće se samo prvi blok naredbi, dok se drugi neće izvršavati. Završetkom poslednje naredbe u prvom bloku, izlazi se iz cele ifthen-else naredbe. Kod switch naredbe to nije slučaj. Kada switch naredba izračuna vrednost izraza, ona prelazi na izvršavanje naredbi obeleženih tom vrednošću, ali po završetku ne izlazi iz čitavog switch bloka, već nastavlja dalje redom da izvršava naredbe koje slede posle, bez obzira na to kojim oznakama su obeležene. Prilikom rešavanja nekih problema, ova osobina switch naredbe može biti korisna, jer omogućava da se za više istih case vrednosti izvrši isti kod. U prethodnom primeru to nije bio slučaj, pa je bilo neophodno staviti naredbu break nakon svake naredbe, kako bi se time postiglo izlaženje iz switch bloka. Da je u prethodnom primeru switch blok bio bez break naredbi, rezultat izvršavanja programa bilo bi ispisivanje sledećih poruka: Petak Subota Nedelja Pogresan redni broj! O break naredbi biće više reči kasnije.
while i do petlje while i do-while naredbe izvršavaje neki blok naredbi dok god je zadati uslov tačan. Uslov koji se zadaje mora imati vrednost boolean. Imaju sledeću sintaksu:
while (uslov) { // neki kod } i
do { // neki kod } while (uslov)
Na primer, ispisivanje brojeva od 1 do 10 moglo bi biti postignuto pomoću while naredbe na sledeći način: class DesetBrojeva { public static void main(String[] args){ int brojac = 1; while (brojac < 11) { System.out.println(brojac); brojac++; } } }
Pomoću while naredbe moguće je kreirati tzv. beskonačne petlje ne sledeći način
while (true) { // neki kod }
Sa beskonačnim petljama treba biti jako oprezan i voditi računa o tome da se obezbedi izlaz iz njih. Razlika izmeĎu while i do-while naredbe je što se kod while naredbe prvo proverava uslov, a zatim izvršava kod, dok se kod do-while naredbe prvo kod izvrši, a tek zatim se proverava uslov. Dakle, korišćenjem do naredbe, kod će biti barem jednom izvršen. Prethodni primer ispisivanja brojeva pomoću do naredbe izgledao bi ovako: class DesetBrojeva { public static void main(String[] args){ int brojac = 1; do { System.out.println(brojac); brojac++; } while (brojac < 10); } }
for petlje Pomoću for naredbe odreĎeni blok naredbi se izvršava zadati broj puta. Osnovna sintaksa for naredbe je sledeća:
for (početna vrednost; uslov prekida; povećanje) { // blok naredbi }
Primer koji sledi ispisuje prvih deset brojeva koristeći naredbu for. class DesetBrojeva { public static void main(String[] args){ for (int brojac = 1; brojac < 11;brojac++){ System.out.println(brojac); } } }
Primetite da se u ovom primeru promenljiva brojac deklariše i povećava unutar for naredbe. U tom slučaju, ona je i vidljiva samo unutar for bloka i ne može biti korišćena izvan njega. Ukoliko iz nekog razloga želimo da promenljivu brojac koristimo i izvan for bloka, tada je neophodno da i deklaracija promenljive bude izvan ove naredbe.
break i continue naredbe Naredbe break i continue se koriste za prekidanje izvršavanja petlji. Break naredba izlazi iz petlje potpuno, dok continue naredba prekida samo tekuću iteraciju i nastavlja novu iteraciju od početka. Pogledajte sledeća dva primera:
int i = 0; while (i <= 10) { i++; if ((i%2)==0) break; System.out.println(i); } int i = 0; while (i < 10) { i++; if ((i%2)==0) continue; System.out.println(i); } U oba primera se celobrojnoj promenljivoj i dodeljuje vrednost 0, a zatim se proverava da li je vrednost promenljive manja od 10. Dok god jeste, promenljiva se uveća za jedan i proveri se da li pri deljenju brojem 2 ima ostatka ili ne (da li je broj paran). Ukoliko nije paran, ispisuje se na izlaz. Ako jeste, u prvom slučaju naredba break prekida izvršavanje naredbe while. U drugom slučaju, naredba continue zaustavlja trenutnu iteraciju i počinje ponovo od početka while bloka. Dakle, promenljiva se ponovo povećava za jedan i ponovo se proverava da li je broj paran. Rezultat izvršavanja ova dva koda bio bi, u prvom slučaju, ispisivanje broja 1, a u drugom ispisivanje svih neparnih brojeva manjih od 10.
Naredbe break i continue mogu da koriste i obeležja (labele). Pogledajte sledeći primer:
out: for (int i = 0; i <10; i++) { while (x < 50) { if (i * x == 400) break out; } } U ovom primeru postoje dve petlje, for i while, jedna unutar druge. Petlja for je obeležena oznakom out. Naredba break se nalazi unutar while petlje, ali koristi obeležje out (break out). Na ovaj način naredba break ne samo da završava petlju u kojoj se nalazi (while), već i onu koja je obeležena oznakom out (for petlju).
return naredba return naredba se koristi u okviru metoda, prekida tekući metod i vraća se na naredbu koja sledi nakon njegovog pozivanja. Ima dva oblika, jedan koji vraća neku vrednost i jedan koji ne vraća. O ovoj naredbi će biti više reči kasnije. Naziv jedinice: Nizovi i rad sa stringovima
Materijali vezani uz ovu lekciju: - Test nizovi i rad sa stringovima - Nizovi i rad sa stringovima (PDF dokument)
Nizovi Kao i u drugim jezicima, i u Javi se koriste nizovi za čuvanje kolekcije podataka u jednoj strukturi. Za razliku od drugih programskih jezika, nizovi u Javi su realni objekti. Svaki element niza može sadržati podatke primitivnog tipa ili objekte. MeĎutim, samo podaci istog tipa mogu biti u jednom nizu. Deklarisanje niza Moguća su dva zapisa deklaracije niza: String dani[]; ili String[] dani; Ova dva zapisa su ekvivalentna, meĎutim obično se koristi drugi zbog svoje čitljivosti. Kreiranje niza Kreiranje niza je moguće korišćenjem naredbe new ili direktnom inicijalizacijom njegovih elemenata. String[] names = new String[10]; Gornja naredba kreira niz sa 10 elemenata. Vrednosti ovih elemenata samim kreiranjem dobijaju podrazumevane vrednosti (0 za brojevne nizove, '\0' za nizove karaktera i null za objekte). Imate mogućnost i da kreirate niz i dodelite vrednosti njegovim elementima istovremeno. Evo primera: String[] jezici = { "engleski", "spanski", "francuski" }; Ovaj primer kreira niz stringova veličine 3. Pristup elementima niza Pristupanje elementima niza vrši se pomoću sledeće sintakse: nekiNiz[indeks] nekiNizmože biti ili promenljiva koja čuva niz ili neki izraz koji za rezultat ima niz. indeks odreĎuje broj elementa kome se pristupa. Indeksiranje počinje od broja 0, pa tako niz od deset elemenata ima indekse od 0 do 9. Pokušaj pristupa elementu van ovog opsega rezultuje greškom prilikom kompajliranja ili izvršavanja. Da biste bili sigurni da uvek pristupate postojećem elementu, možete da proverite dužinu niza
int duzina = nekiNiz.length; Imajte na umu da je poslednji indeks uvek za jedan manji od dužine (broja elemenata) niza. Dodela vrednosti elementima niza Da biste dodelili vrednost elementima niza koristite naredbu dodele: mojNiz[1] = 15; mesec[0] = "Januar"; rec[0] ="the"; rec[5] = rec[0]; Prilikom dodeljivanja vrednosti članovima niza treba imati na umu da je niz objekata u Javi u stvari samo niz referenci do tih objekata, isto kao i u slučaju običnih promenljivih. Multidimenzionalni nizovi Java ne podržava direktno multidimenzione nizove, ali je moguće deklarisati i kreirati niz nizova. int matrica[] [] = new int [12] [12]; matrica[0] [0] = 1; matrica[0] [1] = 2; Sledeći primer ilustruje neke od opisanih tehnika za rad sa nizovima. Kao što ćete videti u kodu, često se za manipulisanje sa nizovima koriste for petlje. Pri tome treba voditi računa da ne pokušate da pristupite elementu niza koji ne postoji (čiji je indeks van opsega). 1:class eksponent { 2:
public static void main(String args[]) {
3:
int nizBrojeva[] = new int[20];
4:
for (int i = 0; i < nizBrojeva.length; i++) {
5:
nizBrojeva[i] = 1;
6:
for(int p = 0; p < i; p++) nizBrojeva[i] *= 2 ;
7:
}
8:
for (int i = 0; i < nizBrojeva.length; i++)
9:
System.out.println("2 na " + i + " je " +
10: 11: 12:}
nizBrojeva[i]); }
U liniji 3 se deklariše niz brojeva od 20 elemenata (indeksi su u rasponu od 0 do 19). For petlja u liniji 6 za svaki indeks i izračunava vrednost 2i i smešta je u element niza. For petlja u liniji 8 ispisuje ove vrednosti. Stringovi String je niska karaktera. U Java programskom jeziku, stringovi su objekti. Kreiranje i rad sa stringovima u Javi vrši se pomoću klase String i metoda koje ona obezbeĎuje. Kreiranje stringa Kao što ste do sada već videli, jedan string možete da kreirate ili direktno (dodelom string literala nekoj promenljivoj tipa String) ili pomoću jednog od jedanaest konstruktora klase String. String ime = “Marko” ; //dodela string literala promenljivoj tipa string ili char[] imeNiz = { 'M', 'a', 'r', 'k', 'o' }; String imeString = new String(imeNiz); U vezi sa String klasom treba napomenuti sledeće. Ova klasa je nepromenljiva, što znači da jednom kreiran String objekat ne može da bude promenjen. Ova klasa ima nekoliko metoda koji, na prvi pogled, menjaju stringove. MeĎutim, ovi metodi ustvari samo prave nove stringove koji sadrže rezulate operacija. Za sve operacije sa stringovima (kopiranje, nadovezivanje, provera jednakosti i dr.) postoje odgovarajući metodi u okviru klase String. Ovde će biti razmatrani neki od njih. Dužina stringa Za odreĎivanje dužine stringa koristi se metod length(). Ovaj metod vraća broj karaktera koji se nalaze u stringu, tipa int. Pogledajte sledeći primer: String naslov = “Java programiranje”; int duzina = naslov.length(); Nakon izvršavanja ove dve linije koda, promenljiva duzina imaće vrednost 18. Nadovezivanje (konkatenacija) stringova Dva stringa moguće je nadovezati na dva različita načina: pomoću operatora + i pomoću metoda concat() klase String. Tako će sledeće dve linije koda imati isti efekat: String naslov = “Java” + “ programiranje”; String naslov = “Java”.concat(“ programiranje”);
Operator + se mnogo češće koristi za nadovezivanje stringova. Sa ovim operatorom ste se već susretali. U jednom od prethodnih primera imali smo ovakvu naredbu: System.out.println("x koordinata tacke je " + tacka.x); Ovde je poruka koja se ispisuje kreirana od jednog stringa ("x koordinata tacke je ") i jedne vrednosti tipa int, pomoću operatora +. Ukoliko pokušate da povežete objekte ili vrednosti koje nisu String, pre povezivanja biće pozvan metod toString() odgovarajuće klase, koji konvertuje tu vrednost u String. Konvertovanje stringa u broj Često u programu numerički podaci bivaju smešteni u String objekte (na primer, podaci uneti od strane korisnika). MeĎutim, da bi program mogao da izvrši odgovarajuća izračunavanja, neophodno je da ove vrednosti budu u promenljivima numeričkog tipa (int, float, double itd). Zbog toga sve klase koje odgovaraju primitivnim tipovima (Integer, Float, Double) imaju metod valueOf() koji konvertuje string u objekat odgovarjuće klase. 1:class konverzija { 2:
public static void main(String[] args) {
3:
String sBroj1 = "123";
4:
String sBroj2 = "456";
5:
System.out.println(sBroj1 + sBroj2);
6:
//konvertovanje stringova u brojeve
7:
int iBroj1 = Integer.valueOf(sBroj1).intValue();
8:
int iBroj2 = Integer.valueOf(sBroj2).intValue();
9:
System.out.println(iBroj1 + iBroj2);
10:
}
11:} U gornjem primeru deklarisane su dve promenljive tipa String. Operator + u liniji 5 će nadovezati ova dva stringa, pa će na ekranu biti ispisana poruka “123456”. U linijama 7 i 8 vrši se konverzija ova dva stringa u brojeve. Operator u liniji 9 će sada sabrati ova dva broja, pa će biti ispisana poruka “579”. Obratite pažnju na linije 7 i 8. Metod valueOf() klase Integer vraća objekat tipa Integer. Zatim se poziva metod intValue() koji objekat tipa Integer konvertuje u vrednost primitivnog tipa int, koja se zatim dodeljuje promenljivim iBroj1 i iBroj2. Ista stvar je mogla biti postignuta i na sledeći način: int iBroj1= Integer.parseInt(sBroj1); Ovde se koristi metod parseInt() klase Integer, koji vraća vrednost tipa int.
Konvertovanje broja u string Ukoliko je potrebno da neku numeričku vrednost konvertujete u String objekat, postoji nekoliko načina za to. int broj = 15; String sBroj = String.valueOf(broj); ili int broj = 15; String sBroj = Integer.toString(broj); Pristup pojedinačnim karakterima i delovima stringa Za pristup odreĎenom karakteru u okviru stringa koristite metod charAt(). Imajte na umu da prvi karakter ima indeks 0, a poslednji za jedan manji od dužine stringa. Pogledajte sledeći primer: 1:class Palindrom { 2:
public static void main(String[] args) {
3:
String rec1 = "kajak";
4:
String rec2 ="";
5:
for (int i=rec1.length(); i>0; i--) {
6:
rec2 += rec1.charAt(i-1);
7:
}
8:
System.out.println("Rec " + rec1 + " je palindrom: " + (rec2.equals(rec1)));
9:
}
10:} U liniji 3 je inicijalizovana reč za koju se proverava da li je palindrom. Od ove reči se zatim formira rečrec2, koja sadrži iste karaktere kao i reč rec1, ali u obrnutom redosledu. rec2 se formira u okviru forpetlje, nadovezivanjem jednog po jednog karaktera reči rec1. U tu svrhu je korišćen metod charAt().Ove dve reči se na kraju porede pomoću metoda equals() klase String. Obratite pažnju da brojač i ima početnu vrednost jednaku dužini reči rec1, ali se zato u liniji 6 koristicharAt(i-1). Vodite računa kada radite sa stringovima da ne pokušate da pristupite nepostojećim karakterima, jer će u tom slučaju doći do greške u kompajliranju. Ukoliko želite da pristupite delu stringa, koristite metod substring(). Ovaj metod ima sledeće argumente: substring(int pocetniIndeks, int krajnjiIndeks)
ili substring(int pocetniIndeks) U prvom slučaju rezultat će biti deo stringa od prvog argumenta (pocetnIndeks) do drugog argumenta (krajnjiIndeks). U drugom slučaju, kada je izostavljen drugi argument, uzima se deo stringa od prvog argumenta pa do kraja. 0
J
1
a
2
v
3
a
4
5
6
7
8
9
10 11 12 13 14 15 16 17
substring(5,12) r
o
g
r
a
m i
r
a
n
j
e
p Ostali korisni metodi klase String Pored do sada opisanih, klasa String ima još metoda koji obezbeĎuju različite operacije sa stringovima. String trim() – uklanja space karaktere sa početka i kraja stringa String toLowerCase() – konvertuje sve karaktere String toUpperCase() – konvertuje sve karaktere u velika slova
u
mala
slova
Metodi za pretraživanje (indexOf(), lastIndexOf()) Metodi za zamenu (replace(), replaceAll(), replaceFirst()) Metodi za poreĎenje (endsWith(), startsWith(), compareTo(), compareToIgnoreCase(), equals(),equalsIgnoreCas e()) Primer koji sledi ilustruje neke od ovih metoda. 1:class StringOperacije { 2:
public static void main(String args[]) {
3:
String s = " Java programski jezik " ;
4:
System.out.println(s);
5:
System.out.println(s.toUpperCase());
6:
System.out.println(s.toLowerCase());
7:
System.out.println("["+s+"]");
8:
s=s.trim();
9:
System.out.println("["+s+"]");
10:
s=s.replace('J','X');
11:
s=s.replace('p','Y');
12:
s=s.replace('j','Z');
13:
System.out.println(s);
14:
int i1 = s.indexOf('X');
15:
int i2 = s.indexOf('Y');
16:
int i3 = s.indexOf('Z');
17:
char ch[] = s.toCharArray();
18:
ch[i1]='J';
19:
ch[i2]='p';
20:
ch[i3]='j';
21:
s = new String(ch);
22:
System.out.println(s);
23:
}
24:} U liniji 3 string s dobija inicijalnu vrednost “ Java programski jezik “. Linije 4, 5 i 6 ispisuju originalan string i stringove napisane samo velikim i samo malim slovima. Linije 7 ispisuje string u srednjim zagradama, kako bi bilo uočljivo da se na početku i na kraju nalaze space karakteri. Metod trim() u 8 liniji uklanja ove karaktere, a linija 9 ispisuje novonastali string. Linije 10, 11 i 12 koriste metodreplace() da zamene početna slova reči slovima X, Y i Z. Obratite pažnju da ovaj metod pravi razliku izmeĎu velikih i malih slova. Linije 14, 15 i 16 pamte pozicije ovih slova. U liniji 17 kreira se niz karaktera od karaktera stringa s. Zatim se u linijama 18, 19 i 20 karakteri na pozicijama koje odgovaraju početnim slovima reči vraćaju u prvobitno stanje. Zatim se na osnovu ovog niza ponovo kreira String objekat s i ispisuje se njegov sadržaj (linije 21 i 22). Naziv jedinice: Klase
Materijali vezani uz ovu lekciju: - Test klase - Klase (PDF dokument)
Definisanje klase
Kao što ste do sada videli, klasa se definiše pomoću ključne reči class.
class ImeKlase { ..... } Podrazumevana klasa koju nasleĎuju sve klase u Javi je klasa Object. Ukoliko želite da vaša klasa bude direktna podklasa neke druge, tada ćete koristiti sledeću sintaksu: class ImeKlase extends ImeNadKlase{ ..... } Na primer, zamislite da pravite program za administrative poslove jednog fakulteta. IzmeĎu ostalih klasa, verovatno ćete želeti da imate klase koje će odgovarati studentima i predavačima. U tom slučaju, mogli biste da imate jednu osnovnu klasu, Osoba i dve podklase, Student i Predavac. class Osoba { String ime; String prezime; String jmbg; ......... } class Student extends Osoba { int godinaUpisa; int godinaStudija; int brojPolozenihIspita; ......... } class Predavac extends Osoba { String[] nazivPredmeta; ......... }
Klasa Osoba bi u svojim promenljivima čuvala neke atribute koje ima bilo koja osoba, bez obzira da li je student ili predavac. Klase Student i Predavac bi sadržale neke atribute specifične za studenta, odnosno predavača. Promenljive instance Promenljive deklarisane u okviru klasa Osoba, Student i Predavac nazivaju se objektne ili instancne promenljive. One čuvaju vrednosti atributa pojedinačnih objekata ovih klasa. Klase Student i Predavac su podklase klase Osoba, pa nasleĎuju objektne promenljive deklarisane u klasi Osoba. Pored ovih promenljivih (ime, prezime, jmbg), klase Student i Predavac imaju i objektne promenljive karakteristične samo za njih.
Klasne promenljive Nasuprot objektnim, klasne promenljive se odnose na celu klasu, a ne na pojedinačne objekte. Deklarišu se pomoću ključne reči static unutar definicije klase:
static int suma; static int maksimum = 10;
U prethodnom primeru mogli bismo da proširimo klasu Osoba sa jednom klasnom promenljivom u kojoj bi se čuvalo ime fakluteta u kojem osoba uči ili predaje. Tako bi klasa Osoba sada izgledala ovako:
class Osoba { static String imeFakulteta = “BARN”; String ime; String prezime; String jmbg; ......... } Promenljiva imeFakulteta je klasna promenljiva, što znači da čuva vrednost koja se odnosi na celu klase, tj. na sve objekte te klase, a ne na neki pojedinačni objekat. Njena promena u okviru jednog objekta dovodi do promene vrednosti tog atributa i kod svih ostalih objekata te klase.
TakoĎe, klase Student i Predavac bi mogle da imaju klasne promenljive brojStudenata i brojPredavaca u kojima bi se čuvao broj kreiranih objekata studenata i predavača. U tom slučaju, mogli bismo da klaseStudent i Predavac definišemo ovako:
class Student extends Osoba { static int brojStudenata; int godinaUpisa; int godinaStudija; int brojPolozenihIspita; ......... } class Predavac extends Osoba { static int brojPredavaca; String[] nazivPredmeta; ......... } Klasnoj promenljivoj možete pristupiti ili preko objekta ili preko cele klase. Na primer,
Osoba lice1 = new Osoba(); System.out.println(lice1.imeFakulteta);
ili samo
System.out.println(Osoba.imeFakulteta);
Ključna reč final
Konstante u Javi se tretiraju kao promenljive čija se vrednost nikad ne menja. Mogu biti kreirane samo kao objektne ili klasne promenljive, a ne kao lokalne. Deklarišu se pomoću ključne reči final. Neophodno je da se inicijalizuju prilikom deklaracije.
final float pi = 3.141592; final int maxIznos = 10000;
Često se koriste za imenovanje različitih stanja. Na primer:
final int LEFT = 0; final int RIGHT = 1; final int CENTER = 2; Tada pod pretpostavkom da imamo deklarisanu promenljivu align tipa int, koristimo prethodno imenovana stanja: this.align = CENTER; Ovakva praksa imenovanja stanja dovodi do poboljšanja čitljivosti koda. Ključna reč final, sem na promenljive, može biti primenjena i na metod i na klasu. Ukoliko se klasa definiše kao final, onda ona ne može da ima podklase. Definisanje metoda kao final biće objašnjeno kasnije. Klasa se definiše kao finalna na sledeči način: final class nekaKlasa { ......... } Da smo u prethodnom primeru klasu Osoba deklarisali kao final, ne bismo mogli da iz nje izvedemo podklase Student i Osoba. Opseg vidljivosti promenljive Kada deklarišete promenljivu ona ima ograničen opseg vidljivosti. Opseg odreĎuje gde ta promenljiva može da bude korišćena. Lokalne promenljive su vidljive samo unutar bloka u kome su deklarisane. Promenljive instance su deklarisane unutar klase, pa svi metodi klase mogu
da koriste.
ih
Kada pozivate neku promenljivu unutar definicije metode, Java prvo traži deklaraciju klase unutar bloka u kome se poziva, zatim u nekom spoljašnjem bloku sve do definicije samog metoda. Ukoliko ta promenljiva nije lokalna, Java dalje proverava da li je deklarisana unutar definicije klase, a na kraju i u nadklasama. Zbog toga je moguće imati nekoliko promenljvih sa istim imenom, ali deklarisanih na različitim nivoima (blokovima). Ovo često dovodi do nečitljivosti koda i grešaka, pa takve situacije treba izbegavati. Pogledajte sledeći primer: 1:class TestVidljivosti { 2: int test = 10; 3: void printTest () { 4: int test = 20; 5: System.out.println("test = " + test); 6: } 7: 8: public static void main (String args[]) { 9: TestVidljivosti st = new TestVidljivosti(); 10: st.printTest(); 11: } 12:} U ovoj klasi postoje dve promenljive test sa istim imenom i definicijom. Prva je objektna promenljiva i ima vrednost 10. Druga je lokalna promenljiva i ima vrednost 20. Lokalna promenljiva sakriva promenljivu instance, pa println() metod štampa vrednost 20. Kontrolisanje pristupa
Ukoliko se eksplicitno ne navede, podrazumevana zaštita u Javi je zaštita na nivou paketa. To znači da će promenljivima (i metodima) jedne klase moći da pristupe sve klase u okviru jednog paketa, ali ne i izvan njega. Iako u okviru jedne klase može biti deklarisano mnoštvo promenljivih i metoda, nisu svi podjednako korisni onome ko tu klasu koristi. Neke od promenljivih možda služe samo za neka izračunavanja unutar same klase. Promena neke od njih može i da naruši funkcionisanje objekata te klase. Zbog toga je često neophodno ograničiti pristup nekim od promenljivih ili metoda.
Nivo zaštite promenljivih, metoda reči public, private iprotected.
i
klasa
u
Javi
se
definiše
pomoću
ključnih
private Ovo je najveći nivo zaštite. Promenljive i metodi deklarisani kao private su vidljivi samo u unutar klase u kojoj su definisani. Zbog toga se privatne promenljive i metodi ne nasleĎuju. private boolean writersBlock = true; Deklarisanjem nekih metoda i promenljvih kao private na odreĎeni način ograničava funkcionalnost klase na samo one elemente koji želite da budu vidljivi spolja. Na ovaj način klasa postaje i lakša za korišćenje, obzirom da onaj ko je koristi ne mora da zna ništa o njenom unutrašnjem funkcionisanju. Cela klasa ne može biti deklarisana kao private. Generalno pravilo je da sve objektne promenljive budu privatne, a da se napišu metodi koji nisu privatepomoću kojih je moguće pristupiti ovim promenljivim. public Ovo je najmanji nivo zaštite, potpuno suprotan od private. Promenljive, metodi i klase koji su deklarisani kao public su vidljivi svuda, u svim klasama unutar paketa, pa čak i izvan paketa. public boolean writersBlock = true; protected Promenljive i metodi deklarisane kao protected su vidljive svuda unutar paketa, a izvan paketa samo iz podklase. Naziv jedinice: Metodi
Materijali vezani uz ovu lekciju: - Test metodi - Metodi (PDF dokument)
METODI Kreiranje metoda Metodi definišu ponašanje objekta – šta se dešava kada se objekat kreira, koje operacije mogu biti preduzete nad objektom i slično. Samo definisanje metoda ima četiri osnovna dela: ime metoda tip objekta ili primitivni tip koji metod vraća listu argumenata telo metoda
Kombinacija prva tri elementa (ime, tip, i argumenti) mora da bude jedinstvena. Drugim rečima, možete da imate više metoda koji se isto zovu i imaju isti tip, ali u tom slučaju lista argumenata mora biti različita. Ova osobina se zove „method overloading“ (pretrpanost metodima) i o njoj će biti više reči kasnije. Dakle, osnovna sintaksa definicije metoda bi bila: tipMetoda imeMetoda (tip1 arg1, tip2 arg2, tip3 arg3...) { ..... } Argumenti metoda deklarisani na prethodni način postaju lokalne promenljive unutar tela metoda i nije ih potrebno posebno deklarisati. Njihove vrednosti su vrednosti koje su prosleĎene metodu prilikom njegovog pozivanja. Ukoliko metod ne vraća nikakvu vrednost, umesto imena tipa koristi se ključna reč void. Ukoliko metod vraća neku vrednost, tada je neophodno negde u telu metoda koristiti naredbu return, koja prosleĎuje tu vrednost. Pogledajte sledeći primer klase Opseg koja definiše metod napraviNiz(). Ovaj metod uzima dva broja kao argumente i kreira niz koji sadrži sve cele brojeve koji se nalaze izmeĎu ova dva broja. 1:class Opseg { 2: int[] napraviNiz(int donja, int gornja) { 3: int niz[] = new int[ (gornja - donja) + 1 ]; 4: for (int i = 0; i < niz.length; i++) { 5: niz[i] = donja++; 6: } 7: return niz; 8: } 9: 10: public static void main(String arg[]) { 11: int niz[]; 12: Opseg noviOpseg = new Opseg(); 13: niz = noviOpseg.napraviNiz(1, 10); 14: System.out.print("Niz: [ "); 15: for (int i = 0; i < niz.length; i++) { 16: System.out.print(niz[i] + " "); 17: } 18: System.out.println("]"); 19: } 20:} U liniji 13 poziva se metod napraviNiz() klase Opseg. Ovom metodu se prosleĎuju vrednosti 1 i 10 kao donja i gornja granica niza. Ove vrednosti bivaju smeštene u promenljive donja i gornja deklarisane u definiciji metoda. Niz koji on vraća nakon izračunavanja se dodeljuje promenljivoj niz, a zatim se u okviru for petlje ispisuju vrednosti elemanata ovog niza.
Prosleđivanje argumenata metodu Ukoliko se kao argumenti prosleĎuju promenljive primitivnog tipa, u stvari se prosleĎuju samo vrednosti tih promenljivih. Bilo kakva promena ovih vrednosti unutar definicije metoda ne izaziva promenu originalnih promenljivih. Sa objektima je stvar drugačija. Ukoliko prosleĎujete promenljivu koja sadrži objekat, prosleĎuje se njena referenca. To znači da će bilo kakva promena nad objektom unutar definicije metoda uticati na originalan objekat. Klasni metodi Slično kao i klasne promenljive, klasni metodi se definišu pomoću ključne reči static i dostupni su bilo kom objektu te klase, a mogu biti dostupni i drugim klasama. Zbog toga neki klasni metodi mogu biti korišćeni bilo gde, bez obzira da li postoji instanca te klase. U prethodnoj lekciji smo imali takav primer: int iBroj1 = Integer.valueOf(sBroj1).intValue(); Ovde je pozivan klasni metod valueOf() klase Integer, bez da smo prethodno kreirali objekat te klase. U praksi se ovakvo pozivanje često koristi. Na primer, klasa Math sadrži različite metode za različite matematičke operacije. Obično se ovi metodi pozivaju direktno, bez kreiranja objekta tipa Math. float root = Math.sqrt(453.0); Da biste jedan metod definisali kao klasni, koristite ključnu reč static, kao i kod klasnih promenljivih. static nekiTip nekiMetod (tip1 arg1, tip2 arg2, ...) { ..... } Metodi definisani kao final Kao i promenljive i klase, i metodi mogu bit definisani pomoću ključne reči final. Kod metoda, ova ključna reč znači da taj metod ne može biti preklopljen nekim unutar podklase. Ključna reč final se u definiciji metoda ubacuje posle modifikatora zaštite, a pre tipa metoda. public final void finalniMetod() { ... }
Privatni metodi, kao i metodi definisani unutar klasa koje su final, su već finalni, pa ih nije potrebno deklarisati kao final.
Metod main() Aplikacije su Java programi koji mogu da se izvršavaju samostalno, za razlliku od apleta koji zahtevaju neki browser da bi se izvršili. Java aplikacije se sastoje od jedne ili više klasa. Neophodno je da jedna od tih klasa bude početna. Ova klasa mora da ima metod main(), sa kojim ste se do sada već susretali. Pravilo je da je metod main() početni metod svake Java aplikacija. Definicija ovog metoda uvek izgleda ovako: public static void main(String args[]) {…} -
public znači da je ovaj metod dostupan drugim metodama i klasama. Ovaj metod mora biti deklarisan kao public static znaši da je ovo metod klase void znači da ovaj metod ne vraća nikakvu vrednost argument ovog metoda je niz stringova. Ovaj niz se koristi za preuzimanje argumenata prilikom pozivanja aplikacije iz komandne linije ili od strane neke druge aplikacije
Imajte na umu da je ovo klasni metod, što znači da nije kreiran objekat klase koja ga sadrži automatski prilikom njegovog pozivanja. Ukoliko želite da koristite objekat te klase, morate sami da ga kreirate unutar tela metoda. Iako u okviru aplikacije možete imati nekoliko klasa, pri čemu svaka od njih može imati svoj main() metod, samo se metod main() početne klase izvršava, dok se ostali ignorišu.
Methods overloading Izraz „methods overloading“ (pretrpanost metodima) se odnosi na kreiranje višestrukih metoda sa istim imenom, ali različitom definicijom. Sa ovim ste se već susreli prilikom pozivanja konstruktora String() iDate(). U klasam String i Date postoji nekoliko metoda konstruktora sa istim imenom. U zavisnosti koji argumenti su prosleĎeni prilikom pozivanja, Java poziva onaj metod koji može da te argumente i obradi. Da biste kreirali overloaded metode, jednostavno definišite nekoliko metoda sa istim imenom i tipom, a različitom listom argumenata. Java ovakve metode razlikuje upravo po listi argumenata, a ne po tipu samog metoda. Tako nije moguće imati dva metoda istog imena i istih argumenata, a različitog tipa. TakoĎe, prilikom kreiranja overloaded metoda imena argumenata nisu relevantna, samo njihov broj i tip.
Konstruktor Metodi konstruktori su metodi koji se koriste da bi inicijalizovali novi objekat klase, kada je on kreiran. Konstruktori se razlikuju od ostalih metoda u nekoliko stvari: -
pozivaju se pomoću ključne reči new prilikom kreiranja novog objekta uvek imaju isto ime kao i klasa ne vraćaju nikakvu vrednost
Pogledajte sledeći primer. 1: public class Osoba { 2: static String imeFakulteta = "BARN"; 3: String ime; 4: String prezime; 5: String jmbg; 6: int godine; 7: 8: Osoba(String i, String p, int g) { 9: ime = i; 10: prezime = p; 11: godine = g; 12: } 13: 14: void prikaziOsobu() { 15: System.out.println("Zdravo. Ja sam " + ime); 16: System.out.println("Imam " + godine + " godine"); 17: } 18:} Klasa Osoba ima dva metoda. Prvi je konstruktor, definisan u linijama 5-8, koji inicijalizuje objektne promenljive ime i godine vrednostima koje su mu prosleĎene prilikom kreiranja objekta. Drugi je objektni metod koji ispisuje podatke o osobi. Obzirom da je moguće imati nekoliko konstruktora koji na različit način inicijalizuju objekat, često se ukazuje potreba da jedan konstruktor poziva drugi. Da biste pozvali konstruktor trenutne klase, koristite ključnu reč this kao da je ime metoda koji želite da pozovete sa odgovarajućim argumentima. Pogledajte primer konstruktora Date() klase Date. public Date() { this(System.currentTimeMillis()); } Ovaj konstruktor poziva konstruktor Date(long date) i prosleĎuje mu trenutno vreme. Preklapanje metoda Slično kao i kod promenljivih, i prilikom pozivanja metoda Java prvo traži definiciju metoda unutar klase objekta koji ga poziva. Ukoliko ne pronaĎe odgovarajuću definiciju, Java prosleĎuje poziv prvoj nadklasi, dok god metod ne bude pronaĎen. Na taj način je obezbeĎeno nasleĎivanje metoda, pa nije potrebno duplirati kod ukoliko je metod već definisan u nadklasi.
MeĎutim, ponekad ćete želeti da se objekat podklase drugačije ponaša od objekta nadklase. Tada možete u okviru podklase da definišete metod sa istim imenom, tipom i argumentima, ali sa različitim funkcionisanjem. Ovaj postupak se naziva preklapanje metoda. Sa konstruktorima je stvar malo drugačija. Obzirom da konstruktori imaju isto ima kao i klasa, nije moguće da preklopite jedan konstruktor drugim. Ukoliko želite da iskoristite funkcionalnost konstruktora nadklase, možete da ga pozovete pomoću ključne reči super. U prethodnom primeru podklasu Student.
smo
definisali
klasu Osoba.
Sada
ćemo
definisati
njenu
1:class Student extends Osoba{ 2: static int brojStudenata=0; 3: int godinaUpisa; 4: int godinaStudija; 5: int brojPolozenihIspita; 6: 7: Student(String i, String p, int g, int gs) { 8: super(i,p,g); 9: godinaStudija = gs; 10: brojStudenata +=1; 11: } 12: void prikaziOsobu() { 13: System.out.print("Zdravo. Ja sam " + ime + " " + prezime + "."); 14: System.out.println(" Upisao sam fakultet " + godinaStudija + ". godine."); 15: System.out.println("Imam " + godine + " godine"); 16: } 17:} U ovom primeru imamo klasu Student koja je u stvari podklasa klase Osoba. to znači da nasleĎuje njene atribute i ponašanja (promenljive i metode). Promenljive ime i godine nismo ponovo kreirali, jer ćemo koristiti one nasleĎene iz klase Osoba. MeĎutim, metod prikaziOsobu() smo definisali drugačije u klasiStudent i time preklopili originalni metod. U okviru konstruktora klase Student koristimo originalni konstruktor klase Osoba (linija 8) pomoću ključne reči super. Ključna reč this Ukoliko u okviru definicije metoda želite da pristupite trenutnom objektu, onom na koji se metod i odnosi, koristite ključnu reč this. t = this.x; this.nekiMetod(this); return this; U većini slučajeva ključna reč this može da se izostavi, ukoliko ne postoje lokalne promenljive sa istim imenom.
Imajte na umu da je this referenca na trenutnu instancu klase, pa zbog toga može biti korišćena jedino u metodama instance. Klasni metodi ne mogu da je koriste. Metod finalize() Ovaj metod se poziva neposredno pre nego što garbage collector uništi objekat. Klasa Object ima metod finalize() koji ne radi ništa. Ovaj metod nasleĎuju i sve ostale klase koje se kreiraju. Ukoliko ipak želite da nešto bude uraĎeno pre uništavanja objekta, možete da preklopite ovaj metod. Metodfinalize() ima sledeću isntaksu: protected void finalize() throws Throwable { //neki kod } Naziv jedinice: Apstraktne klase, metodi i interfejsi
Materijali vezani uz ovu lekciju: - Test apstraktne klase, metodi i interfejsi - Apstraktne klase, metodi i interfejsi (PDF dokument)
Apstraktne klase Kada ureĎujete klase u hijerarhiju nasleĎivanja, obično su “više” klase apstraktnije i uopštenije, dok su “niže” klase konkretnije i specifičnije. Često polazna klasa i nema instance, već služi kao izvor informacija koje podklase koriste. Ovakve klase se nazivaju apstraktnim i deklarišu se pomoću ključne reči abstract. Definicija apstraktne klase izgleda ovako: public abstract class nekaKlasa { .......... } Apstraktne klase ne mogu da imaju objekte. Ukoliko pokušate da kreirate instancu apstraktne klase, izazvaćete grešku kompajlera. MeĎutim, one mogu da sadrže sve što i normalne klase, uključujući klasne i objektne promenljive i metode sa bilo kojim nivoom zaštite. Apstraktni metodi Apstraktni metodi su metodi kod kojih je definisano ime, tip i lista argumenata, ali ne i konkretna implementacija. Podklase klase koja sadrži apstraktni metod moraju da obezbede njegovu implementaciju. Ovi metodi pružaju mogućnost da se neke generalne informacije čuvaju u nadklasi, a da ih podklase koriste na različite načine.
Apstraktni metodi se deklarišu pomoću ključne reči abstract, koja u definiciji metoda uvek sledi iza modifikatora zaštite. Apstraktni metodi mogu da postoje samo u apstraktnim klasama. Oni nemaju telo i ne mogu biti pozivani. Tako smo klasu Osoba mogli da definišemo kao apstraktnu i u tom slučaju ne bismo mogli da kreiramo objekat tipa Osoba. TakoĎe, metod prikaziOsobu() može biti deklarisan kao abstract, obzirom da u podklasama Student i Predavac imamo njegovu konkretnu implementaciju. public abstract class Osoba { static String imeFakulteta = "BARN"; String ime; String prezime; String jmbg; int godine; Osoba(String i, String p, int g) { ime = i; prezime = p; godine = g; } abstract void prikaziOsobu(); } Interfejsi Hijerarhija klasa obezbeĎuje jednostruko, linijsko nasleĎivanje. Jedna klasa može da ima samo jednu nadklasu od koje nasleĎuje atribute i ponašanje. MeĎutim, često je potrebno obezbediti način da jedna klasa nasledi više različitih unapred definisanih ponašanja. Java rešava ovaj problem pomoću hijerarhije interfejsa. Java interfejs je kolekcija apstraktnih metoda (ponašanja) koji mogu biti iskombinovani u bilo kojoj klasi da bi obezbedili ponašanje koje njena nadklasa ne obezbeĎuje. Interfejs sadrži samo apstraktne definicije metoda i konstante, a ne i objektne promenljive niti implementacije metoda. Interfejsi se koriste kada se očekuje da neko ponašanje bude obezbeĎeno od strane više različitih klasa. Kreiranje interfejsa Interfejsi se definišu korišćenjem ključne reči interface: interface imeInterfejsa { ... telo interfejsa } Modifikatori koji mogu da se koriste za interfejse su public i abstract. Modifikator abstract se podrazumeva, tj. svaki interfejs je sam po sebi apstraktan tako da nije neophodno to i eksplicitno navesti. Unutar tela metoda navode se definicije promenljivih i metoda, ali sa odreĎenim ograničenjima. Promenljive mogu biti deklarisane samo kao public static final, što praktično znači da unutar tela interfejsa možete da imate deklarisane samo konstante. Metodi mogu
da budu deklarisani samo kaopublic abstract. Pokušaj dodeljivanja drugih modifikatora promenljivoj ili metodu rezultuje greškom kompajlera. public interface Grad { public static final String drzava=”Srbija”; public abstract void prikaziGrad(); } Interfejsi takoĎe mogu da nasleĎuju atribute i ponašanja od drugih interfejsa, tj. jedan interfejs može da ima svoje podinterfejse public interface Adresa extends Grad { public abstract void prikaziUlicu(); public abstract void prikaziBroj(); } TakoĎe, jedan interfejs može da nasledi nekoliko drugih. Na primer public interface Adresa extends Grad, Selo { ........... } Korišćenje interfejsa Ukoliko želite da neka klasa koristi interfejs, upotrebite ključnu reč implements na sledeći način public class NekaKlasa implements NekiInterfejs { .......... } Obzirom da interfejsi sadrže samo apstraktne definicije metoda, neophodno je da klasa koja koristi odreĎeni interfejs implementira sve metode tog interfejsa. Za razliku od korišćenja apstraktnih klasa, ukoliko koristite interfejs vaša klasa mora da implementira sve metode koji su definisani u njemu. U hijerarhiji klase jedna klasa mogla je da nasledi samo jednu nadklasu. Sa interfejsima je stvar drugačija. Jedna klasa može da uključi proizvoljno mnogo interfejsa razdvojenih zarezom public class Skola implements Adresa, Institucija { .......... } Ukoliko uključite više interfejsa, moguće je da dva ili više njih imaju definisan isti metod. Ukoliko je metod definisan na isti način, tada je dovoljno da klasa implementira ovaj metod i da budu zadovoljena oba interfejsa. Ako se metodi razlikuju u listi parametara, tada unutar klase treba implementirati oba metoda (slučaj pretrpanosti metoda). MeĎutim, problem nastaje ako se metodi razlikuju po tipu. Tada nije moguće uključiti oba interfejsa. U ovakvim slučajevima bi trebalo preispitati dizajn čitave aplikacije. Interfejse je moguće koristiti i prilikom deklarisanja promenljivih, na isti način kao i klase. Na primer
Adresa Zgrada1 = new Skola(); Adresa Zgrada2 = new DomZdravlja(); Kada je promenljiva deklarisana kao interfejs, to znači da može da ukazuje na objekat bilo koje klase koja implementira taj interfejs. Interfejsi se često koriste i za čuvanje skupa konstanti koje ostale klase mogu da koriste.
Naziv jedinice: Paketi
Materijali vezani uz ovu lekciju: - Test paketi - Paketi (PDF dokument)
Paketi Paketi su način na koji se organizuju klase. Jedan paket može da sadrži proizvoljan broj klasa koje su na neki način slične (po nameni, oblasti, nasleĎivanju i sl.). Paketi su korisni iz više razloga: omogućavaju organizovanje klasa u jedinice, slično kako se direktorijumi koriste za organizaciju fajlova smanjuju probleme sa konfliktima imena, obzirom da omogućavaju da jedna klasa bude sakrivena unutar paketa pružaju mogućnost zaštite klasa, promenljivih i metoda Paketi, sem klasa, mogu da sadrže i druge pakete, i time omogućuju još jedan vid hijerarhije. Biblioteka postojećih klasa u Javi je organizovana na taj način. Osnovni nivo je paket java, a unutar njega paketiio, net, util i awt. awt paket, na primer, ima i svoje podpakete. Obično se, po konvenciji, osnovni nivo koristi za identifikaciju autora tog paketa, pa tako imamo paketesun, netscape i sl. Korišćenje paketa Postoji nekoliko načina da koristite klasu nekog paketa. Ukoliko klasa pripada paketu java.lang, kao npr. klasa System, jednostavno koristite ovu klasu bez eksplicitnog pozivanja samog paketa. Kao što je već napomenuto, klase ovog paketa su automatski dostupne. Ukoliko klasa pripada nekom drugom paketu, možete je pozvati koristeći njeno puno ime, koje uključuje i pakete u kojima se nalazi (npr. java.awt.Font)
java.awt.Font f= new java.awt.Font(); Ukoliko često koristite klase iz drugih paketa, možete da uvezete te klase ili ceo paket u vaš program pomoću komande import. Individualnu klasu uvozite na sledeći način import java.util.Vector; TakoĎe, možete da uvezete ceo paket na sledeći način import java.awt.*; Asteriks na kraju ove naredbe ne znači da će biti uvezene sve klase ovog paketa, već samo one koje se i pozivaju u programu i koje su definisane kao public. Ova komanda takoĎe neće uvesti ni podpakete koje dati paket može da sadrži. Komanda import u izvornom fajlu mora da se nalazi na samom početku, ispred definicije klase, ali nakon definicije paketa, o čemu će biti reči kasnije. Konflikti imena Nakon što ste uvezli jednu klasu ili paket klasa, obično ovim klasama možete da pristupate po njihovom imenu, bez eksplicitnog navoĎenja imena paketa. MeĎutim, ukoliko u paketima koje ste uvezli postoji nekoliko klasa sa istim imenom, tada je neophodno da navedete celu putanju do klase. Recimo da ste uvezli dva paketa, barn i singidunum, i da oba ova paketa sadrže klasu Student. Tada bi sledeća komanda Student s= new Student(); izavala grešku kompajlera, obzirom da nije navedeno na koju klasu Student se misli; da li onu u okviru paketa barn ili u okviru paketa singidunum. U tom slučaju, ovu klasu bi bilo moguće pozvati kao barn.Student s= new barn.Student(); Lociranje klase Da bi Java mogla da koristi neku klasu, neophodno je da može da je locira u sistemu fajlova na računaru. Tom prilikom Java koristi ime samog paketa i direktorijume koji se nalaze u CLASSPATHpromenljivoj. Ime paketa odgovara imenu direktorijuma u sistemu fajlova, pa se tako klasa java.applet.Applet nalazi u java/applet direktorijumu. Kada koristite neku klasu u svom kodu, Java traži odgovarajući paket i klasu u direktorijumima navedenim u CLASSPATH promenljivoj, kao i u tekućem direktorijumu. Ukoliko ne može da naĎe odgovarajuću klasu, doći će do greške. Kreiranje paketa
Prva stvar kod kreiranja paketa je izbor odgovarajućeg imena. Postoje odreĎene konvencije za to. U svakom slučaju, ime treba na neki način da ukazuje ili na autora ili na sadržaj samog paketa. Za razliku od imena klasa, ime paketa mora da bude jedinstveno. Ne mogu da postoje dva paketa sa istim imenom. Obično se imena paketa pišu malim slovima, kako bi se jasno razlikovala od imena klasa. Nakon toga, neophodno je da imate kreiranu putanju direktorijuma koja odgovara imenu paketa. Na primer, za paket koji se zove edu.barn.dl mora biti kreirana putanja edu/barn/dl, a tek unutar direktorijuma dl mogu biti smeštene klase tog paketa. Dobra vest je da većina razvojnih okruženja, pa iJBuilder kreira ove putanje za vas, meĎutim treba biti obazriv sa kopiranjem i premeštanjem ovih fajlova i direktorijuma. Ukoliko su prethodna dva uslova ispunjena, tada je potrebno na početak koda svake klase koja treba da pripada paketu ubaciti komandu package. Ovu komandu ste već viĎali. Njena sintaksa izgleda ovako
package mojeklase; ili package edu.barn.dl; Ova komanda mora da se nalazi na samom početku klase. Postupak kreiranja paketa je znatno olakšan u JBuilder-u. Prilikom otvaranja samog projekta, JBuilderkreira direktorijum koje je nazvan kao i sam projekat. Kada kreirate novu klasu u projektu, JBuilder će vas pitati i za ime paketa u okviru koga će se klasa nalaziti i sam ubaciti komandu package u kod klase.
Naziv jedinice: Obrada izuzetaka
Materijali vezani uz ovu lekciju: - Test obrada izuzetaka - Obrada izuzetaka (PDF dokument)
Java izuzeci Koliko god se trudili da, kao dobar programer, napišete program koji nema greške, koji nikada neće neočekivano prestati da radi i koji će moći da se izbori sa svakom nepredviĎenom situacijom, na žalost nećete uspeti. U realnosti greške se dešavaju, bilo zbog toga što programer nije predvideo svaku moguću situaciju ili zbog toga što su te situacije izvan kontrole programera. Java obezbeĎuje način da se sa tim situacijama izborite pomoću izuzetaka. U trenutku kada se desi neka nepredviĎena situacija, Java proizvodi izuzetak ( exception). Izuzeci u Javi su objekti, instance klasa koje nasleĎuju klasu Throwable. Dakle, kada se desi nepredviĎena situacija,
Java kreira objekat tipaThrowable. Ova klasa ima dve podklase, Error i Exception. Objekti klase Error su interne greške u Java okruženju (virtuelnoj mašini). One su retke i obično fatalne i njima se nećete baviti. Klasa Exception je iz programerskog ugla daleko interesantnija i korisnija. Podklase klase Exception mogu se podeliti u dve grupe: izuzeci za vreme izvršavanja (kao što su ArrayIndexOutofBounds, SecurityException ili NullPointerException) ostali izuzeci (kao što su EOFException i MalformedURLException) Prva grupa izuzetaka obično nastaje zbog loše napisanog koda. Druga grupa izuzetaka nastaje kada se nešto nepredviĎeno dogodi, na primer kada čitate iz fajla koji se završi pre nego očekujete ili ukoliko je korisnik uneo loš format podatka (na primer URL koji nije odgovarajućeg formata). Većina izuzetaka se nalazi u paketu java.lang, ali ima ih i u drugim paketima (java.io i java.net) Obrada izuzetaka Ukoliko koristite metode koji proizvode izuzetke, neophodno je da te izuzetke i obradite u svom kodu. Ukoliko to ne učinite, kompajler će javiti grešku. Izuzeci se obraĎuju pomoću naredbi try i catch.
try {
// neki kod koji moze // da proizvede izuzetak e
} catch (nekiIzuzetak e) { // kod koji se izvrsava ako se izuzetak javi } Ovaj blok naredbi praktično znači “probaj da izvršiš neki kod, a ako se pojavi izuzetak uradi nešto drugo”. Ukoliko se izuzetak pojavio, biće kreiran objekat neke od podklasa klase Exception i izvršavaće se kod u catch bloku. To znači da ćete u okviru catch bloka moći da koristite metode klase Exception. Svi izuzeci nasleĎuju klasu Exception. Zato će prethodni kod biti u stanju da obradi bilo koji izuzetak ukoliko koristitecatch (Exception e). MeĎutim, ukoliko želite da različite podklase izuzetaka obraĎujete na različite načine,možete da koristite nekoliko catch blokova.
try {
// neki kod koji moze // da proizvede izuzetke e1, e2 i e3
} catch (nekiIzuzetak1 e1) { // kod koji se izvrsava ako se javi izuzetak e1 } catch (nekiIzuzetak2 e2) { // kod koji se izvrsava ako se javi izuzetak e2 } catch (nekiIzuzetak3 e3) { // kod koji se izvrsava ako se javi izuzetak e3 } U prethodnim primerima izvršiće se ili blok try ili deo bloka try i blok catch. Ukoliko postoji nešto što je neophodno da se izvrši bez obzira da li se izuzetak pojavio ili ne, koristite naredbu finally. Na primer
NekiFajl f = new NekiFajl(); if (f.open("ime fajla")) { try { UradiNesto(); } catch (IOException e) { // obradi greške } finally { f.close(); } } Deklarisanje metoda koji prozvode izuzetke Ukoliko pišete neki metod i očekujete da mogu da se pojave sitaucije u kojima izvršavanje metoda ne bi uspelo, možete da proizvedete izuzetak pomoću klauzule throws i na taj način obezbedite da potencijalni korisnici vašeg metoda moraju da obrade taj izuzetak. Sintaksa je sledeća
public tipMetoda NekiMetod() throws Izuzetak1, Izuzetak2 { ........ } Naredba throws samo govori da metod može da proizvede izuzetak, a ne da će on to zaista i da učini. Izuzetke tipa Error, kao i izuzetke za vreme izvršavanja ne morate da proizvodite eksplicitno, obzirom da se već pretpostavlja da oni mogu da se pojave bilo gde. Dobar primer za to je OutOfMemoryError, koji može da se desi na bilo kom mestu u programu i bilo kada i nemoguće ga je predvideti. Ukoliko ipak navedete neki od ovih izuzetaka, korisnici neće biti obavezni da ih obrade. Obavezno je obraditi samo one izuzetke koji ne spadaju u navedene dve grupe. Prosleđivanje izuzetaka Naredbu throws možete da koristite i u drugom slučaju. Ukoliko vaš metod koristi neki drugi metod koji može da proizvede izuzetak, tada ste u obavezi i da ga obradite. MeĎutim, ukoliko ne želite da to učinite u tekućem metodu, možete da ga prosledite dalje. Recimo da pišete metod procitajFajl() na sledeći način
public void procitajFajl(imeFajla) { // pozivanje metoda koji otvara fajl // i koji moze da proizvede izuzetak otvoriFajl(imeFajla); // uradi nesto sa fajlom ............. } i pretpostavimo da metod otvoriFajl() može da proizvede izuzetak, na primer ukoliko fajl ne postoji. Tada bi kompajler javio grešku za prethodni kod, obzirom da nigde niste obradili mogući izuzetak. MeĎutim ukoliko upotrebite naredbuthrows na sledeći način
public void procitajFajl(imeFajla) throws Izuzetak { // pozivanje metoda koji otvara fajl
}
// i koji moze da proizvede izuzetak otvoriFajl(imeFajla); // uradi nesto sa fajlom .............
tada vaš metod procitajFajl() preuzima izuzetak metoda otvoriFajl() i prosleĎuje ga nekom drugom metodu u okviru koga je pozvan. Proizvođenje izuzetaka Samo deklarisanje da metod proizvodi izuzetak pomoću naredbe throws znači da je moguće da izuzetk bude proizveden. MeĎutim da bi se to zaista i desilo, u telu metoda morate zaista i da ga proizvedete. Obzirom da su svi izuzeci objekti klase Exception, neophodno je kreirati novi objekat pomoću ključne reči throw.
throw new ServiceNotAvailableException(); U zavisnosti koji tip izuzetaka koristite, konstruktor klase može da ima i argumente.
throw new ServiceNotAvailableException(“Baza nije dostupna”); Onog momenta kada u telu metoda proizvedete izuzetak, metod se napušta, bez izvršavanja daljeg kod (sem onog u bloku finnaly, ako postoji) i bez vraćanja bilo kakve vrednosti. Kreiranje izuzetaka Kao što je već rečeno, izuzeci su klase. Prema tome, da biste kreirali svoj izuzetak, jednostavno treba da kreirate klasu. Ova klasa bi trebala da nasledi neku od postojećih, pa odaberite onaj od postojećih izuzetaka koji je najbliskiji vašem. Na primer, ukoliko pravite izuzetak za loš format ulaznog fajla, bilo bi logično da on nasledi klasu IOException. Obično klase izuzetaka imaju dva konstruktora, jedan bez argumenata i jedan sa jednim String argumentom. Ovaj string predstavlja poruku koja objašnjava zbog čega je došlo do izuzetka. Zbog toga se u okviru ovog drugog konstruktora poziva metod super(), kako bi ta poruka bila obraĎena i da bi kasniije mogla da bude pročitana pomoću metoda koje klasa Throwable obezbeĎuje. Na primer,
public class MojPrviIzuzetak extends Exception { public MojPrviIzuzetak() {} public MojPrviIzuzetak(String poruka) { super(poruka); } } Naziv jedinice: Rad sa fajlovima
Materijali vezani uz ovu lekciju: - Test rad sa fajlovima
- Rad sa fajlovima (PDF dokument)
Klasa File
Do sada, ulazne i izlazne podatke smo preuzimali i upisivali pomoću tokova. Tokovi se, kao što ste videli, koriste za čitanje i upisivanje podataka u najrazličitije destinacije, pa i u fajlove. MeĎutim tokovi, sem čitanja i upisivanja podataka, ne podržavaju ostale uobičajene operacije sa fajlovima. U te svrhe koristićemo klasu File. Ova klasa se nalazi u paketu java.io.
File klasa omogućava pisanje koda nezavisnog od platforme, koji manipuliše fajlovima i direktorijumima.
Objekti ove klase ne predstavljaju same fajlove, već njihova imena. Sam fajl sa tim imenom ne mora čak ni da postoji. File objekat sadrži string koji predstavlja ime fajla ili ime direktorijuma. Ovaj string se nikada ne menja za jedan objekat, dok god on postoji.
File klasa implementira mnoštvo važnih metoda koji mogu da provere postojanje, mogućnost čitanja i pisanja, tip, veličinu i vreme modifikovanja fajlova i direktorijuma, kao i da prave nove, menjaju imena postojećim i brišu fajlove i direktorijume.
Ime jednog fajla može imati različite verzije. File klasa vam dopušta da koristite bilo koju od njih. Pogledajte sledeći primer.
1:import java.io.*; 2: 3:public class TestFajl { 4:
public static void main(String[] args) {
5:
File a = new File ("test.txt");
6:
File b = new File ("FajlB" + File.separator+ "testB.txt");
7:
System.out.println ("a.toString() = " + a.toString() +
8: 9:
"; b.toString() = " + b.toString()); System.out.println ("a.getName() = " + a.getName() +
10:
"; b.getName() = " + b.getName());
11:
System.out.println ("a.getParent() = " + a.getParent() +
12:
"; b.getParent() = " + b.getParent());
13: System.out.println ("a.getAbsolutePath() = " + a.getAbsolutePath() 14: b.getAbsolutePath() = " + b.getAbsolutePath()); 15:
+ ";
}
16:}
Linija 5 kreira novi objekat a tipa File. Ovim je kreirano samo ime fajla, a ne i sam fajl. Linija 6 kreira objekat b tipaFile. Promenljiva File.separator sadrži separator direktorijuma u putanjama fajlova, karakterističan za sistem na kome se program izvršava (npr. '\' za Windows, '/' za UNIX). Linije 7 i 8 koriste metod toString() klase File, koji samo konvertuje objekat u String. Linije 9 i 10 koriste metodgetName() koji vraća ime samog fajla, a ne i direktorijume koji mu prethode. Linije 11 i 12 koriste metod getParent()koji kao vrednost vraća direktorijum u kome se fajl nalazi, ukoliko je ovaj podatak dostupan. Ukoliko nije vraća se vrednost null. Linije 13 i 14 koriste metod getAbsolutePath() koji vraća apsolutnu putanju do fajla, koristeći trenutni radni direktorijum za njeno kreiranje, ukoliko nije navedeno drugačije.
Rezultat izvršavanja ovog programa zavisi od platforme na kojoj se program izvršava, kao i od tekućeg radnog direktorijuma. Jedan od mogućih rezultata bi bio:
a.toString() = test.txt; b.toString() = FajlB\testB.txt a.getName() = test.txt; b.getName() = testB.txt a.getParent() = null; b.getParent() = FajlB a.getAbsolutePath() = F:\BARN\Projekti\Fajlovi\test.txt; b.getAbsolutePath() = F:\BARN\Projekti\Fajlovi\FajlB\testB.txt
Manipulisanje fajlovima
Svi metodi koje smo do sada koristili su vršili različite operacije samo nad imenima fajlova, tj. nad stringovima. Ukoliko se objekat klase File koji ste kreirali odnosi na neki postojeći fajl ili direktorijum, tada su vam na raspolaganju i mnogi drugi metodi pomoću kojih možete da manipulišete fajlovima.
canRead() – testira da li aplikacija može da čita iz navedenog fajla canWrite() – testira da li aplikacija može da upisuje u navedeni fajl createNewFile() – kreira novi, prazan fajl sa navedenim imenom ukoliko fajl sa tim imenom ne postoji delete() – briše fajl sa navedenim imenom exists() - testira da li fajl sa navedenim imenom postoji isDirectory() – testira da li se navedeno ime odnosi na direktorijum isFile() – testira da li se navedeno ime odnosi na fajl lastModified() – kao vrednost vraća vreme kada je fajl poslednji put modifikovan length() – vraća dužinu navedenog fajla list() – vraća niz stringova koji predstavljaju sadržaj navedenog direktorijuma listFiles() – vraća niz stringova koji predstavljaju imena fajlova sadržanih u navedenom direktorijumu mkdir() – kreira direktorijum na navedenoj apsolutnoj putanji mkdirs() – kreira direktorijum na navedenoj putanji, uključujući i sve direktorijume koji mu prethode, a koji ne postoje
renameTo() – menja ime postojećeg fajla ili direktorijuma, meĎutim kreirani objekat File se i dalje odnosi na prvobitni fajl (ime u okviru objekta ostaje nepromenjeno)
RandomAccessFile klasa
Za razliku od klasa FileInputStream i FileOutputStream, koje su omogućavale sekvencijalni pristup fajlovima, klasaRandomAccessFile omogućava čitanje i upisivanje bajtova, teksta i drugih tipova podataka na bilo koju lokaciju u fajlu. Ona ima dva konstruktora:
RandomAccessFile(String ime, String mod) i
RandomAccessFile(File imeFajla, String mod).
Pomoću argumenta mod, fajl može biti otvoren samo za čitanje ("r") ili za čitanje i pisanje ("rw"). Objekat ove klase se uglavnom ponaša kao niz bajtova. U okviru njega postoji tzv. file pointer ili kursor, koji odreĎuje lokaciju na kojoj će se upisivati ili sa koje će se čitati podaci iz fajla. Informacija o poziciji
ovog kursora se dobija pomoću metoda getFilePointer(), dok se pomoću metoda seek() kursor postavlja na odgovarajuću poziciju. U primeru koji sledi upotrebljeni su neki metodi klasa File i RandomAccessFile.
1:import java.io.*; 2:public class TestRandomAccessFile { 3:
public static void main(String[] args) {
4:
boolean daLiJeKreiran = false;
5:
long pozicija = 0;
6:
String linija = "";
7:
File test = new File("test.txt");
8:
try {
9:
// proverava da li fajl vec postoji
10:
if (test.exists()) {
11:
test.delete();
12:
}
13:
// kreira novi, prazan fajl
14:
daLiJeKreiran = test.createNewFile();
15: 16: 17: 18:
if (daLiJeKreiran) { RandomAccessFile otvorenTest = new RandomAccessFile(test,"rw");
19:
pozicija = otvorenTest.getFilePointer();
20:
linija = otvorenTest.readLine();
21:
System.out.println("Procitana linija iz fajla: " +
22: 23:
linija); System.out.println("sa pozicije " + pozicija);
24: 25:
//upisuje se tekst u fajl i
26:
//cita pozicija kursora nakon upisivanja
27:
otvorenTest.writeBytes("Java programiranje");
28:
pozicija = otvorenTest.getFilePointer();
29:
System.out.println("Pozicija nakon upisivanja" +
30:
" teksta u fajl: " + pozicija);
31: 32:
// postavljanje pozicije na pocetak
33:
otvorenTest.seek(0);
34:
pozicija = otvorenTest.getFilePointer();
35:
System.out.println("Pozicija nakon metoda seek(0): "
36:
+ pozicija);
37:
linija = otvorenTest.readLine();
38:
System.out.println("Procitana linija iz fajla: "
39:
+ linija);
40:
System.out.println("sa pozicije " + pozicija);
41:
}
42: 43:
} catch (Exception e) {} }
44:}
Rezultat izvršavanja ovog programa biće:
Procitana linija iz fajla: null sa pozicije 0 Pozicija nakon upisivanja teksta u fajl: 18 Pozicija nakon metoda seek(0): 0 Procitana linija iz fajla: Java programiranje sa pozicije 0 U liniji 7 kreira se novi objekat klase File na osnovu stringa "test.txt". Za sada je kreirano samo ime fajla, a ne i sam fajl. U linijama 10 i 11 proverava se da li fajl test.txt već postoji. Ukoliko je to tačno, fajl se briše. U liniji 14, pomoću metoda createNewFile(), kreira se fajl test.txt. Ovaj metod vraća vrednost true ukoliko je fajl uspešno kreiran.
U liniji 17 kreira se novi objekat klase RandomAccessFile na osnovu objekta test. Primetite da će ovaj objekat, za razliku od tokova, biti korišćen i za čitanje i za upisivanje podataka. Obzirom da do sada ništa nije upisano u fajl, naredbe u linijama 19 i 20 dodeliće vrednosti 0 i null promenljivim pozicija i linija. Ove vrednosti se ispisuju u linijama 21 – 23. U liniji 27 se upisuje tekst u fajl. Obratite pažnju da je pozicija kursora nakon upisivanja 18, što znači da se kursor nalazi na kraju fajla. Ukoliko želite da pročitate ono što je upisano, morate da pomerite kursor na početak fajla. To se postiže pomoću metoda seek() u naredbi 33. Naziv jedinice: Osnove dizajniranja aplikacija
Materijali vezani uz ovu lekciju: - Test osnove dizajniranja aplikacija - Osnove dizajniranja aplikacija (PDF dokument)
Java.awt paket Ukoliko pravite bilo kakvu ozbiljniju aplikaciju, neophodno je da ona ima i svoj korisnički interfejs. Kreiranje korisničkog interfejsa u Javi postiže se korišćenjem klasa paketa java.awt. U njemu se nalaze klase koje odgovaraju različitim kontrolama grafičkog interfejsa i koje obezbeĎuju upravljanje dogaĎajima. Paket AWT se sastoji od osnovnog paketa(java.awt) i četiri podpaketa (java.awt.event, java.awt.image, java.awt.datatransfer i java.awt.peer). Glavni java.awt paket sadrži većinu klasa i interfejsa za kreiranje grafičkog korisničkog okruženja (prozore, menije, dugmad, check polja i dr.). Ovi interfejsi i klase su povezani hijerarhijski. Postoje tri osnovna aspekta ove hijerarhije: -
primitivna grafika fontovi standardni elementi korisničkog interfejsa
Primitivna grafika obuhvata klase i metode paketa java.awt.Graphics, koje omogućavaju iscrtavanje linije, pravougaonika, krugova, elipsa i poligona na ekran. Fontovi se kod većine grafičkih sistema tretiraju kao grafički elementi. U okviru klase java.awt.Font možete da koristite bilo koji od fontova i stilova. Naravno, to ne mora da znači da i korisnik ima odgovarajući font na svom računaru. U tom slučaju font koji ste vi odabrali će biti zamenjen nekim drugim. Imajte to na umu kada birate fontove koji će se prikazivati. Pod standardnim elementima korisničkog interfejsa podrazumevaju se one kontrole koje imate u skoro svim Windowsaplikacijama: meniji, scrollbar-ovi, dugmad, tekstualna polja, check polja i sl. Sve ove kontrole, pa čak i ceo prozor ili prozor za dijalog nasleĎuju jednu osnovnu klasu, Component. Na slici koja sledi je prikazana hijerarhija svih klasa paketa java.awt koji nasleĎuju klasu Component.
U nastavku ovog kursa koristićemo sledeće termine: - kontrola za elemente kao što su labela, tekstualno polje, dugme i sl. - kontejner za sve elemente koji mogu u sebi da sadrže neke druge (paneli, apleti, prozori, dijalozi, okviri i sl.) - komponenta za sve prethodno, tj. za bilo kog naslednika klase Component. Aplikacije sa korisničkim interfejsom Kao što ste do sada videli, sve aplikacije pisane u Javi imaju jednu klasu koja se definiše kao početna, unutar koje postoji metod main(). Ovaj metod se prvi izvršava prilikom pokretanja programa, i on dalje kreira objekte i pokreće metode drugih klasa unutar programa. U Java aplikacijama se korisnički interfejs gradi programski, tj. svi prozori i komponente unutar njih predstavljaju objekte koji se kreiraju unutar koda same aplikacije. Zbog toga se obično unutar main() metoda aplikacije kreira i objekat klase Frame, koji predstavlja glavni prozor aplikacije. import java.awt.*; public class pocetna { public static void main(String[] args) { Frame glavniProzor = new Frame(); glavniProzor.setVisible(true); } } Izvršavanjem prethodnog programa pojaviće se prozor aplikacije. Objekat klase Frame, tj. prozor aplikacije, ukoliko se ne navede drugačije, ima veličinu 0x0, tako da će prethodni kod prikazati samo naslovnu liniju prozora i to bez naslova. Čak ni dugme Close neće imati svoju funkciju. Sve to treba da obezbedite programski. Zbog toga se često u programima ne koristi direktno klasa Frame, već se kreira njena podklasa u kojoj se podešava željeni izgled i funkcionalnost prozora. Tako bismo prethodni kod mogli da proširimo na sledeći način:
1:import java.awt.*; 2:import java.awt.event.*; 3: 4:public class pocetnaFrame extends Frame{ 5: public pocetnaFrame() { 6: enableEvents(AWTEvent.WINDOW_EVENT_MASK); 7: setSize(300, 200); 8: setTitle("Vrlo jednostavna aplikacija"); 9: } 10: 11: // Redefinisan metod kako bi se aplikacija ugasila 12: // pritiskom na Close dugme 13: 14: protected void processWindowEvent(WindowEvent e) { 15: super.processWindowEvent(e); 16: if (e.getID() == WindowEvent.WINDOW_CLOSING) { 17: System.exit(0); 18: } 19: } 20:}
1:import java.awt.*; 2:import java.awt.event.*; 3:public class pocetna { 4: public static void main(String[] args) { 5: pocetnaFrame glavniProzor = new pocetnaFrame(); 6: glavniProzor.setVisible(true); 7: } 8:} Klasa pocetnaFrame predstavlja glavni prozor aplikacije. Ona nasleĎuje klasu Frame. U njenom konstruktoru vrše se neka dodatna podešavanja. Linija 6 omogućava procesiranje dogaĎaja koji će se pojaviti nad ovim prozorom. Linija 7 odreĎuje veličinu prozora (300 x 200 piksela). Linija 8 postavlja naslov prozora. Metod u linijama 14 – 19 je neophodan kako bi se aplikacija završila prilikom zatvaranja njenog glavnog prozora. Klasa pocetna je početna klasa aplikacije u kojoj se kreira novi objekat klase pocetnaFrame (glavni prozor aplikacije). Dodavanje komponenti Prozor prethodne aplikacije ne sadrži ništa sem sopstvenog okvira. Klasa Frame je podklasa klase Container, čiji objekti mogu da sadrže druge komponente. Da biste u okviru vašeg glavnog prozora zaista i imali neke druge komponente, neophodno je da kreirate objekte tih komponenti i da ih dodate u prozor pomoću metoda add(). Na primer, u glavni prozor naše aplikacije mogli bismo da postavimo jedno dugme. Tada bi konstruktor klase pocetnaFrame izgledao ovako:
public pocetnaFrame() { enableEvents(AWTEvent.WINDOW_EVENT_MASK); setSize(300, 200); setTitle("Vrlo jednostavna aplikacija"); Button dugme1 = new Button("OK");
}
add(dugme1);
Ukoliko biste pokrenuli prethodni program sa ovako izmenjenim kontruktorom glavni prozor aplikacije bi izgledao ovako:
Obratite pažnju da je dugme OK prekrilo čitav prostor unutar prozora. Prostorni rasporedi Da biste komponente rasporedili na željeni način, u Javi se koriste tzv. menadžeri prostornog rasporeda (layoutmanager). Oni omogućavaju da se komponente organizuju tako da izgledaju slično na bilo kojoj platformi. Ovi menadžeri se uglavnom kombinuju sa panelima, objektima klase Panel. U okviru jednog prozora možete da postavite nekoliko panela, pri čemu svaki od njih može da ima svoj layout menadžer. U okviru awt paketa postoji pet osnovnih menadžera. Da biste koristili bilo koji od njih, kreirajte objekat odreĎenog menadžera i dodelite ga nekom kontejneru pomoću metoda setLayout(). Nakon toga možete da dodajete komponente u odgovarajući kontejner. Redosled kojim se dodaju komponente u kontejner kao i argumenti koji se koriste prilikom dodavanja utiču na konačan raspored i izgled aplikacije.
FlowLayout raspored
U okviru ovog rasporeda, komponente se dodaju u kontejner jedna po jedna, počevši od gornje leve pozicije. Ovaj menadžer ima i svoje poravnanje unutar jednog reda, pri čemu se podrazumeva da su komponente centralno poravnate ukoliko nije navedeno drugačije. Komponente se postavljaju u redove onim redom kojim su ubačene pomoću metoda add().
GridLayout raspored
Korišćenjem ovog rasporeda, čitava površina panela se deli na ćelije pomoću redova i kolona. Komponente se tada dodaju u ćelije, redom počevši od gornje levo. Prilikom kreiranja rasporeda navodi se broj redova i kolona na koje želite da podelite kontejner. Na primer:
setLayout(new GridLayout(3, 2)); U ovom rasporedu možete da postavite i razmak izmeĎu ćelija
setLayout(new GridLayout(3, 2, 10, 30)); Na ovaj način su ćelije odvojene 10 piksela horizontalno i 30 piksela vertikalno.
BorderLayout raspored
Pomoću ovog rasporeda komponente se postavljaju u kontejner na jednu od pozicija: sever, jug, istok, zapad ili centar. Komponente postavljene po obodu kontejnera zauzimaju onoliko mesta koliko im je potrebno, dok komponenta u centru zauzima sav ostali raspoloživ prostor. Postavljanje ovog rasporeda vrši se na isti način kao i postavljanje prethodnih. Postavljanje samih komponenti se vrši pomoću metoda add() na sledeći način:
TextField tekstPolje = new TextField ("", 50); add(tekstPolje, BorderLayout.NORTH); I BorderLayout raspored može da ima razmak izmeĎu pozicija. On se postavlja na sledeći način:
setLayout(new BorderLayout(10, 10)); CardLayout raspored Kada koristite ovaj raspored, praktično koristite posebne panele koji se prikazuju pojedinačno, pri čemu jedan preklapa drugi. Uvek je vidljiv samo jedan. Korišćenje ovog raporeda obično podrazumeva da imate i neku kontrolu (na primer, dugme ili radio dugmad) koje vam omogućavaju da prelazite sa jednog na drugi panel pomoću metoda show().
GridBagLayout raspored
Ovaj prostorni raspored vam omogućava najveću kontrolu nad postavljanjem komponenti. Kada koristite ovaj raspored, praktično koristite dve klase GridBagLayout, koji organizuje ceo prostor kontejnera, i GridBagConstraints koji definiše osobine svake komponente u mreži – njen položaj, dimenzije, poravnanje itd. Korišćenje ovog rasporeda odvija se u nekoliko koraka: -
kreiranje GridBagLayout objekta i njegovo postavljanje za menadžera rasporeda pomoću metoda setLayout() kreiranje objekta GridBagConstraints podešavanje osobina komponente prosleĎivanje informacije o komponenti menadžeru dodavanje komponente u panel
Jedna ćelija može da sadrži samo jednu komponentu, dok jedna komponenta može da se nalazi unutar nekoliko ćelija. Objekti klase GridBagConstraints imaju nekoliko atributa koji odgovaraju osobinama položaja jedne komponente. Neke od njih su: gridx – broj koji označava prvu ćeliju sa leve strane od koje se prostire komponenta gridy – broj koji označava prvu ćeliju odozgo od koje se prostire komponenta gridwidth – broj ćelija u jednom redu preko kojih se prostire komponenta gridheight – broj ćelija u koloni preko kojih se prostire komponenta anchor – broj koji odreĎuje gde će biti prikazana komponenta ukoliko joj je dodeljen veći prostor nego što je potrebno za njeno prikazivanje fill – odreĎuje da li povećati veličinu komponente tako da ona ispuni ceo prostor koji joj je odreĎen za prikazivanje insets – objekat klase Insets koji odreĎuje rastojanje komponente od ivica prostora koji joj je dodeljen za prikazivanje
XYLayout raspored
Ovaj raspored je karakterističan za JBuilder. On omogućava da kontrolu postavite na tačno odreĎenu poziciju unutar kontejnera. Obično se koristi u toku dizajniranja aplikacije, pri čemu bi trebalo da se na
kraju zameni nekim drugim odgovarajućim rasporedom, kako bi aplikacija izgledala isto na bilo kom sistemu.
Naziv jedinice: Upravljanje događajima
Materijali vezani uz ovu lekciju: - Test upravljanje dogaĎajima - Upravljanje dogaĎajima (PDF dokument)
Događaji Kod aplikacije koje imaju korisnički interfejs se ne izvršava linearno, od prve naredbe do poslednje. Sve što smo do sada radili sa korisničkim interfejsom jeste kreiranje njegovih komponenti i njihovo rasporeĎivanje. Kada pokrenete takvu aplikaciju, nakon pojavljivanja svih komponenti na ekranu, čeka se neka akcija korisnika. Ukoliko korisnik pritisne neki taster na tastaturi ili dugme miša, generiše se dogaĎaj. Ovi dogaĎaji se dalje obraĎuju u posebnim procedurama, kako bi vaša aplikacija bila funkcionalna. Svi dogaĎaji koje generišu AWT komponente nasleĎuju klasu AWTEvent. Osluškivači i adapteri događaja U Javi, dogaĎaji se obraĎuju pomoću tzv. osluškivača dogaĎaja ( event listeners). Naime, obzirom da se jedan dogaĎaj (npr. pritisak na dugme) sastoji iz nekoliko akcija (pozicioniranje kursora miša na dugme, pritisak levog dugmeta miša, otpuštanje levog dugmeta miša), komponenta na osnovu svih tih preduzetih akcija generiše dogaĎaj neke od podklasa klase AWTEvent ("dugme je pritisnuto"), koji se onda prosleĎuje odgovarajućem osluškivaču. Osluškivač tada preduzima odreĎene akcije koje su potrebne da se dogaĎaj pritiskanja dugmeta obradi, bez ulaženja u detalje o pojedinačnim akcijama od kojih se taj dogaĎaj sastoji. Osluškivači u Javi su realizovani preko interfejsa. Obzirom da postoji više vrsta dogaĎaja (podklase klase AWTEvent), svakom od njih odgovara i odgovarajući osluškivač pomoću koga se taj dogaĎaj obraĎuje. Da biste obradili neki dogaĎaj, neophodno je da kreirate klasu koja implementira odgovarajući osluškivač. Na primer,
class Reakcija implements ActionListener { ..... } Unutar ove klase neophodno je da implementirate sve metode definisane unutar interfejsa. Interfejs ActionListener ima definisan samo jedan metod, actionPerformed(). MeĎutim, postoje osluškivači koji imaju nekoliko definisanih metoda. Na primer, osluškivač dogaĎaja miša, MouseListener ima pet metoda: mousePressed(), mouseReleased(),mouseEntered(), mouseExited() i mouseClicked(). Ta
da, ukoliko koristite direktno interfejs osluškivača, morali biste da implementirate svih pet metoda, bez obzira što možda želite da obradite samo jedan od njih. Zbog toga postoje posebne klase, tzv. adapteri, koje već imaju implementirane sve metode jednog interfejsa i koje možete da koristite u svom kodu umesto da direktno implementirate neki interfejs.
Zbog svega navedenog, postupak obraĎivanja dogaĎaja ima tri koraka: 1. 2. 3.
Kreira se klasa koja implementira interfejs osluškivača nekog dogaĎaja ili koja nasleĎuje neki od odgovarajućih adaptera. Unutar ove klase implementira se metod koji obraĎuje odreĎeni dogaĎaj. Za odreĎenu komponentu registruje se instanca osluškivača.
Pogledajte sledeći kod.
1:import java.awt.*; 2:import java.awt.event.*; 3:public class TestDogadjaja extends Frame{ 4: Panel p1 = new Panel(); 5: 6: public TestDogadjaja() { 7: enableEvents(AWTEvent.WINDOW_EVENT_MASK); 8: setSize(600, 400); 9: setTitle("Pritisnite dugme"); 10: Button b1 = new Button("Pritisni me"); 11: add(p1); 12: p1.setBackground(new Color(255, 255, 255)); 13: p1.add(b1); 14: b1.addActionListener(new Reakcija()); 15: } 16: 17: class Reakcija implements ActionListener { 18: public void actionPerformed(ActionEvent e) { 19: int r, g, b; 20: r = (int) (Math.random()*255); 21: g = (int) (Math.random()*255); 22: b = (int) (Math.random()*255); 23: p1.setBackground(new Color(r,g,b)); 24: } 25: }
26: 27: 28: 29: 30: 31: 32: 33: 34: 35:}
// Redefinisan metod kako bi se aplikacija ugasila // pritiskom na Close dugme protected void processWindowEvent(WindowEvent e) { super.processWindowEvent(e); if (e.getID() == WindowEvent.WINDOW_CLOSING) { System.exit(0); } }
Prethodna klasa odgovara glavnom prozoru aplikacije. Da bi taj prozor bio kreiran u toku izvršavanja aplikacije, neophodna nam je i sledeća klasa, koja će biti početna za ovu aplikaciju.
public class pocetna { public static void main(String[] args) { TestDogadjaja td = new TestDogadjaja(); td.show(); } } Obratite pažnju na klasu TestDogadjaja. Unutar konstruktora ove klase postavljaju se neke inicijalne vrednosti i ubacuju se kontrole u glavni prozor. U linijama 11 i 12 ubacuje se panel p1 i postavlja se da boja njegove pozadine bude bela. Zatim se u liniji 13 dodaje dugme b1 na ovaj panel. U liniji 14 kreira se novi objekat klase Reakcija i dodaje se dugmetu b1 kao osluškivač tipa ActionListener, tj. prate se korisnikove akcije nad ovim dugmetom. Kada korisnik bude pritisnuo dugme, generisaće se dogaĎaj tipa ActionEventkoji će biti prosleĎen objektu klase Reakcija. Klasa Reakcija je definisana tako da implementira interfejs ActionListener. Ovaj interfejs ima samo definiciju jednog metoda, actionPerformed(), pa je neophodno da klasa Reakcija obezbedi kod za ovaj metod. Upravo taj metod definiše šta će se dešavati ukoliko korisnik pritisne dugme. U ovom slučaju, generiše se slučajna boja i postavlja kao vrednost boje pozadine panela p1. Vrste događaja i osluškivača Podklase klase AWTEvent odgovaraju različitim vrstama dogaĎaja koji mogu da se dese nad nekom komponentom i svaka od njih ima odgovarajući osluškivač pomoću koga se obraĎuje. Svaki dogaĎaj koji se generiše ima svoj ID, broj koji preciznije odreĎuje na koji način se dogaĎaj izvršio. Kada je jednom generisan dogaĎaj, koristite metod getID() da biste bliže odredili njegovu vrstu. Ovaj broj (ID) odgovara jednoj od konstanti deklarisanih u podklasama dogaĎaja. Na primer, u prethodnom primeru smo redefinisali metod processWindowEvent(), kako bismo obezbedili da se pritiskom na dugme Close glavnog prozora završi rad cele aplikacije. Pogledajte kod tog metoda. U njemu se preuzima dogaĎaj e klase WindowEvent i čita se njegov ID pomoću e.getID(). Ovaj broj se tada poredi sa konstantomWindowEvent.WINDOW_CLOSING definisanom u klasi WindowEvent. Ukoliko je ovaj
broj jednak toj konstanti, znači da je nad prozorom izvršena akcija pritiskanja dugmeta prestaje sa radom.
Close i aplikacija
ActionEvent –
odgovara semantičkim dogaĎajima visokog nivoa generisanim od strane komponente nad kojom je izvršena neka akcija, kao što je, na primer, pritiskanje dugmeta, potvrda unosa teksta pomoću tastera Enter ili izbor neke stavke iz menija. DogaĎaji ovog tipa se prosleĎuju svim osluškivačima tipa ActionListener. Unutar klaseActionEvent postoje sledeći indikatori dogaĎaja: ACTION_PERFORMED – akcija je izvršena ALT_MASK – bilo je pritisnuto dugme Alt za vreme izvršavanja akcije CTRL_MASK - bilo je pritisnuto dugme Control za vreme izvršavanja akcije SHIFT_MASK – bilo je pritisnuto dugme Shift za vreme izvršavanja akcije
FocusEvent – dogaĎaj niskog nivoa koji se javlja kada komponenta dobije fokus ili ga izgubi (na primer, kada korisnik postavi kursor miša na neko tekst polje ili kad pomoću tab tastera prelazi sa jedne na drugu kontrolu). Ovaj dogaĎaj se proleĎuje osluškivačima tipa FocusListener. Ova klasa ima sledeće indikatore dogaĎaja: FOCUS_GAINED – kontrola je dobila fokus FOCUS_LOST – kontrola je izgubila fokus
KeyEvent –
generišu se od strane komponente nad kojom je pritisnut, otpušten ili otkucan neki taster sa tastature. Ovi dogaĎaji se prosleĎuju osluškivaču tipa KeyListener. Taster je "otkucan" (key typed dogaĎaj), ako je pritisnut pa pušten nad nekom kontrolom. Ovo je dogaĎaj višeg nivoa, obzirom da obuhvata i slučaj kada je pritisnuta kombinacija tastera (npr. Shift + a). On se generiše kad god je unešena neka kombinacija koja predstavlja Unicode karakter, dok ne reaguje na funkcionalne tastere. DogaĎaji "key pressed" i "key released" su dogaĎaji nižeg nivoa i zavise od platforme. Pomoću njih je moguće obraditi i pritisak na tastere koji ne generišu karakter. Unutar ove klase postoje dodatni metodi koje možete da koristite da dobijete informaciju o tasteru koji je pritisnut. getKeyChar() – vraća karakter koji je pritisnut getKeyCode() – vraća celobrojni kod tastera koji je pritisnut getKeyText() – vraća string koji opisuje kod tastera (na primer HOME ili F1) Indikatori ove vrste dogaĎaja su: KEY_PRESSED – dugme je pritisnuto KEY_RELEASED – dugme je pušteno KEY_TYPED – dugme je pritisnuto i pušteno, tj. otkucan je neki karakter
MouseEvent – generiše se od strane komponente nad kojom se desila neka akcija mišem. Ova klasa se koristi za sve dogaĎaje miša (pritisak na dugme miša, pokretanje kursora, povlačenje i sl.). Svi ovi dogaĎaji se prosleĎuju osluškivačima tipa MouseListener i MouseMotionListener. Unutar ove klase postoji metod getButton() koji daje informaciju o tome koje dugme miša je pritisnuto. Ovaj metod može da vrati jednu od sledećih vrednosti: BUTTON1, BUTTON2, BUTTON3 ili NOBUTTON. Indikatori dogaĎaja klase MouseEvent su: MOUSE_CLICKED – klik mišem (dugme je pritisnuto i pušteno)
MOUSE_DRAGGED –
povlačenje mišem (dugme je pritisnuto, pomeren je kursor miša, dugme je
pušteno)
MOUSE_ENTERED – kursor miša je ušao u geometrijski prostor komponente MOUSE_EXITED – kursor miša je napustio geometrijski prostor komponente MOUSE_MOVED – kursor miša je pomeren MOUSE_PRESSED – dugme miša je pritisnuto MOUSE_RELEASED – dugme miša je pušteno MOUSE_WHEEL – točkić miša je zarotiran WindowEvent – dogaĎaj niskog nivoa koji se generiše kada prozor promeni svoj status (otvori, zatvori, aktivira, deaktivira, promeni fokus i dr.) ili se nad njim izvrši neka akcija. DogaĎaji ovog tipa se prosleĎuju osluškivačima klaseWindowListener. U okviru ove klase postoje metodi getNewState() i getOldState() koji daju informaciju o tome koje je novo i staro stanje prozora, ukoliko je došlo do promene stanja. Unutar ove klase postoje sledeći indikatori dogaĎaja:
WINDOW_ACTIVATED – prozor je aktiviran WINDOW_DEACTIVATED – prozor nije više aktivan WINDOW_CLOSING – nastaje kada korisnik pokuša
da zatvori prozor na dugme Close. Ukoliko se ovaj dogaĎaj ne obradi u programskom kodu, akcija korisnika se otkazuje, tj. prozor neće biti zatvoren. WINDOW_CLOSED – prozor je zatvoren WINDOW_ICONIFIED – prozor je iz normalnog stanja prešao u minimizovano WINDOW_DEICONIFIED – prozor je iz minimizovanog prešao u normalno stanje WINDOW_GAINED_FOCUS – prozor je dobio fokus WINDOW_LOST_FOCUS – prozor je izgubio fokus WINDOW_OPENED – prozor je otvoren. Ovaj dogaĎaj se generiše kada prozor prvi put postane vidljiv. WINDOW_STATE_CHANGED – promenjeno je stanje prozora
Naziv jedinice: Osnove Java apleta
Materijali vezani uz ovu lekciju: - Test osnove java apleta - Osnove Java apleta (PDF dokument)
Apleti Kao što znate, Java aplikacije su samostalni programi koji mogu biti izvršavani pomoću bilo kog Java interpretera. Za razliku od njih, Java apleti su programi koji se izvršavaju unutar nekog browser-a. Informacija o apletu se nalazi unutar specijalnog taga na nekoj HTML strani. Kada browser učita neku
stranicu koja koristi aplet, on učitava i sam aplet sa servera i izvršava ga lokalno, na korisnikovom računaru. Iako jedan isti program može biti kreiran i kao aplet i kao aplikacija, postoji veoma značajna razlika izmeĎu ove dve vrste izvršavanja programa. Ona se ogleda u skupu zabrana koje imaju apleti: -
apleti apleti apleti apleti
ne ne ne ne
mogu mogu mogu mogu
da da da da
čitaju niti pišu u korisnikov sistem fajlova komuniciraju sa bilo kojim serverom, sem onog sa kog su učitani pokreću druge programe na korisnikovom računaru učitavaju programe lokalne platforme, uključujući DLL-ove
Kreiranje apleta Da biste kreirali aplet, potrebno je da kreirate podklasu klase Applet. Ova klasa je deo paketa java.applet i ona obezbeĎuje metode koji su neophodni za rad unutar browser-a. Imajući ovo u vidu, definicija glavne klase apleta bi izgledala ovako:
public class MojAplet extends java.applet.Applet { ...... } Sem glavne klase, aplet može da sadrži i više pomoćnih klasa, ali je glavna klasa apleta ta koja se izvršava prilikom pokretanja apleta. TakoĎe, neophodno je da glavna klasa bude deklarisana kao public. Kod aplikacija Java prilikom pokretanja programa poziva main() metod aplikacije. Kod izvršavanja apleta, Java kreira instancu glavne klase apleta i zatim se poziva serija metoda te instance. Različiti apleti mogu da koriste istu klasu, ali različite instance. Metodi apleta Apleti imaju različite aktivnosti koje odgovaraju različitim etapama u životu apleta, kao što su inicijalizacija, iscrtavanje ili dogaĎaji miša. Svaka aktivnost ima odgovarajući metod, pa kad se neki dogaĎaj desi, Java poziva metod specifičan za taj dogaĎaj. Pet najvažnijih etapa u izvršavanju apleta su inicijalizacija, pokretanje, zaustavljanje, uništavanje i iscrtavanje. Inicijalizacija Inicijalizacija se dešava kada se aplet prvi put učita, slično kao metod main() kod aplkacija. Inicijalizacija apleta obično uključuje čitanje i prosleĎivanje parametara apletu, kreiranje pomoćnih objekata, podešavanje inicijalnog stanja apleta, ulčitavanje slika i fontova i dr. Ovoj etapi odgovara metod init(). Pokretanje i zaustavljanje Nakon inicijalizacije, aplet se pokreće. Pokretanje se razlikuje od inicijalizacije u tome što aplet može biti pokrenut nekoliko puta, dok se inicijalizacija dešava samo jednom. Na primer, ukoliko korisnik prateći neki link do neke druge strane napusti stranu koja sadrži aplet, podrazumeva se da će sve niti pokrenute u apletu nastaviti sa izvršavanjem. Pomoću metoda stop() i start() možete da zaustavite izvršavanje apleta i pokrenete ga ponovo kada se korisnik vrati na polaznu stranu. Uništavanje Uništavanje se dešava neposredno pre oslobaĎanja memorije samog apleta i omogućava da, na primer, zaustavite niti koje se izvršavaju, zatvorite otvorene konekcije ili uklonite neke druge objekte koji su aktivni. Sve ovo se postiže unutar metoda destroy().
Iscrtavanje Iscrtavanjem aplet praktično crta bilo šta na ekranu (tekst, sliku, grafičke objekte, pozadinu i sl.). Iscrtavanje se dešava veoma često, nakon inicijalizacije, nakon pomeranja prozora browser-a, u animacijama i sl. Ovoj fazi odgovara metodpaint(). Definicija metoda paint() je sledeća
public void paint(Graphics g) { ..... } Primetite da ovaj metod koristi argument, objekat klase Graphics. Ovaj objekat se kreira i prosleĎuje metodu paint() od strane browser-a. Obzirom da klasa Graphics pripada paketu java.awt, neophodno je da uvezete ovaj paket u vaš kod. Pogledajte sledeći primer veoma jednostavnog apleta. 1:import java.awt.Graphics; 2:import java.awt.Font; 3:import java.awt.Color; 4: 5:public class Pozdrav extends java.applet.Applet { 6: Font f = new Font("TimesRoman", Font.BOLD, 36); 7: public void paint(Graphics g) { 8: g.setFont(f); 9: g.setColor(Color.red); 10: g.drawString("Pozdrav!", 5, 40); 11: } 12:} Ovaj aplet implementira samo metod paint(), koji ispisuje poruku na ekranu. Obzirom da je sam aplet veoma jednostavan, metodi start(), stop(), init() i destroy() nisu ponovo implementirani, tj. preuzeta je njihova implementacija iz klase Applet. Metod paint() preuzima objekat g klase Graphics od samog browser-a. Ovaj objekat u stvari predstavlja prostor u okviru web strane u kome će se aplet pojaviti. U linijama 8, 9 i 10 metod paint() menja neke elemente ovog prostora (font i boju) i iscrtava navedeni tekst. Poziv metoda drawString("Pozdrav!", 5, 40) ispisuje tekst na poziciji (5, 40), pri čemu pozicija (0,0) odgovara gornjem levom uglu prostora dodeljenog apletu. Postavljanje apleta na web stranu Da bi prethodni aplet zaista bio prikazan unutar neke web strane, neophodno je da kreirate HTML stranu i uključite aplet pomoću