You are on page 1of 76

Uvod

Računar je složen sistem koji se sastoji iz puno komponenata. Najvažnija komponenta je centralna
procesorska jedinica. U pitanju je jedan čip čiji je posao da izvršava programe.
Program je lista nedvosmislenih instrukcija koje računar mehanički izvršava. Računar može da
izvršava instrukcije koje su napisane u tzv. mašinskom jeziku. Svaki tip računara ima svoj mašinski
jezik i može da direktno izvršava samo programe koji su pisani u tom jeziku. (Programe koji su
pisani u drugim jezicima može da izvršava samo ako se prevedu u mašinski jezik tog računara.)
Mašinski jezik se sastoji od vrlo jednostavnih isntrukcija koje CPU tog računara može direktno da
izvršava. Sa druge strane, skoro svi programi se pišu u programskim jezicima višeg nivoa, kao što
su Java, Pascal ili C++. Program koji se napiše u nekom od ovih jezika ne može da se direktno
izvršava na nekom računaru. On mora da se prvo prevede u mašinski jezik. Ovo radi poseban
program, kompajler. Kompajler uzima program napisan u jeziku višeg nivoa i prevodi ga u izvršni
program u mašinskom jeziku. Ako program treba da se izvrši na nekom drugom računaru, mora da
se prevede u taj drugi mašinski jezik uz upotrebu drugog kompajlera, koji odgovara tom drugom
tipu računara.
Postoji i alternativa za kompajliranje programa pisanog u jeziku višeg nivoa. Umesto da se koristi
kompajler koji odjednom prevodi program, možete da koristite interpreter, koji prevodi instrukciju
po instrukciju. Interpreter je program koji se ponaša slično kao CPU, odnosno postoje ciklusi
važenja instrukcija i njihovog izvršavanja. Interpreter radi u petlji koja stalno čita instrukcije iz
programa, odlučuje da li je potrebno da se ona izvrši i ako je potrebno obavlja odgovarajuđu
komandu iz mašinskog jezika.
Postoje interpreteri koji izvršavaju jezike višeg nivoa. Na primer, programski jezik LISP radi preko
interpretera, a ne preko kompajlera.
Dizajneri Jave su odlučili da koriste kombinaciju kompilacije i interpretacije. Programi koji su
pisani u Javi se kompajliraju u mašinski jezik, ali je u pitanju mašinski jezik za računar koji ne
postoji u stvarnosti. U pitanju je virtuelni računar, poznat kao Java virtuelna mašina. Mašinski kod
za JVM se naziva bajtkod. Nema nijednog razloga zašto Java bajtkod ne bi mogao da se koristi kao
mašinski jezik za pravi računar. Sun Microsystems su i napravili takav računar, odnosno procesor.
Sa druge strane, jedna od najvažnijih stvari u Javi je da se Java program može da izvršava na bilo
kom računaru. Sve što na tom računaru treba da postoji je interpreter za Java bajtkod.
Za svaki računar treba da postoji drugi Java bajtkod interpreter, ali kad računar jednom ima taj
interpreter, on može da izvršava bilo koji program pisan u Javi. Isti Java program se može da izvrši
na bilo kom računaru koji ima takav interrpreter. Ovo je i jedna od najvažnijih karakteristika Jave,
Isti program može da se izvršava na različitim računarima.

1
Zašto biste koristili Java bajtkod? Zašto se ne bi distribuisao originalni Java program, koji bi se
kasnije kompajlirao u odgovarajući mašinski jezik. Postoji više razloga. Prvo, kompajler mora da
razume Javu, koja je složeni jezik visokog nivoa. Sam kompajler je složeni program. Interpreter za
bajtkod je sa druge strane prilično jednostavan program. Lako je napisati interpterer bajtkoda za
svaki tip računara, nakon čega taj interpreter može da izvrši bilo koji Java program. Bilo bi mnogo
teže napisati Java kompajler za svaki tip računara.
Još jedan razlog je sigurnost. Puno Java programa se preuzimaju preko mreže. Ne biste želeli da
preuzmete program koji će oštetiti Vaš računar. Interpreter bajtkoda se ponaša kao bafer između
Vas i programa koji ste preuzeli. Vi u suštini pokrećete interpreter, koji indirektno izvršava preuzeti
program. Interpreter može da Vas zaštiti od potencijalno opasnih akcija, koje su deo tog programa.
Java i Java bajtkod ne moraju obavezno da budu povezani. Program napisan u Javi bi mogao da se
kompajlira i u neki drugi mašinski jezik, realnog računara. Programi pisani u drugim programskim
jezicima bi mogli da se kompajliraju u Java bajtkod. Ipak, kombinacija Jave i Java bajtkoda je ono
što daje nezavisnost platforme, sigurnost i kompatibilnost.

Objektno orijentisano programiranje


