Java - Curs
Java - Curs
TM
Curs 1 Introducere in Java
Curs 2 Obiecte si clase in Java
Curs 3 Exceptii
Curs 3 Fluxuri Intrari ! Iesiri"
Curs # Inter$ete
Curs # Pac%ete
Curs & 'eriali(area obiectelor
Curs & Colectii
Curs ) Inter$ata gra$ica
Curs * +esenarea
Curs , Fire de executie
Curs - Programarea .n retea
Curs 1/ 0pplet1uri
Curs 11 2ucrul cu ba(e de date .n Java
Curs 12 Organi(area $isierelor 34ava si 3class
Curs 1
Introducere in Java
Ce este Java ?
Crearea unei aplicatii simple
Crearea unui applet simplu
Structura lexicala a limbajului Java
o Setul de caractere
o Cuvinte cheie
o Identificatori
1
o Literali
o Separatori
o Operatori
o Comentarii
Tipuri de date
Variabile
Controlul executiei
Vectori
Siruri de caractere
olosirea ar!umentelor de la linia de comanda
Top
Ce este Java 5
2imba4ul de programare Java
Java este un limbaj de pro!ramare de nivel "nalt# de$voltat de JavaSoft# companie "n cadrul firmei Sun
%icros&stems' (intre caracteristicile principale ale limbajului amintim)
simplitate# elimina supra"ncarcarea operatorilor# mostenirea multipla si toate *facilitatile* ce pot
provoca scrierea unui cod confu$'
robustete# elimina sursele frecvente de erori ce apar in pro!ramare prin eliminarea pointerilor#
administrarea automata a memoriei si eliminarea fisurilor de memorie printr+o procedura de
colectare a ,!unoiului, care rulea$a "n fundal' -n pro!ram Java care a trecut de compilare are
proprietatea ca la executia sa nu *crapa sistemul*'
complet orientat pe obiecte + elimina complet stilul de pro!ramare procedural
usurinta in ceea ce priveste programarea in retea
securitate# este cel mai si!ur limbaj de pro!ramare disponibil "n acest moment# asi!ur.nd
mecanisme stricte de securitate a pro!ramelor concreti$ate prin) verificarea dinamica a codului
pentru detectarea secventelor periculoase# impunerea unor re!uli stricte pentru rularea
pro!ramelor lansate pe calculatoare aflate la distanta# etc
este neutru din punct de vedere ar%itectural
portabililtate# cu alte cuvinte Java este un limbaj independent de platforma de lucru# aceeasi
aplicatie ruland# fara nici o modificare# pe sisteme diferite cum ar fi /indo0s# -1I2 sau
%acintosh# lucru care aduce economii substantiale firmelor care de$volta aplicatii pentru Internet'
compilat si interpretat
asi!ura o per$ormanta ridicata a codului de octeti
permite pro!ramarea cu $ire de executie 3multitheaded4
dinamicitate
este modelat dupa C si C66# trecerea de la C# C55 la Java fac.ndu+se foarte usor'
permite creearea unor documente /eb "mbunatatite cu animatie si multimedia'
Java 7 un limba4 compilat si interpretat
In functie de modul de executie al pro!ramelor# limbajele de pro!ramare se "mpart "n doua cate!orii )
interpretate ) instructiunile sunt citite linie cu linie de un pro!ram numit interpretor si traduse "n
instructiuni masina6 avantaj ) simplitate6 de$avantaje ) vite$a de executie redusa
7
compilate ) codul sursa al pro!ramelor este transformat de compilator "ntr+un cod ce poate fi
executat direct de procesor6 avantaj ) executie rapida6 de$avantaj ) lipsa portabilitatii# codul
compilat "ntr+un format de nivel sca$ut nu poate fi rulat dec.t pe platforma pe care a fost compilat'
Programele Java sunt fi att interpretate ct si compilate.
Codul de octeti este diferit de codul masina' Codul masina este repre$entat de o succesiune de 8 si 16
codurile de octeti sunt seturi de instructiuni care seamana cu codul scris "n limbaj de asamblare' Codul
masina este executat direct de catre procesor si poate fi folosit numai pe platforma pe care a fost creat6
codul de octeti este interpretat de mediul Java si de aceea poate fi rulat pe orice platforma care foloseste
mediul de executie Java'
Cod sursa Java -> (compilare) -> Cod de octeti -> (interpretare)
Crearea unei aplicatii simple
1' 'criererea codului sursa
2. 2. class FirstApp {
3. 3. public static void main( String args!) {
". ". S#stem.out.println($%ello &orld$)'
(. (. )
*. *. )
Toate aplicatiile Java contin o clasa principala3primara4 "n care trebuie sa se !aseasca metoda
main' Clasele aplicatiei se pot !asi fie "ntr+un sin!ur fisier# fie "n mai multe'
9' 'alvarea $isierelor sursa
Se va face "n fisiere cu extensia .+ava
iserul care contine codul sursa al clasei primare trebuie sa aiba acelasi nume cu clasa primara a
aplicatiei 3clasa care contine metoda main4
Obs) Java face distinctie "ntre literele mari si mici'
C,-+ava-FirstApp.+ava
:' Compilarea aplicatiei
Se foloseste compilatorul Java# +avac
;pelul compilatorului se face pentru fisierul ce contine clasa principala a aplicatiei' Compilatorul
creea$a c.te un fisier separat pentru fiecare clasa a pro!ramului6 acestea au extensia 'class si sunt
plasate "n acelasi director cu fisierele sursa'
+avac FirstApp.+ava -> FirstApp.class
<' 8ularea aplicatiei
=
Se face cu interpretorul java# apelat pentru unitatea de compilare corespun$atoare clasei
principale# fiind "nsa omisa extensia .class asociata acesteia'
+ava FirstApp
>ularea unei aplicatii care nu foloseate interfata !rafica# se va face "ntr+o fereastra sistem'
Crearea unui applet
Crearea structurii de fisere si compilarea applet+urilor sunt identice ca "n ca$ul aplicatiilor' (ifera "n
schimb structura pro!ramului si modul de rulare al acestuia'
1' 'crierea codului sursa si salvarea .n $isier
2. 2. import +ava.a&t.. '
3. 3. import +ava.applet.. '
". ". public class FirstApplet e/tends Applet {
(. (. 0mage img'
*. *. public void init() {
1. 1. img 2 get0mage(getCode3ase()4 $ta5.gi6$)'
7. 7. )
8. 8. public void paint (9rap:ics g) {
;<. ;<. g.dra&0mage(img4 <4 <4 t:is)'
;;. ;;. g.dra&=val(;<<4<4;(<4(<)'
;2. ;2. g.dra&String($%ello> ?# name is @a5>$4 ;;<4 2()'
;3. ;3. )
;". ;". )
Salvarea se va face "n fisierul FirstApplet.+ava
1?' Compilarea applet1ului
+avac FirstApplet.+ava -> FirstApplet.class
1@' 8ularea applet1ului
;pplet+urile nu rulea$a independent' Ale pot fi rulate doar prin intermediul unui bro0ser ) Internet
Axplorer# 1etscape sau printr+un pro!ram special cum ar fi appletvie0er+ul din setul J(B'
1' Creearea unui fisier CT%L pentru miniaplicatie 3exemplu'html4
2. 2. A:tml>
3. 3. A:ead>
". ". Atitle>First Java AppletA-title>
(. (. A-:ead>
D
*. *. Abod#>
1. 1. Aapplet code2FirstApplet.class &idt:2"<<
:eig:t2"<<>
7. 7. A-applet>
8. 8. A-bod#>
;<. ;<. A-:tml>
11' Vi$uali$area appletului
appletvie&er e/emplu.:tml
'tructura lexicala a limba4ului
'etul de caractere
Limbajului Java lucrea$a "n mod nativ folosind setul de caractere -nicode' ;cesta este un standard
international care "nlocuieste vechiul set de caractere ;SCII si care foloseste pentru repre$entarea
caracterelor 7 octeti# ceea ce "nseamna ca se pot repre$enta @??=@ de semne# spre deosebire de ;SCII#
unde era posibila repre$entarea a 7?@ de caractere' Erimele 7?@ caractere -nicode corespund celor din
;SCII# referirea la celelate fac.ndu+se prin Bu////# unde //// repre$inta codul caracterului'
Ax)
Bu<<3< - Bu<<38 , ci6re 0S=-Catin < - 8
Bu<**< - Bu<**8 , ci6re arabic-indic < - 8
Bu"e<< - Bu8666 , litere din al6abetul %an (C:ine54 Japone54 Coreean)
Cuvinte c%eie
Cuvintele re$ervate "n Java sunt cele din C55# cu c.teva exceptii
Identi$icatorii
Sunt secvente nelimitate de litere si cifre -nicode# "ncepand cu o litera' Identificatorii nu au voie sa fie
identici cu cuvintele re$ervate'
2iteralii constantele"
Literalii pot fi de urmatoarele tipuri
literali .ntregi
Sunt acceptate = ba$e de numeratie ) ba$a 18# ba$a 1@ 3"ncep cu caracterele 8x4 si ba$a : 3"ncep cu
cifra 84 si pot fi de doua tipuri)
o normali# 3se repre$ pe D octeti + =7 biti4
o lun!i 3: octeti + @D biti4 ) se termina cu caracterul L 3sau l4'
literali $lotanti
Eentru ca un literal sa fie considerat flotant el trebuie sa aiba cel putin o $ecimala dupa vir!ula# sa
fie "n notatie exponentiala sau sa aiba sufixul sau f pentru valorile normale 3repre$' pe =7 biti4#
respectiv ( sau d pentru valorile duble 3repre$' pe @D biti4
?
literali logici
true ) valoarea booleana de adevar
false ) valoarea booleana de fals
;tentie) spre deosebire de C55# literalii "ntre!i 1 si 8 nu mai au rolul de adevarat si false
literali caracter
-n literal de tip caracter este utili$at pentru a exprima caracterele codului -nicode' >epre$entarea
se face fie folosind o litera# fie o secventa escape scrisa "ntre apostrofuri' Secventele escape permit
repre$entarea caracterelor care nu au repre$entare !rafica si repre$entarea unor caractere speciale
precum bacFslash# caracterul apostrof# etc' Secvente escape predefinite "n Java)
Cod 'ecventa Escape Caracter
Gu888: ,Gb, HacFspace3HS4
Gu888< ,Gt, Tab ori$ontal 3CT4
Gu888a ,Gn, Linie noua + linefeed 3L4
Gu888c ,Gf, Ea!ina noua + formfeed 34
Gu888d ,Gr, Inceput de rand 3C>4
Gu8877 ,G*, Ihilimele
Gu8879 ,G,, ;postrof
Gu88?c ,GG, HacFslash
literali siruri de caractere
-n literal sir de caractere este format din $ero sau mai multe caractere "ntre !hilimele' Caracterele
care formea$a sirul de caractere pot fi caractere !rafice sau secvente escape ca cele definite la
literalii caracter' (aca sirul este prea lun! el poate fi scris ca o concatenare de subsiruri de
dimensiune mai mica' Concatenarea sirurilor se face cu operatorul 5 3$Ana $ D $ are $ D $
mere $4' Sirul vid este $$' (upa cum vom vedea# orice sir este de fapt o instanta a clasei String#
definita "n pachetul java'lan!'
'eparatori
-n separator este un caracter care indica sf.rsitul unei unitati lexicale si "nceputul alteia' In Java
separatorii sunt urmatorii) ( ) { ) ! ' 4 . Instructiunile unui pro!ram se separa cu punct si vir!ula
Operatori
atribuirea) 2
operatori matematici) D4 -4 .4 -4 E
Aste permisa notatia prescurtata de forma lval op2 rval (e/, n D2 2)
Axista operatorii pentru autoincrementare si autodecrementare 3post si pre4
e/, /DD4 DD/4 n--4 --n
Observatie) evaluarea expresiilor lo!ice se face prin metoda scurtcircuitului 3evaluarea se opreste
"n momentul "n care valoarea de adevar a expresiei este si!ur determinata4
operatori lo!ici) FF(and)4 GG(or)4 >(not)
operatori relationali) A4 A24 >4 A24 224 >2
operatori pe biti) F (and)4 G(or)4 H(/or)4 I(not)
operatori de translatie AA4 >>4 >>> (s:i6t la dreapta 6ara semn)
operatorul i6-else, e/presieJlogica K valJptJtrue , valJptJ6alse '
operatorul # 3vir!ula4 folosit pentru evaluarea secventiala a operatiilor int /2<4 #2;4 522'
operatorul 5 pentru concatenarea sirurilor)
String s2$abcd$
int /2;<<'
S#stem.out.println(s D $ - $ D /)'
@
operatori pentru conversii 3cast4 ) (tipJdeJdata)
int i 2 2<<'
long l 2 (long)i' --&idening conversion - conversie prin e/tensie
long l2 2 (long)2<<'
int i2 2 (int)l2' --narro&ing conversion - conversie prin contractie
Comentarii
In Java exista trei feluri de comentarii)
Comentarii pe mai multe linii# "nchise "ntre JK si KJ'
Comentarii pe mai multe linii care tin de documentatie# "nchise "ntre JKK si KJ' Textul dintre cele
douL secvente este automat mutat "n documentatia aplicatiei de catre !eneratorul automat de
documentatie +avadoc'
comentarii pe o sin!ura linie care "ncep cu JJ'
Observatii)
1' nu putem sa scriem comentarii "n interiorul altor comentarii'
7' nu putem introduce comentarii "n interiorul literalilor caracter sau sir de caractere'
=' secventele JK si KJ pot sa apara pe o linie dupa secventa JJ dar "si pierd semnificatia6 la fel se
"nt.mplL cu secventa JJ "n comentarii care "ncep cu JK sau JKK'
Tipuri de date
In Java tipurile de date se "mpart "n doua cate!orii) tipuri primitive de date si tipuri re$erinta' Java
porneste de la premi$a ca *orice este un obiect*' ;sadar tipurile de date ar trebui sa fie de fapt definite de
clase si toate variabilele ar trebui sa memore$e de fapt instante ale acestor clase 3obiecte4' In principiu
acest lucru este adevarat# "nsa# pentru usurinta pro!ramarii# mai exista si asa numitele tipurile primitive
de date# care sunt cele u$uale )
aritmetice
o "ntre!i) b#te (; octet)4 s:ort (2)4 int (")4 long (7)
o reale) 6loat (" octeti)4 double (7)
caracter ) c:ar (2 octeti)
lo!ic ) boolean (true si 6alse)
In alte limbaje formatul si dimensiunea tipurilor primitive de date folosite "ntr+un pro!ram pot depinde de
platforma pe care rulea$a pro!ramul' In Java acest lucru nu mai este valabil# orice dependenta de o
anumita platforma specifica fiind eliminata'
Vectorii# clasele si interfetele sunt tipuri re$erinta' Valoarea unei variabile de acest tip este# "n contrast
cu tipurile primitive# o referinta 3adresa de memorie4 catre valoarea sau multimea de valori repre$entata
de variabila respectiva'
Axista trei tipuri de date C care nu sunt suportate de limbajul Java' ;cestea sunt) pointer4 struct si
union' Eointerii au fost eliminati din cau$a ca erau o sursa constanta de erori# locul lor fiind luat de tipul
referinta# iar struct si union nu "si mai au rostul at.t timp c.t tipurile compuse de date sunt formate "n Java
prin intermediul claselor'
9
9ariabile
Variabilele pot avea ca tip fie un tip primitiv de data# fie o referinta la un obiect'
(eclararea variabilelor
@ip numeJvariabila
Initiali$area variabilelor
@ip numeJvariabila 2 valoare
(eclararea constantelor
final @ip numeJvariabila
Conventia de notare a variabilelor in Java este data de urmatoarele criterii)
1' variabilele finale 3constante4 se scriu cu majuscule
7' variabilele normale se scriu astfel ) prima litera cu litera mica# daca numele variabilei este format
din mai multi atomi lexicali# atunci primele litere ale celorlalti atomi se scriu cu majuscule# de
exemplu)
3. 3. 6inal double L0 2 3.;"'
". ". int valoare 2 ;<<'
(. (. long numarMlemente 2 ;23"(*17C'
*. *. String bautura?eaLre6erata 2 $apa$'
In functie de locul "n care sunt declarate variabile se "mpart "n urmatoatele cate!orii)
1' 9ariabile membre# declarate "n interiorul unei clase# vi$ibile pentru toate metodele clasei
respective si pentru alte clase "n functie de nivelul lor de acces 3ve$i *(eclararea variabilelor
membre*4
7' 9ariabile locale# declarate "ntr+o metoda sau "ntr+un bloc de cod# vi$ibile doar "n metodaJblocul
respectiv
=' Parametri metodelor# vi$ibili doar "n metoda respectiva
D' Parametrii de la tratarea exceptiilor
Obs) variabilele declarate "ntr+un 6or pentru controlul ciclului# ram.n locale corpului ciclului'
6or(int i2<' iA;<<' iDD) { )
int i' --oN On Java4 eroare On CDD
:
Obs) Spre deosebire de C55 nu este permisa ascunderea unei variabile )
int /2;2'
{
int /28*' --ilegal
)
Controlul executiei
Instructiunile Java pentru controlul executiei sunt asemanatoare celor din C'
Instructiuni de deci$ie
i6-else4 s&itc:-case
Instructiuni de salt
6or4 &:ile4 do-&:ile
Instructiuni pt' tratarea exceptiilor
tr#-catc:-6inall#4 t:ro&
;lte instructiuni
breaN4 continue4 label, 4 return
Instructiuni de deci(ie
i6-else
i6 (e/pJbooleana) { -.....-)
i6 (e/pJbooleana) { -.....-) else { -.....-)
s&itc:-case
s&itc: (variabila) {
case val; , -. ... .- breaN'
case val2 , -. ... .- breaN'
-.....-
de6ault , -.....-
)
Instructiuni de salt
6or
6or(initiali5are' e/pJbooleana' pasJiteratie)
M/, 6or(int i2<4 +2;<< ' iA;<< FF +><' iDD4 +--)
{-. ... -.)
Obs) at.t la initiali$are c.t si "n pasul de iteratie pot fi mai multe instructiuni
despartite prin vir!ula'
&:ile
&:ile (e/pJbooleana) {
-.....-
)
do-&:ile
do {
-.....-
)
&:ile (e/pJbooleana) '
Instructiuni pentru tratarea exceptiilor
tr#-catc:-6inall#4
t:ro&
3ve$i *Tratarea exceptiilor*4
0lte instructiuni
breaN
paraseste fortat corpul iteratiei curente
continue
termina fortat iteratia curenta
return
return valoare!'
Termina o metoda
label,
(efineste o eticheta
<
;tentie) In Java nu exista goto' Se pot "nsa defini etichete de forma numeJetic:eta,# folosite "n expresii
de !enul) breaN numeJetic:eata sau continue numeJetic:eta
M/emplu,
i2<'
etic:eta,
&:ile (iA;<) {
S#stem.out.println($i2$Di)'
+2<'
&:ile (+A;<) {
+DD'
i6 (+22() continue etic:eta'
i6 (+221) breaN etic:eta'
S#stem.out.println($+2$D+)'
)
iDD'
)
9ectori
Crearea unui vector
1' (eclararea vectorului
2. 2. Tip[] numeVector; sau
3. 3. Tip numeVector[];
". ". M/, int! intregi'
(. (. String adrese!'
@' Instantierea
Se reali$ea$a prin intermediul operatorului ne& si are ca efect alocarea memoriei pentru vector#
mai precis specificarea numarului maxim de elemente pe care "l va avea vectorul6
1. 1. numeVector = new Tip[dimensiune];
7. 7. M/, v 2 ne& int;<!' --se aloca spatiu pentru ;< intregi
8. 8. adrese 2 ne& String;<<!'
Obs) declararea si instantierea unui vector pot fi facute simultan astfel)
Tip[] numeVector = new Tip[dimensiune];
18' Initiali$area 3optional4
(upa declararea unui vector# acesta poate fi initiali$at# adica elementele sale pot primi niste valori
initiale# evident daca este ca$ul pentru asa ceva' In acest ca$ instantierea lipseste# alocarea
memoriei fac.ndu+se automat "n functie de numarul de elemente cu care se initiali$ea$a vectorul'
;;. ;;. M/, String culori! 2 {$Posu$4 $9alben$4 $Qerde$)'
;2. ;2. int !6actorial 2 {;4 ;4 24 *4 2"4 ;2<)'
Observatii)
Erimul indice al unui vector este 8# deci po$itiile unui vector cu n elemente vor fi cuprinse "ntre 8 si n+1
1u sunt permise constructii de !enul Tip numeVector[dimensiune]# alocarea memoriei fac.ndu+se doar
prin intermediul opearatorului ne&'
M/, int v;<!' --ilegal
int v! 2 ne& int;<!' --corect
9ectori multidimensionali
In Java tablourile multidimensionale sunt de fapt vectori de vectori'
M/, int m!!' --declararea unei matrici
m 2 ne& int(!;<!' --cu ( linii4 ;< coloane
18
Obs) m<!4 m;!4 ...4 m(! sunt vectori de intre!i cu 18 elemente
+imensiunea unui vector
Cu ajutorul cuv.ntului cheie length se poate afla dimensiunea unui vector'
int !a 2 ne& int(!'
a.lengt: are valoarea (
int m 2 ne& int(!;<!'
m<!.lengt: are valoarea ;<
Copierea vectorilor
Copierea unui vector "n alt vector se face cu ajutorul metodei System.arraycopy)
int /! 2 {;4 24 34 ")'
int #! 2 ne& int"!'
S#stem.arra#cop#(/4<4#4<4/.lengt:)'
9ectori cu dimensiune variabila
Implementarea vectorilor cu numar variabil de elemente este oferita de clasa Qector din pachetul
+ava.util' -n obiect de tip Qector contine numai elemente de tip =b+ect'
'iruri de caractere
In Java# un sir de caractere poate fi repre$entat printr+un vector format din elemente de tip c:ar# un obiect
de tip String sau un obiect de tip String3u66er'
+eclararea unui sir
(aca un sir de caractere este constant atunci el va fi declarat de tipul String# altfel va fi declarat cu
String3u66er' 3ve$i *Clasele String4 String3u66er*4 Axemple echivalente de declarare a unui sir)
String str 2 $abc$'
c:ar data! 2 {RaR4 RbR4 RcR)'
String str 2 ne& String(data)'
String str 2 ne& String($abc$)'
Concatenarea sirurilor
Concatenarea sirurilor de caractere se face prin intermediul operatorului 6'
String str; 2 $abc$ D $/#5$'
String str2 2 $;23$'
String str3 2 str; D str2'
In Java# operatorul de concatenare 6 este extrem de flexibil "n sensul ca permite concatenarea sirurilor cu
obiecte de orice tip care au o repre$entare de tip sir de caractere'
S#stem.out.print($Qectorul v are$ D v.lengt: D $ elemente$)
Folosirea argumentelor de la linia de comanda
O aplicatie Java poate primi oric.te ar!umente de la linia de comanda "n momentul lansarii ei' ;ceste
ar!umente sunt utile pentru a permite utili$atorului sa specifice diverse optiuni le!ate de functionarea
aplicatiei sau sa furni$e$e anumite date initiale pro!ramului'
11
0tentie) Ero!ramele care folosesc ar!umente de la linia de comanda nu sunt 188M pure Java deoarece
unele sisteme de operare cum ar fi %ac OS nu au "n mod normal linie de comanda'
;r!umentele de la linia de comanda sunt introduse la lansarea unei aplicatii# fiind specificate dupa
numele aplicatiei si separate prin spatiu' (e exemplu# sa presupunem ca aplicatia Sort ordonea$a
lexico!rafic liniile unui fisier si primeste ca ar!ument numele fisierului pe care sa "l sorte$e' Eentru a
ordona fisierul $persoane.t/t$ lansarea aplicatiei se va face astfel)
+ava Sort persoane.t/t
;sadar# formatul !eneral pentru lansarea unei aplicatii care primeste ar!umente de la linia de comanda
este)
java Numeplicatie [arg! arg" . . . argn]
In ca$ul "n care sunt mai multe# ar!umentele trebuie separate prin spatii iar daca unul dintre ar!umente
contine spatii# atunci el trebuie pus "ntre !hilimele' Avident# o aplicatie poate sa nu primeasca nici un
ar!ument sau poate sa i!nore ar!umentele primite de la linia de comanda'
In momentul lansarii unei aplicatii interpretorul parcur!e linia de comanda cu care a fost lansata aplicatia
si# "n ca$ul "n care exista# transmite aplicatiei ar!umentele specificate sub forma unui vector de siruri'
;cesta este primit de aplicatie ca parametru al metodei main' >eamintim ca formatul metodei main din
clasa principala este)
public static void main ( String args[])
Vectorul primit ca parametru de metoda main va contine toate ar!umentele transmise pro!ramului de la
linia de comanda' In ca$ul apelului +ava Sort persoane.t/t vectorul args va contine un sin!ur
element args<!2$persoane.t/t$'
1umarul ar!umentelor primite de un pro!ram este dat deci de dimensiunea vectorului args si acesta
poate fi aflat prin intermediul atributului lengt: al vectorilor)
numarArgumente 2 args.length '
Spre deosebire ce CJC55 vectorul primit de metoda main nu contine pe prima po$itie numele aplicatiei#
"ntruc.t "n Java numele aplicatiei este numele clasei principale# adica a clasei "n care se !aseste metoda
main'
Axemplu) afisarea ar!umentelor primite la linia de comanda
public class Mc:o {
public static void main (String! args) {
6or (int i 2 <' i A args.lengt:' iDD)
S#stem.out.println(argsi!)'
)
)
-n apel de !enul +ava Mc:o SrinN %ot Java va produce urmatorul re$ultat)
SrinN
%ot
Java
3aplicatia Acho a primit = ar!umente4'
-na apel de !enul +ava Mc:o $SrinN %ot Java$ va produce urmatorul re$ultat)
SrinN %ot Java
3aplicatia Acho a primit un sin!ur ar!ument4'
0rgumente numerice la linia de comanda
;r!umentele de la linia de comanda sunt primite sub forma unui vector de siruri 3obiecte de tip String4'
In ca$ul "n care unele dintre acestea repre$inta valori numerice ele vor trebui convertite din siruri "n
numere' ;cest lucru se reali$ea$a cu metode de tipul parse### aflate "n clasa corespun$atoare tipului "n
care vrem sa facem conversia) 0nteger4 Float4 Souble4 etc'
Sa consideram# de exemplu# ca aplicatia Lo&er ridica un numar real la o putere "ntrea!a# ar!umentele
fiind trimise de la linia de comanda)
+ava Lo&er $;2.;$ $3$ --ridica ;2.; la puterea 3
Conversia celor doua ar!umente "n numere se va face astfel)
double numar'
int putere'
numar 2 Souble.parseSouble(args<!)'
putere 2 0nteger.parse0nt(args;!)'
17
%etodele de tipul parseTTT pot produce exceptii 3erori4 de tipul UumberFormatM/ception "n ca$ul "n
care sirul primit ca parametru nu repre$inta un numar de tipul respectiv'
Curs 2
Obiecte si clase in Java
Ciclul de viata al unui obiect
o Crearea obiectelor
o olosirea obiectelor
o (istru!erea obiectelor
Crearea claselor
o (eclararea claselor
o Corpul unei clase
o Constructorii unei clase
o (eclararea variabilelor membre
o Implementarea metodelor
o Specificatori de acces pentru membrii unei clase
o %embri de instanta si membri de clasa
Clase imbricate
Clase si metode abstracte
Clasa Object
Top
Ciclul de viata al unui obiect
Crearea obiectelor
In Java obiectele sunt create prin instantierea unei clase# cu alte cuvinte prin crearea unei instante a unei
clase'Crearea unui obiect presupune trei lucruri)
1' +eclararea obiectului
2. 2. Nume$lasa nume%&iect'
3. 3. M/, Pectangle patrat'
D' Instantierea
Se reali$ea$a prin intermediul operatorului new si are ca efect crearea efectiva a obiectului cu
alocarea spatiului de memorie corespun$ator'
(. (. patrat 2 ne& Pectangle()'
@' Initiali(area
Se reali$ea$a prin intermediul constructorilor clasei respective' Pectangle() este un apel catre
constructorul clasei Pectangle care este responsabil cu initiali$area obiectului' Initiali$area se
poate face si cu anumiti parametri# cu conditia sa existe un constructor al clasei respective care sa
accepte parametrii respectivi6
1. 1. patrat 2 ne& Pectangle(<4 <4 ;<<4 2<<)'
1=
iecare clasa are un set de constructori care se ocupa cu initiali$are obiectelor nou create' (e
exemplu clasa Pectangle are urmatorii constructori)
public Pectangle(Loint p)
public Pectangle(int &4 int :)
public Pectangle(Loint p4 int &4 int :)
public Pectangle()
3ve$i *Constructorii unei clase*4
(eclararea# instantierea si initiali$area obiectului pot aparea pe aceesi linie 3ca$ul cel mai u$ual4)
Pectangle patrat 2 ne& Pectangle(<4 <4 ;<<4 2<<)'
Aste posibila si crearea unor obiecte anonime care servesc doar pentru initiali$area altor obiecte# ca$ "n
care etapa de declarare a obiectului nu mai este pre$enta)
patrat.origin 2 ne& Loint(<4 <)'
--se creea5a un obiect anonim de tip Loint care4
--dupa e/ecutarea atribuirii este automat distrus de catre sistem
0tentie
Spatiul de memorie nu este pre+alocat
(eclararea unui obiect nu implica alocarea de spatiu de memorie pentru acel obiect'
Pectangle patrat'
patrat./ 2 ;<' --MP=APM>
;locarea memoriei se face doar la apelul instructiunii ne0 N
Folosirea obiectelor
Odata un obiect creat# el poate fi folosit "n urmatoarele sensuri) aflarea unor informatii despre obiect#
schimbarea starii sale sau executarea unor actiuni' ;ceste lucruri se reali$ea$a prin)
aflarea sau schimbarea valorilor variabilelor sale
apelarea metodelor sale'
>eferirea valorii unei variabile se face prin o&iect.varia&ila
(e exemplu clasa Pectangle are variabilele publice /4 #4 &idt:4 :eig:t4 origin' ;flarea valorilor
acestor variabile sau schimbarea lor se face prin constructii de !enul)
Pectangle patrat 2 ne& Pectangle(<4 <4 ;<<4 2<<)'
S#stem.out.println(patrat.&idt:)' --a6isea5a ;<<
patrat./ 2 ;<'
patrat.# 2 2<' --sc:imba originea
patrat.origin 2 ne& Loint(;<4 2<)' --sc:imba originea
Obs) ;ccesul la variabilele unui obiect se face "n conformitate cu drepturile de acces pe care le ofera
variabilele respective celorlalte clase' 3ve$i *Specificatori de acces pentru membrii unei clase*4
;pelul unei metode se face prin o&iect.metoda'[parametri](
Pectangle patrat 2 ne& Pectangle(<4 <4 ;<<4 2<<)'
patrat.setCocation(;<4 2<)' --sc:imba originea
patrat.setSi5e(2<<4 3<<)' --sc:imba dimensiunea
Se observa ca valorile variabilelor pot fi modificate indirect prin intermediul metodelor'
Ero!ramarea orientata obiect descurajea$a folosirea directa a variabilelor unui obiect deoarece acesta
poate fi adus "n stari inconsistente 3ireale4' In schimb# pentru fiecare variabila a obiectului trebui sa existe
metode care sa permita aflareaJschimbarea valorilor variabilelor sale'
patrat.&idt: 2 -;<<' --stare inconsistenta
patrat.setSi5e(-;<<4 -2<<)
--metoda setSi5e poate sa teste5e daca valorile sunt corecte si sa
--valide5e sau nu sc:imbarea lor
+istrugerea obiectelor
1D
%ulte limbaje de pro!ramare impun ca pro!ramatorul sa tina evidenta obiectelor create si sa le distru!a "n
mod explicit atunci c.nd nu mai este nevoie de ele# cu alte cuvinte sa administre$e sin!ur memoria
ocupata de obiectele sale' Eractica a demonstart ca aceasta tehnica este una din principala furni$oare de
erori ce duc la functionarea defectuoasa a pro!ramelor'
In Java pro!ramatorul nu mai are responsabilitatea distru!erii obiectelor sale "ntruc.t# "n momentul rularii
unui pro!ram# simultan cu interpretorul Java rulea$a si un proces care se ocupa cu distru!erea obiectelor
care nu mai sunt folosite' ;cest proces pus la dispo$itie de platforma Java de lucru se numeste garbage
collector 3colector de !unoi4# prescurtat gc'
-n obiect este elimnat din memorie de procesul de colectare atunci c.nd nu mai exista nici o referinta la
acesta' >eferintele 3care sun de fapt variabile4 sunt distruse "n mod )
natural# atunci c.nd variabila respectiva iese din domeniul sau# de exemplu la terminarea unei
metode
explicit# daca atribuim variabilei respective valoare null'
Cum $unctionea(a colectorul de gunoaie 5
IC este un proces de prioritate sca$uta care se executa periodic si care scanea$a dinamic memoria
ocupata de pro!ramul Java aflat "n executie si marchea$a acele obiecte care au referinte directe sau
indirecte' (upa ce toate obiectele au fost parcurse cele care au ramas nemarcate sunt eliminate din
memorie'
Erocesul !c poate fi fortat sa se execute prin metoda gc a clasei S#stem'
Finali(are
Inainte ca un obiect sa fie eliminat din memorie# procesul !c da acelui obiect posibilitatea *sa curete dupa
el*# apel.nd metoda de finali$are a obiectului respectiv' -$ual# "n timpul finali$arii un obiect "si "nchide
fisierele si socFet+urile folosite# distru!e referintele catre alte obiecte 3pentru a usura sarcina colectorului
de !unoaie4# etc' Codul pentru finali$are unui obiect trebuie scris "ntr+o metoda speciala numita 6inali5e
a clasei ce descrie obiectul respectiv'
(e exemplu# clasa Pectangle are urmatorul cod pentru finali$area obiectelor sale)
class Pectangle {
...
protected void 6inali5e() t:ro&s @:ro&able {
origin 2 null'
super.6inali5e()'
)
)
Crearea claselor
+eclararea claselor
+eclararea unei clase
public!abstract!6inal! class Nume$lasa
e/tends UumeSuperclasa!
implements 0nter6ata; 4 0nter6ata2 ... !!
{
--corpul clasei
)
;sadar# prima parte a declaratie o ocupa modificatorii clasei' ;cestia sunt)
1?
Modi$icatorii unei clase
pu&lic
Implicit# o clasa poate fi folosita doar de clasele aflate "n acelasi pachet cu clasa respectiva 3daca
nu se specifica un anume pachet# toate clasele din directorul curent sunt considerate a fi "n
acelasi pachet4'
O class declarata cu public poate fi folosita de orice clasa# indiferent de pachetul "n care se
!aseste'
a&stract
(eclara o clasa abstracta 3sablon4' O clasa abstracta nu poate fi instantiata# fiind folosita doar
pentru a crea un model comun pentru o serie de subclase6 3ve$i *Clase si metode abstracte*4
final
(eclara ca respectiva clasa nu poate avea subclase' (eclarare claselor finale are doua scopuri)
securitate ) unele metode pot astepta ca parametru un obiect al unei anumite clase si nu
al unei subclasei# dar tipul exact al unui obiect nu poate fi aflat cu exactitate dec.t "n
momentul executiei6 "n felul acesta nu s+ar mai putea reali$a obiectivul limbajului Java
ca un pro!ram care a trecut compilarea nu mai este susceptibil de nici o eroare 3nu
*crapa sistemul*4'
programare n spririt orientat-obiect ) *O clasa perfecta nu trebuie sa mai aiba subclase*
(upa numele clasei putem specifica# daca este ca$ul# faptul ca respectiva clasa este subclasa a unei alte
clase cu numele NumeSuperclasa sauJsi ca implementea$a una sau mai multe interfete# ale caror nume
trebuie separate prin vir!ula'
Se observa ca# spre deosebire de C55# Java permite doar mostenirea simpla# asadar o clasa poate avea un
sin!ur un sin!ur parinte 3superclasa4' Avident o clasa poate avea oric.ti mostenitori 3subclase4' Axtinderea
unei clase se reali$ea$a deci astfel)
class 3 e/tends A {...) --A este superclasa clasei 3
Corpul unei clase
-rmea$a declararea clasei si este cuprins "ntre acolade' Contine)
declararea variabilelor de instanta si de clasa 3cunoscute "mpreuna ca variabile membre4
declararea si implementarea metodelor de instanta si de clasa 3cunoscute "mpreuna ca metode
membre4
Spre deosebire de C55# nu este permisa doar declararea metodei "n corpul clasei# urm.nd ca
implementare sa fie facuta "n afara ei' Implementarea metodelor unei clase trebuie sa se faca *inline* in
corpul clasei'
In C66 In Java
class A {
void metoda;()'
int metoda2() {
--implementare
)
)
A,,metoda;() {
--implementare
)
class A {
void metoda(){
--implementare
)
)
Obs) variabilele unei clase pot avea acelasi nume cu metodele clasei'
1@
Constructorii unei clase
Constructorii unei clase sunt metode speciale care au acelasi nume cu cel al clasei# nu returnea$a nici o
valoare si sunt folositi pentru initiali$area obiectelor acelei clase "n momentul instantierii lor'
class Sreptung:i {
Sreptung:i() {
--constructor
)
)
O clasa poate avea unul sau mai multi constructori care trebuie "nsa sa difere prin lista de ar!umente
primite' In felul acesta sunt permise diverse tipuri de initiali$ari ale obiectului la crearea sa# "n functie de
numarul parametrilor cu care este apelat constructorul'
class Sreptung:i {
double /4 #4 &4 :'
Sreptung:i(double /<4 double #<4 double &o4 double :<) {
/2/<' #2#<' &2&<' :2:<'
)
Sreptung:i(double /<4 double #<) {
t:is(/<4 #<4 <4 <)'
)
Sreptung:i() {
--initiali5are implicita
t:is(<4 <4 ;<<4 ;<<)'
)
)
Constructorii sunt apelati automat la instantierea unui obiect' In ca$ul "n care dorim sa apelam explicit
constructorul unei clase folosim metoda this' argumente (# care apelea$a constructorul corespun$ator
3ca ar!umente4 al clasei respective' ;ceasta metoda este folosita atunci c.nd sunt implementati mai multi
constructori pentru o clasa pentru a nu repeta secventele de cod scrise la constructorii cu mai putine
ar!umente'
(intr+o subclasa putem apela si constructorii superclasei cu metoda super' argumente ('
class Latrat e/tends Sreptung:i {
double si5e'
Latrat(double /<4 double #<4 double s<) {
super(/<4 #<4 s<4 s<)' --se apelea5a constructorul superclasei
si5e 2 s<'
)
)
Constructorii sunt apelati automat la instantierea unui obiect'
In ca$ul "n care scrieti o clasa care nu are declarat nici un constructor# sistemul "i creea$a automat un
constructor implicit care nu primeste nici un ar!ument si care nu face nimic' (eci pre$enta constructorilor
"n corpul unei clase nu este obli!atorie' (aca "nsa ati scris un constructor pentru o clasa care are mai mult
de un ar!ument# atunci constructorul implicit 3fara nici un ar!ument4 nu va mai fi furni$at implicit de
catre sistem'
class Sreptung:i {
--nici un constructor
)
...
Sreptung:i d'
d2ne& Sreptung:i()' -> =V (a 6ost generat constructorul implicit)
19
class Sreptung:i {
double /4 #4 &4 :'
Sreptung:i(double /<4 double #<4 double &o4 double :<) {
/2/<' #2#<' &2&<' :2:<'
)
)
...
Sreptung:i d'
d2ne& Sreptung:i()' -> Mroare la compilare
Constructorii unei clase pot avea urmatorii specificatori de acces)
'peci$icatorii de acces ai constructorilor
private
1ici o alta clasa nu poate instantia obiecte ale acestei clase' O astfel de clasa poate contine
metode publice 3numite *factor& methods*4 care sa+si cree$e propriile obiecte si sa le returne$e
altor clase# control.nd "n felul acesta diversi parametri le!ati de creare obiectelor sale'
protected
(oar subclasele pot crea obiecte de tipul clasei respective'
pu&lic
Orice clasa poate crea instante ale clasei respective
implicit
(oar clasele din acelasi pachet pot crea instante ale clasei respective
+eclararea variabilelor membre
Variabilele se delara de obicei "naintea metodelor# desi acest lucru nu este impus de compilator'
class UumeClasa {
--declararea variabilelor
--declararea metodelor
)
Variabilele unei clase se declara "n corpul clasei dar nu "n corpul unei metode' Variabilele declarate "n
cadrul unei metode sunt locale metodei respective'
(eclararea unei variabile presupune specificarea urmatoarelor lucruri)
numele variabilei
tipul de date
nivelul de acces la acea variabila de catre alte clase
daca este constanta sau nu
daca este variabila de instanta sau de clasa
Ieneric# o variabila se declara astfel)
+eclararea variabilelor membre
modi6icatori! @ipSeSate numeQariabila 2 valoare0nitiala ! '
unde un modificator poate fi )
1:
un specificator de acces ) public4 protected4 private
3ve$i *Specificatori de acces pentru membrii unei clase*4
unul din cuvintele re$ervate) static4 6inal4 transient4 volatile
M/, double /'
protected static int n'
public String s 2 $abcd$'
private Loint p 2 ne& Loint(;<4 ;<)'
6inal long ?AT 2 ;<<<<<C'
static
(eclararea
variabilelor de
clasa
Ere$enta lui declara ca o variabila este variabila de clasa si nu de instanta)
int / ' --variabila de instanta
static int nrSe=biecteCreate' --variabila de clasa
3ve$i *%embri de instanta si membri de clasa*4
final
(eclararea
constantelor
Indica faptul ca valoarea variabilei nu mai poate fi schimbata# cu alte cuvinte este folosit
pentru declararea constantelor'
6inal double L0 2 3.;" '
...
L0 2 3.;"; -> eroare la compilare
Erin conventie numele variabilelor finale se scriu cu litere mari' olosirea lui 6inal
aduce o flexibilitate sporita "n lucrul cu constante# "n sensul ca valoarea unei variabile nu
trebuie specificata neaparat la declararea ei 3ca "n exemplul de mai sus4# ci poate fi
specificata si ulterior# dupa care ea nu va mai putea fi modificata'
class @est {
6inal int ?AT'
@est() {
?AT 2 ;<<' -- legal
?AT 2 2<<' -- ilegal -> eroare la compilare
)
)
transient
Aste folosit la seriali$area obiectelor# pentru a specifica ce variabile membre ale unui
obiect nu participa la seriali$are 3ve$i *Seriali$area obiectelor*4
volatile
Aste folosit pentru a semnala compilatorului sa nu execute anumite optimi$ari asupra
membrilor unei clase' Aste o facilitate avansata a limbajului Java'
Implementarea metodelor
%etodele sunt responsabile cu descrierea comportamentului unui obiect' Ieneric# o metoda se declara
astfel)
+eclararea metodelor membre
modi6icatori! @ipPeturnat nume?etoda ( argumente! )
t:ro&s @ipM/ceptie!
{
--corpul metodei
)
unde un modificator poate fi )
un specificator de acces ) public4 protected4 private
3ve$i *Specificatori de acces pentru membrii unei clase*4
unul din cuvintele re$ervate) static4 abstract4 6inal4 native4 s#nc:roni5ed
1<
static
(eclararea
metodelor de clasa
Ere$enta lui declara ca o metoda este metoda de clasa si nu de instanta)
void metoda;() ' --metoda de instanta
static void metoda2()' --metoda de clasa
3ve$i *%embri de instanta si membri de clasa*4
a&stract
(eclararea
metodelor abstracte
O metoda abstracta este o metoda care nu are implementare si trebuie sa faca parte
dintr+o clasa abstracta'3ve$i *Clase si metode abstracte*4
final
Specifica faptul ca acea metoda nu mai poate fi supradefinita "n subclasele clasei "n
care ea este definita ca fiind finala' 3ve$i *%etode finale*4
native
In ca$ul "n care aveti o librarie "nsemnata de functii scrise "n alt limaj de pro!ramare
dec.t Java 3C de exemplu4# acestea pot fi refolosite din pro!ramele Java'
synchroni)ed
Aste folosit "n ca$ul "n care se lucrea$a cu mai multe fire de executie iar metoda
respectiva se ocupa cu partajarea unei resurse comune' ;re ca efect construirea unui
semafor care nu permite executarea metodei la un moment dat dec.t unui sin!ur fir de
executie' 3ve$i *ire de executie*4
Tipul returnat de o metoda
%etodele pot sau nu sa returne$e o valoare 3un obiect4 la terminarea lor' Tipul returnat poate fi at.t un tip
primitiv de date 3int# double# etc'4 sau o referinta la un obiect al unei clase' In ca$ul "n care o metoda nu
returnea$a nimic atunci la rubrica TipReturnat trebuie obli!atoriu sa apara cuv.ntul cheie void' (M/,
void a6isarePe5ultat() )
(aca o metoda trebuie sa returne$e o valoare acest lucru se reali$ea$a prin intermediul instructiunii
return# care trebuie sa apara "n toate situatiile de terminare a functiei'
double radical(double /) {
i6 (radical >2 <)
return ?at:.sWrt(/)'
else
S#stem.out.println($Mroare - numar negativ>$)'
--Mroare la compilare - lipseste return pe aceasta ramura
)
In ca$ul "n care "n declaratia functiei tipul returnat este un tip primitiv de date# valoarea returnata la
terminarea functiei trebuie sa aiba obli!atoriu acel tip# altfel va fi furni$ata o eroare la compilare'
(aca valoarea returnata este o referinta la un obiect al unei clase# atunci clasa obiectului returnat rebuie sa
coincida sau sa fie o subclasa a clasei specificate la declararea metodei' (e exemplu# fie clasa Loligon si
subclasa acesteia Latrat'
Loligon metoda;( ) {
Loligon p 2 ne& Loligon()'
Latrat t 2 ne& Latrat()'
i6 (...)
return p' -- legal
else
return t' -- legal
)
Latrat metoda2( ) {
Loligon p 2 ne& Loligon()'
Latrat t 2 ne& Latrat()'
i6 (...)
return p' -- ilegal
else
return t' -- legal
)
Trimiterea parametrilor catre o metoda
Si!natura unei metode este data de numarul si tipul ar!umentelor primite de acea metoda)
metoda(tip; argument;! 4 tip2 argument2! ... )
78
Tipul de date al unui ar!ument poate fi orice tip valid al limbajului# at.t tip primitiv de date c.t si referinta
la un obiect'
M/, adaugareLersoana(String nume4 int varsta4 6loat salariu)
String este tip re6erinta4 int si 6loat sunt tipuri primitive
Spre deosebire de alte limbaje# "n Java nu pot fi trimise ca parametri ai unei metode referinte la alte
metode 3functii4# "nsa pot fi trimise obiecte care sa contina implementarea acelor metode# pentru a fi
apelate' (e asemenea# "n Java o metoda nu poat primi un numar variabil de ar!umente# ceea ce "nseamna
ca apelul unei metode trebuie sa se faca cu specificarea exacta a numarului si tipurilor ar!umentelor'
1umele ar!umentelor primite trebuie sa difere "ntre ele si nu trebuie sa coincida cu numele nici uneia din
variabilele locale ale metodei' Eot "nsa sa coincida cu numele variabilelor membre ale clasei ca$ "n care
diferentierea se va face prin intermediul variabile this'
class Cerc {
int /4 #4 ra5a'
public Cerc(int /4 int #4 int ra5a) {
t:is./ 2 /'
t:is.# 2 #'
t:is.ra5a 2 ra5a'
)
)
0tentie7 In Java ar!umentele sunt trimise doar prin valoare 3pass-by-value4
;cest lucru "nsemna ca metoda receptionea$a doar valorile variabilelor primite ca parametri' C.nd
ar!umentul are tip primitiv de date metoda nu+i poate schimba valoarea dec.t local 3"n cadrul metodei46 la
revenirea din metoda variabila are aceeasi valoare ca la apelul inittial al metodei 3modificarile facute "n
cadrul metodei sunt pierdute4'
C.nd ar!umentul este de tip referinta metoda nu poate schimba referinta obiectului "nsa poate apela
metodele acelui obiect si poate modifica orice variabila membra accesibila'
;sadar# daca dorim ca o metoda sa schimbe starea3valoarea4 unui ar!ument primit# atunci el trebuie sa fie
neaparat de tip referinta 3trebuie sa fie un obiectN4' (e exemplu# sa consideram clasa Cerc descrisa
anterior si dorim sa implementam o metoda care sa returne$e parametrii cercului)
9arianta incorecta
...
int / 2 -;4 # 2 -;4 r 2 -;'
cerc.a6laLarametri(/4 #4 r)'
S#stem.out.println($/ 2 $ D / D $4 # 2 $ D # D $4 ra5a 2 $ D r)'
. . .
In acesct scop "n clasa Cerc ar trebui sa avem o metoda de !enul)
class Cerc {
int /4 #4 ra5a'
...
public void a6laLarametri(int val/4 int val#4 int valr) {
--metoda nu 6unctionea5a cum ar trebui>
val/ 2 /'
val# 2 #'
valr 2 ra5a'
)
)
;ceasta metoda "nsa nu va reali$a lucrul propul "ntruc.t ea primeste doar valorile variabilelor /4 # si r
adica (-;4 -;4 -;) si nu referinte la ele 3adresele lor de memorie4 astfel "nc.t sa le poata modifica
valoarea' In conclu$ie# metoda nu reali$ea$a nimic pentru ca nu poate schimba valorile unor variabile
aflate "n afara corpului ei'
9arianta corecta
(efinim o clasa suplimentara care descrie parametrii pe care dorim sa+i aflam)
class CLaram {
71
public int /4 #4 ra5a'
)
class Cerc {
int /4 #4 ra5a'
public void a6laLarametri(CLaram param) {
param./ 2 /'
param.# 2 #'
param.ra5a 2 ra5a'
)
)
...
CLaram p 2 ne& CLaram()'
cerc.a6laLarametri(p)'
S#stem.out.println($/ 2 $ D p./ D $4 # 2 $ D p.# D $4 ra5a 2 $ D p.ra5a)'
'upra.ncarcarea si suprade$inirea metodelor
Sunt doua concepte extrem de utile ale EOO si se refera la)
suprancarcarea (overloaing! ) "n cadrul unei clase pot exista metode cu acelasi nume cu
conditia ca si!naturile lor sa fie diferite 3lista de ar!umente primite sa difere fie prin numarul
ar!umentelor# fie prin tipul lor4 astfel "nc.t la apelul functiei cu acel nume sa se poata stabili "n
mod unic care dintre ele se executa' enomenul de supradefinire a metodelor se mai numeste si
polimorfism'
supraefinirea (overriing!) o subclasa a unei clase poate rescrie o metoda a clasei parinte# prin
implementarea unei metode cu acelasi nume si aceeasi si!natura ca ale superclasei'
Axemplificare)
class A {
void metoda() {
S#stem.out.println($A, metoda 6ara parametru$)'
)
--supraincarcare - polimor6ism
void metoda(int arg) {
S#stem.out.println($A, metoda cu un parametru$)'
)
)
class 3 e/tends A {
--suprade6inire
void metoda() {
S#stem.out.println($3, metoda 6ara parametru$)'
)
)
O metoda supradefinita poate sa)
i!nore complet codul metodei corespun$atoare din superclasa 3ca$ul de mai sus4
3 b 2 ne& 3()'
b.metoda()' -> a6isea5a $3, metoda 6ara parametru$
sa extinda codul metodei parinte# execut.nd "nainte de codul propriu si functia parinte'
class 3 e/tends A {
--suprade6inire prin e/tensie
void metoda() {
super.metoda()'
S#stem.out.println($3, metoda 6ara parametru$)'
)
)
. . .
3 b 2 ne& 3()'
77
b.metoda()' -> a6isea5a ,
$A, metoda 6ara parametru$
$3, metoda 6ara parametru$
Metode $inale
Specifica faptul ca acea metoda nu mai poate fi supradefinita "n subclasele clasei "n care ea este definita
ca fiind finala' ;cest lucru este util daca respectiva metoda are o implementare care nu trebuie schimbata
sub nici o forma "n subclasele ei# fiind critica pentru consistenta starii unui obiect' (e exemplu studentilor
unei universitati trebuie sa li se calcule$e media finala "n functie de notele obtinute la examene "n aceeasi
maniera# indiferent de facultatea la care sunt'
class Student {
. . .
6inal 6loat calc?edie(int nrM/amene4 6loat note!4 6loat ponderi!) {
...
)
. . .
)
class Student0n6ormatica e/tends Student{
6loat calc?edie(int nrM/amene4 6loat note!4 6loat ponderi!) {
return ;<.<<'
)
)--eroare la compilare>
'peci$icatori de acces pentru membrii unei clase
Sunt cuvinte re$ervate ce controlea$a accesul celorlate clase la membrii unei clasei' Specificatorii de
acces pentru variabilele si metodele unei clase sunt) public4 protected4 private si cel implicit
3pacNage4# iar nivelul lor de acces este dat "n tabelul de mai jos)
'peci$icator Clasa 'ubclasa Pac%et Toti
private 2
protected 2 2KK 2
public 2 2 2 2
pacFa!eK 2 2
Axemple de declaratii)
private int secretLersonal'
proteceted String secretSeFamilie'
public Qector elemente'
long doar0ntreLrieteni ' -> pacNage
private void metoda0nterna()'
public double calculea5aPe5ultat()'
Obs13K4) (aca nu este specificat nici un modificator de acces# implicit nivelul de acces este la nivelul
pachetului 3pacFa!e4' ;sadar# modificatorul *pacFa!e* nu apare explicit "n declararea unei
variabileJmetode 3"n ca$ul "n care apare# compilatorul va furni$a o eroare4'
Obs73KK4) In ca$ul "n care declaram un membru *protected* atunci accesul la acel membru din subclasele
clasei "n care a fost declarata variabila depinde si de pachetul "n care se !aseste subclasa) daca sunt "n
acelasi pachet accesul este permis# daca nu sunt "n acelasi pachet accesul nu este permis dec.t pentru
obiecte de tipul subclasei'
7=
Membri de instanta si membri de clasa
O clasa Java poate contine doua tipuri de variabile si metode )
e instanta) declarate $ara modificatorul static# specifice fiecarei instante si
e clasa) declarate cu modificatorul static# specifice clasei
9ariabile
C.nd declarati o variabila membra cum ar fi / "n exemplul de mai jos)
class ?#Class {
int / ' --variabila de instanta
)
se declara de fapt o variabila de instanta# cee ce "nsemna ca la fiecare creare a unei instante a clasei
?#Class sistemul aloca o $ona de memorie separata pentru memorarea valorii lui x'
?#Class o; 2 ne& ?#Class()'
o;./ 2 ;<<'
?#Class o2 2 ne& ?#Class()'
o2./ 2 2<<'
S#stem.out.println(o;./) -> a6isea5a ;<<
S#stem.out.println(o2./) -> a6isea5a 2<<
;sadar# fiecare obiect nou creat va putea memora valori diferite pentru variabilele sale de instanta'
Eentru variabilele de clasa 3statice4 sistemul aloca o sin!ura $ona de memorie la care au acces toate
instantele clasei respective# ceea ce "nseamna ca daca un obiect modifica valoarea unei variabile statice ea
se va modifica si pentru toate celelate obiecte'
class ?#Class {
int / ' --variabila de instanta
static long n' --variabila de clasa
)
. . .
?#Class o; 2 ne& ?#Class()'
?#Class o2 2 ne& ?#Class()'
o;.n 2 ;<<'
S#stem.out.println(o2.n) -> a6isea5a ;<<
o2.n 2 2<<'
S#stem.out.println(o;.n) -> a6isea5a 2<<
Metode
Similar ca la variabile# metodele declarate fara modificatorul static sunt metode de instanta iar cele
declarate cu static sunt metode de clasa 3statice4' (iferenta "ntre cele doua metode este urmatoarea)
metodele de instanta operea$a at.t pe variabilele de instanta c.t si pe cele statice ale clasei
metodele de clasa operea$a doar pe variabilele statice ale clasei
class ?#Class {
int / ' --variabila de instanta
static long n' --variabila de clasa
void metodaSe0nstanta() {
n DD' --legal
/ --' --legal
static void metodaStatica() {
n DD' --legal
/ --' --ilegal
)
Intruc.t metodele de clasa nu depind de starea obiectelor clasei respective# apelul lor se poate face astfel)
?#Class.metodaStatica()' --legal4 ec:ivalent cu
?#Class ob+ 2 ne& ?#Class()'
ob+.metodaStatica()' --legal
spre deosebire de metodele de instanta care nu pot fi apelate dec.t unei instante a clasei respective)
?#Class.metodaSe0nstanta()4 --ilegal
?#Class ob+ 2 ne& ?#Class()'
7D
ob+.metodaSe0nstanta()' --legal
:tilitatea membrilor de clasa statici"
Sunt folositi pentru a pune la dispo$itie valori si metode independente de starea obiectelor dintr+o anumita
clasa'
1' +eclararea constantelor
2. 2. class ?#Class {
3. 3. 6inal double L0 2 3.;"' --variabila 6inala de instanta
". ". )
La fiecare instantiere a clasei ?#Class va fi re$ervata $ona de memorie pentru variabilele finale
ale obiectului respectiv# ceea ce este o risipa "ntruc.t aceste constante au aceleasi valori pentru
toate instantele clasei' (eclararea corecta a constantelor trebuie asadar facuta cu modificatorii
static si final# pentru a le re$erva o sin!ura $ona de memorie# comuna tuturor obiectelor)
class ?#Class {
static 6inal double L0 2 3.;"' --variabila 6inala de clasa
)
?' ;umararea obiectelor unei clase
*. *. class ?#Class {
1. 1. static long nr0nstante 2 <'
7. 7. ?#Class() { --constructorul este apelat la 6iecare
instantiere
8. 8. nr0nstante DD'
;<. ;<. )
;;. ;;. )
olosind variabile statice putem controla diversi parametri le!ati de crearea obiectelor unei clase
17' Implementarea $unctiilor globale
Spre deosebire de C55# "n Java nu putem avea functii !lobale definite ca atare# "ntruc.t *orice este
un obiect*' (in acest motiv si metodele care au o functionalitate !lobala trebuie implementate "n
cadrul unei clase' ;cest lucru se va face prin intermediul metodelor de clasa 3!lobale4# deoarece
acestea nu depind de starea particulara a obiectelor din clasa respectiva' (e exemplu# sa
consideram functia !lobala sWrt care extra!e radicalul unui numar si care se !aseste "n clasa
?at:' (aca nu ar fi fost functie de clasa# apelul ei ar fi trebuit facut astfel 3incorect# de altfel4)
;3. ;3. ?at: ob+ 2 ne& ?at:()'
;". ;". double rad;2; 2 ob+.sWrt(;2;)'
ceea ce ar fi fost extrem de neplacut pentru pro!ramatori' iind "nsa functie statica ea poate fi
apelata prin) ?at:.sWrt(;2;) '
Initiali(area variabilelor de clasa
Se poate face "n momentul declararii lor )
class ?#Class {
static 6inal double L0 2 3.;"'
static long nr0nstante 2 <'
static 6inal double MLS 2 <.<;'
)
sau prin intermediul unui bloc static e initiali"are)
class ?#Class {
7?
static {
6inal double L0 2 3.;"'
long nr0nstante 2 <'
6inal double MLS 2 <.<;'
)
)
Clase imbricate
O clasa imbricata este# prin definitie# o clasa membra a unei alte clase
class ClasaSeAcoperire{
. . .
class Clasa0mbricata {
. . .
)
)
olosirea claselor imbricate se face atunci c.nd o alta clasa are nevoie "n implementarea ei de o
alta clasa si nu exista nici un motiv pentru care clasa imbricata sa fie declarata de sine statatoare
3nu mai este folosita nicaieri4'
public class Lac:et { --clasa de acoperire
class Continut { --clasa imbricata
private String mar6a'
private 6loat cantitate'
Continut (String mar6a4 6loat cantitate) {
t:is.mar6a 2 mar6a'
t:is.cantitate 2 cantitate'
)
)
class Sestinatie { --clasa imbricata
private String dest'
private int termen'
Sestinatie(String undeLleaca4 int inCateXile) {
dest 2 undeLleaca'
termen 2 inCateXile'
)
)
public void trimite(String mar6a4 6loat cant4 String dest4
int termen) {
Continut c 2 ne& Continut(mar6a4 cant)'
Sestinatie d 2 ne& Sestinatie(dest4 termen)'
)
public static void main(String! args) {
Lac:et p 2 ne& Lac:et()'
p.trimite($banane$4 ;<<4 $Pomania$4 1)'
)
)
Ca membra a unei clase# o clasa imbricata are un privile!iu special fata de celelalte clase) acces
nelimitat la variabilele clasei de acoperire# chiar daca acestea sunt private'
Clase interne
7@
Ca orice alta clasa o clasa imbricata poate fi declarata statica sau nu' O clasa imbricata nestatica se
numeste clasa interna'
class ClasaSeAcoperire{
. . .
static class Clasa0mbricataStatica {
. . .
)
class Clasa0nterna {
. . .
)
)
(iferentierea acestor denumiri se face deoarece)
o o *clasa imbricata* reflecta relatia sintactica a doua clase6 codul unei clase apare "n
interiorul dodului altei clase6
o o *clasa interna* reflecta relatia dintre instantele a doua clase# "n sensul ca o instanta a unei
clase interne nu poate exista dec.t "n cadrul unei instante a clasei de acoperire'
In !eneral cele mai folosite clase imbricate sunt clasele interne
;sadar# o clasa interna este o clasa imbricata ale carei instante nu pot exista dec.t "n cadrul
instantelor clasei de acoperire si care are acces direct la toti membrii clasei sale de acoperire'
Identi$icarea claselor imbricate
(upa cum stim orice clasa produce la compilare asa numitele *unitati de compilare*# care sunt
fisiere av.nd numele clasei respective si extensia .class# si care contin toate informatiile despre
clasa respectiva'
Eentru clasele imbricate aceste unitati de compilare sunt denumite astfel) numele clasei de
acoperire# urmat de simbolul ,O, apoi de numele clasei imbricate'
class ClasaSeAcoperire{
class Clasa0nterna; {)
class Clasa0nterna2 {)
)
Eentru exemplul de mai sus vor fi !enerate trei fisiere)
ClasaSeAcoperire.class
ClasaSeAcoperireYClasa0nterna;.class
ClasaSeAcoperireYClasa0nterna2.class
In ca$ul "n care clasele imbricate au la r.ndul lor alte clase imbricate 3situatie mai putin u$uala4
denumirea lor se face dupa aceeasi metoda ) adau!area unui ,O, si apoi numele clasei imbricate'
Clase si metode abstracte
-neori "n proiectarea unei aplicatii este necesar sa repre$entam cu ajutorul claselor concepte
abstracte care sa nu poata fi instantiate si care sa foloseasca doar la de$voltarea ulterioara a unor
clase ce descriu obiecte concrete' (e exemplu "n pachetul +ava.lang exista clasa abstracta
Uumber care modelea$a conceptul !eneric de *numar*' Intr+un pro!ram nu avem "nsa nevoie de
numere !enerice ci de numere "ntre!i# reale# etc' Clasa Uumber serveste ca superclasa pentru clase
cum ar fi 3#te4 Souble4 Float4 0nteger4 Cong si S:ort ce implementea$a obiecte pentru
79
descrierea numerelor de un anumit tip' ;sadar clasa Uumber repre$inta un concept abstract si nu
vom putea instantia obiecte de acest tip)
Uumber numar9eneric 2 ne& Uumber()' --eroare
+eclararea unei clase abstracte
Se face folosind cuv.ntul re$ervat a&stract "n declaratia clasei)
abstract class ClasaAbstracta {
. . .
)
(aca vom "ncerca sa instantiem un obiect al clasei ClasaAbstracta vom obtine o eroare la
compilarea pro!ramului de !enul)class ClasaAbstracta is an abstract class. 0t canRt
be instantiated'
Metode abstracte
Spre deosebire de clasele obisnuite care trebuie sa furni$e$e implementari pentru toate metodele
declarate o clasa abstracta poate contine metode fara nici o implementare' %etodele fara nici o
implementare se numesc metode abstracte si pot aparea doar "n clase abstracte'
In fata unei metode abstracte trebuie sa apara cuv.ntul cheie abstract# altfel va fi furni$ata o
eroare de compilare'
abstract void metodaAbstracta()' --corect
void metoda()' --incorect
(?et:od metoda reWuires a met:od bod#' ot:er&is& declare it abstract)
In felul acesta o clasa abstracta poate pune la dispo$itia subclaselor sale un model complet pe care
trebuie sa+l implemente$e# furni$.nd chiar implementarea unor metode comune tuturor claselor
sau las.nd explicitarea unor metode fiecarei subclase "n parte'
-n exemplu elocvent de folosire a claselor si metodelor abstracte este descrierea obiectelor !rafice
"ntr+o maniera orientata+obiect'
o Obiecte !rafice ) linii# dreptun!hiuri# cercuri# curbe He$ier# etc
o Stari comune ) po$itia3ori!inea4# dimensiunea# culoarea# etc
o Comportament ) mutare# redimensionare# desenare# colorare# etc'
Eentru a folosi starile si comportamentele comune acestor obiecte "n avantajul nostru putem
declara o clasa !enerica 9rap:ic=b+ect care sa fie superclasa pentru celelalte clase'
%etodele abstracte vor fi folosite pentru implementarea comportamentului specific fiecarui obiect#
cum ar fi desenarea iar cele obisnuite pentru comportamentul comun tuturor# cum ar fi schimbarea
ori!inii'
Implementarea clasei abstracte IraphicObject)
7:
abstract class 9rap:ic=b+ect {
int /4 #'
. . .
void move@o(int ne&T4 int ne&Z) { --metoda normala
. . .
)
abstract void dra&()' --metoda abstracta
) --nici o
implementare
;tentie) Orice subclasa non+abstracta a unei clase abstracte trebui sa furni$e$e implementari ale
metodelor abstracte din superclasa'
Implementarea claselor pentru obiecte !rafice ar fi)
class Circle e/tends 9rap:ic=b+ect {
void dra&() {
. . . --obligatoriu implementarea
)
)
class Pectangle e/tends 9rap:ic=b+ect {
void dra&() {
. . . --obligatoriu implementarea
)
)
Observatii)
O clasa abstracta poate sa nu aiba nici o metoda abstracta'
O metoda abstracta nu poate aparea dec.t "ntr+o clasa abstracta'
Orice clasa care are o metoda abstracta trebuie declarata ca fiind abstracta'
Clasa Ob4ect
Orice clasa are o superclasa
(upa cum am va$ut la crearea unei clase clau$a *extends* specifica faptul ca acea clasa este o
subclasa a altei clase# numita superclasa' O clasa poate avea o sin!ura superclasa 3Java nu suporta
mostenirea multipla4 si chiar daca nu specificati clau$a *extends* la crearea unei clase ea totusi va
avea o superclasa' Cu alte cuvinte# in Java orice clasa are o superclasa si numai una'
Superclasa tuturor celorlalte clase este clasa %&ject# care este radacina ierarhiei de clase "n Java'
Clasa =b+ect este si superclasa implicita a claselor care nu specifica o alta superclasa' (eclaratia
class ?#Class {) este echivalenta cu class ?#Class e/tends =b+ect {)'
7<
Clasa Ob4ect
Aste cea mai !enerala dintre clase# orice obiect fiind# direct sau indirect# descendent al acestei
clase' (efineste si implementea$a comportamentul comun al tuturor claselor Java cum ar fi)
o posibilitatea compararii obiectelor "ntre ele
o specificarea unei repre$entari ca sir de caractere a unui obiect
o returnarea clasei din care face parte un obiect
o notificarea altor obiecte ca o variabila de conditie s+a schimbat# etc
iind sublcasa a lui =b+ect# orice clasa poate supradefini metodele clasei =b+ect care nu sunt
finale' %etode care pot fi supradefinite sunt) clone* e+uals,hash$ode* finali)e *toString
clone
;cesasta metoda este folosita pentru duplicarea obiectelor 3creearea unor clone4'
Clonarea unui obiect presupune crearea unui nou obiect de acelasi tip si care sa aiba
aceeassi stare 3aceleasi valori pentru variabilele sale4
e+uals4
hash$ode
;ceste metode trebuie supradefinite "mpreuna' In metoda eWuals este scris codul
pentru compararea a doua obiecte' Implicit 3implementarea din clasa Object4 aceasta
metoda compara referintele obiectelor' -$ual este redefinita pentru a testa daca starile
obiectelor coincid sau daca doar o parte din variabilele lor coincid'
%etoda :as:Code returnea$a un cod "ntre! pentru fiecare obiect pentru a testa
consistenta obiectelor) acelasi obiect trebuie sa returne$e acelasi cod pe durata
executiei pro!ramului' (aca doua obiecte sunt e!ale conform metodei eWuals atunci
apelul metodei :as:Code pentru fiecare din cele doua obiecte trebuie sa returne$e
acelasi "ntre!'
finali)e
In aceasta metoda se scrie codul care *curata dupa un obiect* "nainte de a fi eliminat
din memorie de colectorul de !unoaie'3ve$i *(istru!erea obiectelor*4
toString
Aste folosita pentru a returna o repre$entare ca sir de caractere a unui obiect' Aste utila
pentru concatenarea sirurilor cu diverse obiecte "n vederea tiparirii'
?#=b+ect ob+ 2 ne& ?#=b+ect()'
S#stem.ot.println($=biect2$ D ob+)' --ec:ivalent cu
S#stem.ot.println($=biect2$ D ob+.toString())'
Exemplu de suprade$inire a metodelor clasei %&ject
class ?#=b+ect e/tends =b+ect {
--clasa in care este suprade6inita metoda eWuals
public int /'
public boolean eWuals(=b+ect ob+) {
i6 (ob+ 22 null) return 6alse'
i6 (>(ob+ instanceo6 ?#=b+ect)) return 6alse'
i6 ( ((?#=b+ect) ob+)./ 22 /)
return true'
else
return 6alse'
)
public s#nc:roni5ed =b+ect clone() {
?#=b+ect m 2 ne& ?#=b+ect()'
m./ 2 /'
return m'
)
public 6inal s#nc:roni5ed String toString() {
return $$ D / D $!$'
)
public void 6inali5e() {
S#stem.out.println($Finali5are$)'
=8
/ 2 -;'
)
)
class =t:er=b+ect {
public int /'
--clasa in care U[ este suprade6inita metoda eWuals
)
class @est=b+ect { --clasa principala - contine metoda main
public static void main(String args!) {
=t:er=b+ect o; 2 ne& =t:er=b+ect()'
=t:er=b+ect o2 2 ne& =t:er=b+ect()'
o;./ 2 ;'
o2./ 2 ;'
i6 (o;.eWuals(o2))
S#stem.out.println($test;, o; 22 o2$)'
else
S#stem.out.println($test;, o; >2 o2$)'--corect
--Sesi /2; pt ambele obiecte egalitatea se obtine doar cand
--adresele lor de memorie coincid deoarece nu este implementata
--metoda eWuals
o2 2 o;'
i6 (o;.eWuals(o2))
S#stem.out.println($test2, o; 22 o2$)'--corect
else
S#stem.out.println($test2, o; >2 o2$)'
----------------------------------------------
?#=b+ect m; 2 ne& ?#=b+ect()'
?#=b+ect m2 2 ne& ?#=b+ect()'
m;./ 2 ;'
m2./ 2 ;'
i6 (m;.eWuals(m2))
S#stem.out.println($test3, m; 22 m2$)'--corect
else
S#stem.out.println($test3, m; >2 m2$)'
--/2; pt ambele obiecte -> metoda eWuals returnea5a true
?#=b+ect m3'
m3 2 (?#=b+ect) m;.clone()'
S#stem.out.println($=biectul clonat, $ D m3)' --ec:ivalent cu
S#stem.out.println($=biectul clonat, $ D m3.toString())'
--Se tipareste, =biectul clonat, ;!
)
)
Curs 3
Exceptii
Ce sunt exceptiile ?
;vantajele exceptiilor
*Erinderea* si tratarea exceptiilor 3Instructiunile tr#-catc:-6inall# 4
*;runcarea* exceptiilor 3Clau$a t:ro&s # Instructiunea t:ro& 4
Ierarhia claselor ce descriu exceptii 3Clasa @:ro&able 4
Axceptii la executie
Crearea propriilor exceptii
=1
Top
Ce sunt exceptiile5
Termenul exceptie este o prescurtare pentru *eveniment exceptional* si poate fi definit astfel)
+e$initie
O exceptie este un eveniment ce se produce "n timpul executiei unui pro!ram si care provoaca
"ntreruperea cursului normal al executiei'
Axceptiile pot aparea din diverse cau$e si pot avea nivele diferite de !ravitate) de la erori fatale cau$ate de
echipamentul hard0are p.na la erori ce tin strict de codul pro!ramului# cum ar fi accesarea unui element
din afara spatiului alocat unui vector' In momentul c.nd o asemenea eroare se produce "n timpul executiei
sistemul !enerea$a automat un obiect de tip exceptie ce contine)
informatii despre exceptia respectiva
starea pro!ramului "n momentul producerii acelei exceptii
public class M/ceptii {
public static void main(String argsst) {
int v! 2 ne& int;<!'
v;<! 2 <' --e/ceptie4 vectorul are elementele v<!...v8!
S#stem.out.println($Aici nu se mai a+unge...$)'
)
)
La rularea pro!ramului va fi !enerata o exceptie si se va afisa mesajul )
M/ception in t:read $main$ +ava.lang.Arra#0nde/=ut=63oundsM/ception ,;<
at M/ceptii.main (M/ceptii.+ava,")
Crearea unui obiect de tip exceptie se numeste aruncarea unei exceptii 3*thro0in! an exception*4' In
momentul "n care o metoda !enerea$a o exceptie 3arunca o exceptie4 sistemul de executie este responsabil
cu !asirea unei secvente de cod dintr+o metoda care sa trate$e acea exceptie' Cautarea se face recursiv#
"ncep.nd cu metoda care a !enerat exceptia si mer!.nd "napoi pe linia apelurilor catre acea metoda'
Secventa de cod dintr+o metoda care tratea$a o anumita exceptie se numeste anali"or e exceptie
3*exception handler*4 iar interceptarea si tratarea exceptie se numeste prinerea exceptiei 3*catch the
exception*4'
Cu alte cuvinte la aparitia unei erori este *aruncata* o exceptie iar cineva trebuie sa o *prinda* pentru a o
trata' (aca sistemul nu !aseste nici un anali$or pentru o anumita exceptie atunci pro!ramul Java se
opreste cu un mesaj de eroare 3"n ca$ul exemplului de mai sus mesajul *;ici nu se mai ajun!e'''* nu va fi
tiparit4'
0tentie7 In Java tratarea erorilor nu mai este o optiune ci o constr.n!ere' Orice cod care poate provoca
exceptii trebui sa specfice modalitatea de tratare a acestora'
0vanta4ele exceptiilor
Erin modalitatea sa de tratare a exceptiilor Java are urmatoarele avantaje fata de mecanismul traditional
de tratare a erorilor)
1' Separarea codului pentru tratarea unei erori de codul "n care ea poate sa apara
7' Eropa!area unei erori p.na la un anali$or de exceptii corespun$ator
=' Iruparea erorilor dupa tipul lor
=7
'epararea codului pentru tratarea unei erori de codul .n care ea poate sa apara
In pro!ramarea traditionala tratarea erorilor se combina cu codul ce poate produce aparitia lor conduc.nd
la ada numitul *cod spa!hetti*' Sa consideram urmatorul exemplu) o functie care "ncarca un fisier "n
memorie)
citesteFisier {
desc:ide 6isierul'
determina dimensiunea 6isierului'
aloca memorie'
citeste 6isierul in memorie'
inc:ide 6isierul'
)
Eroblemele care pot aparea la aceasta functie# aparent simpla sunt de !enul) *Ce se "nt.mpla daca) ''' ?*
fisierul nu poate fi deschis
nu se poate determina dimensiunea fisierului
nu poate fi alocata suficienta memorie
nu se poate face citirea din fisier
fisierul nu poate fi "nchis
-n cod traditional care sa trate$e aceste erori ar arata astfel)
int citesteFisier {
int codMroare 2 <'
deschide fisier'
i6 (6isierul s-a desc:is) {
determina dimensiunea fisierului'
i6 (s-a determinat dimensiunea) {
aloca memorie'
i6 (s-a alocat memorie) {
citeste fisierul in memorie'
i6 (nu se poate citi din 6isier) {
codMroare 2 -;'
)
) else {
codMroare 2 -2'
)
) else {
codMroare 2 -3'
)
inchide fisierul'
i6 (6isierul nu s-a inc:is FF codMroare 22 <) {
codMroare 2 -"'
) else {
codMroare 2 codMroare F -"'
)
) else {
codMroare 2 -('
)
return codMroare'
)--cod $spag:etti$
;cest stil de pro!amare este extrem de susceptibil la erori si "n!reunea$a extrem de mult "ntele!erea sa'
In Java# folosind mecansimul exceptiilor# codul ar arata astfel)
int citesteFisier {
try {
desc:ide 6isierul'
determina dimensiunea 6isierului'
aloca memorie'
citeste 6isierul in memorie'
inc:ide 6isierul'
)
catch (6isierul nu s-a desc:is) {tratea5a eroarea')
catch (nu s-a determinat dimensiunea) {tratea5a eroarea')
catch (nu s-a alocat memorie) {tratea5a eroarea )
catch (nu se poate citi dun 6isier) {tratea5a eroarea')
==
catch (nu se poate inc:ide 6isierul) {tratea5a eroarea')
)
Propagarea unei erori p<na la un anali(or de exceptii corespun(ator
Sa presupunem ca apelul la metoda citesteisier este consecinta unor apeluri imbricate de metode)
int metoda; {
apel metoda2'
. . .
)
int metoda2 {
apel metoda3'
. . .
)
int metoda3 {
apel citesteFisier'
. . .
)
Sa presupunem de asemenea ca dorim sa facem tratarea erorilor doar "n metoda;' Traditional# acest lucru
ar trebui facut prin propa!area erorii "ntoarse de metoda citesteFisier p.na la metoda;'
int metoda; {
int codMroare 2 apel metoda2'
i6 (codMroare >2 <)
procesea5aMroare'
. . .
)
int metoda2 {
int codMroare 2 apel metoda3'
i6 (codMroare >2 <)
return codMroare'
. . .
)
int metoda3 {
int codMroare 2 apel citesteFisier'
i6 (codMroare >2 <)
return codMroare'
. . .
)
Java permite unei metode sa arunce exceptiile aparute "n cadrul ei la un nivel superior# adica functiilor
care o apelea$a sau sistemului' Cu alte cuvinte o metoda poate sa nu "si asume responsabilitatea tratarii
exceptiilor aparute "n cadrul ei)
metoda; {
tr# {
apel metoda2'
)
catc: (e/ceptie) {
procesea5aMroare'
)
. . .
)
metoda2 throws e/ceptie{
apel metoda3'
. . .
)
metoda3 throws e/ceptie{
apel citesteFisier'
. . .
)
=ruparea erorilor dupa tipul lor
In Java exista clase corespun$atoare tuturor exceptiilor care pot aparea la executia unui pro!ram' ;cestea
sunt !rupate "n functie de similaritatile lor "ntr+o ierarhie de clase' (e exemplu# clasa 0=M/ception se
ocupa cu exceptiile ce pot aparea la operatii de intrareJiesire si diferentia$a la r.ndul ei alte tipuri de
=D
exceptii# cum ar fi FileUotFoundM/ception# M=FM/ception# etc'
La r.ndul ei clasa 0=M/ception se "ncadrea$a "ntr+o cate!orie mai lar!a de exceptii si anume clasa
M/ception' >adacina acestei ierarhii este clasa @:ro&able 3ve$i *Ierarhia claselor ce descriu exceptii*4'
Interceptarea unei exceptii se poate face fie la nivelul clasei specifice pentru acea exceptie fie la nivelul
uneia din superclasele sale# "n functie de necesitatile pro!ramului)
tr# {
FilePeader 6 2 ne& FilePeader($input.dat$)'
--acest apel poate genera e/ceptie de tipul
FileUotFoundM/ception
--tratarea ei poate 6i 6acuta in unul din modurile de mai +os
)
catc: (FileUotFoundM/ception e) {
--e/ceptie speci6ica provocata de absenta 6isierului
Rinput.datR
) --sau
catc: (0=M/ception e) {
--e/ceptie generica provocata de o operatie de intrare-iesire
) --sau
catc: (M/ception e) {
--cea mai generica e/ceptie - UMPMC=?AUSA@A>
)
>Prinderea> si tratarea exceptiilor
Tratarea exceptiilor se reali$ea$a prin intermediul blocurilor de instructiuni try* catch si finally. =
secventa de cod care tratea5a anumite e/ceptii trebuie sa arate ast6el,
try {
0nstructiuni care pot genera o e/ceptie
)
catch (@ipM/ceptie; ) {
Lrelucrarea e/ceptiei de tipul ;
)
catch (@ipM/ceptie2 ) {
Lrelucrarea e/ceptiei de tipul 2
)
. . .
finally {
Cod care se e/ecuta indi6erent daca apar sau nu e/ceptii
)
Sa consideram urmatorul e/emplu , citirea unui 6isier si a6isarea lui pe ecran. Fara
a 6olosi tratarea e/ceptiilor codul programului ar arata ast6el,
--MP=UA@>
import +ava.io..'
public class CitireFisier {
public static void citesteFisier() {
File0nputStream sursa 2 null' --s este 6lu/ de intrare
int octet'
sursa 2 ne& File0nputStream($6isier.t/t$)'
octet 2 <'
--citesc 6isierul caracter cu caracter
&:ile (octet >2 -;) {
octet 2 sursa.read()'
S#stem.out.print((c:ar)octet)'
)
sursa.close()'
)
public static void main(String args!) {
=?
citesteFisier()'
)
)
Acest cod va 6urni5a erori la compilare deoarece On Java tratarea erorilor este
obligatorie.
Folosind mecanismul e/ceptiilor metoda citesteFisier Osi poate trata singura erorile
pe care le poate provoca,
--C=PMC@
import +ava.io..'
public class CitireFisier {
public static void citesteFisier() {
File0nputStream sursa 2 null' --s este 6lu/ de intrare
int octet'
tr# {
sursa 2 ne& File0nputStream($6isier.t/t$)'
octet 2 <'
--citesc 6isierul caracter cu caracter
&:ile (octet >2 -;) {
octet 2 sursa.read()'
S#stem.out.print((c:ar)octet)'
)
catc: (FileUotFoundM/ception e) {
S#stem.out.println($Fisierul nu a 6ost gasit >$)'
S#stem.out.println($M/ceptie, $ D e.get?essage())'
S#stem.e/it(;)'
)
catc: (0=M/ception e) {
S#stem.out.println($Mroare de intrare-iesire$)'
S#stem.out.println($M/ceptie, $ D e.get?essage())'
S#stem.e/it(2)'
)
6inall# {
i6 (sursa >2 null) {
S#stem.out.println($0nc:idem 6isierul...$)'
tr# {
sursa.close()'
)
catc: (0=M/ception e) {
S#stem.out.println($Fisierul poate 6i
inc:is>$)'
S#stem.out.println($M/ceptie, $ D
e.get?essage())'
S#stem.e/it(3)'
)
)
)
)
public static void main(String args!) {
citesteFisier()'
)
)
3locul $tr#$ contine instructiunile de desc:idere a unui 6isier si de citire dintr-un
6isier ambele put\nd produce e/ceptii. M/ceptiile provocate de aceste instructiuni
sunt tratate On cele doua blocuri $catc:$4 c\te unul pentru 6iecare tip de e/ceptie.
0nc:iderea 6isierului se 6ace On blocul $6inall#$4 deoarece acesta este sigur ca se
va e/ecuta. Fara a 6olosi blocul $6inall#$ Onc:iderea 6isierului ar 6i trebuit 6acuta
On 6iecare situatie On care 6isierul ar 6i 6ost desc:is4 ceea ce ar 6i dus la
scrierea de cod redundant,
tr# {
. . .
sursa.close()'
)
=@
. . .
catc: (0=M/ception e) {
. . .
sursa.close()' --cod redundant
)
tentie- =bligatoriu un bloc de instructiuni $tr#$ trebuie sa 6ie urmat de unul sau
mai multe blocuri $catc:$4 On 6unctie de e/ceptiile provocate de acele instructiuni
sau (optional) de un bloc $6inall#$
.runcarea. e/ceptiilor
0n ca5ul On care o metoda nu Osi asuma responsabilitatea tratarii uneia sau mai
multor e/ceptii pe care le pot provoca anumite instructiuni din codul sau atunci ea
poate sa $arunce$ aceste e/ceptii catre metodele care o apelea5a4 urm\nd ca acestea
sa implemente5e tratarea lor sau4 la r\ndul lor4 sa $arunce$ mai departe e/ceptiile
respective.
Acet lucru se reali5ea5a prin speci6icarea On declaratia metodei a clau5ei t:ro&s,
metoda throws @ipM/ceptie;4 @ipM/ceptie24 ... {
. . .
)
tentie- = metoda care nu tratea5a o anumita e/ceptie trebuie obligatoriu sa o
$arunce$. 0n e/emplul de mai sus daca nu 6acem tratarea e/ceptiilor On cadrul metodei
citesteFisier atunci metoda apelanta (main) va trebui sa 6aca acest lucru,
import +ava.io..'
public class CitireFisier {
public static void citesteFisier() throws FileUotFoundM/ception4 0=M/ception
{
File0nputStream sursa 2 null' --s este 6lu/ de intrare
int octet'
sursa 2 ne& File0nputStream($6isier.t/t$)'
octet 2 <'
--citesc 6isierul caracter cu caracter
&:ile (octet >2 -;) {
octet 2 sursa.read()'
S#stem.out.print((c:ar)octet)'
)
sursa.close()'
)
public static void main(String args!) {
tr# {
citesteFisier()'
)
catc: (FileUotFoundM/ception e) {
S#stem.out.println($Fisierul nu a 6ost gasit >$)'
S#stem.out.println($M/ceptie, $ D e.get?essage())'
S#stem.e/it(;)'
)
catc: (0=M/ception e) {
S#stem.out.println($Mroare de intrare-iesire$)'
S#stem.out.println($M/ceptie, $ D e.get?essage())'
S#stem.e/it(2)'
)
)
)
=bservati ca4 On acest ca54 nu mai putem di6erentia e/ceptiile provocate de citirea
din 6isier si de Onc:iderea 6isierului ambele 6iind de tipul 0=M/ception.
Aruncarea unei e/ceptii se poate 6ace si implicit prin instructiunea t:ro& ce are
6ormatul, throw obiectJdeJtipJM/ceptie .
M/emple,
t:ro& ne& 0=M/ception()'
i6 (inde/ >2 vector.lengt:)
=9
t:ro& ne& Arra#0nde/=ut=63oundsM/ception()'
catc:(M/ception e) {
S#stem.out.println($A aparut o e/ceptie)'
t:ro& e'
)
Aceasta instructune este 6olosita mai ales la aruncarea e/ceptiilor proprii care4
evident4 nu sunt detectate de catre mediul de e/ecutie. (ve5i $Crearea propriilor
e/ceptii$)
0erarhia claselor ce descriu e/ceptii
Padacina claselor ce descriu e/ceptii este clasa Thowa&le iar cele mai importante
subclase ale sale sunt Mrror4 M/ception si PuntimeM/ception4 care sunt la r\ndul lor
superclase pentru o serie Ontreaga de tipuri de e/ceptii.
$lasa 1rror
Mrorile (obiecte de tip Mrror) sunt ca5uri speciale de e/ceptii generate de
6unctionarea anormala a ec:ipamentului :ard pe care rulea5a un program Java si sunt
invi5ibile programatorilor. [n program Java nu trebuie sa trate5e aparitia acestor
erori si este improbabil ca o metoda Java sa provoace asemenea erori.
$lasa 1/ception
=biectele de acest tip sunt e/ceptiile standard care trebuie tratate de catre
programele Java. 0n Java4 tratarea e/ceptiilor nu este o optiune ci o constr\ngere.
M/ceptiile care pot $scapa$ netratate sunt Oncadrate On subclasa PuntimeM/ception si
se numesc exceptii la executie.
0n general metodele care pot 6i apelate pentru un obiect e/ceptie sunt de6inite On
clasa @:ro&able si sunt publice4 ast6el Onc\t pot 6i apelate pentru orice tip de
e/ceptie. Cele mai u5uale sunt,
String get?essage( ) tipareste detaliul unei e/ceptii
void printStacN@race( ) tipareste in6ormatii despre locali5area e/ceptiei
String toString( )
metoda din clasa =b+ect4 da repre5entarea ca sir de
caractere a e/ceptiei
1/ceptii la e/ecutie '2untime1/ception(
0n general tratarea e/ceptiilor este obligatorie On Java. Se la acest principu se
sustrag Onsa asa numitele exceptii la executie sau4 cu alte cuvinte4 e/ceptiile care
pot proveni strict din vina programatorului si nu generate de o cau5a e/terna.
Aceste e/ceptii au o superclasa comuna si anume 2untime1/ception si On acesata
categorie sunt incluse,
operatii aritmetice (Ompartire la 5ero)
=:
accesarea membrilor unui obiect ce are valoarea null
operatii cu elementele unui vector (accesare unui inde/ din a6ara
domeniului4etc)
Aceste e/ceptii pot aparea uriunde On program si pot 6i e/trem de numeroare iar
Oncercarea de $prindere$ a lor ar 6i e/trem de anevoioasa. Sin acest motiv
compilatorul permite ca aceste e/ceptii sa ram\na netratate4 tratarea lor ne6iind
Onsa ilegala.
int v! 2 ne& int;<!'
tr# {
v;<! 2 <'
) catc: (Arra#0nde/=ut=63oundsM/ception e) {
S#stem.out.println($Atentie la indecsi>$)'
e.printStacN@race()'
)--legal
$rearea propriilor e/ceptii
Adeseori poate aparea necesitatea crearii unor e/ceptii proprii pentru a pune On
evidenta ca5uri speciale de erori provocate de clasele unei librarii4 ca5uri care nu
au 6ost preva5ute On ierar:ia e/ceptiilor standard Java.
= e/ceptie proprie trebuie sa se Oncadre5e On ierar:ia e/ceptiilor Java4 cu alte
cuvinte clasa care o implementea5a trebuie sa 6ie subclasa a unei clase de+a
e/istente On aceasta ierar:ie4 pre6erabil una apropiata ca semni6icatie sau
superclasa M/ception.
class ?#M/ception e/tends M/ception {
public ?#M/ception() {)
public ?#M/ception(String msg) {
super(msg)'
--apelea5a constructorul superclasei M/ception
)
)
[n e/emplu de 6olosire a e/ceptiei nou create,
public class @est?#M/ception {
public static void 6() t:ro&s ?#M/ception {
S#stem.out.println($M/ceptie in 6()$)'
t:ro& ne& ?#M/ception()'
)
public static void g() t:ro&s ?#M/ception {
S#stem.out.println($M/ceptie in g()$)'
t:ro& ne& ?#M/ception($aruncata din g()$)'
)
public static void main(String! args) {
tr# {
6()'
) catc:(?#M/ception e) {e.printStacN@race()')
tr# {
g()'
) catc:(?#M/ception e) {e.printStacN@race()')
)
)
Fra5a c:eie este e/tends M/ception care speci6ica 6aptul ca noua clasa ?#Mception
este subclasa a clasei M/ception si deci implementea5a obiecte ce repre5inta
e/ceptii.
0n general codul adaugat claselor pentru e/ceptii proprii este nesemni6icativ, unul
sau doi constructori care a6isea5a un mesa+ de eroare la iesirea standard.
Pularea programului de mai sus va produce urmatorul re5ultat,
M/ceptie in 6()
?#M/ception()
at @est?#M/ception.6(@est?#M/ception.+ava,;2)
at @est?#M/ception.main(@est?#M/ception.+ava,2<)
=<
M/ceptie in g()
?#M/ception(), aruncata din g
at @est?#M/ception.g(@est?#M/ception.+ava,;*)
at @est?#M/ception.main(@est?#M/ception.+ava,23)
Lrocesul de creare a unei noi e/ceptii poate 6i dus mai departe prin adaugarea unor
noi metode clasei ce descrie acea e/ceptie4 Onsa aceasta de5voltare nu Osi are rostul
On ma+oritatea ca5urilor. 0n general4 e/ceptiile proprii sunt descrise de clase
6oarte simple c:iar 6ara nici un cod On ele4 cum ar 6i,
class SimpleM/ception e/tends M/ception { )
Aceasta clasa se ba5ea5a pe constructorul implicit creat de compilator Onsa nu are
constructorul SimpleM/ception(String)4 care On practica nici nu este prea des
6olosit.
Curs 3
Fluxuri Intrari ! Iesiri"
Ce sunt fluxurile ?
Clasificarea fluxurilor
Ierarhia claselor pentru lucrul cu fluxuri
o luxuri de caractere
o luxuri de octeti
%etode comune fluxurilor
olosirea fluxurilor
o luxuri pentru citireaJscrierea efectiva a datelor
o luxuri pentru procesarea datelor
o Crearea unui flux
luxuri pentru lucrul cu fisiere 3fluxuri de tip *ile*4
Conectarea fluxurilor de caractere3fluxuri de tip *Eipe*4
Citirea si scrierea cu $ona tampon
Concatenarea fisierelor 3clasa SePuenceInputStream4
luxuri pentru filtrarea datelor
o Clasele (ataInputStream si (ataOutputStream
o Scrierea propriilor fluxuri de filtrare
luxuri standard de intrareJiesire 3citirea de la tastaturaJscrierea pe ecran4
;nali$a lexicala pe fluxuri 3clasa StreamToFeni$er4
;lte clase pentru lucrul cu fisiere
o Clasa >andom;ccesile 3fisiere cu acces direct4
o Clasa ile
o Interfata ilenameilter 3filtrarea fisierelor dintr+un director4
Top
Ce sunt $luxurile5
;deseori pro!ramele necesita citirea unor informatii care se !asesc pe o sursa externa sau trimiterea unor
informatii catre o destinatie externa' Informatia se poate !asi oriunde ) "ntr+un fisier pe disc# "n retea# "n
D8
memorie sau "n alt pro!ram si poate fi de orice tip) date primitive# obiecte# ima!ini# sunete# etc' Eentru a
aduce informatii dintr+un mediu extern# un pro!am Java trebui sa deschida un canal e comunicatie (flux!
catre sursa informatiilor 3fisier# memorie# socFet#etc4 si sa citeasca serial informatiile respective)
Similar# un pro!ram poate trimite informatii catre o destinatie externa deaschi$.nd un canal de
comunicatie 3flux4 catre acea destinatie si scriind serial informatiile respective)
Indiferent de tipul informatiilor# citireaJscrierea informatiilor de peJcatre un mediu extern respecta
urmatorii al!oritmi)
Citirea 'crierea
desc:ide canal comunicatie
&:ile (mai sunt in6ormatii) {
citeste in6ormatie
)
inc:ide canal comunicati'
desc:ide canal comunicatie
&:ile (mai sunt in6ormatii) {
scrie in6ormatie
)
inc:ide canal comunicati'
Eentru a !enerali$a# at.t sursa externa a unor informatii c.t si destinatia lor sunt va$ute ca fiind niste
procese care produc# respectiv consuma informatii)
(efinitii)
-n flux este un canal de comunicatie unidirectional "ntre doua procese'
-n proces care descrie o sursa externa de date se numeste proces proucator'
-n proces care descrie o destinatie externa pentru date se numeste proces consumator'
-n flux care citeste date se numeste flux e intrare'
-n flux care scrie date se numeste flux e iesire'
Observatii)
luxurile sunt canale de comunicatie seriale pe : sau 1@ biti'
luxurile sunt unidirectionale# de la producator la consumator
iecare flux are un sin!ur proces producator si un sin!ur proces consumator
Intre doua procese pot exista oric.te fluxuri# orice proces put.nd fi at.t producator si consumator
"n acelasi timp# dar pe fluxuri diferite
Consumatorul si producatorul nu comunica direct printr+o interfata de flux ci prin intermediul
codului Java de tratare a fluxurilor
Clasele si intefetele standard pentru lucu cu fluxuri se !asesc "n pachetul java.io' (eci orice pro!ram
care necesita operatii de intrareJiesire trebuie sa contina instructiunea de import a pachetului +ava.io)
import java.io.3;
Clasi$icarea $luxurilor
Axista trei tipuri de clasificare a fluxurilor)
D1
1' (upa *directia* canalului de comunicatie deschis fluxurile se "mpart "n)
o fluxuri de intrare 3pentru citirea datelor4
o fluxuri de iesire 3pentru scrierea datelor4
7' (upa tipul de date pe care operea$a)
o fluxuri de octeti 3comunicare seriala se reali$ea$a pe : biti4
o fluxuri de caractere 3comunicare seriala se reali$ea$a pe 1@ biti4
=' (upa actiunea lor)
o fluxuri primare de citireJscriere a datelor 3se ocupa efectiv cu citireaJscrierea datelor4
o fluxuri pentru procesarea datelor
Ierar%ia claselor pentru lucrul cu $luxuri
Fluxuri de caractere
Clasele radacina pentru ierarhia claselor ce se ocupa cu fluxurile de caractere sunt >eader 3pentru
fluxuri de intrare4 si /riter 3pentru fluxuri de iesire4' ;cestea sunt superclase abstracte pentru
clase ce implementea$a fluxuri speciali$ate pentru citireaJscrierea datelor pe 1@ biti'
Ierarhia claselor pentru fluxuri de intrare pe caractere)
Ierarhia claselor pentru fluxuri de iesire pe caractere)
;u fost puse "n evidenta 3colorate cu !ri4 fluxurile care intra "n cate!oria fluxurilor pentru
procesarea datelor'
D7
Fluxuri de octeti
Clasele radacina pentru ierarhia claselor ce se ocupa cu fluxurile de octeti sunt InputStream
3pentru fluxuri de intrare4 si OutputStream 3pentru fluxuri de iesire4' ;cestea sunt superclase
abstracte pentru clase ce implementea$a fluxuri speciali$ate pentru citireaJscrierea datelor pe :
biti'
Ierarhia claselor pentru fluxuri de intrare pe octeti)
Ierarhia claselor pentru fluxuri de iesire pe octeti)
;u fost puse "n evidenta 3colorate cu !ri4 fluxurile care intra "n cate!oria fluxurilor pentru
procesarea datelor'
0tentie7 Eentru majoritatea pro!ramelor scrierea si citirea datelor se vor face prin intermediul
fluxurilor de caractere deoarece acestea permit manipularea caracterelor -nicode 31@+biti4# "n timp
ce fluxurile de octeti permit doar lucrul pe : biti + caractere ;SCII'
Metode comune $luxurilor
Superclasele abstracte >eader si InputStream definesc metode similare pentru citirea datelor'
8eader Input'tream
int read()
int read(c:ar bu6!)
int read(c:ar bu6!4 int o66set4int
lengt:)
int read()
int read(b#te bu6!)
int read(b#te bu6!4 int o66set4int
lengt:)
D=
(e asemenea ambele clase pun la dispo$itie metode pentru marcarea unei locatii "ntr+un flux#
saltul peste un numar de po$itii# resetarea po$itiei curente# etc'
Superclasele abstracte /riter si OutputStream sunt de asemenea paralele# definind metode
similare pentru scrierea datelor'
?riter Output'tream
int &rite()
int &rite(c:ar bu6!)
int &rite(c:ar bu6!4 int o66set4int
lengt:)
int &rite()
int &rite(b#te bu6!)
int &rite(b#te bu6!4 int o66set4int
lengt:)
Inchiderea oricarui flux se reali$ea$a prin metoda close' In ca$ul "n care aceasta nu este apelata
explicit fluxul va fi automat "nchis de catre colectorul de !unoaie atunci c.nd nu va mai exista nici
o referinta la el'
%etodele referitoare la fluxuri pot !enera exceptii de tipul 0%1/ception'
Folosirea $luxurilor
;sa cum am va$ut fluxurile pot fi "mpartite "n functie de activitatea lor# "n fluxuri care se ocupa
efectiv cu citireaJscrierea datelor si fluxuri pentru procesarea datelor' In continuare vom vedea
care sunt cele mai importante clase din cele doua cate!orii si la ce folosesc acestea)
Fluxuri pentru citirea!scrierea e$ectiva a datelor
Clasele ce descriu fluxuri pentru citireaJscrierea efectiva a datelor pot fi "mpartite "n functie de
tipul sursei datelor astfel)
Tip sursa Fluxuri caractere Fluxuri octeti
Memorie
$harrray2eader*
$harrray4riter
5yterray0nputStream*
5yterray%utputStream
;ceste fluxuri folosesc pentru scriereaJcitirea informatiilor "n memorie si sunt create pe un vector existent
deja' Cu alte cuvinte permit tratarea vectorilor ca sursaJdestinatie pentru crearea unor fluxuri de
intrareJiesire'
String2eader* String4riter String5uffer0nputStream
Eermit tratarea sirurilor de caractere aflate "n memorie ca sursaJdestinatie pentru crearea unor fluxuri de
intrareJiesire' Strin!>eader si Strin!/riter sunt folosite cu obiecte de tip Strin! iar
Strin!HufferInputStream cu obiecte de tip Strin!Huffer'
Pipe
6iped2eader* 6iped4riter 6iped0nputStream* 6iped%utputStream
Implementea$a componentele de intrareJiesire ale unei conducte de date 3pipe4' Eipe+urile sunt folosite
pentru a canali$a iesirea unui pro!ram sau fir de executie catre intrarea altui pro!ram sau fir de executie
Fisier
7ile2eader* 7ile4riter 7ile0nputStream* 7ile%utputStream
1umite si fluxuri fisier# acestea sunt folosite pentru citirea datelor dintr+un fisier# respectiv scrierea datelor
"ntr+un fisier 3ve$i *luxuri pentru lucrul cu fisiere*4'
Fluxuri pentru procesarea datelor
DD
Clasele ce descriu fluxuri pentru procesarea datelor pot fi "mpartite "n functie de tipul de procesare
pe care "l efectuea$a)
Tip procesare Fluxuri caractere Fluxuri octeti
>@u$$eri(are>
5uffered2eader*5uffered4riter 5uffered0nputStream*5uffered%utputStream
Sunt folosite pentru a introduce un buffer "n procesul de scriereJcitire a informatiilor# reduc.nd astfel
numarul de accese la dispo$itivul ce repre$inta sursa ori!inala de date' Sunt mult mai eficiente dec.t
fluxurile fara buffer si din acest motiv se recomanda folosirea lor ori de c.te ori eset posibil 3ve$i *Citirea
si scrierea cu $ona tampon*4'
Filtrare
7ilter2eader* 7ilter4riter 7ilter0nputStream* 7ilter%utputStream
Sunt clase abstracte ce definesc o interfata pentru fluxuri care filtrea$a automat datele citite sau scrise
3ve$i *luxuri pentru filtrare*4'
Conversie
octeti1
caractere
0nputStream2eader*
%utputStream4riter
ormea$a o punte de le!atura "ntre fluxurile de caractere si fluxurile de octeti' -n flux
InputStream>eader citeste octeti dintr+un flux InputStream ai "i converteate la caractere folosind
codificarea standard a caracterelor sau o codificare specificata de pro!ram' Similar# un flux
OutputStream/riter converteste caractere "n octeti si trimite re$utatul catre un flux de tipul
OutputStream'
Concatenare
Se+uence0nputStream
Concatenea$a mai multe fluxuri de intrare "ntr+unul sin!ur 3ve$i *Concatenarea fisierelor*4'
'eriali(are
%&ject0nputStream* %&ject%utputStream
olosite pentru seriali$area obiectelor 3ve$i *Seriali$area obiectelor*4'
Conversie
tipuri de date
8ata0nputStream* 8ata%utputStream
olosite la scriereaJcitirea datelor de tip primitiv "ntr+un format independent de masina pe care se
lucrea$a 3ve$i *olosirea claselor (ataInputStream si (ataOutputStream*4'
;umarare
9ineNum&er2eader 9ineNum&er0nputStream
1umara liniile citite de la un flux de intrare'
Citire .n avans
6ush&ac:2eader 6ush&ac:0nputStream
luxuri de intrare care au un buffer de 1+caracter3octet4 "n care este citit "n avans si caracterul 3octetul4
care urmea$a celui curent citit'
0$isare
6rint4riter 6rintStream
%etode convenabile pentru afisarea informatiilor'
Crearea unui $lux
Orice flux este un obiect al clasei ce implementea$a fluxul respectiv' Crearea unui flux se
reali$ea$a asadar similar cu crearea obiectelor prin instructiunea new'('
M/emple,
--crearea unui 6lu/ de intrare pe caractere
FilePeader in 2 ne& FilePeader($6isierJintrare.t/t$)'
--crearea unui 6lu/ de iesire pe caractere
File]riter out 2 ne& File]riter($6isierJiesire.t/t$)'
--crearea unui 6lu/ de intrare pe octeti
File0nputStream in 2 ne& File0nputStream($6isierJintrare.t/t$)'
--crearea unui 6lu/ de iesire pe octeti
File=utputStrem out 2 ne& File=utputStream($6isierJiesire.t/t$)'
;sadar# crearea unui flux primitiv de date care scrieJciteste informatii de la un dispo$itiv extern
are formatul !eneral)
D?
7lu/6rimitiv nume7lu/ = new 7lu/6rimitiv' dispo)itiv e/tern (
luxurile de procesare nu pot exista de sine statatoare ci se suprapun pe un flux primitiv de
citireJscriere a datelor' (in acest motiv constructorii claselor pentru fluxurile de procesare nu
primesc ca ar!ument un dispo$itiv extern de memorare a datelor ci o referinta la un flux primitiv
responsabil cu citireaJscrierea efectiva a datelor)
M/emple,
--crearea unui 6lu/ de intrare printr-un bu66er
3u66eredPeader in 2 ne& 3u66eredPeader(ne& FilePeader($6isier.in$))'
--ec:ivalent cu
FilePeader 6r 2 ne& FilePeader($6isier.in$)'
3u66eredPeader in 2 ne& 3u66eredPeader(6r)'
--crearea unui 6lu/ de iesire printr-un bu66er
3u66ered]riter out 2 ne& 3u66ered]riter(ne& File]riter($6isier.out$)))'
--ec:ivalent cu
File]riter 6o 2 ne& File]riter($6isier.out$)'
3u66ered]riter out 2 ne& 3u66ered]riter(6o)'
;sadar# crearea unui flux pentru procesarea datelor are formatul !eneral)
7lu/6rocesare nume7lu/ = new 7lu/6rocesare' referinta7lu/6rimitiv (
In !eneral# fluxurile pot fi !rupate "n succesiuni oric.t de lun!i)
Sata0nputStream in 2
ne& Sata0nputStream(
ne& 3u66ered0nputStream(
ne& File0nputStream($6isier.in$)))'
Fluxuri pentru lucrul cu $isiere $luxuri de tip >File>"
luxurile pentru lucrul cu fisiere sunt cele mai usor de "nteles' Clasele care implementea$a aceste
fluxuri sunt urmatoarele)
7ile2eader* 7ile4riter ; caractere
7ile0nputStream* 7ile%utputStream ; octeti
Constructorii acestor clase accepta ca ar!ument un obiect care sa specifice un anume fisier' ;cesta
poate fi un sir de caractere# on obiect de tip ile sau un obiect de tip ile(esciptor 3ve$i *Clasa
ile*4'
Constructorii clasei ile>eader)
public FilePeader( String 6ileUame ) t:ro&s FileUotFoundM/ception
public FilePeader( File 6ile ) t:ro&s FileUotFoundM/ception
public FilePeader( FileSescriptor 6d )
Constructorii clasei ile/riter)
public File]riter( String 6ileUame ) t:ro&s 0=M/ception
D@
public File]riter( File 6ile ) t:ro&s 0=M/ception
public File]riter( FileSescriptor 6d )
public File]riter( String 6ileUame4 boolean append ) t:ro&s 0=M/ception
Cei mai u$uali constructori sunt cei care primesc ca ar!ument numele fisierului' ;cestia pot
provoca exceptii de tipul FileUotFoundM/ception "n ca$ul "n care fisierul cu numele specificat
nu exista' (in acest motiv orice creare a unui flux de acest tip trebuie facuta "ntr+un bloc tr# sau
metoda "n care sunt create fluxurile respective trebuie sa arunce exceptiile de tipul
FileUotFoundM/ception sau de tipul superclasei 0=M/ception'
M/emplu, un program care copie con!inutul unui 6isier On alt 6isier,
import +ava.io..'
public class Cop# {
public static void main(String! args) t:ro&s 0=M/ception {
FilePeader in 2 ne& FilePeader($in.t/t$)'
File]riter out 2 ne& File]riter($out.t/t$)'
int c'
&:ile ((c 2 in.read()) >2 -;)
out.&rite(c)'
in.close()'
out.close()'
)
)
Obs) metoda main arunca exceptii 0=M/ception care este superclasa pentru
FileUotFoundM/ception' ;ceste exceptii nu vor *prinse* dec.t de interpretor si va fi afisat un
mesaj de eroare la aparitia lor'
Citirea si scrierea cu (ona tampon
Clasele pentru citireaJscrierea cu $ona tampon sunt)
5uffered2eader* 5uffered4riter ; caractere
5uffered0nputStream* 5uffered%utputStream ; octeti
Sunt folosite pentru a introduce un buffer "n procesul de scriereJcitire a informatiilor# reduc.nd
astfel numarul de accese la dispo$itivul ce repre$inta sursa ori!inala de date' Sunt mult mai
eficiente dec.t fluxurile fara buffer si din acest motiv se recomanda folosirea lor ori de c.te ori
este posibil'
Clasele Huffered>eader si HufferedInputStream citesc "n avans date si le memorea$a "ntr+o $ona
tampon 3buffer4' ;tunci c.nd se executa o operatie read34# octetul citit va fi preluat din buffer' In
ca$ul "n care buffer+ul este !ol citirea se face direct din flux si# odata cu citirea octetului# vor fi
memorati "n buffer si octetii care "i urmea$a'
Similar# se lucrea$a si cu clasele Huffered/riter si HufferedOutputStream'
luxurile de citireJscriere cu buffer sunt fluxuri de procesare si sunt folosite prin suprapunere cu
alte fluxuri'
M/emplu,
3u66ered=utputStream out 2 ne& 3u66ered=utputStream(
ne& File=utputStream($out.dat$)4 ;<2")
D9
Constructorii acestor clase sunt urmatorii)
5uffered2eader
3u66eredPeader( Peader in )
3u66eredPeader( Peader in4 int dimJbu66er )
5uffered4riter
3u66ered]riter( ]riter out )
3u66ered]riter( ]riter out4 int dimJbu66er )
5uffered0nputStream
3u66ered0nputStream( 0nputStream in )
3u66ered0nputStream( 0nputStream in4 int dimJbu66er )
5uffered%utputStream
3u66ered=utputStream( =utputStream out )
3u66ered=utputStream( =utputStream out4 int dimJbu66er )
In ca$ul constructorilor "n care dimensiunea buffer+ului nu este specificata# aceasta primeste
valoarea implicita de ?17 octeti'
%etodele acestor clase sunt cele u$uale de tipul read si write 3ve$i *%etode comune fluxurilor*4'
Ee l.n!a acestea# clasele pentru scriere prin buffer mai au si metoda flush care !oleste explicit
$ona tampon chiar daca aceasta nu este plina'
M/emplu,
3u66ered]riter out 2 ne& 3u66ered]riter(
ne& File]riter($out.dat$)4 ;<2")
--am creat un 6lu/ cu bu66er de ;<2" octeti
6or(int i2<' iA;<2"' iDD)
out.&rite(i)'
--bu66erul nu este plin -> in 6isier nu s-a scris nimic
out.6lus:()'
--bu66erul este golit -> datele se scriu On 6isier
Metoda read2ine
3u66eredPeader br 2 ne& 3u66eredPeader(ne& FilePeader($in$))
String input'
&:ile ((input 2 br.readCine()) >2 null) {
. . .
--readCine metoda speci6ica care citeste o linie
)
%etoda readCine permite citirea unui flux linie cu linie'
Concatenarea $isierelor
Clasa Se+uence0nputStream permite unei aplicatii sa combine serial mai multe fluxuri de intrare
astfel "nc.t acestea sa apara ca un sin!ur flux de intrare' Citirea datelor dintr+un astfel de flux se
face astfel) se citeste din primul flux de intrare specificat p.na c.nd se ajun!e la sf.rsitul acestuia#
dupa care primul flux de intrare este "nchis si se deschide automat urmatorul flux de intrare din
care se vor citi "n continuare datele# dupa care procesul se repeta p.na la terminarea tuturor
fluxurilor de intrare'
Constructorii acestei clase sunt)
SeWuence0nputStream( Mnumeratio
n e )
Construieste un flux secvential dintr+o multime de fluxuri de
intrare' iecare obiect "n enumerarea primita ca parametru
trebuie sa fie de tipul 0nputStream'
D:
SeWuence0nputStream( 0nputStrea
m s;4 0nputStream s2 )
Construieste un flux de intrare care combina doua fluxuri s1
si s7' Erimul flux citit va fi s1'
Axemplul cel mai elocvent de folosirea a acestei clase este concatenarea a doua fisiere)
--Concatenarea a 2 6isiere ale caror nume sunt primite la linia de comanda
--Pe5ultatul concatenarii este a6isat pe ecran
import +ava.io..'
public class Concatenare; {
public static void main(String args!) t:ro&s 0=M/ception {
File0nputStream 6; 2 ne& File0nputStream(args<!)'
File0nputStream 62 2 ne& File0nputStream(args;!)'
SeWuence0nputStream s 2 ne& SeWuence0nputStream(6;4 62)'
int c'
&:ile ((c 2 s.read()) >2 -;)
S#stem.out.&rite(c)'
s.close()'
--6; si 62 sunt Onc:ise automat
)--main
)--class
Eentru concatenarea mai multor fisiere exista doua variante
o folosirea unei enumerari + primul constructor
o concatenarea pe r.nd a acestora folosind al 7+lea constructor6 concatenarea a = fisiere va
construi un flux de intrare astfel)
o o File0nputStream 6; 2 ne& File0nputStream(args<!)'
o o File0nputStream 62 2 ne& File0nputStream(args;!)'
o o File0nputStream 63 2 ne& File0nputStream(args2!)'
o o SeWuence0nputStream s 2 ne& SeWuence0nputStream(
o o 6;4 ne& SeWuence0nputStream(624 63))'
Fluxuri pentru $iltrarea datelor
-n flux de filtrare se atasea$a altui flux pentru a filtra datele care sunt cititeJscrise de catre acel
flux' Clasele pentru fluxuri de filtrare au ca superclase clasele abstracte 7ilter0nputStream
3pentru filtrarea fluxurilor de intrare4 si 7ilter%utputStream 3pentru filtrarea fluxurilor de
iesire4'
Clasele pentru filtrarea datelor sunt)
8ata0nputStream* 8ata%utputStream
5uffered0nputStream* 5uffered%utputStream
9ineNum&er0nputStream
6ush&ac:0nputStream
6rintStream 'flu/ de iesire(
Observati ca toate aceste clase descriu fluxuri de octeti'
iltrarea datelor nu trebuie va$uta ca o metoda de a elimina anumiti octeti dintr+un flux ci de
D<
transforma acesti octeti "n date care sa poata fi interpretate sub alta forma'
;sa cum am va$ut la citireaJscrierea cu $ona tampon clasele de filtrare HufferedInputStream si
HufferedOutputStream !rupea$a datele unui flux "ntr+un buffer# urm.nd ca citireaJscrierea sa se
faca prin intermediu acelui buffer 3ve$i *Citirea si scrierea cu $ona tampon*4'
;sadar fluxurile de filtrare nu elimina date citite sau scrise de un anumit flux# ci introduc o noua
modalitate de manipulare a lor' (in acest motiv fluxurile de filtrare vor contine anumite metode
speciali$ate pentru citireaJscrierea datelor# altele dec.t cele comune tuturor fluxurilor 3metode de
tip readJ0rite4'
olosirea fluxurilor de filtrare se face prin atasarea lor de un flux care se ocupa efectiv de
citireaJscrierea datelor)
7lu/7iltrare nume7lu/ = new 7lu/7iltrare ' referintalt7lu/ (
Cele mai importante clase din aceasta cate!orie sunt (ataInputStream si (ataOutputStream
Clasele +ataInput'tream si +ataOutput'tream
;ceste clase ofera metode prin care un flux nu mai este va$ut ca o "nsiruire de octeti# ci ca o sursa
de date primitive' Erin urmare vor furni$a metode pentru citirea si scrierea datelor la nivel de tip
de data si nu la nivel de octet' Constructorii si metodele cele mai importante 3altele dec.t
readJ0rite4 sunt date "n tabelul de mai jos )
+ataInput'tream +ataOuput'tream
--Constructor
Sata0nputStream(0nputStream in)
--Constructor
Sata=utputStream(=utputStream out)
read3oolean( )
read3#te( )
readC:ar( )
readSouble( )
readFloat( )
read0nt( )
readCong( )
readS:ort( )
read[nsigned3#te( )
read[nsignedS:ort( )
String read[@F( )
&rite3oolean( boolean v )
&rite3#te( int v )
&riteC:ar( int v )
&riteSouble( double v )
&riteFloat( 6loat v )
&rite0nt( int v )
&riteCong( long v )
&riteS:ort( int v )
&rite3#tes( String s )
&riteC:ars( String s )
&rite[@F( String str )
;ceste metode au denumirile !enerice de read### si write### specificate de interfetele
8ata0nput si 8ata%utput' Eot provoca exceptii de tipul 0=M/ception'
0tentie7 -n fisier "n care au fost scrise informatii folosind metode 0rite222 nu va putea fi citit
dec.t prin metode read222'
Fluxuri standard de intrare!iesire
%er!.nd pe linia introdusa de sistemul de operare -1I2 orice pro!ram Java are )
o o intrare standard
o o iesire standard
?8
o o iesire standard pentru erori
In !eneral intrarea standard este tastatura iar iesirea standard este ecranul'
Intrarea si iesirea standard sunt de fapt niste obiecte pre+create ce descriu fluxuri de date pentru
citirea respectiv scrierea la dispo$itivele standard ale sistemului' ;ceste obiecte sunt definite
publice "n clasa S#stem si sunt)
9ariabila 'emni$icatie Tip $lux
S#stem.in
flux standard de intrare
0nputStream
S#stem.out
flux standard de iesire
LrintStream
S#stem.err
flux standard pentru afisarea erorilor
LrintStream
0$isarea in$ormatiilor pe ecran
;m va$ut deja numeroase exemple de folosire a fluxului standard de iesire# el fiind folosit la
afisarea oricaror re$ultate pe ecran 3"n modul consola4)S#stem.out.println($mesa+$)'
luxul standard pentru afisarea erorilor se foloseste similar)
catc: (0=M/ception e) {
S#stem.err.println($Mroare de intrare-iesire>$)
)
luxurile de iesire pot fi folosite asadar fara probleme deoarece tipul lor este LrintStream# clasa
primitiva pentru scrierea efectiva a datelor' In schimb fluxul standard de intrare S#stem.out este
de tip 0nputStream care este o clasa abstracta# deci pentru a+l putea utili$a va trebui sa+l folosim
"mpreuna cu un flux de procesare a datelor sau cu orice alt flux ce permite citirea efectiva a
datelor'
Citirea datelor de la tastatura
-$ual vom dori sa folosim metoda readCine pentru citirea datelor de la tastatura si din acest
motiv vom folosi intrarea standard "mpreuna cu o clasa de procesare care implementea$a metoda
readCine' Axemplul tipic este)
3u66eredPeader stdin 2 ne& 3u66eredPeader(ne& 0nputStreamPeader(S#stem.in))'
S#stem.out.print($0ntroduceti o linie,$)'
String linie 2 stdin.readCine()
S#stem.out.println(linie)'
Axemplu) un pro!ram care afisea$a liniile introduse de la tastatura
import +ava.io..'
public class Mc:o {
public static void main(String! args) {
3u66eredPeader stdin 2 ne& 3u66eredPeader(
ne& 0nputStreamPeader(S#stem.in))'
String s'
tr# {
&:ile((s 2 stdin.readCine()).lengt:() >2 <)
S#stem.out.println(s)'
--Lrogramul se opreste cu o linie vida
) catc:(0=M/ception e) {e.printStacN@race()')
)
)
?1
Observatie) %etoda readCine poate provoca exceptii de tipul 0=M/ception'
8edirectarea intrarii!iesirii standard
Incep.nd cu Java 1'1 au fost introduse "n clasa S&stem metode statice pentru a redirecta fluxurile
de intrare si iesire standard' ;ceste metode sunt)
set0n(0nputStream) - redirectare intrare
set=ut(LrintStream) - redirectare iesire
setMrr(LrintStream) - redirectare erori
>edirectarea iesirii este utila "n special atunci c.nd sunt afisate foarte multe date pe ecran si
acestea se derulea$a mai repede dec.t putem citi' Eutem redirecta afisarea catre un fisier pe care
sa+l citim dupa executia pro!ramului' Secventa clasica de redirectare a iesirii este)
LrintStream out 2 ne& LrintStream(ne& 3u66ered=utputStream(
ne& File=utputStream($re5ultate.out$)))'
S#stem.set=ut (out)'
>edirectarea erorilor "ntr+un fisier poate fi de asemenea utila'
LrintStream err 2 ne& LrintStream(ne& 3u66ered=utputStream(
ne& File=utputStream($erori.err$)))'
S#stem.setMrr (err)'
>edirectarea intrarii poate fi utila pentru un pro!ram consola care primeste niste valori de intrare'
Eentru a nu le scrie de la tastatura de fiecare data "n timpul testarii pro!ramului ele pot fi puse "ntr+
un fisier# redirect.nd intrarea standard' In momentul c.nd testarea pro!ramului a luat sf.rsit
redirectarea poate fi eliminata# datele fiind cerute din nou de la tastatura'
M/emplu de 6olosire a redirectarii,
import +ava.io..'
class Pedirectare {
public static void main(String! args) {
tr# {
3u66ered0nputStream in 2 ne& 3u66ered0nputStream(
ne& File0nputStream($Pedirectare.+ava$))'
LrintStream out 2 ne& LrintStream(ne&
3u66ered=utputStream(
ne& File=utputStream($test.out$)))'
S#stem.set0n(in)'
S#stem.set=ut(out)'
S#stem.setMrr(out)'
3u66eredPeader br 2 ne& 3u66eredPeader(
ne& 0nputStreamPeader(S#stem.in))'
String s'
&:ile((s 2 br.readCine()) >2 null)
S#stem.out.println(s)'
out.close()' -- Atentie>
) catc:(0=M/ception e) {
e.printStacN@race()'
)
)
)
?7
0nali(a lexicala pe $luxuri clasa StreamTo:eni)er"
Clasa Stream@oNeni5er parcur!e un flux de intrare de orice tip si "l "mparte "n *atomi lexicali*'
>e$ultatul va consta "n faptul ca "n loc sa se citeasca octeti sau caractere se vor citi# pe r.nd#
atomii lexicali ai fluxului respectiv'
Erintr+un atom lexical se "nQele!e "n !eneral)
o un identificator 3un sir care nu este "ntre !hilimele4
o un numar
o un sir de caractere
o un comentariu
o un separator
;tomii lexicali sunt despartiti "ntre ei de separatori' Implicit acesti separatori sunt cei
obisnuti3 spatiu# tab# vir!ula# punct si vir!ula4# "nsa pot fi schimbati prin diverse metode ale clasei'
Constructorii acestei clase sunt)
public Stream@oNeni5er( Peader r )
public Stream@oNeni5er( 0nputStream is )
Identificarea tipului si valorii unui atom lexical se face prin intermediul variabilelor)
@@JM=F - atom ce marc:ea5 s6\rsitul 6lu/ului
@@JM=C - atom ce marc:ea5 s6\rsitul unei linii
@@JU[?3MP - atom de tip numar
@@J]=PS - atom de tip cuv\nt
nval - valoarea unui atom numeric
sval - sirul continut de un atom de tip cuv\nt
tt#pe - tipul ultimului atom citit din 6lu/
Citirea atomilor din flux se face cu metoda ne/tTo:en'(# care returne$a tipul atomului lexical
citit si scrie "n variabilele nval sau sval valoarea corespun$atoare atomului'
Axemplul tipic de folosire a unui anali$or lexical este citirea unei secvente de numere si siruri
aflate "ntr+un fisier sau primite de la tastatura)
--Citirea unei secvente de numere si siruri
import +ava.io..'
public class @est@oNeni5er {
public static void main(String args!) t:ro&s 0=M/ception{
File0nputStream 6is 2 ne& File0nputStream($test.dat$)'
3u66eredPeader br 2 ne& 3u66eredPeader(ne& 0nputStreamPeader(6is))'
Stream@oNeni5er st 2 ne& Stream@oNeni5er(br)'
int tip 2 st.ne/t@oNen()' --citesc primul atom le/ical
&:ile (tip >2 Stream@oNeni5er.@@JM=F) {
s&itc: (tip) {
case Stream@oNeni5er.@@J]=PS , --cuvant
S#stem.out.println(st.sval)'
breaN'
case Stream@oNeni5er.@@JU[?3MP , --numar
S#stem.out.println(st.nval)'
)
tip 2 st.ne/t@oNen()'--urmatorul atom
)
)
)
?=
;sadar# modul de utili$are tipic pentru un anali$or lexical este "ntr+o bucla *0hile* "n care se
citesc atomii unul c.te unul cu metoda ne/t@oNen p.na se ajun!e la sf.rsitul fluxului 3@@JM=F4' In
cadrul buclei *0hile* se afla tipul atomul curent curent 3"ntors de metoda ne/t@oNen4 si apoi se
afla valoarea numerica sau sirul de caractere corespun$ator atomului respectiv'
-n exemplu mai simplu de folosire 3dar nepractic4 ar fi citirea unui "ntre! sau a unui sir de
caractere de la tastatura)
--Citirea unui Ontreg de la tastatura
import +ava.io..'
public class @estPead0n {
public static void main(String args!) {
tr#{
Peader r 2 ne& 0nputStreamPeader(S#stem.in)'
Stream@oNeni5er st 2 ne& Stream@oNeni5er(r)'
S#stem.out.print($n2$)'
int tip 2 st.ne/t@oNen()'
S#stem.out.println($Qaloarea lui n este $ D (int)st.nval)'
)
catc: (0=M/ception e) {)
)
)
0lte clase pentru lucrul cu $isiere
Clasa 2andomcces7ile $isiere cu acces direct"
luxurile sunt# asa cum am va$ut procese secventiale de intrareJiesire' ;cestea sunt adecvate
pentru scriereaJcitirea de pe medii secventiale de memorare a datelor cum ar fi banda
ma!netica#etc' desi sunt foarte utile si pentru dispo$itive "n care informatia poate fi accesata direct'
Clasa PandomAccesFile)
o permite accesul nesecvential 3direct4 la continutul unui fisier'
o este o clasa de sine statatoare# subclasa directa a clasei =b+ect'
o se !aseste "n pachetul +ava.io'
o implementea$a interfetele Sata0nput si Sata=utput# ceea ce "nseamna ca sunt disponibile
metode de tipul readTTT# &riteTTT 3ve$i *Clasele (ataInputStream si
(ataOutputStream*4'
o permite at.t citirea c.t si scriere dinJin fisiere cu acces direct
o permite specificarea modului de acces al unui fisier 3read+onl&# read+0rite4
Constructorii acestei clase sunt)
PandomAccessFile(String numeFisier4String modJacces) t:ro&s 0=M/ception
PandomAccessFile(String 6isier4String modJacces) t:ro&s 0=M/ception
unde modJacces poate 6i,
$r$ - 6isierul este desc:is numai pentru citire (read-onl#)
$r&$ - 6isierul este desc:is pentru citire si scriere (read-&rite)
Axemple)
PandomAccesFile 6; 2 ne& PandomAccessFile($6isier.t/t$4 $r$)'
--desc:ide un 6isier pentru citire
?D
PandomAccesFile 62 2 ne& PandomAccessFile($6isier.t/t$4 $r&$)'
--desc:ide un 6isier pentru scriere si citire
Clasa PandomAccesFile suporta notiunea de pointer e fisier' ;cesta este un indicator ce
specifica po$itia curenta "n fisier' La deschiderea unui fisier pointerul are valoarea 8# indic.nd
"nceputul fisierului' ;peluri la metode readTTT sau &riteTTT deplasea$a pointerul fisierului cu
numarul de octeti cititi sau scrisi de metodele respective'
In plus fata de metodele de citireJscriere clasa pune la dispo$itie si metode pentru controlul
po$itiei pointerului de fisier' ;cestea sunt)
int sNip3#tes ( int
n )
%uta pointerul fisierului "nainte cu un numar specificat de octeti
void seeN (long
po5itie)
Eo$itionea$a pointerului fisierului "naintea octetului specificat'
long getFileLointer
( )
>eturnea$a po$itia pointerului de fisier 3po$itia de la care se citesteJla
care se scrie4
Clasa 7ile
Clasa File are un nume "nselator# "ntruc.t ea nu se refera doar la un fisier ci poate repre$enta fie
un fisier anume# fie multimea fisierelor dintr+un director' O instanta a acestei clase poate sa
repre$inte asadar) un fisier sau un director'
Specificarea unui fisierJdirector se face prin specificare caii absolute spre acel fisier sau a caii
relative fata de directorul curent' ;cestea trebuie sa respecte conventiile de specificare a cailor si
numelor fisierelor de pe masina !a$da'
-tilitate clasei File consta "n furni$area unei modalitati de a abstracti$a dependentele cailor si
numelor fisierelor fata de masina !a$da precun si punerea la dispo$itie a unor metode pentru
lucrul cu fisere si directoare la nivelul sistemului de operare'
;stfel# "n aceasta clasa vom !asi metode pentru testarea existentei# ster!erea# redenumirea unui
fisier sau director# crearea unui director# listarea fisierelor dintr+un director# etc'
Trebuie mentionat si faptul ca majoritatea constructorilor fluxurilor care permit accesul la fisiere
accepta ca ar!ument un obiect de tip File "n locul unui sir ce repre$inta numele fisierului accesat'
File 6Jin 2 ne& File($6isier.t/t$)'
File0nputStream stJin 2 ne& File0nputStream(6Jin)
Cel mai u$ual constructor al clasei File este) public File( String 6isier)
%etodele mai importante ale clasei File sunt)
boolean isSirector#( )
boolean isFile( )
Testea$a daca un obiect File>-tt> repre5inta un 6isier
sau un director
??
String getUame( )
String getLat:( )
String getAbsoluteLat:()
String getLarent()
;fla numele 3fara cale4# calea fisierului sau directorului
repre$entat de obiectul respectiv
boolean e/ists( )
boolean delete( )
boolean mNdir( )
boolean mNdirs( )
boolean rename@o(File
dest)
Testea$a daca exista un anumit fisierJdirector
Ster!e fisierulJdirectorul repre$entat de obiect
Creea$a un director
Creea$a o succesiune de directoare
>edenumeste un fisierJdirector
String! list( )
String! list
(FilenameFilter 6ilter )
Creea$a o lista cu numele fisierelor dintr+un director
Creea$a o lista cu numele fisierelor dintr+un director filtrate dupa
un anumit criteriu specificat'3ve$i *Interfata ilenameilter*4
boolean canPead( )
boolean can]rite( )
Testea$a daca un anumit fisier poate fi folosit pentru citire#
respectiv scriere
long lengt:( )
long last?odi6ied( )
;fla lun!imea si data ultimei modificari a unui fisier'
Axemplu1) listarea fisierelor din directorul curent
--Cistarea 6isierelor din directorul curent
import +ava.io..'
public class SirCist {
public static void main(String! args) {
tr# {
File director 2 ne& File($.$)'
String! list'
list 2 director.list()'
6or(int i 2 <' i A list.lengt:' iDD)
S#stem.out.println(listi!)'
) catc:(M/ception e) {
e.printStacN@race()'
)
)
)
Axemplu7) aflarea informatiilor despre un fisier
--A6isea5a in6ormatii despre 6isierele primite la linia de comanda
import +ava.io..'
public class File0n6o {
private static void 6ile0n6o(File 6) {
S#stem.out.println(
$Cale absoluta, $ D 6.getAbsoluteLat:() D
$Bn Loate citi, $ D 6.canPead() D
$Bn Loate scrie, $ D 6.can]rite() D
$Bn Uume, $ D 6.getUame() D
$Bn Larinte, $ D 6.getLarent() D
$Bn Cale, $ D 6.getLat:() D
$Bn Cungime, $ D 6.lengt:() D
$Bn Sata ultimei modi6icare, $ D 6.last?odi6ied())'
i6(6.isFile())
S#stem.out.println($Mste 6isier$)'
else i6(6.isSirector#())
S#stem.out.println($Mste director$)'
)
?@
public static void main(String! args) {
6or(int i2<' i A args.lengt:' iDD)
6ile0n6o ( ne& File(argsi!) )'
)
)
Inter$ata FilenameFilter
ve$i *Interfete*
Curs #
Inter$ete
Ce este o interfata ?
(efinirea unei interfete
Implementarea unei interfete
Axemplu de interfata
(iferente "ntre o interfata si o clasa abstracta
%ostenire multipla prin intermediul interfetelor
-tilitatea interfetelor
Crearea !rupurilor de constante
Transmiterea metodelor ca parametri 3call+bacF4
Interfata ilenameilter
Top
Ce este o inter$ata 5
Interfetele duc conceptul de clasa abstracta cu un pas "nainte prin eliminarea oricarei implementari a
metodelor# pun.nd "n practica unul din conceptele EOO de separare a modelului unui obiect 3interfata4 de
implementarea sa' ;sadar# o interfata poate fi privita ca un protocol de comunicare "ntre obiecte'
O interfata Java defineste un set de metode dar nu specifica nici o implementare pentru ele' O clasa care
implementea$a o interfata trebuie obli!atoriu sa specifice implementari pentru toate metodele interfetei#
supun.ndu+se asadar unui anumit comportament'
+e$initie
O interfata este o colectie de metode fara implementare si declaratii de constante
?9
+e$inirea unei inter$ete
(efinirea unei interfete se face prin intermediul cuv.ntului cheie interface)
public! interface Uume0nter6ata
e/tends Super0nter6ata; 4e/tends Super0nter6ata2...!!
{
--corpul inter6etei,constane si metode abstracte
)
O interfata poate avea un sin!ur modificator) public' O interfata publica este accesibila tuturor claselor
indiferent de pachetul din care fac parte' O interfata care nu este publica este accesibila doar claselor din
pachetul din care face parte interfata'
O clasa poate extinde oric.te interfete' ;cestea se numesc superinterfete si sunt separate prin vir!ula
3ve$i *%ostenirea multipla prin intermediul interfetelor*4'
Corpul unei interfete contine)
constante) acestea pot fi sau nu declarate cu modificatorii public4 static si 6inal care sunt
impliciti6 nici un alt modificator nu poate aparea "n declaratia unei variabile a unei interfete
Constantele dintr+o interfata trebuie obli!atoriu initiali$ate'
inter6ace Uume0nter6ata {
int ?AT 2 ;<<' --ec:ivalent cu
public static 6inal ?AT 2 ;<<'
int ?AT' --ilegal - 6ara initiali5are
private int / 2 ;' --ilegal
)
metoe fara implementare) acestea pot fi sau nu declarate cu modificatorul public care este
implicit6 nici un alt modificator nu poate aparea "n declaratia unei metode a unei interfete'
inter6ace Uume0nter6ata {
void metoda()' --ec:ivalent cu
public void metoda()'
protected void metoda2()' --ilegal
0tentie
Variabilele unei interfete sunt implicit publice chiar daca nu sunt declarate cu modificatorul
public'
Variabilele unei interfete sunt implicit constante chiar daca nu sunt declarate cu modificatorii
static si 6inal'
%etodele unei interfete sunt implicit publice chiar daca nu sunt declarate cu modificatorul
public'
In variantele mai vechi de Java era permis si modificatorul abstract "n declaratia interfetei si "n
declaratia metodelor# "nsa a fost eliminat deoarece at.t interfata c.t si metodele sale sunt implicit
abstracte'
Implementarea unei inter$ete
Se face prin intermediul cuv.ntului cheie implements)
?:
class UumeClasa implements Uume0nter6ata sau
class UumeClasa implements 0nter6ata;4 0nter6ata2...
O clasa poate implementa oric.te interfete' 3ve$i *%ostenirea multipla prin intermediul
interfetelor*4'
O clasa care implementea$a o interfata trebuie obli!atoriu sa specifice cod pentru toate metodele
interfetei' (in acest motiv# odata creata si folosita la implementarea unor clase# o interfata nu mai
trebuie modificata # "n sensul ca adau!area unor metode noi sau schimbarea si!naturii metodelor
existente va duce la erori "n compilarea claselor care o implementea$a'
%odificarea unei interfete implica modificarea tuturor claselor care implementea$a acea interfataN
Implementarea unei interfete poate sa fie si o clasa abstracta'
Exemplu de inter$ata
inter6ace 0nstrument {
--de6ineste o metoda 6ara implementare
void pla#()'
)
class Lian implements 0nstrument {
--clasa care implementea5a inter6ata
--trebuie obligatoriu sa implemente5e metoda pla#
public void pla#() {
S#stem.out.println($Lian.pla#()$)'
)
)
class Qioara implements 0nstrument {
--clasa care implementea5a inter6ata
--trebuie obligatoriu sa implemente5e metoda pla#
public void pla#() {
S#stem.out.println($Qioara.pla#()$)'
)
)
public class ?u5ica { --clasa principala
static void pla#(0nstrument i) {
--metoda statica care porneste un instrument generic
--ce implementea5a inter6ata 0nstrument
i.pla#()'
)
static void pla#All(0nstrument! e) {
6or(int i 2 <' i A e.lengt:' iDD)
pla#(ei!)'
)
public static void main(String! args) {
0nstrument! orc:estra 2 ne& 0nstrument2!'
int i 2 <'
orc:estraiDD! 2 ne& Lian()'
orc:estraiDD! 2 ne& Qioara()'
pla#All(orc:estra)'
)
)
Se observa ca folosind interfata 0nstrument putem adau!a noi clase de instrumente fara a
schimba codul metodelor pla# si pla#All din clasa principala "ntruc.t acestea primesc ca
parametru un instrument !eneric'
0tentie
?<
O interfata nu este o clasa# dar orice referinta la un obiect de tip interfata poate primi ca valoare o
referinta la un obiect al unei clase ce implementea$a interfata respectiva 3upcast4' (in acest motiv
interfetele pot fi privite ca tipuri de date'
+i$erente .ntre o inter$ata si o clasa abstracta
La prima vedere o interfata nu este altceva dec.t o clasa abstacta "n care toate metodele sunt
abstracte 3nu au nici o implementare4' ;sadar o clasa abstracta nu ar putea "nlocui o interfata ?
>aspunsul la intrebare este 1u' (eosebirea consta "n faptul ca unele clase sunt fortate sa extinda o
anumita clasa 3de exemplu orice applet trebuie sa fie subclasa a clasei ;pplet4 si nu ar mai putea
sa extinda o clasa abstracta deoarece "n Java nu exista dec.t mostenire simpla' ara folosirea
interfetelor nu am putea forta clasa respectiva sa respecte un anumit protocol'
La nivel conceptual diferenta consta "n)
o extinderea unei clase abstracte fortea$a o relatie "ntre clase
o implementarea unei interfete specifica doar necesitatea implementarii unor anumie metode
Mostenire multipla prin intermediul inter$etelor
Interfetele nu au nici o implementare si nu ocupa spatiu de memorie la instantierea lor' (in acest
motiv nu repre$inta nici o problema ca anumite clase sa implemente$e mai multe interfete sau ca o
interfata sa extinda mai multe interfete 3sa aiba mai multe superinterfete4
class UumeClasa implements 0nter6ata;4 0nter6ata24 ...
inter6ace Uume0nter6ata e/tends 0nter6ata;4 0nter6ata24 ...
O interfata mosteneste at.t constantele c.t si declaratiile de metode de la superinterfetele sale' O
clasa mosteneste doar constantele unei interfete'
Axemplu de clasa care implementea$a mai multe interfete)
inter6ace 0notator {
void inoata()'
)
inter6ace Xburator {
void 5boara()'
)
class Cuptator {
public void lupta() {)
)
class Mrou e/tends Cuptator implements 0notator4 Xburator {
public void inoata() {)
public void 5boara() {)
)
Axemplu de interfata care extinde mai multe interfete )
inter6ace ?onstru {
void ameninta()'
@8
)
inter6ace ?onstruLericulos e/tends ?onstru {
void distruge()'
)
inter6ace ?ortal {
void omoara()'
)
inter6ace Qampir e/tends ?onstruLericulos4 ?ortal {
void beaSange()'
)
class Sracula implements Qampir {
public void ameninta() {)
public void distruge() {)
public void omoara()'
public void beaSange() {)
)
0tentie
O clasa nu poate avea dec.t o superclasa
O clasa poate implementa oric.te interfete
O clasa mosteneste doar constantele unei interfete
O clasa nu poate mosteni implementari de metode dintr+o interfata
Ierarhia interfetelor este independenta de ierarhia claselor care le implementea$a
:tilitatea inter$etelor
O interfata defineste un protocol ce poate fi implementat de orice clasa# indiferent de ierarhia de
clase din care face parte' Interfetele sunt utile pentru)
o definirea unor similaritati "ntre clase independente fara a forta artificial o le!atura "ntre ele'
o asi!ura ca toate clasele care implementea$a o interfata pun la dipo$itie metodele
specificate "n interfata6 de aici re$ulta posibilitatea implementarii unitare a unor clase prin
mai multe modalitati'
o specificarea metodelor unui obiect fara a deconspira implementarea lor 3aceste obiecte se
numesc anonime si sunt folosite la livrarea unor pachete cu clase catre alti pro!ramatori)
acestia pot folosi clasele respective dar nu pot vedea implementarile lor efective4
o definirea unor !rupuri de constante
o transmiterea metodelor ca parametri 3tehnica Call+HacF4 3ve$i *Transmiterea metodelor ca
parametri*4'
Crearea grupurilor de constante
(eoarece orice variabila a unei interfete este implicit declarata cu public4 static si 6inal
interfetele repre$inta o metoda convenabila de creare a unor !rupuri de constante# similar cu enum
din C55'
public inter6ace Cuni {
int 0AU2;4 FM3224 ...4 SMC2;2'
)
@1
olosirea acestor constante se face prin expresii de !enul Uume0nter6ata.constanta )
i6 (luna A Cuni.SMC)
luna DD
else
luna 2 Cuni.0AU'
Transmiterea metodelor ca parametri call1bacA"
Transmiterea metodelor ca parametri se face "n C55 cu ajutorul pointerilor' In Java aceasta
tehnica este implementata prin intermediul interfetelor' Vom ilustra acest lucru prin intermediul
unui exemplu'
#xplorarea unui graf
In fiecare nod trebuie sa se execute prelucrarea informatiei din el prin intermediul unei functii
primite ca parametru'
inter6ace 6unctie {
public int e/ecutie(int arg)'
)
class 9ra6 {
--...
void e/plorare(6unctie 6) {
--...
i6 e/plorarea a a+uns in nodul v
6.e/ecutie(v.valoare)'
--...
)
)
--Se6inim doua 6unctii
class 6; implements 6unctie {
public int e/ecutie(int arg) {
return argD;'
)
)
class 62 implements 6unctie {
public int e/ecutie(int arg) {
return arg.arg'
)
)
public class @estCall3acN {
public static void main(String args!) {
9ra6 9 2 ne& 9ra6()'
9.e/plorare(ne& 6;())'
9.e/plorare(ne& 62())'
)
)
@7
Inter$ata 7ilename7ilter
Instantele claselor ce implementea$a aceasta interfata sunt folosite pentru a crea filtre pentru
fisiere si sunt primite ca ar!umente de metode care listea$a continutul unui director# cum ar fi
metoda list a clasei File'
;ceasta interfata are o sin!ura metoda accept care specifica criteriul de filtrare si anume# testea$a
daca numele fisierului primit ca parametru "ndeplineste conditiile dorite de noi'
(efinitia interfetei)
public inter6ace FilenameFilter {
-- ?etode
public boolean accept( File dir4 String numeFisier )'
)
;sadar orice clasa de specificare a unui filtru care implemente$a interfata FilenameFilter
trebuie sa implemente$e metoda accept a acestei interfete' ;ceste clase mai pot avea si alte
metode# de exemplu un constructor care sa primeasca criteriul de filtrare# adica masca dupa care se
filtrea$a fisierele' In !eneral# o clasa de specificare a unui filtru are urmatorul format)
class SirFilter implements FilenameFilter {
String 6iltru'
--constructorul
SirFilter(String 6iltru) {
t:is.6iltru 2 6iltru'
)
--implementarea metodei accept
public boolean accept(File dir4 String nume) {
--elimin in6ormatiile despre calea 6isierului
String 6 2 ne& File(nume).getUame()'
i6 (6iltrul este indeplinit)
return true'
else
return 6alse'
)
)
%etodele cele mai u$uale ale clasei String folosite pentru filtrarea fisierelor sunt)
boolean ends4ith(String s)
--testea5a daca un sir se termina cu sirul speci6icat s
int inde/%f(String s)
--testea5a daca un sirul are ca subsir sirul speci6icat s
--returnea5a <2nu este subsir4 ><2po5itia subsirului
Instantele claselor pentru filtrare sunt primite ca ar!umente de metode de listare a continutului
unui director' O astfel de metoda este metoda list a clsei File)
String! list (FilenameFilter 6iltru )
Observati ca aici interfata este folosita ca un tip de date# ea fiind substituita cu orice clasa care o
implementea$a' ;cesta este un exemplu tipic de transmitere a unei functii 3functia de filtrare
accept4 ca ar!ument al unei metode'
$istarea fisierelor in irectorul curent care au extensia .%ava
@=
import +ava.io..'
public class SirCist2 {
public static void main(String! args) {
tr# {
File director 2 ne& File($.$)'
String! list'
list 2 director.list(ne& FiltruM/tensie($+ava$))'
6or(int i 2 <' i A list.lengt:' iDD)
S#stem.out.println(listi!)'
) catc:(M/ception e) {
e.printStacN@race()'
)
)
)
class FiltruM/tensie implements FilenameFilter {
String e/tensie'
FiltruM/tensie (String e/tensie) {
t:is.e/tensie 2 e/tensie'
)
public boolean accept (File dir4 String nume) {
return ( nume.ends]it:($.$ D e/tensie) )'
)
)
#xemplu e folosire a claselor anonime
In ca$ul "n care nu avem nevoie de filtrarea fisierelor dintr+un director dec.t o sin!ura data# pentru
a evita crearea unei noi clase care sa fie folosita pentru filtrare putem apela la o clasa interna
anonima# aceasta situatie fiind un exemplu tipic de folosire a acestora'
import +ava.io..'
public class SirCist3 {
public static void main(String! args) {
tr# {
File director 2 ne& File($.$)'
String! list'
--6olosim o clasa anonima pentru speci6icarea 6iltrului
list 2 director.list(ne&
FilenameFilter() {
public boolean accept (File dir4String nume)
return ( nume.ends]it:($.+ava$))'
)
) )'
6or(int i 2 <' i A list.lengt:' iDD)
S#stem.out.println(listi!)'
) catc:(M/ception e) {
e.printStacN@race()'
)
)
)
Curs #
Pac%ete
Crearea unui pachet
@D
(enumirea unui pachet
olosirea membrilor unui pachet
Importul unei clase sau interfete
Importul unui pachet 3importul la cerere4
Eachetele J(B
Top
Crearea unui pac%et
+e$initie
-n pac&et este o colectie de clase si interfete "nrudite' Sunt folosite pentru !asirea si utili$area mai
usoara a claselor# pentru a evita conflictele de nume si pentru a controla accesul la anumite clase'
In alte limbaje de pro!ramare pachetele se numesc librarii'
Toate clasele si interfetele Java apartin la diverse pachete# !rupate dupa functionalitatea lor) clasele de
ba$a se !asesc "n pachetul java.lang# clasele pentru intrariJiesiri sunt "n java.io# clasele pentru !rafica
"n java.awt# cele pentru construirea applet+urile "n java.applet# etc' Crearea unui pachet se reali$ea$a
prin scriere la "nceputul fisierelor sursa ce contin clasele si interfetele pe care dorim sa le !rupam "ntr+un
pachet a instructiunii) pac:age Nume6achet; Sa consideram un exemplu) presupunem ca avem doua
fisiere sursa 9ra6.+ava si Arbore.+ava
=ra$34ava 0rbore34ava
pacNage gra6uri'
class 9ra6 {...)
class 9ra6Ler6ect e/tends 9ra6 {...)
pacNage gra6uri'
class Arbore {...)
class Arbore3inar e/tends Arbore {...)
Clasele 9ra64 9ra6Ler6ect4 Arbore4 Arbore3inar vor face parte din acelasi pachet gra6uri'
Instructiunea pacNage actionea$a asupra "ntre!ului fisier sursa la "nceputul caruia apare' Cu alte cuvinte
nu putem specifica faptul ca anumite clase dintr+un fisier sursa apartin unui pachet iar altele altui pachet'
(aca nu este specificat un anumit pachet# clasele unui fisier sursa vor face parte din pachetul implicit
3care nu are nici un nume4' In !eneral# pachetul implicit este format din toate clasele si intefetele
directorului curent'
Aste recomandabil ca toate clasele si intefetele sa fie plasate "n pachete' Eachetul implicit este folosit doar
pentru aplicatii mici sau la "nceputul de$voltarii unei aplicatii'
+enumirea unui pac%et
Axista posibilitatea ca doi pro!ramatori care lucrea$a la un proiect comun sa foloseasca acelasi nume
pentru unele din clasele lor' (e asemenea# se poate ca una din clasele unei aplicatii sa aiba acelasi nume
cu o clasa a mediului Java' ;cest lucru este posibil at.t timp c.t clasele cu acelasi nume se !asesc "n
pachte diferite# ele fiind diferentiate prin prefixarea lor cu numele pachetelor' ;sadar numele complet al
unei clase este format din numele pachetului la care apartine 5 numele sau)
nume6achet.Nume$lasa
M/, +ava.lang.String (+ava.lang2pac:et4 String2clasa)
(e exemplu sa presupunem ca "n aplicatia noastra folosim o clasa numita StacN)
pacNage m#JpacNage'
class StacN { ... )
@?
Clasa StacN exista deja "n pachetul +ava.util' (iferentierea "ntre cele doua clase se va face prin
specificarea numelui complet al clasei# adica numeleEachetului'1umeleClasei)
+ava.util.StacN s; 2 ne& +ava.util.StacN()'
m#JpacNage.StacN s2 2 ne& m#JpacNage.StacN()'
Ce se "nt.mpla "nsa c.nd doi pro!ramatori care lucrea$a la un proiect comun folosesc clase cu acelasi
nume ce se !asesc "n pachete cu acelasi nume ? Eentru a evita acest lucru companiile folosesc inversul
domeniului lor Internet "n denumirea pachetelor implementate "n cadrul companiei# cum ar fi
com.compan#.numeLac:et' In cadrul unei aceeasi companii conflictele de nume trebuie re$olvate prin
diverse conventii de u$ intern'(e exemplu# adresa mea de e+mail este ac6^in6oiasi.ro# ceea ce
"nseamna ca domeniul meu Internet este in6oiasi.ro' Eachetele create de mine ar trebui denumite
ro.in6oiasi.UumeLac:et' Eentru a re$olva conflicte cu alti pro!ramatori din acelasi domeniu cu mine
pachetele s+ar putea numi) ro.in6oiasi.ac6.UumeLac:et'
Folosirea membrilor unui pac%et
Conform specificatiilor de acces ale unei clase si ale mebrilor ei doar clasele publice si membrii declarati
publici ai unei clase sunt accesibili "n afara pachetului "n care acestea se !asesc' 3ve$i *Specificatori de
acces pentru membrii unei clase*4
Eentru a folosi o clasa publica dintr+un pachet sau pentru a apela o metoda publica a unei clase public a
unui pachet exista trei solutii)
specificarea numelui complet al clasei
importul clasei respective
importul "ntre!ului pachet "n care se !aseste clasa
Specificarea numelui complet al calsei se face# asa cum am va$ut# prin prefixarea numelui clasei cu
numele pachetului) numeLac:et.UumeClasa' ;ceasta metoda este recomandata doar pentru ca$ul "n care
folosirea acelei clase se face o sin!ura data sau foarte rar' (e exemplu ar fi extrem de neplacut sa scriem
de fiecare data c.nd vrem sa declaram un sir de caractere sau sa folosim un obiect !rafic secvete de !enul6
+ava.lang.String s 2 $neplacut$'
+ava.a&t.Pectangle r 2 ne& +ava.a&t.Pectangle()'
+ava.a&t.Circle c 2 ne& +ava.a&t.Circle()'
In aceste situatii vom importa 3include4 clasa respective sau "ntre! pachet din care face parte in aplicatia
noastra' ;cest lucru se reali$ea$a prin instructiunea import# care trebuie sa apara la "nceputul fisierelor
sursa# imediat dupa instructiunea pacNage'
Importul unei clase sau inter$ete
Se face printr+o instructiune import "n care specificam numele clasei 3interfetei4 pe care dorim sa o
folosim dintr+un pachet)
import +ava.a&t.Pectangle'
(in acest moment vom putea folosi "n clasele fisierului "n care am plasat instructiunea de import numele
scurt al clasei Pectangle
Pectangle r 2 ne& Pectangle(<4<4;<<4;<<)'
;ceasta abordare este eficienta "n ca$ul "n care nu avem nevoie dec.t de acea clasa sau doar de c.teva
clase din pachetul respectiv' (aca "n exemplul nostru am avea nevoie si de clasele Circle4 Cine4
Loint4 Lol#gon ar trebui sa avem c.te o instructiune de import pentru fiecare dintre ele)
import +ava.a&t.Pectangle'
import +ava.a&t.Circle'
import +ava.a&t.Cine'
import +ava.a&t.Loint'
@@
import +ava.a&t.Lol#gon'
In aceasta situatie ar fi recomandat importul "ntre!ului pachet si nu al fiecarei clase "n parte'
Importul unui pac%et importul la cerere"
Se face printr+o instructiune import "n care specificam numele pachetului ale carui clase si interfete dorim
sa le folosim dintr+un pachet# urmat de simbolul BCB' Se mai numeste import la cerere deoarece "ncarcarea
claselor se face dinamic "n momentul apelarii lor' Aste cel mai u$ual tip de import'
import +ava.a&t..'
(in acest moment vom putea folosi "n clasele fisierului "n care am plasat instructiunea de import numele
scurt al tuturor claselor pachetului importat)
Pectangle r 2 ne& Pectangle()'
Circle c 2 ne& Circle()' ...
0tentie
K nu are semnificatia u$uala de 0ildcard 3masca4 si nu poate fi folosit dec.t ca atare'
import +ava.a&t.C.' --eroare de compilare
In ca$ul "n care sunt importate doua pachete care contin o clasa cu acelasi nume atunci referirea la ea
trebuie facuta folosind numele complet al clasei respective'
--StacN.+ava
pacNage m#JpacNage'
class StacN { ... )
--alt 6isier sursa
import +ava.util..'
import m#JpacNage..'
...
StacN s 2 ne& StacN()' --ilegal -> con6lict de nume
+ava.util.StacN s; 2 ne& +ava.util.StacN()' --corect
m#JpacNage.StacN s2 2 ne& m#JpacNage.StacN()'--corect
%ediul Java importa automat trei pachete pentru toate fisierele sursa)
pachetul +ava.lang
pachetul curent
pachetul implicit 3fara nume4
Pac%etele J+D
Limbajul Java se ba$ea$a pe o serie de biblioteci 3pachete4 cu ajutorul carora se pot construi aplicatiile'
Axista deci un set de clase deja implementate# ceea ce reduce timpul de de$voltare a unui pro!ram' Cele
mai importante sunt)
+ava.applet
suport pt scrierea de appleturi
+ava.a&t
suportul pentru !rafica3;bstract /indo0in! ToolFit4
+ava.beans
suport pentru scrierea de componente reutili$abile
+ava.io
intrariJiesiri# acces la fisiere
+ava.lang
clasele de ba$a ale limbajului
+ava.mat:
operatii matematice
+ava.net
acces la retea
+ava.rmi
executie la distanta 3>emote %essa!e Interface4
@9
+ava.securit#
mecanisme de securitate ) criptare# autentificare
+ava.sWl
intero!ari SRL
+ava.te/t
suport pentru formatarea textelor
+ava.util
clase utile ) Vector# StacF# >andom# etc
Eachetul +ava.lang contine elementele de ba$a ale limbajului si este importat automat'
Curs &
'eriali(area obiectelor
Ce este seriali$area ?
Seriali$area obiectelor
o Clasa ObjectOutputStream
o Clasa ObjectInputStream
Obiecte seriali$abile
o Implementarea interfetei Seriali$able
o Eersonali$area seriali$arii obiectelor
o Implementarea interfetei Axternali$able
Controlul seriali$arii 3cuv.ntul cheie transient4
Axemplu de folosire a seriali$arii
olosirea seriali$arii pentru copierea obiectelor
Top
Ce este seriali(area 5
+e$initie
Seriali"area este o metoda ce permite transformarea unui obiect "ntr+o secventa de octeti din care
sa poata fi refacut ulterior obiectul ori!inal' Cu alte cuvinte# seriali$area permite salvarea "ntr+o
maniera unitara a datelor "mpreuna cu si!natura unui obiect pe un mediu de stocare a informatiei
extern pro!ramului' Erocesul invers de citirea a unui obiect seriali$at pentru a+i reface starea
ori!inala se numeste eseriali"are' Intr+un cadru mai lar!# prin seriali$are se "ntele!e procesul de
scriereJcitire a obiectelor'
-tilitatea seriali$arii consta "n urmatoarele aspecte)
Compensarea diferentelor "ntre sisteme de operare# adica putem crea un obiect pe o masina
/indo0s# "l seriali$am# apoi "l trimitem prin retea catre o masina -1I2 unde va fi corect
reconstruit' In acest fel comunicarea "ntre sisteme diferite se reali$ea$a unitar# independent de
repre$entarea datelor# ordinea octetilor sau alte detalii specifice sistemelor repective'
Eermite persistenta obiectelor# ceea ce "nseamna ca durata de viata a unui obiect nu este
determinata de executia unui pro!ram "n care acesta este definit + obiectul poate exista si "ntre
@:
apelurile pro!ramelor care "l folosesc' ;cest lucru se reali$ea$a prin seriali$area obiectului si
scrierea lui pe disc "nainte de terminarea unui pro!ram# apoi# la relansarea pro!ramului# obiectul
va fi citit de pe disc si starea lui refacuta' ;cest tip de persistenta a obiectelor se numeste
persistenta usoara# "ntruc.t ea trebuie efectuata explicit de catre pro!ramator si nu este
reali$ea$ata automat de catre sistem'
R'( (Remote 'et&o (nvocation! + comunicarea obiectelor prin socFet+uri) este o modalitate prin
care obiectele de pe o alta masina se comporta ca si c.nd ar exista pe masina pe care rulea$a
pro!ramul nostru' ;tunci c.nd este trimis un mesaj catre un obiect *remote* 3de pe alta masina4#
seriali$area este necesara pentru transportul ar!umentelor prin retea si pentru returnarea valorilor'
Java )eans + sunt componente !rafice definite de utili$ator si care pot fi folosite la fel ca si
componentele !rafice standard' Orice componenta Hean are o stare initiala a informatiilor sale#
stare care este specificata la definirea sa' ;tunci c.nd ea este folosita "ntr+un pro!ram aceasta stare
trebuie "ncarcata de undeva# ceea ce "nseamna ca aceste componente trebuie seriali$ate si salvate
pe disc'
-n aspect important al seriali$arii este ca nu salvea$a doar ima!inea unui obiect ci si toate referintele la
alte obiecte pe care acesta le contine' ;cesta este un proces recusiv de salvare a datelor# "ntruc.t celelalet
obiectele referite de obiectul care se seriali$ea$a pot referi la r.ndul lor alte obiecte# s'a'md' ;sadar
obiectele care construiesc starea altui obiect formea$a o "ntrea!a retea de obiecte# ceea ce "nseamna ca un
al!oritm de salvare a starii unui obiect nu este facil'
In ca$ul "n care starea unui obiect este formata doar din valori ale unor variabile de tipuri primitive# atunci
salvarea datelor "napsulate "n acel obiect se poate face si prin salvarea pe r.nd a datelor# folosind clasa
Sata=utputStream# pentru ca apoi sa fie restaurate prin metode ale clasei Sata0nputStream# dar# asa
cum am va$ut# o asemenea abordare nu este "n !eneral suficienta# deoarece pot aparea probleme cum ar
fi ) datele obiectului pot fi instante ale altor obiecte# unele c.mpuri fac referinta la acelasi obiect# etc'
Seriali$area obiectelor se reali$ea$a prin intermediul fluxurilor definite de clasele =b+ect=utputStream
3pentru salvare4 si =b+ect0nputStream 3pentru restaurare4'
'eriali(area obiectelor
Seriali$area obiectelor se reali$ea$a prin intermediul fluxurilor definite de clasele %&ject%utputStream
3pentru salvare4 si %&ject0nputStream 3pentru restaurare4' ;cestea sunt fluxuri de procesare ceea ce
"nseamna ca ele vor fi folosite "mpreuna cu alte fluxuri pentru citireaJscrierea efectiva a datelor pe mediul
extern pe care va fi salvat sau de pe care va fi restaurat un obiect seriali$at'
%ecanismul implicit de seriali$are a unui obiect va salva numele clasei obiectului# si!natura clasei
obicetului# valorile tuturor c.mpurile seriali$abile ale obiectului 3ve$i *Controlul seriali$arii*4' >eferintele
la alte obiecte seriali$abile din cadrul obiectului curent vor duce automat la seriali$area acestora iar
referintele multiple catre un acelasi obiect sunt codificate utili$.nd un al!oritm care sa poata reface
*reteaua de obiecte* la aceeasi stare ca atunci c.nd obiectul ori!inal a fost salvat'
Clasele =b+ect0nputStream si =b+ect=utputStream implementea$a indirect interfetele Sata0nput#
respectiv Sata=utput# interfete ce declara metode de tipul readTTT# respectiv &riteTTT pentru
scriereaJcitirea datelor primitive' Ee l.n!a aceste metode vor exista si metode pentru scriereaJcitirea
obiectelor'
%etodele pentru seriali$area obiectelor sunt)
private void read%&ject(=b+ect0nputStream stream) --salvare obiect
t:ro&s 0=M/ception4ClassUotFoundM/ception'
private void write%&ject(=b+ect=utputStream stream) --re6acere obiect
t:ro&s 0=M/ception'
;ceste metode contin apeluri catre metodele implicite de seiali$are a obiectelor)
6inal void default4rite%&ject()
t:ro&s 0=M/ception
@<
6inal void default2ead%&ject()
t:ro&s 0=M/ception4ClassUotFoundM/ception4UotActiveM/ception
Clasele care necesita o seriali$are speciala trebuie sa supradefineasca metodele &rite=b+ect si
read=b+ect 3obli!atoriu pe am.ndouaN4 pentru a implementa metode specifice de seriali$are' 3ve$i
*Eersonali$area seriali$arii obiectelor*4'
Clasa Ob4ectOutput'tream
Scrierea obiectelor pe un flux este un proces extrem de simplu' Axemplul de mai jos# afla timpul curent "n
milisecunde construind un obiect de tip Sate si "l salvea$a "ntr+un fisier t:e@ime)
File=utputStream out 2 ne& File=utputStream($t:e@ime$)'
=b+ect=utputStream s 2 ne& =b+ect=utputStream(out)'
s.&rite=b+ect($@oda#$)'
s.&rite=b+ect(ne& Sate())'
s.6lus:()'
s.close()'
;sadar metoda pentru scrierea unui obiect este write%&ject# responsabila cu seriali$area completa a
obiectului' (eoarece implementea$a interfata Sata=utput# pe l.n!a metoda de scriere a obiectelor# clasa
pune la dispo$itie si metode de tipul &riteTTT pentru scrierea tipurilor de date primitive# astfel "nc.t
apeluri ca cele de mai jos sunt permise )
File=utputStream out 2 ne& File=utputStream($t.tmp$)'
=b+ect=utputStream s 2 ne& =b+ect=utputStream(out)'
s.&rite0nt(;23"()'
s.&riteSouble(;2.3"()'
s.&rite[@F($Sir de caractere$)'
s.6lus:()'
s.close()'
%etoda &rite=b+ect arunca exceptii de tipul UotSeriali5ableM/ception daca obiectul primit ca
ar!ument nu este seriali$abil' Vom vedea "n continuare ca un obiect este seriali$abil daca este instanta a
unei clase ce implementea$a interfata Seriali5able'
Clasa Ob4ectInput'tream
Odata ce au fost scrise obiecte si tipuri primitive de date pe un flux# citirea acestora si reconstruirea
obiectelor salvate se va face printr+un flux de intrare de tip =b+ect0nputStream' ;cesta este de
asemenea un flux de procesare si va trebui asociat cu un flux pentru citirea efectiva a datelor# de exemplu
File0nputStream 3pentru date salvate "ntr+un fisier4'
File0nputStream in 2 ne& File0nputStream($t:e@ime$)'
=b+ect0nputStream s 2 ne& =b+ect0nputStream(in)'
String toda# 2 (String)s.read=b+ect()'
Sate date 2 (Sate)s.read=b+ect()'
;sadar# metoda pentru citirea unui obiect seriali$at si refacerea starii lui este read%&ject' Clasa
=b+ect0nputStream implementea$a interfata Sata0nput# deci# pe l.n!a metoda de citire a obiectelor
clasa pune la dispo$itie si metode de tipul readTTT pentru citirea tipurilor de date primitive'
File0nputStream in 2 ne& File0nputStream($t.tmp$)'
=b+ect0nputStream s 2 ne& =b+ect0nputStream(in)'
int n 2 s.read0nt()'
double d 2 s.readSouble(;2.3"()'
String sir 2 s.read[@F()'
0tentie
Ca si la celelate fluxuri de date 3care implemetea$a interfata Sata0nput4 citirea dintr+un flux de
obiecte trebuie sa se faca exact "n ordinea "n carea acestea au fost scrise'
Trebuie observat ca metoda read=b+ect returnea$a un obiect de tipul =b+ect si nu de tipul corespun$ator
obiectului citit# conversia la acest tip trebuind sa se faca explicit)
Sate date 2 s.read=b+ect()' -- ilegal
Sate date 2 (Sate)s.read=b+ect()' -- corect
98
Obiecte seriali(abile
-n obiect este seriali$abil daca si numai daca clasa din care face parte implementea$a interfata
Seriali)a&le' ;sadar# daca dorim ca instantele unei clase sa poata fi seriali$ate# clasa respectiva trebuie
sa implemente$e interfata Seriali5able' ;ceasts interfata este mai deosebita# "n sensul ca nu contine
nici o declaratie de metoda# sin!urul ei scop fiind de a identifica clasele ale caror obiecte sunt
seriali$abile'
Implementarea inter$etei 'eriali(able
(efinitia completa a interfetei Seriali5able este)
pacNage +ava.io'
public inter6ace Seriali5able {
-- nimic>
)
Crearea claselor ale caror instante sunt seriali$abile este extrem de facila) la clasa respectiva trebuie sa
adau!am "n declaratia ei ca implemente$e interfata Seriali5able si nimic mai mult)
public class ClasaSeriali5abila implements Seriali5able {
--putem sa nu scriem nici o metoda deoarece
--inter6ata nu declara nici o metoda>
)
;sadar# clasa poate sa nu contina nici o metoda# ea va contine totusi metode altfel nu ar avea nici un rost#
dar metodele vor fi specifice scopului pentru care ea a fost creata si nu vor avea le!atura cu seriali$area'
;sa cum am va$ut# seriali$area implicita a obiectelor oricarei clase este definita "n metoda
de6ault]rite=b+ect a clasei =b+ect=utputStream care va salva toate datele necesare reconstruirii
obiectului ) numele clasei# si!natura# valorile variabilelor membre si obiectele referite de acestea' In
majoritatea ca$urilor aceasta metoda de seriali$are este suficienta# "nsa o clasa poate avea nevoie de mai
mult control asupra seriali$arii'
Personali(area seriali(arii obiectelor
Eersonali$area seriali$arii se reali$ea$a prin supradefinirea 3"ntr+o clasa seriali$abilaN4 a metodelor
&rite=b+ect si read=b+ect# modific.nd astfel actiunea lor implicita'
%etoda &rite=b+ect controlea$a ce date sunt salvate si este u$ual folosita pentru a adau!a informatii
suplimentare la cele scrise implicit de metoda de6ault]rite=b+ect'
%etoda read=b+ect controlea$a modul "n care sunt restaurate obiectele# citind informatiile salvate si#
eventual# modifc.nd starea obiectelor citite astfel "nc.t ele sa corespunda anumitor cerinte'
;ceste metode trebuie obli!atoriu sa aiba urmatorul format)
private void &rite=b+ect(=b+ect=utputStream stream)
t:ro&s 0=M/ception
private void read=b+ect(=b+ect0nputStream stream)
t:ro&s 0=M/ception4 ClassUotFoundM/ception
(e asemenea# u$ual# primul lucru pe care trebuie sa "l faca aceste metode este apelul la metodele standard
de seriali$are a obiectelor de6ault]rite=b+ect# respectiv de6aultPead=b+ect si abia apoi sa execute
diverse operatiuni suplimentare' orma lor !enerala este)
private void &rite=b+ect(=b+ect=utputStream s)
t:ro&s 0=M/ception {
s.de6ault]rite=b+ect()'
-- personali5area seriali5arii
)
91
private void read=b+ect(=b+ect0nputStream s)
t:ro&s 0=M/ception4ClassUotFoundM/ception {
s.de6aultPead=b+ect()'
-- personali5area deseriali5arii
. . .
-- actuali5area starii obiectului (daca e necesar)
)
%etodele &rite=b+ect si read=b+ect sunt responsabile cu seriali$area clasei "n care sunt definite#
seriali$area superclasei sale fiind facuta automat 3si implicit4' (aca "nsa o clasa trebuie sa+si coordone$e
seriali$area proprie cu seriali$area superclasei sale# atunci trebuie sa implemente$e interfata
M/ternali5able'
Implementarea inter$etei Externali(able
Eentru un control complet# explicit# al procesului de seriali$are# o clasa trebuie sa implemente$e interfata
M/ternali5able' Eentru instante ale acestor clase doar numele clasei este salvat automat pe un flux de
obiecte# clasa fiind responsabila cu scrierea si citirea membrilor sai si trebuie sa se coordone$e cu
superclasele ei'
(efinitia interfetei M/ternali5able este)
pacNage +ava.io'
public inter6ace 1/ternali)a&le e/tends Seriali5able {
public void &riteM/ternal(=b+ect=utput out)
t:ro&s 0=M/ception'
public void readM/ternal(=b+ect0nput in)
t:ro&s 0=M/ception4 ClassUotFoundM/ception'
)
;sadar# aceste clase trebuie sa implemente$e obli!atoriu metodele &riteM/ternal si readM/ternal "n
care se va face seriali$area completa a obiectelor si coordonarea cu superclasa ei'
Controlul seriali(arii
Axista ca$uri c.nd dorim ca unele variabile membre sau sub+obiecte ale unui obiect sa nu fie salvate
automat "n procesul de seriali$are' ;cestea sunt ca$uri comune atunci c.nd respectivele c.mpuri
repre$inta informatii confidentiale# cum ar fi parole# sau variabile auxiliare pe care nu are rost sa le
salvam' Chiar declarate ca private "n cadrul clasei aceste c.mpuri participa la seriali$are' O modalitate de
a controla seriali$are este implementarea interfetei M/ternali5able# asa cum am va$ut anterior' ;ceasta
metoda este "nsa incomoda atunci c.nd clasele sunt !reu de seriali$at iar multimea c.mpurilor care nu
trebuie salvate este redusa'
Eentru ca un c.mp sa nu fie salvat "n procesul de seriali$are atunci el trebuie declarat cu modificatorul
transient si trebuie sa fie ne+static' (e exemplu# declararea unei parole ar trebui facuta astfel)
transient private String parola' --ignorat la seriali5are
S(LS
0tentie
%odificatorul static anulea$a efectul modificatorului transient6
static transient private String parola' --participa la seriali5are
(e asemenea# nu participa la seriali$are sub+obiectele neseriali$abile ale unui obiect# adica cele ale
caror clase nu au fost declarate ca implement.nd interfata Seriali5able 3sau M/ternali5able4'
M/emplu, (c\mpurile marcate RSAR participa la seriali5are4 cele marcate RU[R4
nu participa)
class A { ... )
class 3 implements Seriali5able { ... )
public class @est implements Seriali5able {
private int /' -- SA
transient public int #' -- U[
static int var;' -- SA
97
transient static var2' -- 8
A a' -- U[
3 b;' -- SA
transient 3 b2' -- U[
)
;tunci c.nd o clasa seriali$abila deriva dintr+o alta clasa# salvarea c.mpurilor clasei parinte se va
face doar daca si aceasta este seriali$abila' In ca$ contrar# subclasa trebuie sa salve$e explicit si
c.mpurile mostenite'
M/;, class Larinte implements Seriali5able {
int /'
)
class Fiu e/tends Larinte implements Seriali5able {
int #'
)--Ca seriali5area obiectelor de tip Fiu se salvea5a at\t / c\t si #.
M/2, class Larinte {
int /'
)
class Fiu e/tends Larinte implements Seriali5able {
int #'
)--Seriali5area nu decurge normal.
Exemplu de $olosire a seriali(arii
import +ava.io..'
public class @estSeriali5are {
public static void main(String args!) t:ro&s 0=M/ception {
?#=b+ect ob+ 2 ne& ?#=b+ect(;<4 2<4 3<)'
--salvam obiectul in 6isierul $6isier.tmp$
File=utputStream 6out 2 ne& File=utputStream($6isier.tmp$)'
=b+ect=utputStream sout 2 ne& =b+ect=utputStream(6out)'
sout.&rite=b+ect(ob+)'
sout.6lus:()'
sout.close()'
6out.close()'
S#stem.out.println($A 6ost salvat obiectul $ D ob+)'
S#stem.out.println($Pestauram...$)'
File0nputStream 6in 2 ne& File0nputStream($6isier.tmp$)'
=b+ect0nputStream sin 2 ne& =b+ect0nputStream(6in)'
tr# {
ob+ 2 (?#=b+ect) sin.read=b+ect()'
) catc: (ClassUotFoundM/ception e) {)
sin.close()'
6in.close()'
S#stem.out.println($A 6ost restaurat obiectul $ D ob+)'
)
)
class ?#=b+ect implements Seriali5able {
int /' --este salvat
transient private int #' --nu este salvat
transient static int 5' --nu este salvat
public ?#=b+ect(int /4 int #4 int 5) {
t:is./ 2 /'
9=
t:is.# 2 #'
t:is.5 2 5'
)
public String toString() {
return ne& String($/2$ D / D $4 #2$ D # D $4 52$ D 5)'
)
)
>e$ultatul acestui pro!ram va fi )
A 6ost salvat obiectul /2;<4 #22<4 523<
Pestauram...
A 6ost restaurat obiectul /2;<4 #2<4 523<
Folosirea seriali(arii pentru copierea obiectelor
Se stie ca nu putem copia un obiect prin instructiunea de atribuire' O secventa de forma)
?#=b+ect o; 2 ne& ?#=b+ect(;<4 2<4 3<)'
?#=b+ect o2 2 o;'
nu face dec.t sa declare obiectul o7 ca fiind o referinta la obiectul o1 si prin urmarea orice
schimbare "ntr+unul din cele doua obiecte se va reflecta si "n celalalt'
O posibilitate de a face o copie unui obiect este folosirea metodei clone() a clasei Object'
?#=b+ect o; 2 ne& ?#=b+ect(;<4 2<4 3<)'
?#=b+ect o2 2 (?#=b+ect) o;.clone()'
Conversia la clasa ?#=b+ect este necesara deoarece metoda clone() returnea$a un obiect de tip
=b+ect' (eficienta acestei metode este ca nu functionea$a corect dec.t atunci c.nd clasa clonata
nu are c.mpuri referinta ca alte obiecte# obiectele referite nemaifiind copiate la r.ndul lor'
O metoda clone34 care sa reali$e$e o copie efectiva a unui obiect# "mpreuna cu copierea tuturor
obiectelor referite de c.mpurile acelui obiect poate fi implementata prin mecanismul seriali$arii
astfel)
public =b+ect clone() {
tr# {
3#teArra#=utputStream bout 2 ne& 3#teArra#=utputStream()'
=b+ect=utputStream out 2 ne& =b+ect=utputStream(bout)'
out.&rite=b+ect(t:is)'
out.close()'
3#teArra#0nputStream bin 2 ne& 3#teArra#0nputStream()'
=b+ect0nputStream in 2 ne& =b+ect0nputStream(bin)'
=b+ect ret 2 in.read=b+ect()'
in.close()'
return ret'
) catc: (M/ception e) {
S#stem.out.println(e)'
9D
return null'
)
)
Curs &
Colectii
Ce sunt colectiile ?
Interfetele de ba$a care descriu colectii
o Collection
o Set
o List
o %ap
o SortedSet
o Sorted%ap
Implementari ale colectiilor
olosirea eficienta a colectiilor
;l!oritmi
Iteratori si enumerari
Axemplu) !estionarea an!ajatilor unei companii
Top
Ce sunt colectiile 5
+e$initie
O colectie este un obiect care !rupea$a mai multe elemente "ntr+o sin!ura unitate' Erin colectii
vom avea acces la tipuri de date cum ar fi vectori# multimi# tabele de dispersie# etc' Colectiile sunt
folosite pentru memorarea si manipularea datelor# precum si pentru transmiterea datelor de la o
metoda la alta'
In Java colectiile sunt tratate intr+o maniera unitara# fiind or!ani$ate intr+o arhitectura ce cuprinde)
Inter$ete) tipuri abstracte de date ce descriu colectiile' Interfetele permit utili$area colectiilor
independent de detaliile implementarilor'
Implementari) implementari concrete ale interfetelor ce descriu colectii' ;ceste clase repre$inta
tipuri e ate reutili"abile'
0lgoritmi) metode care efectuea$a diverse operatii utile cum ar fi cautarea# sortarea definite
pentru obiecte ce implementea$a interfete ce descriu colectii' ;cesti al!oritmi se numesc si
polimorfici deoarece aceeasi metoda poate fi folosita pe implementari diferite ale unei colectii'
;ceste tipuri de al!oritmii descriu notiunea de functionalitate reutili"abila'
(intre avantajele oferite de utili$area colectiilor amintim)
8educerea e$ortului de programare) prin punerea la dispo$itia pro!ramatorului a unui set de
tipuri de date si al!oritmi ce modelea$a structuri si operatii des folosite in aplicatii'
9?
Cresterea vite(ei si calitatii programului) implementarile efective ale colectiilor sunt de inalta
performanta si folosesc al!oritmi cu timp de lucru optim' In scrierea unei aplicatii putem sa ne
concentram eforturile asupra problemei in sine si nu asupra modului de repre$entare si manipulare
a informatiilor'
Inter$ete ce descriu colectii
Interfetele ce descriu colectii repre$inta nucleul mecanismului de lucru cu colectii' Scopul acestor
interfete este de a permite utili$area colectiilor independent de modul lor de implementare' Ierarhia lor
este pre$entata in ima!inea de mai jos)
%ai jos sunt descrise structurile de date modelate de aceste interfete)
Collection
Collection descrie un !rup de obiecte numite si elementele sale' -nele implementari ale acestei interfete
permit existenta elementelor duplicate# alte implementari nu' -nele au elementele ordonate# altele nu'
%odelea$a o colectie la nivelul cel mai !eneral' In J(B nu exista nici o implementare directa a acestei
interfete# ci exista doar implementari ale unor subinterfete mai concrete cum ar fi Set sau Cist'
'et
%odelea$a notiunea de multime "n sens matematic' O multime nu poate avea elemente duplicate'
2ist
(escrie liste (secvente! de elemente indexate' Listele pot contine duplicate si permit un control precis
asupra po$itiei unui element prin intermediul indexului acelui element'
O clasa independenta ce implementea$a o functionalitate asemanatoare este clasa Qector'
9@
Map
Implementarile acestei interfete sunt obiecte ce asocia$a fiecarui element o cheie unica' 1u pot contine
asadar chei duplicate si fiecare chei este asociata la un sin!ur element'
O clasa independenta ce implementea$a o functionalitate asemanatoare este clasa %as:@able'
'orted'et
Aste asemanatoare cu interfata Set la care se adau!a faptul ca elementele dintr+o astfel de colectie sunt
ordonate ascendent' Eune la dispo$itie operatii care beneficia$a de avantajul ordonarii elementelor'
'ortedMap
Aste asemanatoare cu interfata ?ap la care se adau!a faptul ca multimea cheilor dintr+o astfel de colectie
este ordonata ascendent'
Inter$ata Collection
Interfata Collection modelea$a un !rup de obiecte numite elemente' Scopul acestei interfete este de a
folosi colectii la un nivel de maxima !eneralitate' In definitia interfetei vom observa ca metodele se
impart in trei cate!orii'
public inter6ace Collection {
-- =peratii de ba5a la nivel de element
int si5e()'
boolean isMmpt#()'
boolean contains(=b+ect element)'
boolean add(=b+ect element)' -- =ptional
boolean remove(=b+ect element)' -- =ptional
0terator iterator()'
-- =peratii la nivel de colectie
boolean containsAll(Collection c)'
boolean addAll(Collection c)' -- =ptional
boolean removeAll(Collection c)' -- =ptional
boolean retainAll(Collection c)' -- =ptional
void clear()' -- =ptional
-- =peratii de conversie in vector
=b+ect! toArra#()'
=b+ect! toArra#(=b+ect a!)'
)
Inter$ata 'et
%odelea$a notiunea de multime "n sens matematic' O multime nu poate avea elemente duplicate'
(efineste aceleasi metode ca interfata Collection' (oua dintre clasele care ofera implementari concrete
ale acestei interfete sunt <ashSet si TreeSet' 3ve$i *Implementari*4
Inter$ata 2ist
99
Interfata Cist descrie liste (secvente! de elemente indexate' Listele pot contine duplicate si permit un
control precis asupra po$itiei unui element prin intermediul indexului acelui element' In plus fata de
elementele definite de interfata Collection avem metode pentru)
acces po$itional
cautare 3aflarea indexului unui element4
iterare ordonata
extra!erea unei subliste
(efinitia interfetei este data mai jos)
public inter6ace Cist e/tends Collection {
-- Acces po5itional
=b+ect get(int inde/)'
=b+ect set(int inde/4 =b+ect element)' -- =ptional
void add(int inde/4 =b+ect element)' -- =ptional
=b+ect remove(int inde/)' -- =ptional
abstract boolean addAll(int inde/4 Collection c)' -- =ptional
-- Cautare
int inde/=6(=b+ect o)'
int last0nde/=6(=b+ect o)'
-- 0terare
Cist0terator list0terator()'
Cist0terator list0terator(int inde/)'
-- M/tragere sublista
Cist subCist(int 6rom4 int to)'
)
(oua clase care implementea$a interfata Cist sunt rray9ist si Vector'
Inter$ata Map
Implementarile acestei interfete sunt obiecte ce asocia$a fiecarui element o cheie unica' 1u pot contine
asadar chei duplicate si fiecare chei este asociata la un sin!ur element'
(efinitia interfetei este data mai jos)
public inter6ace ?ap {
-- =peratii de ba5a la nivel de element
=b+ect put(=b+ect Ne#4 =b+ect value)'
=b+ect get(=b+ect Ne#)'
=b+ect remove(=b+ect Ne#)'
boolean containsVe#(=b+ect Ne#)'
boolean containsQalue(=b+ect value)'
int si5e()'
boolean isMmpt#()'
-- =peratii la nivel de colectie
void putAll(?ap t)'
void clear()'
-- Qi5uali5ari ale colectiei
public Set Ne#Set()'
public Collection values()'
public Set entr#Set()'
-- 0nter6ata pentru manipularea unei inregistrari
public inter6ace Mntr# {
=b+ect getVe#()'
=b+ect getQalue()'
=b+ect setQalue(=b+ect value)'
9:
)
)
Clase care implementea$a interfata ?ap sunt <ash=ap# Tree=ap si <ashta&le'
Inter$ata 'orted'et
Aste asemanatoare cu interfata Set la care se adau!a faptul ca elementele dintr+o astfel de colectie sunt
ordonate ascendent conform ordinii lor naturale# sau conform cu ordinea data de un comparator specificat
la crearea colectiei'
Aste subclasa a interfetei Set# oferind metode suplimentare pentru)
extra!ere de subliste
aflarea primuluiJultimului element din lista
aflarea comparatorului folosit pentru ordonare
(efinitia interfetei este data mai jos)
public inter6ace SortedSet e/tends Set {
-- Subliste
SortedSet subSet(=b+ect 6romMlement4 =b+ect toMlement)'
SortedSet :eadSet(=b+ect toMlement)'
SortedSet tailSet(=b+ect 6romMlement)'
-- Capete
=b+ect 6irst()'
=b+ect last()'
Comparator comparator()'
)
Inter$ata 'ortedMap
Aste asemanatoare cu interfata ?ap la care se adau!a faptul ca multimea cheilor dintr+o astfel de colectie
este ordonata ascendent conform ordinii naturale# sau conform cu ordinea data de un comparator
specificat la crearea colectiei'
Aste subclasa a interfetei ?ap# oferind metode suplimentare pentru)
extra!ere de subtabele
aflarea primeiJultimei chei
aflarea comparatorului folosit pentru ordonare
(efinitia interfetei este data mai jos)
public inter6ace Sorted?ap e/tends ?ap {
Sorted?ap sub?ap(=b+ect 6romVe#4 =b+ect toVe#)'
Sorted?ap :ead?ap(=b+ect toVe#)'
Sorted?ap tail?ap(=b+ect 6romVe#)'
=b+ect 6irst()'
=b+ect last()'
Comparator comparator()'
)
9<
Implementari ale colectiilor
Clasele de ba$a care implementea$a interfete ce descriu colectii sunt pre$entate in tabelul de mai jos'
1umele lor este de forma S0mplementareTS0nter6ataT# unde ,implementare, se refera la structura de
date folosita'
Implementari
Interfete
'et CashSet TreeSet
2ist ;rra&List LinFedList
Map Cash%ap Tree%ap
J(B 1'7 furni$ea$a c.te doua clase ce implementea$a fiecare tip de colectie# "n fiecare ca$ prima
implementare fiind cea de ba$a# care va fi in !eneral folosita' ;cestea sunt) %as:Set4 Arra#Cist si
%as:?ap'
Clasele care descriu colectii au multe trasaturi comune cum ar fi)
permit elementul null
sunt seriali$abile
au definita metoda clone
au definita metoda toString# care returnea$a o repre$entare ca sir de caractere a colectiei
respective
permit crearea iteratorilor pentru parcur!ere
implementarea interfetelor este indirecta# "n sensul ca au o
Implementarea interfetelor este indirecta "n sensul ca aceste clase au superclase abstracte care ofera
implementari concrete pentru majoritatea metodelor definite de interfete' Cele mai importante superclase
sunt &stract$ollection si &stract=ap# din care sunt apoi extinse clasele abstracte &stract9ist si
&stractSet#respectiv &stract=ap'
Clasele pre$entate in tabelul de mai sus sunt extensii concrete ale claselor abstracte aminitite'
Sin!ura interfata care nu are nici o implementare este Collection'
Folosirea e$icienta a colectiilor
(upa cum am va$ut# fiecare interfata ce descrie o colectie are c.te doua implementari# dintre care una este
de ba$a# fiind folosita in <8M din ca$uri' (e exemplu# interfata Cist este implementata de clasele
Arra#Cist si CinNedCist# prima fiind cea mai folosita' (e ce exista atunci si clasa CinNedCist ?
>aspunsul consta in faptul ca implementari diferite ale interfetelor pot oferi performante mai bune in
functie de situatie# prin reali$area unor compromisuri "ntre spatiul necesar pentru repre$entarea datelor#
rapiditatea re!asirii acestora si timpul necesar actuali$arii colectiei in ca$ul unor modificari'
Sa consideram urmatoarele exemple ce creea$a o lista folosind Arra#Cist# respectiv CinNedCist si
executa diverse operatii pe ea'
--e/emplul ;
import +ava.util..'
public class Cist; {
:8
public static void main(String(args!) {
Cist lst 2 ne& Arra#Cist()'
--Cist lst 2 ne& CinNedCist()'
6inal int U 2 2(<<<'
6or(int i2<' i A U' iDD)
lst.add(ne& 0nteger(i))'
--.
)
)
--e/emplul 2 - Cist2
Adaugam la e/emplul ; (.) urmatoarea secventa
6or(int i2<' i A U' iDD)
lst.get(i)'
--e/emplul 3 - Cist3
Adaugam la e/emplul ; (.) urmatoarea secventa
6or(int i2<' i A U' iDD)
lst.remove(<)'
Timpii aproximativi de rulare a acestor pro!rame sunt dati in tabelul de mai jos)
0rraE2ist 2inAed2ist
List1 3add4 8'D 8'D
List7 3!et4 8'D 71'=
List= 3remove4 @'< 8'D
;sadar# adau!area elementelor este rapida pentru ambele tipuri de liste' Arra#Cist ofera acces in timp
constant la elementele sale si din acest motiv folosirea lui *!et* este rapida# "n timp ce pentru CinNedCist
este extrem de lenta# deoarece intr+o lista inlantuita accesul la un element se face prin parcur!erea
secventiala a listei p.na la elementul respectiv'
La eliminarea elementelor din lista folosirea lui Arra#Cist este lenta deoarece elementele ramase sufera
un proces de reindexare 3shift la st.n!a4 in timp ce pentru CinNedCist este rapida si se face prin simpla
schimbare a unor le!aturi'
(eci# Arra#Cist se comporta bine pentru ca$uri in care avem nevoie de re!asirea unor elemente la po$itii
diferite in lista# iar CinNedCist functionea$a optim atunci c.nd facem multe operatii de editare3ster!eri#
inserari4 "n corpul listei'
(e asemenea# Arra#Cist foloseste mai eficient spatiul de memerie dec.t CinNedCist# deoarece aceasta
din urma are nevoie de o structura de date auxiliara pentru memorare unui nod' 1odurile sunt repre$entate
prin instante ale unei clase interne# av.nd forma)
class Mntr# {
=b+ect element'
Mntr# ne/t'
Mntr# previous'
)
Conclu(ia nu este ca una din aceste clase este mai *buna* dec.t cealalta# ci ca exista diferente
substantiale in repre$entarea si comportamentul diferitelor implementari ale colectiilor si ca ale!erea unei
clase pentru repre$entarea unei colectii trebuie sa se faca "n functie de natura problemei ce trebuie
re$olvata' ;cest lucru este valabil pentru toate tipurile de colectii' (e exemplu# %as:Set si @reeSet sunt
doua modalitati de repre$entare a multimilor' Erima se ba$ea$a pe folosirea unei tabele de dispersie# a
doua pe folosirea unei structuri arborescente'
0lgoritmi
*lgorimtii polimorfici descrisi "n aceasta sectiune sunt metode definite "n clasa $ollections care permit
efectuarea unor operatii utile cum ar fi cautarea# sortarea#etc' Caracterisiticile principale ale al!oritmilor
sunt)
sunt metode statice
:1
au un sin!ur ar!ument de tip colectie
apelul lor va fi de forma $ollections.algoritm'[colectie](
majoritatea operea$a pe liste dar si pe colectii arbitrare
%etodele mai importante din clasa Collections sunt date in tabelul de mai jos)
sort
Sortea$a ascendent o lista referitor la ordinea sa naturala sau la ordinea data de un
comparator
s%u$$le ;mesteca elementele unei liste + opusul lui sort
binarE'earc% Afectuea$a o cautare binara a unui element "ntr+o lista ordonata
reverse Inversea$a ordinea elementelor dintr+o lista
$ill Eopulea$a o lista cu un element
copE Copie elementele unei liste in alta
min >eturnea$a minimul dintr+o colectie
max >eturnea$a maximul dintr+o colectie
enumeration >eturnea$a o enumerare a elementelor dintr+o colectie
Iteratori si enumerari
Anumerarile si iteratorii descriu modalitati pentru parcur!erea secventiala a unei colectii' Ai sunt descrisi
de obiecte ce implementea$a interfetele 1numeration# respectiv 0terator sau 9ist0terator' Toate
clasele care implementea$a colectii au metode ce returnea$a o enumerare sau un iterator pentru
parcur!erea elementelor lor' %etodele acestor interfete sunt date in tabelul de mai jos# semnificatiile lor
fiind evidente)
Enumeration Iterator 2istIterator
boolean :as?oreMlements()
=b+ect ne/tMlement()
boolean :asUe/t()
=b+ect ne/t()
void remove()
boolean :asUe/t()4:asLrevious()
=b+ect ne/t()4 previous()
void add(=b+ect o) void remove()
void set(=b+ect o)
Iteratorii simpli permit eliminarea elementului curent din colectia pe care o parcur!# cei ordonati 3de tip
Cist0terator4 permit si inserarea unui element la po$itia curenta# respectiv modificarea elementului
curent'
Iteratorii sunt preferati enumerarilor datorita posibilitatii lor de a actiona asupra colectiei pe care o
parcur! prin metode de tip remove4 add4 set dar si prin faptul ca denumirile metodelor sunt mai
concise'
In exemplul de mai jos punem "ntr+un vector numerele de la 1 la 18# le amestecam# dupa care le
parcur!em element cu element folosind un iterator'
import +ava.util..'
class @est0terator{
public static void main(String args!) {
Arra#Cist a 2 ne& Arra#Cist()'
6or(int i2<' iA;<' iDD) a.add(ne& 0nteger(i))'
Collections.s:u66le(a)' --amestecam elementele colectiei
S#stem.out.println($Qectorul amestecat, $ D a)'
S#stem.out.println($Larcurgem vectorul element cu element,$)'
:7
S#stem.out.println($Bnvarianta ;, cu &:ile$)'
0terator it 2 a.iterator()'
&:ile (it.:asUe/t())
S#stem.out.print(it.ne/t() D $ $)'
S#stem.out.println($Bnvarianta 2, cu 6or$)'
6or(it2a.iterator()' it.:asUe/t()' )
S#stem.out.print(it.ne/t() D $ $)'
)
)
Exemplu
In exemplul de mai jos vom folosi clasa %as:?ap pentru a tine evidenta an!ajatilor unei companii' Vom
folosi mecanismul seriali$arii pentru salvarea informatiilor intr+un fisier# respectiv pentru restaurarea lor'
--clasa Anga+at
import +ava.io.Seriali5able'
class ngajat implements Seriali5able {
String cod'
String nume'
int salar'
public Anga+at(String cod4 String nume4 int salar) {
t:is.cod2cod'
t:is.nume2nume'
t:is.salar2salar'
)
public String toString() {
return cod D $Bt$ D nume D $Bt$ D salar'
)
)
--clasa Lersonal
import +ava.io..'
import +ava.util..'
class 6ersonal implements Seriali5able {
%as:?ap personal 2 ne& %as:?ap()'
String 6isier2null'
boolean salvat26alse'
void load(String 6is) t:ro&s 0=M/ception{
=b+ect0nputStream in2null'
t:is.6isier26is'
tr# {
in2ne& =b+ect0nputStream(ne& File0nputStream(6isier))'
personal 2 (%as:?ap)in.read=b+ect()'
) catc:(FileUotFoundM/ception e) {
S#stem.out.println($Fisierul $ D 6isier D $ nu e/ista>$)'
) catc:(ClassUotFoundM/ception e) {
S#stem.out.println($Mroare la incarcarea datelor>$)'
)6inall# {
i6 (in >2 null)
in.close()'
)
)
void saveAs(String 6is) t:ro&s 0=M/ception{
=b+ect=utputStream out2null'
tr# {
out2ne& =b+ect=utputStream(ne& File=utputStream(6is))'
out.&rite=b+ect(personal)'
salvat2true'
S#stem.out.println($Salvare reusita in 6isierul $ D 6is)'
:=
)catc:(0=M/ception e) {
S#stem.out.println($Salvarea nu a reusit>$)'
)6inall# {
i6 (out >2 null)
out.close()'
)
)
void save() t:ro&s 0=M/ception {
i6 (6isier 22 null) 6isier2$personal.t/t$'
saveAs(6isier)'
)
Anga+at getAnga+at(String argumente) {
String cod2$$4 nume2$$'
int salar2<'
tr# {
String@oNeni5er st2ne& String@oNeni5er(argumente)'
cod 2 st.ne/t@oNen()'
nume 2 st.ne/t@oNen()'
salar 2 0nteger.parse0nt(st.ne/t@oNen())'
)catc:(UoSuc:MlementM/ception e) {
S#stem.out.println($Argumente incomplete>$)'
)catc:(UumberFormatM/ception e) {
S#stem.out.println($Salarul trebuie sa 6ie numeric>$)'
)
return ne& Anga+at(cod4 nume4 salar)'
)
boolean add(String argumente) {
Anga+at a2getAnga+at(argumente)'
i6 (personal.containsVe#(a.cod)) {
S#stem.out.println($?ai e/ista un anga+at cu acest cod>$)'
return 6alse'
)
personal.put(a.cod4 a)'
salvat26alse'
return true'
)
boolean delete(String cod) {
i6 (personal.remove(cod) 22 null) {
S#stem.out.println($Uu e/ista nici un anga+at cu acest cod>$)'
return 6alse'
)
salvat26alse'
return true'
)
void update(String argumente) {
Anga+at a2getAnga+at(argumente)'
delete(a.cod)'
add(argumente)'
)
void list() {
0terator it2personal.values().iterator()'
&:ile (it.:asUe/t()) S#stem.out.println((Anga+at)(it.ne/t()))'
)
void e/ecutaComen5i() {
String linie4 comanda4 argumente'
tr# {
3u66eredPeader stdin2ne& 3u66eredPeader(ne&
0nputStreamPeader(S#stem.in))'
&:ile (true) {
linie 2 stdin.readCine().trim()'
:D
String@oNeni5er st2ne& String@oNeni5er(linie)'
comanda2st.ne/t@oNen()'
argumente2$$'
&:ile (st.:as?ore@oNens()) argumente D2 st.ne/t@oNen()
D $ $'
argumente2argumente.trim()'
i6 (comanda.starts]it:($e/it$)) breaN'
else i6 (comanda.starts]it:($add$)) add(argumente)'
else i6 (comanda.starts]it:($del$)) delete(argumente)'
else i6 (comanda.starts]it:($update$))
update(argumente)'
else i6 (comanda.starts]it:($list$)) list()'
else i6 (comanda.starts]it:($load$)) load(argumente)'
else i6 (comanda.starts]it:($saveAs$))
saveAs(argumente)'
else i6 (comanda.starts]it:($save$)) save()'
else S#stem.out.println($&:at K$)'
)
i6 (>salvat) save()'
S#stem.out.println($b#e...$)'
)catc: (0=M/ception e) {
S#stem.out.println($Mroare 0-=,$ D e)'
e.printStacN@race()'
)
)
)
--clasa principala 9estiuneAnga+ati
public class >estiunengajati {
public static void main(String args!) {
Lersonal p 2 ne& Lersonal()'
p.e/ecutaComen5i()'
)
)
Curs )
Inter$ata gra$ica
Erivire de ansamblu asupra interfetei !rafice
Componente ;/T
Suprafete de afisare 3Clasa Container4
Iestionarea po$itionarii
o olosirea !estionarilor de po$itionare
o Iruparea componentelor 3Clasa Eanel4
Tratarea evenimentelor
o Axemplu de tratare a evenimentelor
o Tipuri de evenimente si componentele care le !enerea$a
o Avenimente suportate de o componenta
o %etodele interfetelor de tip *Listener*
o olosirea adaptorilor si a claselor interne "n tratarea evenimentelor
olosirea ferestrelor
o Clasa /indo0
o Clasa rame
o Clasa (ialo! 3ferestre de dialo!4
:?
o Clasa ile(ialo!
olosirea meniurilor
o Tratarea evenimentelor !enerate de meniuri
o %eniuri de context 3popup4
o ;cceleratori 3clasa %enuShortcut4
olosirea componentelor
o Label
o Hutton
o ChecFbox
o ChecFboxIroup
o Choice
o List
o Scrollbar
o ScrollEane
o Textield
o Text;rea
Top
Privire de ansamblu asupra inter$etei gra$ice
Interfata !rafica sau# mai bine $is# interfata grafica cu utili"atorul (+,(!# este un termen cu "nteles lar!
care se refera la toate tipurile de comunicare vi$uala "ntre un pro!ram si utili$atorii sai' ;ceasta este o
particulari$are a interfetei cu utili$atorul 3-I4# prin care vom "ntele!e conceptul !eneric de interactiune
"ntre un pro!ram si utili$atorii sai' ;sadar# -I se refera nu numai la ceea ce utili$atorul vede pe ecran ci la
toate mecanismele de comunicare "ntre acesta si pro!ram'
Limbajul Java pune la dispo$itie numeroase clase pentru implementarea diverselor functionalitati -I# "nsa
ne vom ocupa "n continuare de acelea care permit reali$area unei intefete !rafice cu utili$atorul 3I-I4'
Hiblioteca de clase care ofera servicii !rafice se numeste 4ava3aFt# ;/T fiind prescurtarea de la *bstract
-ino. Tool/it si este pachetul care care a suferit cele mai multe modificari "n trecerea de la o versiune
J(B la alta'
In principiu# crearea unei aplicatii !rafice presupune urmatoarele lucruri)
Crearea unei suprafete de afisare 3cum ar fi o fereastra4 pe care vor fi ase$ate obiectele !rafice
care servesc la comunicarea cu utili$atorul 3butoane# controale de editare# texte# etc46
Crearea si ase$area obiectelor !rafice pe suprafata de afisare "n po$itiile corespun$atoare6
(efinirea unor actiuni care trebuie sa se execute "n momentul c.nd utili$atorul interactionea$a cu
obiectele !rafice ale aplicatiei6
*;scultarea* evenimentelor !enerate de obiecte "n momentul interactiunii cu utili$atorul si
executarea actiunilor corespun$atoare asa cum au fost ele definite'
%ajoritatea obiectelor !rafice sunt subclase ale clasei Component# clasa care defineste !eneric o
componenta !rafica care poate interactiona cu utili$atorul' Sin!ura exceptie o constituie meniurile care
descind din clasa MenuComponent'
;sadar# print+o componenta sau componenta !rafica vom "ntele!e "n continuare orice obiect care are o
repre$entare !rafica ce poate fi afisata pe ecran si care poate interactiona cu utili$atorul' Axemple de
componente sunt ferestrele# butoanele# bare de defilare# etc' In !eneral# toate componentele sunt definte de
clase proprii ce se !asesc "n pachetul +ava.a&t# clasa Component fiind superclasa abstracta a tuturor
acestor clase'
:@
Crearea obiectelor !rafice nu reali$ea$a automat si afisarea lor pe ecran' %ai "nt.i ele trebuie ase$ate pe o
suprafata de afisare# care poate fi o fereastra sau suprafata unui applet# si vor deveni vi$ibile "n momentul
"n care suprafata pe care sunt afisate va fi vi$ibila' O astfel de suprafata pe care se asea$a obiectele !rafice
repre$inta o instanta a unei clase obtinuta prin extensia clasei Container6 din acest motiv suprafetele de
afisare vor mai fi numite si containere' Clasa Container este o subclasa aparte a clasei Component# fiind
la r.ndul ei superclasa tuturor suprafetelor de afisare Java 3ferestre# applet+uri# etc4' 3ve$i *Suprafete de
afisare*4
;sa cum am va$ut# interfata !rafica serveste interactiunii cu utili$atorul' (e cele mai multe ori pro!ramul
trebuie sa faca o anumita prelucrare "n momentul "n care utili$atorul a efectuat o actiune si# prin urmare#
obiectele !rafice trebuie sa !enere$e evenimente "n functie de actiunea pe care au suferit+o 3actiune
transmisa de la tastatura# mouse# etc'4' Incep.nd cu versiunea 1'1 a limbajului Java evenimentele se
implementea$a ca obiecte instanta ale clasei 0?TEvent sau ale subclaselor ei'
-n eveniment este produs de o actiune a utili$atorului asupra unui obiect !rafic# deci evenimentele nu
trebuie !enerate de pro!ramator' In schimb "ntr+un pro!ram trebuie specificat codul care se executa la
aparitia unui eveniment' Interceptarea evenimentelor se reali$ea$a prin intermediul unor clase de tip
listener 3ascultator# consumator de evenimente4# clase care sunt definite "n pachetul 4ava3aFt3event' In
Java# orice componenta poate *consuma* evenimentele !enerate de o alta componenta !rafica' 3ve$i
*Tratarea evenimentelor*4
Exemplu7 crearea unei $erestre ce contine doua butoane
import +ava.a&t..'
public class @estA]@; {
public static void main(String args!) {
--cree5 6ereastra - un obiect de tip 6rame
Frame 6 2 ne& Frame($= 6ereastra$)'
--sete5 modul de dipunere a ob. pe supra6ata 6erestrei
6.setCa#out(ne& Flo&Ca#out())'
--cree5 cele doua butoane
3utton b; 2 ne& 3utton($=V$)'
3utton b2 2 ne& 3utton($Cancel$)'
--adaug primul buton pe supra6ata 6erestrei
6.add(b;)'
6.pacN()'
--adaug al doile buton pe supra6ata 6erestrei
6.add(b2)'
6.pacN()'
--a6ise5 6ereastra (o 6ac vi5ibila)
6.s:o&()'
)
)
(upa cum veti observa la executia acestui pro!ram# at.t butoanele adau!ate de noi c.t si butonul de
"nchidere a ferestrei sunt functionale# adica pot fi apasate# dar nu reali$ea$a nimic' ;cest lucru se "nt.mpla
deoarece nu am specificat nicaieri codul care trebuie sa se execute la apasarea acestor butoane'
(e asemenea mai trebuie remarcat ca nu am specificat nicaieri dimensiunile ferestrei sau ale butoanelor si
nici po$itiile "n acestea sa fie plasate' Cu toate acestea ele sunt plasate unul l.n!a celalalt# fara sa se
suprapuna iar suprafata fereastrei este suficient de mare c.t sa cuprinda ambele obiecte' ;ceste
*fenomene* sunt provocate de un obiect special de tip Flo&Ca#out care se ocupa cu !estionarea ferestrei
si cu plasarea componentelor "ntr+o anumita ordine pe suprafata ei'
;sadar# modul de aranjare nu este o caracteristica a suprafetei de afisare' iecare obiect de tip Container#
sau o extensie a lui# are asociat un obiect care se ocupa cu dispunerea componentelor pe suprafata de
afisare si care se numeste gestionar e po"itionare ($ayout 'anager!' 3ve$i *Iestionarea po$itionarii*4
:9
Componente 0?T
Erin componenta vom "ntele!e "n continuare orice obiect care are o repre$entare !rafica ce poate fi afisata
pe ecran si care poate interactiona cu utili$atorul' Axemple de componente sunt ferestrele# butoanele# bare
de defilare# etc' In !eneral# toate componentele sunt definte de clase proprii ce se !asesc "n pachetul
+ava.a&t# clasa Component fiind superclasa abstracta a tuturor acestor clase'
Ierarhia acestor clase este sumari$ata "n dia!rama de mai jos'
(in cau$a unor diferente esentiale "n implementarea meniurilor pe diferite platforme de operare acestea
nu au putut fi inte!rate ca obiecte de tip Component' Superclasa care descrie meniuri este
MenuComponent iar ierarhia subclaselor sale este data "n dia!rama de mai jos)
;sadar# majoritatea obiectelor !rafice sunt subclase ale clasei Component# clasa care defineste !eneric o
componenta !rafica care poate interactiona cu utili$atorul' Sin!ura exceptie o constituie meniurile care
descind din clasa ?enuComponent'
'upra$ete de a$isare Clasa Container"
Crearea obiectelor !rafice nu reali$ea$a automat si afisarea lor pe ecran' %ai "nt.i ele trebuie ase$ate pe o
suprafata# care poate fi o fereastra sau suprafata unui applet# si vor deveni vi$ibile "n momentul "n care
suprafata pe care sunt afisate va fi vi$ibila' O astfel de suprafata pe care se asea$a obiectele !rafice se
numeste suprafata e afisare sau container si repre$inta o instanta a unei clase obtinuta prin extensia
superclasei Container' O parte din ierarhia a carei radacina este Container este pre$entata "n fi!ura de
mai jos)
::
;sadar# un container este folosit pentru a adau!a componente pe suprafata lui' Componentele adau!ate
sunt memorate "ntr+o lista iar po$itiile lor din aceasta lista vor defini ordinea de traversare *front+to+bacF*
a acestora "n cadrul containerului' (aca nu este specificat nici un index la adau!area unei componente
atunci ea va fi adau!ata pe ultima po$itie a listei'
0daugarea unei componente
Clasa Container pune la dispo$itie metoda add pentru adau!area unei componente pe o suprafata de
afisare' O componenta nu poate apartine dec.t unui sin!ur container# ceea ce "nseamna ca pentru a muta
un obiect dintr+un container "n altul trebuie sa+l eliminam mai "nt.i de pe containerul initial' Aliminarea
unei componente de pe un container se face cu metoda remove'
Frame 6 2 ne& Frame($= 6ereastra$)'
3utton b 2 ne& 3utton($=V$)'
6.add(b)' --adauga butonul pe supra6ata 6erestrei
6.s:o&()'
=estionarea po(itionarii
Sa consideram mai "ntai un exemplu de pro!ram Java care afisea$a ? butoane pe o fereastra)
import +ava.a&t..'
public class @estCa#out {
public static void main(String args!) {
Frame 6 2 ne& Frame($9rid Ca#out$)'
6.setCa#out(ne& 9ridCa#out(34 2))' --.
3utton b; 2 ne& 3utton($3utton ;$)'
3utton b2 2 ne& 3utton($2$)'
3utton b3 2 ne& 3utton($3utton 3$)'
3utton b" 2 ne& 3utton($Cong-Uamed 3utton "$)'
3utton b( 2 ne& 3utton($3utton ($)'
6.add(b;)' 6.add(b2)' 6.add(b3)' 6.add(b")' 6.add(b()'
6.pacN()'
6.s:o&()'
)
)
ereastra afisata de acest pro!ram va arata astfel)
:<
Sa modificam acum linia marcata cu ,K, ca mai jos# las.nd neschimbat restul pro!ramului)
Frame 6 2 ne& Frame($Flo& Ca#out$)'
6.setCa#out(ne& Flo&Ca#out())'
ereastra afisata dupa aceasta modificare va avea o cu totul altfel de dispunere a componentelor sale)
%otivul pentru care cele doua ferestre arata at.t de diferit este ca folosesc !estionari de po$itionare
diferiti) 9ridCa#out# respectiv Flo&Ca#out'
-n gestionar e po"itionare (layout manager! este un obiect care controlea$a dimensiunea si aranjarea
3po$itia4 componentelor unui container' ;sadar# modul de aranjare a componentelor pe o suprafata de
afisare nu este o caracteristica a clasei Container' iecare obiect de tip Container# sau o extensie a lui
3Applet4 Frame4 Lanel4 are asociat un obiect care se ocupa cu dispunerea componentelor pe suprafata
sa ) !estionarul de po$itionare' Toate clasele care instantia$a obiecte pentru !estionarea po$itionarii
implementea$a interfata 2aEoutManager'
La instantierea unui container se creea$a implicit un !estionar de po$itionare asociat acestui container' (e
exemplu pentru o fereastra 3un obiect de tip ]indo& sau o subclasa a sa4 !estionarul implict este de tip
3orderCa#out# "n timp ce pentru un container de tip Lanel este o instanta a clasei Flo&Ca#out'
Folosirea gestionarilor de po(itionare
;sa cum am va$ut# orice container are un !estionar implicit de po$itionare + un obiect care implemenea$a
interfata 2aEoutManager# acesta fiindu+i atasat automat la crearea sa' In ca$ul "n care acesta nu
corespunde necesittailor noastre el poate fi schimbat cu usurinta' Cei mai utili$ati !estionari din pachetul
+ava.a&t sunt)
lo0La&out
HorderLa&out
IridLa&out
CardLa&out
IridHa!La&out
;tasarea explicita a unui !estionar de po$itionare la un container se face cu metoda set2aEout a clasei
Container' %etoda poate primi ca parametru orice instanta a unei clase care implementea$a interfata
Ca#out?anager' Secventa de atasare a unui !estionar pentru un container este)
Flo&Ca#out gestionar 2 ne& Flo&Ca#out()'
container.setCa#out(gestionar)'
sau4 mai u5ual ,
container.setCa#out(ne& Flo&Ca#out())'
Ero!ramele nu apelea$a "n !eneral metode ale !estionarilor de po$itionare iar "n ca$ul c.nd avem nevoie
de obiectul !estionar "l putem obtine cu metoda get2aEout din clasa Container'
-na din facilitatile cele mai utile oferite de !estionarii de po$itionare este rearanjarea componentele unui
container atunci c.nd acesta este redimesionat' Eo$itiile si dimensiunile componentelor nu sunt fixe# ele
fiind ajustate automat de catre !estionar la fiecare redimensionare astfel "nc.t sa ocupe c.t mai *estetic*
suprafata de afisare'
Sunt "nsa situatii c.nd dorim sa plasam componentele la anumite po$itii fixe iar acestea sa ram.na acolo
<8
chiar daca redimensionam containerul' olosind un !estionar de po$itionare aceasta po"itionare absoluta
a componentelor nu este posibila si deci trebuie cumva sa renuntam la !estionarea automata a containerul'
;cest lucru se reali$ea$a prin trimitera ar!umentului null metodei setCa#out)
--po5itionare absoluta a componentelor in container
container.setCa#out(null)'
olosind po$itionarea absoluta# nu va mai fi suficient sa adau!am cu metoda add componentele "n
container ci va trebui sa specificam po$itia si dimensiunea lor + acest lucru era facut automat de
!estionarul de po$itionare'
container.setCa#out( null )'
3utton b 2 ne& 3utton($3uton$)'
b.setSi5e(;<4 ;<)'
b.setCocation (<4 <)'
b.add()'
In !eneral# se recomanda folosirea !estionarilor de po$itionare "n toate situatiile c.nd acest lucru este
posibil# deoarece permit pro!ramului sa aiba aceeasi *"nfatisare* indiferent de platforma si re$olutia pe
care este rulat' Eo$itionarea fixa poate ridica diverse probleme "n acest sens'
Sa anali$am "n continuare pe fiecare din cei cinci !estionari amintiti anterior'
=estionarul FloF2aEout
;cest !estionar asea$a componentele pe suprafata de afisare "n flux liniar# mai precis# componentele sunt
adau!ate una dupa alta pe linii# "n limita spatiului disponibil' In momentul c.nd o componenta nu mai
"ncape pe linia curenta se trece la urmatoarea linie# de sus "n jos'
;dau!area componentelor se face de la st.n!a la dreapta pe linie# iar alinierea obiectelor "n cadrul unei
linii poate fi de trei feluri ) la st.n!a# la drepata# centrate' Implicit componentele sunt centrate pe fiecare
linie iar distanta implicita "ntre componente este de ? unitati pe verticala si ? pe ori$ontala'
Aste !estionarul implicit al containerelor derivate din clasa Lanel deci si al applet+urilor'
(imeniunile componentelor afisate sunt preluate automat de catre !estionar prin intermediul metodei
getLre6erredSi5e# implementata de toate componentele standard'
--M/emplu
import +ava.a&t..'
public class @estCa#out {
public static void main(String args!) {
Frame 6 2 ne& Frame($Flo& Ca#out$)'
6.setCa#out(ne& Flo&Ca#out())'
3utton b; 2 ne& 3utton($3utton ;$)'
3utton b2 2 ne& 3utton($2$)'
3utton b3 2 ne& 3utton($3utton 3$)'
3utton b" 2 ne& 3utton($Cong-Uamed 3utton "$)'
3utton b( 2 ne& 3utton($3utton ($)'
6.add(b;)' 6.add(b2)' 6.add(b3)' 6.add(b")' 6.add(b()'
6.pacN()'
6.s:o&()'
)
)
Componentele ferestrei vor fi afisate astfel)
>edimension.nd fereastra astfel "nc.t cele cinci butoane sa nu mai "ncapa pe o linie# ultimele dintre ele
vor fi trecute pe linia urmatoare)
<1
=estionarul @order2aEout
Iestionarul 3orderCa#out "mparte suprafata de afisare "n cinci re!iuni# corespun$atoare celor patru
puncte cardinale si centrului' O componenta poate fi plasata "n oricare din aceste re!iuni# dimeniunea
componentei fiind calculata astfel "nc.t sa ocupe "ntre! spatiul de afisare oferit de re!iunea respectiva'
Eentru a adau!a mai multe obiecte !rafice "ntr+una din cele cinci $one# ele trebuie !rupate "n prealabil
"ntr+un panel# care va fi amplasat apoi "n re!iunea dorita'3ve$i *Iruparea componentelor + clasa Eanel*4
;sadar# la adau!area unei componente pe o suprafata !estionata de 3orderCa#out# metoda add va mai
primi pe l.n!a numele componentei si $ona "n care aceasta va fi amplasata# acesta fiind apecificata prin
una din constantele clasei 3orderCa#out) N%2T<* S%?T<* 1ST* 41ST* $1NT12 '
Aste !estionarul implicit pentru toate containerele care descind din clasa ]indo&# deci este !estionarul
implicit al ferestrelor Java'
--M/emplu
import +ava.a&t..'
public class @est3orderCa#out {
public static void main(String args!) {
Frame 6 2 ne& Frame($3order Ca#out$)'
6.setCa#out(ne& 3orderCa#out())'--poate sa lipseasca
6.add(ne& 3utton($Uord$)4 3orderCa#out.U=P@%)'
6.add(ne& 3utton($Sud$)4 3orderCa#out.S=[@%)'
6.add(ne& 3utton($Mst$)4 3orderCa#out.MAS@)'
6.add(ne& 3utton($Qest$)4 3orderCa#out.]MS@)'
6.add(ne& 3utton($Centru$)4 3orderCa#out.CMU@MP)'
6.pacN()'
6.s:o&()'
)
)
Cele cinci butoane ale ferestrei vor fi afisate astfel)
La redimensionarea ferestrei se pot observa urmatoarele lucruri) nordul si sudul se redimensionea$a doar
pe ori$ontala# estul si vestul doar pe verticala# "n timp ce centrul se redimensionea$a at.t pe ori$ontala c.t
si pe verticala' >edimensionarea componentelor se face astfel "nc.t ele ocupa toata $ona containerului din
care fac parte'
<7
=estionarul =rid2aEout
Iestionarul 9ridCa#out or!ani$ea$a containerul ca un tabel cu r.nduri si coloane# componentele fiind
plasate "n casutele tabelului de la st.n!a la dreapta "ncep.nd cu primul r.nd' Casutele tabelului au
dimensiuni e!ale iar o componenta poate ocupa doar o sin!ura casuta'
1umarul de linii si coloane poate fi specificat "n constructorul !estionarului dar poate fi modificat si
ulterior prin metodele set8oFs si setCols' (e asemenea# distanta "ntre componente pe ori$ontala si
distanta "ntre r.ndurile tabelului pot fi specificate "n constructor sau stabilite ulterior'
;cest tip de !estionar poate fi util "n implementarea unor componente de tip calculator# "n care numerele
si operatiile sunt afisate prin intermediul unor butoane dispuse sub forma unei !rile'
--M/emplu
import +ava.a&t..'
public class @est9ridCa#out {
public static void main(String args!) {
Frame 6 2 ne& Frame($9rid Ca#out$)'
6.setCa#out(ne& 9ridCa#out(34 2))'
6.add(ne& 3utton($;$))'
6.add(ne& 3utton($2$))'
6.add(ne& 3utton($3$))'
6.add(ne& 3utton($"$))'
6.add(ne& 3utton($($))'
6.add(ne& 3utton($*$))'
6.pacN()'
6.s:o&()'
)
)
Cele sase butoane ale ferestrei vor fi pe trei r.nduri si doua coloane astfel)
>edimensionarea ferestrei va determina redimensionarea tuturor componentelor'
=estionarul Card2aEout
Iestionarul CardCa#out tratea$a componentele adau!ate pe suprafata "ntr+o maniera asemanatoare cu cea
a dispunerii cartilor de joc "nntr+un pachet' Suprafata de afisare poate fi asemanata cu pachetul de carti iar
fiecare componenta este o carte din pachet' La un moment dat numai o sin!ura componenta este vi$ibila
3*cea de deasupra*4'
Clasa dispune de metode prin care sa poata fi afisata o anumita componenta din pachet# sau sa se poata
parcur!e secvential pachetul# ordinea "n care componentele se !asesc "n pachet fiind interna !estionarului'
;cest !estionar este util pentru implementarea unor cutii de dialo! de tip tab# "n care pentru o !estionare
mai eficienta a spatiului# componentele sunt !rupate "n pachete# la un moment dat utili$atorul
interaction.nd cu un sin!ur pachet# celelate fiind ascunse'
=estionarul =rid@ag2aEout
Aste cel mai complex si flexibil !estionar de po$itionare din Java' La fel ca "n ca$ul !estionarului
9ridCa#out# suprafata de afisare este considerata ca fiind un tabel# "nsa# spre deosebire de acesta#
numarul de linii si de coloane sunt determinate automat# "n functie de componentele amplasate pe
suprafata de afisare' (e asemenea# "n functie de componentele !estionate# dimensiunile casutelor pot fi
diferite# cu sin!urele restrictii ca pe aceeasi linie casutele trebuie sa aiba aceeasi "naltime# iar pe coloana
trebuie sa aiba aceeasi latime'
<=
Spre deosebire de 9ridCa#out# o componenta poate ocupa mai multe celule adiacente# chiar de
dimensiuni diferite# $ona ocupata fiind referita prin *re!iunea de afisare* a componentei respective'
Eentru a specifica modul de afisare a unei componente# acesteia "i este asociat un obiect de tip
=rid@agConstraints# "n care se specifica diferite proprietati ale componentei referitoare la re!iunea sa
de afisare si la modul "n care va fi plasata "n aceasta re!iune' Le!atura dintre o componenta si un obiect
9rid3agConstraints se reali$ea$a prin metode setConstraints)
9rid3agCa#out grid3ag 2 ne& 9rid3agCa#out()'
container.setCa#out(grid3ag)'
9rid3agConstraints c 2 ne& 9rid3agConstraints()'
. . .
--se speci6ica proprietatile re6eritoare la a6isarea unei componente
grid3ag.setConstraints(componenta4 c)'
container.add(componenta)'
;sadar# "nainte de a adau!a o componenta pe suprafata unui container care are un !estionar de tip
9rid3agCa#out# va trebui sa specificam anumiti parametri 3constr.n!eri4 referitori la cum va fi plasata
componenta respectiva' ;ceste constr.n!eri vor fi specificate prin intermediul unui obiect de tip
9rid3agConstraints# care poate fi folosit pentru mai multe componente care au aceleassi cosntr.n!eri
de afisare)
grid3ag.setConstraints(componenta;4 c)'
grid3ag.setConstraints(componenta24 c)'
. . .
=ruparea componentelor Clasa Panel"
Elasarea componentelor direct pe suprafata de afisare poate deveni incomoda "n ca$ul "n care avem multe
obiecte !rafice' (in acest motiv se recomanda !ruparea obiectelor !rafice "nrudite ca functii astfel "nc.t
sa putem fi si!uri ca# indiferent de !estionarul de po$itionare al suprafetei de afisare# ele se vor !asi
"mpreuna' Iruparea componentelor se face "n panel1uri'
-n panel este cel mai simplu model de container' Al nu are o repre$entare vi$ibila# rolul sau fiind de a
oferi o suprafata de afisare pentru componente !rafice# inclusiv pentru alte panel+uri'
Clasa care instantia$a aceste obiecte este Panel# extensie a superclasei Container'
Eentru a aranja corespun$ator componentele !rupate "ntr+un panel# acestuia i se poate specifica un
!estionar de po$itionare anume# folosind metoda setCa#out' Iestionarul implicit pentru containerele de
tip Lanel este Flo&Ca#out'
;sadar# o aranjare eficienta a componentelor unei ferestre "nseamna)
!ruparea componentelor *"nfratite* 3care nu trebuie sa fie despartie de !estionarul de po$itionare
al ferestrei4 "n panel+uri6
aranjarea componentelor unui panel# prin specificarea acestuia a unui !estionar de po$itionare
corespun$ator
aranjarea panel+urilor pe suprafata ferestrei# prin specificarea !estionarului de po$itionare al
ferestrei'
--M/emplu
import +ava.a&t..'
public class @estLanel {
public static void main(String args!) {
Frame 6 2 ne& Frame($Lanel$)'
<D
Lanel panel 2 ne& Lanel()'
panel.setCa#out(ne& Flo&Ca#out())'
panel.add(ne& Cabel($@e/t,$))'
panel.add(ne& @e/tField($$4 2<))'
panel.add(ne& 3utton($Peset$))'
6.add(panel4 3orderCa#out.U=P@%)'
6.add(ne& 3utton($=V$)4 3orderCa#out.MAS@)'
6.add(ne& 3utton($Cancel$)4 3orderCa#out.]MS@)'
6.pacN()'
6.s:o&()'
)
)
Tratarea evenimentelor
-n eveniment este produs de o actiune a utili$atorului asupra unei componente !rafice si repre$inta
mecanismul prin care utili$atorul comunica efectiv cu pro!ramul' Axemple de evenimente sunt) apasarea
unui buton# modificarea textului "ntr+un control de editare# "nchiderea# redimensionarea unei ferestre# etc'
Componentele care !enerea$a anumite evenimente se mai numesc si surse e evenimente'
Interceptarea evenimentelor !enerate de componentele unui pro!ram se reali$ea$a prin intermediul unor
clase de tip listener 3ascultator# consumator de evenimente4' In Java# orice obiect poate *consuma*
evenimentele !enerate de o anumita componenta !rafica'
;sadar# pentru a scrie cod care sa se execute "n momentul "n care utili$atorul interactionea$a cu o
componenta !rafica trebuie sa facem urmatoarele lucruri)
sa scriem o clasa de tip listener care sa *asculte* evenimentele produse de acea componenta si "n
cadrul acestei clase sa implementam metode specifice pentru tratarea lor6
sa comunicam componentei sursa ca respectiva clasa "i *asculta* evenimentele pe care le
!enerea$a# cu alte cuvinte sa "nre!istram acea clasa drept *consumator* al evenimentelor produse
de componenta respectiva'
Avenimentele sunt# ca orice altceva "n Java# obiecte' Clasele care descriu aceste obiecte se "mpart "n mai
multe tipuri "n functie de componenta care le !enerea$a# mai precis "n functie de actiunea utili$atorului
asupra acesteia' Eentru fiecare tip de eveniment exista o clasa care instantia$a obiecte de acel tip6 de
exemplu) evenimentul !enerat de actionarea unui buton este implementat prin clasa ActionMvent# cel
!enerat de modificarea unui text prin clasa TextAvent# etc'
Toate aceste clase au ca superclasa comuna clasa 0?TEvent' Lista completa a claselor care descriu
evenimente va fi data "ntr+un tabel "n care vom specifica si modalitatile de utili$are ale acestora'
O clasa consumatoare de evenimente 3listener4 poate fi orice clasa care specifica "n declaratia sa ca
doreste sa asculte evenimente de un anumit tip' ;cest lucru se reali$ea$a prin implementarea unei
interfete specifice fiecarui tip de eveniment' ;stfel# pentru ascultarea evenimentelor de tip ActionMvent
clasa respectiva trebuie sa implemente$e interfata ActionCistener# pentru @e/tMvent interfata care
trebuie implementata este @e/tCistener# etc'
Toate aceste interfete au suprainterfata comuna Event2istener'
<?
class Asculta3utoane implements ActionCistener
class Asculta@e/te implements @e/tCistener
Intruc.t o clasa poate implementa oric.te interfete ea va putea sa asculte evenimente de mai multe tipuri)
class Ascultator implements ActionCistener4 @e/tCistener
Vom vedea "n continuare metodele fiecarei interfete pentru a sti ce trebuie sa implemente$e o clasa
consumatoare de evenimente'
;sa cum spus mai devreme# pentru ca evenimentele unei componente sa fie interceptate de catre o
instanta a unei clase ascultator# aceasta clasa trebuie "nre!istrata "n lista ascultatorilor componentei
respective' ;m spus lista# deoarece evenimentele unei componente pot fi ascultate de oric.te clase + cu
conditia ca acestea sa fie "nre!istrate la componenta respectiva' Inre!istrarea unei clase "n lista
ascultatorilor unei componente se face cu metode din clasa Component de tipul addGGG2istener# iar
eliminarea ei din aceasta lista cu removeGGG2istenerm unde 000 repre$enta tipul evenimentului'
Exemplu de tratare a evenimentelor
Inainte de a detalia aspectele pre$entate mai sus# sa consideram un exemplu de tratare a evenimentelor'
Vom crea o fereastra care sa contina doua butoane cu numele *OB*# repectiv *Cancel*' La apasarea
fiecarui buton vom scrie pe bara titlu a ferestrei mesajul * ;ti apasat butonul '''*'
--M/emplu,Ascultarea evenimentelor de la doua butoane
import +ava.a&t..'
import +ava.a&t.event..'
class Fereastra e/tends Frame {
public Fereastra(String titlu) {
super(titlu)'
)
public void initiali5are() {
setCa#out(ne& Flo&Ca#out())' --se stabileste gestionarul
setSi5e(2<<4 ;<<)' --se dimensionea5a 6ereastra
3utton b; 2 ne& 3utton($=V$)'
add(b;)' --se adauga primul buton
3utton b2 2 ne& 3utton($Cancel$)'
add(b2)' --se adauga al doilea buton
scultator listener = new scultator'this(;
&!.addction9istener'listener(;
&".addction9istener'listener(;
--ambele butoane sunt ascultate de obiectul $listener$
--instanta a clasei Ascultator4 de6inita mai +os
)
)
class Ascultator implements ction9istener {
private Fereastra 6'
public Ascultator(Fereastra 6) {
t:is.6 2 6'
)
--metoda inter6etei ActionCistener
public void action6erformed'ction1vent e( {
String command 2 e.getActionCommand()'
--numele comen5ii este numele butonului apasat
S#stem.out.println(e.toString())'
i6 (command.eWuals($=V$))
6.set@itle($Ati apasat =V$)'
else
i6 (command.eWuals($Cancel$))
6.set@itle($Ati apasat Cancel$)'
)
)
<@
public class @estMvent { --6ereastra principala
public static void main(String args!) {
Fereastra 6 2 ne& Fereastra($ActionMvent$)'
6.initiali5are()'
6.s:o&()'
)
)
1u este obli!atoriu sa definim clase speciale pentru ascultarea evenimentelor' In exemplul de mai sus am
definit o clasa speciala *;scultator* pentru a intercepta evenimentele produse de cele doua butoane si din
acest motiv a trebuit sa trimitem ca parametru acestei clase instanta la fereastra noastra' %ai corect ar fi
fost sa folosim chiar clasa *ereastra* pentru a+si asculta evenimentele produse de componentele sale)
class Fereastra e/tends Frame implements ction9istener{
public Fereastra(String titlu) {
super(titlu)'
)
public void initiali5are() {
. . .
&!.addction9istener'this(;
&".addction9istener'this(;
--ambele butoane sunt ascultate c:iar din clasa Fereastra
--deci ascultatorul este instanta curenta, t:is
)
public void action6erformed'ction1vent e( {
String command 2 e.getActionCommand()'
--numele comen5ii este numele butonului apasat
S#stem.out.println(e.toString())'
i6 (command.eWuals($=V$))
t:is.set@itle($Ati apasat =V$)'
else
i6 (command.eWuals($Cancel$))
t:is.set@itle($Ati apasat Cancel$)'
)
)
. . .
;sadar# orice clasa poate asculta evenimnte de orice tip cu conditia sa implemente$e interfetele specifice
acelor evenimente'
Tipuri de evenimente si componentele care le generea(a
In tabelul de mai jos sunt pre$entate "n st.n!a tipurile de evenimente si interfetele iar "n dreapta lista
componentelor ce pot !enera evenimente de acel tip precum si o scurta explicatie despre motivul care le
provoaca'
Eveniment!Inter$ata Componente care generea(a acest eveniment
;ctionAvent
;ctionListener
Hutton# List# Textield# %enuItem# ChecFbox%enuItem# %enu# Eopup%enu
;ctiuni asupra unui control
;djustmentAvent
;djustmentListener
Scrollbar si orice clasa care implementea$a interfata ;djustable
%odificarea unei valori variind "ntre doua limite
ComponentAvent
ComponentListener
Component si subclasele sale
>edimensionari# deplasari# ascunderi ale componentelor
ContainerAvent
ContainerListener
Container si subclasele sale
;dau!area# ster!erea componentelor la un container
ocusAvent Component si subclasele sale
<9
ocusListener Ereluarea# pierderea focusului de catre o componenta
Be&Avent
Be&Listener
Component si subclasele sale
;pasarea# eliberarii unei taste c.nd focusul este pe o anumita componenta'
%ouseAvent
%ouseListener
Component si subclasele sale
ClicF# apasare# eliberare a mouse+ului pe o componenta# intrarea# iesirea mouse+ului
peJde pe suprafata unei componente
%ouseAvent
%ouse%otionListener
Component si subclasele sale
%iscarea sau *t.r.rea* 3dra!4 mouse+ului pe suprafata unei componente
/indo0Avent
/indo0Listener
/indo0 si subclasele sale (ialo!# ile(ialo!# rame
Inchiderea# maximi$area# minimi$area# redimensionarea unei ferestre
ItemAvent
ItemListener
ChecFbox# ChecFbox%enuItem# Choice# List si orice clasa care implementea$a
interfata ItemSelectable
Selectia# deselecttia unui articol dintr+o lista sau meniu'
TextAvent
TextListener
Orice clasa derivata din TextComponent cum ar fi ) Text;rea# Textield
%odificarea textului dintr+o componenta de editare a textului
Evenimente suportate de o componenta
-rmatorul tabel pre$inta o clasificare a evenimentelor "n functie de componentele care le suporta)
Componenta Evenimente suportate de componenta
;djustable ;djustmentAvent
;pplet ContainerAvent# ocusAvent# Be&Avent# %ouseAvent# ComponentAvent
Hutton ;ctionAvent# ocusAvent# Be&Avent# %ouseAvent# ComponentAvent
Canvas ocusAvent# Be&Avent# %ouseAvent# ComponentAvent
ChecFbox ItemAvent# ocusAvent# Be&Avent# %ouseAvent# ComponentAvent
ChecFbox%enuItem ;ctionAvent# ItemAvent
Choice ItemAvent# ocusAvent# Be&Avent# %ouseAvent# ComponentAvent
Component ocusAvent# Be&Avent# %ouseAvent# ComponentAvent
Container ContainerAvent# ocusAvent# Be&Avent# %ouseAvent# ComponentAvent
(ialo!
ContainerAvent# /indo0Avent# ocusAvent# Be&Avent# %ouseAvent#
ComponentAvent
ile(ialo!
ContainerAvent# /indo0Avent# ocusAvent# Be&Avent# %ouseAvent#
ComponentAvent
rame
ContainerAvent# /indo0Avent# ocusAvent# Be&Avent# %ouseAvent#
ComponentAvent
Label ocusAvent# Be&Avent# %ouseAvent# ComponentAvent
List ;ctionAvent# ocusAvent# Be&Avent# %ouseAvent# ItemAvent# ComponentAvent
%enu ;ctionAvent
%enuItem ;ctionAvent
Eanel ContainerAvent# ocusAvent# Be&Avent# %ouseAvent# ComponentAvent
<:
Eopup%enu ;ctionAvent
Scrollbar ;djustmentAvent# ocusAvent# Be&Avent# %ouseAvent# ComponentAvent
ScrollEane ContainerAvent# ocusAvent# Be&Avent# %ouseAvent# ComponentAvent
Text;rea TextAvent# ocusAvent# Be&Avent# %ouseAvent# ComponentAvent
TextComponent TextAvent# ocusAvent# Be&Avent# %ouseAvent# ComponentAvent
Textield ;ctionAvent# TextAvent# ocusAvent# Be&Avent# %ouseAvent# ComponentAvent
/indo0
ContainerAvent# /indo0Avent# ocusAvent# Be&Avent# %ouseAvent#
ComponentAvent
Metodele inter$etelor de tip >listener>
Orice clasa care tratea$a evenimente trebuie sa implemente$e obli!atoriu metodele interfetelor
corespun$atoare evenimentelor pe care le tratea$a' Tabelul de mai jos pre$inta# pentru fiecare interfata#
metodele puse la dispo$itie si care trebuie implementate de clasa ascultator'
Inter$ata Metodele inter$etei
;ctionListener
actionLer6ormed(ActionMvent)
;djustmentListener
ad+ustmentQalueC:anged(Ad+ustmentMvent)
ComponentListener
component%idden(ComponentMvent)
componentS:o&n(ComponentMvent)
component?oved(ComponentMvent)
componentPesi5ed(ComponentMvent)
ContainerListener
componentAdded(ContainerMvent)
componentPemoved(ContainerMvent)
ocusListener
6ocus9ained(FocusMvent)
6ocusCost(FocusMvent)
Be&Listener
Ne#Lressed(Ve#Mvent)
Ne#Peleased(Ve#Mvent)
Ne#@#ped(Ve#Mvent)
%ouseListener
mouseClicNed(?ouseMvent)
mouseMntered(?ouseMvent)
mouseM/ited(?ouseMvent)
mouseLressed(?ouseMvent)
mousePeleased(?ouseMvent)
%ouse%otionListener
mouseSragged(?ouseMvent)
mouse?oved(?ouseMvent)
/indo0Listener
&indo&=pened(]indo&Mvent)
&indo&Closing(]indo&Mvent)
&indo&Closed(]indo&Mvent)
&indo&Activated(]indo&Mvent)
&indo&Seactivated(]indo&Mvent)
&indo&0coni6ied(]indo&Mvent)
&indo&Seiconi6ied(]indo&Mvent)
ItemListener
itemStateC:anged(0temMvent)
TextListener
te/tQalueC:anged(@e/tMvent)
<<
Folosirea adaptorilor si a claselor interne .n tratarea evenimentelor
;m va$ut ca o clasa care tratea$a evenimente de un anumit tip trebuie sa implemente$e interfata
corespun$atoare acelui tip' ;ceasta "nseamna ca trebuie sa implemente$e obli!atoriu toate metodele
definite de acea interfata# chiar daca nu specifica nici un cod pentru unele dintre ele' Sunt "nsa situatii
c.nd acest lucru este suparator# mai ales atunci c.nd nu ne interesea$a dec.t o sin!ura metoda a interfetei'
-n exemplu su!estiv este urmatorul) o fereastra care nu are specificat cod pentru tratarea evenimentelor
sale nu poate fi "nchisa cu butonul standard marcat cu ,x, din coltul dreapta sus si nici cu combinatia de
taste ;lt5D' Eentru a reali$a acest lucru trebuie interceptat evenimentul de "nchidere a ferestrei "n
metoda &indoClosing si apelata apoi metoda dispose de "nchidere a ferestrei# eventual umata de iesirea
din pro!ram# "n ca$ul c.nd este vorba de fereastra principala a aplicatiei' ;ceasta "nseamna ca trebuie sa
implementam interfata ]indo&Cistener care are nu mai putin de sapte metode'
--Crearea unei 6erestre cu ascultarea evenimentelor sale
--6olosind implementarea directa a inter6etei ]indo&Cistener
import +ava.a&t..'
import +ava.a&t.event..'
class Fereastra e/tends Frame implements ]indo&Cistener {
public Fereastra(String titlu) {
super(titlu)'
t:is.add]indo&Cistener(t:is)'
)
--metodele inter6etei ]indo&Cistener
public void &indo&=pened(]indo&Mvent e) {)
public void &indo&Closing(]indo&Mvent e) {
dispose()' --inc:id 6ereastra
S#stem.e/it(<)'--termin programul
)
public void &indo&Closed(]indo&Mvent e) {)
public void &indo&0coni6ied(]indo&Mvent e) {)
public void &indo&Seiconi6ied(]indo&Mvent e) {)
public void &indo&Activated(]indo&Mvent e) {)
public void &indo&Seactivated(]indo&Mvent e) {)
)
public class @est]indo&Cistener {
public static void main(String args!) {
Fereastra 6 2 ne& Fereastra($= 6ereastra$)'
6.s:o&()'
)
)
Observati ca trebuie sa implementam toate metodele interfetei# chiar daca nu scriem nici un cod pentru
ele' Sin!ura metoda care ne interesea$a este &indo&Closing "n care specificam ce trebuie facut atunci
c.nd utili$atorul doreste sa "nchida fereastra'
Eentru a evita scrierea inutila a acestor metode exista o serie de clase care implementea$a interfetele de
tip *listener* fara a specifica nici un cod pentru metodele lor' ;ceste clase se numesc aaptori'
Folosirea adaptorilor
-n aaptor este o clasa abstracta care implementea$a o interfata de tip *listener*' Scopul unei astfel de
clase este ca la crearea unui *ascultator* de evenimente# "n loc sa implementa o anumita interfata si
implicit toate metodele sale# sa extindem adaptorul corespun$ator interfetei respective 3daca areN4 si sa
supradefinim doar metodele care ne interesea$a 3cele "n care vrem sa scriem o anumita secventa de cod4'
(e exemplu# adaptorul interfetei ]indo&Cistener este ]indo&Adapter iar folosirea acestuia este data "n
exemplul de mai jos)
--Crearea unei 6erestre cu ascultarea evenimentelor sale
--6olosind e/tinderea clasei ]indo&Adapter
188
import +ava.a&t..'
import +ava.a&t.event..'
class Fereastra e/tends Frame {
public Fereastra(String titlu) {
super(titlu)'
t:is.add]indo&Cistener(ne& Ascultator())'
)
)
class Ascultator e/tends ]indo&Adapter {
--suprde6inim metodele care ne interesea5a
public void &indo&Closing(]indo&Mvent e) {
S#stem.e/it(<)'
)
)
;vantajul clar al acestei modaitati de tratare a evenimentelor este reducerea codului pro!ramului# acesta
devenind mult mai usor li$ibil' Insa exista si doua de$avantaje majore' (upa cum ati observat# fata de
exemplul anterior clasa *ereastra* nu poate extinde ]indo&Adapter deoarece ea extinde deja clasa
Frame si din acest motiv am construi o noua clasa numita *;scultator*' Vom vedea "nsa ca acest
de$avantaj poate fi eliminat prin folosirea unei clase interne'
-n alt de$avantaj este ca orice !reseala de sintaxa "n declararea unei metode a interfetei nu va produce o
eroare de compilare dar nici nu va supradefini metoda interfetei ci# pur si simplu# va crea o metoda a
clasei respective'
class Ascultator e/tends ]indo&Adapter {
-- in loc de &indo&Closing scriem ]indo&Closing
-- nu suprade6inim vreo metoda a clasei ]indo&Adapter
-- nu da nici o eroare
-- nu 6ace nimic >
public void ]indo&Closing(]indo&Mvent e) {
S#stem.e/it(<)'
)
)
In tabelul de mai jos sunt dati toti adaptorii interfetele de tip *listener* + se oberva ca o interfata
TTTCistener are un adaptor de tipul TTTAdapter' Interfetele care nu au un adaptor sunt cele care
definesc o sin!ura metoda si prin urmare crearea unei clase adaptor nu "si are rostul'
Inter$ata >listener> 0daptor
;ctionListener nu are
;djustmentListener nu are
ComponentListener Component;dapter
ContainerListener Container;dapter
ocusListener ocus;dapter
ItemListener nu are
Be&Listener Be&;dapter
%ouseListener %ouse
%ouse%otionListener %ouse%otion;dapter
TextListener nu are
/indo0Listener /indo0;dapter
Folosirea claselor interne anonime"
Stim ca o clasa interna este o clasa declarata "n cadrul altei clase iar clasele anonime sunt acele clase
interne folosite doar pentru instantierea unui sin!ur obiect de acel tip' -n exemplu tipic de folosire a lor
181
este instantierea adaptorilor direct "n corpul unei clase care contine componente ale caror evenimente
trebuie interceptate' Clasa *ereastra* din exemplul anterior poate fi scrisa astfel)
class Fereastra e/tends Frame {
public Fereastra(String titlu) {
super(titlu)'
t:is.add]indo&Cistener(new 4indowdapter'( {
--corpul clasei anonime
public void &indo&Closing(]indo&Mvent e) {
S#stem.e/it(<)'
)
))'
)
)
Observati cum codul pro!ramului a fost redus substantial prin folosirea unui adaptor si a unei clase
anonime'
Folosirea $erestrelor
(upa cum am va$ut suprafetele de afisare ale componentelor !rafice 3containerele4 sunt extensii ale clasei
Container' O cate!orie aparte a acestor containere o repre$inta ferestrele' Spre deosebire de un applet
care "si poate plasa componentele direct pe suprafata de afisare a bro0ser+ului "n care rulea$a# o aplicatie
intependenta are nevoie de propriile ferestre pe care sa faca afisarea componentelor sale !rafice' Eentru
de$voltarea aplicatiilor care folosesc !rafica se vor folosi clasele ?indoF si subclasele sale directe
Frame si +ialog'
Clasa ?indoF
Clasa ]indo& este rar utili$ata "n mod direct' Aa permite crearea unor ferestre top+level care nu au chenar
si nici bara de meniuri' Eentru a crea ferestre mai complexe se utili$ea$a clasele Frame si Sialog'
%etodele mai importante ale clasei ]indo& 3mostenite de toate subclasele sale4 sunt date "n tabelul de mai
jos)
void dispose()
(istru!e 3"nchide4 fereastra si si eliberea$a toate resursele acesteia
Component
getFocus=&ner()
>eturnea$a componenta ferestrei care are focus+ul daca si numai daca fereastra
este activa
]indo&
get=&ned]indo&s()
>eturnea$a un vector cu toate ferestrele subclase ale ferestrei respective
]indo& get=&ner()
>eturnea$a parintele 3superclasa4 ferestrei
void :ide()
ace fereastra invi$ibila fara a o distru!e "nsa' Eentru a redeveni vi$ibila apelati
metoda sho0
boolean isS:o&ing()
Testea$a daca fereastra este vi$ibila sau nu
void pacN()
>edimensionea$a automat fereastra la o suprafata optima care sa cuprinda toate
componentele sale' Trebuie apelata# "n !eneral# dupa adau!area tuturor
componentelor pe suprafata ferestrei'
void s:o&()
ace vi$ibila o fereastra creata' Implicit o fereastra nou creata nu este vi$ibila'
void to3acN()
void toFront()
Trimite fereastra "n spatele celorlalte ferestre deschise
;duce fereastra "n fata celorlalte ferestre deschise
187
Clasa Frame
Aste subclasa directa a clasei ]indo&' si este folosita pentru crearea de ferestre independente si
functionale# eventual contin.nd bare de meniuri' Orice aplicatie !rafica independenta trebuie sa aiba cel
putin o fereastra# numita si fereastra principala# care va fi afisata la pornirea pro!ramului'
Constructorii clasei rame sunt)
7rame '(
Construieste o 6ereastra4 6ara titlu4 initial invi5ibila.
7rame'String title(
Construieste o 6ereastra4 cu titlul speci6icat4 initial invi5ibila.
;sadar# o fereastra nou creata este invi$ibila' Eentru a fi facuta vi$ibila se va apela metoda s:o& definita
"n superclasa ]indo&' In exemplul de mai jos este construita si afisata o fereasta cu titlul *O fereastra*'
--Crearea unei 6erestre
import +ava.a&t..'
public class @estFrame {
public static void main(String args!) {
Frame 6 2 ne& Frame($= 6ereastra$)'
6.s:o&()'
)
)
Crearea ferestrelor prin instantierea obiectelor de tip Frame este mai putin u$uala' (e obicei# ferestrele
unui pro!ram vor fi definite "n clase separate care extind clasa Frame# ca "n exemplul de mai jos)
import +ava.a&t..'
class Fereastra e/tends Frame{
--constructorul
public Fereastra(String titlu) {
super(titlu)'
)
void initiali5are() {
. . .
--adaugam componentele 6erestrei
)
)
public class @estFrame {
public static void main(String args!) {
Fereastra 6 2 ne& Fereastra($= 6ereastra$)'
6.initiali5are()'
6.s:o&()'
)
)
Iestionarul de po$itionare implicit al clasei ]indo& este 3orderCa#out' (in acest motiv# "n momentul "n
care fereastra este creata dar nici o componenta !rafica nu este pusa pe suprafata ei# suprafata de afisare a
feretrei va fi nula' ;celasi efect "l vom obtine daca o redimenionam si apelam apoi metoda pacN care
determina dimeniunea suprafetei de afisare "n functie de componentele !rafice afisate pe ea'
Se observa de asemenea ca butonul de "nchidere a ferestrei nu este functional' Interceptarea
evenimentelor se face prin implementarea interfetei ?indoF2istener si prin adau!area "n lista
ascultatorilor ferestrei 3u$ual4 chiar a obiectului care implementea$a fereastra sau prin folosirea unor
adaptori si clase anonime'
%etodele mai folosite ale clasei rame sunt date "n tabelul de mai jos)
static Framest
getFrames()
%etoda statica ce returnea$a lista tuturor ferestrelor deschise ale unei aplicatii
0mage get0con0mage()
void set0con0mage(0mage
;flaJsetea$a ima!inea3iconita4 care sa fie afisata atunci c.nd fereastra este
18=
img)
minimi$ata
?enu3ar get?enu3ar()
void set?enu3ar(?enu3ar
mb)
;flaJsetea$a bara de meniuri a ferestrei 3ve$i *olosirea meniurilor*4
int getState()
void setState(int s)
>eturnea$aJsetea$a starea ferestrei' O fereastra se poat !asi "n doua stari#
descrise de constantele) rame'ICO1IIA( 3daca este minimi$ata4
rame'1O>%;L 3daca nu este minimi$ata4'
String get@itle()
void set@itle()
;flaJsetea$a titlul ferestrei
boolean isPesi5able()
void
setPesi5able(boolean r)
(eterminaJstabileste daca fereastra poate fi redimenionata de utili$ator'
Clasa +ialog
Toate interfetele !rafice ofera un tip special de ferestre destinate preluarii datelor de la utili$ator' ;cestea
se numesc ferestre e ialog sau casete e ialog si sunt implementate prin intermediul clasei +ialog#
subclasa directa a clasei ]indo&'
(iferenta majora "ntre ferestrele de dialo! si ferestrele normale 3obiecte de tip Frame4 consta "n faptul ca
o fereastra de dialo! este dependenta de o alta fereastra 3normala sau tot fereastra dialo!4# numita si
fereastra parinte' Cu alte cuvinte# ferestrele de dialo! nu au o existenta de sine statatoare'
C.nd fereastra parinte este distrusa sunt distruse si ferestrele sale de dialo!# c.nd este minimi$ata
ferestrele sale de dialo! sunt facute invi$ibile iar c.nd este maximi$ata acestea sunt aduse la starea "n care
se !aseau "n momentul minimi$arii ferestrei parinte'
erestrele de dialo! pot fi de doua tipuri)
modale) care blochea$a accesul la fereastra parinte "n momentul deschiderii lor + de exemplu#
ferestre de introducere a unor date# de ale!ere a unui fisier "n vederea deschideriii# de selectare a
unei optiuni# mesaje de averti$are# etc6
nemodale) care nu blochea$a fluxul de intrare catre fereastra parinte + de exemplu# ferestrele de
cautare a unui cuv.nt "ntr+un fisier'
Implicit o fereastra de dialo! este nemodala si invi$ibila'
Constructorii clasei (ialo! sunt)
Sialog(Frame parinte)
Sialog(Frame parinte4 String titlu)
Sialog(Frame parinte4 String titlu4 boolean modala)
Sialog(Frame parinte4 boolean modala)
Sialog(Sialog parinte)
Sialog(Sialog parinte4 String titlu)
Sialog(Sialog parinte4 String titlu4 boolean modala)
unde *parinte* repre$ina o instanta ferestrei parinte# *titlu* repre$inta titlul ferestrei iar prin ar!umentul
*modala* specificam daca fereastra de dialo! creata va fi modala 3true4 sau nemodala 3false + valoarea
implicita4'
Ee l.n!a metodele mostenite de la superclasa /indo0 clasa (ialo! mai contine metodele)
boolean is?odal()
(etermina daca fereastra de dialo! este modala sau nu'
18D
void set?odal(boolean modala)
Specifica tipul ferestrei de dialo!) modala 3true4 sau nemodala 3false4
Crearea unei ferestre de dialo! este relativ simpla si se reali$ea$a prin crearea unei clase care sa extinda
clasa Sialog' %ai complicat este "nsa modul "n care se implementea$a comunicarea "ntre fereastra de
dialo! si fereastra parinte# pentru ca aceasta din urma sa poata folosi datele introduse 3sau optiunea
specificata4 "n caseta de dialo!' Axista doua abordari !enerale )
obiectul care repre$inta dialo!ul poate sa capte$e evenimentele de la componentele de pe
suprafata sa si sa sa sete$e valorile unor variabile ale ferestrei parinte "n momentul "n care dialo!ul
este "ncheiat sau
obiectul care creea$a dialo!ul 3fereastra parinte4 sa se "nre!istre$e ca ascultator al evenimentelor
de la butoanele care determina "ncheierea dialo!ului# iar fereastra de dialo! sa ofere metode
publice prin care datele introduse sa fie preluate din exterior'
Sa cream# de exemplu# o fereastra de dialo! modala pentru introducerea unui sir de caractere' ereastra
principala a aplicatiei va fi parintele casetei de dialo!# va primi sirul de caractere introdus si "si va
modifica titlul ca fiind sirul primit' (eschiderea ferestrei de dialo! se va face la apasarea unui buton al
ferestrei principale numit *Schimba titlul*' (ialo!ul va mai avea doua butoane OB si Cancel pentru
terminarea sa cu confirmare# respectiv renuntare' Cele doua ferestre vor arata ca "n ima!inile de mai jos
import +ava.a&t..'
import +ava.a&t.event..'
--Fereastra principala a aplicatiei
class FerLrinc e/tends Frame implements ActionCistener{
public FerLrinc(String titlu) {
super(titlu)'
t:is.add]indo&Cistener(ne& ]indo&Adapter() {
public void &indo&Closing(]indo&Mvent e) {
S#stem.e/it(<)'
)
))'
)
public void initiali5are() {
setCa#out(ne& Flo&Ca#out())'
setSi5e(3<<4 ;<<)'
3utton b 2 ne& 3utton($Sc:imba titlul$)'
add(b)'
b.addActionCistener(t:is)'
)
--metoda inter6etei ActionCistener
public void actionLer6ormed(ActionMvent e) {
FerSialog d 2 ne& FerSialog(t:is4 $@itlu$4 true)'
--astept sa se inc:ida 6ereastra modala de dialog
i6 (d.raspuns 22 null) return'
18?
set@itle(d.raspuns)'
)
)
--6ereastra de dialog
class FerSialog e/tends Sialog implements ActionCistener {
public String raspuns 2 null'
private @e/tField te/t'
public FerSialog(Frame parinte4 String titlu4 boolean modala) {
super(parinte4 titlu4 modala)'
t:is.add]indo&Cistener(ne& ]indo&Adapter() {
public void &indo&Closing(]indo&Mvent e) {
raspuns 2 null'
dispose()'
)
))'
setCa#out(ne& Flo&Ca#out())'
3utton oN4 cancel'
oN 2 ne& 3utton($=V$)'
cancel 2 ne& 3utton($Cancel$)'
te/t 2 ne& @e/tField($$4 (<)'
add(cancel)'add(te/t)'add(oN)'pacN()'
oN.addActionCistener(t:is)'
cancel.addActionCistener(t:is)'
s:o&()'
)
--metoda inter6etei ActionCistener
public void actionLer6ormed(ActionMvent e) {
--vad ce buton a 6ost apasat
String buton 2 e.getActionCommand()'
i6 (buton.eWuals($=V$))
raspuns 2 te/t.get@e/t()'
else
i6 (buton.eWuals($Cancel$))
raspuns 2 null'
dispose()'
)
)
--clasa principala
public class @estSialog {
public static void main(String args!) {
FerLrinc 6 2 ne& FerLrinc($Fereastra principala$)'
6.initiali5are()'
6.s:o&()'
)
)
Clasa File+ialog
Eachetul +ava.a&t pune la dispo$itie si un tip de fereastra de dialo! folosita pentru "ncarcarea J salvarea
fisierelor ) clasa File+ialog# subclasa directa a clasei Sialog' Instantele acestei clase au un comportament
comun dialo!urilor de acest tip de pe majoritatea platformelor de lucru# dar forma "n care vor fi afisate
este specifica platformei pe care rulea$a aplicatia'
Constructorii clasei sunt)
FileSialog(Frame parinte)
FileSialog(Frame parinte4 String titlu)
FileSialog(Frame parinte4 String titlu4 boolean mod)
18@
unde *parinte* repre$ina o instanta ferestrei parinte# *titlu* repre$inta titlul ferestrei iar prin ar!umentul
*mod* specificam daca "ncarcam sau salvam un fisier6 valorile pe care le poate lua acest ar!ument sunt
File+ialog32O0+ 3pentru "ncarcare4# respectiv File+ialog3'09E 3pentru salvare4'
--dialog pentru incarcarea unui 6isier
ne& FileSialog(main]in4 $Alegere 6isier$4 FileSialog.C=AS)'
--dialog pentru salvarea unui 6isier
ne& FileSialog(main]in4 $Salvare 6isier$4 FileSialog.SAQM)'
La crearea unui obiect FileSialog acesta nu este implicit vi$ibil' (aca afisarea sa se face cu s%oF caseta
de dialo! va fi modala' (aca afisarea se face cu set9isibletrue" va fi nemodala' (upa selectarea unui
fisier ea va fi facuta automat invi$ibila'
Ee l.n!a metodele mostenite de la superclasa Sialog clasa FileSialog mai contine metodele)
String getSirector#()
void setSirector#(String dir)
;flaJspecifica directorul din care se va face selectia fisierului
sau "n care se va face salvare' Sunt permise si notatii specifice
pentru directorul curent 3'4# directorul radacina 3J4# etc'
String getFile()
void setFile(String 6)
>eturnea$a numele fisierului selectat' Stabileste numele implicit
al fisierului care va aparea "n caseta de dialo!
FilenameFilter getFilenameFilter()
void
setFilenameFilter(FilenameFilter
6)
;flaJspecifica filtrul care se va aplica fisierelor din directorul
din care se va face selectia fisierului sau "n care se va face
salvare 3ve$i *Intrari si iesiri + Interfata ilenameilter* 4 1u
functionea$a pe platformele /indo0s N
int get?ode()
void set?ode(int mod)
;flaJspecifica daca "ncarcam sau salvam un fisier6
FileSialog.C=AS 3pentru "ncarcare4
FileSialog.SAQM 3pentru salvare4
Sa consideram un exemplu "n care vom ale!e# prin intermediul unui obiect FileSialog# un fisier cu
extensia *java*' (irectorul initial este directorul curent# iar numele implicit este @estFileSialog.+ava'
1umele fisierului ales va fi afisat la consola'
import +ava.a&t..'
import +ava.a&t.event..'
import +ava.io..'
class FerLrinc e/tends Frame implements ActionCistener{
public FerLrinc(String titlu) {
super(titlu)'
t:is.add]indo&Cistener(ne& ]indo&Adapter() {
public void &indo&Closing(]indo&Mvent e) {
S#stem.e/it(<)'
)
))'
)
public void initiali5are() {
setCa#out(ne& Flo&Ca#out())'
setSi5e(3<<4 ;<<)'
3utton b 2 ne& 3utton($Alege 6isier$)'
add(b)'
b.addActionCistener(t:is)'
)
--metoda inter6etei ActionCistener
public void actionLer6ormed(ActionMvent e) {
189
FileSialog 6d 2 ne& FileSialog(t:is4 $Alegeti un 6isier$4
FileSialog.C=AS)'
--stabilim directorul curent
6d.setSirector#($.$)'
--numele implicit
6d.setFile($@estFileSialog.+ava$)'
--speci6icam 6iltrul
6d.setFilenameFilter(ne& FilenameFilter() {
public boolean accept(File dir4 String numeFis) {
return (numeFis.ends]it:($.+ava$))'
)
))'
6d.s:o&()' --6acem vi5ibila 6ereastra de dialog
S#stem.out.println($Fisierul ales este,$ D 6d.getFile())'
)
)
public class @estFileSialog {
public static void main(String args!) {
FerLrinc 6 2 ne& FerLrinc($Fereastra principala$)'
6.initiali5are()'
6.s:o&()'
)
)
Folosirea meniurilor
Spre deosebire de celelate obiecte !rafice# care deriva din clasa Component# componentele unui meniu
repre$inta instante ale unor clase derivate din superclasa abstracta MenuComponent' ;ceasta exceptie
este facuta deoarece multe platforme !rafice limitea$a capabilitatile unui meniu'
%eniurile sunt !rupate "n doua cate!orii)
Meniuri $ixe 3vi$ibile permanent4) sunt !rupate "ntr+o bara de meniuri ce contine c.te un meniu
pentru fiecare intrare a sa6 la r.ndul lor aceste meniuri contin articole ce pot fi selectate#
comutatoare + care au doua stari 3checFbox4 sau alte meniuri 3submeniuri4' O fereastra poate avea
un sin!ur meniu fix'
Meniuri de context 3popup4) sunt meniuri invi$bile asociate unei ferestre si care se activea$a prin
apasarea butonul drept al mouse+ului' (iferenta fata de meniurile fixe consta "n faptul ca meniurile
de context nu au bara de meniuri'
In fi!ura de mai jos este pusa "n evidenta alcatuirea unui meniu fix)
18:
Axemplul de mai sus contine o bara de meniuri# doua meniuri principale 1ile si #it' %eniul #it contine
la r.ndul lui alt meniu 3submeniu4 2ptions # articolul ,no si doua comutatoare )ol si (talic'
In Java ;/T meniurile sunt repre$entate ca instante al clasei Menu@ar# aceasta fiind clasa care descrie
barele de meniuri' -n obiect de tip Menu@ar contine obiecte de tip Menu# care sunt de fapt meniurile
derulante propriu+$ise' La r.ndul lor acestea pot contine obiecte de tip MenuItemH C%ecA@oxMenuItem#
dar si alte obiecte de tip ?enu 3submeniuri4'
Sa vedem "n continuare care este ierarhia claselor folosite "n lucrul cu meniuri si sa anali$am pe r.nd
aceste clase)
Eentru a putea contine un meniu o componenta trebuie sa implemente$ interfata MenuContainer' Cel
mai adesea meniurile sunt atasate ferestrelor# mai precis obiectelor de tip Frame# aceste implement.nd
interfata ?enuContainer'
;tasarea unei bare de meniuri la o fereastra se face prin metoda addMenu@ar a clasei Frame'
Sa vedem cum ar arata un pro!ram care construieste un meniu ca cel din fi!ura de mai sus)
import +ava.a&t..'
import +ava.a&t.event..'
public class @est?enu {
public static void main(String args!) {
Frame 6 2 ne& Frame($?eniu$)'
?enu3ar mb 2 ne& ?enu3ar()'
?enu 6isier 2 ne& ?enu($File$)'
6isier.add(ne& ?enu0tem($=pen$))'
6isier.add(ne& ?enu0tem($Close$))'
6isier.addSeparator()'
6isier.add(ne& ?enu0tem($M/it$))'
?enu optiuni 2 ne& ?enu($=ptions$)'
optiuni.add(ne& ?enu0tem($Cop#$))'
optiuni.add(ne& ?enu0tem($Cut$))'
optiuni.add(ne& ?enu0tem($Laste$))'
?enu editare 2 ne& ?enu($Mdit$)'
editare.add(ne& ?enu0tem($[ndo$))'
editare.add(optiuni)'
editare.addSeparator()'
editare.add(ne& C:ecNbo/?enu0tem($3old$))'
editare.add(ne& C:ecNbo/?enu0tem($0talic$))'
mb.add(6isier)'
mb.add(editare)'
18<
6.set?enu3ar(mb)'
6.s:o&()'
)
)
Clasa MenuComponent
Aste o clasa abstracta# din care sunt extinse toate celelalte clase folosite pentru lucrul cu meniuri# fiind
analoa!a celeilalte superclase abstracte Component' Clasa ?enuComponent contine metode de ordin
!eneral# dintre care amintim getUame4 setUame4 getFont4 setFont# cu sintaxa si semnificatiile
u$uale'
Clasa Clasa Menu@ar
Eermite crearea barelor de meniuri asociate unei ferestre cadru 3Frame4' ;ceasta clasa adaptea$a
conceptul de bara de meniuri la platforma curenta de lucru' Eentru a le!a bara de meniuri la o anumita
fereastra trebuie apelata metoda setMenu@ar din clasa Frame'
Crearea unei bare de meniuri si le!area ei de o fereastra se reali$ea$a astfel)
--cree5 bara de meniuri
?enu3ar mb 2 ne& ?enu3ar()'
--adaug meniurile derulante la bara de meniuri
. . .
--atase5 unei 6erestre bara de meniuri
Frame 6 2 ne& Frame($Fereastra cu meniu$)'
6.add?enu3ar(mb)'
Clasa MenuItem
Orice articol al unui meniu trebuie sa fie o instanta a clasei ?enu0tem' Instantele acestei clase descriu
asadar articolele 3optiunile individuale4 ale meniurilor derulante# cum sunt *Open*# *Close*# *Axit*# etc' O
instanta a clasei ?enu0tem repre$inta de fapt o eticheta ce descrie numele cu care va aparea articolul "n
meniu# "nsotita eventual de un accelerator 3obiect de tip ?enuS:ortcut4 ce repre$inta combinatia de taste
cu care articolul poate fi apelat rapid 3ve$i *;cceleratori*4'
Clasa Menu
Aste clasa care permite crearea unui meniu derulant "ntr+o bara de meniuri' Optional# un meniu poate fi
declarat ca fiind tear+off# ceea ce "nseamna ca poate fi deschis si deplasat cu mouse+ul 3dra!!ed4 "ntr+o
alta po$itie dec.t cea ori!inala 3*rupt* din po$itia sa4' ;cest mecanism este dependent de platforma si
poate fi i!norat pe unele dintr ele'
iecare meniu are o eticheta# care este de fapt numele sau ce va fi afisat pe bara de meniuri'
;rticolele dintr+un meniu trebuie sa apartina clasei ?enu0tem# ceea ce "nseamna ca pot fi instante ale
uneia din clasele ?enu0tem4 ?enu sau C:ecNbo/?enu0tem'
--M/emplu
?enu3ar mb 2 ne& ?enu3ar()' --cree5 bara de meniuri
?enu optiuni 2 ne& ?enu($=ptions$)' --cree5 un meniu
optiuni.add(ne& ?enu0tem($Cop#$))'
optiuni.add($Cut$)' --adaug articole
optiuni.add($Laste)'
optiuni.addSeparator()'
optiuni.add($%elp$)'
mb.add(optiuni)' --adaug meniul
la bara
Frame 6 2 ne& Frame($Fereastra cu meniu$)'
6.add?enu3ar( mb )' --atase5 bara unei
6erestre
118
Clasa C%ecAboxMenuItem
Implementea$a "ntr+un meniu articole de tip comutator + articole care au doua stari lo!ice
3validatJnevalidat4# actionarea asupra articolului determin.nd trecerea sa dintr+o stare "n alta' La validarea
unui comutator "n dreptul etichetei sale va aparea un simbol !rafic care indica acest lucru6 la invalidarea
sa# simbolul !rafic va dispare'
Clasa C:ecNbo/?enu0tem are aceeasi functionalitate cu cea a casetelor de validare# implement.nd
interfata 0temSelectable'
Tratarea evenimentelor generate de meniuri
La ale!erea unei optiuni dintr+un meniu se !enerea$a un eveniment de tip 0ctionEvent si comanda este
repre$entata de numele optiunii alese' ;sadar pentru a activa optiunile unui meniu trebuie implementat un
obiect receptor care sa implemente$e interfata 0ction2istener si care "n metoda actionLer6ormed sa
specifice codul ce trebuie executat la ale!erea unei optiuni'
iecarui meniu "n putem asocia un obiect receptor diferit# ceea ce usurea$a munca "n ca$ul "n care ierarhia
de meniuri este complexa' Eentru a reali$a le!atura "ntre obiectul meniu si obiectul receptor trebuie sa
adau!am receptorul "n lista de ascultatori a meniului respectiv prin commanda)
meniu.addActionCistener(listener)'
;sadar# tratarea evenimentelor unui meniu este asemanatoare cu tratarea butoanelor# ceea ce face posibil
ca unui buton de pe suprafata de afisare sa "i corespunda o optiune "ntr+un meniu# ambele cu acelasi
nume# tratarea evenimentului corespun$ator apasarii butonului# sau ale!erii optiunii fac.ndu+se o sin!ura
data "ntr+o clasa care este "nre!istrata ca receptor at.t la buton c.t si la meniu'
-n ca$ special "l constituie optiunile de tip C:ecNbo/?enu0tem' Obiectele de acest tip se !asesc "ntr+o
cate!orie comuna cu Cist4 C:oice4 C:ecN3o/# implementea$a o interfata comuna 0temSelectable si
toate !enerea$a evenimente de tip ItemEvent' (in aceasta cau$a actionarea unei optiuni de tip
C:ecNbo/?enu0tem nu va determina !enerarea unui eveniment de tip ActionMvent de catre meniul din
care face parte# ci va !enera un eveniment 0temMvent chiar de catre articolul respectiv' Eentru a
intercepta un asemenea eveniment avem nevoie de un obiect receptor care sa implemente$e interfata
Item2istener si sa specifice "n metoda acesteia itemStateC:anged codul ce trebuie executat la
validareaJinvalidarea optiunii din meniu' (e asemenea receptorul trebuie "nre!istrat cu metoda
add0temCistener'
Tipul de operatie selectare J deselectare este codificat de c.mpurile statice 0tem1vent.S191$T18 si
0tem1vent.81S191$T18'
Exemplu de tratare a evenimentelor unui meniu
import +ava.a&t..'
import +ava.a&t.event..'
public class @est?enuMvent e/tends Frame
implements ction9istener* 0tem9istener{
public @est?enuMvent(String titlu) {
super(titlu)'
)
public void action6erformed'ction1vent e( {
String command 2 e.getActionCommand()'
i6 (command.eWuals($M/it$))
S#stem.e/it(<)'
--valabila si pentru meniu si pentru buton
)
public void itemState$hanged'0tem1vent e( {
i6 (e.getStateC:ange() 22 0temMvent.SMCMC@MS)
set@itle($C:ecNed>$)'
111
else
set@itle($Uot c:ecNed>$)'
)
public static void main(String args!) {
?enu3ar mb 2 ne& ?enu3ar()'
?enu test 2 ne& ?enu($@est$)'
C:ecNbo/?enu0tem c:ecN 2 ne& C:ecNbo/?enu0tem($C:ecN me$)'
test.add(c:ecN)'
test.addSeparator()'
test.add(ne& ?enu0tem($M/it$))'
mb.add(test)'
@est?enuMvent 6 2 ne& @est?enuMvent($@est ?eniu$)'
3utton btnM/it 2 ne& 3utton($M/it$)'
6.set?enu3ar(mb)'
6.add(btnM/it4 3orderCa#out.S=[@%)'
6.setSi5e(3<<4 2<<)'
6.s:o&()'
test.addction9istener'f('
c:ecN.add0tem9istener'f('
btnM/it.addActionCistener(6)'
)
)
Meniuri de context popup"
;u fost introduse "ncep.nd cu ;/T 1'1 si sunt implementate prin intermediul clasei PopupMenu#
subclasa directa a clasei ?enu' Sunt meniuri invi$ibile care sunt activate u$ual prin apasarea butonului
drept al mouse+ului# fiind afisate la po$itia la care se !asea mouse+ul "n momentul apasarii butonului sau
drept'
%etodele de adau!are a articolelor unui meniu popup sunt identice cu cele de la meniurile fixe#
Lopup?enu fiind subclasa directa a clasei ?enu'
popup 2 ne& Lopup?enu($=ptions$)'
popup.add(ne& ?enu0tem($Ue&$))'
popup.add(ne& ?enu0tem($Mdit$))'
popup.addSeparator()'
popup.add(ne& ?enu0tem($M/it$))'
;fisarea meniului de context se face prin metoda s%oF)
popup.s:o&(Component origin4 int /4 int #)
si este# de obicei# re$ultatul apasarii unui buton al mouse+ului# pentru a avea acces rapid la meniu'
;r!umentul *ori!in* repre$inta componenta fata de ori!inile careia se va calcula po$itia de afisare a
meniului popup' (e obicei# repre$inta instanta ferestrei "n care se va afisa meniul'
%eniurile de context nu se adau!a la un alt meniu 3bara sau sub+meniu4 ci se atasea$a la o componenta
3de obicei la o fereastra4 prin metoda add) 6ereastra.add(pm) ' In ca$ul c.nd avem mai multe meniuri
popup pe care vrem sa le folosim "ntr+o fereastra# trebuie sa le definim pe toate si# la un moment dat# vom
adau!a ferestrei meniul corespun$ator' (upa "nchiderea acestuia vom *rupe* le!atura "ntre fereastra si
meniu prin instructiunea remove)
6ereastra.add(popup;)'
. . .
6ereastra.remove(popup;)'
6ereastra.add(popup2)'
In exemplul de mai jos# vom crea un meniu de contexe ca "n ima!inea de mai jos# pe care "l vom activa la
apasarea butonului drept al mouse+ului pe suprafata ferestrei principale)
117
La ale!erea optiunii *Axit* din meniu vom termina pro!ramul' Interceptarea evenimentelor !enerate de
un meniu popup se reali$ea$a identic ca pentru meniurile fixe 3ve$i *Tratarea evenimentelor !enerate de
meniuri*4'
Exemplu de $olosire a unui meniu popup
import +ava.a&t..'
import +ava.a&t.event..'
class Fereastra e/tends Frame implements ActionCistener{
private Lopup?enu popup' --de6inim meniul popup al 6erestrei
private Component origin' --po5itia meniului va 6i relativa la
--po5itia 6erestrei
public Fereastra(String titlu) {
super(titlu)'
origin 2 t:is'
t:is.add]indo&Cistener(ne& ]indo&Adapter() {
public void &indo&Closing(]indo&Mvent e) {
S#stem.e/it(<)'
)
))'
t:is.add?ouseCistener(ne& ?ouseAdapter() {
public void mouseClicNed(?ouseMvent e) {
i6 ( (e.get?odi6iers() F 0nputMvent.3[@@=U3J?ASV)
22 0nputMvent.3[@@=U3J?ASV )
popup.s:o&(origin4 e.getT()4 e.getZ())'
--3[@@=U3 repre5inta butonul din dreapta mouse-ului
)
))'
setSi5e(3<<4 3<<)'
--cream meniul popup
popup 2 ne& Lopup?enu($=ptions$)'
popup.add(ne& ?enu0tem($Ue&$))'
popup.add(ne& ?enu0tem($Mdit$))'
popup.addSeparator()'
popup.add(ne& ?enu0tem($M/it$))'
add(popup)' --atasam meniul popup 6erestrei
popup.addActionCistener(t:is)'
)
public void actionLer6ormed(ActionMvent e) {
String command 2 e.getActionCommand()'
--Ca alegerea optiunii $M/it$ din meniu parasim aplicatia
i6 (command.eWuals($M/it$))
S#stem.e/it(<)'
)
)
public class @estLopup?enu {
public static void main(String args!) {
Fereastra 6 2 ne& Fereastra($Lopup?enu$)'
6.s:o&()'
)
)
11=
0cceleratori Clasa Menu'%ortcut"
Incep.nd cu Java ;/T 1'1 este posibila specificarea unor combinatii de taste 3acceleratori + shortcuts4
pentru accesarea directa# prin intermediul tastaturii# a optiunilor dintr+un meniu' ;stfel# oricarui obiect de
tip ?enu0tem "i poate fi asociat un obiect de tip accelerator# definit prin intermediul clasei
Menu'%ortcut' Sin!urele combinatii de taste care pot juca rolul acceleratorilor sunt) D sau D D '
;tribuirea unui accelerator la un articol al unui meniu poate fi reali$ata prin constructorul obiectelor de
tip ?enu0tem "n forma)
?enu0tem(String etic:eta4 ?enuS:ortcut accelerator)
--M/emplu
ne& ?enu0tem($=pen$4 ne& ?enuS:ortcut(Ve#Mvent.QVJ=))'
Folosirea componentelor
Clasa 2abel
-n obiect de tip 2abel etic%eta" repre$inta o componenta pentru plasarea unui text pe o suprafata de
afisare' O eticheta este formata dintr+o sin!ura linie de text static ce nu poate fi modificat de catre
utili$ator# dar poate fi modificat din pro!ram'
Axemplu) definim cinci etichete si le plasam "ntr+un container'
import +ava.a&t..'
public class @estCabel {
public static void main(String args!) {
Frame 6 2 ne& Frame($@estCabel$)'
6.setCa#out(ne& 3orderCa#out())'
Cabel nord4 sud4 est4 vest4 centru'
nord 2 ne& Cabel($Uord$4 Cabel.CMU@MP)'
sud 2 ne& Cabel($Sud$4 Cabel.CMU@MP)'
est 2 ne& Cabel($Mst$4 Cabel.P09%@)'
vest 2 ne& Cabel($Qest$4 Cabel.CMF@)'
centru 2 ne& Cabel($Centru$4 Cabel.CMU@MP)'
centru.set3acNground(Color.#ello&)'
centru.setFont(ne& Font($Arial$4 Font.3=CS4 ;"))'
6.add(nord4 3orderCa#out.U=P@%)'
6.add(sud4 3orderCa#out.S=[@%)'
6.add(est4 3orderCa#out.MAS@)'
6.add(vest4 3orderCa#out.]MS@)'
11D
6.add(centru4 3orderCa#out.CMU@MP)'
6.pacN()'
6.s:o&()'
)
)
Clasa @utton
-n obiect de tip @utton buton" repre$inta o componenta pentru plasarea unui buton etichetat pe o
suprafata de afisare'
Axemplu) definim doua butoane si le plasam pe o fereastra6 la apasarea butonului *OB* titlul ferestrei va
fi *Confirmare*# iar la apasarea butonului *Cancel* titlul ferestrei va fi *>enuntare*'
import +ava.a&t..'
import +ava.a&t.event..'
class Fereastra e/tends Frame implements ActionCistener{
public Fereastra(String titlu) {
super(titlu)'
t:is.add]indo&Cistener(ne& ]indo&Adapter() {
public void &indo&Closing(]indo&Mvent e) {
S#stem.e/it(<)'
)
))'
)
public void initiali5are() {
setCa#out(null)'
setSi5e(2<<4 2<<)'
3utton b; 2 ne& 3utton($=V$)'
b;.set3ounds(3<4 3<4 (<4 1<)'
b;.setFont(ne& Font($Arial$4 Font.3=CS4 ;"))'
b;.set3acNground(+ava.a&t.Color.orange)'
add(b;)'
3utton b2 2 ne& 3utton($Cancel$)'
b2.set3ounds(;<<4 3<4 1<4 (<)'
b2.setForeground(+ava.a&t.Color.blue)'
add(b2)'
b;.addActionCistener(t:is)'
b2.addActionCistener(t:is)'
)
--metoda inter6etei ActionCistener
public void actionLer6ormed(ActionMvent e) {
String command 2 e.getActionCommand()'
S#stem.out.println(e.toString())'
i6 (command.eWuals($=V$))
11?
set@itle($Con6irmare>$)'
i6 (command.eWuals($Cancel$))
set@itle($Anulare>$)'
)
)
public class @est3utton {
public static void main(String args!) {
Fereastra 6 2 ne& Fereastra($3utton$)'
6.initiali5are()'
6.s:o&()'
)
)
Clasa C%ecAbox
-n obiect de tip C%ecAbox comutator" repre$inta o componenta care se poate !asi "n doua stari )
*selectata* sau *neselectata* 3onJoff4' ;ctiunea utili$atorului asupra unui comutator "l trece pe acesta "n
starea complementara celei "n care se !asea' Aste folosit pentru a prelua o anumita optiune de la utili$ator'
import +ava.a&t..'
import +ava.a&t.event..'
class Fereastra e/tends Frame implements 0temCistener {
private Cabel label;4 label2'
private C:ecNbo/ cb/;4 cb/24 cb/3'
public Fereastra(String titlu) {
super(titlu)'
t:is.add]indo&Cistener(ne& ]indo&Adapter() {
public void &indo&Closing(]indo&Mvent e) {
S#stem.e/it(<)'
)
))'
)
public void initiali5are() {
setCa#out(ne& 9ridCa#out((4 ;))'
label; 2 ne& Cabel($0ngrediente Li55a,$4 Cabel.CMU@MP)'
label;.set3acNground(Color.orange)'
label2 2 ne& Cabel($$)'
label2.set3acNground(Color.lig:t9ra#)'
cb/; 2 ne& C:ecNbo/($cascaval$)'
cb/2 2 ne& C:ecNbo/($sunca$)'
11@
cb/3 2 ne& C:ecNbo/($ardei$)'
add(label;)'
add(label2)'
add(cb/;)'
add(cb/2)'
add(cb/3)'
pacN()'
setSi5e(2<<4 2<<)'
cb/;.add0temCistener(t:is)'
cb/2.add0temCistener(t:is)'
cb/3.add0temCistener(t:is)'
)
--metoda inter6etei 0temCistener
public void itemStateC:anged(0temMvent e) {
String3u66er ingrediente 2 ne& String3u66er()'
i6 (cb/;.getState() 22 true)
ingrediente.append($ cascaval $)'
i6 (cb/2.getState() 22 true)
ingrediente.append($ sunca $)'
i6 (cb/3.getState() 22 true)
ingrediente.append($ ardei $)'
label2.set@e/t(ingrediente.toString())'
)
)
public class @estC:ecNbo/ {
public static void main(String args!) {
Fereastra 6 2 ne& Fereastra($C:ecNbo/$)'
6.initiali5are()'
6.s:o&()'
)
)
Clasa C%ecAbox=roup
-n obiect de tip C%ecAbox=roup defineste un grup de comutatoare din care doar unul poate fi selectat'
-$ual# aceste componente se mai numesc butoane radio'
import +ava.a&t..'
import +ava.a&t.event..'
class Fereastra e/tends Frame implements 0temCistener {
119
private Cabel label;4 label2'
private C:ecNbo/ cb/;4 cb/24 cb/3'
private C:ecNbo/9roup cbg'
public Fereastra(String titlu) {
super(titlu)'
t:is.add]indo&Cistener(ne& ]indo&Adapter() {
public void &indo&Closing(]indo&Mvent e) {
S#stem.e/it(<)'
)
))'
)
public void initiali5are() {
setCa#out(ne& 9ridCa#out((4 ;))'
label; 2 ne& Cabel($Alegeti postul @Q$4 Cabel.CMU@MP)'
label;.set3acNground(Color.orange)'
label2 2 ne& Cabel($$4 Cabel.CMU@MP)'
label2.set3acNground(Color.lig:t9ra#)'
cbg 2 ne& C:ecNbo/9roup()'
cb/; 2 ne& C:ecNbo/($Lro @Q$4 cbg4 6alse)'
cb/2 2 ne& C:ecNbo/($Antena ;$4 cbg4 6alse)'
cb/3 2 ne& C:ecNbo/($Lrima$4 cbg4 6alse)'
add(label;)'
add(label2)'
add(cb/;)'
add(cb/2)'
add(cb/3)'
pacN()'
setSi5e(2<<4 2<<)'
cb/;.add0temCistener(t:is)'
cb/2.add0temCistener(t:is)'
cb/3.add0temCistener(t:is)'
)
--metoda inter6etei 0temCistener
public void itemStateC:anged(0temMvent e) {
C:ecNbo/ cb/ 2 cbg.getSelectedC:ecNbo/()'
i6 (cb/ >2 null)
label2.set@e/t(cb/.getCabel())'
)
)
public class @estC:ecNbo/9roup {
public static void main(String args!) {
Fereastra 6 2 ne& Fereastra($C:ecNbo/9roup$)'
6.initiali5are()'
6.s:o&()'
)
)
Clasa C%oice
-n obiect de tip C%oice defineste o lista de optiuni din care utili$atorul poate selecta una sin!ura' La un
moment dat# din "ntrea!a lista doar o sin!ura optiune este vi$ibila# cea selectata "n momentul curent' O
componenta C:oice este "nsotita de un buton etichetat cu o sa!eata verticala la apasarea caruia este
afisata "ntrea!a sa lista# pentru ca utili$atorul sa poata selecta o anumita optiune'
11:
import +ava.a&t..'
import +ava.a&t.event..'
class Fereastra e/tends Frame implements 0temCistener {
private Cabel label'
private C:oice culori'
public Fereastra(String titlu) {
super(titlu)'
t:is.add]indo&Cistener(ne& ]indo&Adapter() {
public void &indo&Closing(]indo&Mvent e) {
S#stem.e/it(<)'
)
))'
)
public void initiali5are() {
setCa#out(ne& 9ridCa#out("4 ;))'
label 2 ne& Cabel($Alegeti culoarea$)'
label.set3acNground(Color.red)'
culori 2 ne& C:oice()'
culori.add($Posu$)'
culori.add($Qerde$)'
culori.add($Albastru$)'
culori.select($Posu$)'
add(label)'
add(culori)'
pacN()'
setSi5e(2<<4 ;<<)'
culori.add0temCistener(t:is)'
)
--metoda inter6etei 0temCistener
public void itemStateC:anged(0temMvent e) {
s&itc: (culori.getSelected0nde/()) {
case <,
label.set3acNground(Color.red)'
breaN'
case ;,
label.set3acNground(Color.green)'
breaN'
case 2,
label.set3acNground(Color.blue)'
)
)
)
public class @estC:oice {
public static void main(String args!) {
Fereastra 6 2 ne& Fereastra($C:oice$)'
6.initiali5are()'
6.s:o&()'
11<
)
)
Clasa 2ist
-n obiect de tip 2ist defineste o lista de optiuni care poate fi setata astfel "nc.t utili$atorul sa poata
selecta o sin!ura optiune sau mai multe' Toate optiunile listei sunt vi$ibile "n limita dimensiunilor !rafice
ale componentei'
import +ava.a&t..'
import +ava.a&t.event..'
class Fereastra e/tends Frame implements 0temCistener {
private Cabel label'
private Cist culori'
public Fereastra(String titlu) {
super(titlu)'
t:is.add]indo&Cistener(ne& ]indo&Adapter() {
public void &indo&Closing(]indo&Mvent e) {
S#stem.e/it(<)'
)
))'
)
public void initiali5are() {
setCa#out(ne& 9ridCa#out(24 ;))'
label 2 ne& Cabel($Alegeti culoarea$4 Cabel.CMU@MP)'
label.set3acNground(Color.red)'
culori 2 ne& Cist(3)'
culori.add($Posu$)'
culori.add($Qerde$)'
culori.add($Albastru$)'
culori.select(3)'
add(label)'
add(culori)'
pacN()'
setSi5e(2<<4 2<<)'
culori.add0temCistener(t:is)'
)
--metoda inter6etei 0temCistener
public void itemStateC:anged(0temMvent e) {
s&itc: (culori.getSelected0nde/()) {
178
case <,
label.set3acNground(Color.red)'
breaN'
case ;,
label.set3acNground(Color.green)'
breaN'
case 2,
label.set3acNground(Color.blue)'
)
)
)
public class @estCist {
public static void main(String args!) {
Fereastra 6 2 ne& Fereastra($Cist$)'
6.initiali5are()'
6.s:o&()'
)
)
Clasa 'crollbar
-n obiect de tip 'crollbar defineste o bara de de$ilare verticala sau ori$ontala' Aste utila pentru punerea
la dispo$itie a utili$atorului a unei modalitati su!estive de a ale!e o anumita valoare dintr+un interval'
import +ava.a&t..'
import +ava.a&t.event..'
class Fereastra e/tends Frame implements Ad+ustmentCistener {
private Scrollbar scroll'
private Cabel valoare'
public Fereastra(String titlu) {
super(titlu)'
t:is.add]indo&Cistener(ne& ]indo&Adapter() {
public void &indo&Closing(]indo&Mvent e) {
S#stem.e/it(<)'
)
))'
)
public void initiali5are() {
setCa#out(ne& 9ridCa#out(24 ;))'
valoare 2 ne& Cabel($$4 Cabel.CMU@MP)'
valoare.set3acNground(Color.lig:t9ra#)'
scroll 2 ne& Scrollbar(Scrollbar.%=P0X=U@AC4 <4 ;4 <4 ;<;)'
add(valoare)'
add(scroll)'
pacN()'
setSi5e(2<<4 7<)'
171
scroll.addAd+ustmentCistener(t:is)'
)
--metoda inter6etei 0temCistener
public void ad+ustmentQalueC:anged(Ad+ustmentMvent e) {
valoare.set@e/t(scroll.getQalue() D $ E$)'
)
)
public class @estScrollbar {
public static void main(String args!) {
Fereastra 6 2 ne& Fereastra($Scrollbar$)'
6.initiali5are()'
6.s:o&()'
)
)
Clasa 'crollPane
-n obiect de tip 'crollPane permite atasarea unor bare de defilare 3ori$ontala siJsau verticala4 oricarei
componente !rafice' ;cest lucru este util pentru acele componente care nu au implementata
functionalitatea de defilare automata# cum ar fi listele 3obiecte din clasa Cist4'
import +ava.a&t..'
import +ava.a&t.event..'
class Fereastra e/tends Frame {
private ScrollLane sp'
private Cist list'
public Fereastra(String titlu) {
super(titlu)'
t:is.add]indo&Cistener(ne& ]indo&Adapter() {
public void &indo&Closing(]indo&Mvent e) {
S#stem.e/it(<)'
)
))'
)
public void initiali5are() {
setCa#out(ne& Flo&Ca#out())'
list 2 ne& Cist(1)'
list.add($Cuni$)'
list.add($?arti$)'
list.add($?iercuri$)'
list.add($Joi$)'
list.add($Qineri$)'
177
list.add($Sambata$)'
list.add($Suminica$)'
list.select(;)'
sp 2 ne& ScrollLane(ScrollLane.SCP=CC3APSJAC]AZS)'
sp.add(list)'
add(sp)'
pacN()'
setSi5e(2<<4 2<<)'
)
)
public class @estScrollLane {
public static void main(String args!) {
Fereastra 6 2 ne& Fereastra($ScrollLane$)'
6.initiali5are()'
6.s:o&()'
)
)
Clasa TextField
-n obiect de tip TextField defineste un control de editare a textului pe o sin!ura linie' Aste util pentru
intero!area utili$atorului asupra unor valori'
import +ava.a&t..'
import +ava.a&t.event..'
class Fereastra e/tends Frame implements @e/tCistener {
private @e/tField nume4 parola'
private Cabel acces'
private static 6inal String [0S2$0on$4 L]S2$+ava$ '
public Fereastra(String titlu) {
super(titlu)'
t:is.add]indo&Cistener(ne& ]indo&Adapter() {
public void &indo&Closing(]indo&Mvent e) {
S#stem.e/it(<)'
)
))'
)
public void initiali5are() {
setCa#out(ne& 9ridCa#out(34 ;))'
set3acNground(Color.lig:t9ra#)'
nume 2 ne& @e/tField($$4 3<)'
parola 2 ne& @e/tField($$4 ;<)'
17=
parola.setMc:oC:ar(R.R)'
Lanel p; 2 ne& Lanel()'
p;.setCa#out(ne& Flo&Ca#out(Flo&Ca#out.CMF@))'
p;.add(ne& Cabel($Uume,$))'
p;.add(nume)'
Lanel p2 2 ne& Lanel()'
p2.setCa#out(ne& Flo&Ca#out(Flo&Ca#out.CMF@))'
p2.add(ne& Cabel($Larola,$))'
p2.add(parola)'
acces 2 ne& Cabel($0ntroduceti numele si parola>$4
Cabel.CMU@MP)'
add(p;)'
add(p2)'
add(acces)'
pacN()'
setSi5e(3(<4 ;<<)'
nume.add@e/tCistener(t:is)'
parola.add@e/tCistener(t:is)'
)
--metoda inter6etei @e/tCistener
public void te/tQalueC:anged(@e/tMvent e) {
i6 ((nume.get@e/t().lengt:() 22 <) GG
(parola.get@e/t().lengt:() 22 <)) {
acces.set@e/t($$)'
return'
)
i6 (nume.get@e/t().eWuals([0S) FF
parola.get@e/t().eWuals(L]S))
acces.set@e/t($Acces permis>$)'
else
acces.set@e/t($Acces inter5is>$)'
)
)
public class @est@e/tField {
public static void main(String args!) {
Fereastra 6 2 ne& Fereastra($@e/tField$)'
6.initiali5are()'
6.s:o&()'
)
)
Clasa Text0rea
-n obiect de tip Text0rea defineste un control de editare a textului pe mai multe linii' Aste util pentru
editarea de texte# introducerea unor comentarii# etc '
17D
import +ava.a&t..'
import +ava.a&t.event..'
import +ava.io..'
class Fereastra e/tends Frame implements @e/tCistener4 ActionCistener {
private @e/tArea te/t'
private @e/tField nume'
private 3utton save'
public Fereastra(String titlu) {
super(titlu)'
t:is.add]indo&Cistener(ne& ]indo&Adapter() {
public void &indo&Closing(]indo&Mvent e) {
S#stem.e/it(<)'
)
))'
)
public void initiali5are() {
set3acNground(Color.lig:t9ra#)'
te/t 2 ne& @e/tArea($$4 3<4 ;<4
@e/tArea.SCP=CC3APSJQMP@0CACJ=UCZ)'
nume 2 ne& @e/tField($$4 ;2)'
save 2 ne& 3utton($Salvea5a te/t$)'
save.setActionCommand($save$)'
save.setMnabled(6alse)'
Lanel 6isier 2 ne& Lanel()'
6isier.add(ne& Cabel($Fisier,$))'
6isier.add(nume)'
add(6isier4 3orderCa#out.U=P@%)'
add(te/t4 3orderCa#out.CMU@MP)'
add(save4 3orderCa#out.S=[@%)'
pacN()'
setSi5e(3<<4 2<<)'
te/t.add@e/tCistener(t:is)'
save.addActionCistener(t:is)'
)
--metoda inter6etei @e/tCistener
public void te/tQalueC:anged(@e/tMvent e) {
i6 ((te/t.get@e/t().lengt:() 22 <) GG
(nume.get@e/t().lengt:() 22 <))
save.setMnabled(6alse)'
else
save.setMnabled(true)'
)
17?
--metoda inter6etei ActionCistener
public void actionLer6ormed(ActionMvent e) {
String continut 2 te/t.get@e/t()'
int len 2 continut.lengt:()'
c:ar bu66er! 2 ne& c:arlen!'
tr# {
File]riter out 2 ne& File]riter(nume.get@e/t())'
continut.getC:ars(<4 len-;4 bu66er4 <)'
out.&rite(bu66er)'
out.close()'
te/t.reWuestFocus()'
)
catc:(0=M/ception e/) {
e/.printStacN@race()'
)
)
)
public class @est@e/tArea {
public static void main(String args!) {
Fereastra 6 2 ne& Fereastra($@e/tArea$)'
6.initiali5are()'
6.s:o&()'
)
)
Curs *
+esenarea
Conceptul de desenare
(esenarea obiectelor + metoda paint34
Suprafete de desenare + clasa Canvas
Contextul !rafic de desenare + clasa Iraphics
o Eroprietatile unui context !rafic
o Erimitive !rafice
(esenarea textelor
(esenarea fi!urilor !eometrice
olosirea fonturilor
o Clasa ont
o Clasa ont%etrics
olosirea culorilor
olosirea ima!inilor
o Incarcarea unei ima!ini dintr+un fisier
o ;fisarea ima!inilor
o %onitori$area "ncarcarii ima!inilor + interfata Ima!eObserver
o Crearea ima!inilor "n memorie + clasa %emor&Ima!eSource
Tiparirea
Top
17@
Conceptul de desenare
-n pro!ram Java care are interfata !rafica cu utili$atorul trebui sa desene$e pe ecran toate componentele
sale care au o repre$entarea !rafica vi$uala' ;ceasta desenare include componentele vi$uale standard
folosite "n pro!ram precum si obiectele !rafice definite de catre pro!ramator' (esenarea componentelor
se face automat si este un proces care se executa "n urmatoarele situatii)
la afisarea pentru prima data a unei componente
ca raspuns al unei solicitari explicite a pro!ramului
la operatii de minimi$are# maximi$are# redimensionare a suprafetei de afisare pe care este plasata
o componenta
%etodele care controlea$a procesul de desenare se !asesc "n clasa Component si sunt pre$entate "n tabelul
de mai jos)
void
paint(9rap:ics g)
(esenea$a o componenta' Aste o metoda supradefinita de fiecare componenta "n
parte pentru a furni$a repre$entarea sa !rafica specifica' %etoda este apelata de
fiecare data c.nd continutul componentei trebuie desenat 3redesenat4 + la afisarea
pentru prima data a componentei# la operatii de redimensionare# etc' 1u se apelea$a
explicit'
void
update(9rap:ics
g)
;ctuali$ea$a starea !rafica a unei componente' ;ctiunea acestei metode se reali$ea$a
"n trei pasi)
ster!e componenta prin supradesenarea ei cu culoarea fundalului
stabileste culoarea 3fore!round4 a componentei
apelea$a metoda paint pentru a redesena complet componenta
1u se apelea$a explicit'
void repaint()
Axecuta explicit un apel al metodei update pentru a actuali$a repre$entarea !rafica a
unei componente'
(upa cum se observa sin!urul ar!ument al metodelor paint si update este un obiect de tip =rap%ics'
;cesta obiect repre$inta contextul grafic "n care se executa desenarea componentelor 3ve$i *Contextul
!rafic de desenare + clasa Iraphics*4'
Toate desenele care trebuie sa apara pe o suprafata de desenare se reali$ea$a "n metoda paint a unei
componente# "n !eneral apelata intern sau explicit cu metoda repaint# ori de c.te ori componenta
respectiva trebuie redesenata'
+esenarea obiectelor 1 metoda paint
Toate desenele care trebuie sa apara pe o suprafata de desenare se reali$ea$a "n metoda paint a unei
componente' %etoda paint este definita "n superclasa Component "nsa nu are nici o implementare si# din
acest motiv# orice obiect !rafic care doreste sa se desene$e trebuie sa o supradefineasca pentru a+si crea
propria sa repre$entare'
Componentele standard ;/T au deja supradefinita aceasta metoda deci nu trebuie sa ne preocupe
desenarea lor# "nsa putem modifica repre$entarea lor !rafica prin crearea unei subclase si supradefinirea
metodei paint# av.nd "nsa !rija sa apelam si metoda superclasei care se ocupa cu desenarea efectiva a
componentei'
179
In exemplul de mai jos# redefinim metoda paint pentru un obiect de tip Frame# pentru a crea o clasa ce
instantia$a ferestre pentru o aplicatie demonstrativa 3"n coltul st.n!a sus este afisat textul *;plicatie
(A%O*4'
import +ava.a&t..'
class Fereastra e/tends Frame {
public Fereastra(String titlu) {
super(titlu)'
setSi5e(2<<4 ;<<)'
)
public void paint(9rap:ics g) {
super.paint(g)'--apele5 metoda paint a clasei Frame
g.setFont(ne& Font($Arial$4 Font.3=CS4 ;;))'
g.setColor(Color.red)'
g.dra&String($Aplicatie SM?=$4 (4 3()'
)
)
public class @estLaint {
public static void main(String args!) {
Fereastra 6 2 ne& Fereastra($@est Laint$)'
6.s:o&()'
)
)
Observati ca la orice redimensionare a ferestrei textul *;plicatie (A%O* va fi redesenat' (aca desenarea
acestui text ar fi fost facuta oriunde "n alta parte dec.t "n metoda paint# la prima redimensionare a
ferestrei acesta s+ar pierde'
;sadar# desenarea "n Java trebuie sa se faca doar "n cadrul metodelor paint ale componentelor !rafice'
'upra$ete de desenare 1 clasa Canvas
In afara posibilitatii de a utili$a componente !rafice standard# Java ofera si posibilitatea controlului la
nivel de punct 3pixel4 pe dispo$itivul !rafic# respectiv desenarea a diferite forme !rafice direct pe
suprafata unei componente' (esi este posibil# "n !eneral nu se desenea$a la nivel de pixel direct pe
suprafata ferestrelor sau a altor suprafete de afisare'
In Java a fost definit un tip special de componenta numita Canvas 3p.n$a de pictor4# a carui scop este de a
fi extinsa pentru a implementa obiecte !rafice cu o anumita "nfatisare' ;sadar clasa Canvas este o clasa
!enerica din care se derivea$a subclase pentru crearea suprafetelor de desenare 3planse4' Elansele nu pot
contine alte componente !rafice# ele fiind utili$ate doar ca suprafete de desenat sau ca fundal pentru
animatie' (esenarea pe o plansa se face prin supradefinirea metodei paint'
Concret# o plansa este suprafata dreptun!hiulara de culoare alba pe care se poate desena' Implicit
dimensiunile plansei sunt 8 si# din acest motiv# !estionarii de po$itionare nu vor avea la dispo$itie
dimensiuni implcite pentru afisarea unui obiect de tip Canvas' Eentru a evita acest neajuns este
recomandat ca o plansa sa redefineasca si metodele get?inimumSi5e4 get?a/imumSi5e4
getLre6erredSi5e pentru a+si specifica dimensiunile implicite'
Atapele care trebuie parcurse pentru crearea unui desen# sau mai bine $is# a unui obiect !rafic cu o
anumita "nfatisare sunt)
crearea unei planse de desenare# adica o subclasa a clasei Canvas
redefinirea metodei paint din clasa respectiva
redefinirea metodelor get?inimumSi5e4 get?a/imumSi5e4 getLre6erredSi5e
desenarea efectiva a componentei "n cadrul metodei paint
17:
adau!area plansei la un container cu metoda add'
interceptarea evenimentelor de tip FocusMvent4 Ve#Mvent4 ?ouseMvent4 ComponentMvent si
tratarea lor 3daca este ca$ul4'
(efinirea !enerica a unei planse are urmatorul format)
class Llansa e/tends Canvas {
public void paint(9rap:ics g) {
. . .
--desenarea
)
public Simension get?inimumSi5e() {
return . . .
)
public Simension get?a/imumSi5e() {
return . . .
)
public Simension getLre6erredSi5e() {
return . . .'
)
Axemplu) Sa definim o plansa pe care desenam un patrat si cercul sau circumscris' Elansa o vom afisa
apoi pe o fereastra'
import +ava.a&t..'
class Llansa e/tends Canvas {
Simension canvasSi5e 2 ne& Simension(;<<4 ;<<)'
public void paint(9rap:ics g) {
g.setColor(Color.red)'
g.dra&Pect(<4 <4 ;<<4 ;<<)'
g.setColor(Color.blue)'
g.dra&=val(<4 <4 ;<<4 ;<<)'
)
public Simension get?inimumSi5e() {
return canvasSi5e'
)
public Simension getLre6erredSi5e() {
return canvasSi5e'
)
)
class Fereastra e/tends Frame {
public Fereastra(String titlu) {
super(titlu)'
setSi5e(2<<4 2<<)'
add(ne& Llansa()4 3orderCa#out.CMU@MP)'
)
)
public class @estCanvas {
public static void main(String args!) {
Fereastra 6 2 ne& Fereastra($@est Laint$)'
6.s:o&()'
)
)
Contextul gra$ic de desenare 1 clasa =rap%ics
17<
Inainte ca utili$atorul sa poata desena el trebuie sa obtina un context !rafic de desenare pentru suprafata
careia "i apartine re!iunea pe care se va desena' -n context grafic este# de fapt# un obiect prin intermediul
caruia putem controla procesul de desenare a unui obiect' In !eneral desenarea se poate face)
pe o portiune de ecran#
la imprimanta sau
"ntr+o $ona virtuala de memorie'
-n context !rafic este specificat prin intermediul obiectelor de tip =rap%ics primite ca parametru "n
metodele paint si update' In functie de dispo$itivul fi$ic pe care se face afisarea 3ecran# imprimanta#
plotter# etc4 metodele de desenare au implementari interne diferite# transparente utili$atorului'
Clasa 9rap:ics pune la dispo$itie metode pentru)
primitive !rafice ) desenarea de fi!uri !eometrice# texte si ima!ini
stabilirea proprietatilor unui context !rafic# adica)
o stabilirea culorii si fontului curente cu care se face desenarea
o stabilirea ori!inii coordonatelor suprafetei de desenare
o stabilirea suprafetei "n care sunt vi$ibile componentelor desenate
o stabilirea modului de desenare'
Proprietatile contextului gra$ic
La orice tip de desenare parametrii le!ati de culoare# font# etc' sunt specificati de contextul !rafic "n care
se face desenarea' In continuare# enumeram aceste proprietati si metodele asociate lor "n clasa 9rap:ics'
culoarea curenta de desenare
Color getColor()
void setColor(Color c)
fontul curent cu care vor fi scrise textele
Font getFont()
void setFont(Font 6)
ori!inea coordonatelor + poate fi modificata prin )
translate(int /4 int #)
$ona de decupare) $ona "n care sunt vi$ibile desenele
S:ape getClip()
void setClip(S:ape s)
void setClip(int /4 int #4 int &idt:4 int :eig:t)
modul de desenare
void setTor?ode(Color c;) - desenare $sau e/clusiv$
void setLaint?ode(Color c;) - supradesenare
Primitive gra$ice
Erin primitive !rafice ne vom referi "n continuare la metodele clasei 9rap:ics care permit desenarea de
fi!uri !eometrice si texte'
+esenarea textelor
(esenarea textelor de face cu metodele draF'tringH draF@EtesH draFC%ars "n urmatoarele formate)
dra&String(String str4 int /4 int #)
dra&3#tes(b#test data4 int o66set4 int lengt:4 int /4 int #)
dra&C:ars(c:arst data4 int o66set4 int lengt:4 int /4 int #)
1=8
unde x si & repre$inta coltul din st.n!a+jos al textului' Textul desenat va avea culoarea curenta a
contextului !rafic'
+esenarea $igurilor geometrice
Anumeram "n continuare fi!urile !eometrice ce pot fi desenate "n Java si metodele folosite pentru aceasta)
linii
dra&Cine(int /;4 int #;4 int /24 int #2)
dra&Lol#line(intst /Loints4 intst #Loints4 int nLoints)
dreptun!hiuri simple
dra&Pect(int /4 int #4 int &idt:4 int :eig:t)
6illPect(int /4 int #4 int &idt:4 int :eig:t)
clearPect(int /4 int #4 int &idt:4 int :eig:t)
dreptun!hiuri cu chenar *ridicat* sau *ad.ncit*
dra&3SPect(int /4 int #4 int &idt:4 int :eig:t4 boolean raised)
6ill3SPect(int /4 int #4 int &idt:4 int :eig:t4 boolean raised)
dreptun!hiuri cu colturi rotunjite
dra&PoundPect(int /4 int #4 int &idt:4 int :eig:t4 int arc]idt:4 int
arc%eig:t)
6illPoundPect(int /4 int #4 int &idt:4 int :eig:t4 int arc]idt:4 int
arc%eig:t
ovaluri
dra&=val(int /4 int #4 int &idt:4 int :eig:t)
6ill=val(int /4 int #4 int &idt:4 int :eig:t)
arce circulare sau eliptice
dra&Arc(int /4 int #4 int &idt:4 int :eig:t4 int startAngle4 int
arcAngle)
6illArc(int /4 int #4 int &idt:4 int :eig:t4 int startAngle4 int
arcAngle)
poli!oane
dra&Lol#gon(intst /Loints4 intst #Loints4 int nLoints)
dra&Lol#gon(Lol#gon p)
6illLol#gon(intst /Loints4 intst #Loints4 int nLoints)
6illLol#gon(Lol#gon p)
%etodele care "ncep cu *fill* vor desena fi!uri !eometrice care au interiorul colorat# adica *umplut* cu
culoarea curenta a contextului de desenare'
Folosirea $onturilor
(upa cum va$ut# pentru a scrie un text pe ecran avem doua posibilitati' Erima dintre acestea este sa
folosim o componenta orientata+text cum ar fi Cabel4 @e/tField sau @e/tArea# iar a doua sa apelam la
metodele clasei 9rap:ics de desenare a textelor) dra&String4 dra&C:ars4 dra&3#tes' Indiferent de
modalitatea aleasa# putem specifica prin intermediul fonturilor cum sa arate textul respectiv# acest lucru
reali$.ndu+se prin metoda clasei Component# respectiv 9rap:ics) setFontFont $"'
Cei mai importanti parametri ce caracteri$ea$a un font sunt)
numele fontului) Celvetica Hold# ;rial Hold Italic# etc
familia din care face parte fontul) Celvetica# ;rial# etc
dimensiunea fontului) "naltimea sa
stilul fontului) .ngrosat bold"# nclinat (italic!
metrica fontului
1=1
Clasele care ofera suport pentru lucrul cu fonturi sunt Font si FontMetrics' In continuare sunt pre$entate
modalitatile de lucru cu aceste doua clase'
Clasa Font
-n obiect de tip Font "ncapsulea$a informatii despre toti parametrii unui font# mai putin despre metrica
acestuia' Constructorul u$ual al clasei este cel care primeste ca ar!umene numele fontului# dimensiunea si
stilul acestuia'
Font(String name4 int st#le4 int si5e)
Stilul unui font este specificat prin intermediul constantelor )
Font.LCA0U - normal
Font.3=CS - @ngrosat
Font.0@AC0C - nclinat
M/emple,
ne& Font($Arial$4 Font.3=CS4 ;2)'
ne& Font($@imes Ue& Poman$4 Font.0@AC0C4 ;")'
ne& Font($Courier Ue&$4 Font.LCA0U4 ;<)'
olosirea unui obiect de tip ont se reali$ea$a u$ual astfel)
--pentru componente etic:etate
Cabel label 2 ne& Cabel($@e/t Java$)'
label.setFont(ne& Font($Arial$4 Font.3=CS4 ;2))'
--in metoda paint(9rap:ics g)
g.setFont(ne& Font($@imes Ue& Poman$4 Font.0@AC0C4 ;"))'
g.dra&String($@e/t Java$4 <4 <)'
O platforma de lucru are instalate# la un moment dat# o serie "ntrea!a de fonturi care sunt disponibile
pentru scrierea textelor' Lista acestor fonturi se poate obtine cu metoda getAllFonts a clasei
9rap:icsMnvironment astfel)
Font! 6onturi 2
9rap:icsMnvironment.getCocal9rap:icsMnvironment().getAllFonts()'
Axemplul urmator afisea$a lista primelor 78 de fonturi disponibile pe platforma curenta de lucru' Textul
fiecarui nume de font va fi scris cu fontul sau corespun$ator'
import +ava.a&t..'
class Fonturi e/tends Canvas {
private Font! 6onturi'
Simension canvasSi5e 2 ne& Simension("<<4 "<<)'
public Fonturi() {
setSi5e(canvasSi5e)'
6onturi 2 9rap:icsMnvironment.
getCocal9rap:icsMnvironment().getAllFonts()'
)
public void paint(9rap:ics g) {
String nume'
6or(int i2<' i A 2<' iDD) {
nume 2 6onturii!.getFontUame()'
g.setFont(ne& Font(nume4 Font.LCA0U4 ;"))'
g.dra&String(nume4 2<4 (i D ;) . 2<)'
)
)
public Simension get?inimumSi5e() {
return canvasSi5e'
)
public Simension getLre6erredSi5e() {
return canvasSi5e'
)
)
class Fereastra e/tends Frame {
public Fereastra(String titlu) {
1=7
super(titlu)'
add(ne& Fonturi()43orderCa#out.CMU@MP)'
pacN()'
)
)
public class @estAllFonts {
public static void main(String args!) {
Fereastra 6 2 ne& Fereastra($All 6onts$)'
6.s:o&()'
)
)
Clasa FontMetrics
La afisarea unui sir cu metoda dra&String trebuie sa specificam po$itia la care sa apara sirul pe ecran' In
momentul "n care avem de afisat mai multe siruri trebuie sa calculam po$itiile lor de afisare "n functie de
lun!imea si "naltimea "n pixeli a textului fiecarui sir' Eentru aceasta este folosita clasa FontMetrics' -n
obiect din aceasta clasa se construieste pornind de la un obiect de tip Font si pune la dispo$itie informatii
despre dimensiunile "n pixeli pe care le au caracterele fontului respectiv'
;sadar# un obiect de tip Font?etrics "ncapsulea$a informatii despre metrica unui font# cu alte cuvinte
despre dimensiunile "n pixeli ale caracterelor sale'
-tilitatea principala a acestei clase consta "n faptul ca permite po$itionarea precisa a textelor pe o
suprafata de desenare# indiferent de fontul folosit de acestea'
%etrica unui font consta "n urmatoarele atribute pe care le au caracterele unui font)
linia de ba$a ) este linia dupa care sunt aliniate caracterele unui font
linia de ascendenta ) linia superioara pe care nu o depaseste nici un caracter din font
linia de descendenta ) linia inferioara sub care nu coboara nici un caracter din font
ascendentul) distanta "ntre linia de ba$a si linia de ascendenta
descendentul)distanta "ntre linia de ba$a si linia de descendenta
latimea) latimea unui anumit caracter din font
"naltimea) distanta "ntre liniile de ba$a
distanta "ntre linii 3*leadin!*4)distanta optima "ntre doua linii de text scrise cu acelasi font
i!ura de mai jos pre$inta o ima!ine !rafica asupra metricii unui font)
>eamintim ca la metoda dra&String(String s4 int /4 int #) ar!umentele x si & semnifica coltul
din st<nga14os al textului' Ca sa fim mai precisi# & repre$inta po$itia liniei de ba$a a textului care va fi
scris'
Constructorul clasei Font?etrics creea$a un obiect ce "ncapsulea$a informatii despre un anumit font)
Font?etrics(Font 6)'
Font 6 2 ne& Font($Arial$4 Font.3=CS4 ;;)'
Font?etrics 6m 2 ne& Font?etrics(6)'
1==
-n context !rafic pune la dispo$itie o metoda speciala getFont?etrics de creare a unui obiect de tip
Font?etrics# pornind de la fontul curent al contextului !rafic)
public void paint(9rap:ics g) {
Font 6 2 ne& Font($Arial$4 Font.3=CS4 ;;)'
Font?etrics 6m 2 g.getFont?etrics()'--ec:ivalent cu
Font?etrics 6m 2 ne& Font?etrics(6)'
)
Cele mai u$uale metode ale clasei Font?etrics sunt cele pentru)
aflarea "naltimii unei linii pe care vor fi scrise caractere ale unui font) getIeig%t#
aflarea latimii totale "n pixeli a unui sir de caractere specificat) string?idt%
aflarea latimii unui anumit caracter din font) c%ar?idt%
Axemplu) afisarea unor texte pe ecran 3$ilele saptam.nii# lunile anului si mesajul *Cello ont%etricsN*4
folosind clasa Font?etrics'
import +ava.a&t..'
class @e/te e/tends Canvas {
Simension canvasSi5e 2 ne& Simension(1<<4 3<<)'
private Stringst 5ile2{$Cuni$4 $?arti$4 $?iercuri$4 $Joi$4 $Qineri$4
$Sambata$4 $Suminica$)'
private Stringst luni 2 { $0anuarie$4 $Februarie$4 $?artie$4 $Aprilie$4
$?ai$4 $0unie$4 $0ulie$4 $August$4
$Septembrie$4 $=ctombrie$4 $Uoiembrie$4 $Secembrie$)'
public @e/te() {
setSi5e(canvasSi5e)'
)
public void paint(9rap:ics g) {
Font?etrics 6m'
int /4#'
String enumJ5ile 2 $Xilele saptamanii,$4
enumJluni2$Cunile anului,$4 te/t'
--alegem un 6ont si a6lam metrica sa
g.setFont(ne& Font($Arial$4 Font.3=CS4 2<))'
6m 2 g.getFont?etrics()'
/ 2 <'
# 2 6m.get%eig:t()'
g.dra&String(enumJ5ile4 /4 #)'
/ D2 6m.string]idt:(enumJ5ile)'
6or(int i2<' i A 5ile.lengt:' iDD) {
te/t 2 5ilesit'
i6 (i A 5ile.lengt: - ;) te/t D2 $4 $'
g.dra&String(te/t4 /4 #)'
/ D2 6m.string]idt:(te/t)'
)
--sc:imbam 6ontul
g.setFont(ne& Font($@imes Ue& Poman$4 Font.LCA0U4 ;"))'
6m 2 g.getFont?etrics()'
/ 2 <'
# D2 6m.get%eig:t()'
g.dra&String(enumJluni4 /4 #)'
/ D2 6m.string]idt:(enumJluni)'
6or(int i2<' i A luni.lengt:' iDD) {
te/t 2 lunisit'
i6 (i A luni.lengt: - ;) te/t D2 $4 $'
g.dra&String(te/t4 /4 #)'
/ D2 6m.string]idt:(te/t)'
)
--sc:imbam 6ontul curent
1=D
g.setFont(ne& Font($Courier Ue&$4 Font.3=CS4 *<))'
6m 2 g.getFont?etrics()'
/ 2 <'
# D2 6m.get%eig:t()'
g.dra&String($%ello Font?etrics>$4 /4 #)'
)
public Simension get?inimumSi5e() {
return canvasSi5e'
)
public Simension getLre6erredSi5e() {
return canvasSi5e'
)
)
class Fereastra e/tends Frame {
public Fereastra(String titlu) {
super(titlu)'
add(ne& @e/te()43orderCa#out.CMU@MP)'
pacN()'
)
)
public class @estFont?etrics {
public static void main(String args!) {
Fereastra 6 2 ne& Fereastra($Font?etrics$)'
6.s:o&()'
)
)
Folosirea culorilor
Orice culoare este formata prin combinatia culorilor standard rosu 3>ed4# verde 3Ireen4 si albastru 3Hlue4#
la care se adau!a un anumit !rad de transparenta 3;lpha4' iecare din acesti patru parametri poate varia
"ntr+un interval cuprins fie "ntre 8 si 7?? 3daca dorim sa specificam valorile prin numere "ntre!i4# fie "ntre
8'8 si 1'8 3daca dorim sa specificam valorile prin numere reale4'
O culoare este repre$entata printr+o instanta a clasei Color sau a subclasei sale 'EstemColor' Eentru a
crea o culoare avem doua posibilitati)
sa folosim una din constantele definite "ntr+un din cele doua clase
sa folosim unul din constructorii clasei Color'
Sa vedem mai "nt.i care sunt constantele definite "n aceste clase)
Color 'EstemColor
blacN
blue
c#an
darN9ra#
gra#
green
lig:t9ra#
magenta
orange
pinN
red
&:ite
#ello&
activeCaption
activeCaption3order
activeCaption@e/t
control
control%ig:lig:t
controlS:ado&
contol@e/t
desNtop
menu
te/t
te/t%ig:lig:t
&indo&
. . .
1=?
Observati ca "n clasa Color sunt definite culori u$uale din paleta standard de culori# "n timp ce "n clasa
S#stemColor sunt definite culorile componentelor standard 3ferestre# texte# meniuri# etc4 ale platformei
curente de lucru' olosirea acestor constante se face ca "n exemplele de mai jos)
Color rosu 2 Color.red'
Color galben 2 Color.#ello&'
Color 6undal 2 S#stemColor.desNtop'
(aca nici una din aceste culori predefinite nu corespunde preferintelor noastre atunci putem crea noi
culori prin intermediul constructorilor clasei Color)
Color(6loat r4 6loat g4 6loat b)
Color(6loat r4 6loat g4 6loat b4 6loat a)
Color(int r4 int g4 int b)
Color(int r4 int g4 int b4 int a)
Color(int rgb)
unde r# !# b# a sunt valorile pentru rosu# verde# albastru si transparenta 3alpha4 iar parametrul *r!b* de la
ultimul constructor repre$inta un "ntre! format din) bitii 1@+7= rosu# :+1? verde# 8+9 albastru'
Valorile ar!umentelor varia$a "ntre 8+7?? pentru tipul int# respectiv 8'8+1'8 pentru tipul float' Valoarea
7?? 3sau 1'84 pentru transparenta specifica faptul ca respectiva culoare este complet opaca# iar valoarea 8
3sau 8'84 specifica transparenta totala' Implicit# culorile sunt complet opace'
--M/emple de 6olosire a constructorilor,
Color alb 2 ne& Color(2((4 2((4 2(()'
Color negru 2 ne& Color(<4 <4 <)'
Color rosu 2 ne& Color(2((4 <4 <)'
Color rosu@ransparent 2 ne& Color(2((4 <4 <4 ;27)'
%etodele cele mai folosite ale clasei Color sunt)
Color
brig:ter()
Color darNer()
Creea$a o noua versiune a culorii curent mai deschisa J "nchisa
int getAlp:a()
int getPed()
int get9reen()
int get3lue()
(etermina parametrii din care este alcatuita culoarea
int getP93()
(etermina valoarea ce repre$inta culoarea respectiva 3bitii 1@+7= rosu# :+1? verde# 8+9
albastru4
Sa consideram o aplicatie cu ajutorul careia putem vi$uali$a dinamic culorile obtinute prin diferite
combinatii ale parametrilor ce formea$a o culoare' ;plicatia va arata astfel)
import +ava.a&t..'
import +ava.a&t.event..'
class Culoare e/tends Canvas {
public Color color 2 ne& Color(<4 <4 <4 2(()'
Simension canvasSi5e 2 ne& Simension(;(<4 (<)'
public Culoare() { setSi5e(canvasSi5e)' )
public void paint(9rap:ics g) {
g.setColor(color)'
g.6illPect(<4 <4 canvasSi5e.&idt:4 canvasSi5e.:eig:t)'
String te/t 2 $$'
te/t D2 $ P2$ D color.getPed()'
1=@
te/t D2 $ 92$ D color.get9reen()'
te/t D2 $ 32$ D color.get3lue()'
te/t D2 $ A2$ D color.getAlp:a()'
g.dra&String(te/t4 <4 3<)'
)
public Simension getLre6erredSi5e() {return canvasSi5e' )
)
--6ereastra principala
class Fereastra e/tends Frame implements Ad+ustmentCistener {
private Scrollbar rQalue4 gQalue4 bQalue4 aQalue'
private Culoare culoare'
public Fereastra(String titlu) {
super(titlu)'
t:is.add]indo&Cistener(ne& ]indo&Adapter() {
public void &indo&Closing(]indo&Mvent e) {
S#stem.e/it(<)'
)
))'
)
public void initiali5are() {
Lanel rgbQalues 2 ne& Lanel()'
rgbQalues.setCa#out(ne& 9ridCa#out("4 ;))'
rQalue 2 ne& Scrollbar(Scrollbar.%=P0X=U@AC4 <4 ;4 <4 2(*)'
rQalue.set3acNground(Color.red)'
gQalue 2 ne& Scrollbar(Scrollbar.%=P0X=U@AC4 <4 ;4 <4 2(*)'
gQalue.set3acNground(Color.green)'
bQalue 2 ne& Scrollbar(Scrollbar.%=P0X=U@AC4 <4 ;4 <4 2(*)'
bQalue.set3acNground(Color.blue)'
aQalue 2 ne& Scrollbar(Scrollbar.%=P0X=U@AC4 <4 ;4 <4 2(*)'
aQalue.setQalue(2(()'
aQalue.set3acNground(Color.lig:t9ra#)'
rgbQalues.add(rQalue)'
rgbQalues.add(gQalue)'
rgbQalues.add(bQalue)'
rgbQalues.add(aQalue)'
rgbQalues.setSi5e(2<<4 ;<<)'
add(rgbQalues4 3orderCa#out.CMU@MP)'
culoare 2 ne& Culoare()'
add(culoare4 3orderCa#out.U=P@%)'
pacN()'
rQalue.addAd+ustmentCistener(t:is)'
gQalue.addAd+ustmentCistener(t:is)'
bQalue.addAd+ustmentCistener(t:is)'
aQalue.addAd+ustmentCistener(t:is)'
)
public void ad+ustmentQalueC:anged(Ad+ustmentMvent e) {
int r 2 rQalue.getQalue()'
int g 2 gQalue.getQalue()'
int b 2 bQalue.getQalue()'
int a 2 aQalue.getQalue()'
Color c 2 ne& Color(r4 g4 b4 a)'
culoare.color 2 c'
culoare.repaint()'
1=9
)
)
--clasa principala
public class @estColor{
public static void main(String args!) {
Fereastra 6 2 ne& Fereastra($Color$)'
6.initiali5are()'
6.s:o&()'
)
)
Folosirea imaginilor
;ceasta este o ima!ine)
In Java ;/T este posibila folosirea ima!inilor create extern "n format gif sau %peg' Orice ima!ine este o
instanta a clasei Image' ;ceasta nu este o clasa de componente 3nu extinde clasa Component4 ci
implementea$a obiecte care pot fi desenate pe suprafata unor componente cu metode specifice unui
context !rafic pentru componenta respectiva 3similar modului cum se desenea$a o linie sau un cerc4'
Incarcarea unei imagini dintr1un $isier
Crearea unui obiect de tip 0mage se face folosind o ima!ine dintr+un fisier fie aflat pe masina pe care se
lucrea$a# fie aflat la o anumita adresa 3->L4 pe Internet' %etodele pentru "ncarcarea unei ima!ini dintr+
un fisier se !asesc "n clasele Applet si @oolNit# av.nd "nsa aceeasi denumire getImage si urmatoarele
formate)
0pplet ToolAit
public 0mage get0mage([PC url)
public 0mage get0mage([PC url4 String 6isier)
public 0mage get0mage([PC url)
public 0mage get0mage(String 6isier)
Eentru a obtine un obiect de tip @oolNit se va folosi metoda getSe6ault@oolNit# ca "n exemplul de mai
jos)
@oolNit toolNit 2 @oolNit.getSe6ault@oolNit()'
0mage image; 2 toolNit.get0mage($imageFile.gi6$)'
0mage image2 2 toolNit.get0mage(
ne& [PC($:ttp,--+ava.sun.com-grap:ics-people.gi6$))'
%etoda get0mage nu verifica daca fisierul sau adresa specificata repre$inta o ima!ine valida si nici nu
"ncarca efectiv ima!inea "n memorie# aceste operatiuni fiind facute abia "n momentul "n care se va reali$a
afisarea ima!inii pentru prima data' %etoda nu face dec.t sa cree$e un obiect de tip 0mage care face
referinta la o anumita ima!ine externa'
1=:
(intre metodele clasei 0mage cele mai des folosite sunt cele pentru determinarea dimensiunilor unei
ima!ini)
int get%eig:t(0mage=bserver observer)
int get]idt:(0mage=bserver observer)
unde parametrul observer este u$ual t:is' 3despre interfata 0mage=bserver se va discuta ulterior4
0$isarea imaginilor
;fisarea unei ima!ini "ntr+un context !rafic se reali$ea$a prin intermediul metodei draFImage din clasa
9rap:ics si# "n !eneral# se reali$ea$a "n metoda paint a unui obiect de tip Canvas' Cele mai u$uale
formate ale metodei sunt)
boolean dra&0mage(0mage img4 int /4 int #4 0mage=bserver observer)
boolean dra&0mage(0mage img4 int /4 int #4 Color bgcolor4
0mage=bserver observer)
boolean dra&0mage(0mage img4 int /4 int #4 int &idt:4 int :eig:t4
0mage=bserver observer)
boolean dra&0mage(0mage img4 int /4 int #4 int &idt:4 int :eig:t4
Color bgcolor4 0mage=bserver observer)
unde)
img este obiectul ce repre$inta ima!inea
/ si # sunt coordonatele st.n!a+sus la care va fi afisata ima!inea# relative la spatiul de
coordonate al contextului !rafic
observer este un obiect care *observa* "ncaracarea ima!inii si va fi informat pe masura derularii
acesteia6 de obicei se specifica t:is'
&idt:4 :eigt: repre$inta "naltimea si latimea la care trebuie scalata ima!inea
bgColor repre$inta culoarea cu care vor fi colorati pixelii transparenti ai ima!inii
In exemplul urmator afisam aceeasi ima!ine de trei ori
0mage img 2 @oolNit.getSe6ault@oolNit().get0mage($ta5.gi6$)'
g.dra&0mage(img4 <4 <4 t:is)'
g.dra&0mage(img4 <4 2<<4 ;<<4 ;<<4 t:is)'
g.dra&0mage(img4 2<<4 <4 2<<4 "<<4 Color.#ello&4 t:is)'
%etoda dra&0mage returnea$a true daca ima!inea a fost afisata "n "ntre!ime si 6alse "n ca$ contrar# cu
alte cuvinte metoda nu astepta ca o ima!ine sa fie complet afisata ci se termina imediat ce procesul de
afisare a "nceput' Sa detaliem putin acest aspect'
In ca$ul "n care se afisea$a o ima!ine care se !aseste pe Internet sau ima!inea afisata este de dimensiuni
mari se va observa ca aceasta nu apare complet de la "nceput ci este desenata treptat fara interventia
pro!ramatorului' ;cest lucru se "nt.mpla deoarece metoda dra&0mage nu face dec.t sa declanse$e
procesul de "ncarcareJafisare a ima!inii# dupa care reda imediat controlul apelantului# lucru deosebit de
util "ntruc.t procesul de "ncarcare a unei ima!ini poate dura mult si nu este de dorit ca "n acest interval de
timp 3p.na la "ncarcarea completa a ima!inii4 aplicatia sa fie blocata'
Ca urmare# la apelul metodei dra&0mage va fi desenata numai portiunea de ima!ine care este disponibila
la un moment dat si care poate fi incompleta' (e aceea trebuie sa existe un mecanism prin care
componenta sa fie redesenata "n momentul "n care au mai sosit informatii le!ate de ima!ine'
;cest mecanism este reali$at prin intermediul interfetei ImageObserver# implementata de clasa
Component si deci de toate componentele' ;ceasta interfata specifica obiecte care au "nceput sa utili$e$e
o ima!ine incompleta si care trebuie anuntate de noile date obtinute "n le!atura cu ima!inea respectiva'
Monitori(area .ncarcarii imaginilor 1 inter$ata ImageObserver
Interfata are o sin!ura metoda image:pdate apelata periodic de firul de executie 3creat automat4 care se
ocupa cu "ncarcarea ima!inii' ormatul acestei metode este)
boolean image[pdate (0mage img4 int 6lags4 int /4 int #4 int &4 int : )
Implementarea implicita consta "ntr+un apel la metoda repaint pentru dreptun!hiul specificat la apel si
care repre$inta $ona din ima!ine pentru care se cunosc noi informatii' Intre!ul 6lags furni$ea$a
1=<
informatii despre starea transferului' ;ceste informatii pot fi aflate prin intermediul constantelor definite
de interfata' ;cestea sunt )
A3=P@
Incarcarea ima!inii a fost "ntrerupta# "nainte de completarea ei'
ACC30@S
Ima!inea a fost "ncarcata complet
MPP=P
; aparut o eroare "n timpul "ncarcarii ima!inii
FPA?M30@S
Totii bitii cadrului curent sunt disponibili
%M09%@
Inaltimea ima!inii este disponibila
LP=LMP@0MS
Eroprietatile ima!inii sunt disponibile
S=?M30@S
;u fost receptionati noi pixeli ai ima!inii
]0S@%
Latimea ima!inii este disponibila
Ere$enta "n 6lags a unui bit de valoare 1 pe po$itia repre$entata de o constanta "nseamna ca respectiva
conditie este "ndeplinita'
--M/emple
(6lags F ACC30@S) >2 <
imaginea este completa
(6lags F MPP=P G A3=P@ ) >2 <
a aparut o erorare sau trans6erul imaginii a 6ost Ontrerupt
%etoda image[pdate poate fi redefinta pentru a personali$a afisarea ima!inii' Eentru aceasta
implementam clasei de tip Canvas# folosita pentru afisarea ima!inii# metoda image[pdate# care va fi
apelata asincron de fiecare data c.nd sunt disponibili noi pixeli'
public boolean image[pdate(0mage img4 int 6lags4 int /4 int #4 int &4 int :) {
--se desenea5a imaginea numai daca toti bitii sunt disponibili
i6 (( 6lags F ACC30@S) >2 <) { repaint()' )
--daca am toti bitii nu mai sunt necesare noi update-uri
return ( (6lags F (ACC30@S G A3=P@)) 22 <)'
)
Crearea imaginilor .n memorie 1 clasa MemorEImage'ource
In ca$ul "n care dorim sa folosim o anumita ima!ine creata direct din pro!ram si nu "ncarcata dintr+un
fisier vom folosi clasa MemorEImage'ource# aflata in pachetul +ava.a&t.image' Eentru aceasta va
trebui sa definim un vector de numere "ntre!i "n care vom scrie valorile "ntre!i 3>IH4 ale culorilor
pixelilor ce definesc ima!inea noastra' (imensiunea vectorului va fi "naltimea "nmultita cu latimea "n
pixeli a ima!inii' Constructorul clasei %emor&Ima!eSource este)
?emor#0mageSource(int &4 int :4 intst pi/eli4 int o664 int scan)
unde)
&4 : repre$inta dimensiunile ima!inii 3latimea si "naltimea4
pi/eli! este vectorul cu culorile ima!inii
o664 scan repre$inta modalitatea de construire a matricii ima!inii pornind de la vectorul cu
pixeli# normal aceste valori sunt off U 8# scan U 0
In exemplul urmator vom crea o ima!ine cu pixeli de culori aleatorii si o vom afisa pe ecran)
int & 2 ;<<'
int : 2 ;<<'
intst pi/ 2 ne& ints& . :t'
int inde/ 2 <'
6or (int # 2 <' # A :' #DD) {
6or (int / 2 <' / A &' /DD) {
int red 2 (int) (?at:.random() . 2(()'
int green 2 (int) (?at:.random() . 2(()'
int blue 2 (int) (?at:.random() . 2(()'
pi/sinde/DDt 2 ne& Color(red4 green4 blue).getP93()'
)
)
img 2 create0mage(ne& ?emor#0mageSource(&4 :4 pi/4 <4 &))'
1D8
g.dra&0mage(img4 <4 <4 t:is)'
--g este un conte/t gra6ic
Tiparirea
Tiparirea in Java este tratata in aceeasi maniera ca si desenarea# sin!urul lucru diferit fiind contextul
!rafic in care se executa operatiile' Eachetul care ofera suport pentru tiparire este 4ava3aFt3print# iar clasa
principala care controlea$a tiparirea este PrinterJob' O aplicatie va apela metode ale acestei clase pentru)
crearea unei sesiuni de tiparire 3job4
invocarea dialo!ului cu utili$atorul pentru specificarea unor parametri le!ati de tiparire
tiparirea efectiva
Orice componenta care poate fi afisata pe ecran poate fi si tiparita' In !eneral# orice informatii care trebuie
at.t afisate c.t si tiparite# vor fi incapsulate "ntr+un obiect !rafic + componenta# care are o repre$entare
vi$uala descrisa de metoda paint si care va specifica si modalitatea de repre$entare a sa la imprimanta'
-n obiect care va fi tiparit trebuie sa implemente$e interfata Printable care contine o sin!ura metoda
print responsabila cu descrierea modalitatii de tiparire a obiectului' In ca$ul c.nd ima!inea de pe ecran
coincide cu ima!inea de la imprimanta# codurile metodelor paint si print pot fi identice' In !eneral#
metoda print are urmatorul format)
public int print(9rap:ics g4 LageFormat p64 int page0nde/)
t:ro&s LrinterM/ception {
--descrirea imaginii obiectului ce va 6i a6isata la imprimanta
--poate 6i un apel la metoda paint, paint(g)
i6 (ceva nu este in regula) {
return Lrintable.U=JS[C%JLA9M'
)
return Lrintable.LA9MJMT0S@S'
)
)
Easii care trebuie efectuati pentru tiparirea unui obiect sunt)
1' Crearea unei sesiuni de tiparire
LrinterJob.getLrinterJob
7' Specificarea obiectului care va fi tiparit6 acesta trebuie sa
implemente$e interfata Lrintable
setLrintable
=' Optional# initierea unui dialo! cu utili$atorul pentru
preci$area unor parametri le!ati de tiparire
printSialog
D' Tiparirea efectiva
print
In exemplul urmator vom defini un obiect care are aceeasi repre$entare pe ecran c.t si la imprimanta 3un
cerc circumscris unui patrat# "nsotit de un text4 si vom tipari obiectul respectiv'
import +ava.io..'
import +ava.a&t..'
import +ava.a&t.event..'
import +ava.a&t.print..'
class Llansa e/tends Canvas implements 6rinta&le {
Simension d 2 ne& Simension("<<4 "<<)'
public Simension getLre6erredSi5e() {
return d'
1D1
)
public void paint(9rap:ics g) {
g.dra&Pect(2<<4 2<<4 ;<<4 ;<<)'
g.dra&=val(2<<4 2<<4 ;<<4 ;<<)'
g.dra&String($%ello$4 2<<4 2<<)'
)
public int print(9rap:ics g4 LageFormat p64 int pi)
t:ro&s LrinterM/ception {
i6 (pi >2 ;) {
return Lrintable.U=JS[C%JLA9M'
)
paint(g)'
g.dra&String($Uumai la imprimanta$4 2<<4 3<<)'
return Lrintable.LA9MJMT0S@S'
)
)
class Fereastra e/tends Frame implements ActionCistener {
private Llansa plansa 2 ne& Llansa()'
private 3utton print 2 ne& 3utton($Lrint$)'
public Fereastra(String titlu) {
super(titlu)'
add]indo&Cistener(ne& ]indo&Adapter() {
public void &indo&Closing(]indo&Mvent e) {
S#stem.e/it(<)'
)
))'
add(plansa4 3orderCa#out.CMU@MP)'
Lanel sout: 2 ne& Lanel()'
sout:.setCa#out(ne& Flo&Ca#out(Flo&Ca#out.CMU@MP))'
sout:.add(print)'
add(sout:4 3orderCa#out.S=[@%)'
print.addActionCistener(t:is)'
pacN()'
)
public void actionLer6ormed(ActionMvent e) {
--;.crearea unei sesiuni de tiparire
6rinterAo& printAo& = 6rinterAo&.get6rinterAo&'(;
--2.stabilirea obiectului ce va 6i tiparit
printAo&.set6rinta&le'plansa(;
--3.initierea dialogului cu utili5atorul
i6 (printAo&.print8ialog'() {
tr# {
--".tiparirea e6ectiva
printAo&.print'(;
) catc: (LrinterM/ception e) {
S#stem.out.println($M/ceptie la tiparire>$)'
e.printStacN@race()'
)
)
)
)
public class @estLrint {
1D7
public static void main(String args!) t:ro&s M/ception {
Fereastra 6 2 ne& Fer($@est Lrint$)'
6.s:o&()'
)
)
Tiparirea textelor
O alta varianta pentru tiparirea de texte este deschiderea unui flux catre dispo$itivul special repre$entat de
imprimanta si scrierea informatiilor# linie cu linie# pe acest flux' In /indo0s# imprimanta poate fi referita
prin >lpt1># iar "n -nix prin >!dev!lp>' Observati ca aceasta abordare nu este portabila# deoarece necesita
tratare speciala "n functie de sistemul de operare folosit'
import +ava.io..'
import +ava.a&t..'
class @estLrint {
public static void main(String args!) t:ro&s M/ception {
--pentru ]indo&s
Lrint]riter imp 2 ne& Lrint]riter(ne& File]riter($lpt;$))'
--pentru [U0T
--Lrint]riter imp 2 ne& Lrint]riter(ne& File]riter($-dev-lp$))'
imp.println($@est imprimanta$)'
imp.println($A3CSM$)'
imp.close()'
)
)
Curs ,
Fire de executie
Ce este un fir de executie ?
Crearea unui fir de executie
o Axtinderea clasei Thread
o Implementarea interfetei >unnable
Ciclul de viata al unui fir de executie
Stabilirea prioritatilor de executie
Sincroni$area mai multor fire de executie
o Scenariul producator J consumator
o Hlocarea unui obiect 3cuv.ntul cheie s&nchroni$ed4
o %etodele 0ait# notif& si notif&;ll
Iruparea firelor de executie
Comunicarea prin fluxuri de tip *pipe*
Top
1D=
Ce este un $ir de executie 5
irele de executie fac trecerea de la pro!ramarea secventiala la pro!ramarea concurenta' -n pro!ram
secvential repre$inta modelul clasic de pro!ram ) are un "nceput# o
secventa de executie a instructiunilor sale si un sf.rsit' Cu alte
cuvinte# la un moment dat pro!ramul are un sin!ur punct de
executie' -n pro!ram aflat "n executie se numeste proces' -n
sistem de operare monotasFin! 3%S+(OS4 nu este capabil sa
execute dec.t un sin!ur proces la un moment dat "n timp ce un
sistem de operare multitasFin! 3-1I2# /indo0s4 poate rula
oric.te procese "n acelasi timp 3concurent4# aloc.nd periodic cuante
din timpul de lucru al CE- fiecarui proces' ;m reamintit acest lucru deoarece notiunea de fir de executie
nu are sens dec.t "n cadrul unui sistem de operare multitasFin!'
-n fir de executie este similar unui proces secvential "n sensul ca are un "nceput# o secventa de executie si
un sf.rsit' (iferenta "ntre un fir de executie si un proces consta "n faptul ca un fir de executie nu poate
rula independent ci trebuie sa rule$e "n cadrul unui proces'
+e$initie
-n fir e executie este o succesiune sceventiala de instructiuni care se executa "n cadrul unui
proces'
-n pro!ram "si poate defini "nsa nu doar un fir de executie ci oric.te# ceea ce "nseamna ca "n cadrul unui
proces se pot executa simultan mai multe fire de executie# permit.nd executia concurenta a sarcinilor
independente ale acelui pro!ram'
-n fir de executie poate fi asemanat cu o versiune redusa a unui proces# ambele rul.nd simultan si
independent pe o structura secventiala de executie a instructiunilor lor' (e asemenea executia simultana a
firelor de executie "n cadrul unui proces este similara cu executia concurenta a proceselor) sistemul de
operare va aloca ciclic cuante din timpul procesorului fiecarui fir de executie p.na la terminarea lor' (in
acest motiv firele de executie mai sunt numite si procese usoare'
Care ar fi "nsa deosebirile "ntre un fir de executie si un proces ? In primul r.nd deosebirea majora consta
"n faptul ca firele de executie nu pot rula dec.t "n cadrul unui proces' O alta deosebire re$ulta din faptul ca
fiecare proces are propria sa memorie 3propriul sau spatiu de adrese4 iar la crearea unui nou proces 3forF4
este reali$ata o copie exacta a procesului parinte ) cod 5 date6 la crearea unui fir de executie nu este copiat
dec.t codul procesului parinte6 toate firele de executie au deci acces la aceleasi date# datele procesului
ori!inal' ;sadar un fir de executie mai poate fi privit si ca un context e executie "n cadrul unui proces
parinte'
irele de executie sunt utile "n multe privinte# "nsa u$ual ele sunt folosite pentru executarea unor operatii
consumatoare de timp fara a bloca procesul principal ) calcule matematice# asteptarea eliberarii unei
resurse# acestea reali$.ndu+se de obicei "n fundal'
Crearea unui $ir de executie
1DD
Ca orice alt obiect Java# un fir de executie este o instanta a unei clase' irele de executie definite de o
clasa vor avea acelasi cod si# prin urmare# aceeasi secventa de instructiuni' Crearea unei clase care sa
defineasca fire de excutie poate fi facuta prin doua modalitati)
13 prin extinderea clasei T%read
23 prin implementarea inter$etei 8unnable
Orice clasa ale carei instante vor fi executate "ntr+un fir de executie trebuie declarata ca fiind 2unna&le'
;ceasta este o interfata care contine o sin!ura metoda# si anume metoda run' ;sadar# orice clasa ce
descrie fire de executie va contine o metoda run "n care este implementat codul ce va fi executat de firul
de executie' Interfata Punnable este conceputa ca fiind un protocol comun pentru obiectele care doresc sa
execute un cod pe durata existentei lor 3care repre$inta fire de executie4'
Cea mai importanta clasa care implementea$a interfata Punnable este clasa Thread' Clasa @:read
implementea$a un fir de executie !eneric care# implicit# nu face nimic' Cu alte cuvinte metoda run nu
contine nici un cod'
Orice fir de executie este o instanta a clasei @:read sau a unei subclase a sa'
Extinderea clasei T%read
Cea mai simpla metoda de a crea un fir de executie care sa reali$e$e ceva este prin extinderea clasei
@:read si supradefinirea metodei run a acesteia' ormatul !eneral al unei astfel de clase este)
public class Simple@:read e/tends Thread {
public Simple@:read(String nume) {
super(nume)'
--apele5 constructorul superclasei @:read
)
public void run() {
--codul e/ecutat de 6irul de e/ecutie
)
)
Erima metoda a clasei este constructorul# care primeste ca ar!ument un sir ce va repre$enta numele firului
de executie creat "n momentul c.nd constructorul este apelat'
Simple@:read t 2 ne& Simple@:read($Java$)
--creea5a un 6ir de e/ecutie cu numele Java
In ca$ul "n care nu vrem sa dam nume firelor de executie pe care le cream atunci putem renunta la
definirea acestui constructor si sa ram.nem doar cu constructorul implicit# fara ar!umente# care creea$a
un fir de executie fara nici un nume' -lterior acesta poate primi un nume cu metoda setUame(String)'
Avident# se pot defini si alti constructori# acestia fiinde utili c.nd vrem sa trimitem diversi parametri
firului de executie'
; doua metoda este metoda run# *inima* oricarui fir de executie "n care scriem efectiv codul pe care
trebuie sa+l execute firul de executie'
-n fir de executie creat nu este automat pornit# lansarea sa "n executie se reali$ea$a prin metoda start#
definita de asemenea "n clasa @:read'
Simple@:read t 2 ne& Simple@:read($Java$)
t.start()
--creea5a si lansea5a un 6ir de e/ecutie
Sa consideram "n continuare un exemplu "n care definim un fir de executie ce afisea$a numerele "ntre!i
dintr+un interval cu un anumit pas' irul de executie este implementat de clasa Counter'
class Counter e/tends @:read { --clasa care de6ineste 6irul de e/ecutie
private int 6rom4 to4 step'
public Counter(int 6rom4 int to4 int step) {
t:is.6rom 2 6rom'
t:is.to 2 to'
t:is.step 2 step'
1D?
)
public void run() {
6or(int i 2 6rom' i A2 to' i D2 step)
S#stem.out.print(i D $ $ )'
)
)
public class @estCounter { --clasa principala
public static void main(String args!) {
Counter cnt;4 cnt2'
cnt; 2 ne& Counter(<4 ;<4 2)'
--numara de la < la ;<< cu pasul (
cnt2 2 ne& Counter(;<<4 2<<4 ;<)'
--numara de la ;<< la 2<< cu pasul ;<
cnt;.start()'
cnt2.start()'
--pornim 6irele de e/ecutie
--ele vor 6i distruse automat la terminarea lor
)
)
I.ndind secvential# s+ar crede ca acest pro!ram va afisa prima data numerele de la 8 la 188 cu pasul ?#
apoi numerele de la 188 la 788 cu pasul 18# "ntruc.t primul apel este catre contorul cnt;# deci re$ultatul
afisat pe ecran ar trbui sa fie) < ( ;< ;( 2< 2( 3< 3( "< "( (< (( *< *( 1< 1( 7< 7( 8< 8( ;<<
;<< ;;< ;2< ;3< ;"< ;(< ;*< ;1< ;7< ;8< 2<< '
In realitate "nsa# re$ultatul obtinut va fi o intercalare de valori produse de cele doua fire de executie ce
rulea$a simultan' La rulari diferite se pot obtine re$ultate diferite deoarece timpul alocat fiecarui fir de
executie poate sa nu fie acelasi# el fiind controlat de procesor "ntr+o maniera *aparent* aleatoare) < ;<< (
;;< ;< ;2< ;( ;3< 2< ;"< 2( !BC !DC !EC !FC !GC "CC 3< 3( "< "( (< (( *< *( 1< 1( 7<
7( 8< 8( ;<<
Implementarea inter$etei 8unnable
Ce facem "nsa c.nd dorim sa cream o clasa care instantia$a fire de executie dar aceasta are deja o
superclasa# stiind ca "n Java nu este permisa mostenirea multipla ?
class FirM/ecutie e/tends Larinte4 @:read -- ilegal >
In acest ca$ nu mai putem extinde clasa @:read ci trebuie sa implementam direct "n clasa noastra interfata
2unna&le' Clasa @:read implementea$a ea "nsasi interfata Punnable si# din acest motiv# la extinderea ei
obtineam o implementare implicita a interfetei' ;sadar# interfata Punnable permite unei clase sa fie
active# fara a extinde clasa @:read'
Interfata >unnable se !aseste "n pachetul +ava.lang si este definita astfel)
public inter6ace Punnable {
pulic abstract void run( )'
)
Erin urmare# o clasa care instantia$a fire de executie prin implementarea interfetei Punnable trebuie
obli!atoriu sa implemente$e metoda run'
ormatul !eneral al unei clase care implementea$a interfata Punnable este)
public class Simple@:read implements 2unna&le {
private @:read simple@:read 2 null'
public Simple@:read() {
i6 (simple@:read 22 null) {
simple@:read 2 ne& @:read(t:is)'
simple@:read.start()'
)
1D@
public void run() {
--codul e/ecutat de 6irul de e/ecutie
)
)
Spre deosebire de modalitatea anterioara# se pierde "nsa tot suportul oferit de clasa @:read pentu crearea
unui fir de executie' Simpla instantiere a unei clase care implemenea$a interfata Punnable nu creea$a nici
un fir de executie' (in acest motiv crearea firelor de executie prin instantierea unei astfel de clase trebuie
facuta explicit' Cum se reali$ea$a acest lucru ?
In primul r.nd trebuie declarat un obiect de tip @:read ca variabila membra a clasei respective' ;cest
obiect va repre$enta firul de executie propriu $is al carui cod se !aseste "n clasa noastra'
private @:read simple@:read 2 null'
-rmatorul pas este instantierea si initiali$area firului de executie' ;cest lucru se reali$ea$a ca pentru orice
alt obiect prin instructiunea ne&# urmata de un apel la un constructor al clasei @:read# "nsa nu la oricare
dintre acestia' Trebuie apelat constructorul care sa primeasca drept ar!ument o instanta a clasei noastre'
(upa creare# firul de executie poate fi lansat printr+un apel la metoda start'3;ceste operatiuni sunt scrise
de obicei "n constructorul clasei noastre pentru a fi executate la initiali$area unei instante# dar pot fi scrise
oriunde "n corpul clasei sau chiar "n afara ei4
simple@:read 2 ne& @:read( t:is )'
simple@:read.start()'
Specificarea ar!umentului t:is "n constructorul clasei @:read determina crearea unui fir de executie care
la lansarea sa va cauta "n clasa noastra metoda run si o va executa' ;cest constructor accepta ca ar!ument
orice instanta a unei clase *>unnable*' ;sadar metoda run nu trebuie apelata explicit# acest lucru
reali$.ndu+se automat la apelul metodei start'
;pelul explicit al metodei run nu va furni$a nici o eroare# "nsa aceasta va fi executata ca orice alta
metoda# deci nu "ntr+un fir de executie' Sa rescriem acum exemplul anterior 3afisarea numerele "ntre!i
dintr+un interval cu un anumit pas4# folosind interfata Punnable' Vom vedea ca implementarea interfetei
Punnable permite o flexibilitate sporita "n lucrul cu fire de executie'
9arianta 1 standard"
Crearea firului de executie se reali$ea$a "n constructorul clasei Counter
class Counter implements Punnable {
private @:read counter@:read 2 null'
private int 6rom4 to4 step'
public Counter(int 6rom4 int to4 int step) {
t:is.6rom 2 6rom'
t:is.to 2 to'
t:is.step 2 step'
i6 (counter@:read 22 null) {
counter@:read 2 ne& @:read(t:is)'
counter@:read.start()'
)
)
public void run() {
6or(int i 2 6rom' i A2 to' i D2 step)
S#stem.out.print(i D $ $ )'
)
)
public class @est@:read2 {
public static void main(String args!) {
Counter cnt;4 cnt2'
--lanse5 primul 6ir de e/ecutie (prin constructor)
cnt; 2 ne& Counter(<4 ;<<4 ()'
--lanse5 al doilea 6ir de e/ecutie (prin constructor)
cnt2 2 ne& Counter(;<<4 2<<4 ;<)'
)
)
1D9
9arianta 2
Crearea firului de executie se reali$ea$a "n afara clasei Counter)
class Counter implements Punnable {
private int 6rom4 to4 step'
public Counter(int 6rom4 int to4 int step) {
t:is.6rom 2 6rom'
t:is.to 2 to'
t:is.step 2 step'
)
public void run() {
6or(int i 2 6rom' i A2 to' i D2 step)
S#stem.out.print(i D $ $ )'
)
)
public class @est@:read2 {
public static void main(String args!) {
Counter cnt;4 cnt2'
cnt; 2 ne& Counter(<4 ;<<4 ()'
cnt2 2 ne& Counter(;<<4 2<<4 ;<)'
ne& @:read( cnt; ).start()'
--lanse5 primul 6ir de e/ecutie
ne& @:read( cnt2 ).start()'
--lanse5 al doilea 6ir de e/ecutie
)
)
Ciclul de viata al unui $ir de executie
iecare fir de executie are propriul sau ciclu de viata ) este creat# devine activ prin lansarea sa "n executie
si# la un moment dat# se termina' In continuare vom vedea mai "ndeaproape starile "n care se poate !asi un
fir de executie' (ia!rama de mai jos ilustrea$a !eneric aceste stari precum si metodele care provoaca
tran$itia dintr+o stare "n alta)
;sadar# un fir de executie se poate !asi "n una din urmatoarele patru stari)
13 ;eF T%read
23 8unnable
33 ;ot 8unnable
#3 +ead
'tarea >;eF T%read>
-n fir de executie se !aseste "n aceasta stare imediat dupa crearea sa# cu alte cuvinte dupa instantierea
unui obiect din clasa @:read sau dintr+o subclasa a sa'
@:read counter@:read 2 ne& @:read ( t:is )'
1D:
--counter@:read se gaseste in starea Ue& @:read
In aceasta stare firul de executie este *vid*# el nu are alocate nici un fel de resurse sistem si sin!ura
operatiune pe care o putem executa asupra lui este lansarea "n executie# prin metoda start' ;pelul
oricarei alte metode "n afara de start nu are nici un sens si va provoca o exceptie de tipul
0llegal@:readStateM/ception'
'tarea >8unnable>
(upa apelul metodei start un fir de executie va trece "n starea *>unnable*# adica se !aseste "n executie'
counter@:read.start()'
--counter@:read se gaseste in starea Punnable
%etoda start reali$ea urmatoarele operatiuni necesare rularii firului de executie)
aloca resursele sistem necesare
planifica firul de executie la CE- pentru a fi lansat
apelea$a metoda run a obiectului repre$entat de firul de executie
-n fir de executie aflat "n starea >unnable nu "nseamna neaparat ca acesta se !aseste efectiv "n executie#
adica instructiunile sale sunt interpretate de procesor' ;cest lucru se "nt.mpla din cau$a ca majoritatea
calculatoarelor au un sin!ur procesor iar acesta nu poate rula simultan toate firele de executie care se
!asesc "n starea >unnable' Eentru a re$olva aceasta problema interpretorul Java implementea$a o
planificare care sa partaje$e dinamic si corect procesorul "ntre toate firele de executie care sunt "n starea
>unnable' ;sadar# un fir de executie care *rulea$a* poate sa+si astepte de fapt r.ndul la procesor'
'tarea >;ot 8unnable>
-n fir de executie ajun!e "n acesata stare "n una din urmatoarele situatii)
este *adormit* prin apelul metodei sleep'
a apelat metoda wait# asteapt.nd ca o anumita conditie sa fie satisfacuta
este blocat "ntr+o operatie de intrareJiesire
>0dormirea> unui $ir de executie
%etoda sleep este o metoda statica a clasei @:read care provoaca o pau$a "n timpul rularii firului curent
aflat "n executie# cu alte cuvinte "l *adoarme* pentru un timp specificat' Lun!imea acestei pau$e este
specificata "n milisecunde si chiar nanosecunde'
public static void sleep( long millis )
t:ro&s 0nterruptedM/ception
public static void sleep( long millis4 int nanos )
t:ro&s 0nterruptedM/ception
Intruc.t poate provoca exceptii de tipul 0nterruptedM/ception apelul acestei metode se face "ntr+un
bloc de tip tr#-cact:)
tr# {
@:read.sleep(;<<<)'
--6ace pau5a de o secunda
) catc: (0nterruptedM/ception e) {
. . .
)
Observati ca metoda fiind statica apelul ei nu se face pentru o instanta anume a clasei @:read' ;cest lucru
este foarte normal deoarece# la un moment dat# un sin!ur fir este "n executie si doar pentru acesta are sens
*adormirea* sa'
In intervalul "n care un fir de executie *doarme*# acesta nu va fi execut chiar daca procesorul devine
disponibil' (upa expirarea acestui interval firul revine "n starea >unnable# iar daca procesourul este "n
continuare disponibil "si contiunua executia'
Eentru fiecare tip de intrare "n starea *1ot >unnable*# exista o secventa specifica de iesire din starea
repectiva# care readuce firul de executie "n starea >unnable' ;cestea sunt)
(aca un fir de executie a fost *adormit*# atunci el devine >unnable doar dupa scur!erea
intervalului de timp specificat de instructiunea sleep'
1D<
(aca un fir de executie asteapta o anumita conditie# atunci un alt obiect trebuie sa "l informe$e
daca acea conditie este "ndeplinita sau nu6 acest lucru se reali$ea$a prin instructiunile noti6# sau
noti6#All
3ve$i *Sincroni$area firelor de executie*4'
(aca un fir de executie este blocat "ntr+o operatiune de intrareJiesire atunci el redevine >unnable
atunci c.nd acea operatiune s+a terminat'
'tarea >+ead>
Aste starea "n care ajun!e un fir de executie la terminarea sa' -n fir de executie nu poate fi oprit din
pro!ram printr+o anumita metoda# ci trebuie sa se termine "n mod natural la terminarea metodei run pe
care o executa' Spre deosebire de versiunile curente ale limbajului Java# "n versiunea 1'8 exista metoda
stop a clasei @:read care termina fortat un fir de executie# "nsa ea a fost eliminata din motive de
securitate'
;sadar# un fir de executie trebuie sa+si *aranje$e* sin!ur propria sa *moarte*'
Terminarea unui $ir de executie
(upa cum am va$ut# un fir de executie nu poate fi terminat fortat de catre pro!ram ci trebuie sa+si
*aranje$e* sin!ur terminarea sa' ;cest lucru poate fi reali$at "n doua modalitati)
Erin scrierea unor metode run care sa+si termine executia "n mod natural6 la terminarea metodei
run se va termina automat si firul de executie# acesta intr.nd "n starea (ead' ;cesta este ca$ul din
exemplul considerat anterior)
public void run() {
6or(int i 2 6rom' i A2 to' i D2 step)
S#stem.out.print(i D $ $ )'
)
(upa afisarea numerelor din intervalul specificat metoda se termina si odata cu ea si firul de
executie repsectiv'
Erin folosirea unei variabile de terminare' In ca$ul c.nd metoda run trebuie sa execute o bucla
infinita atunci aceasta trebuie controlata si printr+o variabila care sa opreasca aceasta bucla atunci
c.nd dorim ca firul de executie sa se termine' -$ual# aceasta este o variabila membra a clasei care
descrie firul de executie care fie este publica# fie este asociata cu o metoda care "i schimba
valoarea'
Sa consideram exemplul unui fir de executie care trebuie sa numere secundele scurse p.na la apasarea
tastei Anter' Vom scrie mai "nt.i pro!ramul folosind metoda stop)
Terminarea unui $ir de executie $olosind metoda >.nvec%ita> stop
import +ava.io..'
public class @est@:read {
public static void main(String args!) t:ro&s 0=M/ception {
]aitVe# t:read 2 ne& ]aitVe#()'
t:read.start()'
S#stem.in.read()' --astept apasarea tastei Mnter
t:read.stop()' --opresc 6irul de e/ecutie
S#stem.out.println($S-au scurs $ D t:read.sec D $ secunde$)'
)
)
class ]aitVe# e/tends @:read {
public int sec 2 <'
public void run() {
&:ile (true) {
tr# {
1?8
@:read.sleep(;<<<)' --pau5e de o secunda
sec DD' --s-a mai scurs o secunda
) catc:(0nterruptedM/ception e){)
)
)
)
Observam ca metoda run nu se termina natural# ea rulea$a la infinit astept.nd sa fie terminata fortat'
;cest lucru l+am reali$at aici cu metoda stop' ;ceasta metoda este "nsa *"nvechita* 3deprecated4 iar la
compilarea pro!ramului vom obtine un mesaj de averti$are "n acest sens' Eutem evita metoda stop prin
folosirea unei variabile de terminare'
Terminarea unui $ir de executie $olosind o variabila de terminare
import +ava.io..'
public class @est@:read {
public static void main(String args!) t:ro&s 0=M/ception {
]aitVe# t:read 2 ne& ]aitVe#()'
t:read.start()'
S#stem.in.read()' --astept apasarea tastei Mnter
t:read.running 2 6alse'
S#stem.out.println($S-au scurs $ D t:read.sec D $ secunde$)'
)
)
class ]aitVe# e/tends @:read {
public int sec 2 <'
public boolean running 2 true' --variabila de terminare
public void run() {
&:ile ( running ) {
tr# {
@:read.sleep(;<<<)'
sec DD'
) catc:(0nterruptedM/ception e){)
)
)
)
Metoda is0live
;ceasta metoda este folosita pentru a vedea daca un fir de executie a fost pornit si nu s+a terminat "nca'
%etoda returnea$a)
true + daca firul este "n una din starile >unnable sau 1ot >unnable
false + daca firul este "n una din starile 1e0 Thread sau (ead
Intre starile >unnable sau 1ot >unnable# repectiv 1e0 Thread sau (ead nu se poate face nici o
diferentiere'
]aitVe# t:read 2 ne& ]aitVe#()'
-- isAlive retunea5a 6alse (starea este Ue& @:read)
t:read.start()'
-- isAlive retunea5a true (starea este Punnable)
S#stem.in.read()'
t:read.running 2 6alse'
-- isAlive retunea5a 6alse (starea este Sead)
1u este necesara distru!erea explicita a unui fir de executie' Sistemul Java de colectare a !unoiului se
ocupa de acest lucru' Al poate fi fortat sa de$aloce resuresele alocate unui thread prin atribuirea cu null a
variabilei care referea instanta firului de executie) m#@:read 2 null '
1?1
'tabilirea prioritatilor de executie
%ajoritatea calculatoarelor au un si!ur procesor# ceea ce "nseamna ca firele de executie trebuie sa+si
"mparta accesul la acel procesor' Axecutia "ntr+o anumita ordine a mai multor fire de executie pe un sin!ur
procesor se numeste planificare (sc&euling!' Sistemul Java de executie a pro!ramelor implementea$a un
al!oritm simplu# determinist de planificare# cunoscut sub numele de planificare cu prioritati fixate'
iecare fir de executie Java primeste la crearea sa o anumita prioritate' O prioritate este de fapt un numar
"ntre! cu valori cuprinse "ntre %I1VE>IO>ITW si %;2VE>IO>ITW' Implicit prioritatea unui fir de
executie nou creat are valoarea 1O>%VE>IO>ITW' ;ceste trei constante sunt definite "n clasa @:read)
public static 6inal int ?0UJLP0=P0@Z - prioritatea minima
public static 6inal int U=P?JLP0=P0@Z - prioritatea implicita
public static 6inal int ?ATJLP0=P0@Z - prioritatea ma/ima
Schimbarea ulterioara a prioritatii unui fir de executie se reali$ea$a cu metoda setLriorit# a clasei
@:read'
Elanificatorul Java lucrea$a "n modul urmator ) daca la un moment dat sunt mai multe fire de executie "n
starea >unnable# adica sunt pre!atite pentru a fi executate# planificatorul "l va ale!e pe cel cu prioritatea
cea mai mare pentru a+l executa' (oar c.nd firul de executie cu prioritate maxima se termina sau este
suspendat din diverse motive va fi ales un fir de executie cu o prioritate mai mica' In ca$ul "n care toate
firele au aceeasi prioritate ele sunt alese dupa un al!oritm simplu de tip *round+robin*'
(e asemenea# planificarea este complet preemptiva ) daca un fir cu prioritate mai mare dec.t firul care se
executa la un moment dat solicita procesorul# atunci firul cu prioritate mai mare este imediat trecut "n
executie iar celalalt trecut "n asteptare' Elanificatorul Java nu va "ntrerupe "nsa un fir de executie "n
favoarea altuia de aceeasi prioritate# "nsa acest lucru "l poate face sistemul de operare "n ca$ul "n care
acesta aloca procesorul "n cuante de timp 3un astfel de SO este /indo0s <?J1T4'
;sadar# un fir de executie Java cedea$a procesorul "n una din situatiile )
un fir de executie cu o prioritate mai mare solicita procesorul
metoda sa run se termina
vrea sa faca explicit acest lucru apel.nd metoda #ield
timpul alocat pentru executia sa a expirat 3pe SO cu cuante de timp4
In nici un ca$ corectitudinea unui pro!ram nu trebuie sa se ba$e$e pe mecansimul de planificare a firelor
de executie# deoarece acesta poate fi imprevi$ibil si depinde de la un sistem de operare la altul'
-n fir de executie de lun!a durata si care nu cedea$a explicit procesorul la anumite intervale de timp
astfel "nc.t sa poata fi executate si celelalte fire de executie se numeste fir de executie egoist si trebuie
evitata scrierea lor# "ntruc.t acaparea$a pe termen nedefinit procesorul# bloc.nd efectiv executia celorlalte
fire de executie p.na la terminarea sa' -nele sistemele de operare combat acest tip de comportament prin
metoda alocarii procesorului "n cuante de timp fiecarui fir de executie# "nsa nu trebuie sa ne ba$am pe
acest lucru la scrierea unui pro!ram' -n fir de executie trebuie sa fie *corect* fata de celelalte fire si sa
cede$e periodic procesorul astfel "nc.t toate sa aiba posibilitatea de a se executa'
Exemplu de $ir de executie >egoist>
--un 6ir de e/ecutie care numara pana la ;<<.<<< din ;<< On ;<<
class Sel6is: e/tends @:read {
public Sel6is:(String name) {
super(name)'
)
public void run() {
int i 2 <'
&:ile (i A ;<<<<<) {
--bucla stransa care acaparea5a procesorul
i DD'
i6 (i E ;<< 22 <)
S#stem.out.println(getUame()D$ a a+uns la $Di)'
)
)
)
1?7
--clasa principala
public class @estSel6is:@:read {
public static void main(String args!) {
Sel6is: s;4 s2'
s; 2 ne& Sel6is:($Firul ;$)'
s;.setLriorit# (@:read.?ATJLP0=P0@Z)'
s2 2 ne& Sel6is:($Firul 2$)'
s2.setLriorit# (@:read.?ATJLP0=P0@Z)'
s;.start()'
s2.start()'
)
)
irul de executie s1 are prioritate maxima si p.na nu+si va termina executia nu+i va permite firului s7 sa
execute nici o instructiune# acapar.nd efectiv procesorul' >e$ultatul va arata astfel)
Firul ; a a+uns la ;<<
Firul ; a a+uns la 2<<
Firul ; a a+uns la 3<<
. . .
Firul ; a a+uns la 888<<
Firul ; a a+uns la ;<<<<<
Firul 2 a a+uns la ;<<
Firul 2 a a+uns la 2<<
. . .
Firul 2 a a+uns la 888<<
Firul 2 a a+uns la ;<<<<<
>e$olvarea acestei probleme se face fie prin intermediul metodei statice #ield a clasei @:read care
determina firul de executie curent sa se opreasca temporar# d.nd oca$ia si altor fire sa se execute# fie prin
*adormirea* temporara a firului curent cu ajutorul metodei sleep' %etoda run a clasei Sel6is: ar trebui
rescrisa astfel)
public void run() {
int i 2 <'
&:ile (i A ;<<<<<) {
i DD'
i6 (i E ;<< 22 <)
S#stem.out.println(getUame()D$ a a+uns la $Di)'
#ield()' --cede5 temporar procesorul
)
Erin metoda #ield un fir de executie nu cedea$a procesorul dec.t firelor de executie care au aceeasi
prioritate cu a sa si nu celor cu prioritati mai mici'
'incroni(area $irelor de executie
E.na acum am va$ut cum putem crea fire de executie independente si asincrone# cu alte cuvinte care nu
depind "n nici un fel de executia sau de re$ultatele altor fire de executie' Axista "nsa numeroase situatii
c.nd fire de executie separate# dar care rulea$a concurent# trebuie sa comunice "ntre ele pentru a accesa
diferite resurse comune sau pentru a+si transmite dinamic re$ultatele *muncii* lor' Cel mai elocvent
scenariu "n care firele de executie trebuie sa se comunice "ntre ele este cunoscut sub numele de problema
proucatorului3consumatorului# "n care producatorul !enerea$a un flux de date care este preluat si
prelucrat de catre consumator'
Sa consideram de exemplu o aplicatie Java "n care un fir de executie 3producatorul4 scrie date "ntr+un
fisier "n timp ce alt fir de executie 3consumatorul4 citeste date din acelasi fisier pentru a le prelucra' Sau#
sa presupunem ca producatorul !enerea$a niste numere si le plasea$a# pe r.nd# "ntr+un buffer iar
consumatorul citeste numerele din acel buffer pentru a le interpreta' In ambele ca$uri avem de+a face cu
fire de executie concurente care folosesc o resursa comuna ) un fisier# respectiv un vector si# din acest
motiv# ele trebuie sincroni$ate "ntr+o maniera care sa permita decur!erea normala a activitatii lor'
'cenariul producator ! consumator
1?=
Eentru a "ntele!e mai bine modalitatea de sincroni$are a doua fire de executie sa implementam efectiv o
problema de tip producatorJconsumator'
Sa consideram urmatoarea situatie)
Eroducstorul !enerea$a numerele "ntre!i de la 1 la 18# fiecare la un interval nere!ulat cuprins "ntre
8 si 188 de milisecunde' Ee masura ce le !enerea$a "ncearca sa le plase$e "ntr+o $ona de memorie
3o variabila "ntrea!a4 de unde sa fie citite de catre consumator'
Consumatorul va prelua# pe r.nd# numerele !enerate de catre producator si va afisa valoarea lor pe
ecran'
Eentru a fi accesibila ambelor fire de executie# vom "ncapsula variabila ce va contine numerele !enerate
"ntr+un obiect descris de clasa 3u66er si care va avea doua metode put 3pentru punerea unui numar "n
buffer4 si get 3pentru obtinerea numarului din buffer4'
ara a folosi nici un mecanism de sincroni$are clasa Huffer arata astfel)
class 3u66er {
private int number 2 -;'
public int get() {
return number'
)
public void put(int number) {
t:is.number 2 number'
)
)
Vom implementa acum clasele Eroducator si Consumator care vor descrie cele doua fire de executie'
;mbele vor avea o referinta comuna la un obiect de tip Huffer prin intermediul caruia "si comunica
valorile'
class 6roducator e/tends @:read {
private 3u66er bu66er'
public Lroducator(3u66er b) {
bu66er 2 b'
)
public void run() {
6or (int i 2 <' i A ;<' iDD) {
bu66er.put(i)'
S#stem.out.println($Lroducatorul a pus,Bt$ D i)'
tr# {
sleep((int)(?at:.random() . ;<<))'
) catc: (0nterruptedM/ception e) { )
)
)
)
class $onsumator e/tends @:read {
private 3u66er bu66er'
public Consumator(3u66er b) {
bu66er 2 b'
)
public void run() {
int value 2 <'
6or (int i 2 <' i A ;<' iDD) {
value 2 bu66er.get()'
S#stem.out.println($Consumatorul a primit,Bt$ D value)'
)
)
)
--Clasa principala
public class @estSincroni5are; {
public static void main(String! args) {
3u66er b 2 ne& 3u66er()'
Lroducator p; 2 ne& Lroducator(b)'
1?D
Consumator c; 2 ne& Consumator(b)'
p;.start()'
c;.start()'
)
)
(upa cum ne asteptam re$ultatul rularii acestui pro!ram nu va re$olva fi nici pe departe problema
propusa de noi# motivul fiind lipsa oricarei sincroni$ari "ntre cele doua fire de executie' %ai precis#
re$ultatul va fi ceva de forma)
Consumatorul a primit, -;
Consumatorul a primit, -;
Lroducatorul a pus, <
Consumatorul a primit, <
Consumatorul a primit, <
Consumatorul a primit, <
Consumatorul a primit, <
Consumatorul a primit, <
Consumatorul a primit, <
Consumatorul a primit, <
Consumatorul a primit, <
Lroducatorul a pus, ;
Lroducatorul a pus, 2
Lroducatorul a pus, 3
Lroducatorul a pus, "
Lroducatorul a pus, (
Lroducatorul a pus, *
Lroducatorul a pus, 1
Lroducatorul a pus, 7
Lroducatorul a pus, 8
;mbele fire de executie accesea$a resursa comuna# adica obiectul de tip Huffer# "ntr+o maniera haotica si
acest lucru se "nt.mpla din douG motive )
consumatorul nu asteapta "nainte de a citi ca producatorul sa !enere$e un numar si va prelua de
mai multe ori acelasi numar'
producatorul nu asteapta consumatorul sa preia numarul !enerat "nainte de a produce un altul# "n
felul acesta consumatorul va *rata* cu si!uranta unele numere 3"n ca$ul nostru aproape pe toate4'
Eroblema care se ridica "n acest moment este ) cine trebuie sa se ocupe de sincroni$area celor doua fire de
executie ) clasele Eroducator si Consumator sau resursa comuna Huffer ?
>aspunsul este) resursa comuna Huffer# deoarece ea trebuie sa permita sau nu accesul la continutul sau si
nu firele de executie care o folosesc' In felul acesta efortul sincroni$arii este transferat de la
producatorJconsumator la un nivel mai jos# cel al resursei critice'
;ctivitatile producatorului si consumatorului trebuie sincroni$ate la nivelul resursei comune "n doua
privinte)
1' Cele doua fire de executie nu trebuie sa accese$e simultan buffer+ul 6 acest lucru se reali$ea$a prin
blocarea obiectului Huffer atunci c.nd este accesat de un fir de executie# astfel "nc.t nici nu alt fir
de executie sa nu+l mai poate accesa' 3ve$i *Hlocarea unui obiect*4'
7' Cele doua fire de executie trebuie sa se coordone$e# adica producatorul trebuie sa !aseasca o
modalitate de a *spune* consumatorului ca a plasat o valoare "n buffer# iar consumatorul trebuie sa
comunice producatorului ca a preluat aceasta valoare# pentru ca acesta sa poata !enera o alta'
Eentru a reali$a aceasta comunicare# clasa Thread pune la dispo$itie metodele wait* notify*
notifyll' 3ve$i *%etodele 0ait# notif&# notif&;ll*4'
olosind sincroni$area clasa Huffer va arata astfel)
class 3u66er {
private int number 2 -;'
private boolean available 2 6alse'
public synchroni)ed int get() {
&:ile (>available) {
tr# {
wait'('
--asteapta producatorul sa puna o valoare
1??
) catc: (0nterruptedM/ception e) { )
)
available 2 6alse'
notifyll()'
return number'
)
public synchroni)ed void put(int number) {
&:ile (available) {
tr# {
wait'('
--asteapta consumatorul sa preia valoarea
) catc: (0nterruptedM/ception e) { )
)
t:is.number 2 number'
available 2 true'
notifyll()'
)
)
>e$ultatul obtinut va fi cel scontat)
Lroducatorul a pus, <
Consumatorul a primit, <
Lroducatorul a pus, ;
Consumatorul a primit, ;
. . .
Lroducatorul a pus, 8
Consumatorul a primit, 8
@locarea unui obiect cuv<ntul c%eie sEnc%roni(ed"
+e$initie
-n se!ment de cod ce !estionea$a o resursa comuna mai multor de fire de executie separate si
concurente se numeste sectiune critica' In Java o sectiune critica poate fi un bloc de instructiuni
sau o metoda'
Controlul accesului "ntr+o sectiune critica se face prin cuv.ntul cheie synchroni)ed' Elatforma Java
asocia$a un monitor fiecarui obiect al unui pro!ram ce contine sectiuni critice care necesita sincroni$are'
;cest monitor va indica daca resursa critica este accesata de vreun fir de executie sau este libera# cu alte
cuvinte *monitori$ea$a* o resursa critica' In ca$ul "n care este accesata# va *pune un lacat* pe aceasta#
astfel "nc.t sa "mpiedice accesul altor fire de executie la ea' In momentul c.nd resursa este eliberata
*lacatul* va fi eliminat pentru a permite accesul altor fire de executie'
In exemplul tip producatorJconsumator de mai sus# sectiunile critice sunt metodele put si get iar resursa
citica comuna este obiectul bu66er' Consumatorul nu trebuie sa accese$e buffer+ul c.nd producatorul
tocmai pune o valoare "n el# iar producatorul nu trebuie sa modifice valoarea din buffer "n momentul c.nd
aceasta este citita de catre consumator'
public synchroni)ed int get() {
...
)
public synchroni)ed void put(int number) {
...
)
Sa observam ca ambele metode au fost declarate cu modificatorul s&nchroni$ed' Cu toate acestea sistemul
asocia$a un monitor unei instante a clasei Huffer si nu unei metode anume' In momentul "n este apelata o
metoda sincrona firul de executie care a facut apelul va bloca obiectul a carei metoda o accesea$a # ceea
ce "nseamna ca celelalte fire de executie nu vor mai putea accesa resursele critice# adica nu vor putea
apela nici o metoda sincrona din acel obiect' ;cesta este un lucru lo!ic# deoarece mai multe sectiuni
critice 3metode sincrone4 ale unui obiect !estionea$a de fapt o sin!ura resursa critica'
In exemplul nostru# atunci c.nd producatorul apelea$a metoda put pentru a scrie un numar# va bloca tot
1?@
obiectul de tip Huffer# astfel ca firul de executie consumator nu va avea acces la cealalta metoda sincrona
!et# si reciproc'
public s#nc:roni5ed void put(int number) {
-- bu66er blocat de producator
...
-- bu66er deblocat de producator
)
public s#nc:roni5ed int get() {
-- bu66er blocat de consumator
...
-- bu66er deblocat de consumator
)
Metodele FaitH noti$E si noti$E0ll
Obiectul de tip Huffer din exemplul are o variabila membra privata numita number# "n care este memorat
numarul pe care "l comunica producatorul si din care "l preia consumatorul' (e asemenea# mai are o
variabila privata lo!ica available care ne da starea buffer+ului) daca are valoarea true "nseamna ca
producatorul a pus o valoare "n buffer si consumatorul nu a preluat+o "nca6 daca este false# consumatorul a
preluat valoarea din buffer dar producatorul nu a pus deocamdata alta la loc'
(eci# la prima vedere metodele clasei Huffer ar trebui sa arate astfel)
public s#nc:roni5ed int get() {
i6 (available) {
available 2 6alse'
return number'
)
)
public s#nc:roni5ed int put(int number) {
i6 (>available) {
available 2 true'
t:is.number 2 number'
)
)
Implementate ca mai sus cele doua metode nu vor functiona corect ;cest lucru se "nt.mpla deoarece
firele de executie# desi "si sincroni$ea$a accesul la buffer# nu se *asteapta* unul pe celalalt' Situatiile "n
care metodele !et si put nu fac nimic vor duce la *ratarea* unor numere de catre consumator' ;sadar# cele
doua fire de executie trebuie sa se astepte unul pe celalalt'
public s#nc:roni5ed int get() {
&:ile (>available) {
--nimic - astept ca variabila sa devina true
)
available 2 6alse'
return number'
)
public s#nc:roni5ed int put(int number) {
&:ile (available) {
--nimic - astept ca variabila sa devina 6alse
)
available 2 true'
t:is.number 2 number'
)
Varianta de mai sus# desi pare corecta# nu este' ;ceasta deoarece implementarea metodelor este *selfish* +
cele doua metode "si asteapta in mod e!oist conditia de terminare' Ca urmare# corectitudinea functionarii
va depinde de sistemul de operare# ceea ce trpre$inta o !reseala de pro!ramare'
Eunerea corecta a unui fir de executie "n asteptare se reali$ea$a cu metoda wait a clasei @:read# care are
trei forme)
void &ait( )
void &ait( long timeout )
void &ait( long timeout4 long nanos )
1?9
(upa apelul metodei &ait# firul de executie curent eliberea$a monitorul asociat obiectului respectiv si
asteapta ca una din urmatoarele conditii sa fie "ndeplinita)
un alt fir de executie informea$a pe cei care *asteapta* la un anumit monitor sa se tre$easca6 acest
lucru se reali$ea$a printr+un apel al metodei notifyll sau notify'
perioada de astepatare specificata a expirat'
%etoda &ait poate produce exceptii de tipul 0nterruptedM/ception# atunci c.nd firul de executie care
asteapta 3este deci "n starea 1ot >unnable4 este "ntrerupt din asteptare si trecut fortat "n starea >unnable#
desi conditia asteptata nu era "nca "ndeplinita'
%etoda noti6#All informea$a toate firele de executie care sunt "n asteptare la monitorul obiectului
curent "ndeplinirea conditiei pe care o asteptatu' %etoda noti6# informea$a doar un sin!ur fir de
executie'
Iata variantele corecte ale metodelor get si put)
public s#nc:roni5ed int get() {
&:ile (>available) {
tr# {
&ait()'
--asteapta producatorul sa puna o valoare
) catc: (0nterruptedM/ception e) { )
)
available 2 6alse'
noti6#All()'
return number'
)
public s#nc:roni5ed void put(int number) {
&:ile (available) {
tr# {
&ait()'
--asteapta consumatorul sa preia valoarea
) catc: (0nterruptedM/ception e) { )
)
t:is.number 2 number'
available 2 true'
noti6#All()'
)
)
=ruparea $irelor de executie
Iruparea firelor de executie pune la dispo$itie un mecanism pentru manipularea acestora ca un tot si nu
individual' (e exemplu# putem sa pornim sau sa suspendam toate firele dintr+un !rup cu un sin!ur apel de
metoda' Iruparea firelor de executie se reali$ea$a prin intermediul clasei Thread>roup'
iecare fir de executie Java este mebmru al unui !rup# indiferent daca specificam explicit acest lucru'
;filierea unui fir de executie la un anumit !rup se reali$ea$a la crearea sa si devine permanenta# "n sensul
ca nu vom putea muta un fir de executie dintr+un !rup "n altul# dupa ce acesta a fost creat' In ca$ul "n care
cream un fir de executie fara a specifica "n constructor din ce !rup face parte# el va fi plasat automat "n
acelasi !rup cu firul de executie care l+a creat' La pornirea unui pro!ram Java se creea$a automat un
obiect de tip @:read9roup cu numele main# care va repre$enta !rupul tuturor firelor de executie create
direct din pro!ram si care nu au fost atasate explicit altui !rup' Cu alte cuvinte# putem sa i!noram complet
plasarea firelor de executie "n !rupuri si sa lasam sistemul sa se ocupe cu aceasta# adun.ndu+le pe toate "n
!rupul main'
Axista situatii c.nd pro!ramul creea$a multe fire de executie iar !ruparea lor poate usura substantial
1?:
manevrarea lor' Crearea unui fir de executie si plasarea lui "ntr+un !rup 3altul dec.t cel implicit4 se
reali$eaa prin urmatorii constructori ai clasei @:read)
public @:read(@:read9roup group4 Punnable target)
public @:read(@:read9roup group4 String name)
public @:read(@:read9roup group4 Punnable target4 String name)
iecare din acesti costructori creea$a un fir de executie# "l initiali$ea$a si "l plasea$a "ntr+un !rup
specificat ca ar!ument' In exemplul urmator vor fi create doua !rupuri# primul cu doua fire de executie iar
al doile cu trei)
@:read9roup grup; 2 ne& @:read9roup($Lroducatori$)'
@:read p; 2 ne& @:read(grup4 $Lroducator ;$)'
@:read p2 2 ne& @:read(grup4 $Lroducator 2$)'
@:read9roup grup2 2 ne& @:read9roup($Consumatori$)'
@:read c; 2 ne& @:read(grup4 $Consumator ;$)'
@:read c2 2 ne& @:read(grup4 $Consumator 2$)'
@:read c3 2 ne& @:read(grup4 $Consumator 3$)'
Eentru a afla carui !rup apartine un anumit fir de executie putem folosi metoda get@:read9roup a clasei
@:read' -n !rup poate avea ca parinte un alt !rup# ceea ce "nseamna ca firele de executie pot fi plasate
"ntr+o ierarhie de !rupuri# "n care radacina este !rupul implicit main# ca "n fi!ura de mai jos)
Axemplu) listarea firelor de executie active
public class Mnumerate@est {
public void listCurrent@:reads() {
@:read9roup current9roup 2 @:read.current@:read().get@:read9roup()'
--a6lu numarul 6irelor de e/ecutie active
int num@:reads 2 current9roup.activeCount()'
--pun intr-un vector re6erinte la 6irele de e/ec. active
@:read! list=6@:reads 2 ne& @:readnum@:reads!'
current9roup.enumerate(list=6@:reads)'
--le a6ise5 pe ecran
6or (int i 2 <' i A num@:reads' iDD)
S#stem.out.println($@:read _$ D i D $ 2 $ D
list=6@:readsi!.getUame())'
)
)
Comunicarea prin $luxuri de tip >pipe>
1?<
O modalitate deosebit de utila prin care doua fire de executie pot comunica este reali$ata prin intermediul
canalelor e comunicatii (pipes!' ;cestea sunt implementate prin fluxuri descrise de clasele
6iped2eader* 6iped4riter - pentru caractere4 respectiv
6iped%utputStream* 6iped0nputStream - pentru octeti
Constructorii acestor clase sunt )
public LipedPeader( )
public LipedPeader( Liped]riter p& ) t:ro&s 0=M/ception
public Liped]riter( )
public Liped]riter( LipedPeader pr ) t:ro&s 0=M/ception
In ca$ul "n care este folosit constructorul fara ar!ument conectarea unui flux de intrare cu un flux de iesire
se face prin metoda connect)
public void connect( Liped]riter p& ) t:ro&s 0=M/ception
public void connect( LipedPeader pr ) t:ro&s 0=M/ception4
Intruc.t fluxurile care sunt conectate printr+un pipe trebuie sa execute simultan operatii de scriereJcitire
folosirea lor se va face "n cadrul unor fire de executie'
unctionarea obicetelor care instantia$a Liped]riter si LipedPeader este asemanatoare cu a canalelor
-1I2 3pipes4' iecare capat al unui canal este utili$at dintr+un fir de executie separat' La un capat al
pipeline+ului se scriu caractere# la celalalt se citesc' La citire# daca nu sunt date disponibile firul de
executie se va bloca' Se observa ca acesta este un comportament tipic producator+consumator# firele de
executie comunic.nd printr+un canal'
>eali$area conexiunii se face astfel)
Liped]riter p&; 2 ne& Liped]riter()'
LipedPeader pr; 2 ne& LipedPeader(p&;)'
sau
LipedPeader pr2 2 ne& LipedPeader()'
Liped]riter p&2 2 ne& Liped]riter(pr2)'
sau
LipedPeader pr 2 ne& LipedPeader()'
Liped]riter p& 2 ne& Liped]irter()'
pr.connect(p&) --ec:ivalent cu
p&.connect(pr)'
Scrierea si citirea peJde pe canale se reali$ea$a prin metodele u$uale read si &rite "n toate formele lor'
Sa reconsideram acum exemplul producatorJconsumator folosind canale de comunicatie'
Eroducatorul trimite datele printr+un flux de iesire de tip Sata=utputStream catre consumator care le
primeste printr+un flux de intrare de tip Sata0nputStream' ;ceste doua fluxuri sunt interconectate prin
intermediul unor fluxuri de tip *pipe*'
import +ava.io..'
--clasa principala
public class @estLipes {
public static void main(String! args) t:ro&s 0=M/ception {
Liped=utputStream pipe=ut 2 ne& Liped=utputStream()'
Liped0nputStream pipe0n 2 ne& Liped0nputStream(pipe=ut)'
Sata=utputStream out 2 ne& Sata=utputStream( pipe=ut)'
Sata0nputStream in 2 ne& Sata0nputStream( pipe0n )'
Lroducator p; 2 ne& Lroducator(out)'
Consumator c; 2 ne& Consumator(in)'
p;.start()'
c;.start()'
)
)
class Lroducator e/tends @:read {
private Sata=utputStream out'
public Lroducator(Sata=utputStream out) {
1@8
t:is.out 2 out'
)
public void run() {
6or (int i 2 <' i A ;<' iDD) {
tr# { out.&rite0nt(i)' )
catc: (0=M/ception e) {)
S#stem.out.println($Lroducatorul a pus,Bt$ D i)'
tr# {
sleep((int)(?at:.random() . ;<<))'
) catc: (0nterruptedM/ception e) { )
)
)
)
class Consumator e/tends @:read {
private Sata0nputStream in'
public Consumator(Sata0nputStream in) {
t:is.in 2 in'
)
public void run() {
int value 2 <'
6or (int i 2 <' i A ;<' iDD) {
tr# { value 2 in.read0nt()' )
catc: (0=M/ception e) {)
S#stem.out.println($Consumatorul a primit,Bt$ D value)'
)
)
)
Curs -
Programarea .n retea
1otiuni !enerale despre retele
Lucrul cu ->L+uri
SocFet+uri
Comunicarea prin conexiuni
Comunicarea prin data!rame
Trimiterea de mesaje catre mai multi clienti
Top
;otiuni generale despre retele
Ero!ramarea "n retea implica trimiterea de mesaje si date "ntre aplicatii ce rulea$a pe calculatoare aflate
"ntr+o retea locala sau conectate la Internet' Eachetul care ofera suport pentru scrierea aplicatiilor de retea
este 4ava3net' Clasele din acest pachet ofera o modalitate facila de pro!ramare "n retea# fara a fi nevoie de
1@1
cunostine prealabile referitoare la comunicarea efectiva "ntre calculatoare' Cu toate acestea sunt necesare
c.teva notiuni fundamentale referitoare la retele# cum ar fi protocol# adresa IE# port# socFet'
Ce este un protocol 5
-n protocol repre$inta o conventie de repre$entare a datelor folosita "n comunicarea "ntre doua
calculatoare' ;v.nd "n vedere faptul ca orice informatie care trebuie trimisa prin retea trebuie seriali$ata
astfel "nc.t sa poata fi transmisa secvential# octet cu octet# catre destinatie# era nevoie de stabilirea unor
conventii 3protocoale4 care sa fie folosite at.t de calculatorul care trimite datele c.t si de cel care le
primeste'
Cele mai utili$ate protocoale sunt TCP si :+P'
+e$initii
T4P (Transport 4ontrol Protocol! este un protocol ce furni$ea$a un flux si!ur de date "ntre doua
calculatoare' ;cest protocol asi!ura stabilirea unei conexiuni permanente "ntre cele doua
calculatoare pe parcursul comunicatiei'
,5P (,ser 5atagram Protocol! este un protocol ce trimite pachete independente de date# numite
atagrame# de la un calculator catre altul fara a !aranta "n vreun fel ajun!erea acestora la
destinatie' ;cest protocol nu stabileste o conexiune permanta "ntre cele doua calculatoare'
Cum este identi$icat un calculator .n retea 5
Orice calculator !a$da conectat la Internet este identificat "n mod unic de adresa sa IP 3IE este acronimul
de la (nternet Protocol4' ;ceasta repre$inta un numar repre$entat pe =7 de biti# u$ual sub forma a D octeti#
cum ar fi de exemplu) ;83.22*.2*.23; si este numit adresa 0L numerica. Corespun5atoare
unei adrese numerice e/ista si o adresa 0L simbolica4 cum ar 6i 6enrir.in6oiasi.ro.
Se asemenea 6iecare calculator a6lat Ontr-o retea locala are un nume unic ce poat 6i
6olosit la identi6icarea locala a acestuia.
Clasa Java care repre5inta notiunea de adresa 0L este 0netddress.
$e este un port H
[n calculator are On general o singura legatura 6i5ica la retea. =rice in6ormatie
destinata unei anumite masini trebuie deci sa speci6ice obligatoriu adresa 0L a
acelei masini. 0nsa pe un calculator pot e/ista concurent mai multe procese care au
stabilite cone/iuni On retea4 astept\nd diverse in6ormatii. Lrin urmare datele
trimise catre o destinatie trebuie sa speci6ice pe l\nga adresa 0L a calculatorului
si procesul catre care se Ondreapta in6ormatiile respective. 0denti6icarea proceselor
se reali5ea5a prin intermdiul porturilor.
[n port este un numar de ;* biti care identi6ica On mod unic procesle care rulea5a pe
o anumita masina. =rice aplicatie care reali5ea5a o cone/iune On retea va trebui sa
atase5e un numar de port acelei cone/iuni. Qalorile pe care le poate lua un numar de
port sunt cuprinse Ontre < si *((3( (deoarece sunt numere repre5entate pe ;* biti)4
numerele cuprinse Ontre < si ;<23 6iind Onsa re5ervate unor servicii sistem si4 din
acest motiv4 nu trebuie 6olosite On aplicatii.
$lase de &a)a din java.net
Clase din +ava.net permit comunicare Ontre procese 6olosind protocoalele @CL si [SL
si sunt pre5entate On tabelul de mai +os.
TCP :+P
[PC
[PCConnection
SocNet
ServerSocNet
SatagramLacNet
SatagramSocNet
?ulticastSocNet
1@7
Aceste clase permit programarea de retea la nivel de aplicatie.
Cele 1 nivele ale comunicarii On retea sunt ,
;pplication+level la&ers
;pplication La&er
Eresentation La&er
Session La&er 3SocFets4
(ata communication+level la&ers
Transport La&er 3TCE# -(E4
1et0orF La&er 3IE4
(ata La&er
Eh&sical La&er
9ucrul cu ?29;uri
8efinitie
URL este acronimul pentru Uniform Resource Locator si repre5inta o re6erinta
(adresa) la o resursa a6lata pe 0nternet. Aceasta este On general un 6isier
repre5ent\nd o pagina ]eb sau o imagine4 Onsa un [PC poat re6eri si interogari
la ba5e de date4 re5ultate ale unor comen5i (programe)4 etc.
M/emple de [PC-uri sunt,
:ttp,--+ava.sun.com
:ttp,--students.in6oiasi.ro-inde/.:tml
:ttp,--&&&.in6oiasi.ro-Iac6-imgs-ta5.gi6
:ttp,--&&&.in6oiasi.ro-Iac6-+ava-curs-8-progJretea.:tml_url
Supa cum se observa din e/emplele de mai sus4 un [PC are doua componente principale,
;. 0denti6icatorul protocolului 6olosit (:ttp4 6tp4 etc)
2. Uumele resursei re6erite. Acesta are urmatoarele componente,
o numele calculatorului ga5da (&&&.in6oiasi.ro)
o calea completa spre resursa re6erita (Iac6-+ava-curs-8-progJretea.:tml)
Uotatia Iuser semni6ica u5ual subdirectorul :tml al directorului re5ervat
pe server utili5atorului speci6icat (%=?M).
0n ca5ul On care este speci6icat doar un director4 6isierul ce repre5inta
resursa va 6i considerat implicit inde/.:tml.
o optional4 o re6erinta de tip anchor On cadrul 6isierului re6erit (_url)
o optional4 portul la care sa se reali5e5e cone/iunea
Clasa care permite lucrul cu [PC-uri este java.net.?29. Aceasta are mai multi
constructori pentru creearea de obiecte ce repre5inta re6erinte catre resurse
a6late On retea4 cel mai u5ual 6iind cel care primeste ca parametru un sir de
caractere. 0n ca5ul On care sirul nu repre5inta un [PC valid va 6i aruncata o
e/ceptie de tipul ?al6ormed[PCM/ception.
tr# {
[PC m#[PC 2 ne& [PC($:ttp,--+ava.sun.com$)'
) catc: (?al6ormed[PCM/ception e) {
. . .
)
=data creat4 un obiect de tip [PC poate 6i 6olosit pentru
o a6larea in6ormatiilor despre resursa re6erita (numele calculatorului
ga5da4 numele 6isierului4 protocolul 6olosit. etc)4
o citirea printr-un 6lu/ a continutului 6isierului respectiv
o conectarea la acel [PC pentru citirea si scrierea de in6ormatii
1@=
$itirea continutului unui ?29
=rice obiect de tip [PC poate returna un 6lu/ de intrare de tip 0nputStream
pentru citirea continutului sau' Secventa clasica pentru aceasta operatiune este)
--A6isarea paginii inde/.:tml de la adresa &&&.in6oiasi.ro
public class Citire[PC {
public static void main(String! args) t:ro&s 0=M/ception{
3u66eredPeader br 2 null'
tr# {
[PC resursa 2 new ?29($:ttp,--&&&.in6oiasi.ro$)'
0nputStream in 2 resursa.openStream'('
br 2 ne& 3u66eredPeader(ne& 0nputStreamPeader(in))'
String linie'
&:ile ((linie 2 br.readCine()) >2 null) {
--procesea5a linia citita
S#stem.out.println(linie)'
)
) catc:(?al6ormed[PCM/ception e) {
S#stem.err.println($[PC incorect, $ D e)'
)
6inall# {
br.close()'
)
)
)
Conectarea la un :82
Se reali$ea$a prin metoda openConnection ce reali$ea$a stabilirea unei conexiuni bidirectionale
cu resursa specificata' ;ceasta conexiune este repre$entata de un obiect de tip :82Coneection ce
permite crearea at.t a unui flux de intrare pentru citirea informatiilor de la ->L+ul specificat c.t si
a unui flux de iesire pentru scrierea de date catre acel ->L' Operatiunea de trimitere de date dintr+
un pro!ram catre un ->L este similara cu trimiterea de date dintr+un F=P? aflat "ntr+o pa!ina
CT%L' %etoda folosita pentru trimitere este PO'T' In ca$ul trimiterii de date# obiectul ->L este
de fapt un pro!ram 3comanda4 ce rulea$a pe serverul /eb referit prin ->L+ul respectiv 3servlet#
c!i+bin# php# etc4'
'ocAet1uri
+e$initie
-n soc/et (soclu! este o abstractiune soft0are folosita pentru a repre$enta fiecare din cele doua
*capete* ale unei conexiuni "ntre doua procese ce rulea$a "ntr+o retea' iecare socFet este atasat
unui port astfel "nc.t sa poata identifica unic pro!ramul caruia "i sunt destinate datele'
SocFet+urile sunt de doua tipuri)
o TCE# implementate de clasele SocNet si ServerSocNet
o -(E# implementate de clasa SatagramSocNet
O aplicatie de retea ce foloseste socFet+uri se "ncadrea$a "n modelul client!server de concepere a
unei aplicatii' In acest model aplicatia este formata din doua cate!orii distincte de pro!rame
numite servere# respectiv clienti'
Ero!ramele de tip server sunt cele care ofera diverse servicii eventualilor clienti# fiind "n stare de
asteptare at.ta vreme c.t nici un client nu le solicita serviciile Ero!ramele de tip client sunt cele
1@D
care initia$a conversatia cu un server# solicit.nd un anumit serviciu' -$ual# un server trebuie sa fie
capabil sa trate$e mai multi clienti simultan si# din acest motiv# fiecare cerere adresata serverului
va fi tratata "ntr+un fir de executie separat'
Comunicarea prin conexiuni
In acest model se stabileste o conexiune TCE "ntre un pro!ram client si un server care furni$ea$a
un anumit serviciu'
'tructura generala a unui server ba(at pe conexiuni
&:ile (true) {
accept a connection '
create a t:read to deal &it: t:e client '
end &:ile
import +ava.net..'
import +ava.io..'
public class SimpleServer e/tends Thread {
-- Se6inesc portul pe care se gaseste serverul in a6ara intervalului ;-;<2",
public static 6inal int 6%2T = F!CC'
private static ServerSocNet serverSocNet 2 null'
private SocNet clientSocNet 2 null'
public void run() {
--M/ecuta solicitarea clientului
String cerere4 raspuns'
tr# {
--in este 6lu/ul de intrare de la client
3u66eredPeader in 2 ne& 3u66eredPeader(ne& 0nputStreamPeader(
clientSoc:et.get0nputStream'( ))'
--out este 6lu/ de iesire catre client
Lrint]riter out 2 ne& Lrint]riter(
clientSoc:et.get%utputStream'( )'
--primesc cerere de la client
cerere 2 in.readCine()'
--trimit raspuns clientului
raspuns 2 $:ello $ D cerere'
out.println(raspuns)'
out.6lus:()'
) catc: (0=M/ception e) {
S#stem.err.println($Mroare de citire-scriere Bn$ D e)'
) 6inall# {
-- 0nc:id socNetul desc:is pentru clientul curent
tr# {
clientSocNet.close()'
) catc: (0=M/ception e) {
S#stem.err.println($SocNetul nu poate 6i inc:is Bn$ D
e)'
)
)
)
1@?
public SimpleServer() t:ro&s 0=M/ception {
serverSoc:et = new ServerSoc:et'6%2T('
tr# {
--Asteapta un client
clientSoc:et = serverSoc:et.accept'('
--M/ecuta solicitarea clientului intr-un 6ir de e/ecutie
ne& @:read(t:is).start()'
) 6inall# {
serverSocNet.close()'
)
)
public static void main(String! args) t:ro&s 0=M/ception {
SimpleServer server 2 ne& SimpleServer()'
)
)
'tructura generala a unui client ba(at pe conexiuni
import +ava.net..'
import +ava.io..'
public class SimpleClient {
public static void main(String! args) t:ro&s 0=M/ception {
--adresa 0L a serverului
String serverAddress 2 $;21.<.<.;$'
--portul la care serverul o6era serviciul
int L=P@ 2 7;<<'
SocNet clientSocNet 2 null'
Lrint]riter out 2 null'
3u66eredPeader in 2 null'
String cerere4 raspuns'
tr# {
clientSoc:et = new Soc:et'serverddress* 6%2T('
out 2 ne& Lrint]riter(
clientSocNet.get=utputStream()4 true)'
in 2 ne& 3u66eredPeader(ne& 0nputStreamPeader(
clientSocNet.get0nputStream()))'
--se trimite o cerere la server
cerere 2 $duNe$'
out.println(cerere)'
--se asteapta raspuns de la server
raspuns 2 in.readCine()'
S#stem.out.println(raspuns)'
) catc: ([nNno&n%ostM/ception e) {
S#stem.err.println($Serverul nu poate 6i gasit Bn$ D e)'
S#stem.e/it(;)'
) 6inall# {
i6 (out >2 null)
out.close()'
i6 (in >2 null)
in.close()'
i6 (clientSocNet>2 null)
clientSocNet.close()'
)
)
)
1@@
Comunicarea prin datagrame
In acest model clientul trimite un pachet cu cererea catre server# acesta primeste pachetul si
returnea$a raspunsul tot prin intermediul unui pachet' -n astfel de pachet se numeste atagrama
si este repre$entat printr+un obiect din clasa +atagramPacAet' Erimirea si trimiterea data!ramelor
se reali$ea$a tot prin intermediul unui socFet# acesta fiind modelat preintr+un obiect al clasei
+atagram'ocAet'
'tructura generala a unui server ba(at pe datagrame
import +ava.net..'
import +ava.io..'
public class SatagramServer {
public static 6inal int L=P@ 2 72<<'
private SatagramSocNet socNet 2 null'
SatagramLacNet cerere4 raspuns 2 null'
public SatagramServer() t:ro&s 0=M/ception {
Soc:et = new 8atagramSoc:et'6%2T('
tr#
{
&:ile (true) {
--Seclara pac:etul in care va 6i receptionata cererea
b#te! bu6 2 ne& b#te2(*!'
cerere = new 8atagram6ac:et'&uf* &uf.length('
--Astepta aparitia unui pac:et cu cererea
soc:et.receive'cerere('
--A6la adresa si portul de la care vine cererea
0netAddress adresa 2 cerere.getAddress()'
int port 2 cerere.getLort()'
--Construieste raspunsul
bu6 2 ($%ello $ D ne&
String(cerere.getSata())).get3#tes()'
--@rimite un pac:et cu raspunsul catre client
raspuns = new 8atagram6ac:et'&uf* &uf.length* adresa*
port('
soc:et.send'raspuns('
)
) 6inall# {
socNet.close()'
)
)
public static void main(String! args) t:ro&s 0=M/ception {
ne& SatagramServer()'
)
)
'tructura generala a unui client ba(at pe datagrame
import +ava.net..'
1@9
import +ava.io..'
public class SatagramClient {
public static void main(String! args) t:ro&s 0=M/ception {
--adresa 0L si portul la care rulea5a serverul
0netAddress address 2 0netAddress.get3#Uame($;21.<.<.;$)'
int port272<<'
SatagramSocNet socNet 2 null'
SatagramLacNet pacNet 2 null'
b#te bu6!'
tr# {
--Construieste un socNet pentru comunicare
soc:et = new 8atagramSoc:et'('
--Construieste si trimite pac:etul cu cerere catre server
bu6 2 $SuNe$.get3#tes()'
pacNet 2 ne& SatagramLacNet(bu64 bu6.lengt:4 address4 port)'
socNet.send(pacNet)'
--Asteapta pac:etul cu raspunsul de la server
bu6 2 ne& b#te2(*!'
pacNet 2 ne& SatagramLacNet(bu64 bu6.lengt:)'
socNet.receive(pacNet)'
--A6isea5a raspunsul
S#stem.out.println(ne& String(pac:et.get8ata'())'
) 6inall# {
socNet.close()'
)
)
)
Trimiterea de mesa4e catre mai multi clienti
(iverse situatii impun !ruparea mai multor clienti astfel "nc.t un mesaj 3pachet4 trimis pe adresa
!rupului sa fie receptionat de fiecare dintre acestia' Iruparea mai multor pro!rame "n vederea
trimiterii multiple de mesaje se reali$ea$a prin intermediul unui socFet special# descris de clasa
Multicast'ocAet# extensie a clasei SatagramSocNet'
-n !rup de clienti abonati pentru trimitere multipla este specificat printr+o adresa IE din intervalul
22".<.<.; - 238.2((.2((.2(( si un port -(E' ;dresa 22".<.<.< este re$ervata si nu trebuie
folosita'
Inregistrarea unui client .ntr1un grup
import +ava.net..'
import +ava.io..'
public class ?ulticastClient {
public static void main(String! args) t:ro&s 0=M/ception {
--adresa 0L si portul care repre5inta grupul de clienti
1@:
0netAddress group 2 0netAddress.get3#Uame($"IC.C.C.!$)'
int port2JJJJ'
?ulticastSocNet socNet 2 null'
b#te bu6!'
tr# {
--Se alatura grupului a6lat la adresa si portul speci6icate
soc:et = new =ulticastSoc:et'port(;
soc:et.join>roup'group('
--asteapta un pac:et venit pe adresa grupului
bu6 2 ne& b#te2(*!'
SatagramLacNet pacNet 2 ne& SatagramLacNet(bu64 bu6.lengt:)'
socNet.receive(pacNet)'
S#stem.out.println(ne& String(pacNet.getSata()))'
) 6inall# {
soc:et.leave>roup'group(;
socNet.close()'
)
)
)
Transmiterea unui mesa4 catre un grup
import +ava.net..'
import +ava.io..'
public class ?ulticastSend {
public static void main(String! args) t:ro&s M/ception {
0netAddress group 2 0netAddress.get3#Uame($23<.<.<.;$)'
int port 2 """"'
b#te! bu6'
SatagramLacNet pacNet 2 null'
--Creea5a un socNet cu un numar oarecare
SatagramSocNet socNet 2 ne& SatagramSocNet(<)'
tr#
{
--@rimite un pac:et catre toti clientii din grup
bu6 2 (ne& String($Salut grup$)).get3#tes()'
pacNet 2 ne& SatagramLacNet(bu64 bu6.lengt:4 group4 port)'
socNet.send(pacNet)'
) 6inall# {
socNet.close()'
)
)
)
Curs 1/
0pplet1uri
Ce este un applet ?
1@<
Crearea unui applet simplu
Ciclul de viata al unui applet
Interfata !rafica cu utili$atorul
(efinirea si folosirea parametrilor
Ta!+ul S;EELATT
olosirea firelor de executie "n appleturi
;lte metode oferite de clasa ;pplet
Erobleme de securitate
Ero!rame care sunt at.t appleturi c.t si aplicatii
Top
Ce este un applet 5
+e$initie
-n applet repre$inta o suprafata de afisare 3container4 ce poate fi inclusa "ntr+o pa!ina /eb si
!estionata printr+un pro!ram Java' -n astfel de pro!ram se mai numeste miniaplicatie sau# prin
abu$ de limbaj# applet'
Codul unui applet poate fi format din una sau mai multe clase' -na dintre acestea este principala si
extinde clasa 0pplet# fiind clasa ce trebuie specificata "n documentul CT%L ce descrie pa!ina de /eb "n
care dorim sa includem appletul'
(iferenta fundamentala dintre un applet si o aplicatie consta "n faptul ca# un applet nu poate fi executat
independent# ci va fi executat de bro0serul "n care este "ncarcata pa!ina /eb ce contine appletul
respectiv' O aplicatie independenta este executata prin apelul interpretorului %ava# av.nd ca parametru
numele clasei principale a aplicatiei# clasa principala fiind cea care contine metoda main' Ciclul de viata
al unui applet este complet diferit# fiind dictat de evenimentele !enerate de catre bro0ser la vi$uali$area
documentului CT%L ce contine appletul'
Eachetul care ofera suport pentru creearea de appleturi este 4ava3applet'
Crearea unui applet
Orice applet este implementat prin crearea unei subclase a clasei 0pplet' Ierarhia claselor din care deriva
Applet este pre$entata "n fi!ura de mai jos)
iind derivata din clasa Container# clasa Applet descrie de fapt suprafete de afisare# asemenea claselor
Frame sau Lanel'
198
:n applet simplu
import +ava.applet.Applet'
import +ava.a&t..'
public class AppletSimplu e/tends Applet {
public void paint(9rap:ics g) {
g.setFont(ne& Font($Arial$4 Font.3=CS4 ;*))'
g.dra&String($%ello$4 <4 3<)'
)
)
-$ual# clasa principala va fi salvata "ntr+un fisier cu acelasi nume si extensia .+ava' ;sadar# vo salva
clasa de mai sus "ntr+un fisier AppletSimplu.+ava'
Compilarea
Compilarea se face la fel ca si la aplicatiile independente# apel.nd compilatorul 4avac pentru clasa
principala a appletului 3cea care extinde Applet4'
+avac AppletSimplu.+ava
In ca$ul "n care compilarea a reusit va fi !enerat fisierul AppletSimplu.class'
Executia vi(uali(area"
Eentru a vi$uali$a acest applet trebuie sa cream un document CT%L# sa+i spunem demo.:tml# "n care sa
specificam cel putin urmatoarele informatii
clasa ce contine codul appletului
latimea si "naltimea suprafetei alocate pe pa!ina /eb
A%@?C>
A%MAS>
A@0@CM> [n applet simplu A-@0@CM>
A-%MAS>
K6691T $%81=.ppletSimplu.class. 408T<=!CC <10><T=BCLK,6691TL
A-%@?C>
Vi$uali$area acestui document se poate face cu orice bro0ser 3Internet Axplorer# 1etscape# etc4# sau cu
utilitarul appletvie&er ce vine "n pachetul J(B'
appletvie&er demo.:tml
Ciclul de viata al unui applet
Axecutia unui applet "ncepe "n momentul "n care un bro0ser afisea$a o pa!ina /eb "n care este inclus
appletul respectiv si poate trece prin mai multe etape' iecare etapa este str.ns le!ata de un eveniment
!enerat de catre bro0ser si determina apelarea unei metode specifice din clasa ce implementea$a appletul'
1' Incarcarea in memorie
Aste creata o instanta a clasei principale a appletului si "ncarcata "n memorie'
7' Initiali(area
Aste apelata metoda init ce permite initiali$area diverselor variabile# citirea unor parametri de
intrare# etc'
=' Pornirea
Aste apelata metoda start
D' Executia propriu1(isa
Consta "n interactiunea dintre utili$ator si componentele afisate pe suprafata appletului sau "n
executarea unui anumit cod "ntr+un fir de executie' In unele situatii "ntrea!a executie a appletului
se consuma la etapele de initiali$are si pornire'
191
?' Oprirea temporara
In ca$ul "n care utili$atorul paraseste pa!ina /eb "n care rulea$a appletul este apelata metoda
stop a acestuia# d.ndu+i astfel posibilitatea sa se opreasca temporar c.t timp nu este vi$ibil# pentru
a nu consuma inutil din timpul procesorului' ;celasi lucru se "nt.mpla daca fereastra bro0serului
este minimi$ata' In momentul c.nd pa!ina /eb ce contine appletul devine din nou activa# va fi
reapelata metoda start'
@' Oprirea de$initiva
La "nchiderea tuturor instantelor bro0serului folosit pentru vi$uali$are# appletul va fi eliminat din
memorie si va fi apelata metoda destro# a acestuia# pentru a+i permite sa elibere$e resursele
detinute' ;pelul metodei destro# este "ntotdeauna precedat de apelul lui stop'
Metodele speci$ice appleturilor
;sadar# exista metode specifice appletului ce sunt apelate automat la diverse evenimente !enerate de catre
bro0ser' ;cestea sunt date "n tabelul de mai jos)
Metoda 'ituatia .n care este apelata
init
La initiali$area appletului6 teoretic# aceasta metoda ar trebui sa se apele$e o sin!ura
data# la prima afisare a appletului "n pa!ina# "nsa# la unele bro0sere# este posibil ca
ea sa se apele$e de mai multe ori'
start
Imediat dupa initiali$are si de fiecare data c.nd appletul redevine activ# dupa o
oprire temporara'
stop
(e fiecare data c.nd appletul nu mai este vi$ibil 3pa!ina /eb nu mai este vi$ibila#
fereastra bro0serului este minimi$ata# etc4 si "nainte de destro#'
destroE
La "nchiderea ultimei instante a bro0serului care a "ncarcat "n memorie clasa
principala a appletului'
;ceste metode sunt apelate automat de bro0ser si nu trebuie apelate explicit din pro!ram N
'tructura generala a unui applet
import +ava.applet.Applet'
import +ava.a&t..'
import +ava.a&t.event..'
public class StructuraApplet e/tends Applet {
public void init() {
)
public void start() {
)
public void stop() {
)
public void destroy'( {
)
public void paint(9rap:ics g) {
)
)
Inter$ata gra$ica cu utili(atorul
197
(upa cum am va$ut# clasa Applet este o extensie a superclasei Container# ceea ce "nseamna ca
appleturile sunt# "nainte de toate# suprafete de afisare' Elasarea componentelor# !estionarea po$itionarii lor
si tratarea evenimentelor !enerate se reali$ea$a la fel ca si "n ca$ul aplicatiilor' -$ual# adau!area
componentelor pe suprafata appletului precum si stabilirea obiectelor responsabile cu tratarea
evenimentelor !enerate sunt operatiuni ce vor fi reali$ate "n metoda init'
Iestionarul de po$itionare implicit este Flo&Ca#out# "nsa acesta poate fi schimbat prin metoda
setCa#out'
+esenarea pe supra$ata unui applet
Axista o cate!orie "ntrea!a de appleturi ce nu comunica cu utili$atorul prin intermediul componentelor ci#
executia lor se re$uma la diverse operatiuni de desenare executate "n metoda paint' >eamintim ca metoda
paint este responsabila cu definirea aspectului !rafic al oricarei componente' Implicit# metoda paint din
clasa Applet nu reali$ea$a nimic# deci# "n ca$ul "n care dorim sa desenam direct pe suprafata unui applet
va fi nevoie sa supradefinim aceasta metoda'
In ca$ul "n care este aleasa aceasta solutie# evenimentele tratate u$ual vor fi cele !enerate de mouse sau
tastatura'
+e$inirea si $olosirea parametrilor
Earametrii sunt pentru appleturi ceea ce ar!umentele de la linia de comanda sunt pentru aplicatiile
independente' Ai permit utili$atorului sa personali$e$e aspectul sau comportarea unui applet fara a+i
schimba codul si recompila clasele'
+e$inirea parametrilor se face "n cadrul ta!ului ALLCM@ din documentul CT%L ce contine appletul si sunt
identificati prin atributul P080M' iecare parametru are un nume# specificat prin ;0ME si o valoare#
specificata prin 902:E# ca "n exemplul de mai jos)
AALLCM@ C=SM2$AppletSimplu.class$ ]0S@%2;<< %M09%@2(<
ALAPA? UA?M2te/tA6isat QAC[M2$Salut$>
ALAPA? UA?M2numeFont QAC[M2$@imes Ue& Poman$>
ALAPA? UA?M2dimFont QAC[M22<>
A-ALLCM@>
Ca si "n ca$ul ar!umentelor trimise aplicatiilor de la linia de comanda# tipul parametrilor este sir de
caractere# indiferent daca valoarea este "ntre !hilimele sau nu'
iecare applet are si un set de parametri prestabiliti ale caror nume nu vor putea fi folosite pentru
definirea de noi parametri folosind metoda de mai sus' ;cestia apar direct "n corpul ta!ului ALLCM@ si
definesc informatii !enerale despre applet' Axemple de astfel de parametri sun C=SM# ]0S@% sau %M09%@'
Lista lor completa va fi pre$entata la descrierea ta!ului ALLCM@ ' fi pre
Folosirea parametrilor primiti de catre un applet se face prin intermediul metodei getParameter care
primeste ca ar!ument numele unui parametru si returnea$a valoarea acestuia' In ca$ul "n care nu exista
nici un parametru cu numele specificat# metoda "ntoarce null# ca$ "n care pro!ramul trebuie sa atribuie o
valaore implicita variabilei "n care se dorea citirea respectivului parametru'
Sa rescriem apletul considerat initial 3AppletSimplu4 astfel "nc.t acesta sa afise$e textul primit ca
parametru# folosind un font cu numele si dimeniunea specificate de asemenea ca parametri'
import +ava.applet.Applet'
import +ava.a&t..'
public class AppletSimplu e/tends Applet {
String te/t4 numeFont'
19=
int dimFont'
public void init() {
te/t = get6arameter'.te/tfisat.(;
i6 (te/t22null)
te/t2$%ello$' -- valoare implicita
numeFont 2 getLarameter($numeFont$)'
i6 (numeFont22null)
numeFont2$Arial$'
tr# {
dimFont 2 0nteger.parse0nt(getLarameter($dimFont$))'
) catc:(UumberFormatM/ception e) {
dimFont 2 ;*'
)
)
public void paint(9rap:ics g) {
g.setFont(ne& Font(numeFont4 Font.3=CS4 dimFont))'
g.dra&String(te/t4 2<4 2<)'
)
)
Orice applet poate pune la dispo$itie o *documentatie* referitoare la parametrii pe care "i suporta# pentru a
veni "n ajutorul utili$atorilor care doresc sa includa appletul "ntr+o pa!ina /eb' ;ceasta se reali$ea$a prin
supradefinirea metodei getParameterIn$o# care returnea$a un vector format din triplete de siruri' iecare
element al vectorului este de fapt un vector cu trei elemente de tip String# cele trei siruri repre$ent.nd
numele parametrului# tipul sau si o escriere a sa'
public String!! getLarameter0n6o() {
String!! in6o 2 {
--Nume Tip 8escriere
{$te/tA6isat$4 $String$4 $Sirul ce va 6i a6isat$)4
{$numeFont$4 $String$4 $Uumele 6ontului$)4
{$dimFont$4 $int$4 $Simensiunea 6ontului$)
)'
return in6o'
)
Informatiile furni$ate de un applet pot fi citite din bro0serul folosit pentru vi$uali$are prin metode
specifice acestuia' (e exemplu# "n 1etscape se foloseste optiunea Page info din meniul 6ie.'
Tag1ul J0PP2ETK
A 6691T
$%815S1 2 directorApplet!
$%81 2 clasaApplet
9T 2 textAlternativ!
N=1 2 numeInstantaApplet!
408T< 2 latimeInPixeli
<10><T 2 naltimeInPixeli
90>N 2 aliniere!
VS6$1 2 spatiuVertical!
<S6$1 2 spatiuOrizontal!
>
A 62= N=1 2 numeParametru V9?1 2 valoare >!
A 62= N=1 2 numeParametru! V9?1 2 valoare! >!
. . .
text "#$L alternativ!
A-6691T>
;tributele puse "ntre parante$e patrate sun optionale'
CO+E@0'E L irector*pplet
19D
Specifica ->L+ul "n care se !aseste clasa appletului' -$ual se exprima relativ la directorul
documentului CT%L' In ca$ul "n care lipseste# se considera implicit ->L+ul documentului'
CO+E L clasa*pplet
1umele fisierului ce contine clasa principala a appletului' ;cesta va fi cautat "n directorul
specificat de C=SM3ASM' 1u poate fi absolut'
02T L text*lternativ
Specifica textul ce trebuie afisat daca bro0serul "ntele!e ta!ul ALLCM@ dar nu poate rula appleturi
Java'
;0ME L nume(nstanta*pplet
Ofera posibilitatea de a da un nume respectivei instante a appletului# astfel "nc.t mai multe
appleturi aflate pe aceeasi pa!ina sa comunice "ntre ele folosindu+se de numele lor'
?I+TI L latime(nPixeli
IEI=IT L naltime(nPixeli
Specifica latimea si "naltimea suprafetei "n care va fi afisat appletul'
02I=; L aliniere
Semnifica modalitatea de aliniere a appletului "n pa!ina /eb' ;cest atribut poate primi una din
urmatoarele valori) le6t4 rig:t4 top4 te/ttop4 middle4 absmiddle4 baseline4 bottom4
absbottom # seminificatiile lor fiind aceleasi ca si la ta!ul 0?9'
9'P0CE L spatiu6ertical
I'P0CE L spatiu2ri"ontal
Specifica numarul de pixeli dintre applet si mar!inile suprafetei de afisare'
J P080M ;0ME L numeParametru7 902:E L valoare7 K
Ta!+urile SE;>;%T sunt folosite pentru specificarea parametrilor unui applet'
ve$i *(efinirea si folosirea parametrilor*
text 8T'$ alternativ
Aste textul ce va fi afisat "n ca$ul "n care bro0serul nu "ntele!e ta!ul ALLCM@' Hro0serele care
"ntele! Java vor i!nora acest text'
Folosirea $irelor de executie .n appleturi
iecare applet aflat pe o pa!ina /eb se executa "ntr+un fir de executie propriu' ;cesta este creat de catre
bro0ser si este responsabil cu desenarea appletului 3apelul metodelor update si paint4 precum si cu
transmiterea mesajelor !enerate de catre componentele appletului' In ca$ul "n care dorim sa reali$am si
alte operatiuni consumatoare de timp este recomandat sa le reali$am "ntr+un alt fir de executie# pentru a nu
bloca interactiunea utili$atorului cu appletul sau redesenarea acestuia'
Structura unui applet care doreste sa lanse$e un fir de executie poate avea doua forme' In prima situatie
appletul porneste un fir de executie la initial$area sa iar acesta va rula# indiferent daca appletul mai este
sau nu vi$ibil# p.na la oprirea sa naturala 3terminarea metodei run4
import +ava.applet.Applet'
class Applet@:read; e/tends Applet implements Punnable {
@:read applet@:read 2 null'
public void init() {
i6 (applet@:read 22 null) {
applet@:read 2 ne& @:read(t:is)'
applet@:read.start()'
)
)
public void run() {
19?
--codul 6irului de e/ecutie
)
)
In ca$ul "n care firul de executie pornit de applet efectuea$a operatii ce au sens doar daca appletul este
vi$ibil# cum ar fi animatie# ar fi de dorit ca acesta sa se opreasca atunci c.nd appletul nu mai este vi$ibil
3la apelul metodei stop4 si sa reporneasca atunci c.nd appletul redevine vi$ibil 3la apelul metodei start4'
import +ava.applet.Applet'
public class StructuraApplet e/tends Applet implements Punnable {
@:read applet@:read 2 null'
boolean running 2 6alse'
public void start() {
--reporneste 6irul de e/ecutie
i6 (applet@:read 22 null) {
applet@:read 2 ne& @:read(t:is)'
running 2 true'
applet@:read.start()'
)
)
public void stop() {
--opreste 6irul de e/ecutie
running 2 6alse'
applet@:read 2 null'
)
public void run() {
&:ile (running) {
--codul 6irului de e/ecutie
)
)
)
-n applet este considerat activ imediat dupa apelul metodei start si devine inactiv la apelul metodei
stop'Eentru a afla daca un applet este activ se foloseste metoda is0ctive'
0lte metode o$erite de clasa 0pplet
Clasa Applet ofera metode specifice applet+urilor pentru)
Punerea la dispo(itie a unor in$ormatii despre applet
Similara cu metoda getLarameter0n6o ce oferea o *documentatie* despre parametrii pe care "i suporta
un applet# exista metoda get0ppletIn$o ce permite specificarea unor informatii le!ate de applet cum ar fi
numele# autorul# versiunea# etc' %etoda returnea$a un sir de caractere contin.nd informatii despre applet'
public String getApplet0n6o() {
return $Cel mai simplu applet4 autor necunoscut4 ver ;.<$'
)
0$larea unor adrese :82 re$eritoare la applet
Se reali$ea$a cu metodele)
getCode@ase + ce returnea$a ->L+ul directorului ce contine clasa appletului
get+ocument@ase + returnea$a ->L+ul directorului ce contine documentul CT%L "n care este
inclus appletul respectiv'
19@
Sunt foarte utile deoarece permit specificarea relativa a fisierelor folosite de un applet'
0$isarea imaginilor
;fisarea ima!inilor "ntr+un applet se face fie prin intermediul unei componente ce permite acest lucru#
cum ar fi o suprafata de desenare de tip Canvas# fie direct "n metoda paint a applet+ului# folosind metoda
dra&0mage a clasei 9rap:ics' In ambele ca$uri# "ncarcarea ima!inii "n memorie se va face cu ajutorul
metodei getImage din clasa Applet' ;ceasta poate primi ca ar!ument fie adresa ->L absoluta a
fisierului ce contine ima!inea# fie calea sa relativa la o anumita adresa ->L# cum ar fi cea a directorului
"n care se !aseste documentul CT%L ce contine appletul 3getSocument3ase4 sau a directorului "n care se
!aseste clasa appletului 3getCode3ase4'
import +ava.applet.Applet'
import +ava.a&t..'
public class Applet0magine e/tends Applet {
0mage img 2 null'
public void init() {
img 2 get0mage(getCode3ase()4 $ta5.gi6$)'
)
public void paint(9rap:ics g) {
g.dra&0mage(img4 <4 <4 t:is)'
)
)
0$isarea unor mesa4e .n bara de stare a broFserului
;cest lucru se reali$ea$a cu metoda s%oF'tatus
public void init() {
s:o&Status($0nitiali5are applet...$)'
)
0$larea contextului de executie
Contextul de executie al unui applet se refera la pa!ina "n care acesta rulea$a si este descris de interfata
0ppletContext' Crearea unui obiect ce implementea$a aceasta interfata se reali$ea$a de catre bro0ser# la
apelul metodei get0ppletContext a clasei Applet' Erin intermediul acestei interfete un applet poate
*vedea* "n jurul sau# put.nd comunica cu alte applet+uri aflate pe aceeasi pa!ina sau cere bro0ser+ului sa
deschida diverse documente'
AppletConte/t env 2 getAppletConte/t()'
0$isarea unor documente .n broFser
Se face cu metoda s%oF+ocument ce primeste adresa ->L a fisierului ce contine documentul dorit 3text#
html# ima!ine# etc4' ;ceasta metoda se !aseste "n interfata AppletConte/t'
tr# {
[PC doc 2 ne& [PC($:ttp,--&&&.in6oiasi.ro$)'
getAppletConte/t().s:o&Socument(doc)'
) catc:(?al6ormed[PCM/ception e) {)
Comunicarea cu alte applet1uri a$late pe aceeasi pagina
;ceasta comunicare implica de fapt identificarea unui applet aflat pe aceeasi pa!ina si apelarea unei
metode sau setare unei variabile publice a acestuia' Identificarea se face prin intermediu numelui pe care
orice instanta a unui applet "l poate specifica prin atributul ;0ME' 3ve$i ta!+ul S;EELATT4'
Obtinerea unei instante a unui applet al carui nume "l cunoastem sau obtinerea unei enumerari a tuturor
applet+urilor din pa!ina se fac cu metodele definite de interfata AppletConte/t get0pplet si get0pplets'
199
8eproducerea unor sunete
' ' '
Probleme de securitate
-n applet nu poate sa)
Citeasca sau scrie fisiere pe calculatorul pe care a fost "ncarcat 3client4
(eschida conexiuni cu alte masini "n afara de cea de pe care provine 3host4
Eorneasca pro!rame pe masina client
Citeasca diverse proprietati ale sistemului de operare al clientului
erestrele folosite de un applet# altele dec.t cea a bro0serului# vor arata altfel dec.t "ntr+o aplicatie
obisnuita'
Programe care sunt at<t appleturi c<t si aplicatii
import +ava.applet.Applet'
import +ava.a&t..'
public class AppletApp e/tends Applet {
public void init() {
add(ne& Cabel($Applet si aplicatie$))'
)
public static void main(String args!) {
AppletApp applet 2 ne& AppletApp()'
Frame 6 2 ne& Frame($Aplicatie si applet$)'
6.setSi5e(2<<4 2<<)'
6.add(applet4 3orderCa#out.CMU@MP)'
applet.init()'
applet.start()'
6.s:o&()'
)
)
Curs 11
2ucrul cu ba(e de date .n Java
Ieneralitati despre ba$e de date
Ce este J(HC ?
Conectarea la o ba$a de date
Afectuarea de secvente SRL
19:
Obtinerea si prelucrarea re$ultatelor
Axemplu
Top
=eneralitati despre ba(e de date
;plicatiile care folosesc ba$e de date sunt# "n !eneral# aplicatii complexe folosite pentru !estionarea unor
informatii de dimensiuni mai mari "ntr+o maniera si!ura si eficienta'
Ce este o ba(a de date 5
O ba"a e ate repre$inta o modalitate de stocare a unor informatii 3date4 pe un suport extern# cu
posibilitatea re!asirii acestora' -$ual# o ba$a de date este memorata "ntr+unul sau mai multe fisiere'
%odelul clasic de ba$a de date este cel relational# "n care datele sunt memorate "n tabele' Ee l.n!a tabele#
o ba$a de date mai poate contine) proceduri si functii# utili$atori si !rupuri de utili$atori# tipuri de date#
obiecte# etc'
(intre producatorii cei mai importanti de ba$e de date amintim Oracle# S&base# IH%# Informix#
%icrosoft# etc'
Crearea unei ba(e de date
Se face cu aplicatii speciali$ate oferite de producatorul tipului respectiv de ba$a de date'
0ccesul la o ba(a de date
Se face prin intermediul unui driver specific tipului respectiv de ba$a de date' ;cesta este responsabil cu
accesul efectiv la datele stocate# fiind le!atura "ntre aplicatie si ba$a de date'
Ce este J+@C 5
+e$initie
J5)4 (Java 5atabase 4onnectivity! este o interfata standard SRL de acces la ba$e de date' J(HC
este constituita dintr+un set de clase si interfete scrise "n Java# furni$.nd mecanisme standard
pentru proiectantii aplicatiilor de ba$e de date'
Eachetul care ofera suport pentru lucrul cu ba$e de date este 4ava3sMl'
olosind J(HC este usor sa transmitem secvente SRL catre ba$e de date relationale' Cu alte cuvinte# nu
este necesar sa scriem un pro!ram pentru a accesa o ba$a de date Oracle# alt pro!ram pentru a accesa o
ba$a de date S&base si asa mai departe' Aste de ajuns sa scriem un sin!ur pro!ram folosind ;EI+ul J(HC
si acesta va fi capabil sa trimita secvente SRL ba$ei de date dorite' Hine"nteles# scriind codul sursa "n
Java# ne este asi!urata portabilitatea pro!ramului' (eci# iata doua motive puternice care fac combinatia
Java + J(HC demna de luat "n seama'
19<
iind robust# si!ur# usor de folosit# usor de "nteles# Java este un excelent limbaj pentru a de$volta aplicatii
de ba$e de date' Tot ceea ce+i lipseste este modalitatea prin care aplicatiile Java pot comunica cu ba$ele
de date' ;ici vine "nsa J(HC+ul care ofera acest mecanism'
Ce $ace J+@C1ul5
In linii mari# J(HC face trei lucruri)
stabileste o conexiune cu o ba$a de date
trimite secvente SRL
prelucrea$a re$ultatele
Conectarea la o ba(a de date
Erocesul de conectare la o ba$a de date implica doua operatii)
1' "ncarcarea "n memorie a unui driver corespun$ator
7' reali$area unei conexiuni propriu+$ise
+e$initie
O conexiune (sesiune! la o ba$a de date repre$inta un context prin care sunt trimise secvente SRL
si primite re$ultate' Intr+o aplicatie pot exista mai multe conexiuni simultan la ba$e de date diferite
sau la aceeasi ba$a'
Clasele si interfetele responsabile cu reali$area unei conexiuni sunt)
clasa 8river=anager# ce se ocupa cu "nre!istrarea driverelor ce vor fi folosite "n aplicatie
interfata 8river# pe care trebuie sa o implemente$e orice clasa ce descrie un driver
clasa 8river6roperty0nfo
interfata $onnection# descrie obiectele ce modelea$a o conexiune propriu+$isa cu ba$a de date
Incarcarea .n memorie a unui driver
Erimul lucru pe care trebuie sa+l faca o aplicatie "n procesul de conectare la o ba$a de date este sa "ncarce
"n memorie clasa ce implementea$a driver+ul necesar comunicarii cu respectiva ba$a de date' ;cest lucru
poate fi reali$at prin mai multe modalitati)
;. Sriver?anager.registerSriver(ne& sun.+dbc.odbc.Jdbc=dbcSriver())'
2. Class.6orUame($sun.+dbc.odbc.Jdbc=dbcSriver$)'
3. S#stem.setLropert#($+dbc.drivers$4 $sun.+dbc.odbc.Jdbc=dbcSriver$)'
". +ava -S+dbc.drivers2sun.+dbc.odbc.Jdbc=dbcSriver
'peci$icarea unei ba(e de date
O data ce un driver J(HC a fost "ncarcat "n memorie cu Sriver?anager# acesta poate fi folosit la
stabilirea unei conexiuni cu o ba$a de date' ;v.nd "n vedere faptul ca pot exista mai multe drivere
"nre!istrate "n memorie# trebuie sa avem posibilitea de a specifica pe l.n!a identificatorul ba$ei de date si
driverul ce trebuie folosit'
;ceasta se reali$ea$a prin intermediul unei adrese specifice# numita J+@C :82# ce are urmatorul
format)
jd&c-su&;protocol-identificatorM&a)aMdeMdate
C.mpul sub-protocol denumeste tipul de driver ce trebuie folosit pentru reali$area conexiunii si poate fi
obc9 oracle9 sybase9 b: si asa mai departe' (entificatorul ba"ei e ate este un indicator specific
fiecarui driver care specifica ba$a de date cu care aplicatia doreste sa interactione$e' In functie de tipul
1:8
driver+ului acest identificator poate include numele unei masini !a$da# un numar de port# numele unui
fisier sau al unui director# etc'
+dbc,odbc,testdb
+dbc,oracle,t:in^persistent+ava.com,;(2;,testdb
+dbc,s#base,testdb
+dbc,db2,testdb
La primirea unui J(HC ->L# Sriver?anager+ul va parcur!e lista driver+elor "nre!istrate "n memorie#
p.na c.nd unul dintre ele va recunoaste ->L+ul respectiv' (aca nu exista nici unul potrivit# atunci va fi
lansata o exceptie de tipul S`CM/ception# cu mesajul no suitable driver'
8eali(area unei conexiuni
%etoda folosita pentru reali$area unei conexiuni este getConnection din clasa Sriver?anager si poate
avea mai multe forme)
Connection c 2 Sriver?anager.getConnection(url)'
Connection c 2 Sriver?anager.getConnection(url4 username4 pass&ord)'
Connection c 2 Sriver?anager.getConnection(url4 dbproperies)'
O conexiune va fi folosita pentru)
crearea de secvente SRL ce vor fi folosite pentru intero!area sau actuali$area ba$ei
aflarea unor informatii le!ate de ba$a de date 3meta+date4
Clasa Connection asi!ura suport pentru controlul tran$actiilor din memorie catre ba$a de date prin
metodele commit4 rollbacN4 setAutoCommit '
E$ectuarea de secvente 'N2
O data facuta conectarea cu Sriver?anager.getConection()# se poate folosi obiectul Connection
re$ultat pentru a se crea un obiect de tip 'tatements# cu ajutorul caruia putem trimite secvente SRL catre
ba$a de date' Cele mai u$uale comen$i SRL sunt cele folosite pentru)
1' intero!area ba$ei de date 3SMCMC@4
7' actuali$area ba$ei de date 30USMP@4 [LSA@M4 SMCM@M4
Connection c 2 Sriver?anager.getConnection(url)'
Statement s 2 c.createStatement()'
PesultSet r 2 s.e/ecute`uer#($SMCMC@ . FP=? unJtabel =PSMP 3Z oJcoloana$)'
s.e/ecute[pdate($SMCM@M . FP=? unJtabel$)'
%etoda e/ecute`uer# trimite intero!ari SRL catre ba$a de date si primeste rasuns "ntr+un obiect de tip
PesultSet'
Obtinerea si prelucrarea re(ultatelor
Inter$ata 8esult'et
String Wuer# 2 $SMCMC@ cod4 nume FP=? localitati =PSMP 3Z nume$'
PesultSet r 2 s.e/ecute`uer#( Wuer# )'
&:ile (r.ne/t()) {
S#stem.out.println (
r.getString ($cod$) D $4$ D
r.getString ($nume$) )'
1:1
Inter$ata 8esult'etMeta+ata
PesultSet r 2 s.e/ecute`uer#($ SMCMC@ . FP=? localitati$ )'
PesultSet?etaSata rsmd 2 r.get?etaSata()'
S#stem.out.println($Coloane, $ D rsmd.getColumnCount())'
Exemplu
import +ava.sWl..'
import +ava.io..'
public class @estJS3C {
public static void main (String! args) {
String db[rl 2 $+dbc,odbc,test$'
String user 2 $dba$'
String pass&ord 2 $sWl$'
tr#{
Class.6orUame($sun.+dbc.odbc.Jdbc=dbcSriver$)'
)
catc:(ClassUotFoundM/ception e) {
e.printStacN@race()'
S#stem.out.println($Mroare incarcare driver>Bn$ D e)'
)
tr#{
Connection c2Sriver?anager.getConnection(db[rl4 user4
pass&ord)'
Statement s2 c.createStatement()'
PesultSet r 2
s.e/ecute`uer#(
$ SMCMC@ cod4 nume FP=? localitati$D
$ =PSMP 3Z nume$)'
&:ile (r.ne/t()) {
S#stem.out.println (
r.getString ($cod$) D $4$ D
r.getString ($nume$) )'
)
s.close()'
)
catc:(S`CM/ception e) {
e.printStacN@race()'
)
)
)
Curs 12
Organi(area $isierelor 34ava si 3class
Or!ani$area fisierelor sursa 3'java4
Or!ani$area fisierelor cuextensia 'class
1ecesitatea or!ani$arii fisierelor
Setarea caii de cautare 3CL;SSE;TC4
;rhive J;>
1:7
Top
Organi(area $isierelor sursa 34ava"
Orice aplicatie nebanala trebuie sa fie construita folosind o or!ani$are ierarhica a surselor si fisierelor
'class ale sale' Aste recomandat ca strate!ia de or!ani$are a fisierelor sursa sa respecte urmatoarele
conventii)
1' Codul sursa al claselor si interfetelor sa se !aseasca "n fisiere ale caror nume sa fie numele scurt al
claselorJinterfetelor si care sa aiba extenisa 'java'
0tentie
Aste obli!atoriu ca o clasaJinterfata publica sa se !aseasca "ntr+un fisier av.nd numele
clasei3interfetei4 si extenisa 'java' (in acest motiv "ntr+un fisier sursa nu pot exista doua clase
publice' Eentru clasele care nu sunt publice acest lucru nu este obli!atoriu ci doar recomandat'
Intr+un fisier sursa pot exista oric.te clase care nu sunt publice'
7' isierele sursa trebuie sa se !aseasca "n directoare care sa reflecte numele pachetelor "n care se
!asesc clasele si interfetele din acele fisiere sursa' Cu alte cuvinte un director va contine surse
pentru clase si interfete din acelassi pachet iar numele directorului va fi chiar numele pachetului'
(aca numele pachetelor sunt formate din mai multe unitati lexicale separate prin punct# atunci
acestea trebuie de asemenea sa corespunda unor directoare ce vor descrie calea spre fisierele sursa
ale caror claseJinterfete fac parte din pachetele respective'
Vom clarifica modalitatea de or!ani$are a fisierelor sursa ale unei aplicatii printr+un exemplu concret' Sa
presupunem ca dorim crearea unui pro!ram java care sa repre$inte diverse notiuni matematice din
domenii diferite cum ar fi !eometrie# al!ebra# anali$a# etc' Eentru a simplifica lucrurile sa presupunem ca
dorim sa cream# clase care sa descrie urmatoarele notiuni) poligon9 cerc9 polieru9 sfera9 grup9 functie' O
prima varianta ar fi sa construim c.te o clasa java pentru fiecare si sa le plasam "n acelasi director
"mpreuna cu un pro!ram care sa le foloseasca# "nsa# av.nd "n vedere posibila extindere a aplicatiei cu noi
repre$entari de notiuni matematice# aceasta abordare ar fi ineficienta'
O abordare ele!anta ar fi aceea "n care clasele care descriu notiuni din acelasi domeniu sa se !aseasca "n
pachete separate si directoare separate' Ierarhia fisierelor sursa ar fi)
-matematica
,surse
-geometrie
-plan
Loligon.+ava
Cerc.+ava
-spatiu
Loliedru.+ava
S6era.+ava
-algebra
9rup.+ava
-anali5a
Functie.+ava
=atematica.java
Clasele descrise "n fisierele de mai sus trebuie declarate "n pachete denumite corespun$ator cu numele
directoarelor "n care se !asesc)
1:=
Eoli!on'java
pacNage geometrie.plan'
public class Loligon { . . . )
Cerc'java
pacNage geometrie.plan'
public class Cerc { . . . )
Eoliedru'java
pacNage geometrie.spatiu'
public class Loliedru { . . . )
Sfera'java
pacNage geometrie.spatiu'
public class S6era { . . . )
Irup'java
pacNage algebra'
public class 9rup { . . . )
unctie'java
pacNage anali5a'
public class Functie { . . . )
?atematica.+ava este clasa principala a aplicatiei'
1umele lun! al unei clase trebuie sa descrie calea spre acea clasa "n cadrul fisierelor sursa ale unei
aplicatii'
Organi(area $isierelor 3class
In urma compilarii fisierelor sursa vor fi !enerate unitati de compilare pentru fiecare clasa si interfata din
fisierele sursa' Eentru fiecare clasaJinterfata va fi !enerat un fisier cu extensia 'class si cu numele
claseiJinterfetei respective'
Ca si la fisierele 'java# un fisier 'class trebuie sa se !aseasca "ntr+o serie de directoare care sa reflecte
numele pachetului din care face parte' Initial# "n urma compilarii fisierele sursa si unitatile de compilare
3'class4 se !asesc "n acelasi director# "nsa ele pot fi apoi or!ani$ate separat'
>evenind la exemplul de mai sus# putem avea urmatoarea or!ani$are)
-matematica
,clase
-geometrie
-plan
Loligon.class
Cerc.class
-spatiu
Loliedru.class
S6era.class
-algebra
9rup.class
-anali5a
Functie.class
=atematica.class
Crearea acestei structuri ierarhice poate fi facuta automat de catre compilator' In directorul aplicatiei
3matematica4 cream subdirectorul clase si dam comanda)
+avac -sourcepat: surse surse-?atematica.+ava -d clase
sau
+avac -classpat: surse surse-?atematica.+ava -d clase
;ecesitatea organi(arii $isierelor
1:D
Or!ani$area fisierelor sursa este necesara deoarece "n momentul c.nd compilatorul "nt.lneste un nume de
clasa el trebuie sa poata identifica acea clasa# ceea ce "nseamna ca trebuie sa !aseasca fiserul sursa care o
contine'
Similar# fisierele 'class sunt or!ani$ate astfel pentru a da posibilitatea interpretorului sa !aseasca o
anumita clasa "n timpul executiei pro!ramului' Insa aceasta or!ani$are nu este suficienta deoarece
specifica numai partea finala din calea catre fisierele 'java si 'class )
-matematica-clase-geometrie-plan-Loligon.class' Eentru aceasta# at.t la compilare c.t si la
interpretare trebui specificata lista de directoare "n care se !asesc fisierele aplicatiei' ;ceasta lista se
numeste cale e cautare (classpat&!'
+e$initie
O cale e cautare este o lista de directoare sau arhive "n care vor fi cautate fisierele necesare unei
aplicatii' iecare director din calea de cautare este directorul imediat superior structurii de
directoare formate de or!ani$area claselor "n directoare corespun$atoare pachetelor# astfel "nc.t
compilatorul si interpretorul sa poata construi calea completa spre clasele aplicatiei' Implicit calea
de cautare este formata doar din directorul curent'
Sa consideram clasa principala a aplicatiei ?atematica.+ava)
import geometrie.plan..'
import algebra.9rup'
import anali5a.Functie'
public class ?atematica {
public static void main(String args!) {
Loligon a 2 ne& Loligon()'
geometrie.spatiu.S6era 2 ne& geometrie.spatiu.S6era()'
--...
)
)
Identificarea unei clase referite "n pro!ram se face "n felul urmator)
1' La directoarele aflate "n calea de cautare se adau!a subdirectoarele specificate "n import sau "n
numele lun! al clasei
7' In directoarele formate este cautat un fisier cu numele clasei' In ca$ul "n care nu este !asit nici
unul sau sunt !asite mai multe va fi semnalata o eroare'
'etarea caii de cautare C20''P0TI"
Se poate face "n doua modalitati)
1' Setarea variabile de mediu C20''P0TI 3nerecomandat4
2. 2. [U0T,
3. 3. SM@ CCASSLA@% 2 cale; , cale2 , ...
". ". Pecomandat sa apara si directorul curent .
(. (. S=S s:ell (]indo&s 8(-U@),
*. *. SM@ CCASSLA@% 2 cale; ' cale2 ' ...
1. 1. Pecomandat sa apara si directorul curent .
:' olosirea optiunii 1classpat% la compilarea si interpretarea pro!ramelor
8. 8. +avac - classpat: Acale de cautare> A6isier.+ava>
;<. ;<. +ava - classpat: Acale de cautare> A6isier.class>
Lansarea "n executie a aplicatiei noastre# din directorul aplicatiei# s+ar putea face astfel)
+ava -classpat: clase ?atematica.+ava
O or!ani$are eficienta a fisierelor aplicatiei ar arata astfel)
-matematica
-surse
-clase
compile.bat (+avac -sourcepat: surse surse-?atematica.+ava -d
clase)
1:?
run.bat (+ava -classpat: clase ?atematica.+ava)
0r%ive J08 Java 08c%ive"
+e$initie
Sunt arhive "n format XIE folosite pentru compresarea mai multor fisere "n unul sin!ur' (iferenta
consta "n faptul ca un fisier J;> contine# pe l.n!a fiserele arhivate# si un director denumit ?M@A-
0UF# ce contine diverse informatii auxiliare'
-n fisier J;> poate fi creat folosind utilitarul 4ar sau metode ale pachetului 4ava3util34ar'
@ene$icii
portabilitate + este sin!urul format de arhivare independent de platforma
compresarea fisierelor est optimi$ata pentru fisiere de tip class
minimi$area timpului de incarcare a unui applet ) daca appletul 3fisiere class# resurse# etc4 este
compresat intr+o arhiva jar# el poate fi incarcat intr+o sin!ura tran$actie CTTE# fara a fi deci
nevoie de a se deschide o conexiune noua pt' fiecare fisier'
securitate + arhivele J;> pot fi *semnate* electronic
mecanismul pentru lucrul cu fisiere J;> este parte inte!rata a platformei Java'
Folosirea utilitarului 4ar
;rhivatorul jar se !aseste "n subdirectorul bin al directorului "n care este instalat mediul Java' In tabelul
de mai jos sunt sumari$ate operatiile principale)
Operatie Comanda
Crearea unei arhive
+ar c6 nume-ar:iva 6isier(e)-
intrare
Vi$uali$are continutului unei arhive
+ar t6 nume-ar:iva
Axtra!erea continutului unei arhive
+ar /6 nume-ar:iva
Axtra!erea doar a unor fisiere dintr+o arhiva
+ar /6 nume-ar:iva 6isier(e)-
ar:ivate
Axecutarea unei aplicatii "mpachetate "ntr+un fisier jar 3 J(B
1'14
+re -cp app.+ar ClasaLrincipala
Axecutarea unei aplicatii "mpachetate "ntr+un fisier jar 3 J(B
1'74
;licatia trebuie compresata in asa fel incat interpretorul sa stie
unde se !aseste clasa principala
+ava -+ar app.+ar
(eschiderea "ntr+un bro0ser a unui applet compresat "ntr+un
fisier jar
Aapplet code2UumeClasaApplet.class
archive2$UumeAr:iva.+ar$
&idt:2latime
:eig:t2Onaltime>
A-applet>
Axemple)
arhivarea a doua fisiere class) +ar c6 classes.+ar A.class 3.class
arhivarea tuturor fisierelor din directorul curent) +ar cv6 all6iles.+ar .
1:@
Executarea aplicatiilor .mpac%etate .ntr1o ar%iva J08
Eentru a rula o aplicatie "mpachetata "ntr+o arhiva J;> trebuie sa facem cunoscuta interpretorului numele
clasei principale a aplicatiei' Sa consideram urmatorul exemplu# "n care dorim sa arhivam clasele )
9rap:Mditor.class4 9rap:.class4 Mdge.class4 Qerte/.class # clasa principala fiind
9rap:Mditor' Vom scrie)
+ar cv6m editor.+ar ..class
In urma acestei comen$i vom obtine arhiva editor.+ar' (aca vom "ncerca sa lansam "n executie aceasta
arhiva prin comanda +ava -+ar editor.+ar vom obtine urmatoarea eroare)
$Failed to load ?ain-Class mani6est 6rom editor.+ar$
' ;ceasta "nseamna ca "n fiserul ?ani6est.m6 ce se !aseste "n directorul ?M@A-0UF trebuie sa "nre!istram
clasa principala a aplicatiei' ;cest lucru "l vom face "n doi pasi)
1' se creea$a un fisier cu un nume oarecare 3ex) m&manifest 4 "n care vom scrie)
?ain-Class , 9rap:Mditor.+ava
7' adau!am aceasta completare la fisierul manifest al arhivei editor'jar)
+ar cv6m editor.+ar m#mani6est
;mbele operatii puteau fi executate "ntr+un sin!ur pas)
+ar cv6m editor.+ar m#mani6est ..class
Fisiere J08 executabile
Ee sistemele /in=7# platforma Java 7 va asocia extensiile 'jar cu interpretorul java# ceea ce "nseamna cs
fac.nd dublu+clicF pe o arhiva jar va fi lansata "n executie aplicatia "mpachetata "n acea arhiva 3daca
exista o clasa principala4'
Top
1:9