1 uvod u programski jezik java - · pdf filedrdušant.malbaški 1 uvod u...
TRANSCRIPT
Dr Dušan T. Malbaški
1 UVOD U PROGRAMSKI JEZIK JAVA
2
3
• java se prvi put pojavila pod imenom Oakgodine 1992. Prva radna verzija, pod imenom Java, nastala je 1995.
• rešava (stari) problem portabilnosti(prenosivosti), tj. prenošenja programa sa jedne platforme (računara) na drugu
4
klasično rešenje problema portabilnosti
•prenosi se izvorni kod i ponovo prevodi na ciljnoj platformi
izvorni program PREVODILAC
mašinski program
prevođenje
izvorni program
prevodilac 1mašinski
program 1
prevodilac 2mašinski
program 2
klasični postupak prenošenja
5
javino rešenje problema portabilnosti
•prenosi se prevedeni (tj. "mašinski") kod i na ciljnoj platformi se ne prevodi
virtuelna mašina
izvorni program
java kompajler
JVMJVM JVMprevedeni program
"bajt kod"
6
• ulogu računara kao neposrednog izvršioca programa preuzima program koji se zove virtuelna mašina (Java Virtual Machine, JVM)
• u ulozi mašinskog programa pojavljuje se tzv. bajt-kod – visokooptimizovani prikaz programa koji virtuelna mašina može da "izvrši"
• virtuelna mašina povezuje se sa stvarnim hardverom prilikom instaliranja virtuelne mašine i ta veza je nevidljiva za program pisan na javi
• dakle, program "ne vidi" hardver, nego samo JVM.
7
Osnovne osobine jave
• rešava problem portabilnosti izvršnog koda
• čist objektni jezik (postoje samo bazni tipovi i klase)
• jako tipiziran jezik
• izuzetno bogat gotovim klasama
• pogodan za mrežno programiranje
• pogodan za konkurentno programiranje
• programi su relativno sporo izvršavaju, jer ih izvršava JVM
8
java i C++
• nema pokazivača; zamenjeni su tzv. referencama koje podsećaju na dereferencirani pokazivač u C-u
• izvedeni tipovi, niz i string, realizovani su kao klase
• nema preklapanja operatora
• nema pretprocesora
• slobodni potprogrami su drukčije realizovani
• nema višestrukog nasleđivanja
• memorija se oslobađa automatski, te nema destruktora niti operatora delete
9
• nema naredbe typedef
• nema modifikatora dužine i predznaka (unsigned, short, long itd.)
• nema naredbe goto; naredbe break i continue su pojačane
• niz izraza dozvoljen samo u naredbi for
• ima poseban logički tip sa nazivom boolean i vrednostima true i false
• ima poseban način modularizacije, putem tzv. paketa
10
Raspodela memorije
• pre svega, radi se o virtuelnoj memoriji, a ne o hardverskoj memoriji, te je sloboda kreiranja bila daleko veća!
• (virtuelna) memorija ima samo dve komponente: stek i hip
• svi objekti nalaze se na hipu i pristupa im se putem referenci!
• sami objekti su bezimeni, a imena imaju reference
11
stek
hip
objekat
referenca
12
Elementi jave• alfabet se sastoji od uobičajenih grupa simbola:
• velika i mala slova engleske abecede i znak _• cifre 0 do 9• specijalni znaci * > < + - += -= == << >>>
• format izvornog koda je slobodan• identifikatori sadrže samo slova i cifre, a prvi simbol je
slovo• naziv klase počinje velikim slovom• za promenljive i metode koristi se camel notacija• nazivi paketa sadrže samo mala slova• nazivi karakterističnih metoda imaju prefikse get set has
is
13
Komentari
• java ima tri vrste komentara
• kraći komentari počinju dvoznakom //
• duži komentari stavljaju se između dvoznakova /* i */
14
dokumentacioni komentari
• u velikoj meri olakšavaju izradu dokumentacije softvera (pre svega klase), bez koje se ne može!
• dokumentacija je deo izvornog koda i izrađuje se zajedno s njim!
• najčešće se dokumentuju klasa i njene metode
/**
dokumentacione direktive
*/
15
• dokumentacione direktive služe kao uputstva za izradu dokumentacije koja se formira pomoću posebnog programa sa nazivom javadoc
• opšti oblik dokumentacione direktive:
@direktiva propratni tekst
2 TIPOVI PODATAKA
1
2
• Tipovi podataka su realizovani su tako da postoje samo
– bazni tipovi i
– klase
• drugim rečima, izvedeni tipovi kao što su niz ili string nemaju posebnu realizaciju: realizovani su kao klase
3
Bazni tipovi
• logički tip (boolean)
• znakovni tip (char)
• celobrojni tipovi (int, long, short, byte)
• realni tipovi (double, float)
• tip void primenjuje se samo na metode
logički tip
• poseban tip, nekompatibilan sa ostalim baznim tipovima
• identifikator: boolean
• konstante (literali): false, true
• namena: upravljanje naredbama if i ciklusima, kao i formiranje logičkih izraza
znakovni tip
• kompatibilan sa ostalim baznim tipovima (izuzev boolean)
• identifikator: char
• UNICODE, dužine 16 bita!
• literali se prikazuju na tri načina:
– direktno
– pomoću eskejp sekvenci
– preko odgovarajućih UNICODE kodova
• direktno: 'a' 'R' '+' '0' 'x'; izuzeci su znaci \ ' "
• eskejp sekvence: \n \r \b \t \f \' \" \\
• UNICODE: \ooo \uxxxx, gde su ooo tri oktalne cifre, a xxxx četiri heksadecimalne cifre, sve sa vrednošću koda
familija celobrojnih tipova
• sastoji se od četiri tipa:
– byte: 8 bita, -128 do +127
– short: 16 bita, -32768 do +32767
– int: 32 bita, -2147483648 do +2147483647
– long: 64 bita, približno -91018 do + -91018
literali:
• dekadni oblik je isti kao u svim drugim programskim jezicima: 1 -125 0 +3241. Vodeća nula, npr. 0465, nije dozvoljena
• oktalni prikaz prepoznaje se upravo po vodećoj nuli: 054 ili 023 odn. 07762 (mogu imati i negativan predznak, ali to nema praktičnog značaja)
• heksadecimalni prikaz prepoznaje se po prefiksu 0x ili 0X: 0x4a91 0x67AB 0X5CD2. Takođe mogu imati negativan predznak što nije naročito važno
• kod navođenja, podrazumeva se tip int. Dakle, literal 467 je tipa int. Za long dodaje se sufiks L ili l. Prema tome literali 25634L, 0x89ABCL su tipa long.
familija realnih tipova
• sastoji se od dva tipa:– double: 64 bita, 4.910-324 do 1.810308
– float: 32 bita, 1.410-45 do 3.41038
• literali se zadaju– decimalno: 0.5 -45.0 0.0 +245.3265
– eksponencijalno: 1e10 2.3E-6 -7.8e-23
• podrazumevani tip literala je double
• float literali se zadaju sufiksom F ili f:
1.5F -3.2e-6f 1E-8F
• postoji i sufiks d odn. D za double literale, ali se podrazumeva
String literali
• predstavljaju tekstuelne konstante i koriste se za inicijalizaciju stringova
• predstavljaju se kao
"tekst"
• na primer, "Petar Petrovic" "ovo je string"
• mogu da sadrže i eskejp sekvence
"\nprelazak u novi red"
Literal null
• odgovara referencama svih vrsta
• označava da referenca ne pokazuje ni na jedan objekat
13
Promenljive
• pošto su reference na objekte (skalarne) promenljive sledi da prirodu promenljive imaju– polja svih vrsta (baznih tipova ili referenci)
u objektima
– lokalne promenljive svih vrsta u metodama
• Drugim rečima, sve čime manipulišemo u programu ima prirodu skalarnepromenljive!
• promenljiva se definiše iskazomtip ime1[=inicijalizator1],..., imen[=inicijalizatorn];gde je tip tip svih promenljivih iz definicije.
int a,b,c = 10;char cx = 'x', znak;
• Inicijalizatori su opcioni i ne moraju biti konstantni izrazi. Sve što se traži je da se vrednost inicijalizatora može izračunati. Na primer,
double h = 2*x+y-1;gde x i y moraju imati definisane vrednosti
• definicije promenljivih u metodama mogu se naći bilo gde u kodu (ali ispred prve primene)
15
Domet identifikatora promenljive
• domet (opseg, doseg) identifikatora promenljive predstavlja njegovu oblast važenja, tj. deo koda u kojem se taj identifikator može koristiti.
• Domet polja opredeljen je činjenicom da je polje deo klase, što znači da je u potpunosti dostupno za sve metode klase. Pristup polju iz metoda drugih klasa regulisan je nizom pravila i mehanizama o kojima će biti reči.
16
• domet lokalne promenljive omeđen je mestom definisanja s jedne i krajem odgovarajućeg bloka s druge strane.
• Pod blokom podrazumevamo sekvencu naredbi dopunjenu definicijama promenljivih (dakle, i objekata). Raspored naredbi i definicija je proizvoljan. Opšti oblik bloka je
{ definicije i naredbe}
17
domet x
{int a;. . . int b;{double x = a+b;. . .
}. . .
}
domet a
domet b
blok 1
blok 2
18
Primer: klasa Krugdatoteka: Krug.javapublic class Krug {
private double r;public Krug(double r) {
this.r = r;}public double r() {
return r;}public double obim() {
return 2*r*Math.PI;}public double povrsina() {
return r*r*Math.PI;}
}
poklapa se sa imenom klase
referenca objekta na samog sebe
parametar, metodai polje mogu se poklopiti po imenu
konstruktor
metoda
!
19
• klasa Krug nalazi se u istoimenoj datoteci Krug.java
• kompletan sadržaj klase nalazi se u naredbi class
• kontrola pristupa zadaje se za svaki član ponaosob
• svaki objekat ima polje this koje je referenca na samog sebe
• umesto standardnih biblioteka (npr. math.h) postoji standradna klasa (Math)
• u ulozi glavnog programa pojavljuje se svaka klasa koja ima metodu sa nazivom main
• program se poziva komandom
java klasa sa metodom main
20
glavni programdatoteka: TestKrug.java
public class TestKrug {
public static void main(String args[]) {
Krug kr = new Krug(1);
System.out.println("Poluprecnik: "+kr.poluprecnik());
System.out.println("Obim: "+kr.obim());
System.out.println("Povrsina: "+kr.povrsina());
}
}
kreiranje objekta kr
poziv metode
21
priprema programa
javac Krug.java //prevodjenje klase Krug
javac TestKrug.java //prevodjenje klase TestKrug
java TestKrug //aktiviranje programa
poziv prevodioca: rezultat je datoteka Krug.class (bajt kod)
poziv virtuelne mašine
3 OPERATORI I IZRAZI
1 2
aritmetički operatori
+ potvrda predznaka
- promena predznaka
+ sabiranje
- oduzimanje
* množenje
/ deljenje
% moduo
++ inkrement
-- dekrement
3
relacioni operatori
== != > >= < <=
• rezultat je tipa boolean!
4
logički operatori
& konjunkcija
| disjunkcija
! negacija
^ ekskluzivna disjunkcija
&& optimizovana konjunkcija (kao u C-u)
|| optimizovana disjunkcija (kao u C-u)
• operandi i rezultat su tipa boolean
5
bit-operatori
& konjunkcija
| disjunkcija
~ komplement
^ ekskluzivna disjunkcija
>> šift udesno (popunjava se bitom predznaka)
>>> šift udesno (popunjava se nulama)
<< šift ulevo
• operandi i rezultat su celobrojni
6
operatori dodele
osnovni operator dodele: =
ostali operatori dodele:
+= -= *= /= %=
&= |= ^= >>= >>>= <<=
• operatori &= |= ^= odnose se i na logičke i na bit-operatore.
7
uslovni izraz
logički_izraz ? izraz_1 : izraz_2
8
konverzija
• slično C-u i java dozvoljava mešovite izraze, pri čemu dolazi do konverzije
• konverzija može biti implicitna (automatska) i eksplicitna (type cast)
• implicitna konverzija izvodi se prilikom računanja binarnih izraza
• za operatore dodele važe posebna pravila
• eksplicitna konverzija vrši se operatorima
9
implicitna konverzija običnih binarnih operatora
• odnosi se na sve međusobno kompatibilne tipove (tj. na sve bazne tipove osim boolean) i na sve binarne operatore osim osnovnog operatora dodele =)
• prvo se vrži promocija: tipovi byte i short pretvaraju se u int, bez obzira na to da li su operandi različitog tipa
• potom se vrši konverzija po sekvenci
char int long float double
• ako su oba operanda char rezultat je int!
10
primeriint i,j; double d; float f; byte b1, b2; short s;
char c1, c2;
d * i //rezultat double
i + j //rezultat int
f / b1 //rezultat float
b1 + b2 //rezultat int!
s - b1 //rezultat int
c1 + c2 //rezultat int!
i += d //moze! rezultat je int
11
implicitna konverzija operatora dodele
• desna strana prilagođava se levoj
• nije dozvoljena konverzija iz složenijeg u manje složen tip (samo kod osnovnog operatora dodele =)!
int = short
short = int //ne
double = long
long = double //ne
short = byte
byte += int //moze!
double *= int //moze
12
eksplicitna konverzija
• vrši se pomoću operatora kasta
(tip)
• gde je tip ciljni tip.
(int) z
(short) i
• ako se konvertuje realni u celobrojni decimale se seku
• eksplicitna konverzija je naročito važna kod referenci na objekte!
4 NIZ I STRING
1
2
tip niza
• tip niza u javi realizovan je kao specijalna klasa, što znači da je svaki niz objekat
• to dalje znači da se nalazi na hipu i da mu se pristupa putem reference
• niz je specijalna klasa po tome što se
– kreira na poseban način
– ima operaciju indeksiranja
– poseduje inicijalizator
3
kreiranje niza
• referenca na niz deklariše se iskazom
tip imeNiza[] ili tip[] imeNiza
gde je tip tip svakog elementa.
• na primer, iskazom
int x[] ili int[] x
deklariše se referenca na int niz x (ali se niz ne kreira!)
• niz se stvara posebnom operacijom new koja važi za sve objekte.
4
• operacijom
imeNiza = new tip[duzina]
na hipu se
– stvara niz dužine duzina i
– na njega usmerava prethodno deklarisana referenca
imeNiza
5
• na primer, operacijom
x = new int[3]
stvara se int niz x dužine 3
x
• deklarisanje i kreiranje niza može se izvršiti jednom naredbom:
tip[] imeNiza = new tip[duzina];
int[] x = new int[3];
6
posebne osobine niza
• indeksiranje se izvodi kao i u drugim programskim jezicima izrazom
imeNiza[indeks]
gde je indeks celobrojni izraz sa vrednošću
0 <= indeks <= duzina-1
• na primer,
x[2] x[2*i-j+1] x[j] x[3]
• za razliku od C/C++ java proverava probijanje indeksa!
greška!
7
• niz kao objekat uvek ima polje length koje sadrži dužinu niza, tako da se ona ne mora pratiti posebnom promenljivom; vrednost polja length postavlja se pri kreiranju
• dakle,
imeNiza.length duzina
• za naš primer,
x.length 3
• uočimo da kod javinih nizova nema potrebe za rezervisanjem viška memorijskog prostora: niz zauzima onoliko memorije koliko ima aktuelnih elemenata!
8
• niz se može inicijalizovati:
tip[] imeNiza = {v1,...,vk};
gde su v1,...,vk inicijalne vrednosti elemenata na indeksima redom 0,1,..,k-1. Uočimo da se operacija new ne navodi!
• na primer,
double[] y = {1.1, 2.0, -5.6, 0.0};
1.1
y
2.0 -5.6 0.0
9
matrica• javina matrica je doslovno niz nizova,
preciznije niz referenci na nizove
• kreiranje:
tip[][] imeMatrice = new tip[v][k];
gde je tip tip elemenata matrice, v broj vrsta i k broj kolona.
• kao i svaki drugi niz, i matrica se može deklarisati i formirati posebnim naredbama. Tada je deklaracija oblika
tip[][] imeMatrice;
10
• izgled hipa posle kreiranja matrice
int[][] mtr = new int[2][3]
mtr
11
indeksiranje• matrica se indeksira odgovarajućom
operacijom [] koja se može primeniti jedan ili dva puta:
int[][] m = new int[5][10];
........
m[0][3] //pristup elementu u vrsti 0 i koloni 3
m[2] //pristup vrsti 2
• dužina se određuje se poljem length
m.length //broj vrsta (=5)
m[3].length //duzina vrste 3 (=10)
12
inicijalizacija• matrica se inicijalizuje kao i svaki drugi niz,
uzimajući u obzir da su elementi tog niza takođe nizovi
int[][] iNiz = {{1, 2}, {0, -1}, {4, 5}};
vrsta 0
vrsta 1vrsta 2
13
int[][] m1;
m1 = new int[2][];
double[][] m2 = new double[2][];
m2[0] = new double[3];
m2[1] = new double[4];
int iNiz = {{1, 2}, {0, -1}, {4, 5}};
m1
m2
iNiz
14
String
• po prirodi stvari, string je tekstuelni tip
• stringovi su važan tip podataka jer mogu da posluže kao univerzalni prenosioci podataka (npr. kao tip argumenata programa)
• kao i tip niza, tip stringa u javi je realizovan kao specijalna klasa
• naziv klase je String
15
posebne osobine stringova• Postoje string literali koji se mogu koristiti pri
inicijalizaciji ili pri prenosu argumenata u metodu– inicijalizacija:
String s = "Ovo je string"
mada može i
String s = new String("Ovo je string");
– prenos argumenta
ob.metoda("string literal")
• literali se ne mogu dodeljivati (z = "abc";)
ne treba new
16
konkatenacija• nad stringovima je definisan operator
konkatenacije (spajanja) + i operator +=String a = "xy", b = "zt", c, d = "w";
c = a + b; //c je sada "xyzt"
d += c; //d je "wxyzt"
• zapazimo: posle operacije d+=c stari sadržaj stringa dostaje na hipu, ali je nedostupan
w
wxyzt
d
17
• operator konkatenacije je polimorfan
• ako je jedan operand string, operacija + se interpretira kao konkatenacija, drugi se automatski prevodi u string
double x = 1.5; String tekst = "Vrednost x je ", r;
r = tekst + x; //r "Vrednost x je 1.5"
• drugi operand može biti i objekat, pod uslovom da u njegovoj klasi postoji metoda toString() (što je uvek slučaj)
18
prenos stringova u metodu
• string se u metodu prenosi po vrednosti
• to znači da ako se string-parametar u metodi promeni to neće imati uticaj na original (što nije slučaj sa drugim objektima kada su argumenti metode)
• razlog: da se omogući prenos string literala kao argumenata, jer oni moraju ostati nepromenjeni
19
void poruka(String txt) {
......
txt += "xxx";
......
}
String tekstPoruke = "Ovo je poruka";
poruka(tekstPoruke);
• po završetku metode, tekstPoruke je i dalje "Ovo je poruka" (a ne "Ovo je porukaxxx")
20
metode klase String• Klasa String raspolaže velikim brojem gotovih
metoda od kojih izdvajamo samo dve:
– int length() daje dužinu stringa
– char charAt(int poz) da je znak na poziciji poz u stringu, gde je
0 poz length()-1
5 NAREDBE
1
2
Klasifikacija
naredbe
prosta naredbaupravljačke
strukture
blok
selekcije
ciklusi
naredbe iskoka
3
prosta naredba
• definisana je kao
izraz;
• primeri:
x = 1;
y = 2*z -3;
a += 6;
t++;
++t;
;
!
4
blok
• blok je upravljačka struktura koja odgovara sekvenci, dopunjenoj definicijama
• definicije su potpuno ravnopravne sa naredbama i mogu se sa njima mešati
• pravilo: svaki identifikator pre prve upotrebe mora biti definisan
• opšti oblik bloka:
{ definicije i naredbe}
• blok se može labelirati
uključujući i druge blokove
5
{ x = 1;
y += x;
double z = x + y;
x *= z;
{
double t;
t = Math.sin(y);
y -= 2*t;
}
}
domet z
domet t
6
selekcije
• iste su kao i u C-u
• razlika je samo u načinu realizacije logičkog tipa kojim se upravlja naredbama if, jer java ima tip boolean
• naredba switch se uopšte ne razlikuje od iste naredbe u C-u
7
naredbe if
if(log_izraz) naredba
if(log_izraz) naredba1
else naredba2
log_izraz
naredba
log_izraz
naredba1naredba2
true
false
truefalse
8
naredba switch
• potpuno ista kao u C-u, uključujući i potrebu primene skoka break
switch(celobrojni_izraz) {
case c1:
niz_naredbi1case c2:
niz_naredbi2.............
default:
niz_naredbi0.............
case ck:
niz_naredbik}
9
celobrojniizraz
niz_naredbi1
niz_naredbi2
niz_naredbik
niz_naredbi0
c1ck
c2
default
!
deo defaultnije obavezan
u novijim verzijama
može i String!
uloga break
switch(i+j) {
case 2:
x = 1; y++;
case 0: case -4:
z*=t; t--;
case 6:
p = q = r = s = 0;
case 1:
x++;
}
switch(i+j) {
case 2:
x = 1; y++; break;
case 0: case -4:
z*=t; t--; break;
case 6:
p = q = r = s = 0; break;
case 1:
x++;
}uočiti višestruke case labele
i+j=-4 i+j=-4
10
11
ciklusi
• skoro isti kao i u C-u
• razlika je ponovo u načinu realizacije logičkog tipa kojim se upravlja naredbama ciklusa, jer java ima tip boolean
12
ciklus while
while(log_izraz) naredba
log_izraz naredbafalse
true
13
ciklus forfor(inicijalizacija;uslov;modifikacija) naredba
• inicijalizacija: izraz1,...,izrazn
• uslov: logički izraz
• modifikacija: izraz
false
true
inicijalizacija
naredba
uslov modifikacija
14
for(i=0,s=0;i<n;i++) s+=a[i];
• u posebnom slučaju, brojačka promenljiva može se definisati unutar ciklusa i tada za domet ima samo taj ciklus
for(int j=0;j<m;j++) z-=Math.cos(j);
j važi samo unutar ciklusa
15
ciklus do-while
do naredba while(log_izraz);
log_izraz
naredba
false
true
16
naredbe iskoka
• java nema naredbu goto!
• pošto ostale naredbe nemaju proizvoljno odredište, bolje ih je nazvati "naredbe iskoka"
• naredbe iskoka su:
– break
– continue i
– return
17
naredba break
• kao i u C-u, koristi se u dva slučaja:
– u okviru naredbe switch na uobičajeni način
– u okviru ciklusa, za momentalni iskok iz ciklusa (tj. za završetak ciklusa)
18
labelirana naredba break
• naredba break je pojačana varijantom koja koristi labele (razlog: nepostojanje goto)
• labelirati se mogu
– svi ciklusi
– blokovi
• opšti oblik labelirane naredbe break
break labela;
gde labela predstavlja labelu ciklusa ili bloka čije se izvršavanje prekida
19
nivo1: while(i<n) {
.........
nivo2: while(j>0) {
.........
nivo3: for(k=0;k<m;k++) {
..... break nivo1;
..... break nivo2;
..... break nivo3; //ili samo break;
}
}
}
20
prvi: {
.........
drugi: {
.........
treci: {
..... break prvi;
..... break drugi;
..... break treci;
}
}
}
21
labelirana naredba continue
• samo kod ciklusa
• opšti oblik labelirane naredbe continue
continue labela;
gde labela predstavlja labelu ciklusa na čiju se sledeću iteraciju preskače
22
out: while(i != n) {
.........
while(j<=k) {
.... continue out;
..... continue
}
........
}
23
naredba return
• koristi se u metodama sa identičnim formama kao i kod C-ovih potprograma
6 ELEMENTARNO RUKOVANJE KLASOM
1
2
Naredba class
• naredbom class tadaje se kompletan sadržaj klasekoji čine polja, metode i tzv. unutrašnje klase
class ImeKlase {
//polja
//metode
//unutrasnje klase
}
gde se oznaka odnosi na skup modifikatora kojima se klasi pridružuju posebne osobine
3
modifikatori
• modifikatori su službene reči kojima se podešava ponašanje čitave klase, polja, metode ili njenih parametara
• primeri: public, private, static, abstract, final
• ideja je ista kao kod C-a, ali je namena drukčija (ne postoje modifikatori dužine ili predznaka)
4
polja
• polja mogu biti baznog tipa ili pak reference na objekte
• imaju osobine promenljivih
• definišu se, kao i sve promenljive, iskazom
tip imePolja [inicijalizator]
gde je tip oznaka baznog tipa ili naziv klase kojoj polje pripada, a oznaka za skup modifikatora
5
primeri
int a;
double b = 3.5;
X t;
X pX = new X();
t i pX su reference na objekat klase X
inicijalizacija; češće se vrši konstruktorom
6
• sva polja moraju biti inicijalizovana
• polja se mogu inicijalizovati na četiri načina:
– direktno, u okviru definicije
– implicitno (automatski)
– u inicijalizacionom bloku
– konstruktorom (najčešći slučaj, o konstruktorimakasnije)
Inicijalizacija
7
• direktna inicijalizacija ista je kao za promenljive:
class K {
int a = 1;
.................
direktna inicijalizacija
8
• ako se polje ne inicijalizuje, početna vrednost biće zadata automatski, prema sledećoj šemi
tip vrednost
boolean false
char '\u0000'
byte 0
short 0
int 0
long 0
float 0.0
double 0.0
referenca null
9
• inicijalizacioni blok je deo klase i zadaje se kao i svaki drugi blok
class M {
int n;
double x;
{
n = 10;
x = 2*Math.sin(n);
}
..........................
inicijalizacioni blok
10
metode
• opšti oblik metode je
zaglavlje
{
blok
}
11
• zaglavlje je oblika
tip nazivMetode(parametri)
gde je tip tip rezultata (ako ga nema tip je void), a parametri se zadaju konstruktom
T1p1, ... Tnpn
kao i u C-u.
12
• izvršavanje metode završava se, kao i u C-u, na tri načina:
– return izraz, gde je izraz vrednost rezultata
– return, ako je metoda void
– poslednjom naredbom, ako je metoda void
13
primer
public class Rectangle {
private double a, b;
public void setRectangle(double a, double b) {
this.a = a; this.b = b;
}
public double geta() { return a;}
public double getb() {return b;}
public double perimeter() {return 2*(a+b);}
public double surface() {return a*b;}
} kontrola pristupa za svaki član ponaosob!
zaglavlje
blok
14
objekat kao rezultat
• ako je vrednost metode objekat, kao rezultat vraća se referenca (koja je skalar!)
• omogućeno da vrednost metode bude niz!
double[] zbirNizova(double[] x, double[] y) {
double zbir = new double[x.length];
for(int i=0;i<zbir.length;i++) zbir[i] = x[i] + y[i];
return zbir;
}
• metoda zbirNizova vraća referencu na niz!
zbir je niz!
15
aktiviranje metode
• metoda se aktivira, kao i u drugim programskim jezicima, preko objekta iskazom
objekat.metoda(argumenti);
• primeri:
Rectangle rec; double p;
rec = new Rectangle();
rec.setRectangle(5, 4);
p = 2 * rec.surface() - 3;
kreiranje objekta rec
aktiviranje metode setRectangle
16
prenos argumenata
• način prenosa argumenata je standardan:
– bazni tipovi i stringovi prenose se po vrednosti, (kao i same reference na objekte!)
– objekti (uključujući i nizove) prenose se po adresi(tako da metoda radi sa originalom!)
17
prenos po vrednosti
• odnosi se na parametre baznih tipova, na stringove i na reference
• prilikom aktiviranja metode na steku se pravi kopija argumenta
• ako se argument unutar metode promeni, to nema uticaja na originalnu vrednost, jer se menja vrednost kopije na steku
18
prenos objekata
• objekti se prenose po adresi, tako da metoda radi sa originalnim objektom i svaka promena njegovog stanja unutar metode predstavlja promenu stanja originala!
• važna napomena: prenos po adresi u javi se svodi na prenos reference po vrednosti, tj. na steku se pravi kopija reference
• ako se unutar metode promeni referenca (a ne objekat) to nema uticaja na njenu originalnu vrednost koja ostaje nepromenjena
19
public void m(K par) {
par.set(j);ako se objekat par promeni, menja se original
}
public void m(K par) {
par = new K();ako se referenca par promeni, originalna ref. par ostaje ista
}
public void m(final K par) {
par = new K();ako se referenca par promeni, biće javljena greška!
}
final se odnosi se na referencu, a ne na objekat!
20
m(ob)
ob
21
Konstruktori
• konstruktori su metode koje se pozivaju prilikom kreiranja objekta; sam objekat kreira se operacijom new
• može ih biti više, a svi nose ime klase
• nemaju nikakav tip jer se ne pozivaju direktno (poziva ih new)
• ako se ne napiše nijedan konstruktor, prevodilac će napraviti ugrađeni konstruktor (konstruktor bez parametara, sa praznim telom).
22
primer
• dva konstruktora za klasu Rectangle:public class Rectangle {private double a, b;public Rectangle(double a, double b) {
this.a = a; this.b = b;}public Rectangle(Rectangle rec) {
a = rec.a; b = rec.b;}
....................}
23
polje this
• kao i u drugim programskim jezicima, u svakom objektu postoji polje this, što predstavlja referencu na samog sebe
• kada se u metodi napiše ime nekog polja x, podrazumeva se this.x
• na primer, drugi konstruktor ima stvarni oblik
public Rectangle(Rectangle rec) {
this.a = rec.a; this.b = rec.b;
}
24
smeštanje klase
• klasa se smešta u datoteku koja se po imenu poklapa sa klasom, a ima ekstenziju .java
• pored te klase, u istoj datoteci može se naći još poneka klasa, ali ona ne može biti public
• dakle, klasa Rectangle mora se smestiti u datoteku Rectangle.java
• kada se klasa prevede kompajlerom javac biće stvoren bajt-kod sa ekstenzijom .class (u našem primeru Rectangle.class)
25
Instanciranje klase
• klasa se instancira u dva razdela koji se mogu realizovati jednom ili dvema naredbama:
– definisanje reference
– kreiranje objekta i usmeravanje reference na njega; objekat je uvek na hipu!
• definisanje reference:
NazivKlase nazivReference;
• primer:
Rectangle rec;
26
• objekat se kreira operacijom new uz poziv konstruktora i rezultat se dodeljuje referenci
nazivReference = new konstruktor(argumenti);
• primer:
rec = new Rectangle(3, 4);
• instanciranje se može izvesti i jednom naredbom
Rectangle rec = new Rectangle(3, 4);
27
rec
objekatreferenca
sam objekat je bezimen!
Rectangle rec = new Rectangle(3, 4);
28
Uništavanje objekata
• java nema metode tipa destruktora, niti se objekti mogu uništiti eksplicitnom operacijom
• umesto tog, postoji background proces, nazvan Garbage Collector (gc) koji automatski uništava neaktuelne objekte (tj. objekte koji nisu referencirani)
• npr. ako se u programu izvede operacija ob = null, u nekom trenutku gc će osloboditi memoriju koju je zauzimao objekat
29
• gc se uključuje automatski i nije dobra praksa pokušavati sa eksplicitnim pozivom (koji je moguć)
• gc čisti samo hip i ne oslobađa druge zauzete resurse
• često se uključuje (i donekle usporava rad VM)
• svaka klasa poseduje metodu void finalize()koju podešavamo tako da izvrši završne radnje pri uništavanju objekta (npr. zatvori neki tok i sl.). Pri uništavanju gc obavezno poziva ovu metodu
30
Kontrola pristupa članovima
• java ima četiri nivoa kontrole pristupačlanovima klase, od kojih navodimo, za sada, dva:
– private - samo metode matične klase
– public - metode svih klasa
• za svaki član modifikator se zadaje posebno
31
pristup članovima klase
• poljima se pristupa i metode se pobuđuju pomoću operatora selekcije .
• primeri:
Rectangle r = new Rectangle(3, 5); double x, y, z;
x = 2*r.surface() - 4.5;
r.setRectangle(5, 8);
z = r.a + r.b; //ne moze! a i b su private!
y = r.getb();
32
Dodela• operator dodele = izvršava se nad
referencama, a ne objektima
• posle dodele, obe reference pokazuju na isti objekat!
ob2 = ob1ob2ob1
33
Kloniranje• postupak pravljenja kopije objekta nosi naziv
kloniranje• može se izvesti na više načina, a najjednostavniji i
najčešći jeste korišćenje konstruktoraRectangle r1 = new Rectangle(3,5); r2;r2 = new Rectangle(r1);
r1r2
34
Upoređivanje• operatorima == i != upoređuju se reference, a
ne objekti!
r1
r2
r3 r4
r1 != r2 r3 == r4
35
Upoređivanje stanja• provera da li su dva objekta u istom stanju
(imaju iste vrednosti polja) vrši se tako što se pravi (obična!) metoda sa zaglavljem
public boolean equals(Object ime_parametra)
• primenjena na objekat ob, u obliku
ob.equals(ob1)
metoda treba da vrati true ako su ob i ob1klonovi, a false u suprotnom.
• ako je ob==ob1 (jedan objekat), programer odlučuje u zavisnosti od konkretnog slučaja
36
r1
r2
r5 r6equals vraća true
programer odlučuje!
r3r4
equals vraća false
37
primer• za klasu Rectangle:
boolean equals(Object rec) {
return (a==((Rectangle)rec).a) &
(b==((Rectangle)rec).b);
}
• metoda vraća true i ako je u pitanju isti objekat (odluka programera!)
• zapaziti eksplicitnu konverziju iz Object u Rectangle
eksplicitna konverzija
38
Rectangle r1, r2, r3, r4;
r1 = new Rectangle(1,2);
r2 = new Rectangle(1,2);
r3 = new Rectangle(3,4);
r4 = new Rectangle(r1); //kloniranje!
r5 = r1; //r5 i r1 referenciraju isti objekat!
r1.equals(r2) true
r1.equals(r3) false
r1.equals(r4) true
r1.equals(r5) true
39
primer• za klasu Rectangle:
boolean equals(Object rec) {
return (this!=rec) &
(a==((Rectangle)rec).a) &
(b==((Rectangle)rec).b);
}
• metoda vraća false ako je u pitanju isti objekat (odluka programera!)
• zapaziti eksplicitnu konverziju iz Object u Rectangle
40
Rectangle r1, r2, r3, r4;
r1 = new Rectangle(1,2);
r2 = new Rectangle(1,2);
r3 = new Rectangle(3,4);
r4 = new Rectangle(r1); //kloniranje!
r5 = r1; //r5 i r1 referenciraju isti objekat!
r1.equals(r2) true
r1.equals(r3) false
r1.equals(r4) true
r1.equals(r5) false
7 STATIČKI ČLANOVI KLASE
1
2
• to su članovi klase za čiju upotrebu nije neophodan objekat
• definišu se dodavanjem modifikatora static
• mogu biti polja, metode ili unutrašnje klase
• statička polja igraju ulogu globalnih promenljivih, a statičke metode igraju ulogu potprograma
• o statičkim unutrašnjim klasama - kasnije
3
statičke metode
• pošto za aktiviranje statičkih metoda nije potreban objekat, one predstavljaju način za realizaciju (običnih) potprograma!
• statička metoda definiše se dodavanjem modifikatora static u zaglavlje
• u načelu, aktivira se iskazom
naziv-klase.metoda(argumenti)
• može se aktivirati i uobičajeno, preko objekta
naziv-objekta.metoda(argumenti)
4
• na primer, standardna klasa Math sadrži matematičke funkcije realizovane kao statičke metode
• funkcija sin aktivira se, na primer, sa
Math.sin(2*x+5)
gde je Math naziv pomenute klase.
• zapaziti da su metode main, println i printstatičke metode!
5
• Neka je Point klasa čiji objekti predstavljaju tačke u Dekartovom koordinatnom sistemu
public class Point {private double x, y; //koordinatepublic Point(double x, double y) {this.x = x; this.y = y;
}public double getX() {return x;}public double getY() {return y;}public void set(double x, double y) {this.x = x; this.y = y;
}public static double distance(Point p1, Point p2) {
return Math.sqrt(Math.pow(p1.x()-p2.x(),2)+Math.pow(p1.y()-p2.y(),2));
}}
statička metoda
statička metodastatička metoda
6
primer:
Point a, b; double r1, r2, r3;
a = new Point(1,2);
b = new Point(3,4);
r1 = Point.distance(a,b);
Point c = new Point(10,20);
r2 = c.distance(a,b); //vazi r1==r2!
Point q = null;
r3 = q.distance(a,b); //vazi r1==r2==r3!
poziv preko klase (standardni postupak)
može i ovako
moze čak i ovako!
7
statička polja
• statička polja predstavljaju način za realizaciju globalnih promenljivih i imenovanih konstanata
• mogu biti baznog ili klasnog tipa (objekti)
• definišu se dodavanjem modifikatora static u definiciju i najčešće su public
• u načelu, pristupa im se iskazom
naziv-klase.polje
• može se pristupiti i uobičajeno, preko objekta (vrlo retko)
naziv-objekta.polje
8
• na primer, standardna klasa Math sadrži polje PI realizovano kao statičko polje
• pristupa mu se sa
Math.PI
• zapaziti da je out statičko polje klasnog tipa u klasi System!
9
inicijalizacija statičkih polja
• statička polja se inicijalizuju, kao i nestatička, na četiri načina:
– direktno, u okviru definicije
– implicitno (automatski)
– putem konstruktora
– tzv. statičkim blokom
• prva tri načina: identično, kao i kod nestatičkih polja
10
• statički inicijalizacioni blok je deo klase i zadaje se kao i svaki drugi blok, sa dodatkom reči static
class K {
public static int w;
static double x;
static {
w = 10;
x = 2*Math.sqrt(w);
}
..........................
statički inicijalizacioni blok
!
11
• statički inicijalizacioni blok biće izvršen:
– pri prvom obraćanju statičkom članu (klasa ne mora biti instancirana) ili
– pri prvom instanciranju klase
• pošto u istoj klasi mogu da postoje i nestatička i statička polja, redosled inicijalizacije je
– statička polja, pa onda
– nestatička polja
12
odnos nestatičkih i statičkih članova
• pravilo je jednostavno:
– statičke metode mogu referencirati samo statičke članove klase (ne mogu referencirati nestatičke članove)
– nestatičke metode mogu referencirati svečlanove, statičke i nestatičke
– konstruktori mogu referencirati sve članove klase
13
primerpublic class Klasa {private static double a; //staticko polje;private double x; //nestaticko poljepublic static void setA(double aa) {a = aa;}public double getA() {return a;}public static void setX(double x) {this.x = x;}public double getX() {return x;}public static double stm() {
double z = getX();return z;}
}
može: nestatička metoda obraća se statičkom polju a
ne može: statička metoda obraća se nestatičkoj metodi getX
ne može: statička metoda obraća se nestatičkom polju x
14
realizacija imenovanih konstanata
• imenovane konstante realizuju se kao zaključana statička polja
• zaključavaju se modifikatorom final
public class K {
public static final boolean TACNO = true;.......................
}
• imenovana konstanta TACNO koristi se putem iskaza K.TACNO i ima vrednost true
• u klasi Math postoji tako realizovana konstanta Math.PI, koja ima vrednost 3.1415926...
8 DOKUMENTOVANJE KLASE
1
2
• zbog velikog broja metoda, klasa koja nije (dobro) dokumentovana neupotrebljiva je!
• dokumentuje se čitava klasa, kao i njeni članovi (polja i metode)
• zbog lakše izrade, dokumentacija je deo izvornog koda klase
• uključuje se u izvorni kod pomoću posebnog oblika komentara
/**
dokumentacione direktive
*/
3
dokumentacione direktive
• ima ih više, sa opštim oblikom
@direktiva propratni_tekst
• dokumentacija se formira iz izvornog koda posebnim programom javadoc
• javadoc formira dokumentaciju u obliku html dokumenta, koji se pregleda običnim (bilo kojim) pretraživačem
4
@deprecatedzastarelo@deprecated
@version 2.0podaci o verziji@version verzija
@author Jovan Jovicpodaci o autoru@author autor
@see Queue#get()pozivanje na drugu metodu
@see klasa#metoda
@see Queuepozivanje na drugu klasu@see klasa
@throws StackExceptionizuzetak@throws klasa opis
@return Napon u mVopis rezultata metode@return opis
@param date Datumopis parametra metode@param ime opis
PrimerOpis direktiveDirektiva
5
/*** Sat sa inkrementom od jedne sekunde* @author D. Malbaski* @version 2.0*/public class Clock {
int hour,min,sec; //Podrazumevane vrednosti hour==min==sec==0
/*** Postavlja vreme na zadatu vrednost.* Sekunde se automatski postavljaju na 0.* @param h Sat* @param m Minut*/public void setTime(int h,int m) {
hour= h;min= m;sec= 0;
}
6
/*** Ocitava sat* @return Sat*/public int getHour() {
return hour;}
/*** Ocitava minut* @return Minut*/public int getMin() {
return min;}
/*** Ocitava sekund* @return Sekunda*/public int getSec() {
return sec;}
7
/*** Pomera casovnik za 1 sekund i podesava sate i minute.*/public void tick() {
if((sec=(sec+1)%60)==0)if((min=(min+1)%60)==0)
hour= (hour+1)%24;}
}
• Programsku dokumentaciju formiraćemo pozivom programa javadoc sa sledećim oblikom:
javadoc -d doc -author -version Clock.java
što znači da će se dokumentacijske datoteke naći u direktorijumu doc koji je poddirektorijum onog iz kojeg je aktiviran program javadoc i da se zahteva da u dokumentaciju budu uvršteni i podaci o autoru, kao i oznaka verzije.
• Pretraživačem se otvara dokument Index.html
8
9
9 NASLEĐIVANJE I POLIMORFIZAM
1
2
• sintaksa:
class B extends A {
//dodati clanovi
// redefinisane metode
}
A
B
3
opšte osobine nasleđivanja
• za realizaciju se ne koristi izvorni kod
• proširivanje dodavanjem novih članova (naravno) postoji
• redefinisana metoda mora imati isto zaglavlje; ako nema iste parametre, u izvedenoj klasi postojaće obe verzije!
• nasleđivanje je tranzitivno
• višestrukog nasleđivanja nema
4
posebne osobine nasleđivanja
• i u javi postoji kontrola pristupa nivoa protected
• i java ima ugrađeni i podrazumevani konstruktor
• modifikatorom final u definiciji klase zabranjuje se njeno nasleđivanje
• modifikatorom final u definiciji metode zabranjuje se njeno redefinisanje; kompajler će pokušati da tu metodu realizuje in-line
5
rezime primene final
1. uz promenljivu služi za zaključavanje
2. uz parametar metode sprečava promenu vrednosti
3. uz klasu sprečava nasleđivanje
4. uz metodu sprečava redefinisanje
6
redefinisanjepublic class A {
…………….public void met(int par) {…}
}
public class B extends A {…………….public double met(int par) {…}public void met(int par) {…}
}
public class C extends A {………………
public void met(double par) {…}}
ne može!
redefinisana metoda
dodata metoda. U klasi C postoje obe verzije
7
ključna reč super
• ima dve namene:
– kada se upotrebi kao referenca, označava verziju metode iz neposrednog pretka
– kada se upotrebi kao metoda predstavlja poziv konstruktora neposrednog pretka
• i ključna reč this može se u nekoj metodi upotrebiti za poziv konstruktora matične klase
8
public class A {
……………..
public void set(int i) {…}
}
public class B extends A {
……………..
public void set(int i) {…}
public int setFromA(int k) {… super.set(k);…}
}
redefinisana
poziv verzije setiz klase A
9
public class A {
public A(int i) {…}
………………
}
public class B extends A {
public B(int j) {…super(j);…}
………………..
}
poziv konstruktora
klase A
10
konstruisanje pri nasleđivanju
• slična situacija kao u C++: konstruktor date klase mora pozvati konstruktor bazne klase, eksplicitno (pomoću super) ili implicitno (kada se poziva podrazumevani konstruktor bazne klase)
• mala razlika: pri eksplicitnom pozivu konstruktor počinje pozivom konstruktora bazne klase (ispred ne sme biti ništa)
1111
• svaki konstruktor sadrži eksplicitan ili implicitan poziv konstruktora natklase
• implicitno se poziva podrazumevani konstruktor; ako ga nema javlja se greška
A0
A1
An
X
A0 A1 An X....
iz A0 iz A1iz An iz X
objekat klase Xpozivanje
izvršavanje
12
public class An {
public An(int i) {…}
………………
}
public class X extends An {
public X(int j) {
super(j);
…......
}
………………..
}
poziv konstruktora
klase An
ovde ne sme biti ničega
13
Polimorfizam
• u javi postoje sve vrste polimorfizma: parametarski (generičke klase), inkluzioni, preklapanje i koercitivni
14
inkluzioni polimorfizam
• Inkluzioni polimorfizam potiče iz opšte logike, međusobno je uslovljen nasleđivanjem i mora da važi u svakom objektnom jeziku!
• inkluzioni polimorfizam može se ukratko formulisati sledećim tvrđenjem:
objekat-potomak se u svakom trenutku možetretirati kao predak
15
• inkluzioni polimorfizam ispoljava se i u javi u tri standardna slučaja:
– referenca na potomak može se dodeliti referenci na predak
– referenca na potomak može biti argument metode čiji je parametar definisan kao predak
– metoda koja, kao rezultat vraća predak, može ga unutar tela formirati kao referencu na potomak
16
Predak pr; Potomak po = new Potomak();
pr = po;
pr.m();
dodela
Predak
Potomak
m
m
redefinisana metoda
poziva se verzija određena objektom, tj. verzija iz potomka (kao kod virtuelnih metoda u C++)
17
tip metoda(Predak pr) {...}
• može se pozvati sa
metoda(po)
gde je po objekat iz klase Potomak
zamena parametra argumentom
18
Predak metoda(parametri) {
Potomak pt = new Potomak();
.........
return pt;
}
potomak kao rezultat
19
• Dinamičko ("kasno") povezivanje (dynamic linkage, dynamic dispatch, late binding) postoji i u javi, jer je to osobina nevezan za programski jezik
• u iskazu
ob.metoda(parametri)
verzija metode određena je objektom koji trenutno referiše referenca ob i ne može se precizirati u toku prevođenja; postaje poznata tek u trenutku izvršavanja
Dinamičko povezivanje
20
• java nema preklapanja operatora
• preklapanje metoda postoji i vrlo intenzivno se koristi:
– u različitim klasama mogu postojati istoimene metode
– u istoj klasi takođe mogu postojati istoimene metode, a najmanja detektabilna razlika je tip jednog parametra; tip rezultata ne učestrvuje u detekciji različitih verzija
• na primer, metoda println realizovana je u više verzija, sa različitim tipom parametara
preklapanje
21
• realizije se putem eksplicitne konverzije:
(ciljni_tip)promenljiva
• veoma često se koristi u kombinaciji sa nasleđivanjem odn. inkluzionim polimorfizmom
koercitivni (prinudni) polimorfizam
22
• neka su pr i po reference redom na predak i potomak
• inkluzioni polimorfizam dozvoljava dodelu oblika pr = po
• dodela po = pr nije dozvoljena, iako je pod određenim uslovima izvodljiva
• ova dodela moguća je pod uslovom da referenca pr ne pokazuje na predak, nego na potomak (ili neki od "potomkovih potomaka")
23
• da bi se izvela dodela (kada je moguća), mora se primeniti koercija oblika
po = (Potomak)pr
PredakPotomak
pr pr
po = pr nije moguće po = pr jeste
moguće
24
• vrši se posebnim binarnim operatorom instanceof; levi operand je objekat (referenca), a desni klasa
• opšti oblik:
ob instanceof K
• ima logičku vrednost
– true ako ob referiše objekat klase K ili klase koja je potomak K
– false u suprotnom
provera legalnosti koercije
25
• u našem primeru, bezbedna dodela bila bi
if(pr instanceof Potomak) po = (Potomak)pr;
• napomena: ako pr referiše klasu koja nije u vezi nasleđivanja sa Potomak, operator instanceof opet vraća false
PredakPotomak
pr pr
pr instanceof Potomak je false pr instanceof Potomak
je true
26
Jedinstvena hijerarhija klasa
• jedna od najvažnijih osobina jave:
– koren te hijerarhije jeste klasa sa nazivom Object
– zbog tranzitivnosti, klasa Object je predak svake javine klase!
– ako neku klasu K ne izvedemo eksplicitno iz druge klase, ona će automatski biti izvedena iz klase Object
sve klase čine jedinstvenu hijerarhiju baziranu na nasleđivanju
27
public class M {
………..
}
M
klasa M se implicitno izvodi iz klase Object, tako da će biti prevedena kao
public class M extends Object {……………..}
28
Klasa Object
• metode definisane u klasi Object postoje u svim javinim klasama
• neke karakteristične metode:
– Object clone() kloniranje objekta
– boolean equals(Object ob) upoređivanje dva objekta; ako se ne redefiniše vraća false
– void finalize() koristi je GC pri uništavanju objekta
– String toString() pretvaranje objekta u string; ako se ne redefiniše vraća prazan string
29
equals
• metoda equals može se redefinisati ili dodati
boolean equals(Object rec) {
return (a==((Rectangle)rec).a) &
(b==((Rectangle)rec).b);
}
boolean equals(Rectangle rec) {
return (a==rec.a) & (b==rec.b);
}
redefinisana
dodata
30
• ako je metoda equals dodata, u klasi će postojati dve verzije: jedna nasleđena iz klase Object što vraća false i druga, dodata
• to stvara mogućnost da se objekat upoređuje sa objektom bilo koje klase; ako se klase ne slažu, vraćena vrednost biće false, jer se aktivira nasleđena verzija
• ako je rec objekat klase Rectangle, a crcobjekat klase Circle (krug), tada je poziv
rec.equals(crc)
legalan i vraća false
31
Kontrola pristupa
• opšte pravilo: prilikom redefinisanja, kontrola pristupa ne može se pooštriti, a može se ublažiti
• na primer, metoda koja je bila public ne može se redefinisati tako da postane private ili protected
• razlog: dinamičko povezivanje
32
public class A {……………….
public void met() {…}}public class B extends A {……………….
private void met() {…} //redefinisana}
A obA; B obB = new B();
obA = obB; //legalna dodela potomka pretku
obA.met(); Greška! Aktivirala bi se private verzija iz klase B.Greška bi se prijavila tek prilikom izvršenja!
zabranjeno
10 MODULARIZACIJA I INKAPSULACIJA
1
2
Modularizacija
• Modularnost klase (proširivost+višekratna upotreba) ostvaruje se kombinacijom dva postupka:
– smeštanjem klase u posebnu datoteku
– objedinjavanjem takvih datoteka u module koji nose naziv paketi (odgovaraju bibliotekama)
klasa
klasa
klasa
datoteka
klasadatotek
a
paket
public
public
default
default
3
osobine paketa
• sve klase koje pripadaju istom paketu moraju se nalaziti u istom direktorijumu
• paket ima naziv koji se mora poklapati sa nazivom tog direktorijuma
• (konvencija) naziv direktorijuma (dakle, i naziv paketa) piše se isključivo malim slovima
• paket može imati potpakete (koji se, dakle, moraju naći u odgovarajućim subdirektorijumima)
4
UML
• u UML, paket se prikazuje simbolom
• pripadnost klase paketu prikazuje se ovako:
paket::Klasa
5
formiranje paketa
• struktura paketa i potpaketa prati strukturu direktorijuma
paket1
korendir
paket2
paket21
paket1::A
paket1::B
paket2::C
paket21::D
6
smeštanje klase u paket
• da bi se neka klasa X smestila u paket pakmoraju se uraditi dve stvari:– izvorni kod klase X mora početi naredbom
package naziv_paketa;
package pak;
public class X {
…………..
}
– datoteka X.class sa bajt-kodom klase X mora se fizički smestiti u direktorijum pak
7
prevođenje izvornog koda
• kompajliranje izvornog koda klase vrši se iz tzv. "korenog"direktorijuma koji je nadređen direktorijumu sa paketom (u našem primeru, to je direktorijum korendir)
• ako se radi o potpaketu, naredba packagemora da prati putanju od korenog direktorijuma do direktorijuma sa potpaketom:
package paket2.paket21
!
8
javac paket1\A.java
javac paket1\B.java
javac paket2\C.java
javac paket2\paket21\D.java
package paket1;public class A {……….}
A.java
package paket1;public class B {……….}
B.java
package paket2;public class C {……….}
C.java
package paket2.paket21;public class D {……….}
D.java
prevodi se iz direktorijuma
korendir
9
ISHOD:
A.class nalazi se u direktorijumu paket1B.class nalazi se u direktorijumu paket1C.class nalazi se u direktorijumu paket2D.class nalazi se u direktorijumu paket21
10
Korišćenje klase
• kada se klasa nalazi u paketu, njen identifikator nije više samo ime, već ime kvalifikovano nazivom paketa
• dakle, identifikatori navedenih klasa jesu
paket1.A
paket1.B
paket2.C
paket2.paket21.D
11
primeri
• ako se navedene klase koriste u nekoj klasi koja je u korenom direktorijumu korendir, tada su odgovarajući iskazi npr.
paket1.A objA = new paket1.A(…);
paket1.B = new paket1.B(...);
paket2.paket21.D = new paket2.paket21.D(…);
važi i za poziv konstruktora, kao i za poziv
statičkih članova
12
Skraćenica import
• da bi se izbeglo korišćenje punog identifikatora klase, uvedena je skraćenica
import paket.klasa; ili import paket.*;
čijom primenom se identifikator klase ponovo svodi samo na ime
• skraćenice import (ako ih ima, a skoro uvek ih ima) navode se u klijentu neposredno iza naredbe package (ako je ima)
• oblik import.* omogućuje skraćeno obraćanje svim klasama paketa
13
primeri
import paket1.A;………………A obA = new A(…);paket1.B obB = new paket1.B(…);
import paket1.*;………………….A obA = new A(…);B obB = new B(…);
14
Varijabla classpath
• do sada opisana struktura je nefleksibilna, praktično neupotrebljiva, jer se klijent mora nalaziti u korenom direktorijumu
• šta ako nije (a to je gotovo uvek slučaj)?
15
• problem se rešava varijablom okruženja (environment variable) sa nazivom classpath
C
dir1
dir2
dir3
dir4
G
paket
X.class
klijent
16
• varijabla classpath setuje se tako da prati putanju direktorijuma, sve do direktorijuma koji je direktno nadređen direktorijumu u kojem se nalazi paket
• setuje se komandom operativnog sistema koja u Windows ima oblik
set CLASSPATH = putanja do naddirektorijuma
• za prethodni primer
set CLASSPATH = .; c:\dir3\dir4
tekući dir.
17
• najbolje je pomenutu putanju nadodati na već formiranu vrednost
set CLASSPATH = %CLASSPATH%; .; c:\dir3\dir4
• varijablu CLASSPATH po pravilu održava razvojni sistem (npr. Eclipse)
zatečena vrednost CLASSPATH
18
Imenovani i neimenovani paket
• u isti direktorijum mogu se smestiti dva paketa: jedan nosi ime direktorijuma, a drugi nema ime
• dakle, u direktorijumu npr. pack mogu se nalaziti
– klase koje imaju naredbu package pack; one pripadaju paketu sa nazivom pack
– klase koje nemaju ovu naredbu; one pripadaju neimenovanom paketu
19
• posmatrajmo direktorijum packpackage pack;public class X {..............}package pack;public class Y {..............}
public class Z {..................}
pripada imenovanom paketu pack
pripada imenovanom paketu pack
pripada neimenovanom paketu
imenovani i neimenovani paket koji su u istom direktorijumu nemaju međusobno nikakve logičke veze, tojestimenovani i neimenovani paket su različiti paketi, bez obzira na to što su u istom direktorijumu
20
Inkapsulacija• Inkapsulacija je sredstvo za objedinjavanje
strukture (polja) i ponašanja (metode) u softversku celinu, tako da bude ostvarena kontrola pristupa
• članovi klase u javi se inkapsuliraju naredbom class i modifikatorima kontrole pristupa
• modifikatori kontrole pristupa primenjuju se na– pojedinačne članove (polja, metode, unutrašnje
klase); modifikator se navodi uz svaki član
– celu klasu
21
Kontrola pristupa članovima
• java ima četiri nivoa kontrole pristupa članovima klase (od najzatvorenijeg do najotvorenijeg):
private samo metode matične klase
(default ili friendly)
prethodno + metode klasa iz istog paketa
protected prethodno + metode potklasa
public metode svih klijenata
ovaj modifikator nema ključnu reč!
22
Kontrola pristupa članovima
public class A {
int i;
protected double x;
private long z;
public A(int k, double w) {...}
public void met1() {...};
double met2() {...};
..........................
}
ovako izgleda nivo default
nivo default
23
još jednom:
• prilikom redefinisanja nivo kontrole pristupa ne sme se pooštriti
24
Kontrola pristupa čitavoj klasi
• postoje dva nivoa kontrole pristupa klasi:
– nivo default (bez modifikatora): klasu mogu koristiti samo klase iz istog paketa
– nivo public: klasu mogu koristiti sve klase
public class A {..........} //nivo public
class B {..........} //nivo default
• naročito obratiti pažnju na nivo default; lako se može desiti da se modifikator publiczaboravi napisati, pa klasa automatski postaje nedostupna za klase izvan svog paketa!
25
Smeštanje klase u datoteku
• do sada smo smatrali da se svaka klasa nalazi u sopstvenoj datoteci čije se ime poklapa sa imenom klase
• prošireno pravilo: u jednoj datoteci može se nalaziti više klasa, ali samo je jedna public i nosi ime datoteke; ostale, ako ih ima, moraju biti default
26
primer
• Napravićemo paket dekart sa klasama Tack i Duz koje predstavljaju tačku i duž u pravouglom koordinatnom sistemu (obe klase moraju se nalaziti u direktorijumu dekart)
dekart::Tacka
x:realy:real
+x():real+y():real
dekart::Duz
a:Tackab:Tacka
+a():Tacka+b():Tacka+duzina():real
2
kompozicija
27
Tacka.java
package dekart;
public class Tacka
double x, y;
public Tacka(double x, double y) {
this.x = x; this.y = y;
}
public double x() { return x; }
public double y() { return y; }
}
kontrola pristupa: default
28
Duz.java
package dekart;
public class Duz {
Tacka a, b;
public Duz(Tacka a, Tacka b) {
this.a = a; this.b = b;
}
public Tacka a() { return a; }
public Tacka b() { return b; }
29
public double duzina() {
return Math.sqrt(Math.pow((a.x-b.x),2) +
Math.pow((a.y-b.y),2));
{
}
metoda duzina ima direktan pristup poljima x i y klase Tacka, jer je klasa Duz u istom paketu u kojem je i klasa Tacka
30
Primer klijentskog softvera
import dekart.*;
public class Test {
public static void main(String args[]) {
Duz d = new Duz(new Tacka(1,2),new Tacka(3,4));
System.out.println("Duzina duzi: "+d.duzina());
}
}
da bi se izbeglo koriscenje punihnaziva dveju klasa koji bi trebalo da budu dekart.Tacka i dekart.Duz
11 GENERIČKE KLASE
1
2
• generičke klase su klase parametrizovane drugim klasama
• predstavljaju vid parametarskog polimorfizma
• u javi su realizovane osloncem na jedinstvenu hijerarhiju klasa, a posebno na činjenicu da sve klase nasleđuju klasu Object
3
kako funkcioniše generičnost?
• klasu koja se ponaša kao da je parametrizovana klasom T realizujemo tako što
– na mestu gde bi trebalo da se pojavi generički parametar T stavljamo klasu Object
– u klijentu koristimo inkluzioni polimorfizam ili koercitivni polimorfizam (kast) za konverziju iz Object u konkretnu klasu, tj. generički argument
• ovako definisana klasa ponaša se kao generička klasa i to je dugo bio jedini način za realizaciju generičnosti u javi
4
public class GenClass {Object f;public GenClass(Object f) {this.f = f;
}public void setf(Object f) {this.f = f;
}public Object getf() {return f;
}}
Object igra ulogu generičkog parametra
5
• klijent:
GenClass g = new GenClass("Objekat kreiran");
g.setf("Polje f setovano");
String s = (String)g.getf();
• u ovom klijentu, klasa GenClass ponaša se kao generička klasa sa generičkim argumentom String
inkluzioni polimorfizam
koercija
6
sintaksa
• definiše se sa
class ImeKlase<P1,...,Pn> {
//genericki parametri mogu se upotrebiti
//za tip polja, tip metode i tip parametra
//metode
}
gde je modifikator ili public ili default (tj. prazan), a P1,...,Pn su generički parametri
7
public class GenClass<T> {T f;public GenClass(T f) {this.f = f;
}public void setf(T f) {this.f = f;
}public T getf() {return f;
}}
T je generički parametar
8
instanciranje i korišćenje
• generička klasa se instancira tako što se uz ime obavezno navode generički argumenti:
GenClass<String> g;
g = new GenClass<String>("Objekat kreiran");
• za korišćenje nije potrebna koercija:
String s = g.getf();
ne treba (String)
poziv konstruktora
9
UML
GenKlasa
veza korišćenja sa stereotipom bind
generički parametri
<P1,...,Pn>
GenKlasa<A1,...,An>
generički argumenti
KonkKlasa
<<bind>><A1,...,An>
prvinačin
druginačin
10
ograničavanje gen. parametra
• svaki generički parametar može se ograničiti natklasom:
class ImeKlase<P extends T> {
................
}
• prilikom konkretizacije, generički argument može biti samo klasa T ili neka klasa koja je nasleđuje!
11
džokerski generički parametar (wildcard)
• označava se sa ?
• upotrebljava se za oznaku tipa promenljivih i/ili parametara metode kada se zna da su generički, ali se ne zna konkretizacija (tj. ne znaju se generički argumenti tih tipova)
• drugim rečima, generička klasa sa džokerskim argumentom ponaša se kao čist generički tip
• između generičke klase sa džokerskim argumentom i konkretizovane generičke klase postoji odnos sličan inkluzionom polimorfizmu
12
primer
• metoda met ima za parametar tip GenClass:
public void met(GenClass<?> par) {…}
metoda se može pozvati sa argumentom čiji je tip bilo koja konkretizacija klase GenClass
• razlog: ako bi se upotrebio identifikator, prevodilac ne bi znao da li se identifikator odnosi na bilo koju klasu ili na neku konkretnu klasu
• dakle, ne
public void met(GenClass<P> par) {…}
P može biti konkretna klasa sa tim nazivom
13
još jedan primer
• Lista je u javi realizovana kao gotova generička klasa sa nazivom LinkedList<T>
• Iskazom
LinkedList<?> lst = new LinkedList<String>();
promenljiva lst dobija tip LinkedList<String>što se obezbeđuje u toku prevođenja
podseća na dodelu potomka pretku
14
• Džokerski generički parametar može se ograničiti "odozgo" iskazom
GenClass<? extends K>
a može se ograničiti i "odozdo" iskazom
GenClass<? super M>
• u prvom slučaju generički argument pripada klasi K ili nekom njenom potomku, a u drugom pripada nekoj natklasi klase M (ali ne može biti M)
15
generičke metode
• statički članovi klase ne mogu koristiti generičke parametre klase, ali
• svaka metoda, nestatička ili statička (uključujući i konstruktore) može imati sopstvene generičke parametre koji su nezavisni od generičkih parametara klase:
static <U, V extends U> int met(U x, V[] y) {…}
<P> konstruktor(P a) {…}
• napomena: pri pozivu, argumenti generičke metode se ne navode
16
Sirovi tipovi (Raw Types)
• jesu način za upotrebu generičkih klasa koji povezuje stari i novi način realizacije
• koriste se tako što se generička klasa koristi bez navođenja generičkih argumenata
GenClass sOb = new GenClass("ovo je string");
• prilikom korišćenja mora se vršiti koercija:String str = (String)sOb.getf();
što je, u stvari, stari način korišćenja generičnosti
17
Brisanje (erasing)
• postupak za povezivanje sintakse generičnosti sa stvarnom realizacijom (baziranom na jedinstvenoj hijerarhiji klasa)
• izvodi se u toku prevođenja tako što
– pre izrade bajt-koda, svaki generički parametar biva zamenjen najbližom konkretnom natklasom; ako parametar nema gornju granicu, zamenjuje se sa Object, a ako je ima, zamenjuje se (konkretnom) gornjom granicom
– pri obraćanju metodama sa generičkim rezultatom, dodaje se operator konverzije
18
public class GenClass<T> {T f;public GenClass(T f) {this.f = f;
}public void setf(T f) {this.f = f;
}public T getf() {return f;
}}
posle brisanja postaje
public class GenClass extends Object {Object f;public GenClass(Object f) {this.f = f;
}public void setf(Object f) {this.f = f;
}public Object getf() {return f;
}}
T se zamenjuje sa Object
19
• Slično, u klasipublic class GenerickaKlasa<P extends KonkrKlasa> {……………….}
svaka pojava P zamenjuje se sa KonkrKlasa• Obraćanje metodi što vraća generički tip ili
polju generičkog tipa snabdeva se operatorom kasta:
GenClass<String> obs = new GenClass<String>("ovo je string");……………….String s = obs.getf(); zamenjuje se saString s = (String)obs.getf();
• Sledi da je najveća prednost posebne sintakse činjenica da se kastovanje vrši automatski!
P se zamenjuje sa KonkrKlasa
20
Nasleđivanje
• generičke klase mogu se povezivati nasleđivanjem, pri čemi potklasa prosleđuje konkretne generičke argumente natklasi
• negenerička klasa može imati generičku potklasu
21
Operator instanceof
• primenljiv je i na generičke klase, ali sa džokerskim generičkim argumentom
• dakle, dozvoljeno je pisati
ob instanceof GenClass<?>
s tim što će operacija vratiti true ako sam objekat pripada bilo kojoj konkretizaciji GenClass.
• nije dozvoljeno pisati
ob instanceof GenClass<String>
i to zbog brisanja
DA
NE
22
Ograničenja• Klase koje su generički parametri ne mogu se
instancirati unutar generičke klase (razumljivo)
• Statičke metode ne mogu koristiti generičke parametre klase, ali mogu imati sopstvene
• Poseban problem čine nizovi koji su, sami po sebi generički
23
Ograničenja kod nizova• ne može se definisati niz generičkih referenci
zadatog tipa:GenClass<String>[] g = new GenClass<String> [100];
ali se može upotrebiti džokerski argument:GenClass<?>[] g = new GenClass<?> [100];
• u drugom slučaju biće stvoren niz referenci tipa Object
DA
NE
24
• polje tipa niza generičkih vrednosti može se definisati, ali se ne može instancirati
public class H<P> {
P[] values;
public H() {
values = new P[200];
}
………………….
}
DA
NE
25
• rešenje: proslediti niz kao parametar konstruktora
public class H<P> {
P[] values;
public H(P[] values) {
this.values = values;
}
……………….
}
DA
12 APSTRAKTNE KLASE
1
2
definicija
• apstraktne klase u javi slične su apstraktnim klasama u C++, ali nisu identične
• po definiciji, apstraktna klasa (u javi) je klasa koja se ne može instancirati
• podsetimo se: u C++, apstraktna klasa je klasa sa bar jednom apstraktnom metodom
• klasa se proglašava za apstraktnu modifikatorom abstract
3
apstraktne metode
• kao i u C++, apstraktna metoda je metoda koja nema realizaciju
• deklariše se samo zaglavljem uz dodavanje modifikatora abstract
public abstract tip metoda (parametri);
4
UML
• u UML, apstrakktna klasa prikazuje se ovako:
• apstraktna metoda izgleda ovako:
+
- ime(parametri):tip {abstract}
#
ImeKlase{abstract}
5
osobine
• klasa može biti apstraktna čak i kad nema nijednu apstraktnu metodu
• ako ima bar jednu apstraktnu metodu, klasa se mora proglasiti za apstraktnu dodavanjem modifikatora abstract
6
primena
• ima nešto širu primenu nego u C++
• apstraktna klasa
– služi za "izvlačenje" zajedničkih osobina skupa klasa u zajedničkog pretka (kao i u C++)
– služi za izradu klase koja se ne može direktno instancirati
13 INTERFEJSI
1
2
definicija
• interfejs je poseban element jave (nije klasa!), koji se koristi za spregu klijenta sa klasom
• osobine:– nema nijednu operacionalizovanu metodu– (ako ih uopšte ima), polja se tretiraju kao public
static final (modifikatori se ne pišu)– može biti public ili default– svi članovi su public (modifikator se ne piše)– ne može se instancirati (nema konstruktor)– može biti generički– omogućuje polimofnu zamenu
3
sintaksa
• definiše se sa
interface NazivInterfejsa {
//polja (sva su public static final)
//zaglavlja metoda (sve su public)
}
gde je modifikator ili public ili default (tj. prazan)
4
veza između interfejsa i klase
• između interfejsa i klase uspostavlja se veza implementacije koja podseća na nasleđivanje (ali nije ista!)
• sintaksa:
NazivKlase implements NazivInterfejsa {
………………..
}
• u klasi su implementirane sve metode iz interfejsa
5
UML
<<interface>>NazivInterfejsa
K1 K2 Kn
klase
interfejs
veza implementacije
6
inkluzioni polimorfizam
• za vezu implementacije važi inkluzioni polimorfizam i to u sve tri forme!
<<interface>>Intr
Klasa
Intr in = new Klasa();ili
Intr in;in = new Klasa();
7
• kada se izvrši polimorfno pridruživanje objekta interfejsu in, nad promenljivom inmogu se primeniti samo metode zadate u interfejsu i koristiti samo polja zadata u interfejsu, tj.
• kroz interfejs "vidi se" samo onaj deo objekta koji je deklarisan u interfejsu
8
operator instanceof
• operator instanceof primenljiv je i na interfejs
Intr in;
Klasa obK = new Klasa();
in = obK;
// in instanceof Intr je true
// obK instanceof Intr je true
// in instanceof Klasa je true
// obK instanceof Klasa je true
in
obK
9
opšti slučaj
• data klasa nasleđuje tačno jednu klasu, a može implementirati više interfejsa
<<interface>>I1
A
<<interface>>In
K ........
class A extends K
implements I1,...,In {
…………………
}
10
primene interfejsa
• neke karakteristične primene interfejsa:
– višestruka realizacija iste klase
– nasleđivanje implementacije
– više pogleda na istu klasu
– realizacija tipa enumeracije
– filtriranje tipa argumenta
11
višestruka realizacija klase
• kao što je poznato, većina klasa može se realizovati na više načina
• na primer, red (queue) može se realizovati sekvencijalno ili spregnuto
• korišćenjem zajedničkog interfejsa može se postići da se obe verzije koriste na isti način, što programeru u velikoj meri olakšava rad
12
<<interface>>Queue
+get():T+put(T el)+remove():T+isEmpty():boolean+isFull():boolean
SequentialQueue LinkedQueue
public interface Queue<T> {
T get();
void put(T el);
T remove();
boolean isEmpty();
boolean isFull();
}
<T>
<T> <T>
13
Queue<String> q;
q = new SequentialQueue<String>();
q = new LinkedQueue<String>();
u oba slučaja q se koristi na isti način (preko metoda get, put, remove,isEmpty i isFull), jer se samo te metode "vide"
14
nasleđivanje implementacije
• mehanizam za preuzimanje sadržaja neke klase u datu uz istovremeno podešavanje interfejsa date klase
• primer: spregnuto realizovan red može se napraviti od spregnute liste, uz promenu interfejsa reda da bi se eliminisao višak operacija iz liste
• postoji i u C++ kao private nasleđivanje
15
primer: spregnuti red<<interface>>
Queue
+get():T+put(T el)+remove():T+isEmpty():boolean+isFull():boolean
SequentialQueue LinkedQueue
java.util::LinkedList
<T>
<T>
<T> <T>
16
public class LinkedQueue<T> extends LinkedList<T>
implements Queue<T> {
public T get() {
return isEmpty() ? null : getFirst();
}
public void put(T el) {
addLast(el);
}
public T remove() {
return removeFirst();
}
//isEmpty() je vec implementirana u LinkedList!
public boolean isFull() {
return false;
}
}
metode nasleđene iz LinkedList
17
više pogleda na klasu
• ako se složena klasa veže za više interfejsa, ona se može "videti" kroz njih na različite načine (slično biblioteci u C/C++)
18
public interface Radio {metode radija}
public interface Sat {metode sata}
public class RadioSat {
//ovde su implementirani i radio i sat!
}
<<interface>>Radio
RadioSat
<<interface>>Sat
19
Radio rd = new RadioSat();
Sat st = new RadioSat();
RadioSat rds = new RadioSat();
• mehanizam podseća na višestruko nasleđivanje, ali to nije slučaj, jer nema preuzimanja sadržaja iz klasa Radio i Sat(u pitanju su samo interfejsi)
ponaša se kao radio
ponaša se kao sat
ponaša se kao radio-sat
20
zamena za enumeraciju
• mada postoji posebna komponenta jave zvana Enumeration, tip enumeracije nejjednostavnije se realizuje interfejsom, jer su sva polja public static final:
public interface Boja {
int CRVENA=0;
int ZELENA=1;
int PLAVA=2;
}
• korišćenje: Boja.CRVENA, Boja.ZELENA itd.
21
filtriranje tipa argumenta
• kada metoda treba da prihvati kao argumente samo objekte koji garantuju određeno ponašanje, a klase kojima ti objekti pripadaju nisu vezane nasleđivanjem
22
• metoda met može da primi kao argument samo objekat klase K ili M (ili neke njihove potklase):
public tip met(J par) {...}• naredba naredba može da se izvrši samo ako
ob pripada klasama K ili M, odn. njihovim potklasama:
if(ob instanceof J) naredba
M
K
<<interface>>J
<<interface>>J
23
višestruko nasleđivanje
• Java nema višestruko nasleđivanje niti se ono može u celosti postići drugim sredstvima
• neka klasa X treba višestruko da nasledi klase A i B
X
A B
24
• jedno rešenje je zameniti višestruko nasleđivanje kompozicijom, tj. u klasi Xdefinisati jedno polje tipa A i još jedno polje tipa B
public class X {
A a;
B b;
// eventualno formiranje interfejsa klase
}
• time je postignuta ušteda na vremenu izrade klase X, ali
• polimorfizam ne važi, tj. obX instanceof A i obX instanceof B daje false.
25
• drugo rešenje je napraviti interfejse A i B i implementirati ih u klasi X. Polimorfizam sada važi, ali se kompletna realizacija mora izvesti u klasi X (nema preuzimanja koda)
• ovaj slučaj sreli smo u primeru RadioSat
14 UNUTRAŠNJE I ANONIMNE KLASE
1
2
definicija
• Unutrašnja (inner) klasa je klasa koja je član druge (tzv. "spoljašnje") klase
• kao član, ni po čemu se ne razlikuje od drugih članova (polja, metoda):– može biti nestatička ili statička– važe sva četiri nivoa kontrole pristupa– spoljašnja klasa je u potpunosti otvorena za
metode unutrašnje klase i obrnuto
• može se, čak, definisati i unutar metode• služi, najčešće, za interne potrebe
spoljašnje klase
3
sintaksa
• definiše se kao i svaka druga klasa
class NazivKlase {
..................
}
s tim što se naredba class u celosti nalazi unutar naredbe class spoljašnje klase (ili unutar metode, ako je klasa unutrašnja za metodu)
4
UML
SpoljašnjaKlasa UnutrašnjaKlasa
5
primer
• za primer spregnutog reda: kako onemogućiti bilo kakav pristup članovima liste koji su sadržani u klasi Queue?
<<interface>>
Queue
LinkedQueue
{abstract} java.util::LinkedList
PLinkedQueue
instancira se preko ovog
TT
U
sam red je ovde
ne može se instancirati
6
import java.util.LinkedList;
public abstract class LinkedQueue {
public static <V> Queue<V> makeQueue() {
return new PLinkedQueue<V>();
}
private static class PLinkedQueue<U> extends LinkedList<U>
implements Queue<U> {
public void put(U element) {
addLast(element);
}
public U get() {
return isEmpty() ? null : getFirst();
}
public U remove() {
return removeFirst();
}
public boolean isFull() {
return false;
}
}
}
unutrašnja klasa
7
instanciranje
• klasa LinkedQueue instancira se tako što se, ustvari, kreira objekat unutrašnje klase PLinkedQueue
• pošto je unutrašnja klasa statička, a spoljašnja apstraktna (te se ne može instancirati), instanciranje reda izvodi se primenom statičke metode makeQueue:
Queue<String> q = LinkedQueue.makeQueue();
8
Anonimne klase
• bezimene klase koje se definišu i instanciraju istovremeno
• najčešće se koriste pri formiranju rezultata metode, kada je on objekat anonimne klase
• objekat anonimne klase formira se izrazom
new Klasa_ili_Interfejs() {opis anonimne klase}
gde je Klasa_ili_Interfejs koju anonimna klasanasleđuje odn. implementira
9
• u UML se prikazuju upisivanjem stereotipa <<Anonimous>> na mesto naziva klase i vezivanjem za datu klasu vezom "biti unutrašnja klasa"
UML
10
<<interface>>AnInterface
ClassWithAnonimous <<Anonimous>>
11
public interface AnInterface {void inc();void dec();
}//Klasa sa anonimnom unutrasnjom klasompublic class ClassWithAnonimous {private int x;ClassWithAnonimous() {
x = 0;}public int get() {
return x;}//Metoda sa unutrasnjom klasom koja konkretizuje AnInterfacepublic AnInterface value() {
return new AnInterface() {public void inc() {
x++;}public void dec() {x--;
}};
}}
definisanje i instanciranje anonimne klase koja implementira interfejs
AnInterface
15 KARAKTERISTIČNE KLASE
1
2
Omotači
• Omotač (wrapper) je klasa koja predstavlja objektnu realizaciju odgovarajućeg baznog tipa
• Na primer, ako treba napraviti red sa elementima tipa char, naredba
Queue<char> q = LinkedQueue.makeQueue();
neće proći, jer char nije klasa!
• za svaki bazni tip postoji odgovarajući omotač
3
• Omotači (osim za logički i znakovni tip) su uređeni u mini hijerarhiju sa korenom u apstraktnoj klasi Number
Number{abstract}
Integer Long Float Double
Boolean Character
Object
4
Omotači
• Omotači raspolažu repertoarom metoda za konverziju iz baznog tipa u omotač i obrnuto
• U novijim verzijama jave konverzija iz tipa u omotač i obrnuto je automatizovana
Queue<Character> q = LinkedQueue.makeQueue();
.......
q.put('a');
char c = q.get();
q.put(new Character('b'));
automatska konverzija iz char u Character
automatska konverzija iz Character u char
direktna primena omotača
5
• bazni tip i omotač mogu se koristiti kao da su isti tip:
int i = new Integer(10);
Character obC = new Character('x');
............
obC = 'y';
automatska konverzija
6
Kontejneri
• Kontejneri su klase koje realizuju strukture podataka
• ima ih više, a najvažnije su
– ArrayList<E> dinamički niz
– LinkedList<E> dvostruko spregnuta lista
– HashMap<K,V> heš tabela
• sve su generičke
• sve implementiraju interfejs Collection, što garantuje postojanje glavnih operacija vezanih za strukture podataka
7
interfejs Collection
int size() Očitavanje aktuelnog broja elemenata
boolean add(E el) Dodavanje elementa el; u slučaju neuspeha vraća false
boolean remove(Object el) Uklanjanje jedne instance elementa el. Rezultat je true u slučaju uspeha, inače false
void clear() Uklanjanje svih elemenata
boolean isEmpty() Provera da li je kolekcija prazna
boolean contains(Object el) Provera da li kolekcija sadrži objekat el. Proverava se sadržaj (ne referenca!)
Object[] toArray() Konverzija kolekcije u niz
Iterator<E> iterator() Vraća iterator zadate kolekcije
8
iteratori
• iterator je složena operacija kojom se pristupa svim elementima kontejnera (tj. strukture podataka)
• u javi je realizovan u dva vida:– kao naredba
– kao generički interfejs koji je implementiran u kontejnerskim klasama
9
naredba for
• naredba za iteriranje kroz kontejner tipa Collection ili kroz niz
• u teoriji, ovakve naredbe zovu se foreach
• opšti oblik:for(TipEl imeEl : imeNiza_Kolekcije) naredba
• neka je arrLst dinamički niz sa elementima tipa Integer:
ArrayList<Integer> arrLst = new ArrayList<Integer>();
10
• štampanje svih elemenata dinamičkog niza:
for(Integer e : arrLst) System.out.println(e);
• još jednom, uočimo da je naredba foreachprimenljiva i na obične nizove!
11
iterator kao interfejs
• drugi način jeste realizacija iteratora kao generičkog interfejsa
• dok je naredba foreach primenljiva samo na kolekcije, interfejs Iterator upotrebljiv je u bilo kojoj klasi koja ga implementira
• generički interfejs Iterator<E> ima tri metode:– boolean hasNext() koja vraća true sve dok se ne pristupi
poslednjem elementu
– E next() vraća sledeći element
– void remove() uklanja element kojem je upravo pristupljeno pomoću next()
• iterator se kreira iz klase metodom iterator()
• postoji u svim kontejnerima!
12
• štampanje svih elemenata dinamičkog niza:
Iterator<Integer> iter = arrLst.iterator();
while(iter.hasNext())
System.out.println(iter.next ());
• napomena: metoda iterator se u matičnoj klasi realizuje tako da, kao rezultat, vraća objekat anonimne klase što implementira interfejs Iterator, naredbom
return new Iterator<E> {.....
}
realizacija hasNext(), next() i
remove()
13
Klasa Class
• specijalna generička klasa koja sadrži podatke o datoj klasi (tzv. metapodatke)
• objekti se ne konstruišu nego preuzimaju iz posmatrane klase, preko tzv. klasnih literala
• svakoj klasi u programu pridružuje se klasni literal sa nazivom
ImeKlase.class
koji sadrži podatke o klasi ImeKlase.
14
• Posmatrajmo klasu MyClass. Njoj se automatski pridružuje klasni literal MyClass.class sa nizom podataka o klasi MyClass.
• Podaci o klasi MyClass mogu se dohvatiti na dva načina:
– direktno, preko odgovarajuće promenljive tipa Class
– indirektno, preko objekta klase MyClass
15
• direktni način:
Class<?> c = MyClass.class
• indirektni način, preko metode getClass():
MyClass myObj = new MyClass();
....
Class<?> c = myObj.getClass();
• Korišćenjem objekata klase Class mogu se prikupiti različiti podaci o klasi MyClass, pa čak i aktivirati neka od njenih metoda, koristeći ime metode
16
RTTI
• RTTI je akronim od Runtime Type Identification i odnosi se na utvrđivanje tipa objekta u toku izvršenja
• Operator ob instanceof K, primenjen na objekat obutvrdiće da li je ob zadatog tipa, tj. da li pripada klasi K njenoj potklasi
• Ako je potrebno utvrditi da li objekat ob pripada klasi K i nijednoj drugoj, to postižemo primenom metoda getClass i equals klase Class
ob.getClass().equals(K.class)
• rezultat je true samo ako ob referencira objekat klase K.
16 PREVENCIJA OTKAZA
1
2
Postupci
1. ugraditi u klasu metode-indikatore za proveru nastanka otkaza (npr. isEmptykod steka)
2. havarijski prekid programa (metoda System.exit(int exitcode))
3. vrednost metode kao kod uspešnosti
4. rukovanje izuzecima
3
vrednost metode kao kod uspešnosti
• pogodan za void metode, nepogodan za metode koje vraćaju rezultat
• pogodnost jave: ako je vraćeni rezultat objekat, tada se faktički vraća referenca
– u takvim slučajevima vrednost null može da bude kod neuspešnosti (dosta često se koristi)
4
Rukovanje izuzecima
• podaci o nastalom izuzetku se pakuju u objekte
Throwable
Object
Error Exception
RuntimeException
!rezervisano za
javu
5
• klase izuzetaka su obične klase, uređene u mini-hijerarhiju sa korenom u klasi Throwable
• za rukovanje izuzecima mogu se koristiti gotove klase ili se mogu praviti klase koje se obavezno uključuju u hijerarhiju "ispod" klase Exception ili neke koja je već nasleđuje
6
karakteristične metode
• postoje u svim klasama izuzetaka, jer su definisane u klasi Throwable
• konstruktor() i konstruktor(String poruka)
• String getMessage()
• String toString()
• void printStackTrace() – standardna reakcija na nastanak izuzetka
!
7
primer sopstvene klase
public class MyException extends Exception {
public MyException() {}
public MyException(String message) {
super(message+" FROM MyException");
}
}
8
generisanje izuzetka
• izuzetak se generiše naredbom throw sa opštim oblikom
throw new konstruktor(parametri)
gde je sa konstruktor označen konstruktor klase izuzetaka koja se koristi.
• na primer,if(x<0) throw new MyException("Negativan argument");
!
9
• metoda koja generiše izuzetak mora ga i deklarisati iskazom throws na sledeći način:
tip imeMetode(parametri) throws Ex1,...,Exn {
....................
}
gde su Ex1,...,Exn klase izuzetaka koje generiše metoda.
public double f(double x) throws MyException {
if(x<0) throw MyException("Negativan argument");
return 2*Math.sin(x)*Math.sqrt(x);
}
10
• Važi inkluzioni polimorfizam. Sledeća metoda može da generiše bilo koji izuzetak što nasleđuje klasu Exception:
tip imeMetode throws Exception {
.............
}
• sledeća metoda može da generiše bilo koji izuzetak:
tip imeMetode throws Throwable {
.............
}
11
• Izuzeci iz klase RuntimeException (i njenih potklasa) ne moraju se deklarisati:
public double f(double x) {
if(x<0) throw RuntimeException("Negativan
argument");
return 2*Math.sin(x)*Math.sqrt(x);
}
nema iskaza throws
12
prihvatanje izuzetka
• Izuzeci se mogu
– prihvatiti i obraditi tzv. blokom try
– proslediti višem nivou poziva
– delimično obraditi i proslediti višem nivou
13
prihvatanje i obrada• opšti oblik bloka try:try {... kritične naredbe ...} catch(ExClass1 e) {
... obrada izuzetka e} catch(ExClass2 e) {
... obrada izuzetka e.............................} catch(ExClassn e) {
... obrada izuzetka e} finally {
... obavezno se izvrsava}
lista hendlera pregleda se linearno.Paziti na to da se potomak nađe ispred pretka!
14
• najčešće korišćen način za obradu izuzetka je poziv metode printStackTrace() kojim se prikazuju tačke (linije koda) u kojima su nastali izuzeci
public void prikazf (double y) {try {
System.out.println("f("+y+")="+f(y));} catch(MyException e {
System.out.println(e.getMessage());e.printStackTrace();
}}
15
prosleđivanje
• prosleđivanje se vrši izostavljanjem bloka try i deklarisanjem izuzetka:
public void prikazf (double y) throws MyException {
System.out.println("f("+y+")="+f(y));
}
• ako izuzetak pripada klasi RuntimeException ili njenim potklasama, ne mora se deklarisati!
ako nije RuntimeException
16
obrada i prosleđivanje• prosleđivanje se vrši kombinacijom bloka try i
naredbe throw:public void prikazf (double y) throws MyException {try {
System.out.println("f("+y+")="+f(y));} catch(MyException e {
System.out.println(e.getMessage());e.printStackTrace();throw e;
}}
ako nije RuntimeException
1717
Propagacija izuzetaka
m0
m1
mk-1
mk
• izuzetak mora biti detektovan!
ovde je nastao izuzetak
propagacija izuzetka
ovo je main
1818
• svaka od metoda m0,...,mk-1,mk može se pripremiti:
– da nema hendler za nastali izuzetak; tada se izuzetak automatski prosleđuje na viši nivo poziva, ali mora biti deklarisan (osim za RuntimeException i njene potklase)
– da ima hendler; tada se hendler izvršava i propagacija se zaustavlja
• u hendler se može ubaciti naredba throw egde je e izuzetak; tada se propagacija nastavlja izuzetkom e