Objektno orijentisano programiranje je odgovor na softversku krizu iz devedesetih godina pro{log
veka. Tada dolazi do nagle ekspanzije primene ra~unara u svim oblastima. Programi postaju sve
ve}i i slo`eniji. U njihovom razvoju u~estvuje sve ve}i broj programera. Tradicionalni algoritamski
na~in programiranja ne mo`e da odgovori izazovima koji se tada javljaju. Ovde se pre svega misli
na mogu}nost kasnijeg odr`avanja softvera. Programi imaju vi{e hiljada linija koda u kojima se
treba sna}i. Odgovor je bio u objektno orijentisanom programiranju.

[ta su objekti?
Sve mo`e biti objekat. Objekti su svuda oko nas. Objektni mogu predstavljati realne ili apstraktne
stvari. Objekat je va{ pas, sto, knjiga, bicikla sve {to nas okru`uje.
Objekti iz realnog sveta imaju dve karakteristike, a to su stanje i pona{anje. Stanje Va{eg psa
predstavlja njegova boja, ime, rasa i sl. Pona{anje nam govori da li on laje, da li je gladan i sl.
Softverski objekti su sli~ni ovim objektima iz realnog sveta po tome {to imaju stanje i pona{anje.
Stanje softverskog objekta se izra`ava njegovim atributima, koji se opisuju preko promenljivih.
Pona{anje softverskog objekta se implementira preko metoda. Metodi su funkcije (potprogrami)
koji su pridru`eni jednom objektu.
Objekti iz realnog sveta mogu da se predstave softverskim objektima. Na primer u programu za
kontrolu rada elektronske bicikle, se bicikla mo`e predstaviti softverskim objektom, bicikl. Pored
realnih objekata softverski objekti se mogu koristiti i za predstavljanje apstraktnih stvari. Tako na
primer, u programiranju GUI-ja (grafi~ki korisni~ki interfejs) se za predstavljanje doga|aja mo`e
koristiti objekat. Doga|aj mo`e biti klik mi{em, ili pritisak nekog tastera na tastaturi.

Sve {to jedan softverski objekat zna (stanje) i mo`e da uradi (pona{anje) se predstavlja atributima i
metodima koji se u njemu nalaze. Na primer, bicikla iz realnog sveta ima svoje atribute, koji se
odnose na trenutnu brzinu (10 km/h), broj zup~anika (5) i sl.

2
Objektni dijagrami pokazuju da atributi objekta ~ine njegovo jezgro. Metodi okru`uju to jezgro i
sakrivaju ga od ostatka programa. Pakovanje atributa objekta i njihova za[tita putem metoda se
naziva u~aurenjem. Objekat se prema tome, sastoji od jezgra, koje ~ine njegovi atributi i
membrane, koju ~ine njegovi metodi, preko koje se tom jezgru pristupa.
U~aurenje promenljivih i metoda je ideja koja programerima pru`a dve osnovne prednosti:
Modularnost: Izvorni kod objekta se mo`e napisati i kasnije se mo`e odr`avati nezavisno od drugih
objekata i njihovog koda. Objekat se tako|e mo`e lako proslediti izvan granica sistema. mo`ete
nekom dati svoju biciklu i ona }e i dalje da radi.
Skrivanje informacija: Objekat ima javni interfejs koji drugi objekti koriste za komunikaciju sa
njim. Objekat mo`e da odr`ava svoje privatne informacije i metode koji se mogu u bilo kom
trenutku promeniti, a da to ne uti~e na objekte oko njega. Ne morate da poznajete detalje u vezi
mehanizma sa zup~anicima bicikle, da biste mogli da je koristite.
^emu ova pri~a o objektima? Java je ~ist objektno orijentisani jezik. To zna~i da u Javi nijedno
par~e koda ne mo`e da postoji ako nije deo objekta. U C++-u koji je tako|e objektno orijentisani
jezik, mogu da postoje i delovi koda koji nisu objektno orijentisani. Ne samo da mogu, nego uvek
postoji takav kod, jer uvek mora da postoji funkcija main, koja ozna~ava glavni program, a koja
nije deo nijedne klase.

Java aplikacije
Svaka aplikacija pisana u Javi mora da sadr`i klasu, koja defini{e metod po imenu main(). Klasa
mo`e da ima proizvoljno ime, ali metod koji se u aplikaciji prvi pokre}e je metod po imenu main().
Obi~no se iz ovog metoda pozivaju druge metode te ili drugih klasa.

Prva Java aplikacija


Prva aplikacija je ona koju }ete videti na po~etku rada s abilo kojim programskim jezikom,
aplikacija koja }e ispisati tekst “Zdravo”. Evo kako izgleda kod:
/**
* Klasa ZdravoApp implementira aplikaciju koja na
* standardnom izlazu prikazuje tekst zdravo
*/
public class ZdravoApp {
public static void main(String[] args) {
System.out.println("Zdravo!"); //Prikazuje string
}
}
Program sadr`i definiciju klase ZdravoApp. U ovoj klasi postoji samo jedan metod, metod main().
Prva linija definicije ovog metoda je uvek:
public static void main(String[] args)

U metodu postoji samo jedan izvr{ni iskaz:


System.out.println("Zdravo!");

3
Klju~na re~ public u definiciji metoda main ozna~ava da tom metodu mo`e da se globalno pristupi.
Klju~na re~ static osigurava pristup ~ak i kada ne postoji objekat (instanca) klase ZdravoApp.
Klju~na re~ void ozna~ava da ovaj metod ne vra}a nikakvu vrednost.
System je standardna klasa koja podr`ava unos preko tastature i prikazivanje izlaza na ekranu. Ova
klasa se nalazi u paketu java.lang i mo`e joj se pristupiti samo preko imena klase, System.
Objekat out predstavlja standardni izlazni tok, u ovom slu~aju ekran monitora. Ovaj objekat je ~lan
klase System. Ovaj metod je deklarisan kao static, {to zna~i da mu se mo`e pristupati i kada ne
postoji instanca klase System.
println je metod koji pripada objektu out i on {tampa tekst koji se nalazi u zagradama na ekran.
Program se kompajlira komandom:
javac ZdravoApp.java
a izvr{ava komandom
java ZdravoApp
Kada se program izvr{i na ekranu treba da se prika`e tekst
Zdravo

Komentari u kodu
Postoji nekoliko mogu}ih vrsta definisanja komentara. Jedan od na~ina je da se se upotrebe dve
kose crte //. Sve {to sledi iza ovih znakova, a nalazi se u istom redu, smatra se komentarom i to
kompajler zanemaruje prilikom prevo|enja.
// ovo je komentar u jednom redu
Alternativa je da se po~etak komentara ozna~i sa /*, a kraj komentara sa */. Sve {to se nalazi
izme|u po~etka i kraja komentara kompajler zanemaruje prilikom prevo|enja. Tekst komentara se na
ovaj na~in mo`e da pro{iri na vi{e redova.
/* ovo je komentar u
u vi{e redova
*/
Komentari koji slu`e za generisanje dokumentacije po~inju znacima /**, a zavr{avaju se kao i
obi~an komentar sa */. Ovakve komentare zatim ~ita poseban program, javadoc, koji od nje pravi
dokumentaciju sa hiperlinkovima. Sva dokumentacija koju nalazite na sajtovima vezanim za Java
kod, je napravljena na ovaj na~in. U okviru ove dokumentacije mogu se koristiti razli~ite HTML
oznake. Na primer:
@version - ozna~ava verziju programa
@author - ozna~ava autora itd.

Osnove jezika Java


Podaci i promenljive
Promenljiva je imenovani deo memorije koji se koristi za sme{tanje informacija u programu. Svaki
deo memorije kome ste dali ime mo`e da primi sa odre|eni tip podatka. Svaka promenljiva ima
svoje ime i tip. Preko imena pristupate podatku na koji ta promenljiva ukazuje. tip odre|uje {ta u toj
promenljivoj mo`e da se na|e i koje su peracije dozvoljene. Kada se jednom defini{e tip promenljive
u tom delu memorije mogu da se sme{taju samo podaci tog tipa (ceo broj, realan broj, niz karaktera,
objekat i sl.) Na osnovu zadatog tipa kompajler kasnije mo`e da proverava da ste toj promenljivoj

4
poku{ali da zadate neki drugi tip podatka. Ime i tip se promenljivoj zadaju preko deklaracije. Op{ti
oblik deklaracije je:
tip ime
Pored imena i tipa svaka promenljiva ima i svoj domen. Domen promenljive je deo koda u kome se
ta promenljiva mo`e da koristi. Domen se implicitno defini{e na osnovu mesta gde se nalazi
deklaracije promenljive.

Osnovni tipovi promenljivih

Celobrojne vrednosti
Postoje ~etiri tipa promenljivih koji se mogu koristiti za celobrojne vrednosti. Svaki od njih mo`e
da ima predznak, {to zna~i da mogu da sadr`e pozitivne i negativne brojeve. Ovi tipovi se razlikuju
po opsegu vrednosti koje mogu da se sme{taju. Evo koji su to tipovi:
byte - vrednosti mogu biti od -128 do +128 i u memoriji zauzimaju 1 bajt (8 bitova)
short - vrednosti mogu biti od -32768 do 32767 i u memoriji zauzimaju 2 bajta (16 bitova)
int - vrednosti mogu biti o -2147483648 do +2147483647 i u memoriji zauzimaju 4 bajta (32 bita)
long - vrednosti mogu biti od -9223372036854775808 do +9223372036854775807 i u memoriji
zauzimaju 8 bajtova (64 bita)
Evo kako izgledaju deklaracije ovih tipova:
byte najmanjaVrednost;
short brojac;
int br;
long najvecaVrednost;
U jednom iskazu se mo`e deklarisati i vi{e promenljivih:
int a, b;
Prilikom deklaracije se mo`e izvr{iti i inicijalizacija promenljive.
int a = 1;

Tipovi sa pokretnim zarezom


Slu`e za sme{tanje realnih brojeva. Postoje dva tipa, float i double.
float - vrednosti mogu biti od-3.4x1038 do 3.4x1038 i u memoriji zauzimaju 4 bajta. Vrednosti se
predstavljaju sa ta~no{}u od 7 cifara.
double - vrednosti mogu biti od -1.7x10308 do 1.7x10303 i u memoriji zauzimaju 8 bajtova.
Vrednosti se predstavljaju sa ta~no{}u od 17 cifara.
Primer:
float a = 1.5;
double b = 1.67;

Znakovne promenljive
Promenljiva tipa char zauzima u memoriji dva bajta. Vrednost ovakve promenljive je jedan
karakter, kao {to je A, * , x ili belina (blanko karakter). Vrednost mo`e biti i neki specijalni
karakter, kao {to je tabulator, ili neki od Unicode karaktera koji dolaze iz razli~itih jezika. Kada se

5
karakter unosi u program on se mora uokviriti jednostrukim navodnicima ‘A’, ‘*’. Navodnici nisu
deo vrednosti i ne sme{taju se u promenljivu. U pitanju je samo konvencija.
char c = ‘a’;

Promenljive tipa boolean


Promenljive ovog tipa mogu da imaju samo dve vrednosti: true (ta~no) i false (neta~no).
boolean t = false;
boolean p = true;
Primer:
public class MaxVariablesDemo {
public static void main(String args[]) {

// celi brojevi
byte najveciByte = Byte.MAX_VALUE;
short najveciShort = Short.MAX_VALUE;
int najveciInteger = Integer.MAX_VALUE;
long najveciLong = Long.MAX_VALUE;

// realni brojevi
float najveciFloat = Float.MAX_VALUE;
double najveciDouble = Double.MAX_VALUE;

// ostali pritimitivni tipovi


char c = 'S';
boolean b = true;

// prikazivanje
System.out.println("Najveca vrednost tipa byte je " + najveciByte);
System.out.println("Najveca vrednost tipa short je " + najveciShort);
System.out.println("Najveca vrednost tipa int je " + najveciInteger);
System.out.println("Najveca vrednost tipa long je " + najveciLong);

System.out.println("Najveca vrednost tipa float je " + najveciFloat);


System.out.println("Najveca vrednost tipa double je " + najveciDouble);

if (Character.isUpperCase(c)) {
System.out.println("Karakter " + c + " je veliko slovo.");
} else {
System.out.println("Karakter " + c + " je malo slovo.");
}
System.out.println("Vrednost za promenljivu b je " + b);
}
}

Operatori i zrazi

Aritmeti~ki operatori
U tabeli koja sledi su prikazani tipovi i opis aritmeti~kih operatora:

Operator Upotreba Opis


+ op1 + op2 Sabira op1 i op2
- op1 - op2 Oduzima op2 od op1

6
* op1 * op2 Mno`i op1 sa op2
/ op1 / op2 Deli op1 sa op2
% op1 % op2 Ra~una ostatak deljenja op1 sa op2

Sledi primer AritmetikaDemo u kome se defini{u dve celobrojne promenljive i dva realna broja sa
dvostrukom precizno{}u i sa njima se obavljaju razli~ite aritmeti~ke operacije.

public class ArithmeticDemo {


public static void main(String[] args) {

//nekoliko brojeva
int i = 37;
int j = 42;
double x = 27.475;
double y = 7.22;
System.out.println("Vrednosti promenljivih su...");
System.out.println(" i = " + i);
System.out.println(" j = " + j);
System.out.println(" x = " + x);
System.out.println(" y = " + y);

//sabiranje brojeva
System.out.println("Sabiranje...");
System.out.println(" i + j = " + (i + j));
System.out.println(" x + y = " + (x + y));

//oduzimanje brojeva
System.out.println("Oduzimanje...");
System.out.println(" i - j = " + (i - j));
System.out.println(" x - y = " + (x - y));

//Mno`enje brojeva
System.out.println("Mnozenje...");
System.out.println(" i * j = " + (i * j));
System.out.println(" x * y = " + (x * y));

//deljenje brojeva
System.out.println("Deljenje...");
System.out.println(" i / j = " + (i / j));
System.out.println(" x / y = " + (x / y));

//Deljenje po modulu
System.out.println("Deljenje po modulu...");
System.out.println(" i % j = " + (i % j));
System.out.println(" x % y = " + (x % y));

//mesanje tipova
System.out.println("Mesanje tipova...");
System.out.println(" j + y = " + (j + y));
System.out.println(" i * x = " + (i * x));
}
}

Izlaz iz ovog programa je:

Vrednosti promenljivih su...


i = 37
j = 42
x = 27.475

7
y = 7.22
Sabiranje...
i + j = 79
x + y = 34.695
Oduzimanje...
i - j = -5
x - y = 20.255
Mnozenje...
i * j = 1554
x * y = 198.37
Deljenje...
i / j = 0
x / y = 3.8054
Deljenje po modulu...
i % j = 37
x % y = 5.815
Mesanje tipova...
j + y = 49.22
i * x = 1016.58
Kada se kao operandi u jednoj aritmeti~koj operaciji koriste zajedno ceo broj i realan broj, rezultat
je realan broj. Ceo broj se implicitno konvertuje u realan broj pre samog izra~unavanja. U tabeli
koja sledi su prikazani tipovi podataka koji se vra}aju iz aritmeti~kih operacija, na osnovu tipova
operanada. Potrebne konverzije se vr{e pre {to se obavi operacija.

Tip podatka za
Tipovi podataka za operande
rezultat

long
Nijedan od operanada nije float ili double (artiemtika celih brojeva), a
najmanje jedan od operatora je tipa long.

int
Nijedan od operanada nije float ili double (aritmetika celih brojeva).
Nijedan operand nije long.
double Najmanje jedan operand je tipa double.
float Najmanje jedan operand je tipa float. Nijedan nije tipa double.

Postoje i dva operanda koji omogu}avaju skra}eno izra~unavanje. To su operator ++ koji operand
pove}ava za 1 i operator -- koji operand smanjuje za 1. Oba operatora mogu da se pojave ispred
operanda (prefiks) i iza operanda (postfiks). Kod verzije prefiks, ++op/--op se prvo operand
pove}ava za 1, pa se taj rezultat koristi dalje u izrazima. Kod verzije postfix se prvo operand
primeni u izrazu (stara vrednost), a tek posle se ta vrednost promeni.
public class Voce
{
public static void main(String[] args)
{
//deklaracija i inicijalizacija tri promenljive
int brojNarandzi = 5;
int brojJabuka = 10;
int brojVocaka = 0;
// povecava se broj narandzi i racuna zbir vocaka
brojVocaka = ++brojNarandzi + brojJabuka;
System.out.println(“Ukupan broj vocaka u programu”);
System.out.println(“Broj narandzi je “ + brojNarandzi);
System.out.println(“Ukupan broj vocaka je “ + brojVocaka);

8
}
}
Ukupan broj vo}aka je sada 16. Razlog je {to se broj narand`i prvo pove}ao za 1, pa je taj broj u{ao
u sabiranje.
Ako se iskaz sabiranja promeni na:
brojVocaka = brojNarandzi++ + brojJabuka;
ukupni broj vo}aka je 15, po{to je u sabiranje u{la stara vrednost za broj narand`i, koja je tek
naknadno pove}ana.

Relacioni i uslovni operatori


Relacioni operator poredi dve vrednosti i odre|uje vrednost izme|u njih. Na primer, != vra}a ta~no
ako dva operanda nisu jednaki. U tabeli koja sledi su dati relacioni operatori:
Operator Upotreba Vra}a true(ta~no) ako je
> op1 > op2 op1 ve}e op2

>= op1 >= op2 op1 ve}e ili jednako od op2

< op1 < op2 op1 manje op2

<= op1 <= op2 op1 manje ili jednako op2

== op1 == op2 op1 i op2 su jednaki

!= op1 != op2 op1 i op2 su razli~iti

U primeru koji sledi smo definisali tri cela broja i poredili ih pomo}u relacionih operatora.
public class RelacioniDemo {
public static void main(String[] args) {

//Nekoliko brojeva
int i = 37;
int j = 42;
int k = 42;
System.out.println("Vrednosti promenljivih...");
System.out.println(" i = " + i);
System.out.println(" j = " + j);
System.out.println(" k = " + k);

//vece od
System.out.println("Vece od...");
System.out.println(" i > j = " + (i > j)); //false
System.out.println(" j > i = " + (j > i)); //true
System.out.println(" k > j = " + (k > j)); //false, oni su jednaki

//vece ili jednako


System.out.println("Vece ili jednako...");
System.out.println(" i >= j = " + (i >= j)); //false
System.out.println(" j >= i = " + (j >= i)); //true
System.out.println(" k >= j = " + (k >= j)); //true

//manje od
System.out.println("Manje od...");
System.out.println(" i < j = " + (i < j)); //true
System.out.println(" j < i = " + (j < i)); //false
System.out.println(" k < j = " + (k < j)); //false

9
//manje ili jednako
System.out.println("Manje ili jednako...");
System.out.println(" i <= j = " + (i <= j)); //true
System.out.println(" j <= i = " + (j <= i)); //false
System.out.println(" k <= j = " + (k <= j)); //true

//jednako
System.out.println("Jednako...");
System.out.println(" i == j = " + (i == j)); //false
System.out.println(" k == j = " + (k == j)); //true

//razlicito
System.out.println("Razlicito...");
System.out.println(" i != j = " + (i != j)); //true
System.out.println(" k != j = " + (k != j)); //false

}
}
Evo kako izgleda izlaz iz ovog programa:
Vrednosti promenljivih...
i = 37
j = 42
k = 42
Vece od...
i > j = false
j > i = true
k > j = false
Vece ili jednako...
i >= j = false
j >= i = true
k >= j = true
Manje od...
i < j = true
j < i = false
k < j = false
Manje ili jednako...
i <= j = true
j <= i = false
k <= j = true
Jednako...
i == j = false
k == j = true
Razlicito...
i != j = true
k != j = false
Relacioni operatori se ~esto koriste zajedno sa logi~kim operatorima, ~ime se dobijaju slo`eni
izrazi. U Javi postoje slede}i logi~ki operatori:

Operator Upotreba Vra}a true(ta~no)ako je

&& op1 && op2


i op1 i op2 imaju vrednost true. op2 se izra~unava samo ako je
potrebno.

|| op1 || op2
ili op1 ili op2 ima vrednost true (ta~no). op2 se izra~unava samo
ako je potrebno.
! ! op op ima vrednost false (neta~no)

10
& op1 & op2
i op1 i op2 imaju vrednost ta~no. Uvek se izra~unava i op1 i
op2.
| op1 | op2 Ili je op1 ili je op2 true (ta~no). Uvek se izra~Unava i op1 i op2.

^ op1 ^ op2
ako su op1 i op2 razli~iti, odnosno ako jedan ima vrednost true,
ali ne oba.

Koja je razlika izme|u operatora && i &? Razlika je u brzini izvr{avanja programa. Sa operatorom
& se vrednost drugog operatora uvek izra~unava, dok se sa operatorom && izra~unava vrednost
prvog operanda, a ako je to dovoljno da se izra~una vrednost celog izraza, drugi operand se ne
izra~unava.

Operatori dodele
Osnovni operator dodele je operator =, kojim se jedna vrednost dodeljuje drugoj.
U Javi postoje i operatori dodele kojim se odjednom izvr{ava vi{e operacija. Pretpostavimo da
`elite da saberete vrednost promenljive sa nekim brojem i da rezultat dodelite istoj promenlivoj.
Napisali biste:
i = i + 2;
Skra}eno se ovo mo`e napisati pomo}u operatora += na slede}i na~in:
i += 2;
Prethodna dva izraza su ekvivalentna.
U tabeli koja sledi su dati neki od operatora ovog tipa:

Operator Upotreba Ekvivalentno sa


+= op1 += op2 op1 = op1 + op2

-= op1 -= op2 op1 = op1 - op2

*= op1 *= op2 op1 = op1 * op2

/= op1 /= op2 op1 = op1 / op2

%= op1 %= op2 op1 = op1 % op2

&= op1 &= op2 op1 = op1 & op2

|= op1 |= op2 op1 = op1 | op2

^= op1 ^= op2 op1 = op1 ^ op2

Ostali operatori
U tabeli koja sledi su dati ostali operatori koji postoje u Javi.
Operator Opis
?: Skra}eni iskaz if-else

[]
Koristi se za deklarisanje nizova, za kreiranje nizova, i za pristup elementima
niza.

11
. Koristi se za formiranje kvalifikovanih imena.
( params ) Defini{e se lista parametara. Vrednosti se odvajaju zarezima.
( tip ) Konvertuje se jedan tip u neki drugi.
new Kreira se novi objekat ili niz.
instanceof Odre|uje se da li je prvi operator instanca (primerak) drugog

Operator ?:
Ovaj operator vra}a op2, ako op1 ima vrednost true (ta~no) ili vrednost op3 ako op1 ima vredcnost
false (neta~no).
op1 ? op2 : op3
Pretpostavimo da imamo dve celobrojne promenljive tipa int, mojeGodine i tvojeGodine. @elimo
da tre}oj promenljivoj, stariji, dodelimo ve}u od ove dve vrednosti. Evo kako izgleda iskaz:
stariji = tvojeGodine > mojeGodine ? tvojeGodine : mojeGodine
Prvi argument ovog operatora je logi~ki izraz tvojeGodine > mojeGodine. Ako taj izraz ima
vrednost true (ta~no), promenljiva stariji dobija vrednost tvojeGodine, a ako je prvi izraz ocenjen
kao false (neta~no) promenljiva stariji dobija vrednost mojeGodine.

Operator []
Ovaj operator se koristi za deklarisanje nizova i za pristupanje elementima niza.
float [] realniNiz = new float[10];
Ovaj izraz deklari{e niz realnih brojeva sa deset elemenata. Sedmom ~lanu niza mo`ete da
pristupite na slede}i na~in:
realniNiz[6]

Operator .
Ovaj operator se koristi za pristup ~lanovima klase. Vi{e o njemu kada se bude govorilo o klasama.

Operator ()
Koristi se prilikom deklarisanja i poziva metoda klase. Vi{e o njemu kada se bude govorilo o
klasama.

Operator (tip)
Vrednost se konvertuje u odre|eni tip.
(double) a a se pretvara u tip double.

Operator new
Koristi se za kreiranje novog objekta ili niza.
Integer a = new Integer(10);
U ovom primeru se kreira novi objekat klase Integer.

Operator instanceof
Ovaj operator testira da li prvi operator predstavlja priemrak klase koja je data drugim operatorom.

12
op1 instanceof op2
op1 mora biti objekat, a op2 mora biti ime klase. Objekat je instanca klase ako je primrak ba{ te
klase ili neke klase koja je iz nje izvedena.

Prioritet operatora
Ako se u izrazu na|e vi{e operatora oni se izvr{avaju odre|enim redosledom. U tabeli koja sledi je
dat prioritet operatora. Operatori sa najvi{im prioritetom su navedeni prvi, a zatim slede oni sa
ni`im prioritetom. Ako `elite da promenite prioritet operatora, treba da koristite zagrade.

postfiks operatori [] . (params) expr++ expr--

unarni operatori ++expr --expr +expr -expr ~ !

operatori kreiranja i kovenrzije new (type)expr

mno`enje * / %

sabiranje + -

pomeranje << >> >>>

relacioni < > <= >= instanceof

jednakost == !=

bitovsko I &

bitovsko isklju~ivo ILI ^

bitovsko uklju~ivo ILI |

Logi~ko I &&

logi~ko ILI ||

uslovni ? :

dodela = += -= *= /= %= &= ^= |= <<= >>= >>>=

Logi~ki izrazi
Osnovni element svih programa je dono{enje odluka. Morate biti u stanju da izaberete izme|u
razli~itih mogu}nosti, na primer, “Ako imam para na ra~unu kupi}u nov auto, a ako nemam kupi}u
mese~nu kartu za autobus.”. Programski se dono{enje odluka realizuje pomo}u relacionih operatora
i odgovaraju}ih logi~kih izraza.

Iskaz if
Iskaz if je elementarni logi~ki izraz. Njegov najjednostavniji oblik je:
if (izraz)
iskaz;
Izraz mo`e biti bilo koji izraz koji daje vrednost true (ta~no) ili false (neta~no). Ako je vrednost
izraza true, onda se izvr{ava iskaz koji sledi, u suprotnom ne.
Primer:

13
if(broj % 2 != 0) //proverava se da li je broj neparan
++broj; //ako je neparan, neka postane paran
Ovaj iskaz se mo`e napisati i na neki drugi na~in, ali se preporu~uje ovakva forma.
if(broj %2 != 0) ++broj; //ovako ne bi trebalo, mada je mogu}e
Ako je potrebno da se kao rezultat iskaza if izvr{i vi{e iskaza, a ne samo jedan kao u prethodnom
primeru, mogu se uporebiti viti~aste zagrade.
if(izraz){
iskaz1;
iskaz2;

}
Primer:
if(broj % 2 != 0){ //proverava se da li je broj neparan
++broj; //ako je neparan, neka postane paran
System.out.println(“Broj je pretvoren u paran i njegova vrednost je sada “ + broj);
}
Ako je izraz ocenjen kao ta~an, izvr{avaju se svi iskazi izme|u viti~astih zagrada, a ako nije, ne
izvr{ava se nijedan.

Klauzula else
Osnovni iskaz if mo`e da se pro{iri klauzulom else.
if(izraz)
iskaz1;
else
iskaz2;
Iskaz ili iskazi koji slede iza klauzule elese se izvr{avaju samo u slu~aju da izraz u klauzuli if nije
ta~an. Ako je potrebno da se u klauzuli else izvr{i vi{e iskaza tako|e se mogu uporebiti viti~aste
zagrade.
if(izraz){
iskaz1;

}else{
iskaz2;

}

Klauzula else if
Ukoliko prilikom dono{enja oluke postoji vi{e mogu}nosti, mo`e se upotrebiti klauzula else if.
if(izraz1)
iskaz1;
else if(izraz2)
iskaz2;
else if(izraz3)
iskaz3;
else
iskaz4;

14
Ako je vrednost izraza izraz1 ocenjena kao ta~na, izvr{ava se iskaz1. Ako izraz nema vrednost true,
proverava se vrednost izraza izraz2. Ako je njegova vrednost ta~na, izvr{ava se iskaz iskaz2. Posle
izvr{enja iskaza iskaz2 program se nastavlja kodom koji sledi iza celog iskaza if. Ako vrednost
izraza izraz2 nije true, proverava se vrednost izraza izraz3 itd. Ako nijedan od izraza u klauzulama
else if nije ocenjen kao ta~an (true), izvr{ava se iskaz (iskazi) iza klauzule else, ako ona postoji.
Primer:
public class IfElseDemo {
public static void main(String[] args) {

int rezultatTesta = 76;


char ocena;

if (rezultatTesta >= 90) {


ocena = 'A';
} else if (rezultatTesta >= 80) {
ocena = 'B';
} else if (rezultatTesta >= 70) {
ocena = 'C';
} else if (rezultatTesta >= 60) {
ocena = 'D';
} else {
ocena = 'F';
}
System.out.println("Ocena = " + ocena);
}
}
Izlaz iz programa je:
Ocena = C;
Kao {to vidite vrednost promenljive rezultatTesta mo`e da zadovolji vi{e od jednog uslova, jer je
76 >= 70, a tako|e je i rezultatTesta >= 60. Ocena je ipak C, zato {to se izvr{ava samo prvi blok
koda koji pripada izrazu rezultatTesta >= 70. Kada se izvr{i taj blok, kontrola programa prelazi na
kod iza iskaza if, u ovom slu~aju na iskaz System.out… Izrazi koji slede iza izraza koji je bio
zadovoljen se ne proveravaju, a samim tim se i ne izvr{ava pripadaju}i kod.
Iskazi if mogu biti ugne`deni. U okviru jednog if iskaza mo`e da se na|e drugi, u okviru tog drugog,
tre}i itd. Evo kako to izgleda:
if(izraz1){
if(izraz1-1){
if(izraz1-1-1)
iskaz1-1-1;
}else
iskaz1-1;
}

Iskaz switch
Ovaj iskaz se koristi za uslovno izvr{avanje iskaza na bazi vrednosti celobrojnog izraza. U primeru
koji sledi je upotrebljen iskaz switch koji na osnovu celobrojne vrednosti mesec {tampa ime
meseca, na koji promenljiva ukazuje.
public class SwitchDemo {
public static void main(String[] args) {

int mesec = 8;
switch (mesec) {
case 1: System.out.println("Januar"); break;
case 2: System.out.println("Februar"); break;

15
case 3: System.out.println("Mart"); break;
case 4: System.out.println("April"); break;
case 5: System.out.println("Maj"); break;
case 6: System.out.println("Jun"); break;
case 7: System.out.println("Jul"); break;
case 8: System.out.println("Avgust"); break;
case 9: System.out.println("Septembar"); break;
case 10: System.out.println("Oktobar"); break;
case 11: System.out.println("Novembar"); break;
case 12: System.out.println("Decembar"); break;
}
}
}
Rezultat ovog programa je Avgust. Isti efekat se mogao posti}i i pomo}u iskaza if:
int mesec = 8;
if (mesec == 1) {
System.out.println("Januar");
} else if (month == 2) {
System.out.println("Februar");
}
…… itd.
Stvar je li~nog izbora koji }ete od ovih metoda koristiti. Prilikom dono{enja odluke treba imati u
vidu iskaz switch odluku mo`e da donese samo na osnovu celobrojne vrednosti, dok se u iskazu if
mogu da koriste razli~iti uslovi.
Verovatno ste u prethodnom kodu primetili prisustvo iskaza break. Ovaj iskaz se naj~e{}e koristi
zajedno sa iskazom switch, jer se bez njega kontrola toka programa, nakon izvr{enja pravog iskaza,
prenosi na slede}i iskaz u switch bloku. Ako se doda iskaz break, onda se kontrola toka, nakon {to
se izvr{i pravi iskaz, prenosi na kod koji sledi iza iskaza switch.
Na~in kontrole toka programa u iskazu switch (bez iskaza break) mo`e ponekad i da bude od
koristi. Evo primera u kome smo to iskoristili:
public class SwitchDemo2 {
public static void main(String[] args) {

int mesec = 2;
int godina = 2000;
int brojDana = 0;

switch (mesec) {
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
brojDana = 31;
break;
case 4:
case 6:
case 9:
case 11:
brojDana = 30;
break;
case 2:
if ( ((godina % 4 == 0) && !(godina % 100 == 0))
|| (godina % 400 == 0) )
brojDana = 29;
else
brojDana = 28;
break;

16
}
System.out.println("Broj dana je " + brojDana);
}
}
Izlaz iz programa je:
Broj dana je 29
Ovaj program izra~unava broj dana u mesecu za zadatu godinu i mesec. Kao {to vidite svi meseci
koji imaju 31 dan su bez iskaza break, koji postoji samo kod poslednjeg u nizu. Isto va`i i za mesec
koji imaju 30 dana (i oni su grupisani i postoji samo jedan iskaz break).
Ako `elite da se neki iskazi izvr{e u slu~aju da nijedan od case iskaza nije zadovoljen, mo`ete da
upotrebite klauzulu default. Iskazi koji slede iza ove klauzule se izvr{avaju ako nijedan slu~aj
(case) nije zadovoljen. Evo kako izgleda prepravljen program iz prvog primera, sada sa dodatom
klauzulom default:
public class SwitchDemo {
public static void main(String[] args) {

int mesec = 8;
switch (mesec) {
case 1: System.out.println("Januar"); break;
case 2: System.out.println("Februar"); break;
case 3: System.out.println("Mart"); break;
case 4: System.out.println("April"); break;
case 5: System.out.println("Maj"); break;
case 6: System.out.println("Jun"); break;
case 7: System.out.println("Jul"); break;
case 8: System.out.println("Avgust"); break;
case 9: System.out.println("Septembar"); break;
case 10: System.out.println("Oktobar"); break;
case 11: System.out.println("Novembar"); break;
case 12: System.out.println("Decembar"); break;
default: System.out.println("Niste uneli ispravan broj za mesec");break;

}
}
}

Petlje
Petlje se koriste za izvr{avanje dela koda koji se ponavlja. U Javi postoje tri vrste petlji: while, do
while i for.

Petlja while
Ova petlja se koristi za ponovljeno izvr{avanje bloka iskaza sve dok je uslov ta~an. Evo kako
izgleda ta petlja:
while(izraz){
iskazi..
}
Prvo se izra~unava vrednost izraza. Ta vrednost mora biti tipa boolean. Ako je vrednost izraza true
(ta~no), izvr{avaju se iskazi koji pripadaju petlji. Posle izvr{avanja iskaza, ponovo se proverava
vrednost izraza, i ako je ta vrednost true, ponovo se izvr{avaju iskazi. Ovo se ponavlja sve dok je
vrednost izraza ocenjena kao ta~na (true).
U primeru koji sledi se pomo}u petlje while ide kroz string. Ovo se ponavlja sve dok se ne nai|e na
karakter g. Svaki karakter koji nije g se dodaje u objekat StringBuffer. Na kraju se rezultuju}i string
{tampa.
public class WhileDemo {

17
public static void main(String[] args) {

String kopirajOdMene = "Kopiraj ovaj string sve dok se ne " +


" dodje do slova 'g'.";
StringBuffer kopirajUMene = new StringBuffer();

int i = 0;
char c = kopirajOdMene.charAt(i);

while (c != 'g') {
kopirajUMene.append(c);
c = kopirajOdMene.charAt(++i);
}
System.out.println(kopirajUMene);
}
}
Izlaz iz ovog programa je:
Kopiraj ovaj strin

Petlja do-while
Ova petlja je sli~na sa petljom while. Sintaksa za petlju do-while je:
do{
iskazi..
}while(izraz);
Razlika u odnosu na petlju while je u tome da se kod petlje while uvek prvo proveri vrednost izraza,
pa se tek u zavisnosti od rezultata izvr{ava telo petlje. Kod petlje do-while se telo petlje uvek
izvr{ava makar jednom, a tek posle prvog izvr{enja se proverava vrednost izraza.
Evo kako izgleda prethodni primer, ali sa petljom do-while:
public class DoWhileDemo {
public static void main(String[] args) {

String kopirajOdMene = "Kopiraj ovaj string sve dok se ne " +


" dodje do slova 'g'.";
StringBuffer kopirajUMene = new StringBuffer();

int i = 0;
char c = kopirajOdMene.charAt(i);

do {
kopirajUMene.append(c);
c = kopirajOdMene.charAt(++i);
} while (c != 'g');
System.out.println(kopirajUMene);
}
}

Petlja for
Op{ti oblik ove petlje je:
for(inicijalizacija; uslov_petlje; izraz petlje){
iskazi…
}
Deo ozna~en sa inicijalizacija se izvr{ava jednom pre pokretanja petlje. Tu se obi~no inicijalizuje
broja~ petlje. Izvr{avanje petlje se nastavlja sve dok se uslov_petlje izra~unava kao ta~an. Ovaj
izraz se proverava na po~etku svakog izvr{enja petlje. Kada njegova vrednost bude false (neta~no),
18
program se nastavlja kodom koji sledi iza petlje. Izraz ozna~en sa izraz_petlje se izvr{ava na kraju
petlje. Obi~no se tu pove}ava ili smanjuje broja~ petlje za neku zadatu vrednost.
Primer:
Public class ForPetlja{
public static void main (String[] args){
int limit = 20; // Trazi se suma od 1 do ove vrednosti
int sum = 0; // vrednost sume
for(int i = 1; i <= limit’ i++)
sum += i;
System.out.println(“suma = “ + sum);
}
}
Broja~ petlje mo`e biti i realan broj.
Petlje mogu da se ugne`davaju. Prvo se izvr{ava unutra{nja petlja, pa tek onda spolja{nja.

Iskazi continue i break kao delovi petlje


Ako `elite da se u nekom prolazu kroz petlju presko~i neki njen deo i da se izvr{enje nastavi od
po~etka petlje, mo`ete upotrebiti iskaz continue.
Primer:
for(int i = 1; i <= limit’ i++){
if(i % 3 == 0)
continue; // preskace se ostatak iteracije
sum += i;
}
Iskaz break se mo`e upotrebiti za trenutni prekid petlje. Program se iskazom break nastavlja kodom
koji sledi iza petlje. Sledi primer u kome se pronalaze prosti brojevi. Prost broj je onaj koji nije
deljiv bez ostatka ni sa jednim drugim brojem (osim sa 1).
public class ProstiBrojevi{
public static void main (String[] args){
int nVrednost = 50; // maksimalna vrednost koja se proverava
boolean prostBroj = true; // tacno ako je prost broj
// provera svih vrednosti od 2 do nVrednost
for(int i = 2; i <= nVrednost; i++){
prostBroj = true; // pretpostavka da je trenutna vrednost prost broj
for(int j = 2; j < i; j++){
if(i % j == 0){ //tacno ako j deli bez ostatka
prostBroj = false; // ako smo dospeli do ovde, postojalo je deljenje
bez ostatka, sto znaci da nije prost broj
break;
}
}
// ispisivanje prostih brojeva
if(prostBroj) // da li je to prost broj
System.out.println(i); // u pitanju je prost broj pa se ispisuje
}
}
}
Ispisuju se prosti brojevi od 1 do nVrednost (u ovom slu~aju 50). Spolja{nja petlja ide kroz sve
brojeve koje treba proveriti. Broja~ te petlje je i. Za svako i, unutra{nja petlja proverava da li
postoji neki broj sa kojim se to i mo`e da podeli bez ostatka. Ako mo`e, to zna~i da nije u pitanju
prost broj i da treba napustiti unutra{nju petlju (za to slu`i iskaz break).
Na kraju se svi prona|eni prosti brojevi {tampaju.

19
Nizovi i stringovi
Niz je struktura podataka koja se sastoji od zadatog broja stavki, pri ~emu su sve stavke (elementi)
istog tipa. ^lanovi niza se u Javi uvek numeri{u po~ev od 0. Jedan niz, na primer, mo`e da sadr`i
100 celobrojnih vrednosti, koje su numerisane od 0 do 99. Niz se deklari{e na slede}i na~in:
int[] niz;
Ovo je deklaracija niza. U ovom trenutku niz jo{ uvek nema dodeljenu memoriju.
U trenutku kreiranja niza se defini{e njegova du`ina i dodeljuje se potrebna memorija. Nizovi u Javi
su objekti pa se u skladu sa time kreiraju pomo}u operatora new. Iskaz koji sledi zauzima dovoljno
memorije za niz od deset celobrojnih vrednosti i zatim taj niz dodeljuje promenljivoj niz, koju smo
ranije deklarisali.
niz = new int[10];

Pristup elementima niza


Elementima niza se pristupa preko imena niza, iza kojeg u uglastim zagradama sledi indeks
elementa, kome se pristupa. Na primer, iskaz
niz[4]
pristupa petom elementu niza.
Java proverava da li element niza kome pristupate postoji. Ako poku{ate da pristupite nepostoje}em
elementu niza javi}e se izuzetak tipa IndexOutOfBoundsException.

Veli~ina (du`ina) niza


Veli~inu niza }ete dobiti na slede}i na~in:
imeNiza.length
Sledi primer koji pokazuje kako se pristupa elementima niza i kako se odre|uje njegova veli~ina.
for (int i = 0; i < niz.length; i++) {
niz[i] = i;
System.out.print(niz[i] + " ");
}

Inicijalizacija nizova
Elementima niza se mogu odmah u toku definisanja dodeliti vrednosti. Evo kako se to radi:
boolean[] answers = { true, false, true, true, false };
Veli~ina niza je u ovom slu~aju odre|ena brojem elemenata. Ako zadajete inicijalne vrednosti niza,
morate da ih zadate za sve elemente.
U primeru koji sledi je pokazano kako se odre|uje element niza sa najve}om vredno{}u.
public class MaxNiz{
public static void main (String[] args){
double[] A = {2., 5., 3., 12.5, 5.3, 17.5};
double max = A[0];
for (int i = 1; i < A.length; i++) {
if (A[i] > max)
max = A[i];
}
System.out.println("Maksimum je " + max);
}
}

20
Kopiranje niza
Kopiranje niza se vr{i tako {to se u novi niz kopira svaki novi element niza zasebno. Iskazi:
double [] A = {1.,4..6.};
double [] B = A;
ne dovode do kopiranja niza A u niz B. U ovom slu~aju je samo napravljena nova promenljiva B,
koja ukazuje na isti niz kao i promenljiva A. Ako se `eli kopiranje treba napisati:
double[] B = new double[A.length]; //Pravi se novi niz, iste velicine kao
A
for (int i = 0; i < A.length; i++)
B[i] = A[i]; // Kopira se svaki element iz A u B.

Vi{edimenzionalni nizovi
Niz kao elemente mo`e da ima druge nizove.
Pretpostavimo da `elite da pratite vremenske prilike na 10 razli~Itih geografskih lokacija, tokom
jedne godine. Ho}ete da merite temperaturu na svakoj od ovih lokacija u toku svakog dana u godini.
Ovo mo`ete da ostvarite pomo}u niza od 10 elemenata, ~iji je svaki element drugi niz od 365
~lanova. Ovakav niz bi se deklarisao na slede}i na~in:
float [] [] temperatura = new float [10] [365];
Ovaj niz ima dve dimenzije, pa je zna~i u pitanju dvodimenzionalan niz. Prva dimenzija se kre}e od
0 do 9 i odnosi se na geografsku lokaciju, a druga se kre}e od 0 do 364 i odnosi se na temperature.
Ako `elite da uka`ete na temperaturu u toku stotog dana na {estoj lokaciji mo`ete da napi{ete:
temperatura [5] [99]
U primeru koji sledi }emo vrednosti za temperaturu generisati po slu~ajnom principu. Uzima}emo
nasumi~ne vrednosti izme|u -10 i +35 stepeni Celzijusa.
public class Vreme {
public static void main(String[] args) {
float[][] temperatura = new float[10][365];
// generisanje temperature
for(int i = 0; i < temperatura.length; i++)
for(int j = 0; j < temperatura[i].length; j++)
temperatura [i][j] = (float) (45.0 * Math.random() - 10.0);

//izracunavanje prosecne vrednosti za temperaturu


for(int i = 0; i < temperatura.length; i++){
float prosek = 0.0f; // prosecna vrednost
for(int j = 0; j < temperatura[i].length; j++)
prosek += temperatura[i][j];

//prikaz prosecne temperature za trenutnu lokaciju


System.out.println("Prosecna temperatura na lokaciji " + (i+1) + " je " +
prosek/(float) temperatura[i].length);
}
}
}

Nizovi nizova promenljive du`ine


Kada su elementi jednog niza drugi nizovi, oni ne moraju biti iste du`ine. Niz se mo`e deklarisati na
slede}i na~in:
float primer [] [];
Ovim se deklari{e niz primer tipa float. Broj elemenata u prvoj dimenziji se mo`e zadti izrazom:
primer = new float [6] []; // definicija sest elemenata, od kojih je svaki niz

21
Sada imamo dodeljenih {est elemenata od kojih svaki mo`e da sadr`i jednodimenzionalni niz. Ti
nizovi se dalje mogu definisati pojedina~no:
primer[2] = new float [6];
primer[5] = new float[10];
Ukoliko bismo hteli da niz primer ima trougaoni oblik, odnosno da prvi element bude niz sa jednim
elementom, drugi niz sa dva elementa, tre}i niz sa tri elementa itd., mogli biste da napi{ete:
for(int i = 0; i < primer.length; i++)
primer[i] = new float[i+1];
Niste ograni~eni na dve dimenzije. Niz mo`e da ima i vi{e dimenzija. Na primer niz sa tri dimenzije
se mo`e deklarisati na slede}i na~in:
int [] [] [] triDim= new int[3] [] []; // tri dvodimenzionalna niza
Svaki od ova tri elementa u prvoj dimenziji niza mo`e da sadr`i razli~it dvodimenzionalni niz, tako
da mo`ete da napi{ete:
triDim[0] = new int[4] [];
triDim[1] = new int[2] [];
triDim[2] = new int[5] [];
Dalje bismo mogli da napi{emo:
triDim[0][1] = new int[3]; //itd

Nizovi karaktera
Nizovi koje smo dosada pominjali su bili numeri~ki nizovi. Mnogo ~e{}e od numeri~kih nizova
}ete koristiti nizove znakova (karaktera). Mo`ete na primer, da deklari{ete promenljivu niza tipa
char, sa 50 ~lanova:
char[] poruka = new char[50];
Sa nizovima karaktera se obi~no ne radi preko ovakvih nizova. U Javi postoji posebna klasa koja se
koristi specijalno za rad sa karakterima. To je klasa String. U pitanju je standardna klasa koja dolazi
zajedno sa Javom.

String literali
Do sada smo ve} vi{e puta koristili String literale. Skoro svaki put kada smo koristili iskaz println,
kao argument smo koristili i string literal. String literal je bilo koja vrednost napisana izme|u
dvostrukih navodnika:
“Ovo je string literal”
Ovo je konstantan objekat klase String, koji kompajler pravi za upotrebu u programu. Ako u okviru
Stringa `elite da ubacite i neki specijalni karakter, kao {to je znak za novi red, ili tabulator morate
da koristite escape sekvencu. Iskaz
System.out.println(“Ovo je \n String konstanta”);
Dodaje novi red kod {tampanja.
Znak \n je oznaka za novi red. Ovaj kod daje slede}i izlaz:
Ovo je
String konstanta

22
Objekti tipa string
Promenljiva tipa String je u stvari objekat klase String. Ova promenljiva se deklari{e sli~no kao i
ostale promenljive osnovnih tipova. Ako je potrebno ova promenjiva se mo`e inicijalizovati odmah
prilikom deklaracije:
String mojString = “Moj prvi string”;
Promenljiva mojString sadr`i referencu na deo memorije u kome se ~uva sam string. Mo`ete da
napi{ete:
mojString = “Ovo je drugi string”;
Promenljiva mojString sada ukazuje na drugi deo memorije, sa drugim stringom, a prvi se odbacuje.
Objekti klase String su nepromenljivi. Ako `elite da promenite sadr`aj stringa morate da odbacite
staru referencu i da napravite novu. O izbacivanju starog stringa brine sama Java preko skuplja~a
otpada. To je mehanizam koji objekte i promenljive koji vi{e nisu potrebni, posle izvesnog vremena
izbacuje iz memorije.
Promenljiva tipa string mo`e da se inicijalizuje i na null vrednost. Iskaz
String mojString = null;
deklari{e promenljivu mojString koja ne ukazuje ni na jedan string. Dobra programerska praksa je
da stringove kojima `elite da vrednost dodelite kasnije, uvek inicijalizujete na ovaj na~in.

Operacije nad stringovima

Spajanje stringova
Spajanje dva stringa se mo`e ostvariti putem operatora +.
mojString = “Prvi string se spaja “ + “ sa drugim”;
Operacijom spajanja stringova preko operatora + se pravi potpuno novi objekat tipa String koji je
nezavisan od operanada. Na taj novi objekat ukazuje promenljiva mojString.
Za spajanje stringova mo`ete da upotrebite i operator +=:
String fraza = “Spajanje je “ ;
fraza += “moguce izvrsiti i ovako”;
Ovim se ne menja string “Spajanje je “. String na koji promenljiva fraza ukazuje posle nakon
izvr{enja drugog iskaza je potpuno novi objekat.
Primer:
public class StringProba {
public static void main(String[] args) {
String prviString = "Puno ";
String drugiString = "ruku ";
String treciString = "olaksavaju posao";

String mojString; // promenljiva za smestaj rezultata


mojString = prviString + drugiString + treciString;
System.out.println(mojString);

// konverzija celih brojeva u string i spajanje sa dva stringa


int brojRuku = 99;
mojString = brojRuku + " " + drugiString + treciString;
System.out.println(mojString);

//kombinacija stringa i celih brojeva


mojString = "pedeset pet je " + 5 + 5;
System.out.println(mojString);

23
// kombinacija celih brojeva i stringa
mojString = 5 + 5 + " je deset";
System.out.println(mojString);
}
}
Prvo spajanje je jednostavno i spaja tri stringa. Tri promenljive prviString, drugiString i treciString
se spajaju i sme{taju u ~etvrtoj promenljivoj mojString.
Drugo spajanje stringova se odnosi na spajanje celog broja 99 i stringa “ “. Ovde pre samog
spajanja dolazi do konverzije numeri~ke vrednosti brojRuku u String, nakon ~ega se to spaja sa
stringom “ “. Razlog je u tome {to je operator + levo asocijativan, pa se parovi kod spajanja
uskla|uju sa leve strane. Ovo je bitno kod slede}a dva spajanja.
Iskazi izgledaju sli~no, ali u jednom slu~aju 5 + 5 daje 55, a u drugom 10.
Razlika je u tome da kod prvog iskaza prilikom sabiranja uvek postoji makar jedan operand tipa
string, tako da se uvek radi o spajanju stringova. U drugom iskazu je prva operacija matemati~ko
sabiranje, a rezultat se konvertuje u String da bi se omogu}ilo spajanje sa literalom “je 10”.

Pore|enje stringova
Osnovni tipovi se porede pomo}u operatora ==. Za objekte tipa String (ili bilo koje druge objekte)
ovo ne va`i. Iskaz
string1 == string2
}e proveriti da li ove dve promenljive ukazuju na isti string. Ako referenciraju (ukazuju) na
razli~Ite stringove, bez obzira na to da li je sadr`aj tih stringova identi~an, ovaj iskaz vra}a false
(neta~no). Drugim re~ima, ovaj iskaz ne poredi same stringove, ve} reference na stringove.
Primer:
public class PoredjenjeStringova {
public static void main(String[] args) {
String string1 = "Suvise " ;
String string2 = "kolacica";
String string3 = "Suvise kolacica";

string1 += string2;

System.out.println("Test 1");
System.out.println("string3 je sada: " + string3);
System.out.println("string1 je sada: " + string1);

if(string1 == string3){
System.out.println("string1 == string3 je tacno " + "string1 i string3
referenciraju na isti string");
}else{
System.out.println("string1 == string3 je netacno " + "string1 i string3
ne referenciraju isti string");
}

// sada string1 i string3 referenciraju na iste stringove


string3 = string1;

System.out.println("Test 2");
System.out.println("string3 je sada: " + string3);
System.out.println("string1 je sada: " + string1);
if(string1 == string3){
System.out.println("string1 == string3 je tacno " + "string1 i string3
referenciraju na isti string");
}else{

24
System.out.println("string1 == string3 je netacno " + "string1 i string3
ne referenciraju isti string");
}
}
}
Na po~etku su definisane i inicijalizovane tri promenljive tipa String. Nakon iskaza dodele sadr`aj
promenljivih string1 i string3 }e biti identi~an, ali pore|enje po jednakosti ipak vra}a false, po{to
promenljive ukazuju na dva razli~ita stringa.
Nakon toga smo promenili promenljivu string3, tako da ukazuje na isti objekat kao i string1. U tom
slu~aju iskaz if se ocenjuje kao ta~an, po{to string1 i string3 ukazuju na isti objekat.
Ako `elite da uporedite dve promenljive tipa String i da utvrdite da li je njihov sadr`aj identi~an,
koristi}ete metod equal, klase String. Ovaj metod poredi stringove sa pravljenjem razlike izme|u
malih i velikih slova. Dva stringa su jednaka ako su iste du`ine, ako imaju isti broj znakova i ako je
svaki znak u jednom stringu identi~an odgovaraju}em znaku u drugom.
Ako ne `elite da se pravi razlika izme|u malih i velikih slova, mo`ete da koristite metod
equalIgnoreCase().
Primer:
public class PoredjenjeStringova1 {
public static void main(String[] args) {
String string1 = "Suvise " ;
String string2 = "kolacica";
String string3 = "Suvise kolacica";

string1 += string2;

System.out.println("Test 1");
System.out.println("string3 je sada: " + string3);
System.out.println("string1 je sada: " + string1);

if(string1.equals(string3)){
System.out.println("string1.equals(string3) je tacno " + "string1 i
string3 su jednaki");
}else{
System.out.println("string1.equals(string3) je netacno " + "string1 i
string3 nisu jednaki");
}

// razlikuje se velicina slova


string3 = "SUVISE kolacica";

System.out.println("Test 2");
System.out.println("string3 je sada: " + string3);
System.out.println("string1 je sada: " + string1);
if(string1.equals(string3)){
System.out.println("string1.equals(string3) je tacno " + "string1 i
string3 su jednaki");
}else{
System.out.println("string1.equals(string3) je netacno " + "string1 i
string3 nisu jednaki");
}

if(string1.equalsIgnoreCase(string3)){// poredjenje uz zanemarivanje malih i


velikih slova
System.out.println("string1.equalsIgnoreCase(string3) je tacno " +
"string1 i string3 su jednaki, ali ako se ne pravi razlika izmedju malih i
velikih slova");
}else{
System.out.println("string1equalsIgnoreCase(string3) je netacno " +
"string1 i string3 nisu jednaki");

25
}
}
}
Pre nego {to se pozabavimo primerom objasni}emo sintaksu koja je vezana za objekte.
U iskazu if smo pozvali metod equals(), objekta string1. To je ista sintaksa koju smo koristili i za
poziv metode println, objekta out. Sintaksa za pozivanje metoda nekog objekta je:
imeObjekta.imeMetoda(lista argumenata odvojenih zarezima)
Metod equals() zahteva jedan argument, tipa String. U pitanju je string koji se poredi sa originalnim
objektom. Metod vra}a true (ta~no) ako je vrednost koja mu je prosle|ena (u ovom primeru string3)
identi~na sa stringom ~iji je metod equals() pozvan. Va`i i obrnuto:
string3.equals(string1)
pri ~emu se dobija isti rezultat.
Metod equalsIgnoreCase() poredi stringove, ali se pri tome zanemaruje razlika izme|u malih i
velikih slova. U skladu sa tim rezultat poslednjeg pore|enja je true (ta~no) jer se stringovi razlikuju
samo po velikim i malim slovima.

Po~etak i kraj stringa


Metod startsWith() klase String omogu}ava proveru da li neki string po~inje odre|enom
kombinacijom znakova. Ako je
string1 = “Suvise kolacica”;
onda iskaz
string1.startsWith(“Suv”)
vra}a true. Prilikom pore|enja se vodi ra~una o malim i velikim slovima, tako da iskaz
string1.startsWith(“sUV”)
vra}a false.
Ako `elite da proverite da li se string zavr{ava nekom kombinacijom karaktera, koristi}ete metod
endsWith(), klase String. Iskaz
string1.endsWith(“ica”) vra}a true. I ovde se pravi razlika izme|u malih i velikih slova.

Pristup pojedinim znakovima u stringu


Vrlo ~esto se javlja potreba za pristupom odre|enom znaku ili znacima koji su deo stringa.
Odre|enom karakteru u stringu se pristupa preko celobrojnog indeksa, koji ozna~ava poziciju znaka
u stringu, ra~unaju}i od po~etka. Prvi znak u stringu je na poziciji 0, drugi na poziciji 1 itd. Po{to
je String objekat, to se i karakterima koji ga ~ine pristupa preko odre|enog metoda. U pitanju je
metod charAt(). Ovaj metod prihvata argument koji predstavlja poziciju karaktera u stringu,
odnosno indeks. Ako poku{ate da upotrebite indeks koji je manji od 0 ili ve}i od du`ine niza, desi}e
se gre{ka u programu.
Da bi se izbegle gre{ke ovakvog tipa potrebno je poznavati du`inu stringa. U tu svrhu se koristi
metod length() objekta tipa String.
U primeru koji sledi je dat program koji analizira odre|eni tekst i odre|uje broj samoglasnika,
razmaka i slova koji ga ~ine.
Primer:
public class KarakteriStringa {
public static void main(String[] args) {
// string koji se analizira

26
String tekst = "Ovo je tekst koji sluzi za vezbu prilikom pristupanja
elementima stringa.";
int razmaci = 0, samoglasnici = 0, slova = 0;// broj razmaka, samoglasnika i
slova u tekstu
int duzinaTeksta = tekst.length();
for (int i = 0; i < duzinaTeksta; i++){
char ch = Character.toLowerCase(tekst.charAt(i));

// provera da li je samoglasnik
if(ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u')
samoglasnici++;
// provera da li je slovo
if(Character.isLetter(ch))
slova++;

// provera da li je razmak
if(Character.isWhitespace(ch))
razmaci++;
}
System.out.println("Tekst sadrzi: samoglasnika - " + samoglasnici + "\n" +
" suglasnika - " +(slova-samoglasnici) + "\n" +
" razmaka - " + razmaci);
}
}
Metod charAt(i) se koristi za odre|ivanje znaka na i-oj poziciji u stringu. Karakter koji se dobija se
pretvara u malo slovo, radi lak{eg ispitivanja da li je u pitanju samoglasnik. Karakter se u pretvara
u malo slovo pomo}u metoda toLowerCase() klase Character. Ovo je klasa koja je u Javi unapred
definisana i slu`i za rad sa karakterima.
Kasnije se u kodu pomo}u metoda isLetter(), klase Character, proverava da li je u pitanju slovo i
pomo}u metoda isWhiteSpace() iste klase, da li je u pitanju razmak (blanko karakter).
Ako `elite da ceo string pretvorite u mala ili velika slova mo`ete uporebiti metode toLowerCase() i
toUpperCase(), klase String. U tom slu~aju se ceo string pretvara u tekst sa samo malim, odnosno
samo velikim slovima.
String tekst = “Ovo su me{ovita slova?”;
String tekstMala = tekst.toLowerCase(); // ovo su samo mala slova
String testVelika = tekst.toUpperCase(); // ovo su samo velika slova

Pretra`ivanje stringova u potrazi za odre|enim karakterima


Ako `elite da u okviru stringa prona|ete odre|eni karakter koristi}ete metode indexOf() i
lastIndexOf(), koji pripadaju klasu String.
int indeks = 0;
indeks = tekst.indexOf(‘a’);
U prethodnom iskazu se pretra`uje sadr`aj stringa tekst i to po~ev{i od po~etka. Vra}a se pozicija
indeksa prvog karaktera ‘a’ na koji se nai|e. Ako slovo ‘a’ ne postoji u stringu, vrati}e se -1.
Oba pomenuta metoda vra}aju ili indeks pojavljivanja karaktera koji se tra`i ili -1, ako karakter nije
prona|en. Zato je va`no da se uvek proverava da li je vrednost koju vra}aju -1 i da se u zavisnosti od
toga izvr{avaju dalje akcije.
Ako `elite da prona|ete poslednje pojavljivanje karaktera ‘a’ u nizu tekst napisa}ete:
indeks = tekst.lastIndexOf(‘a’);
Ako `elite da prona|ete poziciju znaka koji nije ni na po~etku ni na kraju, mo`ete da koristite
varijaciju ovih metoda. U ovom slu~aju se metodima {alju dva argumenta. Pored karaktera koji se
tra`i, zadaje se i pozicija od koje treba da se tra`i.
indeks = tekst.index(‘a’, startIndeks);

27
Ovde se tra`i karakter koji je zadat kao prvi argument, ali po~ev od pozicije koja je zadata kao drugi
argument. U primeru koji sledi se pronalazi prvo pojavljivanje karaktera ‘b’, ali iza prvog
pojavljivanja karaktera ‘a’.
int aIndeks = -1;
int bIndeks = -1;
aIndeks = tekstIndexOf(‘a’);
if(aIndeks >= 0)
bIndeks = tekst.indexOf(‘b’, ++aIndeks);
Ako napi{ete
indeks = tekst.lastIndexOf(‘b’, aIndeks);
onda tra`ite poslednje pojavljivanje karaktera ‘b’ u stringu tekst, ali po~ev od indeksa aIndeks.

Pretra`ivanje stringova u potrazi za odre|enim potstringovima


Postoje i verzije metoda indexOf() i lastIndexOf() koje kao argumente prihvataju znakovni podniz.
U tom slu~aju se tra`i ceo zadati podniz, a ne samo jedan karakter. U svemu ostalom ovi metodi
rade potpuno isto kao verzije koje smo pomenuli u prethodnom odeljku.
indeks = tekst.indexOf(“ovo je”);
U ovom slu~aju se vra}a pozicija prvog pojavljivanja podstringa “ovo je” u okviru stringa tekst.
U primeru koji sledi se pretra`uje zadati string u potrazi za svim pojavljivanjima zadatog
podstringa. Vra}a se broj pojavljivanja podstringa u okviru glavnog stringa.
Primer:
public class PodstringoviStringa {
public static void main(String[] args) {
// string koji se analizira
String tekst = "Ovo je string koji sluzi za probu. " +
"U njemu treba proveriti koliko puta se pojavljuje kombinacija 'je'";
int brojac = 0;// broj pojavljivanja
int indeks = -1; // trenutna pozicija indeksa

String pod = "je";


// pretraga unapred po je
indeks = tekst.indexOf(pod);
while(indeks >= 0){
brojac++;
indeks += pod.length(); // prelaz na poziciju iza poslednjeg slova prvog
pojavljivanja podstringa
indeks = tekst.indexOf(pod, indeks);
}
System.out.println("Kombinacija je se u nizu pojavljuje " + brojac + "
puta");
}
}
Preraditi program, tako da se pretra`ivanje vr{i unazad, pomo}u metoda lastIndexOf().

Izdvajanje podstringova iz zadatog stringa


U klasi String postoji metod substring() koji iz niza izdvaja zadati podstring. Postoje dve verzije
ovog metoda. Jedna iz zadatog stringa vadi podstring, po~ev od zadate pozicije, a kod druge treba
zadati po~etnu i krajnju poziciju.
String grad = “Novi Sad”;
String poslednjaRec = mesto.substring(5);
String poslednjaRec nakon izvr{enja ovog iskaza sadr`i tekst “Sad”. Brojanje indeksa po~inje od 0,
a u novom podstringu se nalazi i karakter sa te po~etne pozicije.
28
Druga verzija ovog metoda tra`i dva argumenta.
String segment = mesto.substring(3,6);
String segment posle izvr{enja ovog iskaza sadr`i tekst “i S”. Podstring se zavr{ava na jednoj
poziciji ispred indeksa koji je zadat kao kraj (6-1=5).
Za razliku od metoda indexOf() kod koje zadavanje indeksa koji je izvan dozvoljenog opsega vra}a
-1, kod metoda substring, zadavanje indeksa koji je van granica samog stringa, dovodi do pojave
gre{ke.
U primeru koji sledi se pomo}u metoda indexOf() i substring() zadati tekst razdvaja na pojedine
re~i.
Primer:
public class SubstringPrimer {
public static void main(String[] args) {
String tekst = "Ovo je string koji sluzi za probu. " +
"U njemu treba izdvojiti pojedine reci";

int count = 0;
char separator = ' ';

//odredjivanje broja podnizova


int indeks = 0;
do{
++count;
++indeks; // pomera se na mesto iza poslednje pozicije
indeks = tekst.indexOf(separator, indeks);
}while(indeks != -1);

//izdvajanje podnizova u niz


String[] subStr = new String[count];// dimenzija niza je prethodno
odre\ena
indeks = 0;
int endIndeks = 0;
for(int i = 0; i < count; i++){
endIndeks = tekst.indexOf(separator, indeks);

if(endIndeks == -1) //ako ne postoji znak separator


subStr[i] = tekst.substring(indeks); // izdvaja se do kraja
else // ako postoji separator
subStr[i] = tekst.substring(indeks, endIndeks);

indeks = endIndeks + 1; // pocetak za sledeci ciklus


}
// prikaz podnizova, odnosno reci
for(int i = 0; i < subStr.length; i++){
System.out.println(subStr[i]);
}
}
}
U prvom delu programa smo izbrojili broj reci u zadatom stringu i taj broj kasnije upotrebili za
definisanje niza. U drugom delu smo, pomo}u metoda substring, vadili iz stringa jednu po jednu
re~.

Objekti klase StringBuffer


Objekti klase String se ne mogu menjati. Ako se `eli da izvede spajanje stringova, da se postoje}i
string pro{iri ili skrati i sl., treba koristiti klasu StringBuffer. Ove operacije se mogu izvesti i
pomo}u klase String, ali je zbog nepromenljivosti ovih objekata cena ve}a. Ve}a cena se ogleda u
sporijem radu i ve}em zauzimanju memorije.

29
Objekat klase StringBuffer se mo`e napraviti na slede}i na~in:
StringBuffer primer = new StringBuffer(“String za inicijalizaciju”);
Prethodni iskaz kreira objekat klase StringBuffer i inicijalizuje ga stringom “String za
inicijalizaciju”. Objekat StringBuffer se mora kreirati uz pomo} klju~ne re~i new. Mogu}e je
napisati i slede}e:
StringBuffer mojString = null;
mojString = new StringBuffer(“Novi string”);

Kapacitet objekata StringBuffer


Objekti klase String imaju dodeljeno onoliko memorije koliko je potrebno za sme{tanje karaktera
koji se nalaze u tom stringu. Memorija dodeljena ovom objektu se vi{e ne mo`e menjati. Za razliku
od ovog, memorija koju zauzima objekat klase StringBuffer se mo`e menjati.
Kada se objekat StringBuffer pravi na osnovu postoje}eg stringa, njegov kapacitet je za 16 ve}i
du`ine stringa. Kapacitet se ovde izra`ava u karakterima koji mogu da stanu u taj objekat.
Kapacitet objekta StringBuffer nije fiksan. Prilikom kreiranja ovog objekta mo`ete da eksplicitno
zadate njegov kapacitet:
StringBuffer buf = new StringBuffer(50);
Ovaj objekat mo`e da uskladi{ti 50 znakova. Ako se prilikom deklaracije izostavi kapacitet, onda se
koristi podrazumevani kapacitet od 16 znakova. Ne treba brinuti o tome da li objekat StringBuffer
ima dovoljan kapacitet da primi va{ string, jer se njegov kapacitet automatski prilago|ava veli~ini
stringa koji u njega treba da se smesti.
Sa druge strane kapacitet objekta StringBuffer je bitan jer uti~e na upotrebu resursa koji se koriste
za skladi{tenje i modifikaciju stringova. Ako je po~etni kapacitet suvi{e mali i ako `elite da tu
ubacite neki ve}i string, onda mora da se zauzme dodatna memorija (da se pove}a kapacite objekta
StringBuffer), {to se odra`ava na produ`eno vreme procesa. Efikasnije je, ako je mogu}e, da se
kapacitet objekta unapred podesi na dovoljnu vrednost, tako da kasnije nisu potrebne promene.

Dodavanje u objekat klase StringBuffer


Ako `elite da ne{to dodate na kraj postoje}eg objekta klase StringBuffer koristi}ete metod append.
StringBuffer buf = new StringBuffer(“Novi bufer”);
buf.append(“ ovo je dodatak”);
U objektu se nakon ovog nalazi tekst “Novi buffer ovo je dodatak”. Metod append vra}a pro{ireni
objekat StringBuffer.
Postoje razli~ite varijacije metoda append, koje omogu}avaju da se u objekat dodaju i drugi
osnovni tipovi. Na primer, iskazi
StringBuffer buf = new StringBuffer(“Proba “);
buf.append(2.3);
u objekat buf dodaju tekst 2.3. Argument koji se prosle|uje metodu je tipa double, ali se on pre
dodavanja pretvara u string i kao takav se dodaje. Sli~ni metodi postoje i za ostale osnovne tipove
(int, char, boolean).
Po{to metod append vra}a isti objekat StringBuffer, to je mogu}e koristiti i slede}i iskaz:
buf.append(“dodatak “).append(2.13).append(“ i ovo je dodatak”);

Umetanje stringova u objekat klase StringBuffer


Metod append koji smo pomenuli se koristi za dodavanje sadr`aja na kraj bafera. Postoji mogu}nost
da se novi sadr`aj ubaci i negde u sredinu postoje}eg objekta klase StringBuffer. U tu svrhu se

30
koristi metod insert, klase StringBuffer. Na primer ako se u baferu buf, nalazi tekst “Ovo je bafer” i
ako izvr{ite iskaz
buf.insert(7, “dodati “);
onda se u baferu nalazi tekst “Ovo je dodati bafer”.
Drugi argument metoda insert mo`e biti i neki od osnovnih tipova, isto kao kod metoda append. I
ovde se prilikom upotrebe nekog od osnovnih tipova prvo vr{i konverzija tog podatka u string, a tek
onda se taj podatak ubacuje u bafer.

Ostali metodi klase StringBuffer


Klasa StringBuffer ima metod charAt() koji radi na isti na~in kao i kod klase String, koji smo ve}
upoznali.
U klasi StringBuffer postoji i metod setCharAt(), kojim se menja znak na zadatoj poziciji u baferu.
Metod prima dva argumenta. Prvi je indeks karaktera koji treba zameniti, a drugi je novi karakter.
buf.setCharAt(3, ‘z’);
Prethodni iskaz menja ~etvrti karakter u baferu i na njegovo mesto stavlja slovo z.
Postoji i metod za okretanje bafera, odnosno stringa koji se u njemu nalazi. U pitanju je metod
reverse, koji preokre}e string, po~ev od poslednjeg prema prvom karakteru.
StringBuffer buf = new StringBuffer(“provera”);
buf.reverse();
Iskaz buf.reverse() vra}a bafer sa sadr`ajem “arevorp”.
Vrlo ~esto }e se za same operacije sa nekim stringom koristiti objekat StringBuffer, ali }e na kraju
biti potrebno da od sadr`aja tog bafera napravimo string. Mo`e biti u pitanju {tampanje ili neka
druga operacija koja tra`i objekat tipa string. Objekat StringBuffer (kao i svi drugi objekti u Javi)
sadr`i metod toString, koji vra}a sadr`aj tog bafera, ali sada kao objekat klase String.
StringBuffer buf = new StringBuffer(“proba”);
String izlazIzBafera = buf.toString();

31
Klase i objekti
Java je programski jezik koji ima puno sli~nosti sa jezikom C++. Ipak Java je jezik koji je vi{e
objektno orijentisan. C++ sadr`i mnoge elemente koji su tu samo zbog kompatibilnosti sa jezikom
C, a koji nisu u skladu sa objektnim pristupom.
Java je sa druge strane potpuno objektno orijentisana. Ako radite u Javi pretpostavlja se da `elite da
koristite samo objektno orijentisano programiranje. U skladu sa ~injenicom da je pravljena kao
~isto objektno orijentisani jezik, to je koncepte vezane za objektno programiranje u Javi lak{e
nau~iti i prihvatiti.
Svaki programski jezik ima svoje zna~enje pojma manipulacija podacima. Ponekad program mora
da stalno vodi ra~una o tome kakva je manipulacija u pitanju. Da li se radi direktno sa objektom ili
se radi sa nekom vrstom indirektne predstave (kao pokaziva~i u C++-u) koja ima specijalnu
sintaksu.
U Javi je ovo mnogo jednostavnije. Sve se tretira kao objekat, Koristi se jedinstvena sintaksa. Iako
se sve tretira kao objekat, identifikator kojim manipuli{ete u stvari predstavlja “referencu” na
objekat. Zamislite situaciju kada sedite pred svojim televizorom (objekat) i u ruci dr`ite daljinski
upravlja~ (referenca). Dokle god dr`ite referencu imate vezu sa objektom (televizorom). Kada neko
zatra`i da promenite kanal, ili da smanjite ton, vi manipuli{ete referencom, koja dalje menja sam
objekat. Ako `elite da se {etate sobom, a da i dalje kontroli{ete objekat, sa sobom nosite referencu
(daljinski), a ne sam objekat (televizor).
Referenca mo`e da postoji i nezavisno od samog objekta. Takva referenca, sa druge strane ne mo`e
da se koristi.
Ako napi{ete
String s;
vi ste napravili samo referencu na neki objekat klase String, ali jo{ uvek niste toj referenci pridru`ili
sam objekat. Da biste mogli da ovu referencu koristite dalje u programu, morate da joj pridru`ite
neki objekat.
s = “ovo je sada objekat”;
Da biste u programu mogli da koristite neki objekat morate da pre toga imate njegovu definiciju.
Definicija objekta se naziva klasom. Kada se jednom defini{e klasa, koja opisuje osobine i
pona{anje nekog objekta, mogu se praviti konkretni primerci te klase. Ovi primerci se ~esto
nazivaju instancama.
U definiciji klase mogu da se na|u samo dve stvari:
polja - promenljive koje skladi{te podatke i koje omogu}avaju da s enapravi razlika izme|u dva
primerka iste klase.
metodi - operacije koje se mogu izvoditi sa tom klasom. Metodi obi~no rade sa poljima, odnosno
promenljivima klase.

Promenljive u definiciji klasa


U okviru klase mogu da postoje dve vrste promenljivih. To su promenljive instance i promenljive
klase.
Napomenuli smo da klasa predstavlja definiciju objekta, a da se na osnovu te definicije prave
razli~ite instance (primerci) te klase. Promenljive instance su one promenljive koje su vezane za
instance klase. Svaka instanca ima svoje vrednosti ovih promenljivih. Ove promenljive razlikuju
jedan objekat od drugog. Ako biste na primer, imali klasu osoba, sa osobinama visina, te`ina i sl.,

32
svaka instanca te klase, odnosno svaka konkretna osoba bi imali svoje vrednosti za visinu, te`inu i
ostale sli~ne osobine.
Promenljive klase je pridru`ena klasi. Ovakve promenljive pripadaju svim instancama te klase.
U primeru koji sledi se deklari{e klasa Sfera, koja opisuje sferu.
public class Sfera {
//promenljive klase
static final double PI=3.14;
static int brojac = 0; // promenljiva klase za brojanje objekata

//promenljive instance
double xCentar;
double yCentar;
double zCentar;
double radijus;

}
Klasa se u Javi defini{e preko klju~ne re~i class iza koje sledi ime klase. Sama definicija klase,
odnosno metodi i atributi, moraju biti u okviru zagrada koje slede iza imena klase. Klju~na re~
public na po~etku prethodnog primera ka`e da se ovoj klasi mo`e da pristupi bilo sa kog mesta u
programu.
Kod koji se odnosi na konkretnu klasu treba da bude u datoteci sa istim imenom i ekstenzijom .java.
Konstanta PI je u prethodnom primeru promenljiva klase. Promenljive klase se deklari{u preko
klju~ne re~i static. Ako ne `elite da se vrednost neke promenljive kasnije u programu menja,
odnosno ako `elite da to kompajler proverava i zabranjuje, mo`ete tu promenljivu deklarisati sa
final, {to je i ura|eno u prethodnom primeru. To zna~i da svaki naredni iskaz koji bi poku{ao da
promeni vrednost za promenljivu PI, ne bi bio ispravan. Ovo bi trebalo koristiti za sve konstante
koje imate u programu.
Slede}a promenljiva je tako|e definisana kao promenljiva klase (static). Ovo je promenljiva koju
}emo koristiti za brojanje koliko je instanci te klase napravljeno u programu. Svi objekti klase Sfera
}e imati samo jednu kopiju promenljivih PI i brojac.
Naredne ~etiri promenljive su promenljive instance. Svaka instanca te klase }e imati svoje primerke
promenljivih xCentar …

Metodi klase
Promenljive klase opisuju stanje objekta, ali nisu dovoljne za funkcionisanje same klase. Mora
postojati neki na~in da se sa tom klasom ne{to i uradi, a to se ~ini preko metoda.
Metoda je blok koda koji ima svoje ime i koja se mo`e izvr{avati vi{e puta sa razli~itih mesta u
programu. Pomo}u metoda mo`ete da slo`ene stvari razlo`ite na zbir manjih, kojima je lak{e
rukovati. Metoda se poziva preko njenog imena i mo`e, ali ne mora da vrati vrednost. Osnovna
struktura metode je:
povratni_tip imeMetode(arg1, arg2, .. argn){
}
Za metodu se mo`e definisati povratni tip koji se vra}a posle njenog izvr{enja. Ako ne `elite da
metoda vra}a vrednost, onda njen povratni tip treba zadati kao void.
Metodi se mogu proslediti odre|eni argumenti, koji se u telu metode koriste za neka izra~unavanja.
Metoda mo`e, ali ne mora da ima argumente. Broj argumenata je proizvoljan.

Povratna vrednost iz metode


Povratna vrednost se iz metoda vra}a preko iskaza return. Na primer, iskaz

33
return povratnaVrednost;
vra}a vrednost promenljive povratnaVrednost.
Nakon izvr{enja iskaza return, program nastavlja sa radom tamo odakle je metoda pozvana. Metode
koje vra}aju vrednost moraju da u telu metode imaju iskaz return. U metodi mo`e da postoji vi{e
iskaza return, naravno ako to zahteva logika samog programa.
Klju~na re~ return mo`e da se upotrebi i sama, bez ikakve promenljive. Ovo se koristi u metodama
koje ne vra}aju vrednost.

Lista argumenata
Izme|u zagrada koje slede iza imena metode se nalazi lista argumenata. Svaki argument mora da
ima svoj tip. Ovo su vrednosti koje se metodi prosle|uju u trenutku njenog poziva i koje ona dalje
interno koristi.
public class mojaKlasa(){
public int mojaMetoda(int a, double b){
int c;

return c;
}
}
Argumenti koji se prosle|uju metodi mogu imati neki od osnovnih tipova (int, float, double…), ali
mogu biti i drugi objekti. Ako se radi o osnovnim tipovima, onda se argumenti prosle|uju po
vrednosti. To zna~i da se za promenljivu koja se prosle|uje metodi u trenutku poziva, pravi nova
kopija, sa kojom dalje ta metoda manipuli{e. To dalje zna~i da metoda ne mo`e da promeni
vrednost promenljive u programu koji je tu metodu pozvao.
Na primer, ako negde u kodu ka`ete
int c = 3;
double d = 5.;
mojaMetoda(c, d);
onda {ta god radili sa argumentom a u samoj metodi, to ne mo`e da promeni vrednost promenljive c
u programu koji je tu metodu pozvao.
Ovo ne va`i za objekte koji se prosle|uju meetodama. Objekti se prosle|uju po referenci, tako da
metoda mo`e da promeni objekat, a to se vidi u u programu iz kojeg je metoda pozvana.
Kao {to postoje dve vrste promenljivih u klasi, tako postoje i dve vrste metoda. To su metode klase
(deklarisane preko klju~ne re~i static) i metode instance. Ako se vratimo na klasu Sfera koju smo
ranije po~eli da defini{emo:
public class Sfera{
// definicija kao i ranije
public static int getBrojac(){
return brojac;
}
}
Ovo je metoda klase. Za sve instance te klase, postoji samo jedan primerak ove metode, {to i jeste
cilj, jer ta metoda vra}a broj instanci klase koji je napravljen. U okviru metoda static ne mo`ete da
pristupate nijednoj od promenljivih instanci, jer ta metoda postoji dok jo{ nije napravljen nijedan
objekat, tako da ne mora da postoji nijedna promenljiva instance.

Pristupanje ~lanu (atributu) klase u metodi


U metodu instance mo`ete da pristupite bilo kom podatku koji je ~lan te klase. Pro{iri}emo malo
klasu Sfera, tako {to }emo dodati metodu za izra~unavanje zapremine.
public class Sfera {
//promenljive klase

34
static final double PI=3.14;
static int brojac = 0; // promenljiva klase za brojanje objekata

//promenljive instance
double xCentar;
double yCentar;
double zCentar;
double radijus;
// staticka metoda klase koja vraca broj napravljenih objekata
public static int getBrojac(){
return brojac;
}
// metoda instance koja racuna zapreminu
double zapremina(){
return 4.0/3.0 * PI * radijus* radijus* radijus;
}
}
Metoda zapremina je metoda instance. Ona nema ulazne argumente, ali vra}a vrednost tipa double,
u ovom slu~aju zapreminu sfere. U metodu se za izra~unavanje zapremine koristi promenljiva
instance radijus.

Promenljiva this
Svaka metoda instance ima promenljivu this, koja se odnosi na trenutni objekat za koji je metoda
pozvana. Kompajler implicitno koristi ovu promenljivu kada se pristupa promenljivim instance te
klase. Na primer, iskaz za vra}anje zapremine u definiciji klase Sfera bi mogao da izgleda ovako:
return 4.0/3.0 * PI * this.radijus* this.radijus* this.radijus;
Stvar je va{eg izbora da li }ete koristiti promenljivu this ili ne u svojim metodima.

Lokalne promenljive
Ako u samoj metodi zadate neke promenljive koje se koriste samo u njoj, te promenljive su lokalne
za tu metodu. @ivotni vek tih promenljivih je `ivotni vek metode. Kada se napusti metoda te
promenljive prestaju da postoje. Skuplja~ otpada u Javi brine o tome da se oslobodi memorija koju
su te promenljive zauzimale.
Ako biste na primer, definisali funkciju za promenu radijusa sfere, ona bi mogla da izgelda ovako:
void promenaRadijusa (double radijus){
this.radijus = radijus;
}
Promenljiva this.radijus ukazuje na promenljivu radijus u instanci, a promenljiva radijus na ulazni
parametar.

Inicijalizacija ~lanova klase


Prilikom definisanja ~lanova klase mo`e se izvr{iti i njihova inicijalizacija. Dobra programerska
praksa je da se sve promenljive prilikom deklaracije inicijalizuju.
public class Sfera {
//promenljive klase
static final double PI=3.14;
static int brojac = 0; // promenljiva klase za brojanje objekata

//promenljive instance
double xCentar = 10.0;
double yCentar= 10.0 ;
double zCentar = 10.0;
double radijus = 5.0;

}

35
Ako je prilikom inicijalizacije potrebno izvr{iti odre|ena izra~unavanja mo`ete da koristite blok za
incijalizaciju. Blokovi za incijalizaciju se ozna~avaju viti~astim zagradama, izme|u kojih se
stavljaju iskazi koji treba da se izvr{e.
Postoje stati~ki i obi~an blok za incijalizaciju. Stati~ki blok za incijalizaciju se deklari{e klju~nom
re~i static ispred viti~astih zagrada. Ovakav blok se izvr{ava jednom, prilikom u~itavanja klase i u
njemu se obi~no inicijalizaciju stati~ki ~lanovi klase.
Nestati~ki blok za inicijalizaciju se izvr{ava jednom prilikom kreiranja svake instance klase i u
njemu mogu da se inicijalizuju promenljive instance.
Primer:
public class ProbaInicijalizacije{
static int[] values = new int[10];
double fl;
// blok za incijalizaciju
static{
for(int i = 0; i < values.length; i++)
values[i] = i;
}
// nestaticki blok za inicijalizaciju
{
fl = 28.0;
}
}

Konstruktori
U svakoj klasi postoji jedna ili vi{e specijalnih metoda, tzv. konstruktora. Ako prilikom definisanja
klase ne zadate nijedan konstruktor, kompajler }e sam napraviti jedan, prazan, podrazumevani
konstruktor. Osnovna namena konstruktora je da obezbedi sredstva za inicijalizaciju promenljivih
instanci. Konstruktor se izvr{ava prilikom kreiranja instance klase. Ako u klasi postoje blokovi za
incijalizaciju, oni se izvr{avaju pre konstruktora.
Konstruktor ima dve osobine koje ga razlikuju od ostalih metoda klase:
Konstruktor nikada ne vra}a vrednost, tako da se za njega ne zadaje povratni tip (pa ni void)
Konstruktor uvek ima isto ime kao klasa.
Primer:
public class Sfera {
//promenljive klase
static final double PI=3.14;
static int brojac = 0; // promenljiva klase za brojanje objekata

//promenljive instance
double xCentar;
double yCentar;
double zCentar;
double radijus;
// konstruktor
Sfera(double rad, double x, double y, double z){
radijus = rad;
xCentar = x;
yCentar = y;
zCentar = z;
brojac++;
}
// staticka metoda klase koja vraca broj napravljenih objekata
public static int getBrojac(){
return brojac;
}

36
// metoda instance koja racuna zapreminu
double zapremina(){
return 4.0/3.0 * PI *radijus * radijus * radijus;
}
}
U gornjem primeru je konstuktor uokviren.
Kao {to vidite konstruktor ima isto ime kao klasa i nema odre|en povratni tip. Konstruktor mo`e da
ima vi{e agumenata, ali ne mora da ima ni jedan. U ovom slu~aju postoje ~etiri argumenta i svaki
od njih se koristi za inicijalizaciju odre|ene promenljive instance. Poslednja akcija u konstruktoru je
da se uve}a brojac, koji broji instance klase Sfera.

Kreiranje objekata klase


Kada se negde u kodu deklari{e promenljiva tipa Sfera, iskazom:
Sfera lp;
ne poziva se nikakav konstruktor. Ovde se ne prave nikakvi objekti. Sve {to se uradili je da ste
napravili promenljivu lp, koja mo`e da sadr`i jedan objekat tipa Sfera, ako ga budemo nekada
pravili. Da biste napravili instancu klase, morate da upotrebite klju~nu re~ new, iza koje sledi poziv
konstruktora. Za na{u klasu Sfera to mo`e da izgleda ovako:
lp = new Sfera(10.0, 1.0, 1.0, 1.0);
Nakon izvr{enja ovog iskaza postoji objekat Sfera sa polupre~nikom 10.0, ~iji je centar ta~ka sa
koordinatama 1.0. Promenljiva lp se nakon ovog iskaza pona{a kao referenca na objekat.
Ako biste sada napisali
Sfera josLp = lp;
nova promenljiva josLp ukazuje na isti objekat kao i promenljiva lp. Jo{ uvek postoji samo jedan
objekat (instanca), ali postoje dve promenljive koje na njega ukazuju.
^injenica da su promenljiva i objekat razdvojeni ima uticaj na na~in na koji se metodi prosle|uju
objekti kao argumenti.

Prosle|ivanje objekata metodi


Objekti se metodama prosle|uju po referenci. To zna~i da se u metodu ne radi sa kopijom objekta,
kao kada se prosle|uju promenljive osnovnih tipova, ve} se radi sa istim objektom. To dalje zna~i
da }e ako u metodu do|e do neke promene objekta, ta promena imati uticaja i na osnovni objekat
koji je metodu prosle|en.
Primer:
Datoteka SferaMain.java
public class SferaMain {
public static void main(String[] args) {
Sfera sf = new Sfera(10., 1.0, 1.0, 1.0);
System.out.println("Radijus sfere je " + sf.getRadijus());
promenaObjekta(sf);
System.out.println("Radijus sfere je " + sf.getRadijus());
}

static void promenaObjekta(Sfera sf){


sf.setRadijus(12.0);
}
}
Datoteka Sfera.java
public class Sfera {
//promenljive klase
static final double PI=3.14;

37
static int brojac = 0; // promenljiva klase za brojanje objekata

//promenljive instance
double xCentar;
double yCentar;
double zCentar;
double radijus;
// konstruktor
Sfera(double rad, double x, double y, double z){
radijus = rad;
xCentar = x;
yCentar = y;
zCentar = z;
brojac++;
}
// staticka metoda klase koja vraca broj napravljenih objekata
public static int getBrojac(){
return brojac;
}
// metoda instance koja racuna zapreminu
double zapremina(){
return 4.0/3.0 * PI *radijus * radijus * radijus;
}
public void setRadijus(double rad){
this.radijus = rad;
}
public double getRadijus(){
return this.radijus;
}
}
U ovom primeru smo prikazali dve klase. Jedna je klasa Sfera koju smo ve} koristili, ali sada
dopunjena metodama setRadijus() i getRadijus(). Ove metode slu`e za promenu atributa radijus i za
njegovo va|enje iz klase.
Druga klasa je SferaMain, koja nam slu`i za izvr{enje ovog programa. Obratite pa`nju na njenu
metodu promenaObjekta(). U ovoj metodi se menja radijus objekta koji se metodi prosle|uje kao
argument. Po kasnijoj {tampi se vidi da promena radijusa u metodi, menja radijus i u objektu koji je
metodi prosle|en.

@ivotni vek objekta (instance)


@ivotni vek objekta je odre|en promenljivom koja na taj objekat referencira. Ako imate deklaraciju
Sfera sf = new Sfera(10.0, 1.0, 1.0, 1.0)
onda objekat sf postoji sve dok postoji promenljiva sf. To }e biti na kraju oblasti u kojoj se ova
deklaracija nalazi.
Na isti objekat mo`e da referencira vi{e promenljivih. U tom slu~aju objekat postoji sve dok postoji
i poslednji objekat koji na njega ukazuje.
Ako se napi{e iskaz
sf = null;
onda promenljiva sf vi{e ne ukazuje na objekat, tako da taj objekat mo`e biti uni{ten (pod
pretpostavkom da nema drugih promenljivih koje na njega ukazuju.
Proces izbacivanja objekata koji se u programu vi{e ne koriste se naziva skupljanjem otpada
(garbage collection). Ovo skupljanje otpada se u Javi odvija automatski. To ipak ne zna~i da objekti
istog trenutka kada se vi{e ne koriste i nestaju iz memorije, pa samim tim ta memorija ne mora da
bude odmah na raspolaganju. U pitanju je proces koji nije pod va{om kontrolom, tako da o njemu
ne treba mnogo brinuti.
38
U primeru koji sledi smo pokazali kako se koristi klasa Sfera koju smo napravili.
Primer:
Datoteka SferaMain.java
public class SferaMain {
public static void main(String[] args) {
System.out.println("Broj objekata je " + Sfera.getBrojac());
Sfera lp = new Sfera(4.0, 0.0, 0.0, 0.0);
System.out.println("Broj objekata je " + lp.getBrojac());

Sfera lp1 = new Sfera(12.0, 1.0, 1.0, 1.0);


System.out.println("Broj objekata je " + Sfera.getBrojac());

System.out.println("Zapremina sfere lp je " + lp.zapremina());


System.out.println("Zapremina sfere lp1 je " + lp1.zapremina());
}
}
Klasa Sfera je ista kao u prethodnom primeru, a u datoteci SferaMain.java smo dali klasu koja
kreira instancu klase Sfera i poziva neke njene metode.

Preklapanje metoda
U klasi mo`ete da defini{ete vi{e metoda sa istim imenom, ali sa razli~itim argumentima. Takvi
metodi se nazivaju preklopljenim metodima.
Preklopljene metode se me|usobno moraju da razlikuju po broju ili tipu argumenata. Ne mogu se
razlikovati samo po povratnom tipu.
Primer za preklopljene metode mogu biti metodi append, klase StringBuffer, koje smo ve} koristili.

Vi{estruki konstruktori
Kao i obi~ne metode, tako se i konstruktori mogu da preklapaju. Preklopljeni konstruktori se koriste
kada je potrebno da instancu klase napravite na osnovu razli~itih ulaznih parametara.
Ako pogledamo klasu Sfera, u njoj mo`emo da imamo jedan podrazumevani konstruktor (bez
argumenata) i konstruktor koji smo ve} napravili (sa argumentima za radijus i koordinate ta~ke).
Primer: Konstruktori iz klase Sfera
// podrazumevani konstruktor
Sfera(){
radijus = 1.0;
xCentar = 0.0;
yCentar = 0.0;
zCentar = 0.0;
brojac++;
}

Sfera(double rad, double x, double y, double z){


radijus = rad;
xCentar = x;
yCentar = y;
zCentar = z;
brojac++;
}
Prilikom kreiranja instanci klase Sfera kompajler odre|uje koji }e konstruktor pozvati na osnovu
tipa argumenata koje ste zadali.
Sfera lp = new Sfera(); // podrazumevani konstruktor
Sfera lp1 = new Sfera(2.0, 1.0, 1.0, 1.0);

39
Primer koji sledi se odnosi na jednostavnu geometriju u ravni. U njemu }emo koristiti dve klase.
Jedna klasa defini{e objekat tacka, a druga liniju. Ove objekte }emo koristiti za pronala`enje
preseka dveju linija.
Klasa Tacka:
public class Tacka {
// Koordinate tacke
double x;
double y;

// Kreiranje tacke na osnovu koordinata


Tacka(double xVal, double yVal)
{
x = xVal;
y = yVal;
}

// Kreiranje tacke na osnovu druge tacke


Tacka(final Tacka oldTacka)
{
x = oldTacka.x;
y = oldTacka.y;
}

// Pomeranje tacke
void move(double xDelta, double yDelta)
{
// parametarske vrednosti koje se dodaju trenutnim koordinatama
x += xDelta;
y += yDelta;
}

// Rastojanje do druge tacke


double distance(final Tacka aTacka)
{
return Math.sqrt(
(x - aTacka.x)*(x - aTacka.x) + (y - aTacka.y)*(y - aTacka.y) );
}

// KOnvertuje tacku u string


public String toString()
{
return Double.toString(x) + ", " + y;
}
}
Klasa Linija (Linija.java):
public class Linija {
Tacka start; // pocetna tacka linije
Tacka end; // Krajnja tacka linije

// Kreiranje linije na osnovu dve tacke


Linija(final Tacka start, final Tacka end)
{
this.start = new Tacka(start);
this.end = new Tacka(end);
}

// Kreiranje linije na osnovu koordinata dveju tacaka


Linija(double xStart, double yStart, double xEnd, double yEnd)
{
start = new Tacka(xStart, yStart);
end = new Tacka(xEnd, yEnd);

40
}

// izracunavanje duzine linije


double length()
{
return start.distance(end); // koristi se metod klase Tacka
}

// Linija se konvertuje u string


public String toString()
{
return "(" + start + "):(" + end + ")";
}

// presek dve linije


Tacka intersects(final Linija Linija1)
{
Tacka lokalnaTacka = new Tacka(0, 0);

double num =
(this.end.y - this.start.y)*(this.start.x - Linija1.start.x) -
(this.end.x - this.start.x)*(this.start.y - Linija1.start.y);

double denom =
(this.end.y - this.start.y)*(Linija1.end.x - Linija1.start.x) -
(this.end.x - this.start.x)*(Linija1.end.y - Linija1.start.y);

lokalnaTacka.x = Linija1.start.x + (Linija1.end.x -


Linija1.start.x)*num/denom;
lokalnaTacka.y = Linija1.start.y + (Linija1.end.y -
Linija1.start.y)*num/denom;

return lokalnaTacka;
}
}
Klasa Geometrija (Geometrija.java):
public class Geometrija {
public static void main(String[] args)
{
// Kreiraju se dve tacke i prikazuju se
Tacka start = new Tacka(0.0, 1.0);
Tacka end = new Tacka(5.0, 6.0);
System.out.println("Napravljene su dve tacke " + start + " i " + end);

// Kreiraju se dve linije i prikazuju se


Linija Linija1 = new Linija(start, end);
Linija Linija2 = new Linija(0.0, 3.0, 3.0, 0.0);
System.out.println("Napravljene su dve linije " + Linija1 + " i " +
Linija2);

// Presek
System.out.println("Presek je " + Linija2.intersects(Linija1));

// Pomera se krajnja tacka linije 1 i prikazuje se novi presek


end.move(1.0, -5.0);
System.out.println("Novi presek je " + Linija1.intersects(Linija2));
}
}

41
U klasi Tacka postoje dva ~lana (x i y koordinata tacke). U ovom trenutku postoje dva konstruktora,
jedan koji tacku pravi na osnovu para koordinata i drugi koji pravi novi objekat Tacka, na osnovu
postoje}eg.
U klasi smo definisali i metodu toString(), koja preklapa metodu toString() nasle|enu iz klase
Object. Ako klasa ima ovu metodu, onda se u prilikom {tampanja pomo}u operatora + (spajanje
stringova) mo`e koristiti objekat ove klase.
U klasi Linija smo liniju definisali preko dva objekta klase Tacka, {to je i prirodno.
U metodu za izra~unavanje preseka, smo koristili parametarske jedna~ine du`i (x=x1 + (x2-x1)t i
y=y1+(y2-y1)s).

Rekurzija
Metode koji smo do sada koristili se pozivaju iz drugih metoda. Proces u kome metoda poziva samu
sebe se naziva rekurzijom. U rekurzivnom metodu mora da postoji i neka logika koja }e prekinuti
poziv metode, jer bi u suprotnom dobili beskona~ane pozive.
U primeru koji sledi je data rekurzivna metoda koja ra~una stepen zadate ceoblrojne vrednosti. To
zna~i da se ra~una xn.
public class Stepen {
public static void main(String[] args)
{
double x = 5.0;
System.out.println(x + " na 4 je " + power(x,4));
System.out.println("7.5 na 5 je " + power(7.5,5));
System.out.println("7.5 na 0 je " + power(7.5,0));
System.out.println("10 na -2 je " + power(10,-2));
}

// Dize se x na n-ti stepen


static double power(double x, int n)
{
if(n > 1)
return x*power(x, n-1); // rekurzivni poziv
else if(n < 0)
return 1.0/power(x, -n); // Negative power of x
else
return n == 0 ? 1.0 : x; // Ako je n 0 vraca se 1, u suprotnom se vraca
x
}
}
Ako je n pozitivan broj, ve}i od 1, metoda power poziva samu sebe, ali sa ulaznim parametrom
smanjenim za 1. Ovo se ponavlja sve dok stepen ne dobije vrednost 0, u kom slu~aju se prekida
rekurzija.
Rekurzivni metodi su veoma zahtevni po pitanju resursa i vremena. Zbog toga treba da se pozivaju
samo kada je to neophodno. Navedeni primer bi se mnogo lak{e realizovao putem petlje. Na taj
na~in bi se izvr{avao mnogo efikasnije. Rekurzije najvi{e primene imaju kod struktura podataka
kao {to je stablo ili liste.

Paketi
Sve klase u Javi su organizovane u pakete. Paketi u Javi su sli~ni direktorijumima (fasciklama) koji
se koriste za organizaciju podataka na disku. I klase koje smo do sada koristili se nalaze u paketima,
ali do sada na to nismo obra}ali pa`nju.
Sve standardne klase koje postoje u Javi su tako|e organizovane u pakete. Klase koje smo do sada
koristili (String, StringBuffer) se nalaze u paketu java.lang. Ovaj paket nije potrebno nazna~avati u

42
kodu, jer je on automatski dostupan u svim programima. Postoje i drugi standardni paketi, ali se oni
uglavnom moraju eksplicitno uklju~iti u kod.
Pakovanje klase se izvodi tako {to se u datoteku u kojoj se nalazi klasa na po~etku doda iskaz za
pakovanje. Ovaj iskaz mora biti prvi u toj datoteci.
package Proba;
public class Sfera …
Prethodni iskaz ka`e da je klasa Sfera pripadnik paketa Proba. U jednom paketu mo`e biti vi{e
klasa. Klju~na re~ public u definiciji klase ukazuje na to da se klasi Sfera mo`e pristupiti i iz drugih
paketa i klasa u programu. Ako se prilikom definicije klase ne navede klju~na re~ public, onda se
toj klasi mo`e pristupati samo iz metoda klasa koje se nalaze u istom paketu.
Paketi su povezani sa strukturom direktorijuma na kome se nalaze datoteke sa Java klasama. Ve}
znamo da se definicija klase nalazi u datoteci ~ije je ime isto kao ime klase. Sve datoteke u paketu
ImePaketa moraju se nalaziti u direktorijumu ImePaketa.
Paketi mogu da imaju strukturu. Na primer, ako `elite da napravite jedan vrhovni paket za rad sa
geomtrijom i nazovete ga Geometrija, a da u njemu razdvojite klase koje se koriste za 2D i 3D
geometriju, mo`ete da napravite jo{ dva paketa po imenu 2dObilici i 3dOblici, koji se nalaze u
paketu Geometrija. Ti paketi se defini{u na slede}i na~in:
package Geometrija.2dOblici;
public class Linija …
Klasa Linija iz ovog primera mora da se nalazi u direktorijumu 2dOblici, koji se nalazi u
direktorijumu Geometrija. Ova struktura mo`e imati dubinu koja odgovara Va{im potrebama.
Prilikom kompajliranja datoteka sa izvornim kodom, nastaju datoteke sa bajt kodom, ~ija je
ekstenzija .class. Struktura direktorijuma sa ovim datotekama, tako|e mora da po{tuje pakete koji se
primenjuju. O ovome brine kompajler, ali i vi to morate znati, jer se prilikom preno{enja tih klasa ta
struktura mora da ispo{tuje.

Dodavanje klasa iz nekog drugog paketa u program


Ako su klase u drugom paketu definisane sa klju~nom re~i public, onda novi program te klase
mo`ete dodati preko iskaza import. Ovaj iskaz treba da se nalazi na po~etku datoteke sa definicijom
klase, ali iza iskaza za definisanje paketa. Na primer, ako u datoteci u~inite dostupnim klase iz
paketa Geometrija.3dOblici, mo`ete da napi{ete:
import Geometrija.3dOblici.*;
Zvezdica na kraju prethodno iskaza zna~e da se uklju~uju sve klase iz paketa. Ako se napi{e
konkretna klasa, pripadnik tog paketa, onda se mo`e pristupati samo toj klasi.
import Geometrija.3dOblici.Sfera; // uklju~uje klasu Sfera
Ime klase, pored imena same klase, sadr`i i ime paketa u kome se ta klasa nalazi. To zna~i da u
programu mo`ete da imate dve klase sa istim osnovnim imenom, ako se one nalaze u razli~itim
paketima. Ovo je isto kao sa datotekama na disku, koje mogu da imaju isto ime, ako se nalaze u
razli~itim direktorijumima.

Standardne klase i paketi


Sve standardne klase koje se isporu~uju sa Javom se nalaze u standardnim paketima. Lista ovih
paketa stalno raste, ali evo nekih od njih:
java.lang - ovaj paket ne mora da se eksplicitno ubacuje u program. Sadr`i osnovne klase kao {to su
String, StringBuffer, Math i sl.
java.io - sadr`i klase koje s ekoriste za ulazno izlazne operacije

43
java.awt - osnovne klase za grafi~ki korisni~ki interfejs (GUI).
java.swing - grafi~ki interfejs, ali pobolj{an
java.util - klase za datum i vreme, za manipulisanje kolekcijama i sl
java.sql - klase za pristup bazama podataka putem jezika SQL

Standardne klase za osnovne tipove objekata


Za sve osnovne tipove podataka u Javi postoje klase omota~i, koje sadr`e osnovni tip ali i dodatne
metode za manipulaciju tim osnovnim tipom. To su slede}e klase:
Boolean
Character
Byte
Short
Integer
Long
Float
Double
Sve ove klase se nalaze u paketu java.lang. Ove klase }ete koristiti ako `elite da od stringa napravite
osnovni tip (meetode tipa parseInt, parseDouble i sl), ili kada je potrebno da na neki drugi na~in
manipuli{ete osnovnim tipom.

Dostupnost ~lanova klase


U istom paketu, bilo koja klasa ima direktan pristup do bilo koje klase iz tog paketa. Promenljive i
metodi te druge klase ne moraju obavezno da budu dostupni. Njihova dostupnost zavisi od atributa
dostupnosti za svaki konkretan metod i atribut. Prilikom definisanja dostupnosti postoje ~etiri
mogu}nosti.
Atribut Dozvoljen pristup
Bez atributa dostupnosti Iz bilo koje klase u okviru paketa
public Iz bilo koje klase, bilo otkuda
private nema pristupa izvan klase
protected iz bilo koje klase u okviru paketa i iz bilo koje potklase, koja se
nalazi u bilo kom paketu
^lanovi klase bi generalno trebalo da budu deklarisani sa atributom private. Ovo je u skladu sa
jednim od principa objektno orijentisanog programiranja, koji se odnosi na u~aurenje. To zna~i da
se ~lanovi klase ne mogu menjati direktno na bilo kom mestu odakle se pozivaju.
Sa druge strane, metode predstavljaju interfejs klase, tako da je njih najbolje deklarisati kao public.
Dobra programerska praksa je da se ~lanovi deklari{u kao privatni, a da se za one koje je potrebno
menjati spolja i ~ije se vrednosti ~itaju spolja deklari{u odgovaraju}i set i get metodi. Promena
ovih ~lanova i pristup do njih je tada mogu} samo preko ovih metoda.
double radijus;
public double getRadijus(){
return this.radijus;
}

44
public void setRadijus(double rad){
this.radijus = rad;
}

Metoda finalize()
U klasi mo`e da postoji i metoda finalize(). Ovo je metoda koja se automatski poziva pre nego {to
se objekat uni{ti i oslobodi prostor u memoriji koji je on zauzimao. To ne mora biti istog trenutka
kada se objekat prestane da koristi. Kada objekat vi{e nije u oblasti va`enja, {to se ti~e programa on
ne postoji, ali Java virtuelna ma{ina mo`da ne}e odmah da ga izbaci iz memorije. Kada do|e do
izbacivanja ona poziva metodu finalize(0. Evo kako izgleda ta metoda:
protected void finalize(){
// kod za ~i{}enje
}
Ova metoda je korisna kada se u klasi koriste neki resursi koji zahtevaju posebnu akciju prilikom
uni{tavanja objekta. Obi~no ti objekti nisu u okviru Java okru`enja i nema garancije da }e biti
automatski oslobo|eni. To mogu biti grafi~ki resirsi, ili datoteke na disku i sl.

Nasle|ivanje
Jedna od osnovnih osobina objektno orijentisanog programiranja jeste nasle|ivanje. Nasle|ivanje
omogu}ava da novu klasu izvedete iz neke postoje}e i da je kasnije pro{irite. U novoj klasi mo`ete
da koristite sve mogu}nosti osnovne klase, ali i da dodate nove.
Klasa iz koje se izvodi nova klasa se naziva osnovnom ili originalnom ili superklasom izvedene
klase.
U primeru koji sledi smo definisali osnovnu klasu Pas, iz koje smo zatim izveli potklasu Spaniel.
class Pas{
// clanovi klase Pas
}
class Spaniel extends Pas{
// clanovi klase Spaniel
}
Prilikom definisanja izvedene klase se koristi klju~na re~ extends (pro{iruje). Ova definicija
konkretno zna~i da se klasa Spaniel izvodi iz klase Pas, tako da }e objekat tipa Spaniel imati sve
~lanove koje ima klasa Pas, plus ~lanove koji su specifi~ni samo za njega.
Spaniel je specijalizovani primerak psa. To odra`ava i realni svet. [panijel je vrsta psa i ima mnoge
osobine koje su zajedni~ke za sve pse, ali ima i jedinstvene osobine koje ga razlikuju od ostalih
vrsta pasa. Mehanizam nasle|ivanja je u ovom slu~aju dobar model za opisivanje stvarnog sveta.
Prilikom nasle|ivanja se odvija aditivan proces u smislu definicije klase. Osnovnu i izvedenu klase
razlikuju dodatni ~lanovi koje pravite u izvedenoj klasi. Bilo koji ~lan koji se defini{e u izvedenoj
klasi je dodatak ~lanovima koji postoje u osnovnoj klasi. Objekat Spaniel }e u sebi uvek imati
kompletan objekat Pas, sa svim njegovim podacima i metodama. To ipak ne zna~i da }e u klasi
Spaniel biti dostupni svi ~lanovi i metodi klase Pas. Dostupni su samo oni ~lanovi koji se nasle|uju.
Ako ~lan osnovne klase nije dostupan u izvedenoj klasi, onda on nije nasle|eni ~lan, ali jeste deo
objekta izvedene klase.
Da biste mogli da izvodite novu klasu iz neke klase, osnovna klasa ili mora biti u istom paketu, ili
mora biti deklarisana kao public.
Potklasa ili izvedena klasa nasle|uje sve ~lanove osnovne klase osim onih koji su deklarisani kao
privatni (klju~na re~ private). Ovo va`i ako su osnovna i izvedena klasa u istom paketu. Ako

45
osnovna i izvedena klasa nisu u istom paketu, onda se nasle|uju samo oni ~lanovi osnovne klase
koji su definisani kao za{ti}eni (klju~na re~ protected).
Pravila nasle|ivanja se odnose i na promenljive instance i na promenljive klase.
class OsnovnaKlasa{
private static int a;// ne nasledjuje se
protected static int b;// nasledjuje se
}
Ako se u izvedenoj klasi defini{e ~lan sa istim imenom kao u osnovnoj klasi, onda taj iz izvedene
klase sakriva onaj iz osnovne.

Nasle|ivanje metoda
Metode koje nisu konstruktori se nasle|uju isto kao i atributi. One metode koje su osnovnoj klasi
deklarisane kao private se ne nasle|uju, a one koje su deklarisane bez atributa dostpunosti se
nasle|uju samo u istom paketu.
Konstruktori se nikad ne nasle|uju.
Primer: Pretpostavimo da smo definisali klasu Zivotinja:
public class Zivotinja{
private String tip;
public Zivotinja(String aTip){
tip = new String(aTip);
}
public String toString(){
return “Ovo je “ + tip;
}
}
U ovoj klasi postoji ~lan tip koji slu`i za to da odredi o kojoj se `ivotinji radi.
Sada mo`emo definisati drugu klasu koja se zasniva na klasi Zivotinja. Ova klasa }e definisati pse.
public class Pas extends Zivotinja{
// konstrktori za objekat Pas
private String ime;
private String rasa;
}
Klasa Pas nasle|uje samo metodu toString(), po{to se ~lanovi deklarisani kao private i kontruktori
ne nasle|uju. Objekat Pas }e imati i podatak ~lan koji se odnosi na tip, ali se tom ~lanu ne mo`e
pristupiti iz klase Pas.

Konstruktori izvedene klase


public class Pas extends Zivotinja{
public Pas(String aIme){
super(“Pas”);
ime = aIme;
rasa = “Nepoznato”;
}
public Pas(String aIme, String aRasa){
super(“Pas”);
ime = aIme;
rasa = aRasa;
}
private String ime;
private String rasa;
}
Kao {to vidite u konstruktorima izvedene klase treba pozivati konstruktore osnovne klase, koji
inicijalizuju podatke koji su definisani u toj klasi. To se radi iskazom:

46
super(“Pas”);
Konstruktor osnovne klase se uvek poziva preko klju~ne re~i super.
Ako u konstruktori izvedene klase niste u prvom redu pozvali konstuktor osnovne klase, kompajler
}e to poku{ati da uradi umesto vas. U tom slu~aju }e se dodati iskaz:
super();
Ovo je podrazumevani konstruktor za osnovnu klasu. Ako on ne postoji, prilikom kompajliranja }e
se javiti gre{ka.
Primer: U primeru koji sledi smo prikazali kako bi mogla da se upotrebi klasa Pas, koju smo pre
toga napravili.
public class TestIzvodjenje {
public static void main(String[] args) {
Pas ps = new Pas("Fido", "Chiuahua");
Pas ps1 = new Pas("Lesi");
System.out.println(ps);
System.out.println(ps1);
}
}
Metod toString koji se ovde poziva je metod koji dolazi iz osnovne klase. Ovaj metod nije svestan
~lanova izvedene klase.
Probajte da iz konstruktora u klasi Pas izbacite poziv konstruktora osnovne klase i analizirajte
rezultate.

Preklapanje metoda osnovne klase


U izvedenoj klasi mo`ete definisati metodu koja ima isto zaglavlje kao i metoda u osnovnoj klasi.
Atribut dostupnosti mora biti isti kao u osnovnoj klasi, ili manje restriktivan. To zna~i da ako je
metoda u osnovno klasi deklarisana kao public, u izvedenoj klasi mora biti tako|e deklarisana kao
public.
Kada se iz instance izvedene klase kasnije poziva metoda sa ovim imenom, poziva se metoda iz
izvedene klase, a ne metoda iz osnovne klase. To zna~i da metoda u izvedenoj klasi ima prioritet u
odnosu na metodu iz osnovne klase.
Pokaza}emo ovo na primeru metode toString() koju smo definisali u klasi Zivotinja. Sada }emo je
definisati i u klasi Pas.
public String toString(){
return "Ime psa je " + ime + " a rasa je " + rasa;
}
Po{to u klasama Zivotinja i Pas postoje metode toString(), koje imaju isto zaglavlje (ime, povratni
tip i argumente), to se prilikom poziva metode iz instance klase Pas, poziva odgovaraju}a metoda te
klase.
Ako bismo `eleli da prika`emo i vrstu `ivotinje, moramo prikazati atribut tip iz osnovne klase. Ovaj
atribut je deklarisan kao privatan, tako da mu s ene mo`e pristupiti iz izvedene klase. Zbog toga
}emo jo{ jednom promeniti metod toString() u izvedenoj klasi:
public String toString(){
return super.toString() + "\nIme psa je " + ime + " a rasa je " +
rasa;
}
Sada se direktno preko iskaza super.toString() poziva metod toString() osnovne klase, koji {tampa
vrstu `ivotinje.

47
Polimorfizam
Pomorfizam je jedna od va`nih osobina objektno orijentisanog programiranja. Ova osobina
omogu}ava da se jedna ista promenljiva, zadatog tipa, koristi za referenciranje objekata razli~itih
tipova, pri ~emu se automatski pozivaju metode specifi~ne za tip objekta kojem se pristupa. To
omogu}ava da se jedna ista metoda pona{a na razli~ite na~ine, u zavisnosti od tipa metoda na koji
se poziv odnosi.
Polimorfizam radi sa izvedenim klasama. Promenljiva zadatog tipa obi~no ukazuje na objekat istog
tipa. Izvedene klase uvode nove mogu}nosti, koje se odnose na ~injenicu da se objekat izvedene
klase mo`e uskladi{titi u promenljivoj koja je tipa direktne ili indirektne osnovne klase.
Ako se prisetimo klasa Zivotinja i Pas iz prethodnog primera, kod njih je mogu}e da se instanca
klase Pas, smesti u promenljivoj tipa Zivotinja. Isto va`i i za instancu klase Spaniel, koja mo`e bti
uskladi{tena u promenljivima tipa Zivotinja i Pas.
Da bi se dobilo polimorfno pona{anje prilikom poziva metode, metoda mora biti ~lan i osnovne i
izvedene klase. Ne mo`ete da pozovete metodu iz objekta izvedene klase, koriste}i metodu osnovne
klase, ako metoda ne postoji u osnovnoj klasi. Metode u osnovnoj i izvedenim klasama moraju da
imaju istu deklaraciju i isti povratni tip, a dostupnost ne sme biti vi{e restriktivna.
Pretpostavimo da ste deklarisali promenljivu
Zivotinja ziv; // deklaracija promenljive tipa Zivotinja
Ovu promenljivu mo`ete upotrebiti za ukazivanje na objekat bilo koje klase koja je izvedena iz
klase Zivotinja. Mo`ete je na primer koristiti za ukazivanje na objekat klase Pas:
ziv = new Pas(“Vucjak”);
Da pogledamo malo detaljnije kako ovo izgleda na primeru. Klasu Pas }emo pro{iriti novom
metodom koja prikazuje zvuk koji pas proizvodi.
public class Pas extends Zivotinja{
// metoda za lavez
public void zvuk(){
System.out.println("Av Av");
}
//.. ostatak isti kao ranije
}
Iz klase Zivotinja mo`emo da izvedemo i klasu Macka:
public class Macka extends Zivotinja {
public Macka(String aIme)
{
super("Macka");
ime = aIme;
rasa = "Nepoznato";
}

public Macka(String aIme, String aRasa)


{
super("Macka");
ime = aIme;
rasa = aRasa;
}

// Vra]a se string sa detaljima o toj macki


public String toString()
{
return super.toString() + "\nIme macke je " + ime + " a rasa je " + rasa;
}

48
// metod za mjaukanje
public void zvuk()
{
System.out.println("Mijauuu");
}

private String ime; // ime macke


private String rasa; // rasa
}
Izve{}emo i klasu za patke.
public class Patka extends Zivotinja {
public Patka(String aIme)
{
super("Patka");
ime = aName;
rasa = "Nepoznato";
}

public Patka(String aIme, String aRasa)


{
super("Patka");
ime = aIme;
rasa = aRasa;
}

// Detalji o patkio
public String toString()
{
return super.toString() + "\nIme patke je " + ime + " a rasa je " + breed;
}

// metod za zvuk
public void zvuk()
{
System.out.println("Kva kva");
}

private String ime;


private String rasa;
}
Da bi mogao da se primeni polimorfizam, metoda zvuk() mora da se implementira i u osnovnoj
klasi Zivotinja. U tu klasu dodajte slede}i kod:
public void zvuk(){
}
Potreban nam je i program koji }e koristiti ove klase.
import java.util.Random;
public class Polimorfizam {
public static void main(String[] args) {
// NIz sa razlicitim zivotinjama
Zivotinja[] zivotinje = {
new Pas("Dzoni", "Pudlica"),
new Macka("Cica", "Sijamska"),
new Patka("Daca")
};

Zivotinja izborZivotinje;

Random select = new Random(); // generator slucajnih brojeva


// Pet slucajnih izbora
for(int i = 0; i < 5; i++){

49
izborZivotinje = zivotinje[select.nextInt(zivotinje.length)];

System.out.println("\nIzabrali ste :\n" + izborZivotinje);


izborZivotinje.zvuk(); // reakcija
}
}
}
Ovde su napravljene tri instance klasa Pas, Macka i Patka. One su sme{tene u nizu ~iji je osnovni
tip Zivotinja. Kasnije koristimo klasu Random i njen objekat select, preko kojih generi{emo
slu~ajne brojeve koje koristimo za pristup elementima niza. Iz dobijenih rezultata (koji su svaki put
kada se program izvr{i razli~Iti) se vidi da se metode toString() i zvuk() pozivaju u zavisnosti od
objekta koji je uskladi{ten u promenljivoj izborZivotinje.

Vi{estruki nivoi nasle|ivanja


Izvedena klasa mo`e biti osnovna za neku drugu klasu. Iz klase Pas bismo mogli da bez problema
izvedemo klasu Vucjak.
public class Vucjak extends Pas{
public Vucjak(String aIme){
super(aIme, “Vucjak”);
}
}
U prethodni primer mo`emo dodati i ovu klasu. Promenite samo slede}i kod:
Zivotinja[] zivotinje = {
new Pas("Dzoni", "Pudlica"),
new Macka("Cica", "Sijamska"),
new Patka("Daca"),
new Vucjak(“Reks”);
};
Klasa Vucjak }e naslediti sve ~lanove klase Pas, uklju~uju}i i one ~lanove koji su nasle|eni iz klase
Zivotinja. Klasa Pas je direktna super klasa, a klasa Zivotinja je indirektna super klasa. Jedini
dodatni ~lan klase Vucjak je konstruktor u kome se poziva konstruktor klase Pas, kome se
prosle|uje ime, i rasa “Vucjak”.

Apstraktne klase
U klasi Zivotinja smo imali metodu zvuk() koja je bila prazna i koja se tu nalazila samo da bi
kasnije mogla da se koristi u izvedenim klasama. Ovaj metod u klasi Zivotinja nema nikakvo
zna~enje.
Ovo se mo`e re{iti i preko apstraktnih klasa. Apstraktna je ona klasa u kojoj su neke metode
deklarisane, ali ne i definisane. Po{to ove metode nemaju definiciju, u pitanju su apstraktne metode.
Evo kako to izgleda na primeru:
public abstract class Zivotinja{
public abstract void zvuk(); //apstraktna metoda
public Zivotinja (String aTip) {
tip = new String(aTip);
}

public String toString() {


return "Ovo je " + tip;
}
private String tip;
}
Od klase koje je deklarisana kao apstraktna se ne mogu praviti instance, ali se mo`e napraviti
promenljiva tog tipa.

50
Univerzalna superklasa
Sve klase koje pravite u Javi su izvedene iz jedne zajedni~ke klase, Object. Ovo se nigde
eksplicitno ne zadaje. To se podrazumeva.
U skladu sa ovim promenljiva tipa Object mo`e da primi instancu bilo koje druge klase. To je
korisno kada treba da napi{ete metodu koja rukuje objektom nepoznatog tipa. U tom slu~aju
dodajete promenljivu tipa Object, a u samoj metodi ispitujete koja je vrsta objekta u pitanju.
Klasa Object ima odre|en broj metoda i atributa (~lanova), koje Va{e klase nasle|uju. Evo koje su to
metode:
Metoda Namena
toString() Vra}a se String koji opisuje trenutni objekat. U
nasle|enoj verziji metode to }e biti ime klase iza
kojeg sledi @, i heksadecimalna reprezentacija
objekta.
equals() Ova metoda poredi prosle|eni objekat i trenutni
objekat i vra}a true ako su objekti isti (ne samo
jednaki ve} to mora biti isti objekat u memoriji).
Vra}a false ako su razli~iti objekti, pa ~ak i ako
su vrednosti njihovih atributa identi~ne.
getClass() Vra}a se objekat tipa Class koji identifikuje
klasu trenutnog objekta.
HashCode() Vra}a hash kod objekta koji se koristi kod
sme{tanja objekta u hash tabelama.
notify(0 Koristi se za obave{tavanje niti koja je u vezi sa
trenutnim objektom.
notifyAll() koristi se za obave{tavanje svih niti koje su u
vezi sa trenutnim objektom.
wait() Dovodi do toga da nit ~eka na promenu u
trenutnom objektu.
Metode getClass(), notify(), notifyAll i wait() se ne mogu preklapati u izvedenim klasama.
Postoje i dve metode tipa protected. To su metode clone() koja se koristi za kopiranje objekta i
metoda finalize() koja se poziva kada se objekat bri{e iz memorije. Ove metode se mogu menjati u
izvedenim klasama.

Metoda toString()
Ovu metodu smo koristili u na{im klasama. Nju kompajler koristi kada je potrebna String
prezentacija objekta. Ako se ova metoda ne preklopi, onda se koristi verzija iz klase Object. U njoj
se prikazuje ime klase, znak @ i hash kod tog objekta.
Pas@b75778b2

Odre|ivanje tipa objekta


Metoda getClass() koju sve klase nasle|uju iz klase Object vra}a objekat tipa Class, koji identifikuje
klasu objekta o kome je re~. Pretpostavimo da imate promenljivu ziv tipa Zivotinja, koja mo`e
ukazivati na objekat tipa Pas, Macka, Patka ili ~ak Vucjak.
Class tipObjekta = ziv.getClass();
System.out.println(tipObjekta.getName()); // prikaz imena klase

51
Ako promenljiva ukazuje na objekat klase Patka, onda }e drugi iskaz iz prethodnog primera dati
izlaz
Patka
Ako se klasa nalazi u nekim paketu ovde }e biti i celo ime paketa u kome se klasa nalazi.

Konverzija tipa objekta


Objekat izvedene klase se mo`e konvertovati u objekat neke od superklasa za tu klasu. Mo`ete na
primer, konvertovati objekat tipa Vucjak u klasu Pas ili Zivotinja, ili Object.
Vucjak vuc = new Vucjak(“Reks”);
Zivotinja ziv = (Zivotinja) vuc; // konvertovanje Vucjaka u Zivotinju.
Ovo i ne mora da se eksplicitno navodi (kod konverzije navi{e)
Zivotinja ziv = vuc;// konvertovanje Vucjaka u Zivotinju
Kada konvertujete objekat u tip natklase, Java zadr`ava informaciju o tome koja je aktuelna klasa
kojoj objekat pripada.
Mogu}a je i obrnuta konverzija, ali tek ako je re~ o povratku na prvobitan tip.
Ako se radi o konverziji u natklasu, onda je mogu}a implicitna konverzija, a ako je re~ o konverziji
u izvedenu klasu, onda konverzija mora da se eksplicitno izvr{i.

Identifikacija objekata
Ako ne znate o kom se objektu radi (na primer, kada je objekat izvedene klase prosle|en metodi
osnovne klase, kao argument, a deklarisani tip je izvedena klasa), mo`ete da preko operatora
instanceof proverite tip objekta, pre same konverzije.
Primer:
Patka pat;
if(ziv instanceof Patka){
pat = (Patka) ziv;

}
Ako promenljiva ziv ukazuje na promenljivu tipa Zivotinja i Vi `elite da je konvertujete u tip Patka,
to se mo`e uraditi samo ako je taj objekat inicijalno ukazivao na tip Patka. Ako to nije bio slu~aj,
poku{aj konverzije dovodi do izuzetka. Na ovaj na~in se pojava tog izuzetka izbegava.
Operator instanceof vra}a true ako je objekat instanca te klase ili neke od njenih potklasa.

Interfejsi
U klasama koje smo izvodili iz klase Zivotinja imali smo metodu zvuk() koja je bila razli~ito
implementirana u svakoj od potklasa. Time smo `eleli da dobijemo polimorfno pona{anje. Ako
Vam je potrebno samo polimorfno pona{anje, a ne i ostalo {to se posti`e nasle|ivanjem, mo`ete
upotrebiti interfejse.
Interfejs predstavlja skup konstanti i apstraktnih metoda. Da bi neka klasa mogla da koristi interfejs,
on mora da se u toj klasi implementira. Nakon implementacije interfejsa u svakoj klasi morate da
napi{ete i kod za metode koje ste u interfejsu deklarisali. Kada klasa implementira interfejs sve
konstante koje su zadate u definiciji interfejsa su direktno dostupne u klasi, isto kao da su nasle|ene
iz neke osnovne klase. Interfejs mo`e da sadr`i konstante, apstraktne metode ili oboje.
Metode u interfejsu su uvek public i abstract, pa se uz njih ne vezuju atributi. Konstante su uvek
public, static i final, pa se ni za njih ne zadaju atributi.
U primeru koji sledi dat je interfejs koji sad`i samo konstante:
public interface FaktoriKonverzije {
double INCH_U_MM = 2.54;

52
double UNCA_U_GRAM = 28.34;
double FUNTA_U_GRAM = 453.59;
}
Ovde je zadato nekoliko konstanti koje se mogu koristiti za konverziju jedinica. Sve one su
podrazumevano public, static i final.
Evo interfejsa koji sadr`i metrode za konverziju:
public interface Konverzija {
double inchUMM(double inchi);
double uncaUGram(double unce);
double funtaUGram(double funte);
}
Interfejs se defini{e klju~nom re~i interface. Interfejs, kao i klasa pripada nekom paketu.
Promenljive koje smo zadali u prvom interfejsu su dostupne izvan interfejsa. Po{to je interfejs
deklarisan kao public, to su ove promenljive dostupne i izvan paketa u kome se interfejs nalazi.
Po{to su static i final, ove promenljive se moraju inicijalizovati i kasnije se ne mogu menjati.
Ako u definiciji interfejsa izostavite klju~nu re~ public, onda je interfejs dostupan samo u paketu u
kome se nalazi.
U interfejsu Konverzija, koji smo zadali smo dali samo deklaraciju svake metode. Kod za svaku od
ovih metoda morate da obezbedite u klasi koja implementira ovaj interfejs.
Interfejs mo`e da pro{iruje neki drugi interfejs, ondnosno da se izvede iz drugog interfejsa. Ako
bismo `eleli da interfejs Konverzija izvedemo iz interfejsa FaktoriKonverzije, mogli bismo da
napi{emo:
public interface Konverzija extends FaktoriKonverzije{
double inchUMM(double inchi);
double uncaUGram(double unce);
double funtaUGram(double funte);
}
Interfejs mo`e da sadr`i vi{e drugih interfejsa.
public interface MojInterfejs extends Interfejs1, Interfejs2 {
// kod
}

Implementacija interfejsa
public class MojaKlasa implements FaktoriKonverzije{
double tezinaUFuntama;
public doublegetTezinaUKg(){
return tezinaUFuntama * FUNTA_U_GRAM;
}
}
Sve konstante koje su definisane u interfejsu FaktoriKonverzije su dostupne u klasi MojaKlasa.
Po{to su tipa public, mo`e im se pristupati i kao ~lanovima klase MojaKlasa.
Ako `elite da implementirate interfejs koji sadr`i metode morate da za svaku metodu obezbedite
kod, odnosno njeno telo.
U primeru koji sledi smo implementirali interfejs Konverzija:
public class MojaKlasa implements Konverzija{
public double inchiUMM(double inchi){
return inchi * INCH_U_MM;
}
public double UncaUGram(double unce){
return unce * UNCA_U_GRAM;
}
public double funtaUGram(double funte){
return funte * FUNTA_U_GRAM;
}

53
}
Svaka metoda iz interfejsa mora imati definiciju u klasi koja taj interfejs implementira. Po{to su
metode interfejsa public, to i metode u klasi moraju biti deklarisane kao public. Po{to interfejs
Konverzija pro{iruje interfejs FaktoriKonverzije, to su u ovoj klasi dostupne i sve promenljive koje
su definisane u tom interfejsu.
Ako u nekoj klasi ne `elite da implementirate sve metode interfejsa, onda morate da tu klasu
deklari{ete kao apstraktnu.

Kada se koriste interfejsi


Interfejs je pogodan na~in za pakovanje konstanti. Interfejs sa konstantama mo`ete da kasnije
iskoristite u razli~Itim klasama koje }e ga implementirati. Konstante su stativ i objekti klase ih
me|usobno dele.
Interfejs je tako|e na~in da se implementira polimorfizam. Kod polimorfizma je potrebno da se u
osnovnoj i svim izvedenim klasama defini{e metoda sa istim zaglavljem. Ovoj metodi, koja je u
razli~itim potklasama razli~ito implementirana se kasnije pristupa preko promenljive koja ukazuje
na osnovnu klasu, a u zavisnosti od toga kojoj od potklasa pripada objekat, dolazi do poziva metoda
iz potklasa.
Sli~na funkcija se mo`e posti}i i interfejsom. Sve klase za koje `elite da se pona{aju polimorfno
treba da implementiraju interfejs sa zajedni~kim metodima, a polimorfno pona{anje se posti`e
pozivom promenljiva koja je tipa tog interfejsa.
U primeru koji sledi smo pokazali kako preko interfejsa mo`e posti}i isto {to smo radili
nasle|ivanjem klase Zivotinja i sl.
Primer:
import java.util.Random;
public class TestInterfejs {
public static void main(String[] args)
{
ZivotinjaIzlaz[] zivotinje = {
new Pas1("Dzoni", "Pudlica"),
new Macka1("Cica", "Sijamska"),
new Patka1("Daca")
};
ZivotinjaIzlaz ziv;
Random select = new Random(); // Random number generator
for(int i = 0; i < 5; i++) {
ziv = zivotinje[select.nextInt(zivotinje.length)];
System.out.println("\nIzarbali ste :\n" + ziv);
ziv.zvuk();
}
}
}
public class Pas1 implements ZivotinjaIzlaz{
public Pas1(String aIme){
ime = aIme;
rasa = "Nepoznato";
}
public Pas1(String aIme, String aRasa){
ime = aIme;
rasa = aRasa;
}
public String toString(){
return "\nIme psa je " + ime + " a rasa je " + rasa;
}
private String ime;
private String rasa;

54
// metoda za lavez
public void zvuk(){
System.out.println("Av Av");
}
}
public class Macka1 implements ZivotinjaIzlaz{
public Macka1(String aIme) {
ime = aIme;
rasa = "Nepoznato";
}

public Macka1(String aIme, String aRasa) {


ime = aIme;
rasa = aRasa;
}

// Vra]a se string sa detaljima o toj macki


public String toString() {
return "\nIme macke je " + ime + " a rasa je " + rasa;
}

// metod za mjaukanje
public void zvuk() {
System.out.println("Mijauuu");
}

private String ime; // ime macke


private String rasa; // rasa
}
public class Patka1 implements ZivotinjaIzlaz{
public Patka1(String aIme) {
ime = aIme;
rasa = "Nepoznato";
}
public Patka1(String aIme, String aRasa) {
ime = aIme;
rasa = aRasa;
}

// Detalji o patkio
public String toString() {
return "\nIme patke je " + ime + " a rasa je " + rasa;
}

// metod za zvuk
public void zvuk() {
System.out.println("Kva kva");
}
private String ime;
private String rasa;
}
Definicije klasa su sli~ne sa onima iz prethodnog primera. Razlika je u tome da se klase ne izvode
iz klase Zivotinja, tako da nema ni poziva konstruktora za super klasu u njihovim konstruktorima.
Promenjena je i metoda toString(), tako {to je izba~en poziv metode super.toString(), jer toga sada
nema.
Nema vi{e promenljive tip iz osnovne klase, koja se nasle|ivala u izvedenim klasama.
U glavnoj klasi za implementaciju se pravi promenljiva tipa ZivotinjaIzlaz, koja ukazuje na
interfejs. Ta promenljiva se koristi za skladi{tenje objekata klase koja implementira taj interfejs. To
se odnosi i na potklase koje nasle|uju interfejs iz direktne ili indirektne klase.

55
Klasa mo`e da implementira vi{e interfejsa. Potrebno je ih samo navesti iza imena klase (u njenoj
definiciji), i odvojiti ih zarezima.

Izuzeci
Izuzeci obi~no signaliziraju na pojavu gre{ke u programu. Izuzetak ukazuje na neuobi~ajen doga|aj
u programu koji zaslu`uje pa`nju.
Osnovna prednost signaliziranja gre{ke pomo}u izuzetka je u tome da se time kod koji rukuje
gre{kom razdvaja od koda koji se izvr{ava kada se stvari odigravaju na uobi~ajeni na~in.
Ne morate sve gre{ke u programu da obra|ujete kao izuzetke. Izuzeci treba da budu rezervisani za
katastrofalne situacije, kada mo`e do}i do prekida rada programa.
Izuzetak je u Javi objekat koji se pravi kada se u programu pojavi neka nenormalna situacija. Ovaj
objekat ima ~lanove (atribute) koji bli`e opisuju prirodu problema. Izuzetak se pojavljuje kada se
objekat koji identifikuje neobi~ne situacije prosledi delu programa koji je posebno napisan da bi
upravljao takvim problemom. Za kod koji prima objekat izuzetka se ka`e da presre}e izuzetak.
Izuzeci se mogu podeliti na ~etiri osnovne kategorije:
Gre{ke u kodu ili podacima - Nastaju na primer, kod neispravnog konvertovanja objekta,
kori{}enja indeksa niza koji je izvan granica, ili kod deljenja nulom.
Izuzeci stanadardnih metoda - Na primer, metod substring(), klase String, mo`e dovesti do pojave
izuzetka StringIndexOutOfBoundsException.
Sopstveni izuzeci - Izuzeci koje sami pravite
Gre{ke Jave - Gre{ke u Java Virtuelnoj Ma{ini koja interpretira Va{ program, ali se obi~no javlja
kao gre{ka u Va{em kodu

Tipovi izuzetaka
Izuzetak je uvek instanca neke klase koja je potklasa standardne klase Throwable. Ovo va`i i za
stadnardne i za sopstvene izuzetke.
Svi standardni izuzeci su pokriveni sa dve direktne potklase klase Throwable, a to su klase Error i
Exception.
Izuzeci pokriveni klasom Error - Ovi izuzeci se odnose na stanja kada se ne o~ekuje da vi ne{to
uradite i stoga i ne treba da ih presre}ete.
Izuzeci pokriveni klasom Exception - Skoro svi izuzeci pokriveni ovom klasom treba da se
presere}u. Izuzetak ~ine izuzeci pokriveni klasom RunTimeException.

Rad sa izuzecima
Ako kod mo`e da proizvede neki od izuzetaka koje treba hvatati (presretati) onda morate i da
napi{ete takav kod. Prilikom pisanja tog koda imate mogu}nost da izaberete da li }e se izuzetak
obraditi u istoj metodi, ili }e se proslediti metodi koja je pozvala metodu u kojoj je izuzetak nastao.
Ako `elite da se gre{ka i objekat klase Exception ne obra|uju na licu mesta, odnosno `elite da ih
prosledite metodi koja je pozvala tu metodu, iza definicije metode treba zadate klju~nu re~ throws i
da navedete vrstu izuzetka.
double mojMetod() throws FileNotFoundException{

}
Ovo zna~i da metoda koja poziva ovu metodu mora da ima kod koji obra|uje izuzetak tipa
FileNotFoundException, ili ga mo`e proslediti dalje u hijerarhiji poziva.

56
Obrada izuzetka
Izuzetak se obra|uje preko tri razli~ita bloka koda. To su blokovi try, catch i finally.
Blok try okru`uje kod koji mo`e dovesti do pojave izuzetka. Kod za koji pretpostavljate da }e
proizvesti izuzetak mora biti u ovom bloku.
Blok catch se odnosi na kod koji obra|uje izuzetak odre|enog tipa.
Blok finally se uvek izvr{ava pre nego {to se zavr{i metoda, bez obzira na to da li je do{lo do
pojave izuzetka.

Blok try
Ako `elite da presretnete (uhvatite) izuzetak, kod se mora nalaziti u okviru bloka try. Blok try
izgleda ovako:
try{
// kod koji moze dovesti do pojave izuzetaka
}

Blok catch
Kod koji obra|uje izuzetak se mora nalaziti u bloku catch. Ovaj blok mora slediti odmah iza bloka
try, sa kodom koji dovodi do pojave izuzetka.
try{
// kod koji moze dovesti do pojave izuzetaka
}catch(ErithmeticException e){
// kod koji obra|uje izuzetak
}
Jedina vrsta izuzetka koju ovaj blok catch mo`e da uhvati je izuzetak tipa ArithmeticException.
Parametar bloka catch mora biti tipa Throwable ili neke od potklasa koje su izvedene iz ove klase.
Ako klasa koju nazna~ite ima potklase, onda taj catch blok mo`e da uhvati izuzetke tog tipa klase,
ali i svih potklasa. To zna~i da mo`ete da kao arugment navedete i klasu Exception, u kom slu~aju
}e se hvatati svi izuzeci.
U primeru koji sledi smo prikazali pojavu i obradu izuzetka.
public class TryCatchProba {
public static void main(String[] args)
{
int i = 1;
int j = 0;

try
{
System.out.println("Ulaz u blok try " + "i = "+ i + " j = "+j);
System.out.println(i/j); // deljenje sa nulom, nastaje izuzetak
System.out.println("Kraj bloka try");
}
// Catch the exception
catch(ArithmeticException e)
{
System.out.println("Doslo je do pojave izuzetka tipa
ArithmeticException");
}

System.out.println("Posle bloka try");


return;
}
}
Promenljiva j u primeru je inicijalizovana na 0, tako da postoji operacija deljenja nulom. Kada se
pojavi izuzetak kontrola programa se odmah prebacuje na blok catch. Nakon {to se izvr{i kod u
57
bloku catch, izvr{avanje programa se nastavlja iskazom koji sledi iza njega. Iskazi u bloku try, koji
slede iza mesta na kome je do{lo do izuzetka se ne izvr{avaju.
Promenite vrednost za j na 1 i probajte ponovo.
Sa blokom try treba pa`ljivo raditi. Promenljive koje defini{ete u ovom bloku, su kao i kod svih
blokova, vidljive samo u okviru bloka.
Blok catch je odvojen od bloka try. Ako `elite da u ovom bloku radite sa objektima koji su
postavljeni u bloku try, onda te promenljive morate definisati ispred bloka try.

Vi{estruki blokovi catch


Ako blok try mo`e da proizvede vi{e razli~itih vrsta izuzetaka, mo`ete staviti vi{e blokva catch.
try{
// kod koji moze dovesti do izuzetka
}catch(ArithmeticException e){
// kod za obradu ovog izuzetka
}catch(IndexOutOfBoundsException e){
// kod za obradu ovog izuzetka
}
Izvr{ava se prvi blok catch koji odgovara tipu nastalog izuzetka. Blokovi koji slede iza njega se ne
izvr{avaju. Ako su dva tipa izuzetka tipa osnovne i potklase i ako je osnovna klasa u catch
blokovima ispred potklase, onda se se izuzetak potklasa nikad ne}e izvr{iti. To zna~i da treba paziti
na redosled iskaza catch.
Ako ima vi{e catch blokova i ako na po~etak stavite klasu Exception, ne}e se izvr{iti nijedan blok
catch iza ovog prvog bloka (to ne mo`e ni da se kompajlira).

Blok finally
Pojava izuzetka zna~i da se izvr{avanje bloka try prekida, bez obzira na kod koji se nalazi iza mesta
nastanka izuzetka. Na taj na~in mo`e da se desi da neki poslovi ostanu nedovr{eni. Mogli ste, na
primer, da otvorite datoteku, koja zatim ostaje nezatvorena.
Blok finally omogu}ava da zavr{ite va`ne stvari koje su prekinute u bloku try. Ovaj blok se
izvr{ava bez obzira na to da li se desio izuzetak ili ne. Ako treba da bude zatvorena datoteka, onda
to zatvaranje treba da stavite u blok finally, ~ime obezbe|ujete da }e se taj posao uvek obaviti.
try{
// kod
}catch(Exception e){
// obrada izuzetka
}finally{
// zavrsni kod
}
Blok try ne mo`e da postoji samostalno, Iza njega mora da ide najmanje jedan blok catch ili finally.
U ve}ini slu~ajeva }ete u metodi napraviti jedan blok try, iza kojeg slede svi blokovi catch i na
kraju mo`da blok finally.
U primeru koji sledi smo pokazali redosled izvr{avanja razli~itih blokova try i catch.
Primer:
import java.io.IOException;

public class TryBlockTest{


public static void main(String[] args) {
int[] x = {10, 5, 0}; // Niz od tri integera

//Ovaj blok javlja izuzetak ako postoji u metodu podeli()


try {

58
System.out.println("Poceo je prvi try blok u metodi main()");
System.out.println("rezultat = " + podeli(x,0)); //Nema gresaka
x[1] = 0; // Dovodi do deljenja sa nulom
System.out.println("rezultat = " + podeli(x,0)); // Aritmeticka greska
x[1] = 1; // sprecava deljenje sa nulom
System.out.println("rezultat = " + podeli(x,1)); // Greska u indeksu
} catch(ArithmeticException e){
System.out.println("U metodi main() je uhvacen aritmeticki izuzetak");
} catch(ArrayIndexOutOfBoundsException e){
System.out.println("U metodi main je uhvacen izuzetak
IndexOutOfBoundsException");
}

System.out.println("Izvan prvog bloka try u metodi main()");


System.out.println("\nPritisnite enter za kraj");

// Ovaj blok sluzi samo za pauziranje programa pre kraja


try{
System.out.println("Drugi blok try u metodi main()");
System.in.read(); // Ceka se na unos
return;
} catch(IOException e){ // Metod read() moze da dovede do
izuzetka
System.out.println("I/O izuzetak uhvacen u metodi main()");
} finally{ // Ovo se uvek izvrsava
System.out.println("blok finallyza drugi blok try u metodi main");
}

System.out.println("Kod u metodi main posle drugog bloka try");


}

// metod za deljenje
public static int podeli(int[] array, int index){
try{
System.out.println("\nUlaz u prvi blok try u metodi podeli()");
array[index + 2] = array[index]/array[index + 1];
System.out.println("Kod na kraju prvog bloka try u podeli()");
return array[index + 2];
} catch(ArithmeticException e) {
System.out.println("Aritemticki izuzetak uhvacen u podeli()");
} catch(ArrayIndexOutOfBoundsException e){
System.out.println("Uhvacen izuzetak Index-out-of-bounds u podeli()");
} finally{
System.out.println("finally blok u podeli()");
}
System.out.println("Izvrsavanje koda nakon bloka try u podeli()");
return array[index + 2];
}
}
U metodi main() postoje dva bloka try. U metodi podeli() postoje dva bloka catch, koji se
izvr{avaju ako do|e do deljenja sa nulom, ili ako se pristupi elementu sa nepostoje}im indeksom. U
metodi podeli postoji i blok finally koji se uvek izvr{ava. U ovoj metodi postoji i kod koji se
izvr{ava izvan svih ostalih blokova. Ovaj deo koda mo`e da dovede do izuzetka
IndexOutOfBoundsException.
Drugi blok try u metodi main() je potreban zato {to se u njemu poziva metoda read() objekata in,
koji je ~lan klase System. U pitanju je standardni ulaz (in). Po{to ova metoda mo`e da dovede do
izuzetka tipa IOException, to se ona ne mo`e pozvati bez blokova try i catch. Ako poku{ate da tako
uradite kompajler }e javiti gre{ku.
Prvi poziv metode podeli() u prvom bloku try ne dovodi do nikakve gre{ke, {to se i vidi iz
{tampanja koja se prikazuju.

59
Drugi poziv metode podeli izaziva deljenje sa nulom. U tom slu~aju se javlja izuzetak
ArithmeticException, koji se hvata u toj metodi.
Tre}i poziv metode podeli() spre~ava deljenje sa nulom, ali dovodi do pojave izuzetka
IndexOutOfBoundsException, koji nastaje usled koda na kraju metoda podeli (return
array[index+2]). Po{to ovaj kod nije u bloku try to se taj izuzetak ne hvata u metodi podeli(). U tom
trenutku metoda se prekida i izvr{avanje se nastavlja u metodi main(), koja hvata taj izuzetak.

Prosle|ivanje izuzetaka
Iako pomo}u bloka catch mo`ete da obradite izuzetak, ~esto se javlja potreba da se izuzetak
prosledi dalje programu, koji na osnovu toga treba da preduzme neku akciju. Izuzetak se iz klauzule
catch mo`e da prosledi preko iskaza throw.
try{
// kod koji dovodi pojave izuzetka
}catch(ArithmeticException e){
// obrada izuzetka
throw e;
}

Objekti izuzetaka
Objekat izuzetka koji se prosle|uje bloku catch mo`e da pru`i dosta informacija o prirordi problema
i njegovom uzroku. Ovo je mogu}e preko metoda klase Throwable iz koje se izvode svi izuzeci.
Objekat klase Throwable ima nekoliko metoda koje pru`aju informacije o izuzetku. To su metoda
getMessage() i metode printStackTrace() i printStackTrace(PrintStream s).
Metoda getMessage() vra}a poruku koja opisuje trenutni izuzetak. To je obi~no puno ime klase
izuzetka i kratak opis izuzetka.
Metoda printStackTrace() prikazuje poruku i pregled izvr{avanja metode. TO se prikazuje na
standardnom izlazu. Pregled izvr{avanja metode sadr`i broj reda u izvornom kodu u kome se
izuzetak pojavio, a iza toga sledi spisak metoda koji su prethodili izvr{enju tog koda. Ovo je vrlo
va`na informacija, jer se na ovaj na~in mo`e da odredi lokacija gre{ke i naravno mesto gde treba
ne{to ispraviti. Metoda printStackTrace() ima i oblik sa prosle|enim objektom PrintStream u kom
slu~aju vi zadajete gde }e se to {tampati.
Promenili smo prethodni primer, tako da se prika`u i informacije o mestu na kome je gre{ka
nastala:
import java.io.IOException;
public class TrTest1 {
public static void main(String[] args) throws IOException {
int[] x = {10, 5, 0}; // Niz od tri integera

//Ovaj blok javlja izuzetak ako postoji u metodu podeli()


try {
System.out.println("Poceo je prvi try blok u metodi main()");
System.out.println("rezultat = " + podeli(x,0)); //Nema gresaka
x[1] = 0; // Dovodi do deljenja sa nulom
System.out.println("rezultat = " + podeli(x,0)); // Aritmeticka greska
x[1] = 1; // sprecava deljenje sa nulom
System.out.println("rezultat = " + podeli(x,1)); // Greska u indeksu
} catch(ArithmeticException e){
System.out.println("U metodi main() je uhvacen aritmeticki izuzetak");
} catch(ArrayIndexOutOfBoundsException e){
System.out.println("U metodi main je uhvacen izuzetak
IndexOutOfBoundsException");
}

System.out.println("Izvan prvog bloka try u metodi main()");


System.out.println("\nPritisnite enter za kraj");

60
// Ovaj blok try sluzi za pauziranje programa pre izlaza
try{
System.out.println("Drugi blok try u metodi main()");
System.in.read(); // Ceka se na unos
return;
} catch(IOException e){ // Metod read() moze da dovede do
izuzetka
System.out.println("I/O izuzetak uhvacen u metodi main()");
} finally{ // Ovo se uvek izvrsava
System.out.println("blok finallyza drugi blok try u metodi main");
}

System.out.println("Kod u metodi main posle drugog bloka try");


}

// podeli method
public static int podeli(int[] array, int index) {
try {
System.out.println("\nUlaz u prvi blok try u metodi podeli()");
array[index + 2] = array[index]/array[index + 1];
System.out.println("Kod na kraju prvog bloka try u podeli()");
return array[index + 2];
} catch(ArithmeticException e) {
System.out.println("Aritemticki izuzetak uhvacen u podeli()\n" +
"\nPoruka iz objekta exception:\n\t" + e.getMessage());
System.out.println("\nIzlaz iz metode StackTrace:\n");
e.printStackTrace(System.out);
System.out.println("\nKraj izlaza iz StackTrace\n");
} catch(ArrayIndexOutOfBoundsException e) {
System.out.println("Uhvacen izuzetak Index-out-of-bounds u podeli()\n" +
"\nMessage in exception object:\n\t" + e.getMessage());
System.out.println("\nIzlaz iz metode StackTrace:\n");
e.printStackTrace(System.out);
System.out.println("\nKraj izlaza iz StackTrace\n");
} finally {
System.out.println("klauzula finally u podeli()");
}
System.out.println("Izvrsavanje koda nakon bloka try u podeli()");
return array[index + 2];
}
}

Sopstveni izuzeci
Ve}ina standardnih izuzetaka u Javi ne pru`a dodatne informacije o stanju koje dovodi do pojave
izuzetka. Ako vam je potrebno vi{e informacija o okolnostima pod kojim je do{lo do pojave
izuzetka, onda mo`ete kreirati sopstvene izuzetke.
Sopstvene izuzetke dodajete kada `elite da imate dodatne informacije kada se pojavi standardni
izuzetak ili kada u kodu imate gre{ku koja opravdava posebnu klasu izuzetka.
Sopstveni izuzeci nisu zamena za normalan kod za oporavak za koji o~ekujete da }e se ~esto
izvr{avati. Ako imate kod koji se ~esto izvr{ava u ovakvim situacijama, onda ga treba ubaciti u
petlju if-then-else, a ne u izuzetke.
Va{e klase izuzetaka moraju da imaju kao superklasu, klasu Throwable. Najbolje je da svoje klase
izvodite iz klase Exception.
Promeni}emo primer koji smo ranije priakzali. Napravi}emo sopstvenu klasu za izuzetak deljenja
sa nulom. Ta klasa }e bli`e obja{njavati izuzetak op{teg tipa ArithmeticException.
Primer:
import java.io.IOException;

61
public class Izuzetak {
public static void main(String[] args) {
int[] x = {10, 5, 0}; // Niz od tri integera

//Ovaj blok javlja izuzetak ako postoji u metodu podeli()


try {
System.out.println("Poceo je prvi try blok u metodi main()");
System.out.println("rezultat = " + podeli(x,0)); //Nema gresaka
x[1] = 0; // Dovodi do deljenja sa nulom
System.out.println("rezultat = " + podeli(x,0)); // Aritmeticka greska
x[1] = 1; // sprecava deljenje sa nulom
System.out.println("rezultat = " + podeli(x,1)); // Greska u indeksu
}catch(DeljenjeSaNulomIzuzetak e){
int index = e.getIndex(); // indeks elementa koji je doveo do greske
if(index > 0){
x[index] = 1;
x[index + 1] = x[index - 1];
System.out.println("Deljenje sa nulom je ispravljeno za element " +
x[index]);
}
}catch(ArithmeticException e){
System.out.println("U metodi main() je uhvacen aritmeticki izuzetak");
} catch(ArrayIndexOutOfBoundsException e){
System.out.println("U metodi main je uhvacen izuzetak
IndexOutOfBoundsException");
}

System.out.println("Izvan prvog bloka try u metodi main()");


System.out.println("\nPritisnite enter za kraj");

// Ovaj blok try sluzi za pauziranje programa pre izlaza


try{
System.out.println("Drugi blok try u metodi main()");
System.in.read(); // Ceka se na unos
return;
} catch(IOException e){ // Metod read() moze da dovede do
izuzetka
System.out.println("I/O izuzetak uhvacen u metodi main()");
} finally{ // Ovo se uvek izvrsava
System.out.println("blok finallyza drugi blok try u metodi main");
}

System.out.println("Kod u metodi main posle drugog bloka try");


}

// metod za deljenje
public static int podeli(int[] array, int index) throws
DeljenjeSaNulomIzuzetak{
try{
System.out.println("\nUlaz u prvi blok try u metodi podeli()");
array[index + 2] = array[index]/array[index + 1];
System.out.println("Kod na kraju prvog bloka try u podeli()");
return array[index + 2];
} catch(ArithmeticException e) {
System.out.println("Aritemticki izuzetak uhvacen u podeli()");
throw new DeljenjeSaNulomIzuzetak(index + 1);
} catch(ArrayIndexOutOfBoundsException e){
System.out.println("Uhvacen izuzetak Index-out-of-bounds u podeli()");
} finally{
System.out.println("finally blok u podeli()");
}
System.out.println("Izvrsavanje koda nakon bloka try u podeli()");
return array[index + 2];
}

62
}
public class DeljenjeSaNulomIzuzetak extends Exception{
private int index = -1; // indeks elementa niza koji dovodi do greske

// podrazumevani konstrktor
public DeljenjeSaNulomIzuzetak(){ }

// Standardni konstruktor
public DeljenjeSaNulomIzuzetak(String s) {
super(s); // Poziv konstruktora osnovne klase
}

public DeljenjeSaNulomIzuzetak(int index){


super("/ sa nulom"); // Poziv osnovnog konstruktora
this.index = index; // Podesavanje indeksa
}

// Uzimanje indeksa za koji se desila greska


public int getIndex() {
return index; // Return the index value
}
}
Promenili smo metod podeli() iz prethodnog primera, tako {to smo definisali da on mo`e da
prosledi izuzetak tipa DeljenjeSaNulomIzuzetak (throws u zaglavlju metoda). Promenili smo i kod
za hvatanje gre{ke u ovom metodu, i to tako {to smo dodali iskaz
throw new DeljenjeSaNulomIzuzetak(index+1)
Ovaj iskaz generi{e novi izuzetak sa vi{e detalja i prosle|uje ga metodi odakle je metoda podeli
pozvana.
U metodi main smo dodali blok catch za obradu novog tipa izuzetka (ispred ArithmeticException) i
u tom kodu smo promenili element koji je doveo do problema.
Ulaz i izlaz u Javi
Ulazne i izlazne operacije se u Javi realizuju pomo}u tokova. Tok je apstraktna prezentacija
ulaznog ili izlaznog ure|aja, koji predstavlja izvor ili odredi{te podataka. U tok mo`ete da upisujete
podatke i iz njega mo`ete da podatke ~itate. Tok se mo`e shvatiti kao niz bajtova koji teku u i iz
programa.
Kada podatke upisujete u tok, tok se naziva izlaznim tokom. Izlazni tok mo`e biti datoteka na disku,
datoteka na drugom ra~unaru, {tampa~ i sl. Izlazni tok mo`e biti i monitor.
Podaci se ~itaju iz ulaznog toka. Obi~no je u pitanju datoteka na disku, ili drugom ra~unaru ili
tastatura.
Samo Java aplikacije mogu da koriste tokove na ma{ini na kojoj se program izvr{ava. Oni obi~no
nisu dostupni apletima.
Osnovni razlog za upotrebu tokova u Javi je da se obezbedi nezavisnost programskog koda u
odnosu na ure|aj koji se koristi. Prednost je u tome da ne morate brinuti o detaljima svakog od
ure|aja, kao i da }e program raditi sa razli~Itim ulazno/izlaznim ure|ajima bez promene koda.
Vrste tokova
Ve}ina klasa koje su potrebne za manipulaciju tokovima se nalaze u paketu java.io. Ovaj paket
podr`ava binarne tokove, koji sadr`e binarne podatke i znakovne tokove, koji sadr`e tokove
znakova. Ako u tok pi{ete podatke kao niz bajtoba, podaci se upisuju isto onako kako se nalaze i u
memoriji. Nema nikakve transformacije podataka.
Znakovni tokovi se koriste za skladi{tenje i ponovno dobijanje teksta. Koriste se i za ~itanje
tekstualnih datoteka koje nisu nastale iz Jave.

63
Klase za ulaz i izlaz
U paketu java.io se nalaze slede}e osnovne klase za podr{ku ulazno izlaznih tokova.
Klasa Opis
File Objekat ove klase predstavlja putanju do datoteke kojoj pristupate za ulaz ili
izlaz. Mo`e da se odnosi i na direktorijum
OutputStream Osnovna klasa za izlazne operacije toka bajtova
InputStream Osnovna klasa za ulazne operacije toka bajtova
Writer Osnovna klasa za izlazne operacije toka znakova
Reader Osnovna klasa za ulazne operacije toka znakova
Klase InputStream, OutputStream, Reader i Writer su apstraktne klase. Iz apstraktnih klasa se ne
mogu praviti instance klase. Ove klase se korsite samo kao osnova za izvo|enje drugih klasa sa
konrkretnim mogu}nostima. U ove ~etiri klase su me|utim, definisani osnovni metodi koji se koriste
za ulazno/izlazne operacije.
Tokovi datoteka koji se defini{u pomo}u klasa koje se izvode iz ove ~etiri navedene klase su po
svojoj prirodi sekvencijalni. Ako `elite da datoteci i zapisima u njoj pristupate po slu~ajnom
principu, morate da koriste klasu RadnomAccessFile.
Definisanje datoteke
Objekat File predstavlja putanju do fizi~ke datoteke ili direktorijuma na disku, a ne sam tok. Pored
toga {to omogu}ava da napravite objekat koji predstavlja putanju do datoteke, u ovoj klasi se nalaze
i nekoliko metoda koji omogu}avaju testiranje objekata koje pravite.
Najjednostavniji na~in kreiranja objekta je preko konstruktora, koji kao arugment prihvata objekat
tipa String, koji odre|uje putanju do datoteke ili direktorijuma.
File mojDir = new File(“F:/jdk1.3/src/java/io”);
Kod Windows operativnih sistema, umesto znaka “/” mo`ete koristiti i ‘\\’.
Ako `elite da dobijete putanju do datoteke morate da obezbedite da prosle|eni string ukazuje na
datoteku.
File mojaDatoteka = new File(“F:/jdk1.3/src/java/io/File.java”);
Ovaj objekat sada ukazuje na datoteku sa izvornim kodom koja sadr`i definiciju klase File.
Ako `elite putanju do datoteke mo`ete da napravite i preko druge verzije konstruktora za klasu File.
U toj verziji se {alju dva argumenta. Prvi argument je drugi objekat File koji ukazuje na
direktorijum, a drugi argument je ime datoteke na tom direktorijumu.
File mojDir = new File(“F:/jdk1.3/src/java/io”)’
File mojaDatoteka = new File(mojDir, “File.java”);
Ovaj pristup je zgodan kada `elite da radite sa vi{e datoteka koje se nalaze u istom direktorijumu.
U primeru koji sledi smo pokazali kako se preko objekta File mogu dobiti informacije o odre|enom
direktorijumu i datotekama u njemu.
Primer:
import java.io.*;
public class TryFile{
public static void main(String[] args){
// Kriera se direktorijum (objekat koji sadrzi ptanju do njega)
File myDir = new File("d:/temp");
System.out.println(myDir +
(myDir.isDirectory()?" is":" is not") + " a directory.");

64
// Kreira se datoteka (objekat koji ukazuje na nju)
File myFile = new File(myDir, "prikaz.doc");
System.out.println(myFile +
(myFile.exists()?" does":" does not") + " exist");
System.out.println("You can" +
(myFile.canRead()?" ":"not ") + "read " + myFile);
System.out.println("You can" +
(myFile.canWrite()?" ":"not ") + "write " + myFile);
return;
}
}
Izlazni tokovi
Izlazni tokovi bajtova se opisuju preko klase OutputStream i onih koje se iz nje izvode. Sve klase
koje se izvode iz ove klase }e naslediti metode koje postoje u ovoj klasi. Potklase ove klase su
FileOutputStream, ByteArrayOutputStream, PipedOutputStream, FilterOutputStream.
Klasa FileOutputStream defini{e izlazni tok kao datoteku.
Klasa ByteArrayOutputStream je izlazni tok koji podatke upisuje u niz bajtova.
Klasa PipedOutputStream dodaje podatke u izlazni tok koji je namenjen za kori{}enje sa objektom
PipedInputStream.
Klasa FilterOutputStream je osnovna klasa za izvo|enje klasa koje pro{iruju mogu}nosti ostalih
klasa.
Izlazni tokovi znakova omogu}avaju pisanje znakovnih podataka. Unicode znakovi se automatski
prebacuju u kod koji koristi ra~unar na kome se program izvr{ava.
Sve klase koje omogu}avaju rad sa znakovima se izvode iz apstraktne klase Writer. Potklase ove
klase su:
StringWriter - pi{e se u String
CharArrayWriter - pi{e se u niz tipa char
PipeWriter - pi{e se u PipeReader
OutputStreamWriter - pi{e se u OutputStream
FileWriter - pi{e se u File
PrintWriter - pi{e se u Writer
BufferedWriter - pi{e se u spremi{te
FilterWriter - apstraktna osnova za Filter.
Klasa Writer defini{e slede}e metode. Ovi metodi se nasle|uju u njenim potklasama.
write (int c) - Pi{e znak c u izlazni tok. Povratni tip je void.
write (char[] cArray) - u tok se pi{e znakovni niz
write char[] cArray, int offset, int length) - u tok se iz niza cArray pi{e length znakova, po~ev od
elementa sa indeksom offset.
write (String str) - u tok se pi{e string
write (String str, int offset, int length) - iz stringa str u tok pi{e length znakova, po~ev od pozicije
offset.
Ako do|e do gre{ke ove metode proizvode izuzetak tipa IOException.

65
U ovoj klasi postoje i metode flush() i close(). Metoda flush() se koristi kada `elite da zavr{ite niz
izlaznih operacija nad tokom (tako {to se prebacuju podaci koji su jo{ uvek unjemu). Metodu
close() pozivate kada `elite da zavr{ite sve operacije i da prekinete vezu sa tokom.
Pisanje u datoteku
Za zapisivanje u tekstualnu datoteku mo`ete da koristite klasu FileWriter. Ova klasa ima
konstruktor koji kao argument prihvata objekat tipa File. U primeru koji sledi }emo u datoteku
dodati tekst.
Primer:
import java.io.*;
public class WriteCharacters{
public static void main(String[] args) {
try {
String dirName = "d:\\kurs\\"; // Direktorijum za izlaznu datoteku
String fileName = "Proba.txt"; // Ime izlazne datoteke
File output = new File(dirName, fileName);
output.createNewFile(); // Ako je potrebno pravi se nova datoteka

if(!output.isFile()){ // PRoverava se da li postoji datoteka


System.out.println("Kreiranje datoteke " + output.getPath() + " nije
uspelo.");
return;
}

BufferedWriter out = new BufferedWriter(


new FileWriter(output.getPath(), true));

String[] sayings = { "Prvi red u datoteci\n",


"Drugi red u datoteci.\n",
"Treci red u datoteci\n",
"Cetvrti red u datoteci\n"};

// Zapisuje se u datoteku. Ispred se pi[e du`ina stringa


for(int i = 0; i < sayings.length; i++){
out.write(sayings[i].length() + sayings[i]);
}
out.close();
}catch(IOException e){
System.out.println("Greska u pisanju u datoteku " + e);
}
}
}
Na po~etku programa se kreira objekat File koji predstavlja putanju do datoteke koju `elimo da
napravimo (direktorijum d:\\kurs i datoteka Proba.txt). Nakon toga smo na osnovu objekta
FileWriter napravili objekat BufferedWriter, koji }e podatke dodavati u izlaznu datoteku. Obratite
pa`nju na drugi argument (true) u konstruktoru klase FileWriter, koji govori da se u tu datoteku
dodaju zapisi. Ako bi vrednost ovog atributa bila false, onda se bi se datoteka uvek pravila iznova.
Ulazni tokovi
Sve klase izvedene iz klase InputStream nasle|uju metode:
read() - slu`i za ~itanje jednog bajta podataka iz toka i da vrati tip int.
read(byte[] buffer) - ~ita se dovoljno bajtova da se popuni niz buffer ili dok se ne do|e do kraja niza.
skip(long n) - koristi se za preskakanje dela datoteke koji ne `elite da obradite
mark(int readlimit) - obele`ava trenutnu poziciju, tako da se kasnije pomo}u metode reset() mo`ete
vratiti na nju.

66
reset() - pozicionira tok na mesto definisano prethodnim pozivom metode mark().
Postoje i druge metode.
Potklase klase InputStream
FileInputStream - ~itanje iz datoteke
SequenceInputStream - omogu}ava spajanje vi{e ulaznih tokova u jedinstveni tok
PipedInputStream - ~itanje iz toka koji dolazi iz objekta PipedOutputStream
ByteArrayInputStream - - ~ita podatke iz niza bajtova
FilterInputStream - Osnovna klasa za filtriranje
ObjectInputStream - ~itanje iz toka sa objektima
Ulazni tok znakova
Ulazne operacije obezbe|uju klase koje se izvode iz klase reader. Ovaj objekat se koristi za ~itanje
toka napisanog preko klase Writer. U primeru koji sledi smo pro~itali datoteku koju smo napravili u
prethodnom primeru. Izlaz smo od{tampali na ekranu.
Primer:
import java.io.*;
public class CitanjeIzDatoteke {
public static void main(String[] args) {
try {
String dirName = "d:\\kurs\\";
String fileName = "Proba.doc";

File input = new File(dirName, fileName);

BufferedReader in = new BufferedReader(new FileReader(input));


int c;
StringBuffer buf = new StringBuffer();
while((c = in.read()) != -1){
buf.append((char)c);
}
System.out.println(buf.toString());
} catch(FileNotFoundException e){
System.err.println(e);
return;
} catch(IOException e){
System.err.println("Error reading input file" + e );
return;
}
}
}
Datoteku ~itamo jedan po jedan karakter. Metod read() objekta BufferedReader ~ita jedan po jedan
karakter i vra}a njegovu int prezentaciju. Ako je dostignut kraj datoteke vra}a -1. Taj karakter koji
se vra}a pretvaramo u tip char i zatim dodajemo u objekat StringBuffer. Kada se petlja zavr{i
{tampa se string koji se nalazi u StringBuffer objektu.
Skladi{tenje objekta u datoteku
Proces sme{tanja objekta u datoteku se naziva serijalizacijom. ^itanje objekta iz datoteke se naziva
deserijalizacijom. Za serijalizaciju i deserijalizaciju objekata se koriste klase ObjectOutputStream i
ObjectInputStream. Ove klase su izvedene iz klasa DataOutputStream i DataInputStream, tako da
ove klase poseduju sposobnost obrade osnovnih tipova, a sve to preko nasle|enih metoda.
Upisivanje objekta u datoteku

67
Konstruktor klase ObjectOutputStream kao argument zahteva objekat klase FileOutputStream. Ovaj
objekat defini{e tok za datoteku u koju nameravate da smestite svoj objekat.
FileOutputStream izlaz = new FileOutputStream(“Proba”);
ObjectOutputStream objectOut = new ObjectOutputStream(izlaz);
Pisanje u datoteku proba mo`ete da izvr{ite preko metode writeObject(), klase ObjectOutputStream,
pri ~emu se objekat o kome se radi prosle|uje kao argument. Ovoj metodi mo`ete da prosledite
objekat bilo koje klase. Da bi se objekat mogao da zapisuje u tok na ovaj na~in klasa mora da
zadovoljava tri osnovna uslova:
Klasa mora biti deklarisana kao public
Klasa mora da implementira interfejs Serializable
Ako klasa ili potklasa ima direktnu ili indirektnu potklasu koja se ne mo`e serijalizovati, onda ta
osnovna klasa mora imati podrazumevani kosntruktor (koji ne zahteva nijedan argument).
Ako su prethodni uslovi zadovoljeni, onda se upisivanje objekta u tok koji je ranije definisan mo`e
uraditi na slede}i na~in:
objectOut.writeObject(mojObjekat);
Prilikom upisivanja se vodi ra~una o tome da se upi{e sve {to je potrebno da bi se objekat, kasnije
u operaciji ~itanja mogao da rekonstrui{e. Tu su i informacije o klasi i svim njenim supreklasama,
kao i sadr`aj i tipovi ~lanova klase. Ovo radi ~ak i kada su ~lanovi klase drugi objekti, sve dok se ti
drugi objekti mogu serijalizovati. Nezavisni objekti se u tok zapisuju posebnim pozivom metode
writeObject(), ali se objekti koji su ~lanovi drugog objekta zapisuju automatski. Metod
writeObject() koji smo mi pozvali }e dalje pozvati istoimene metode za sve objekte koji su ~lanovi
podaci. Svaki nezavisan objekat koji zapisujete zahteva poseban poziv metode, ali se sa objektima
koji su ~lanovi klase, to radi automatski.
Implementacija interfejsa Serializable
U klasu za koju `elite da implementira interfejs Serializable treba dodati slede}i kod:
public MojaKlasa implements Serializable{
// definicija klase
}
Sva polja u klasi moraju biti takva da se mogu serijalizovati, {to zna~i da moraju biti osnovnog tipa
ili tipa klase koja se mo`e serijalizovati.
^lanovi klase deklarisani kao transient
Ako klasa ima ~lanove podatke koji se ne mogu serijalizovati, ili koje ne `elite da upi{ete u tok,
onda treba da ih ozna~ite sa transient.
public MojaKlasa implements Serializable{
transient protected Graphics g;// tranzientan ~lan
}
Ako ste neki ~lan deklarisali sa transient, onda metoda writeObject() ne}e poku{ati da taj ~lan
upisuje u tok. Kada se objekat klase ponovo u~ita, on }e biti ispravno konstruisan, uklju~uju}i i
~lanove koji su deklarisani kao transient. Vrednosti tih ~lanova ne}e biti iste kao pre slanja u
datoteku, po{to se u datoteku nisu ni zapisivale.
Ovo se mo`e koristiti za vrednosti koje nisu bitne, kao {to je na primer trenutno vreme ili teku}i
datum, koji uvek treba da budu postavljeni na trenutnu vrednost. Njih treba eksplicitno
rekonstruisati kada se objekat u~itava iz toka.
^itanje objekta iz datoteke
Najpre treba napraviti objekat ObjectInputStream. Nakon toga se mo`e pozvati metoda readObject()
za taj objekat. Ova metoda vra}a tip Object, koji dalje treba pretvoriti u odgovaraju}i tip.
68
Primer: Objekat tipa MojaKlasa se iz datoteke mo`e u~itati na slede}i na~in:
MojaKlasa obj; // ovde se skladisti objekat
try{
// konstruise se objekat ulaznog toka za datoteku po imenu MojaDatoteka
FileInputStream ulaz = new FileInputStream(“MojaDatoteka”);
ObjectInputStream objectIn = new ObjectInputStream(ulaz);

// deserijalizacija objekta
obj = (MojaKlasa) objectIn.readObject();
}catch(IOException e){
System.out.println(e);
}catch(ClassNotFoundException e){
System.out.println(e);
}
Po{to metoda readObject() mo`e izazvati i izuzetke koji su potklasa klase IOException i izuzetak
ClassNotFoundException, to se moraju napisati najmanje ova dva catch bloka.
Pomo}ne klase
U paketu java.util se nalazi skup klasa op{te namene, koje se koriste za razli~ite stvari. Tu se nalaze
razli~ite klase kontejneri, zatim klase za rad sa datumima, kao i neke klase za obradu stringova.
Klase kolekcija
Kolekcija je op{ti termin za objekat u kome se nalazi skup objekata koji su na neki na~in grupisani.
Postoje tri osnovna tipa kolekcija. To su skupovi, sekvence i mape. Kada se u Javi pomene
kolekcija misli se na kolekciju referenci na objekte, a ne sa kolekciju samih objekata. Objekti su u
odnosu na kolekciju spolja{nji objekti.
Skupovi su najjednostavnije kolekcije. Objekti u njima nisu pore|ani na odre|eni na~in i jednostavno
se u sme{taju u skup bez ikakve kontrole sme{tanja. Ovo je kao kada ne{to stavljate u d`ep.
Jednostavno stavite unutra i stvari se izme|aju bez ikakvog reda.
Sekvence su kolekcije u koje se objekti sme{taju na linearan na~in, sa po~etkom i krajem. Obi~an
niz je primer za kolekciju, ali je ograni~ene veli~ine. Va`na osobina kolekcija je da one mogu da se
{ire i da prihvate onoliko elemenata koliko je potrebno. Po{to je lista (sekvenca) linearna, u nju
mo`ete da objekat dodajete na po~etak, na kraj ili da ga ubacujete ispred odre|enog objekta. Objekat
iz liste se mo`e izvaditi na nekoliko na~in. Mo`e se dobiti prvi, ili poslednji objekat, zatim objekat
na zadatoj poziciji (preko indeksa, kao u nizu), ili se mo`e tra`iti objekat koji je identi~an zadatom
objektu. U ovom poslednjem slu~aju se proveravaju svi objekti koji se nalaze u listi.
Mape se razlikuju od skupova i sekvenci po tome {to sadr`e parove objekata. Mapa se ponekad
naziva i re~nikom, zbog na~ina na koji radi. Svaki objekat koji se sme{ta u mapu ima pridru`en
drugi objekat, klju~. Ova dva objekta se u mapu sme{taju kao par. Klju~ odre|uje gde je objekat
sme{ten u mapi. Objektu u map{i pristupate preko tog klju~a. Ovo je ekvivalentno re~i koju tra`ite
u obi~nom re~niku.
Klju~ mo`e biti bilo koja vrsta objekta. Svi klju~evi u mapi moraju biti razli~iti. Ako na primer,
pravite program za imenik i `elite da imate sve detalje o nekoj osobi (adresa, ime, broj telefona ..) u
jednom objektu, kome se kasnije pristupa preko klju~a, onda taj klju~ mo`e da bude na primer, ime
osobe, ili jo{ bolje mati~ni broj, za koji smo sigurni da je jedinstven. Mesto sme{tanja objekta u
map{i se odre|uje procesom he{iranja. He{iranje obra|uje objekat klju~a i pravi celobrojnu vrednost
koja se zove he{ kod. Idealno je kada he{iranje proizvodi vrednosti koje su uniformno raspore|ene u
odre|enom opsegu. Svaki klju~ treba da proizvede razli~it he{ kod.
U paketu java.util postoji devet klasa koje se mogu koristiti za rukovanje kolekcijama objekata. U
pitanju su liste, skupovi i mape. Pomenu}emo samo neke od njih.

69
Klase koje se koriste za implementaciju povezanih listi i koje se najvi{e koriste su Vector,
ArrayList i LinkedList.
Klasa Vector implementira listu koja automatski pove}ava svoj kapacitet da bi se prihvatili novi
elementi. Objekti se sme{taju i vade iz kolekcije putem indeksa, kao i u obi~nom nizu. Elementima
vektora se mo`e pristupati i preko interfejsa iterator. Vector je jedina klasa koja je sinhronizovana,
odnosno dobro radi kada joj se istovremeno pristupa iz vi{e niti.
ArrayList implentira niz objekata kome se mo`e menjati veli~ina i kome se mo`e pristupati i kao
povezanoj listi. Radi isto kao klasa Vector, ali nije sinhronizovana.
LinkedList implementira povezanu, ulana~anu listu. Ovo je tip kolekcije nazvan lista ili sekvenca.
Objekti se sme{taju na linearan na~in
Klasa Hashtable implementira mapu u kojoj klju~evi ne smeju biti null vrednosti.
Klasa HashMap implementira mapu koja dozvoljava sme{tanje null objekata i dozvoljava da klju~
bude null (samo jedan, jer klju~evi moraju biti jedinstveni).
Rad sa kolekcijom Vector
Klasa Vector predstavlja kolekciju elemenata tipa Object. Funkcioni{e sli~no kao niz, ali mo`e da
automatski raste i time se prilago|ava potrebnom kapacitetu. Po{to sadr`i element tipa Object, u nju
se mo`e sme{tati objekat bilo kojeg tipa. To je i potencijalna opasnost da se unutra na|u klase
razli~Itih tipova, {to mo`e da dovede do problema prilikom rada sa takvim vektorima.
Klasa Vector ima ~etiri konstruktora. Podrazumevani konstruktor pravi prazan objekat klase Vector
sa kapacitetom da se primi 10 objekata. Ako je Vector pun, odnosno ako je dostignut njegov
kapacitet, onda se prilikom dodavanja novog elementa pove}ava kapacitet. Podrazumevani rast
objekta, ako se kapacitet {iri radi primanja novih ~lanova je 10.
Vector transakcija = new Vector();
Kapacitet objekta Vector se mo`e eksplicitno da podesi prilikom kreiranja objekta.
Vector transakcija = new Vector(100);
Ovaj vektor inicijalno ima kapacitet da primi 100 objekata. Svaki put kada se popuni, ako se `eli
dodavanje novog elementa, kapacitet se duplira. Proces dupliranja kapaciteta, mo`e biti prili~no
neefikasan. Ako na primer, u Vector koji smo malopre definisali smestimo 7000 objekata, on }e
realno imati prostor za 12800 objekata. Ovo zna~i da je nepotrebno zauzeto dosta memorije.
Ovo se mo`e izbe}i navo|enjem iznosa za koji Vector treba da se pove}a. U pitanju je slede}i
konstruktor:
Vector transakcija = new Vector(100, 10);
Ovaj objekat ima inicijalni kapacitet od 100, ali }e se kapacitet svaki put uve}avati za samo 10
elemenata. Ovo ne zna~i treba i}i u drugu krajnost i pove}avati kapacitet svaki put samo za 1, jer je
proces pove}anja zahteva vreme, {to mo`e da uti~e na efikasnost programa.
Primer:
import java.util.*;
public class TryVector {
public static void main(String[] args) {
Vector imena = new Vector();
String[] ime = { "Dragan", "Novica", "Petar", "Lazar", "Milan", "Nikola"};

for(int i = 0 ; i<ime.length ; i++)


imena.add(ime[i]);

for(int i = 0 ; i<imena.size() ; i++)

70
System.out.println((String)imena.get(i));
}
}
Sme{tanje objekata u vektor
Objekti se u vektor sme{taju metodom add.
transakcije.add(element);
Ovim se u vektor transakcija dodaje referenca na objekat element. Ovo se dodaje na kraj. Veli~ina
objekta klase Vector se pri tome pove}ava za jedan. Svi objekti koji su pre toga bili u vektoru ostaju
na svojim mestima.
Postoji i verzija metode add() koja prima dva argumenta. Prvi argument je indeks koji ozna~ava
poziciju, a drugi je objekat koji treba uvrstiti. Vrednost indeksa mora biti manja ili jednaka veli~ini
objekta klase Vector. Indeks se broji isto kao od niza, po~ev od 0.
transakcije.add(2, elementNovi);
Prethodni iskaz u vektor transakcija ubacuje element elementNovi i to na tre}u poziciju. Objekat
koji je pre toga bio na tre}oj poziciji se sada pomera na ~etvrtu, ~etvrti na petu itd. Ako navedete
vrednost indeksa koja je negativna ili ve}a od veli~ini, javlja se izuzetak
ArrayIndexOutOfBoundsException.
Promenu elementa u vektoru je mogu}e uraditi preko metoda set(). Ovaj metod prihvata dva
argumenta. Prvi argument je indeks pozicije na koju se sme{ta objekat koji se zadaje kao drugi
argument. Tre}i element u objektu transakcija, klase Vector }ete promeniti na slede}i na~in:
transakcije.set(2, noviElement);
Metod vra}a referencu na objekat koji je prethodno bio na toj poziciji.
Izvla~enje objekata iz vektora
Ako znate indeks elementa u vektoru, mo`ete ga izvaditi preko metode get().
Transakcija trans = (Transakcija) transakcije.get(4);
Ovim se izvla~i peti element vektora. Ovde je neophodna eksplicitna konverzija.
Pristupanje elementima preko iteratora
Elementima vektora se mo`e pristupati preko iteratora koji se mo`e dobiti iz klase Vector. Ovaj
metod obi~no ima prednost u odnosu na metodu get() klase Vector.
Referenca na iterator se dobija pozivom metode iterator, klase Vector.
Iterator it = imena.iterator();
Ova metoda vra}a objekat Iterator, koji se mo`e koristiti za prolaz kroz sve elemente vektora.
Mo`e se koristiti i objekat ListIterator. Pomo}u ovog metoda mo`ete i}i unapred i unazad kroz
vektor.
ListIterator lt = imena.listIterator();
Mogu}e je dobiti i ListIterator koji obuhvata samo deo vektora. Tom prilikom se poziva druga
verzija metode listIterator, koja kao argument prihvata indeks pozizcije prvog elementa vektora,
koji treba da se na|e u iteratoru.
ListIterator lt = imena.listIterator(2);
Ovim se dobija ListIterator koji obuhvata elemente po~ev od elementa na poziciji 2. Argument ne
sme biti negativan.
Brisanje elemenata iz vektora

71
Referencu na element koji se nalazi na odre|enoj poziciji u vektoru mo`ete da izbacite pomo}u
metode remove(). Ona kao argument prima indeks koji ozna~ava poziciju objekta.
transakcije.remove(3);
Uklanja se element koji se nalazi na poziciji 3. Metoda vra}a referencu na objekat koji se uklanja.
Pretra`ivanje vektora
Indeks pozicije objekta koji se nalazi u vektoru se mo`e dobiti pomo}u metode indexOf(). Ovom
metodu se kao argument prosle|uje referenca objekta, ~iji se indeks tra`i.
int pozicija = transakcije.indexOf(element);
Prilikom pretra`ivanja se koristi metoda equals(), tako da Va{a klasa treba da ima odgovaraju}u
implementaciju ove metode.
U primeru koji sledi smo napisali program koji modelira skup ljudi u koji se mogu, sa tastature,
dodavati nove osobe.
Primer:
import java.util.*;
public class TryVector {
public static void main(String[] args) {
Vector imena = new Vector();
String[] ime = { "Dragan", "Novica", "Petar", "Lazar", "Milan", "Nikola"};

for(int i = 0 ; i<ime.length ; i++)


imena.add(ime[i]);

ListIterator lt = imena.listIterator();
while(lt.hasNext()){
System.out.println((String)lt.next());
}

int l = imena.indexOf("Nikola");
System.out.println(l);
}
}
Klase za datum i vreme
U paketu java.util se nalaze klase koje omogu}avaju da radite sa datumom i vremenom. To su klasa
Date, klasa Calendar i klasa GregorianCalendar. Objekat klase Date defini{e odre|eni vremenski
trenutak, sa ta~no{}u do milisekunde, ali mereno od 1 januara 1970-e godine. Po{to se ovo meri u
odnosu na odre|eni datum, to je i to {to se dobija tako|e datum. Klasa GregorianCalendat ima
metode za dobijanje dana, meseca i godine iz datuma, a tu jo{ neke korisne metode. Objekat
kalendara je uvek postavljen na odre|eni datum, ali ga mo`ete i promeniti.
Klasa Date
Ova klasa ima dva konstruktora. To su podrazumevani konstruktor, bez argumenata, i konstruktor
sa jednim argumentom tipa long.
Date() - ovaj konstruktor pravi objekat na osnovu teku}eg vremena sa sata Va{eg ra~unara (sa
ta~no{}u do milisekunde).
Date (long time) - pravi se objekat na osnovu vremena (u milisekundama) po~ev od 1 januara 1970
godine.
Klasa Date ima i neke korisne metode za pore|enje datuma. To su:
after (Date prethodni) - vra}a true ako je teku}i objekat datum koji je kasniji od onog koji je
prosle|en argumentom prethodni), u suprotnom vra}a false.

72
before(Date kasniji) - vra}a true, ako teku}i objekat predstavlja datum koje je raniji od onog koji je
prosle|en kao argument.
equals(Object datum) - vra}a true ako teku}i objekat i argument predstavljaju isti datum i vreme, u
suprotnom vra}a false. Ovo zna~i da }e oba objekta da vrate istu vrednost preko metoda getTime().
Formatiranje datuma
Podrazumevana vrednost za ispisivanje datuma je u skladu sa vremenskom zonom koja je pode{ena
na ra~unaru na kojem se radi. Ako se `eli format datuma u skladu sa odre|enom lokacijom, mo`e se
koristiti klasa SimpleDateFormat koja se nalazi u paketu java.text. Jedan od konstrktora ove klase,
kao argument prihvata `eljeni format datuma. Svaki datum koji se kasnije prosledi metodi format iz
ove klase se formatira prema tim pravilima.
java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("dd-MM-yyyy");
System.out.println(sdf.format(dt));
Ovim se datum {tampa u formatu dan-mesec-godina.
Ako `elite da iz stringa dobijete datum, mo`ete da upotrebite funkciju parse, iz klase
SimpleDateFormat.
Za prethodno pode{en format datum, mo`emo da napi{emo:
dt2 = sdf.parse("03-05-2002");
Dobi}e se novi datum. Ovo je korisno kada se sa odnekud (na primer, sa HTML strane) dobije
datum u obliku stringa, od kojeg kasnije treba napraviti datum.
Kako funkcija parse mo`e da proizvede izuzetak tipa ParseException, to se ovaj izuzetak mora da
uhvati, ina~e }e kompajler da prijavi gre{ku.
Klase za kalendare
Kalendar je klasa koja sadr`i razli~ite pomo}ne funkcije za manipulaciju datumima. Mo`e da se
koristi apstraktna klasa Calendar, ali i klasa GregorianCalendar, od koje je mogu}e praviti instance.
U klasi GregorianCalendar postoji vi{e konstruktora. Podrazumevani konstruktor (bez argumenata)
kreira novi kalendar i njegov datum postavlja na teku}i trenutak.
GregorianCalendar cal = new GregorianCalendar();
Iz ovog objekta mo`ete da dobijete teku}i datum pozivom metoda getTime().
Date sada = cal.getTime();
Ako `elite da kalendar postavite na neki odre|eni datum, postoji metoda setTime(), koja kao
argument prihvata objekat klase Date.
java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("dd-MM-yyyy");
GregorianCalendar cl = new GregorianCalendar();
dt2 = sdf.parse("03-05-2002");
cl.setTime(dt2);
U klasi GregorianCalendar postoje polja koja odgovaraju danima u nedelji, danima u godini,
mesecima u godini, godini i sl.
System.out.println("Dan u mesecu je " + cl.get(cl.DAY_OF_MONTH));// dan u mesecu
System.out.println("MEsec u godini je " + (cl.get(cl.MONTH)+1));//mesec u godini
System.out.println("Godina je " + cl.get(cl.YEAR));// godina
Kalendar poseduje i korisne funkcije koje omogu}avaju sabiranje i oduzimanje datuma. Na primer,
ako `elite da datumu dodate 14 godina, mo`ete da napi{ete:
cl.add(cl.YEAR, 14);
Ako `elite da se vratite u pro{lost, treba da navedete negativan argument.

73
cl.add(cl.MONTH, -5);
Ovim ste se vratili u pro{lost za pet meseci.
Primer:
package proba;
import java.util.*;
public class Datumi {
public static void main(String[] args) {
long vreme = System.currentTimeMillis();
Date dt2 = null;
Date dt = new Date();
Date dt1 = new Date(vreme);

System.out.println(" dt = " + dt.toString());


System.out.println(" dt1 = " + dt1.toString());

java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("dd-MM-yyyy");


System.out.println(sdf.format(dt));

GregorianCalendar cl = new GregorianCalendar();


dt2 = cl.getTime();
System.out.println(" dt2 = " + dt2.toString());
try{
dt2 = sdf.parse("03-05-2002");
System.out.println(" dt2 = " + dt2.toString());
}catch(Exception e){
System.out.println(" izuzetak");
}
cl.setTime(dt2);
System.out.println(" novo vreme je = " + cl.getTime());

System.out.println("Dan u mesecu je " + cl.get(cl.DAY_OF_MONTH));// dan u


mesecu
System.out.println("MEsec u godini je " + (cl.get(cl.MONTH) + 1));// mesec u
godini
System.out.println("Godina je " + cl.get(cl.YEAR));// godina

cl.add(cl.YEAR, 14);
System.out.println(" novo vreme je = " + cl.getTime());
cl.add(cl.MONTH, -5);
System.out.println(" novo vreme je = " + cl.getTime());
}
}
U primeru je pokazano kako se koriste klase koje smo u prethodnom tekstu pomenuli. Za kreiranje
datuma se koristi klasa Date, za formatiranje datuma klasa SimpleDateFormatter i za rad sa vi{e
datuma, klasa GregorianCalendar.
Klasa StringTokenizer
Ova klasa omogu}ava da se zadati string podeli na tokene, na osnovu unapred zadatog delimitera.
Klasa ima nekoliko konstruktora.
StringTokenizer(String s)
Ovaj konstruktor kreira StringTokenizer koji iz stringa s mo`e da vadi pojedine tokene. Koriste se
podrazumevani delimiteri, kao {to su blanko karakter, tabulator ili novi red. Delimiteri se ne
vra}aju.
Drugi konstruktor tako|e kreira tokenizer koji mo`e da razla`e string, ali se posebno zadaje
delimiter.
StringTokenizer(String s, String delim)

74
Delimiter se ne vra}a kao deo tokena.
Tre}i konstruktor kreira tokenizer koji mo`e da razla`e zadati string, zadaje se delimiter, ali se
zadaje jo{ jedan argument koji ukazuje na to da li se delimiter vra}a kao deo tokena koji se dobijaju
iz stringa.
StringTokenizer (Strings, String delim, boolean returnDelimiter)
Ako je vrednost argumenta returnDelimiter pode{ena na true, onda se i delimiter vra}a kao deo
tokena.
String s = "Recenica koja se tokenizuje.|Druga recenica.";
StringTokenizer stok1 = new StringTokenizer (s);
StringTokenizer stok2 = new StringTokenizer (s, "|");
StringTokenizer stok3 = new StringTokenizer (s, " |", true);
Promenljiva stok1 ukazuje na StringTokenizer koji iz stringa s vadi tokene. Kao delimiteri se
koriste blanko, novi red i sl.
Promenljiva stok2 predstavlja StringTokenizer koji tako|e vadi tokene iz stringa s, ali se ovog puta
kao delimiter koristi karakter |. Tom prilikom se ne vra}a sam karakter.
Promenljiva stok3 predstavlja StringTokenizer koji vadi tokene iz stringa s, kao delimiter koristi
karakter |, ali se vra}a i sam karakter koji je delimiter.
Va|enje tokena
Va|enje tokena iz stringa se vr{i preko metoda nextToken(). Ovaj metod ima dve verzije. Jedna
verzija nema argumente. Tada se kao delimiter koristi onaj karakter koji je upotrebljen kod
konstruktora. Druga varijanta prima argument tipa String i ona se koristi ako u toku rada `elite da
promenite karakter koji se koristi kao delimiter.
Tokom va|enja tokena se koristi i metod hasMoreTokens() koji vra}a true ako u stringu koji se
ispituje postoji jo{ tokena, ili false, ako ih vi{e nema.
System.out.println ("count1 = " + stok1.countTokens ());
while (stok1.hasMoreTokens ())
System.out.println ("token = " + stok1.nextToken ());

System.out.println ("\r\ncount2 = " + stok2.countTokens ());


while (stok2.hasMoreTokens ())
System.out.println ("token = " + stok2.nextToken ());

System.out.println ("\r\ncount3 = " + stok3.countTokens ());


while (stok3.hasMoreTokens ())
System.out.println ("token = " + stok3.nextToken ());
Metoda countTokens() broji tokene u stringu. Na nju se ne treba previ{e oslanjati. Za rad je najbolje
koristiti kombinaciju metoda hasMoreTokens() i nextToken(), kao u prethodnom primeru.
Primer:
public class Tokenizer {
public static void main(String[] args) {
String s = "Ovo je recenica koja treba da se tokenizuje. | Ovo je jos jedna
takva recenica. ";
StringTokenizer stok1 = new StringTokenizer (s);
StringTokenizer stok2 = new StringTokenizer (s, "|");
StringTokenizer stok3 = new StringTokenizer (s, " |", true);
System.out.println ("count1 = " + stok1.countTokens ());
while (stok1.hasMoreTokens ())
System.out.println ("token = " + stok1.nextToken ());

System.out.println ("\r\ncount2 = " + stok2.countTokens ());


while (stok2.hasMoreTokens ())

75
System.out.println ("token = " + stok2.nextToken ());

System.out.println ("\r\ncount3 = " + stok3.countTokens ());


while (stok3.hasMoreTokens ())
System.out.println ("token = " + stok3.nextToken ());

}
}

76

You might also like