Sunteți pe pagina 1din 109

UNIVERSITATEA TITU MAIORESCU

FACULTATEA DE INFORMATIC

PROGRAMARE N JAVA

-suport de curs pentru forma de nvmnt la distan -

Conf.univ. dr. Dsclescu Ana Cristina

- 2016 -
Introducere

Acest curs se adreseaz studenilor anului II, specializarea Informatic, forma de nvmnt la
distan. Modul de prezentare ine cont de particularitile nvmntului la distan, la care studiul
individual este determinant..

Disciplina Programarea n Java utilizeaz noiunile predate la disciplinele Bazele Informaticii,


Programare procedural, Programare orientat pe obiecte, discipline studiate n anul I i n anul
II.

Competenele dobndite de ctre studeni prin nsuirea coninutului cursului sunt folosite la
disciplinele de specialitate precum Tehnici avansate de programare, Proiectarea interfeelor
grafice etc. O nenelegere a noiunilor fundamentale prezentate n acest curs poate genera
dificulti n asimilarea conceptelor mai complexe ce vor fi introduse n aceste cursuri de
specialitate.

Principalele obiective ale disciplinei Programare n Java sunt:

nsuirea tehnologiei Java Standard Edition


Deprindere pentru a realiza aplicaii de sine stttoare
Deprindere pentru a realiza aplicaii cu baze de date
Deprindere pentru a realiza aplicaii de tip client i server

Structura cursului este urmtoarea:

Unitatea de nvare 1. Structura programelor Java


Unitatea de nvare 2. Lucrul cu tablouri n Java
Unitatea de nvare 3. Clase i obiecte
Unitatea de nvare 4. Lucrul cu iruri de caractere
Unitatea de nvare 5. Extinderea claselor
Unitatea de nvare 6. Clase abstracte i interfee
Unitatea de nvare 7. Excepii i conversii
Unitatea de nvare 8. Fluxuri de intrare/ieire
Unitatea de nvare 9. Java Database Conectivity (JDBC)
Unitatea de nvare 10. Servlet-uri

2
Pachet software recomandat:

Orice mediu de lucru pentru limbajul Java poate fi folosit, dar pentru a face o alegere mai puin
costisitoare, de altfel gratuit, v sugerm mediul de lucru NetBeans care se poate descrca de pe
site-ul https://netbeans.org/downloads/

Nota final care se va acorda fiecrui student, va conine urmtoarele


componente n procentele menionate:
- examen final 60%
- lucrri practice/ proiect 40%

Coordonator de disciplin
Conf. univ. dr. Ana Cristina Dsclescu

3
Unitatea de nvare nr. 1

STRUCTURA PROGRAMELOR JAVA

Obiectivele Unitii de nvare nr. 1

Obiective:

Dup ce vei parcurge aceast unitate de nvare, vei reui s:

cunoatei noiunile de baz ale limbajului Java;


cunoatei structura unei aplicaii scrise n Java;
cunoatei tipuri de date i instruciuni de control.

Caracteristici de baz ale limbajului Java


nceputul limbajului Java este n toamna anului 1991, cnd firma Sun Microsystems a finanat un
proiect cu numele Green condus de James Gosling. Tehnologia propus a avut un impact
remarcabil asupra ntregii comuniti a dezvoltatorilor de software, impunndu-se prin caliti
deosebite cum ar fi simplitate, robustee i nu n ultimul rnd portabilitate.
Dup patru ani de lucru, echipa Green finalizeaz specificaiile limbajului Java, astfel c n anul
1995 firma Sun Microsystems vinde licena firmelor IBM, Microsoft, Silicon Graphic, Adope i
Netscape.

ncepnd cu anul 1998, cnd a aprut versiunea 2 a limbajului (Java 2 Platform), Java a fost extins,
acoperind i mai multe direcii de dezvoltare: programarea aplicaiilor enterprise (aplicaii de tip
server) precum i a celor adresate dispozitivelor cu resurse limitate, cum ar fi telefoanele mobile,
pager-e sau PDA-uri (mici dispozitive de calcul, de dimensiuni puin mai mari dect ale unui
telefon mobil, cu faciliti de agend i capabile s execute aplicaii ntr-un mod relativ asemntor
cu cel al unui PC).

Caracteristicile de baz ale limbajului Java:

este un limbaj simplu de folosit : elimin suprancrcarea operatorilor, motenirea multipl,


pointerii;
este portabil;
este complet orientat obiect: elimin complet stilul de programare procedural
este distribuit, avnd implementate biblioteci pentru lucrul n reea;
este un limbaj cu securitate ridicat.

4
Platforme de lucru Java
Tehnologiile Java sunt grupate n aa numitele platforme de lucru. Acestea reprezint seturi de
librarii scrise n limbajul Java, precum i diverse programe utilitare, utilizate pentru dezvoltarea de
aplicaii sau componente destinate unei anume categorii de utilizatori.

J2SE (Standard Edition)


Este platforma standard de lucru ce ofer suport pentru crearea de aplicaii independente i
appleturi. De asemenea, aici este inclus i tehnologia JavaWeb Start ce furnizeaz o modalitate
extrem de facil pentru lansarea i instalarea local a programelor scrise n Java direct de
peWeb, oferind cea mai comod soluie pentru distribuia i actualizarea aplicaiilor Java.
J2ME (Micro Edition)
Folosind Java, programarea dispozitivelor mobile este extrem de simpl, platforma de lucru
J2ME oferind suportul necesar scrierii de program dedicate acestui scop.
J2EE (Enterprise Edition)
Aceasta platforma ofer API-ul necesar dezvoltrii de aplicaii complexe, formate din
componente ce trebuie sa ruleze n sisteme eterogene, cu informaiile memorate n baze de date
distribuite, etc. Tot aici gsim i suportul necesar pentru crearea de aplicaii i servicii Web,
bazate pe componente cum ar fi servlet-uri, pagini JSP, etc.

Tipuri de programe implementate n Java


Cu ajutorul limbajului Java se pot dezvolta trei tipuri de programe:

1. Programe Java care se execut individual prin intermediul unui interpretor Java. Acestea se
ncadreaz n programele clasice scrise n diverse limbaje de programare, cum ar
fi:C/C++, Pascal etc. Acest tip de programe Java sunt denumite aplicaii de sine stttoare.

2. Programe Java care se execut n interiorul unui navigator Internet, dintr-un document
HTML. Acest tip de programe Java sunt denumite applet-uri.

3. Aplicaii care se execut pe partea de server numite servlet-uri.

O aplicaie de sine stttoare este un program Java care se execut n afara browser-ului Web .
Principala caracteristic a acestui tip de aplicaie este ncapsularea n cadrul unei clase principale a
unei funcii main() asemntoare cu cea folosita n limbajul C, cu urmtoarea signatura:

public static void main(String args[] )

Aplicaiile care se execut pe partea de client sunt cele ncrcate de pe un server i apoi executate
de programe speciale cum ar fi navigatoarele Web.
Un applet este un program Java care respecta o mulime de reguli astfel nct s poat rula n cadrul
unui navigator Web.

O aplicaie care se execut pe partea de server este o aplicaie care este rulat de server ca urmare a
unei cereri primite de acesta, iar rezultatul este trimis programului solicitant.
Un servlet este o component Web, scris n Java, i care poate interaciona cu diferii clieni
folosind o implementare a paradigmei cerere/rspuns bazata pe protocolul HTTP. Servlet-urile
extind funcionalitatea unui server, de obicei a unui server HTTP.

5
Etapele dezvoltrii unei aplicaii Java
1.Editarea setului de instruciuni de programare cu ajutorul unui editor de texte. n acest fel este
creat un fiier surs, care are extensia .java.

2. Compilarea programului. Pentru aceasta operaie se lanseaz n execuie un program special,


denumit compilator Java. Compilatorul analizeaz textul surs al programului din punct de vedere
sintactic, semnalnd eventualele erori. Daca programul nu conine erori sintactice, compilatorul
traduce acest program n codul main pentru maina virtual Java
Rezultatul compilrii este unul sau mai multe fiiere de tip bytecode. Un fiier de tip bytecode
este o secven de instruciuni de asamblare pentru maina virtual Java cu extensia .class.

3. Conversia (transformarea), de ctre interpretorul Java, a instruciunilor bytecode n


instruciuni inteligibile mainii gazd care apoi sunt executate.

O aplicaie Java este compus din una sau mai multe clase care interacioneaz ntre ele prin
intermediul metodelor. n grupul de clase, care formeaz o aplicaie Java, trebuie sa existe o clas
care s conin o metoda statica avnd numele main. Atunci cnd se execut o aplicaie Java,
maina virtual va cuta i invoca automat metoda static avnd numele main.
Observaie: Metoda main poate fi considerat ca fiind echivalentul Java al funciei main din
C/C++.

Exemplul 1 Cel mai simplu program Java arat astfel:

class aplicatie
{
public static void main (String [ ] args)
{
System.out.println(Primul program Java);
}
}

Observaie: Tipul parametrilor metodei (funciei) main ct i tipul metodei, static void, sunt
obligatorii.

Elemente de baz

Caractere

Limbajele de programare "clasice" utilizeaz setul de caractere ASCII. Limbajul Java folosete
setul de caractere Unicode, care este reprezentabil pe 16 bii, deci are 65 536 caractere, cuprinznd
caractere i simboluri proprii aproape tuturor limbilor existente.

Primele 256 caractere din Unicode sunt cele din setul de caractere Latin-1, dintre care primele 128
sunt cele din codul ASCII.

Un caracter poate fi reprezentat oriunde n textul surs i prntr-o aa numit "secven Escape",
avnd forma \uhhhh sau \Uhhhh, unde am notat prin h o cifr hexazecimal (cifrele hexazecimale
corespunztoare lui 10-15 sunt identificate prin a-f sau A-F). O secven Escape poate s apar deci

6
nu numai n caractere i iruri de caractere, dar i n identificatori. Numrul hexazecimal dntr-o
astfel de secven corespunde numrului de ordine al caracterului n setul Unicode.

Ne mrginim la a indica secvenele Escape pentru semnele diacritice din limba romn:

= \u00c3 = \u00e3
= \u00c2 = \u00e2
= \u00aa = \u00ca
= \u00de = \u00fe
= \u00ce = \u00ee

n continuare vom nelege prin spaii albe caracterele blanc, tab, form-feed, precum i terminatorii
de linie: return, line-feed (linie nou) i return + line-feed.

Anumite caractere pot fi reprezentate prntr-o secven Escape de o form aparte:

\n = \u000a (linie nou) \\ = \u005c (backslash)


\t = \u0009 (tab) \' = \u0027 (apostrof)
\b = \u0008 (backspace) \f = \u000c (form-feed)
\r = \u000d (return) \" = \u0022 (ghilimele)

Motivaia utilizrii setului Unicode este integrarea n limbaje de tip HTML care s permit
circulaia pe Internet.

Identificatori

n Java identificatorii ncep cu o liter (inclusiv '_' i '$') i pot continua cu litere sau / i cifre; este
totui indicat s nu includem n identificatori caracterul '$', deoarece el este folosit de compilatorul
Java pentru a genera identificatori interni, despre care nu vom vorbi aici. Prin "litere" nelegem att
pe cele obinuite (literele mici i mari din alfabetul englez), ct i pe cele din alte limbi. Un
identificator poate avea orice lungime; de aceea este indicat s folosim identificatori ct mai
sugestivi pentru rolul pe care l joac, timpul "pierdut" la scrierea programului fiind recuperat din
plin atunci cnd revedem programul peste cteva luni sau cnd trebuie ca el s fie neles de alte
persoane.

Anumii identificatori au o semnificaie predefinit, ce nu poate fi modificat, i nu pot fi folosii n


alt context dect cel intenionat de ctre autorii limbajului. Ei se numesc cuvinte cheie. O prim list
de cuvinte cheie este urmtoarea:
abstract boolean break byte case
catch char class continue default
do double else extends final
finally float for if implements
import instanceof int interface long
new null package private protected
public return short static super
switch synchronized this throw
throws try void while

Aa cum am precizat n capitolul anterior, n programe sau secvene de cod aceste cuvinte cheie vor
aprea ngroate pentru a veni n ajutorul cititorilor.

7
Constante

n limbajul Java, constantele mai poart i numele de literali. Vom prezenta doar o parte a acestor
constante (de exemplu nu vom vorbi de literali ntregi octali i hexazecimali):

1) Literalii ntregi sunt de dou tipuri:


- normali, reprezentai pe 32 de bii i pentru care scrierea este cea uzual;
- lungi, reprezentai pe 64 de bii, identificai prin faptul c au sufixul 'l' sau 'L'.

2) Literalii reali (n virgul mobil):


- dubli, reprezentai pe 64 de bii, pentru care scrierea este cea uzual. Este vorba de numere
zecimale ce conin opional punctul zecimal i pot fi urmate de un exponent prefixat cu e sau E. De
exemplu urmtorii trei literali reprezint aceeai valoare:
21. 2.1e1 .21E2
- normali, reprezentai pe 32 de bii. Aceti literali au aceeai form ca cei dubli, dar au n plus
sufixul 'f' sau 'F'.
Conform standardului IEEE 754, sunt inclui i literali pentru "nu este un numr", - i +:
Double.NaN, Double.NEGATIVE_INFINITY i Double.POSITIVE_INFINITY(pentru aritmetica
pe 8 octei); Float.NaN, Float.NEGATIVE_INFINITY i Float.POSITIVE_INFINITY(pentru
aritmetica pe 4 octei).
Valoarea NaN apare ca rezultatul unor operaii ca de exemplu mprirea la zero; ea nu este
"ordonat": compararea ei cu orice valoare produce rezultatul false. n schimb valorile
corespunztoare lui - i + sunt ordonate: pentru orice literal "efectiv" val, avem
<val<+.
Cele mai mici valori pozitive pentru literalii normali i dubli sunt:
Float.MIN_VALUE=1.43-45f i Double.MIN_VALUE=5e-324
iar cele mai mari valori posibile pentru literalii n virgul mobil sunt:
Float.MAX_VALUE=3.4028e+38f i Double.MAX_VALUE=1.79769e+308.

3) Literalii booleeni sunt true i false.

4) Literalii de tip caracter au forma 'c', unde c este un caracter sau o secven Escape; aceste
secvene au fost prezentate mai sus.

5) Literalii de tip ir de caractere sunt cuprini ntre ghilimele.


Menionm c irurile de caractere sunt instane ale clasei String declarat standard n Java. Iat
cteva exemple:
"" ( irul vid) ; "ab\nn" (unde apare secvena Escape '\n') .

6) Literalul referin este null.

Comentarii

Comentariile sunt folosite n principal pentru explicitarea aciunilor ntreprinse de cod; ele sunt
ignorate de compilator.

Exist trei tipuri de comentarii:


- de sfrit de linie: ncep cu // i se termin la sfritul liniei;
- generale: ncep cu /* i se termin la prima succesiune */.
- de documentare: ncep cu /** i se termin la prima succesiune */. Acest tip de comentariu poate
fi plasat doar imediat naintea unei clase, unui membru al unei clase sau a unui constructor.
Utilitarul javadoc este capabil s colecteze comentariile de documentare din codul surs al claselor
8
i s le introduc n documente HTML. Din cele de mai sus rezult c nu exist comentarii n
comentarii. irul /**/ este considerat un comentariu de documentare, n timp ce /* */ este un
comentariu general.

Variabile

Forma general folosit pentru declararea variabilelor este:


< ir de modificatori > < tip > < list de identificatori > ;
unde prezena modificatorilor este opional. Informaiile din irul de modificatori sunt separate
prin spaii albe, iar cele din lista de identificatori prin virgul. Dac dorim s specificm i o valoare
iniial pentru un identificator, acesta trebuie urmat de semnul = i de un literal, ca de exemplu n:
int a = 3;
Menionm pentru moment doar urmtorii modificatori:
- modificatori de acces (public, private, protected); dac nu este specificat nici unul dintre aceti
modificatori, se consider c este ataat un modificator implicit;
- static;
- final.

Modificatorii pot nsoi nu numai cmpurile, ci i clasele i metodele, dar despre acest aspect vom
vorbi ntr-un capitol urmtor.
La declararea cmpurilor unei clase se recomand precizarea modificatorilor n ordinea de mai sus.
Aa cum am menionat n capitolul anterior, modificatorul static specific faptul c respectivul
cmp este unic pe clas, deci comun tuturor obiectelor ce sunt instane ale clasei (joac rolul de
memorie comun pentru toate obiectele ce instaniaz clasa); cmpul static poate fi referit din afara
clasei ca orice cmp, dar i prin precalificare cu numele clasei.

O declarare poate s apar oriunde n cadrul unei clase, metode sau a unui bloc de iniializare, deci
nu neaprat la nceputul lor.
Limbajul Java atribuie valori iniiale implicite cmpurilor claselor. Ele sunt:
false (pentru boolean) ; 'u0000' (pentru char) ; null (pentru referine)
0 (pentru orice tip ntreg) ; +0.0f sau +0.0d (pentru float i double) ,
unde tipurile menionate sunt descrise n continuare. n schimb nu este atribuit vreo valoare iniial
prin lips variabilelor locale din metode, constructori i blocuri de iniializare i de aceea aceste
variabile trebuie s primeasc valori nainte de a fi utilizate; nerespectarea acestei reguli conduce la
semnalarea unei erori.

O variabil declarat cu modificatorul final este iniializat implicit sau explicit prin declararea sa;
aceast valoare nu mai poate fi schimbat ulterior.

O variabil are un nume (care este un identificator) i un tip, despre care tim c este un tip primitiv
sau un tip referin. Enumerm n continuare tipurile primitive (de baz).

1) Tipul boolean. Variabilele de acest tip pot lua doar valorile true i false.

2) Tipul char. Variabilele de acest tip sunt reprezentate pe 16 bii i pot primi ca valoare orice
simbol din codul Unicode. O variabil de tip caracter poate fi folosit oriunde poate aprea o
valoare ntreag: este considerat numrul su de ordine n setul de caractere Unicode.

3) Tipuri ntregi. Ele sunt urmtoarele:


byte (octet) short (ntreg scurt) int (ntreg) long (ntreg lung)
reprezentate n ordine pe 1, 2, 4, 8 octei. Valorile maxime sunt n ordine:
255 32767 2109 91018

9
Precizm c n calcule tipurile byte i short sunt convertite la int.

4) Tipurile n virgul mobil float i double, reprezentate respectiv pe 4 i 8 octei.

Fiecrui tip primitiv din Java i corespunde o clas definit standard n Java: Boolean, Character,
Byte, Short, Integer, Long, Float i Double. n aceste clase apar constante i metode utile. Am
prezentat deja cteva constante din aceste clase n discuia asupra literalilor n virgul mobil. Mai
menionm metoda isNaN din clasele Float i Double: metoda primete o valoare de tipul
corespunztor i ntoarce o valoare boolean, care este true dac i numai dac argumentul nu este o
valoare numeric valid.

Operatori
Menionm c Java pune la dispoziia utilizatorului aproximativ 40 de operatori, dintre care unii
sunt descrii n continuare. Trebuie precizat c programatorul poate defini metode noi, dar nu i
operatori noi.

Operatori aritmetici
Aceti operatori sunt urmtorii:
+ - * / %
De asemenea este folosit operatorul unar - pentru schimbarea semnului, precum i operatorul unar +
(introdus pentru simetrie).
n aritmetica ntreag trebuie s inem cont de urmtoarele reguli:
- orice valoare ce depete limita admis este redus modulo aceast limit; de aceea nu exist
depiri (overflow i underflow);
- mprirea ntreag se face prin trunchiere; de exemplu -8/3==-2, iar 8/3==2 ;
- operatorul % este definit prin:
(x/y)*y+x%y==x
De exemplu 8%3==2, iar -8%3==-2.

Operatorii de incrementare i decrementare


Este vorba de operatorii unari ++ i --, care pot fi aplicai operanzilor numerici (ntregi sau n
virgul mobil) att n form prefixat ct i n form postfixat.
Expresiile x++ i ++x sunt echivalente cu x=x+1, cu dou excepii:
- sunt atomice (considerate ca o unic operaie, nu ca o incrementare urmat de o atribuire). Acest
aspect este relevant doar cnd mai multe fire de executare acioneaz asupra unei aceleiai
variabile;
- operandul x este evaluat o singur dat. Aceast excepie are n vedere instruciuni de tipul
a[indice()]=a[indice()]+1, n care este folosit o metod ce ntoarce un ntreg; astfel, n exemplul de
mai sus, invocarea metodei indice va avea loc o singur dat (n caz contrar este posibil ca n
membrul stng i cel drept s nu se refere la aceeai component a tabloului a, de exemplu dac
metoda ntoarce n mod aleator un indice).

Diferena ntre x++ i ++x const n faptul c incrementarea este realizat dup, respectiv nainte de
utilizarea lui x n contextul n care apare. Astfel, dac valoarea curent a lui x este 4, atunci:
- evaluarea expresiei 2 * ++x conduce la rezultatul 10,
- evaluarea expresiei 2 * x++ conduce la rezultatul 8,
dup care valoarea lui x va fi n ambele cazuri 5.
Evident, operatorul -- se supune unor reguli analoage.

10
O construcie de tipurile x++,x--,++x,--x reprezint o expresie aritmetic, dar i o instruciune
(valoarea expresiei nu este folosit, ns x este incrementat sau decrementat).
Operatorii de mai sus pot fi aplicai i pentru tipul char, semnificnd trecerea la precedentul,
respectiv urmtorul caracter din setul de caractere Unicode.

Operatorii de atribuire
Pe lng operatorul = folosit standard pentru atribuire, mai pot fi folosii i operatorii:
+= -= /= *= %=
care reprezint scrieri prescurtate. Astfel x+=y este echivalent cu x=x+y, cu excepia faptului c
evaluarea adresei lui x se face o singur dat (vezi paragraful precedent). Desigur, operatorul %= va
fi folosit doar pentru aritmetica ntreag.

Operatorii relaionali
Este vorba de urmtorii operatori:
> (mai mare ca) >= (mai mare sau egal cu) == (egal cu)
< (mai mic ca) <= (mai mic sau egal cu) != (diferit de)

Operatori booleeni
Este vorba de urmtorii operatori:
(disjuncia logic, sau) && (conjuncia logic, i) ! (negaie)
cu meniunea c la evaluare se face scurtcircuitare (pe scurt, dac la evaluarea unei expresii
booleene devine la un moment dat clar valoarea ei, nu se mai continu n mod inutil evaluarea; de
exemplu dac expresia este disjuncia logic a trei termeni i valoarea primului este true, nu se mai
evalueaz ceilali termeni).

Operatori pe bii
Este vorba de operatorii binari i & care realizeaz disjuncia logic i conjuncia logic la nivel de
bit, pentru fiecare pereche de bii de pe aceeai poziie din reprezentarea operanzilor.

Operatorul condiional ?:
Acest operator se utilizeaz n expresii sub forma:
( cond ? e1 : e2 )
a crei valoare este e1 dac cond este true, respectiv e2 dac cond este false; cond trebuie s fie
o expresie de tip boolean. Pentru a nu intra n amnunte, vom impune deocamdat regula ca e1 i
e2 s aib acelai tip.

Operatori postfixai
Includem aici:
- cuprinderea ntre paranteze a indicilor (cu []);
- operatorul de calificare (.) folosit pentru accesarea membrilor claselor;
- parantezele rotunde folosite pentru specificarea listei de parametri din invocri;
- operatorii postfixai de incrementare/decrementare ++ i -- de mai sus.

11
Operatorul de conversie a tipurilor
Ne mrginim la a preciza c o conversie explicit de tip are forma:
(tip) expresie
urmnd s discutm ulterior condiiile n care poate avea loc o astfel de conversie.

Operatorul + pentru lucrul cu iruri


Acest operator este folosit pentru concatenarea irurilor. Trebuie menionat c dac un membru al
unei sume este un ir de caractere, atunci are loc o conversie implicit a celorlali membri ai sumei
(devenit acum concatenare) la iruri de caractere; aceast facilitate a fost de altfel des folosit n
programele prezentate anterior, de exemplu n cadrul invocrii System.out.print(...). Adugm doar
c printre membrii sumei pot aprea i variabile referin!

Operatorii pentru referine


Sunt utilizai urmtorii operatori:
- accesul la cmpuri (prin calificare);
- invocarea metodelor (prin calificare);
- operatorul de conversie;
- operatorii == i != ;
- operatorul condiional;
- operatorul instanceof , folosit n contextul:
Ob instanceof Clasa
care produce o valoare boolean ce este true dac i numai dac obiectul Ob este diferit de null i
este o instan a clasei Clasa sau poate fi convertit la tipul Clasa (despre conversiile de tip vom
vorbi ntr-un capitol aparte).

Precedena operatorilor
Ordinea n care are loc efectuarea prelucrrilor determinate de operatori este dat n urmtorul tabel
de prioriti ale operatorilor (de la prioritate maxim la prioritate minim):
- operatorii postfix
- operatorii unari de incrementare/decrementare, operatorii + i - unari, operatorul de negaie !
- operatorul new de creare de obiecte i cel de conversie: (tip) expresie
- operatorii multiplicativi: * / %
- operatorii aditivi: + -
- operatorii relaionali i instanceof
- operatorii de egalitate: == !=
- operatorul &
- operatorul
- conjuncia logic &&
- disjuncia logic
- operatorul condiional ( ? : )
- operatorii de atribuire.

Observaii:
- la prioritate egal, operatorii "vecini" acioneaz conform regulilor de asociativitate prezentate n
continuare;
- utilizarea parantezelor este mai puternic dect prioritatea operatorilor. Astfel, spre deosebire de
x+y*z, n (x+y)*z prima operaie care va fi executat este adunarea.

12
Asociativitate

Regula general o constituie asociativitatea la stnga. Fac excepie urmtorii operatori, pentru care
este folosit asociativitatea la dreapta:
- operatorii unari;
- operatorii de atribuire.
- operatorul ( ? : ).
Exemple :

1) n expresia x-y+z nti se va efectua scderea i apoi adunarea;


2) Instruciunea:
x = y = z = 0;
este echivalent cu:
x = ( y = (z = 0));
i are ca efect atribuirea valorii 0 variabilelor x,y,z. Explicaia const n aceea c efectuarea unei
atribuiri conduce i la obinerea unui rezultat (valoarea care a fost atribuit) i care poate fi folosit
ca n exemplul de mai sus.
3) Secvena de program:
int a=5, b=10, c=15;
a += b -=c %= 4;
System.out.println(a + " " + b + " " + c);
produce la ieire:
12 7 3

Controlul execuiei

Limbajul Java prevede mai multe tipuri de instruciuni:


- Instruciunea compus grupeaz mai multe instruciuni prin includerea lor ntre acolade; ia natere
astfel un bloc. Un bloc este considerat a fi o unic instruciune.

- Instruciunea de declarare asociaz unei variabile un anumit tip i eventual i atribuie o valoare
iniial; variabila devine local celui mai interior bloc care o conine, n sensul c exist atta timp
ct se execut instruciuni ale blocului. O instruciune de declarare poate s apar oriunde n
interiorul unui bloc. nainte de utilizarea lor, variabilele locale trebuie s fi primit valori fie prin
iniializare la declarare, fie printr-o instruciune de atribuire (n caz contrar va fi semnalat o eroare
la compilare).

- Invocarea unei metode, indiferent dac ea ntoarce sau nu o valoare.


- Incrementrile, care folosesc forma prefixat sau postfixat a lui ++ sau --.

- Instruciunea de atribuire conine semnul =, eventual prefixat cu un operator.

- Instruciunea vid este format numai din ; i care nu prevede vreo prelucrare.

- Instruciunea prin care este creat un obiect folosete n acest scop operatorul new.

- Instruciunile ce controleaz ordinea de executare, ca de exemplu: if-else, for, while etc. Ele vor
fi prezentate detaliat n continuare.

Trecem la descrierea instruciunilor ce controleaz ordinea de executare. Instruciunile care apar n


cadrul lor vor fi notate prin instr, instr1 etc.

13
- Instruciunea if-else. Ea are una dintre formele:
if (expresie_boolean) instr1
sau
if (expresie_boolean) instr1
else instr2
Este evaluat expresia boolean. Dac rezultatul este true, atunci se execut instr1, iar n caz contrar
se execut instr2 (sau nimic pentru forma scurt).
Clauza else este asociat celui mai recent if cruia nu i s-a asociat un else. Astfel n :
if (a==0) b=1; if (c==1) b=2; else b=3;
clauza else este asociat celui de al doilea if. Pentru a face lucrurile clare, este indicat ca fiecare if
s fie nsoit de un else (urmat eventual de instruciunea vid).

- Instruciunea while are forma:


while (expresie_boolean) instr
Se ncepe cu evaluarea expresiei booleene i se execut n mod repetat instruciunea instr atta timp
ct expresia boolean are valoarea true.

- Instruciunea do-while are forma:


do instr while (expresie_boolean);
Se ncepe cu executarea instruciunii instr i se reia executarea ei atta timp ct expresia boolean
are valoarea true.

- Instruciunea for are forma:


for (iniializri; expresie_boolean; actualizri) instr
unde:
- iniializrile i actualizrile (de obicei incrementri i/sau decrementri) sunt liste de instruciuni
separate prin virgul; listele pot fi eventual vide;

- expresia boolean poate i ea lipsi, caz n care se presupune c ea are implicit valoarea true.

Efectul instruciunii poate fi descris astfel:


iniializri;
while (expresie_boolean) {
instr; actualizri
}

Cadrul tipic de utilizare este n iteraii. De exemplu, suma primelor n numere naturale poate fi
obinut astfel:
s=0;
for (i=0;i<n;i++) s+=i;

Mai prezentm nc un exemplu: dei n-am vorbit nc despre tablouri, menionm c pentru
inversarea ordinii elementelor unui tablou (unidimensional) a este suficient o instruciune for
(indexarea elementelor tablourilor ncepe cu 0):
for(i=0,j=a.length-1; i<j; i++,j--)
{ b=a[i];a[i]=a[j];a[j]=b;}

Un caz limit este:


for( ; ; ) instr

14
care desemneaz repetarea "la infinit" a executrii lui instr. Evident, n cazul folosirii acestei forme,
asigurarea ieirii din ciclu cade n sarcina instruciunii instr.
n iniializrile din for este permis s facem declarri, ca de exemplu:
for(int i=1;i<=n;i++) s+=i;
dar numai dac i nu este deja declarat; precizm c n aceast situaie variabila i este local
instruciunii for.

nainte de a prezenta alte instruciuni, menionm c o instruciune poate fi etichetat. Etichetarea ei


se face astfel:
eticheta:instr
unde eticheta este un identificator. n acest mod va fi posibil s facem referire (trimitere) la
instruciunea respectiv.

- Instruciunea break este folosit pentru a iei dintr-un bloc. O prim form este:
break;
prin care se iese din cea mai interioar instruciune for, while, do sau switch, sau bloc ce conine
aceast instruciune.
Forma:
break eticheta;
unde eticheta este eticheta unui bloc sau a uneia dintre cele 4 tipuri de instruciuni menionate, ce
conine instruciunea break. Ca efect, controlul este transferat la instruciunea cu eticheta
respectiv. Se poate astfel iei de exemplu din dou instruciuni for imbricate. S remarcm faptul
c nu este posibil s trecem controlul oricrei alte instruciuni (ca pentru goto din alte limbaje), deci
transferul este controlat i respect structurarea programului.

- Instruciunea continue are forma:


continue;
i este folosit n cadrul instruciunilor while, do i for. Efectul ei este saltul la condiia care
controleaz reluarea acestor instruciuni de ciclare.
Ca i n cazul instruciunii break, poate fi folosit i varianta etichetat, prin care se face salt la
condiia de control a unei instruciuni while, do sau for cu eticheta respectiv, care o "acoper"
(include) la un nivel superior.

- Instruciunea switch evalueaz o expresie ntreag, a crei valoare este folosit pentru a detecta o
secven de instruciuni ce urmeaz a fi executat. O prim form a ei este:
switch (expresie) {
case val1 : secven_instruciuni1
...
case valk : secven_instruciunik
default : secven_instruciuni
}
unde:
- tipul expresiei poate fi numai char, byte, short sau int;
- val1, ..., valk sunt constante (literali sau cmpuri statice finale iniializate cu expresii constante) de
acelai tip cu al expresiei;
- alternativa default este opional.
Executarea instruciunii are loc dup cum urmeaz. Este calculat valoarea expresiei, care este apoi
comparat pe rnd cu val1, ..., valk, pn cnd se detecteaz prima dat egalitate. Urmeaz
executarea secvenei de instruciuni corespunztoare, dar i a celor care urmeaz; executarea
acestora poate fi limitat prin folosirea instruciunii break. Dac nu se detecteaz nici o egalitate,
atunci se execut secvena de instruciuni corespunztoare lui default (dac aceast alternativ este
prezent) sau nu se execut nimic (n caz contrar).

15
Mai general, o alternativ poate avea mai multe valori, ca n exemplul urmtor:
case 1 : case 3 : case 5 : a = b; b = c; c = a;

Exemplul 2
Programul urmtor:

class Switch {
static void numara(int i) {
switch (i) {
case 1 : System.out.print("unu ");
case 2 : System.out.print("doi ");
case 3 : System.out.println("trei");
}
}

public static void main (String[] args) {


numara(3); numara(2); numara(1);
}
}
va produce la ieire:
trei
doi trei
unu doi trei

- Instruciunea return are una dintre formele:


return;
return expresie;
i furnizeaz valoarea care va fi ntoars (n cazul cnd metoda prevede ntoarcerea unei valori) i
termin executarea metodei n care apare.
Putem folosi return i pentru a iei dintr-un constructor sau dintr-un bloc de iniializare static.

Afiarea datelor pe ecran

n limbajul Java nu exista instruciuni specializate pentru citirea/scrierea datelor. Aceste operaii se
realizeaz prin intermediul unor metode existente n pachetele API ale limbajului. Intrarea i ieirea
n Java se realizeaz cu ajutorul claselor de obiecte din pachetul predefinit java.io. Orice program
care folosete rutinele de intrare/ieire trebuie sa cuprind instruciunea:
import java.io.*
Conceptul fundamental n operaiile de intrare/ieire n limbajul Java este fluxul de intrare/ieire
(stream).

Daca stream-ul este de intrare, succesiunea de bii curge dinspre exterior (n acest caz, de la
tastatur) ctre memoria calculatorului.
Daca stream-ul este de ieire, secvena de bii curge dinspre memoria calculatorului ctre exterior
(n acest caz, ctre ecran).
Java ofer trei fluxuri predefinite pentru operaii I/O standard:
- System.n pentru intrarea standard de la tastatura;
- System.out pentru ieirea standard la ecranul calculatorului;
- System.err pentru fluxul de erori.

Pentru afiarea datelor la ecranul calculatorului se folosesc metodele print i println. Spre
deosebire de limbajul C/C++ care dispune de un numr foarte mare de opiuni de formatare,
afiarea n Java se face exclusiv prin concatenarea de String-uri fr nici o opiune de formatare.
16
Observaie: String-urile sunt obiecte Java care descriu irurile de caractere i le vom studia separat
ntr-o lecie viitoare. S reinem c prin concatenarea a dou iruri se obine un nou sir de caractere
care unete cele doua iruri iniiale. Operatorul de concatenare a doua iruri de caractere folosit de
Java este semnul + (plus).
Sintaxa folosita la apelul metodei print este:
System.out.print (<expresie>);
unde:
- <expresie> - este numele unei variabile de un tip de data sau este o expresie care folosete
operatorul de concatenare pentru iruri de caractere; daca nu toi operanzii din expresie sunt iruri
de caractere, ci alte tipuri primitive de date atunci Java face o conversie temporar la tipul String.
Efectul apelului metodei print este acela ca se realizeaz afiarea pe ecran a variabilei dat ca
parametru i nu se face salt la o linie nou.
Sintaxa folosita la apelul metodei println este:
System.out.println (<expresie>);
unde:
- <expresie> - este numele unei variabile de un tip de data sau este o expresie care folosete
operatorul de concatenare pentru iruri de caractere.
Efectul apelului metodei println este acela ca se realizeaz afiarea pe ecran a variabilei dat ca
parametru i se face salt la o linie noua.
Metoda println se poate apela i fr parametrii, adic n forma:
System.out.println( ); caz n care se face numai un salt la o linie nou fr sa se afieze
nimic.

Aplicaia 1

Scriei o surs Java care calculeaz masa ideal pentru brbai i femei n funcie de vrsta i
nlimea lor. Citirea datelor de intrare (nlimea i vrsta) se va realiza de la tastatur folosind
clasa Scanner.

Pentru a citi de la tastatur se poate folosi clasa Scanner, din pachetul java.util.
Consultai documentaia i observai metodele puse la dispoziie.
Scanner sc = new Scanner(System.n);
int n = sc.nextInt(); //citirea unui numr ntreg

package curs_1;
import java.util.Scanner;

public class Curs_1 {

public static void main(String[] args) {


int varsta, inaltimea;
Scanner n =new Scanner(System.n);
System.out.println(Dati varsta: );
varsta=n.nextInt();
System.out.println(Dati inaltimea: );
inaltimea=n.nextInt();
float masa;
masa= 50F+0.75F*(inaltimea - 150F) + 0.25F*(varsta- 20F);

float masaidealab, masaidealaf;

17
masaidealab=masa;
masaidealaf=masa*0.9F;

System.out.println("Masa ideala barbati: "+masaidealab+" kg");


System.out.println("Masa ideala barbati: "+masaidealaf+" kg");

}
}

Aplicaia 2

Scriei o surs Java care simuleaz n aruncri a dou zaruri. Afiai pe ecran numrul aruncrilor
ctigtoare. O aruncare se consider ctigtoare dac cele zaruri au acelai numr.

package curs_1;
import java.util.Scanner;
import java.util.Random;

public class Zaruri {


public static void main(String args[])
{
int z1, z2, n, i, k=0;
Scanner n=new Scanner(System.n);
System.out.println("Dati nr de aruncari");
n=n.nextInt();
Random rgen = new Random();
for(i=0;i<n;i++)
{
z1=1+rgen.nextInt(6);
z2=1+rgen.nextInt(6);
System.out.println(z1+" "+z2);
if(z1==z2)
k++;
}

System.out.println("Ati castigat de "+k+" ori");


}
}

18
Tem de autoinstruire
Consultai bibliografia pentru a afla :

1. Istoricul i caracteristicile limbajului Java

2. Modalitile de editare, compilare i executare a unui program Java;

3. Alte exemple de programe pentru a nelege mai bine structura programelor n Java, diferena
ntre programarea procedural i programarea orientat pe obiecte, modalitile de transmitere a
parametrilor n Java.

Teste de control
1. Fie urmtoarea declaraie Java:

public private int h;

Care afirmaii sunt adevrate:


A. Variabila h va fi accesata n mod public, deoarece se ia n considerare primul modificator de
acces;
B. Variabila h va fi accesat n mod private, deoarece se ia n considerare ultimul modificator de
acces;
C. Va fi o eroare la compilare deoarece o variabil nu poate fi n acelai timp accesat public i
private;
D. Nici una din variantele de mai sus.

2. Ce rezulta din urmtorul fragment de cod Java?

int x=1;
String []names={"Andreea","Matei","Ana"};
names[--x]+=".";
for(int i=0;i<names.length;i++)
System.out.println(names[i]);

A. Output-ul include Andreea;


B. Output-ul include Matei;
C. Output-ul include Ana;
D. Nimic din cele de mai sus.

3. Fie urmtorul program Java:


public class Program{
static void f(int k){
switch(k){
default: System.out.print("i "); break;
case1: System.out.print("1 "); break;
case 2:case3: System.out.print("21 "); break;

19
case 4:case5: System.out.print("26 ");
}}
public static void main(String []args){
for(int i=0;i<6;i++)
f(i);
}}
Care afirmaii sunt false?
A. Eroare la compilare;
B. Programul se compileaz i la execuie afieaz i 1 21 21 26 26 ;
C. Programul se compileaz i la execuie afieaz i 1 21 26 ;
D. Programul se compileaz i la execuie afieaz i 1 21 21 26 26 i;

4. Fie urmtorul cod Java:

byte b=-7 >>> 1;


System.out.println(b);

Ce se poate spune despre acest cod, daca este integrat intr-un program Java?
A. Va produce eroare la compilare;
B. Va produce eroare la execuie;
C. Programul se compileaz i la execuie afieaz -3;
D. Programul se compileaz i la execuie afieaz -4.

5. Fie urmtorul program Java:


public class Program{
static void f(int k){
switch(k){
default: System.out.print("i "); break;
case1: System.out.print("1 "); break;
case 2:case3: System.out.print("23 "); break;
case 4:case5: System.out.print("45 ");
}
}

public static void main(String []args){


for(int i=0;i<6;i++)
f(i);
}
}
Care afirmaii sunt adevrate?
A. Programul produce eroare la compilare;
B. Programul se compileaz i la execuie afieaz i 1 23 23 45 45;
C. Programul se compileaz i la execuie afieaz i 1 23 45;
D. Programul se compileaz i la execuie afieaz i 1 23 23 45 45 i.

20
Unitatea de nvare nr. 2

LUCRUL CU TABLOURI N JAVA

Obiectivele Unitii de nvare nr. 2


Dup ce vei parcurge aceast unitate de nvare, vei nelege:
Necesitatea utilizrii tablourilor n realizarea programelor;
Cum se declar o variabil de tip tablou;
Cum se face interschimbarea coninutului a doua tablouri;
Modul de lucru cu tablouri multidimensionale n Java.

Necesitatea lucrului cu tablouri n Java


Uneori este necesar s referim anumite variabile ca un singur grup pentru c este dificil s definim
i s folosim individual fiecare variabil. De exemplu, dac dorim s tiprim un set de date n
ordine invers celei n care au fost introduse, trebuie s le citim i s le salvm pe toate nainte de a
putea face prima tiprire. Dac avem de a face cu 1000 de valori, trebuie s declarm 1000 de
variabile ca s le stocm, s scriem 1000 de instruciuni de citire i 1000 de instruciuni de tiprire.
Tabloul este un tip de dat care ne permite s programm mai uor operaii asupra grupurilor de
valori de acelai tip.

Definiie, declarare
Un tablou este o secven de componente de acelai tip. Acest tip poate fi un tip primitiv sau un tip
referin (deci putem lucra cu tablouri de obiecte).
Un tablou a poate fi declarat folosind una dintre urmtoarele modaliti:
tip[] a;
tip a[];
unde tip este tipul componentelor tabloului. n continuare vom folosi numai prima form.
Declararea unui tablou nu are drept consecin crearea sa. Crearea tabloului a declarat mai sus
trebuie fcut explicit, prin:
a = new tip[n];
unde n este o constant sau o variabil ntreag ce a primit o valoare strict pozitiv.
Cele de mai sus devin clare dac specificm faptul (menionat i n primul capitol) c un tablou este
un tip referin. Prin creare se obine un obiect de tip tablou (obiect numit prin abuz de limbaj tot
tablou).
Componentele tabloului pot fi referite prin a[i], cu i lund valori n intervalul 0..n-1; dac i nu
este n acest interval, va fi semnalat o eroare la executare. Lungimea tabloului poate fi referit prin
a.length.

Declararea i crearea pot fi fcute i simultan prin:


tip[] a = new tip[n];
sau prntr-o iniializare efectiv, ca de exemplu:
int[] a = {0,3,2,5,1}
prin care, evident, a.length devine 5.

21
Cmpul length al unui (obiect de tip) tablou este un cmp constant (cu modificatorii public i
final) de tip int; deci, odat creat, un obiect tablou nu i poate schimba dimensiunea (numrul
de componente). Pe de alt parte, variabilei referin la tablou i se poate asocia o referin la un
tablou de acelai tip.

Exemple:

Exemplul 1 Urmtoarea secven de program:

tip[] a ;
a = new tip[10]; ...
a = new tip[20]; ...
este corect. Evident, noul tablou nu are nici o legtur cu cel vechi (n particular
nu se pstreaz valoarea nici unei componente a tabloului vechi).
Pentru interschimbarea coninutului a dou tablouri se poate proceda la fel ca
Exemplul 2
pentru interschimbarea valorilor a dou variabile primitive:
int[] a = {1,2,3,4}, b = {11,12,13}, c;
c=a; a=b; b=c;
deci practic se interschimb referinele la cele dou tablouri.

Exemplul 3 Deoarece un tablou este un tip referin, transmiterea sa ca argument la invocarea


unei metode se supune regulilor deja cunoscute referitoare la apelul prin valoare.
Astfel, executarea urmtorului program:
class C {
void met(int[] a) {
a[0]=9;
a = new int[5]; for (int i=0; i<5; i++) a[i]=0;
}
}
class Tablou2 {
public static void main(String[] s) {
int[] a = {1,2,3,4};
C Ob = new C(); Ob.met(a);
for (int i=0 ; i<a.length; i++)
System.out.print(a[i]+" ");
}
}
va produce la ieire:
9 2 3 4

Tablouri multidimensionale

Limbajul Java permite lucrul cu tablouri multidimensionale. De exemplu expresia C[][] este un
tip ce reprezint tablouri bidimensionale ale cror componente au tipul C.
Tablourile multidimensionale trebuie gndite ca tablouri unidimensionale ale cror elemente sunt
tablouri unidimensionale etc. De aceea referirea la un element al unui tablou multidimensional a se
face prin:
a[indice1]...[indicen].

22
Este suficient s reducem discuia la tablouri bidimensionale, generalizarea fiind imediat. S
considerm urmtorul exemplu:
int[][] a = new int[3][];
a[0] = new int[3];
a[1] = new int[4];
a[2] = new int[2];

Ia natere astfel un tablou de forma:

ceea ce arat c n Java tablourile nu sunt neaprat dreptunghiulare; aceasta conduce desigur la
economie de spaiu.
Evident, a[1].length=4.
La aceeai structur se poate ajunge i prntr-o iniializare efectiv:
int[][] a = { {0,1,2}, {1,2,3,4}, {2,3} };
care n plus atribuie valori elementelor tabloului.
Dac n referirea la un element al unui tablou unul dintre indici nu este n intervalul corespunztor,
va aprea eroarea (numit n Java excepie) cu numele:
IndexOutOfBoundsException
Reamintim c unei referine la un tablou i se poate asocia o referin la un alt tablou. Astfel, pentru
exemplul de mai sus poate apare n continuare:
a[1] = new int[7];
ceea ce permite s schimbm "o parte" dintr-un tablou fr a defini un altul i a copia prile
comune. De asemenea putem de exemplu s interschimbm dou "linii" ale tabloului de mai sus
prin:
int[] temp;
temp = a[0]; a[0] = a[2]; a[2]= temp;

Aplicaia 1

Scriei o surs Java care aloc un n memorie un tablou bidimensional cu n linii de forma:

1
1 2
1 2 3
. . .
1 2 3 . . . n
package Aplicatii;
import java.util.Scanner;
public class Tablou {
public static void main(String args[])
{
int n, i, j;
Scanner tas=new Scanner(System.n);
System.out.print("n= ");
n=tas.nextInt();

int a[][]=new int[n][];


for(i=0;i<n;i++)

23
{
a[i]=new int[i+1];
for(j=0;j<i+1;j++)
a[i][j]=j+1;
}
for(i=0;i<n;i++)
{
for(j=0;j<i+1;j++)
System.out.print(a[i][j]+" ");
System.out.println();
}
}
}

Aplicaii propuse

1. Scriei o surs Java care interclaseaz doi vectori cu elemente ntregi citite de la tastatur.

2. Fie a un tablou de lungime n. Scriei o metod care deplaseaz elementele vectorului cu p poziii
spre dreapta, unde p este un numr dat de la tastatur.

24
Unitatea de nvare nr. 3

CLASE I OBIECTE

Obiectivele Unitii de nvare nr. 3

Obiective:

Dup ce vei parcurge aceast unitate de nvare, vei reui s:


cunoatei ciclul de viaa al obiectelor;
cunoatei structura unei clase Java;
definii metode membre i constructori.

Clase

Un tip de date primitiv poate fi privit ca o reprezentare a unui concept. De exemplu, tipul
primitiv float, mpreun cu operaiile definite asupra acestuia (+, -, *, etc.) reprezint o
versiune a conceptului matematic de numere cu virgul. Pentru alte concepte, care nu au o
reprezentare direct prin tipurile primitive cunoscute de ctre maina virtuala Java, se pot
defini noi tipuri de date care s specifice aceste concepte. De asemenea, aceste tipuri de date
nu au ntotdeauna o reprezentare unitar. Spre exemplu, o aplicaie pentru realizarea
recensmntului persoanelor ar putea necesita un tip de date Persoana, care s includ
numele persoanei, vrsta, localitatea etc. O alt aplicaie poate necesita tipul de date Persoana
pentru calculul ntreinerii, caz n care se vor lua n calcul pentru acest concept alte
caracteristici, cum ar fi suprafaa locuit, numrul persoanelor aflate n ntreinere etc.

Definirea un nou tip de dat care s modeleze un anumit concept se poate realiza prin
definirea unui tip de dat compus, distinct, care s fie cunoscut mainii virtuale Java. Astfel
de tipuri de date compuse apar prin alturarea de variabile cu tipuri de date deja existente;
spre exemplu, pentru a reprezenta o dat calendaristica, ar putea fi suficient s cream un tip de
date care ncapsuleaz 3 variabile de tip int - pentru zi, luna i an. n schimb, pentru tipul de
date Persoana, este nevoie de o variabila de tip String pentru numele persoanei, una de tip int
pentru vrst etc. Desigur, nu este suficient doar s definim tipul de date abstract prin
compunerea mai multor date de tip primitiv, ci este necesar s se stabileasc i care setul de
operaii ce se va executa asupra datelor componente, precum i care sunt restriciile pentru
fiecare n parte.

O clas reprezint structura unui nou tip de date definit de ctre programator, spre deosebire
de primitive a cror structura este deja cunoscuta compilatorului i mainii virtuale. Pe baza
clasei putem construi obiecte, care sunt date de acel nou tip; crearea de obiecte ale unei clase

25
poarta numele de instaniere a clasei n cauz. Fiecare obiect este o instan (ncarnare) a
clasei, aa cum mai multe aparate de acelai fel pot fi construite pornind de la aceeai schem
electronic. La clase diferite vor corespunde tipuri de obiecte diferite, aa cum din doua
scheme electronice distincte obinem doua tipuri de aparate distincte.

O definiie de clas conine att informaia efectiva ce va fi coninut n obiecte, ct i


modalitile de manevrare a acesteia. Din punct de vedere formal, definiia de clas este
formata din membri ai clasei, care sunt de doua tipuri:
- cmpuri (atribute): reprezint datele coninute de ctre viitoarele obiecte (echivalente cu
lista de piese electronice ce compun un aparat). n exemplul de mai sus, variabilele nume i
vrsta sunt cmpuri ale clasei Persoana;
- metode: funcii definite n cadrul clasei, care au acces la atribute i care permit manevrarea
sigura i eficienta a acestora. O parte dintre ele sunt accesibile oricrui utilizator al obiectului
i formeaz interfaa acestuia cu exteriorul (echivalentul butoanelor pe care apsm n cazul
unui aparat), altele putnd fi inaccesibile n exterior innd de refolosirea interna a codului n
cadrul obiectului.

Clasele reprezint o modalitate de a introduce noi tipuri de date ntr-o aplicaie Java, cealalt
modalitate fiind prin intermediul interfeelor.

Declararea unei clase respecta urmtorul format general:


[<modificatori_acces>] [<modificatori_clasa>] class <nume_clasa>
[<clauze_s>]
{<corpul_clasei>}
unde:
<modificatori_acces> - specifica domeniul de vizibilitate (folosire sau acces) al
clasei; modificatorul de acces este opional i poate fi: public;
<modificatori_clasa> - specifica tipul clasei definite; modificatorul clasei este
opional i poate fi: abstract, final;
<nume_clasa> - specifica numele clasei de obiecte; este de preferat ca numele clasei s
nceap cu o majuscul i daca numele clasei conine n interior mai multe cuvinte, aceste
cuvinte sa nceap cu o majuscul;
<clauze_s> - specifica anumite clauze referitoare la poziia pe care o ocupa clasa n
ierarhia de clase din care face parte (clauza extends) sau daca aceasta clasa folosete o
interfa (clauza inplements); despre aceste clauze vom vorbi ntr-o lecie viitoare;
<corpul_clasei> - variabilele clasei (de instan i de clas) i metodele care lucreaz cu
acestea, numite la un loc membrii clasei.

Modificatorii pentru tipurile de clas


O clasa poate fi:
- abstract, caz n care folosim modificatorul abstract;
- final, caz n care folosim modificatorul final.

n cazul n care declarm o clas de obiecte ca fiind abstract, compilatorul va interzice


instanierea acestei clase, adic nu se permite crearea de obiecte din aceasta clasa.
n cazul n care declaram o clasa de obiecte ca fiind final, compilatorul va interzice ca
pornind de la aceast clas s se defineasc subclase. Vom reveni ntr-o lecie viitoare.

26
Modificatorii de acces

n cazul n care declaram o clasa de obiecte ca fiind publica, atunci aceasta clasa poate fi
folosit (accesat) i din exteriorul pachetului din care face parte.
Daca o clasa nu este declarata ca fiind de tip public atunci ea va putea fi folosit (accesat)
doar de clasele din cadrul aceluiai pachet. Acest tip de acces la o clasa se numete package-
friendly i este implicit n Java.

Nota: Toate clasele care nu fac parte din nici un pachet, sunt considerate automat ca fcnd
parte din acelai pachet implicit. Ca o consecina, accesul de tip friendly se aplica pentru toate
aceste clase. Acesta este motivul pentru care vizibilitatea nu este afectata daca se omite
modificatorul public pentru clasele care nu fac parte dintr-un pachet. Totui, aceasta
modalitate de folosire a accesului de tip friendly nu este recomandat.

Corpul unei clase


Corpul unei clase urmeaz imediat dup declararea clasei i este cuprins ntre acolade.
Coninutul acestuia este format din:
- declararea i, eventual, iniializarea variabilelor de instan i de clas (cunoscute mpreun
ca variabile membre);
- declararea i implementarea constructorilor;
- declararea i implementarea metodelor de instan i de clas (cunoscute mpreun ca
metode membre);
- declararea unor clase imbricate (interne).

class A {
void metoda1(){
// Implementare
}
void metoda2(){
// Implementare
}
}

Constructorii unei clase


Constructorii unei clase sunt metode speciale care au acelai nume cu cel al clasei, nu
returneaz nici o valoare i sunt folosii pentru iniializarea obiectelor acelei clase n
momentul instanierii lor.

class NumeClasa {
[modificatori] NumeClasa([argumente]) { // Constructor}}

O clas poate avea unul sau mai muli constructori care trebuie ns s difere prin lista de
argumente primite. n felul acesta sunt permise diverse tipuri de iniializri ale obiectelor la
crearea lor, n funcie de numrul parametrilor cu care este apelat constructorul.

Exemplul 1

S considerm ca exemplu declararea unei clase care descrie noiunea de dreptunghi i


trei posibili constructori pentru aceast clas.

27
class Dreptunghi {
double x, y, w, h;
Dreptunghi(double x1, double y1, double w1, double h1) {
// Constructor general
x=x1; y=y1; w=w1; h=h1;
System.out.println("Instantiere dreptunghi");
}
Dreptunghi(double w1, double h1) {
// Constructor cu doua argumente
x=0; y=0; w=w1; h=h1;
System.out.println("Instantiere dreptunghi");
}
Dreptunghi() {
// Constructor fr argumente
x=0; y=0; w=0; h=0;
System.out.println("Instantiere dreptunghi");
}
}
Constructorii sunt apelai automat la instanierea unui obiect. n cazul n care dorim sa
apelam explicit constructorul unei clase folosim expresia

this( argumente )

care apeleaz constructorul corespunztor (ca argumente) al clasei respective.


Aceasta metoda este folosita atunci cnd sunt implementai mai muli constructori
pentru o clasa, pentru a nu repeta secvenele de cod scrise deja la constructorii cu mai
multe argumente (mai generali). Mai eficient, fr a repeta aceleai secvene de cod n
toi constructorii (cum ar fi afiarea mesajului Instaniere dreptunghi), clasa de mai
sus poate fi rescris astfel:

Exemplul 2

class Dreptunghi {
double x, y, w, h;
Dreptunghi(double x1, double y1, double w1, double h1) {
// Implementam doar constructorul general
x=x1; y=y1; w=w1; h=h1;
System.out.println("Instantiere dreptunghi");
}
Dreptunghi(double w1, double h1) {
this(0, 0, w1, h1);
// Apelm constructorul cu 4 argumente
}
Dreptunghi() {
this(0, 0);
// Apelm constructorul cu 2 argumente
}
}

Constructorul implicit

Constructorii sunt apelati automat la instantierea unui obiect. n cazul n care scriem o
clasa care nu are declarat nici un constructor, sistemul ii creeaza automat un constructor
28
implicit, care nu primeste nici un argument i care nu face nimic. Deci prezenta
constructorilor n corpul unei clase nu este obligatorie. Daca insa scriem un constructor
pentru o clasa, care are mai mult de un argument, atunci constructorul implicit (fara nici
un argument) nu va mai fi furnizat implicit de ctre sistem. Sa consideram, ca exemplu,
urmatoarele declaratii de clase:

class Dreptunghi {
double x, y, w, h;
// Nici un constructor
}
class Cerc {
double x, y, r;
// Constructor cu 3 argumente
Cerc(double x, double y, double r) { ... };
}

Exemplu 3
Sa consideram acum doua instantieri ale claselor de mai sus:

Dreptunghi d = new Dreptunghi();


// Corect (a fost generat constructorul implicit)
Cerc c;
c = new Cerc();
// Eroare la compilare !
c = new Cerc(0, 0, 100);
// Varianta corecta

Constructorii unei clase pot avea urmatorii modificatori de acces:


public, protected, private i cel implicit.
public: n orice alta clasa se pot crea instante ale clasei respective.
protected : doar n subclase pot fi create obiecte de tipul clasei respective.
private: n nici o alta clasa nu se pot instantia obiecte ale acestei clase. O astfel de
clasa poate contine metode publice care sa fie responsabile cu crearea obiectelor,
controland n felul acesta diverse aspecte legate de instantierea clasei respective.
implicit : doar n clasele din acelasi pachet se pot crea instante ale clasei
respective.

Variabilele membre ale unei clase se declara de obicei inaintea metodelor, desi acest
lucru nu este impus de ctre compilator.
class NumeClasa {
// Declararea variabilelor
// Declararea metodelor
}
Variabilele membre ale unei clase se declara n corpul clasei i nu n corpul unei
metode, fiind vizibile n toate metodele respectivei clase. Variabilele declarate n cadrul
unei metode sunt locale metodei respective.

Declararea unei variabile presupune specificarea urmatoarelor lucruri:


numele variabilei
tipul de date al acesteia
nivelul de acces la acea variabila din alte clase

29
daca este constanta sau nu
daca este variabila de instanta sau de clasa
alti modificatori

Generic, o variabila se declara astfel:


[modificatori] Tip numeVariabila [ = valoareInitiala ];
unde un modificator poate fi :
un modificator de acces : public, protected, private;
unul din cuvintele rezervate: static, final, transient, volatile;

Exemple de declaratii de variabile membre:


class Exemplu {
double x;
protected static int n;
public String s = "abcd";
private Point p = new Point(10, 10);
final static long MAX = 100000L;
}

Modificatori:
static
Prezenta lui declara ca o variabila este variabila de clasa i nu de instanta.
int variabilaInstanta ;
static int variabilaClasa;
final
Indica faptul ca valoarea variabilei nu mai poate fi schimbata, cu alte cuvinte este folosit
pentru declararea constantelor.
final double PI = 3.14 ;
...
PI = 3.141; // Eroare la compilare !

Prin conventie, numele variabilelor finale se scriu cu litere mari. Folosirea lui final
aduce o flexibilitate sporita n lucrul cu constante, n sensul ca valoarea unei variabile
nu trebuie specificata neaparat la declararea ei (ca n exemplul de mai sus), ci poate fi
specificata i ulterior intr-un constructor, dupa care ea nu va mai putea fi modificata.

class Test {
final int MAX;
Test() {
MAX = 100; // Corect
MAX = 200; // Eroare la compilare !
}
}

30
Implementarea metodelor

Metodele sunt responsabile cu descrierea comportamentului unui obiect. Intrucat Java este un
limbaj de programare complet orientat-obiect, metodele se pot gasi doar n cadrul claselor.
Generic, o metoda se declara astfel:
[modificatori] TipReturnat numeMetoda ( [argumente] )
[throws TipExceptie1, TipExceptie2, ...]
{
// Corpul metodei
}
unde un modificator poate fi :
un specificator de acces : public, protected, private
unul din cuvintele rezervate: static, abstract, final, native, synchronized;

Modificatorii care pot fi specificati pentru o metoda:


static
Prezenta lui declara ca o metoda este de clasa i nu de instanta.
void metodaInstanta();
static void metodaClasa();

abstract
Permite declararea metodelor abstracte. O metoda abstracta este o metoda care nu are
implementare i trebuie obligatoriu sa faca parte dntr-o clasa abstracta.

final
Specifica faptul ca acea metoda nu mai poate fi supradefinita n subclasele clasei n care
ea este definita ca fiind finala. Acest lucru este util daca respectiva metoda are o
implementare care nu trebuie schimbata sub nici o forma n subclasele ei, fiind critica
pentru consistent starii unui obiect. De exemplu, studentilor unei universitati trebuie sa
li se calculeze media finala, n functie de notele obtinute la examene, n aceiai maniera,
indiferent de facultatea la care sunt.
class Student {
...
final float calcMedie(float note[], float ponderi[]) {
...
}
...
}
class StudentInformatica extends Student {
float calcMedie(float note[], float ponderi[]) {
return 10.00;
}
}// Eroare la compilare !

Apelul metodelor

Apelul unei metode definita ntr-o clasa de obiecte se realizeaza n mai multe moduri:
- prin crearea i utilizarea unei instante a clasei n care a fost definita metoda sau a unei
subclase a clasei respective (ca regula generala de invocare a unei metode); n acest caz se

31
foloseste operatorul punct ( . ), n stinga acestuia punandu-se numele instantei, iar n dreapa
acestuia punandu-se numele metodei;
- prin simpla folosire a numelui sau, n cazul n care clasa n care este apelata metoda este
aceiai cu clasa n care a fost definita; aceasta modalitate este folosita daca atat metoda
apelanta ct i metoda apelata sunt fie numai metode de instanta, fie numai metode de clasa;
- prin folosirea operatorului punct ( . ), n stanga acestuia punandu-se numele clasei n care a
fost definita, iar n dreapta acestuia punandu-se numele metodei; aceasta modalitate este
folosita numai daca metoda este definita ca metoda de clasa.

Exemplu 4

Programele urmatoare (ClasaTablou1.java i ClasaTablou2.java) prezinta un exemplu


de creare a unei clase care defineste o metoda numita creareTablou. Acesta preia doua
numere naturale (o limita inferioara i una superioara) i creaza un tablou
unidimensional care contine toate numerele naturale aflate intre cele doua limite,
inclusiv aceste limite.
Varianta de apel a unei metode prin crearea i utilizarea unei instante a clasei n care a
fost definita metoda.
public class ClasaTablou1 {
int [] creareTablou(int inf, int sup) {
int [] tabl = new int[(sup - inf) +1];
for (int i = 0 ; i < tabl.length; i++)
tabl[i] = inf++;
return tabl; }
public static void main(String args[]) {
ClasaTablou1 unTablou = new ClasaTablou1();
int [] tablou = unTablou.creareTablou(1,10);
System.out.print("Tabloul: [ ");
for (int i = 0; i < tablou.length; i++)
System.out.print(tablou[i] + " ");
System.out.println("]");}
}

Varianta de apel a unei metode prin simpla folosire a numelui metodei, deoarece metoda este
definita i apelata n aceiai clasa. Totusi metoda creareTablou trebuie sa fie declarata ca
metoda de clasa (modificatorul static) pentru a putea fi apelata dntr-o alta metoda de clasa.
public class ClasaTablou2 {
static int [] creareTablou(int inf, int sup){
int [] tabl = new int[(sup - inf) +1];
for (int i = 0 ; i < tabl.length; i++)
tabl[i] = inf++;
return tabl;
}
public static void main(String args[])
{
int [] tablou = creareTablou(1,10);
System.out.print("Tabloul: [ ");
for (int i = 0; i < tablou.length; i++)
System.out.print(tablou[i] + " ");
System.out.println("]");
}
}
32
Metode de instanta

Ca regula generala, o metoda definita ntr-o clasa se poate apela prin crearea unei
instante a clasei respective sau a unei subclase a clasei respective. Aceasta se datoreaza
faptului ca metoda lucreaza cu o serie de variabile ale clasei care sunt memorate n
interiorul instantei i care au valori diferite n instante diferite (numite variabile de
instanta). Astfel de metode se numesc metode ale instantelor clasei.

Metodele de instanta sunt aplicate unui anume obiect, nu unei clase intregi. Majoritatea
metodelor definite ntr-o clasa sunt metode de instanta.

Metode de clasa

Dupa cum stim deja, exista i un alt tip de variabile i anume variabilele de clasa sau
variabilele statice care sunt comune tuturor instantelor clasei respective. Aceste
variabile pot fi accesate fara a avea nevoie de o instanta a clasei n care au fost
declarate.
n mod similar exista i metode de clasa sau metode statice. Pentru a fi apelate, aceste
metode, definite ntr-o clasa, nu au nevoie sa fie creata o instanta a clasei respective sau
a subclasei derivata din clasa respectiva. Metodele de clasa sunt disponibile oricarei
instante a clasei.

Domeniul de vizibilitate (acces) al metodelor unei clase. Modificatori de acces

O metoda este accesibila (apelabila) daca este definita n clasa din care este apelata sau
intr-una din subclasele acesteia. Atunci cand se apeleaza metoda unui obiect, Java cauta
definitia metodei respective n clasa obiectului. Daca nu o gaseste, cauta mai sus n
ierarhia de clase pana cand gaseste o definitie.
n acelasi timp pentru a vedea o metoda i pentru a o putea apela, este nevoie sa avem
drepturile de acces necesare (date de modificatorii de acces).

Modificatorii de acces (vizibilitate) ai metodelor unei clase


n Java exista trei modificatori de vizibilitate ai variabilelor unei clase:
- modificatorul public;
- modificatorul protected;
- modificatorul private.

Modificatorul public face ca metoda respectiva sa fie accesibila oriunde este accesibila
clasa din care face parte metoda.

Modificatorul protected face ca metoda respectiva sa fie accesibila n orice clasa din
pachetul careia ii apartine clasa n care a fost definita. n acelasi timp, metoda este
accesibila n toate subclasele clasei date, chiar daca ele apartin altor pachete.

Modificatorul private face ca metoda respectiva sa fie accesibila doar n interiorul clasei
n care a fost definita.

Daca pentru o metoda a unei clase nu se precizeaza nici un modificator de acces din cei
descrisi mai sus, atunci metoda respectiva devine package-friendly. O metoda
friendly este accesibila n pachetul din care face parte clasa n interiorul careia a fost
definita, dar nu este accesibila n subclasele clasei date daca acestea apartin altor
pachete.

33
Nota: Modificatorii de acces (public, protected, private) sunt plasati primii n definitia
metodei, urmeaza apoi modificatorii care determina felul metodei (static, abstract,
final) i apoi semnatura metodei.

Urmatorul program (TestCerc.java) ilustreaza modul de folosire al variabilelor de


instanata, precum i al metodelor de instanta. n clasa Cerc variabila de instanta este
raza care este vizibila numai n clasa n care a fost declarata (are modificatorul private).
De aceea, accesul la aceasta variabila (pentru examinare i modificare) se face numai
prin intermediul metodelor setRaza i getRaza care sunt publice.

class Cerc
{
private double raza;
public void setRaza(double r) {
raza = r; }
public double getRaza() {
return raza; }
public double arie() {
return Math.PI * raza * raza; }
public double lungime() {
return 2 * Math.PI * raza; }
}
public class TestCerc
{
public static void main(String[] args) {
Cerc cerculMeu = new Cerc();
cerculMeu.setRaza(10);
System.out.println("Raza=" + cerculMeu.getRaza());
System.out.println("Aria=" + cerculMeu.arie());
System.out.println("Lungimea=" +
cerculMeu.lungime());
}
}
Observatie: Deoarece fisierul-sursa TestCerc.java contine o clasa publica, TestCerc,
numele fisierului trebuie sa fie identic cu numele clasei publice, altfel compilarea nu se
va face cu succes. Intr-un fisier-sursa nu se poate defini decat o singura clasa publica.

Referinta this

Cuvantul-cheie this se refera la obiectul curent, adica obiectul a carei metoda a fost
apelata. Metoda poate folosi variabilele de instanta ale obiectului curent sau poate
transmite obiectul curent ca parametru unei alte metode. Iata cateva exemple de folosire
a cuvantului this:
t = this.x; // variabila de instanta x pentru acest obiect
this.resetRaza(this); // apeleaza metoda resetRaza, definita n clasa
curenta i
// transmite obiectul curent
return this; // returneaza obiectul curent

n cele mai multe cazuri nu este nevoie sa se foloseasca explicit cuvantul-cheie this,
deoarece este presupus. De exemplu, ne putem referi atat la variabilele de instanta, ct i

34
la apelurile de metode definite n clasa curenta prin simpla folosire a numelui lor,
deoarece this este implicit folosit de aceste referinte.
De aceea, primele doua exemple se pot rescrie astfel:
t = x; // variabila de instanta x pentru acest obiect
resetRaza(this); // apeleaza metoda resetRaza, definita n clasa curenta

Nu se omite cuvantul-cheie this daca n domeniul de vizibilitate al obiectului curent au


fost definite variabile locale cu acelasi nume ca cel al unei variabile de instanta sau au
fost transmisi unei metode, a obiectului curent, parametrii cu acelasi nume ca cel al unei
variabile de instanta. Aceste aspecte au fost explicate la paragraful referitor la domeniul
de vizibilitate al variabilelor clas

Crearea obiectelor
n Java, ca n orice limbaj de programare orientat-obiect, crearea obiectelor se
realizeaza prin instantierea unei clase i implica urmatoarele etape:

Declararea

Presupune specificarea tipului acelui obiect, cu alte cuvinte specificarea clasei acestuia
NumeClasa numeObiect;

Instantiere

Se realizeaza prin intermediul operatorului new i are ca efect crearea efectiva a


obiectului cu alocarea spatiului de memorie corespunzator.
numeObiect = new NumeClasa();

Initializarea

Se realizeaza prin intermediul constructorilor clasei respective. Initializarea este de fapt


parte integranta a procesului de instantiere, n sensul ca imediat dupa alocarea memoriei
ca efect al operatorului new este apelat constructorul specificat. Parantezele rotunde de
dupa numele clasei indica faptul ca acolo este de fapt un apel la unul din constructorii
clasei i nu simpla specificare a numelui clasei.
Mai general, instantierea i initializarea apar sub forma:
numeObiect = new NumeClasa([argumente constructor]);

Sa consideram urmatorul exemplu, n care declaram i instantiem doua obiecte din clasa
Rectangle, clasa ce descrie suprafete grafice rectangulare, definite de coordonatele
coltului stanga sus (originea) i latimea, respective inaltimea.

Rectangle r1, r2;


r1 = new Rectangle();
r2 = new Rectangle(0, 0, 100, 200);

n primul caz Rectangle() este un apel ctre constructorul clasei Rectangle care este
responsabil cu initializarea obiectului cu valorile implicite. Dupa cum observam n al
doilea caz, initializarea se poate face i cu anumiti parametri, cu conditia sa existe un
constructor al clasei respective care sa accepte parametrii respectivi.

35
Fiecare clasa are un set de constructori care se ocupa cu initializare obiectelor nou
create. De exemplu, clasa Rectangle are urmatorii constructori:

public Rectangle()
public Rectangle(int latime, int inaltime)
public Rectangle(int x, int y, int latime, int inaltime)
public Rectangle(Point origine)
public Rectangle(Point origine, int latime, int inaltime)
public Rectangle(Point origine, Dimension dimensiune)

Declararea, instantierea i initializarea obiectului pot aparea pe aceiai linie (cazul cel
mai uzual):
Rectangle patrat = new Rectangle(0, 0, 100, 100);

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. Aceste lucruri se
realizeaza prin aflarea sau schimbarea valorilor variabilelor sale, respectiv prin apelarea
metodelor sale.
Referirea valorii unei variabile se face prin obiect.variabila De exemplu clasa Rectangle
are variabilele publice x, y, width, height, origin.

Aflarea valorilor acestor variabile sau schimbarea lor se face prin constructii de genul:
Rectangle patrat = new Rectangle(0, 0, 100, 200);
System.out.println(patrat.width); //afiseaza 100
patrat.x = 10;
patrat.y = 20; //schimba originea
patrat.origin = new Point(10, 20); //schimba originea

Accesul la variabilele unui obiect se face n conformitate cu drepturile de acces pe care


le ofera variabilele respective celorlalte clase.

Apelul unei metode se face prin obiect.metoda([parametri]).


Rectangle patrat = new Rectangle(0, 0, 100, 200);
patrat.setLocation(10, 20); //schimba originea
patrat.setSize(200, 300); //schimba dimensiunea

Se observa ca valorile variabilelor pot fi modificate indirect prin intermediul metodelor


sale. Programarea orientata obiect descurajeaza folosirea directa a variabilelor unui
obiect deoarece acesta poate fi adus instari inconsistente. n schimb, pentru fiecare
variabila care descrie starea obiectului trebuie sa existe metode care sa permita
schimbarea/aflarea valorilor variabilelor sale.
Acestea se numesc metode de accesare, sau metode setter - getter i au numele de forma
setVariabila, respectiv getVariabila.
patrat.width = -100; //stare inconsistenta
patrat.setSize(-100, -200); //metoda setter
//metoda setSize poate sa testeze daca noile valori sunt
//corecte i sa valideze sau nu schimbarea lor

36
Rolul operatorului new
La folosirea operatorului new se execut urmatoarele:
- se creaza o noua instanta a clasei date;
- se aloca memorie pentru aceasta instanta;
- se apeleaza o metoda speciala a clasei numita constructor.

Constructorii reprezinta metode speciale pentru crearea i initializarea noilor instante


ale claselor. Constructorii initializeaza noul obiect i variabilele sale, creaza orice alte
obiecte de care are nevoie obiectul creat i realizeaza orice alte operatii de care obiectul
are nevoie la initializarea sa.
ntr-o clasa pot exista mai multe definitii de constructori, fiecare avand un numar diferit
de argumente sau de tipuri.
Cand se foloseste operatorul new, se pot specifica diferite argumente n lista de
argumente i va fi apelat constructorul corespunzator pentru acele argumente.
ntr-o clasa pot fi definiti oricati constructori se doresc pentru a implementa
comportamentul clasei.

Distrugerea obiectelor

Multe limbaje de programare impun ca programatorul sa tina evidenta obiectelor create


i sa le distruga n mod explicit atunci cand nu mai este nevoie de ele, cu alte cuvinte sa
administreze singur memoria ocupata de obiectele sale.

n Java programatorul nu mai are responsabilitatea distrugerii obiectelor sale intrucat, n


momentul rularii unui program, simultan cu interpretorul Java, ruleaza i un proces care
se ocupa cu distrugerea obiectelor care nu mai sunt folosite. Acest proces pus la
dispozitie de platforma Java de lucru se numeste garbage collector (colector de
gunoi), prescurtat gc.

Aplicaie 1 Construii un proiect Java care cuprinde ntr-un pachet Clase o clas care
modeleaz noiunea student. Clasa conine date membre precum: nume,
medie. ntr-un pachet de aplicaii, scriei o surs Java care n care definii un
obiect de tip Student. n acelai pachet de aplicaii scriei o surs Java care
definete un tablou de obiecte de tip Student i afieaz n fereastra System
numrul obiectelor instantiate.

package Clase;

public class Student {


private String nume;
private double medie;
private static int nrObiecte;

public Student(String nume, double medie) {


this.nume = nume;
this.medie = medie;
nrObiecte++;
}

public Student() {
this.nume="####";
this.medie=0.0;

37
nrObiecte++;

}
public String getNume() {
return nume;
}

public void setNume(String nume) {


this.nume = nume;
}

public double getMedie() {


return medie;
}

public void setMedie(double medie) {


this.medie = medie;
}

public String toString()


{
return this.nume+" "+this.medie;
}

public static int getNrObiecte()


{
return nrObiecte;
}
}

Sursa Java

package Clase;
import Clase.Student;

public class Instanta {


public static void main(String args[]){
Student ob1=new Student();
Student tb[]=new Student[10];
for(int i=0;i<2;i++)
tb[i]=new Student();
System.out.println(Student.getNrObiecte());
}}

Aplicatie propus

Construii un proiect Java care cuprinde ntr-un pachet Surse o clas care modeleaz noiunea de
angajat al firmei BestIT. Clasa conine date membre precum: nume, varsta, firma, salariu. ntr-un
pachet de aplicaii, scriei o surs Java care n care definii un obiect de tip Angajat. Testai pentru
obiectul creat metodele motenite din clasa Object. n acelai pachet de aplicaii scriei o surs Java
care definete un tablou de obiecte de tip Angajat i afieaz n fereastra System ci angajai sunt
ntr-un stagiu de internship. Un angajat se consider a fi ntr-un stagiu de internship dac are vrsta
mai mica dect 25.

38
Tema de autoinstruire

1. Care este diferena dintre un constructor i o metod i la ce poate fi folosit un


constructor ?

2. Dac C este o clas fr un constructor definit, avnd un cmp x de tip ntreg, scriei
instruciunile prin care se creeaz un obiect ob de tip C i se afieaz valoarea cmpului
x al obiectului ob.

3. Cum se numete posibilitatea de a exista mai muli constructori, respectiv mai multe
metode cu acelai nume, dar cu signaturi diferite? Exemplificai.

4. Ce afieaz urmtorul program ? Justificai.


class Pereche{
int x, y;
Pereche (int x1, int y1){x=x1 ; y=y1 ;}
void afis(){ System.out.println(re+" "+im);}
}

class Doi{
void modific(int x){x=2;}
void modific(Pereche c){c.im=2;}
}

class M {
public static void main(String sir[]){
Doi d=new Doi();
Pereche c=new Pereche(5,6); c.afis();
d.modific(c.re); c.afis();
d.modific(c);c.afis();
}
}

Teste de control
1. Declararea constructorilor trebuie sa tina cont de:
A. relatia de motenire dintre clase;
B. numele constructorului, care trebuie sa fi identic cu numele clasei;
C. comportamentul obiectelor pe care le instantiaza;
D. o metoda prin care poate fi accesat de toate tipurile din Java sau de tipuri mostenite
din tipul care contine membrul n discutie;

2. Ce puteti spune despre urmatorul program Java?


class C1{
int x=1;
void f(int x){

39
this.x=x;
}
int getX_C1(){
Return x;}}
Class C2 extens C1{
float x=5.0f;
int f(int x){
super.f((int)x);}
float getX_C2(){
return x;}}
public class Subiect9{
public static void main(String []args){
C2 obiect = new C2();
obiect.f(4);
System.out.print(obiect.getX_C2() + " ");
System.out.println(obiect.getX_C1());}}
A. Programul este corect i va afisa la executie 5 4;
B. Programul este corect i va afisa la executie 4.0 4;
C. Va aparea eroare la compilare deoarece n clasa C2 s-a suprascris gresit atributul x
din clasa C1;
D. Va aparea eroare la compilare deoarece metoda suprascrisa f() din clasa C2 intoarce
un tip diferit de void;

3. Ce putet i spune despre urmatorul program Java?


public class Test{
public static void main(String []args){
C1 obiect =new C1();
obiect.f(4,3);
}}
class C1{
public void f(int xx, final int yy){
int a=xx+yy;
final int b=xx-yy;
class C2{
public void g(){
System.out.print("a= "+a);
System.out.print(", b= "+b);
}}
C2 obiect2 = new C2();
obiect2.g();}}
A. Programul este corect i va afisa la executie a=4, b=3;
B. Va aparea eroare la compilare, deoarece clasa C2 nu poate fi defnita n metoda f()
din clasa C1;
C. Va aparea eroare la compilare deoarece n metoda g() nu putem accesa variabila
locala a din metoda f();
D. Va aparea eroare la compilare deoarece nu se creeaza n clasa Test un obiect de tip
C1.C2

4. Ce puteti spune despre urmatorul program Java?


class C1{
int x=1;
void f(int x){
this.x=x;
40
}
int getX_C1(){
Return x;
}
}
Class C2 extens C1{
float x=5.0f;
int f(int x){
super.f((int)x);
}
float getX_C2(){
return x;
}
}
public class Subiect9{
public static void main(String []args){
C2 obiect = new C2();
obiect.f(4);
System.out.print(obiect.getX_C2() + " ");
System.out.println(obiect.getX_C1());
}}
A. Programul este corect i va afisa la executie 5 4;
B. Programul este correct i va afisa la executie 4.0 4;
C. Va aparea eroare la compilare deoarece n clasa C2 s-a suprascris gresit atributul x
din clasa C1;
D. Va aparea eroare la compilare deoarece metoda suprascrisa f() din clasa C2 intoarce
un tip diferit de void;

41
Unitatea de nvare nr. 4

LUCRUL CU IRURI DE CARACTERE

Obiectivele Unitii de nvare nr. 4

Obiective:

Dup ce vei parcurge aceast unitate de nvare, vei reui:


s utilizai aplicaii cu iruri de caractere
s utilizai metode ale claei String

irurile (de caractere) din Java sunt obiecte standard. Orice ir este un obiect al clasei String, ce
apare n pachetul java.lang:
public final class String extends Object

Cunoatem deja civa operatori pentru lucrul cu iruri:


- operatorul +, folosit pentru concatenare:
- operatorul +=, ce creeaz un nou ir prin concatenarea irului din stnga operatorului cu irul din
dreapta sa.
Un (obiect de tip) ir nu poate fi modificat (este "read-only") dar, prin utilizarea metodelor clasei
String putem obine pe baza lui noi iruri.

Clasa String conine constructorii:


public String() i public String(String s)
care permit s construim un nou ir iniializat cu irul vid, respectiv cu irul s.

Toate metodele clasei String au modificatorul de acces public. Trecem la prezentarea


ctorva dintre ele.

Metodele eseniale ale clasei String sunt:


int length() : ntoarce lungimea irul curent (care a invocat metoda);
char charAt(int i): ntoarce caracterul de pe poziia i din irul curent.

S observm diferenele fa de lucrul cu tablouri. Dac s este un ir, iar a un tablou, atunci:
- s.length() este lungimea irului, iar a.length este lungimea tabloului;
- s.charAt(i) este caracterul de pe poziia i din ir, iar a[i] este elementul de pe
poziia i din tablou.

42
Invocarea metodei charAt cu un indice n afara irului lanseaz excepia:
IndexOutOfBoundsException. Aceast excepie mai poate fi lansat i de alte metode
prezentate n continuare (identificarea lor se face cu uurin).

Metode pentru aflarea unui indice din ir

Urmtoarele metode ale clasei String ntorc un rezultat de tipul int, ce reprezint o poziie cu o
anumit proprietate din irul s prin care au fost invocate (dac o astfel de poziie nu exist, este
ntoars valoarea 1).

Metod ntoarce indicele din ir de pe


indexOf(char ch) prima poziie pe care apare ch
indexOf(char ch, int p) prima poziie, mai mare sau egal cu p,
pe care apare ch
indexOf(String sub) prima poziie ncepnd de la care apare
irul sub
indexOf(String sub, int p) prima poziie, mai mare sau egal cu p,
ncepnd de la care apare irul sub
lastIndexof(char ch) ultima poziie pe care apare ch
lastIndexof(char ch, int u) ultima poziie, cel mult egal cu u, pe
care apare ch
lastIndexOf(String sub) ultima poziie de la care apare irul sub
lastIndexof(String sub,int ultima poziie, cel mult egal cu u,
u) ncepnd de la care apare irul sub

Exemplul 1

Urmtorul program citete dou iruri i determin numrul de apariii al celui de al doilea n
primul. irurile sunt introduse la executare din linia de comand.

class nr_apar {
static int nrapar(String s, String subs) {
int nr=0, indice, poz=0;
indice = s.indexOf(subs,poz);
while (indice>=0 && indice<s.length()) {
nr++; poz++;
indice = s.indexOf(subs,poz);
}
return nr;
}

public static void main(String[] s) {


System.out.println( "" + nrapar(s[0],s[1]) );
}
}

43
Compararea irurilor

Clasa String prevede metode pentru compararea coninutului irului care invoc metoda cu
coninutul unui ir transmis ca argument. Vom presupune c irul care invoc metodele este s.
Compararea se refer la iruri n totalitatea lor sau la subsecvene ale lor.

Compararea se face conform ordinii lexicografice: compararea a dou caractere const n


compararea numerelor lor de ordine n setul de caractere Unicode.

boolean equals(String s1) :


ntoarce true dac irurile coincid;
int compareTo(String s1) :
ntoarce o valoare negativ (dac s<s1), zero (dac s=s1) sau o valoare pozitiv (dac
s>s1);
boolean regionMatches(int p, String s1, int p1, int lung) :
compar secvenele de lungime lung ce ncep n s de pe poziia p, respectiv n s1 de pe poziia
p1; este ntoars valoarea True dac i numai dac aceste secvene coincid;
boolean startsWith(String pre) : ntoarce True dac irul pre este prefix al lui s i
False altfel;
boolean endsWith(String suf) : ntoarce True dac irul suf este sufix al lui s i False
altfel.

S remarcm c metoda equals nu poate fi suplinit de operatorul == deoarece prin s==s1 se


compar dou referine i nu coninutul lor.

O alt modalitate de a compara iruri este furnizat de metoda:


String intern()
care ntoarce un ir cu acelai coninut ca cel al irului care invoc metoda, avnd n plus
urmtoarea proprietate: pentru orice dou iruri cu acelai coninut, valoarea ntoars de metoda
intern este aceeai. Drept urmare putem verifica dac dou iruri au acelai coninut prin:
s1.intern() == s2.intern()
care este mai rapid dect:
s1.equals(s2).

Determinarea unui subir cu o anumit proprietate

Metodele clasei String ce se ncadreaz aici sunt urmtoarele (vom presupunde din nou c irul care
invoc metoda este notat prin s):
String substring(int p) :
este ntors subirul lui s ce ncepe de pe poziia p;
String substring(int p, int u) :
este ntors subirul lui s ce ncepe de pe poziia p i se termin pe poziia u-1;
String replace(char c1, char c2) :
este ntors irul obinut din s prin nlocuirea tuturor caracterelor c1 prin caracterul c2;
String toUpperCase() :
fiecare caracter este nlocuit cu echivalentul su majuscul, dac acesta exist;
String toLowerCase() :
fiecare "liter mic" este nlocuit cu "liter mare", dac aceast coresponden exist;
String trim() :
ntoarce irul obinut din s prin eliminarea spaiilor albe de la nceputul i sfritul su;
String concat(String s1) :
ntoarce irul s+s1.
44
iruri i tablouri de caractere

Clasa String prevede metode pentru transformarea irurilor n tablouri de caractere, precum i
pentru transformarea invers:

Metoda toCharArray() invocat de un ir s ntoarce un tablou de caractere de aceeai lungime


i cu aceleai elemente.

Metoda static copyValueOf are dou forme:


String copyValueOf(char[] a)
String copyValueOf(char[] a, int p, int lung)
i ntoarce irul corespunztor tabloului a de caractere, respectiv numai acea secven din tablou ce
ncepe pe poziia p i are lungimea lung.

Exemplu 2

Pentru a determina irul obinut din irul s prin considerarea elementelor sale n ordine invers,
putem scrie urmtoarea metod:

public static String invers(String s) {


char c;
char[] a = s.toCharArray();
for (int p=0,u=a.length-1; p<u; p++,u--) {
c=a[p]; a[p]=a[u]; a[u]=c;
}
return String.copyValueOf(a);
}

Conversii

n multe cazuri suntem pui n situaia de a converti valori numerice n iruri sau de a trebui s
lucrm cu o valoare numeric memorat ntr-un ir.

irul ce corespunde unei valori numerice sau booleene x se obine simplu prin:
String.valueOf(x)

Metoda valueOf a clasei String mai poate fi invocat i pentru un caracter: va fi ntors irul
format din acel unic caracter.

Transformarea invers (de la un ir ce conine un literal boolean sau numeric) la acel literal se poate
realiza folosind metodele puse la dispoziie de clasele nfurtoare.

45
Aplicaii propuse

1. Scriei o surs Java care citete un ir de caractere de la tastatur i care realizeaz urmtoarele
cerine:
a. Afiez pe ecran numrul cuvintelor (acestea pot fi separate prin diferite semne de
punctuaie)
b. Sorteaz n ordine descresctoare cuvintele irului.
c. nlocuiete toate cuvintele de lugime maxim cu cele de lungime minima

2. Scriei o surs Java care citete dntr-o fereastr de dialog CNP-ul unei persoane i afieaz
vrsta acesteia.

3. Scriei o aplicaie Java care, pentru un cuvnt dat de la tastatur afieaz numrul de vocale din
cuvnt i cea mai lung subsecven de consoane (consecutive) din cuvnt.

4. Scriei o surs Java care verific dac dou iruri sunt anagrame

46
Unitatea de nvare nr. 5

EXTINDEREA CLASELOR

Obiectivele Unitii de nvare nr. 5

Dup ce vei parcurge aceast unitate de nvare, vei reui s:

nelegei noiunile fundamentale legate de extinderea claselor;


Aprofundai modul n care sunt apelate cmpurile i metodele n
funcie de tipul declarat i tipul real al unui obiect (polimorfism i
legare dinamic);
Implementai clase derivate din alte clase.

Aa cum am menionat de la nceput, limbajul Java a fost conceput ca un limbaj orientat pe obiecte.
Am prezentat deja una dintre caracteristicile orientrii spre obiecte i anume ncapsularea (datele
mpreun cu operaiile asupra lor sunt "puse la un loc" i anume ntr-o clas).
Vom studia acum modul n care Java trateaz alte aspecte ale programrii orientate pe obiecte:
extinderea claselor, polimorfismul i legarea dinamic.

Cum se definesc clasele extinse


Limbajul Java pune la dispoziie i o alt facilitate important legat de OOP (programarea
orientat pe obiecte): posibilitatea de extindere a claselor. Foarte pe scurt, deci incomplet i nu n
ntregime riguros, aceasta const n:
- o clas poate fi extins, adugndu-se noi cmpuri i noi metode, care permit considerarea unor
atribute suplimentare (dac ne gndim la cmpuri) i unor operaii noi (asupra cmpurilor "iniiale",
dar i asupra cmpurilor nou adugate);
- unele metode ale clasei pe care o extindem pot fi redefinite, iar anumite cmpuri ale acestei clase
pot fi "ascunse";
- un obiect avnd ca tip clasa extins poate fi folosit oriunde este ateptat un obiect al clasei care a
fost extins.

La prima vedere, rezolvarea problemelor de mai sus se poate face simplu: modificm clasa,
introducnd sau/i modificnd cmpurile i metodele clasei. n practica programrii, aceast soluie
este de neconceput. Pe de o parte se pot introduce erori, iar pe de alt parte utilizatorii clasei vechi
nu vor mai putea folosi clasa aa cum o fceau nainte i cum vor n continuare s o fac, nefiind
interesai de noile faciliti; clasa (firma care a elaborat-o) i va pierde astfel vechii clieni. De
aceea vechea clas trebuie s rmn nemodificat, iar actualizarea ei trebuie fcut prin
mecanismul de extindere a claselor, prezentat n continuare.

S reinem deci ca o regul general de programare faptul c nu trebuie modificat o clas testat i
deja folosit de muli utilizatori; cu alte cuvinte, nu trebuie modificat "contractul" ce a dus la
scrierea clasei.

47
Un prim exemplu

Exemplul 1 S presupunem c dorim s urmrim micarea unui punct n plan. Vom ncepe
prin a considera clasa:

class Punct {
int x,y; Punct urm;
Punct(int x, int y) { this.x=x; this.y=y; }
void Origine() { x=0; y=0; }
Punct Miscare(int x, int y) {
Punct p = new Punct(x,y); urm=p; return p;
}
}

Clasa Punct conine:


- cmpurile x, y, urm ;
- constructorul Punct cu signatura (int, int);
- metoda Origine cu signatura () i metoda Miscare cu signatura (int,int).

Vom extinde clasa Punct astfel nct punctul s aib i o culoare:

class Pixel extends Punct {


String culoare;
Pixel(int x, int y, String culoare) {
super(x,y); this.culoare=culoare;
}
void Origine() { super.Origine(); culoare="alb"; }
}

Clasa Pixel conine:


- cmpurile x,y,urm (motenite de la clasa Punct) i culoare (care a fost adugat prin
extindere);
- constructorul Pixel cu signatura (int,int,String);
- metoda Miscare cu signatura (int,int), motenit de la clasa Punct, precum i metoda
Origine cu signatura (), care redefinete metoda Origine a clasei Punct.

Este adoptat urmtoarea terminologie: clasa Punct este superclas a lui Pixel, iar Pixel este
subclas (clas extins) a lui Punct.

n Java, clasele formeaz o structur de arbore n care rdcina este clasa Object, a crei definiie
apare n pachetul java.lang. Orice clas extinde direct (implicit sau explicit) sau indirect clasa
Object. tim c n informatic arborii "cresc n jos", deci rdcina (clasa Object) se afl pe cel
mai de sus nivel.

Termenii de superclas i subclas se refer exclusiv la relaia tat fiu, conform relaiei de
extindere, n arborele de clase. Este incorect de a interpreta aceti termeni n sensul de incluziune!

n exemplul de mai sus, apelurile super.Origine() i super(x,y) se refer respectiv la


metoda Origine i la constructorul din superclasa Punct a lui Pixel. Vom reveni ns cu toate
detaliile legate de super.
48
Fie Sub o clas ce extinde clasa Super. Sunt importante urmtoarele precizri:
- obiectele de tip Sub pot fi folosite oriunde este ateptat un obiect de tipul Super. De exemplu
dac un parametru al unei metode este de tipul Super, putem invoca acea metod cu un argument
de tipul Sub;
- spunem c Sub extinde comportarea lui Super;
- o clas poate fi subclas a unei singure clase (motenire simpl) deoarece, reamintim, clasele
formeaz o structur de arbore. Drept consecin o clas nu poate extinde dou clase, deci nu exist
motenire multipl ca n alte limbaje (exist ns mecanisme pentru a simula aceast facilitate i
anume interfeele);
- o metod din superclas poate fi rescris n subclas. Spunem c metoda este redefinit (dac nu
este static) sau ascuns (dac este static). Evident, ne referim aici la o rescriere a metodei
folosind aceeai signatur, pentru c dac scriem n subclas o metod cu o signatur diferit de
signaturile metodelor cu acelai nume din superclas, atunci va fi vorba de o metod nou. La
rescriere nu putem modifica tipul valorii ntoarse de metod. Accesul la metoda cu aceeai signatur
din superclas se face, dup cum vom vedea, prin precalificare cu super;
- un cmp redeclarat n Sub ascunde cmpul cu acelai nume din Super;
- cmpurile neascunse i metodele nerescrise sunt automat motenite de subclas (n exemplul de
mai sus este vorba de cmpurile x i y i de metoda Miscare);
- apelurile super din constructorii subclasei trebuie s apar ca prim aciune.

Rescrierea metodelor i ascunderea cmpurilor


Cmpurile pot fi ascunse prin redeclararea lor ntr-o subclas. Cmpul cu acelai nume din
superclas nu mai poate fi accesat direct prin numele su, dar ne putem referi la el folosind super
(vezi subcapitolul urmtor) sau o referin la tipul superclasei.

O metod declarat ntr-o clas poate fi rescris ntr-o subclas prin declararea ei n subclas cu
acelai nume, aceeai signatur i acelai tip al valorii ntoarse. n metoda rescris putem schimba
modificatorul de acces, cu condiia ca dreptul de acces s creasc; reamintim c modificatorii de
acces, n ordine de la cel mai restrictiv la cel mai permisiv, sunt: private, protected, cel
implicit (package) i public.
Spunem c metodele rescrise sunt ascunse (dac e vorba de metode statice) sau redefinite (n cazul
metodelor nestatice). Nu este vorba numai de o diferen de terminologie, deoarece metodele statice
pot fi rescrise (ascunse) numai de metode statice, iar metodele nestatice pot fi rescrise (redefinite)
numai de metode nestatice. Alte precizri vor fi fcute n continuare.

Fie A o clas i fie B o subclas a sa. S considerm urmtoarele patru aciuni echivalente din
punctul de vedere al obiectului a ce ia natere:
1) A a; a = new B(...);
2) A a = new B(...);
3) A a; B b; b = new B(...); a = b;
4) A a; B b; b = new B(...); a = (A) b;
S observm c este vorba de o conversie de la o subclas la o superclas, conversie numit
upcasting; ea poate fi implicit (ca n primele trei aciuni) sau explicit (ca n cea de a patra
aciune).

49
Vom spune c obiectul a are tipul declarat A i tipul real B, ceea ce pune n eviden noiunea de
polimorfism.
Tipul real al unui obiect coincide cu tipul su declarat (este cazul obiectului b) sau este o subclas a
tipului declarat (vezi obiectul a).

Fie camp un cmp al clasei A, ce este redeclarat (ascuns) n subclasa B. Dac obiectul a face
referire la cmpul camp, atunci este vorba de cmpul declarat n clasa A, adic este folosit tipul
declarat al obiectului.

Fie met o metod a clasei A, care este rescris n subclasa B. La invocarea metodei met de ctre
obiectul a, este folosit fie implementarea corespunztoare metodei ascunse (dac este static), fie
cea corespunztoare metodei redefinite (dac este nestatic). Cu alte cuvinte, pentru metode statice
este folosit tipul declarat (la fel ca pentru cmpuri), iar pentru metode nestatice este folosit tipul real
al obiectului. n ambele cazuri, se pleac de la tipul indicat mai sus i se merge n sus spre rdcin
(clasa Object) n arborele de clase pn cnd se ajunge la primul tip n care apare metoda
respectiv (evident cu signatura corespunztoare); inexistena unui astfel de tip este semnalat chiar
n faza de compilare.

Exemplul 2 Urmtorul program:

class Super {
static void met1() {
System.out.println("static_Super"); }
void met2() { System.out.println("Super"); }
}

class Sub extends Super {


static void met1() {
System.out.println("static_Sub"); }
void met2() { System.out.println("Sub"); }
}

class Test1 {
public static void main(String[] s) {
Super Ob = new Sub(); Ob.met1(); Ob.met2();
}
}
produce la ieire:
static_Super
Sub

Exemplul 3 Considerm o nou form a claselor din Exemplul 2:

class A {
int va=1, v;
A() { v=va; System.out.print(""+met()); }
int met() { return va; }
}

class B extends A {

50
int vb=2, v;
B() { v=va+vb; }
int met() { return vb; }
}

class Constr {
public static void main (String[] s) {
A a = new B(); System.out.println("\t"+a.met());
}
}

Rezultatele tiprite de programul de mai sus sunt 0 i 2, deoarece:


- la invocarea metodei met din cadrul constructorului clasei A este folosit tipul real al obiectului,
adic este ntors rezultatul furnizat de metoda met redeclarat n B; la momentul invocrii, valoarea
curent a lui vb este 0 (vezi subcapitolul precedent).

- invocarea metodei met n metoda principal, realizat de obiectul a, se va referi tot la metoda
met din clasa B.

Dac ns n clasa B am nlocui declararea int vb=2 a lui vb prin:


static int vb=1;
static { vb=2; }
atunci la ieire vor aprea numerele 2 i 2.

Exemplul 4 S considerm urmtorul program:

class A {
String s="Super";
void scrie() { System.out.println("A : "+s); }
}

class B extends A {
String s="Sub";
void scrie() { System.out.println("B : "+s); }
}

class AB1 {
public static void main(String[] s) {
B b = new B(); A a = b;
a.scrie(); b.scrie();
System.out.println(a.s + "\t" + b.s);
}
}
La executare sunt tiprite urmtoarele:
B : Sub
B : Sub
Super Sub
adic rezultatele ateptate, innd cont c:
- pentru obiectul b: tipul declarat coincide cu cel real i este B;
- pentru obiectul a: tipul declarat este A, iar tipul real este B.

51
S considerm o clas C i dou subclase X i Y ale sale, precum i urmtoarea secven de
instruciuni:
C Ob;
. . . Ob = new X(...);
. . . Ob = new C(...);
. . . Ob = new Y(...);
. . .

n care Ob are mai nti tipul real X, apoi tipul real C, apoi tipul real Y. Spunem c Ob este o
variabil polimorfic, deoarece are pe rnd forma (comportamentul) a mai multor clase.

Din exemplul de mai sus rezult clar c doar la momentul executrii putem determina necesarul de
memorie pentru obiectul Ob, ceea ce justific de ce la creare obiectele sunt "stocate" n heap-ul
memoriei. Mai precis, la crearea unui obiect este alocat spaiu pentru toate cmpurile nestatice din
clas, inclusiv pentru cele ascunse.

Cuvntul cheie super

Putem folosi cuvntul cheie super n orice metod nestatic a unei clase extinse, i anume sub una
dintre formele:
- super(...) : pentru a invoca un constructor al superclasei clasei curente;
- super.met(...) : pentru a invoca o metod a superclasei, metod ce a fost redefinit n clasa
curent;
- super.c : pentru a accesa un cmp c al superclasei, cmp ce a fost ascuns n clasa curent prin
redefinirea sa.
Observm c la accesarea unui cmp sau a unei metode, super acioneaz ca referin la obiectul
curent ca instaniere a superclasei sale.

Exemplul 5 Programul urmtor:

class A {
String s="Super";
void scrie() { System.out.println("A : "+s); }
void metoda() { System.out.println("A:"); }
}

class B extends A {
String s="Sub";
void scrie() { System.out.println("B : "+s+"
"+super.s); }
void metoda() { scrie(); super.scrie();
super.metoda(); }
}

class AB2 {
public static void main(String[] x) {
B b = new B(); b.metoda(); System.out.println(b.s);
System.out.println("****************");
A a; a = b; a.metoda(); System.out.println(a.s);

52
System.out.println("****************");
A c = new A(); c.metoda(); System.out.println(c.s);
}
}

produce la ieire urmtorul rezultat:


B : Sub Super
A : Super
A:
Sub
****************
B : Sub Super
A : Super
A:
Super
****************
A:
Super

Sunt incorecte, nencadrndu-se n formele prezentate mai sus de folosire a lui super, construcii
de forma b.super.metoda() (care ar inteniona ca pentru obiectul b s invocm metoda
metoda din superclasa clasei de tipul creia este) sau urcarea mai multor niveluri n arborele de
clase prin super.super. Pentru a avea acces la un cmp ascuns aflat cu dou niveluri mai sus n
arborele de clase putem proceda de pild ca n exemplul urmtor.

Exemplul 6 Executarea programului:

class A {
int x=1;
void met() { System.out.print("\t"+x); }
}

class B extends A {
boolean x=false;
void met() { System.out.print("\t"+x); super.met(); }
}

class C extends B {
double x=3.14;
void met() { System.out.print("\t"+x); super.met(); }
}

class SubSup {
public static void main (String[] s) {
C Ob = new C(); Ob.met();
}
}

produce la ieire:
3.14 false 1

53
Motenire, polimorfism i legare dinamic
Reamintim urmtoarele:
- orice obiect care instaniaz o clas poate fi folosit n orice cod menit s lucreze cu instanieri ale
superclaselor sale;
- orice obiect care instaniaz o clas poate folosi (n modurile descrise mai sus) codul supraclasei.

La aceste dou caracteristici legate de motenire (extinderea claselor), Java adaug polimorfismul i
legarea dinamic, ntre care exist o strns relaie.

Polimorfismul const n posibilitatea ca o invocare Ob.met(...) s aib drept consecin


invocarea unei anumite metode cu numele met, n funcie de tipul real al obiectului Ob. Unii autori
consider c i cele dou faciliti enunate mai sus fac parte din conceptul de polimorfism.

Legarea dinamic identific metoda met respectiv la executarea programului. Polimorfismul i


legarea dinamic sunt dou caracteristici eseniale ale programrii orientate pe obiecte i vor fi
analizate n acest subcapitol.

Aa cum am precizat n subcapitolul precedent, fiecare obiect are un tip declarat i un tip real; tipul
real coincide cu cel declarat sau este un subtip al acestuia. La invocarea metodelor nestatice se
folosete tipul real, iar la invocarea metodelor statice i la referirea cmpurilor se folosete tipul
declarat. Menionm c n literatura consacrat programrii orientate pe obiecte nu este agreat
opiunea Java de a folosi pentru cmpuri tipul declarat i nu pe cel real.

Pentru metode nestatice se folosete tipul real al obiectelor care le invoc deoarece:
- cronologic, superclasa a fost scris naintea clasei i este de presupus c a fost folosit de mai
muli utilizatori, care vor n continuare s lucreze cu ea;
- n metodele noii clase se pot face referiri la cmpuri nou definite, ceea ce nu este posibil pentru
metodele superclasei.

Utilizarea tipului declarat pentru metodele statice se datoreaz urmtorului fapt: compilatorul "face
tot ce poate" pentru a detecta metoda ce trebuie invocat.

Java folosete legarea dinamic, adic identificarea metodei nestatice concrete care este folosit la
o invocare se face la executare i nu la compilare. De aceea legarea dinamic se mai numete legare
trzie.

Necesitatea legrii dinamice apare din urmtorul exemplu:

Exemplul 7 Fie A o clas n care este definit o metod met, iar B o subclas a sa n care
metoda met este redefinit. Secvena de instruciuni

A Ob;
citete d
if (d>0) Ob = new A(...);
else Ob = new B(...);
Ob.met(...);

arat c doar la momentul invocrii metodei devine clar care dintre cele dou
metode met va fi invocat.

54
Aplicatie 1

Se definete o clas Persoana cu datele membre nume,varsta. Clasa Angajat extinde clasa
Persoana.

package extinderi;

class Persoana
{
String nume;
int varsta;

public Persoana(String nume , int varsta)


{
this.nume = nume;
this.varsta = varsta;
}

public String toString()


{
return nume + " " + varsta;
}
}

class Student extends Persoana


{
String facultate;
int grupa;
double medie;

public Student(String nume , int varsta , String facultate , int


grupa , double medie)
{
super(nume, varsta);
this.facultate = facultate;
this.grupa = grupa;
this.medie = medie;
}

public String toString()


{
return super.toString() + " " + facultate + " " + grupa + " " +
medie;
}
}

class Angajat extends Persoana


{
String firma , functie;
double salariu;

public Angajat(String nume, int varsta , String firma, String


functie, double salariu)
{
super(nume, varsta);
this.firma = firma;
this.functie = functie;
55
this.salariu = salariu;
}

public String toString()


{
return super.toString() + " " + firma + " " + functie + " " +
salariu;
}
}

public class Extinderi_de_clase


{
public static void main(String[] args)
{
Persoana p = new Persoana("Popescu Ion" , 27);
System.out.println(p.toString());

Persoana s = new Student("Ionescu Ana" , 21 , "Facultatea de


Matematic i Informatic" , 241 , 10);
System.out.println(s.toString());

Persoana a = new Angajat("Georgescu Radu" , 33 , "S.C.


RunningBytes" , "Programator Java" , 5000.15);
System.out.println(a.toString());
}
}

56
Tem de autoinstruire

Consultai bibliografia pentru afla despre:

1. alte exemple legate de motenire, rescrierea cmpurilor i ascunderea metodelor.

2. metode existente n clasa Object (toString, equals) i la ce pot fi folosite acestea.

3. informaii complete despre modificatorii de acces.

Teste de control

1. Care este clasa motenit direct sau indirect de orice clasa n Java?

2. Sub ce forme poate fi folosit cuvntul cheie super ?

3. Ce afieaz programul urmtor ? Justificai.

class Unu{
int x;
Unu(int x){this.x=x; afis();}
void afis(){ System.out.println(x);}
void dublu(){x*=2;}
static void nume(){System.out.println("Unu");}
}
class Doi extends Unu{
int y;
Doi(int x,int y){
super(x); this.y=y; afis();
}
void afis(){ System.out.println(x+" "+y);}
void dublu(){
super.dublu();
y*=2;
}
static void nume(){System.out.println("Doi");}
}
class Test{
public static void main(String sir[]){
Doi d=new Doi(4,5);
d.dublu(); d.afis();
Unu u=(Unu)d;
u.dublu(); u.afis();
d.afis();
u.nume();d.nume();
}
}
57
Unitatea de nvare nr. 6

CLASE ABSTRACTE I INTERFEE

Obiectivele Unitii de nvare nr. 6

Dup ce vei parcurge aceast unitate de nvare, vei reui s:

implementai i extindei o interfa;


implementai i extindei o clas abstract;
nelegei diferena dintre clase abstracte i interfee;
implementai o clas intern.

Metode i clase abstracte


Se ntmpl frecvent ca atunci cnd lucrm cu clase extinse, pentru o clas s nu putem preciza
implementarea unei metode, deoarece n subclasele sale ea va fi specific fiecreia dintre ele.
Atunci metodele din aceast categorie vor fi marcate cu cuvntul cheie abstract i se vor reduce la
antetul lor; n acelai timp i clasa trebuie nsoit de atributul abstract. Fiecare metod abstract
trebuie implementat, adic (re)definit n orice subclas care nu este la rndul su abstract.

Nu este posibil s crem obiecte ca instane ale unei clase abstracte. Pe de alt parte, ntr-o subclas
putem s redefinim o metod a superclasei transformnd-o ntr-o metod abstract; aceasta are sens
de exemplu dac n subarborele avnd ca rdcin subclasa, comportamentul materializat prin acea
clas nu mai este valabil n subarbore i este specific fiecrei extensii a subclasei.

Un prim exemplu

Exemplul 1 Urmtoarea clas are ca scop s msoare timpul necesitat de executarea unei
metode oarecare fr parametri i care nu ntoarce vreun rezultat:

abstract class C {
abstract void met();
public long timp() {
long t0 = System.currentTimeMillis();
met();
return System.currentTimeMillis()-t0;
}
}

unde a fost folosit metoda static currentTimeMillis() a clasei System,


metod care ntoarce timpul curent n milisecunde. ntr-o clas ce extinde C, se
poate redefini metoda met i apoi, folosind un obiect ce este o instaniere a noii

58
clase, putem apela metoda timp pentru a determina timpul de executare a metodei
met, ce are acum o implementare precis:

class C1 extends C {
void met () {
int x=0;
for (int i=0; i<1000000; i++) x=x+1-1;
}
}

class Abstr {
public static void main(String[] s) {
C1 Ob = new C1();
System.out.println( "durata="+Ob.timp() );
}
}

Legat de exemplul de mai sus, nu trebuie s ne mire c e posibil ca la executri diferite s obinem
timpi diferii: aceasta este o consecin a faptului c pe perioada executrii programului nostru
sistemul gazd "mai face i altceva", sau c a intervenit colectorul de reziduuri.

Noiunea de interfa
Aa cum s-a menionat anterior, este posibil s declarm clase abstracte n care toate metodele sunt
abstracte. Acest lucru poate fi realizat i prin intermediul interfeelor. n plus, aa cum vom vedea n
continuare, ele reprezint mecanismul propus de Java pentru tratarea problemelor ridicate de
motenirea multipl.
Motenirea multipl este facilitatea oferit de unele limbaje de programare ca o clas s
moteneasc (prin extindere) membri ai mai multor clase. Evident, aceast caracteristic important
a programrii orientate pe obiecte nu este neglijat n Java. Modul n care aceast facilitate poate fi
implementat n Java va fi tratat n continuare.

Interfeele reprezint o modalitate de a declara un tip constnd numai din constante i din metode
abstracte. Ca sintax, o interfa este asemntoare unei clase, cu deosebire c n loc de class
trebuie precizat interface, iar metodele nu au corp, acesta fiind nlocuit cu ';'.
Putem spune c interfeele reprezint numai proiecte, pe cnd clasele sunt o combinaie de proiecte
i implementri. Ca i n cazul claselor abstracte, este evident c nu pot fi create obiecte de tipul
unei interfee.

Cmpurile unei interfee au n mod implicit modificatorii static i final, deci sunt constante.
Metodele interfeelor sunt totdeauna publice i au n mod implicit modificatorul abstract. n
plus ele nu pot fi statice, deoarece fiind abstracte, nu pot fi specifice claselor.

Orice interfa este gndit pentru a fi ulterior implementat de o clas, n care metodele interfeei
s fie redefinite, adic s fie specificate aciunile ce trebuie ntreprinse. Faptul c o clas C
implementeaz o interfa I trebuie specificat prin inserarea informaiei implements I n
antetul clasei.

59
Exemplul 2 Prezentm un prim exemplu de implementare a unei interfee.

interface I {
char c=a; int i=0;
void scrie();
}

class C implements I {
public void scrie() { System.out.println(c+" "+i); }
}

Precizm urmtoarele:
- o interfa poate extinde oricte interfee. n acest mod interfeele permit motenirea unor
"contracte" (numele i signaturile unor metode) fr motenirea implementrii;
- dac o clas implementeaz doar unele din metodele unei interfee, atunci ea trebuie declarat cu
abstract;
- spre deosebire de interfee (care sunt limitate la constante i anunuri de metode), clasele abstracte
pot avea implementri pariale, metode statice, membri cu modificatorul protected, cmpuri
care nu sunt finale etc.;
- o clas poate implementa oricte interfee, dar poate extinde o singur clas.

Dac o clas extinde o alt clas i implementeaz una sau mai multe interfee, atunci trebuie
anunat nti extinderea i apoi implementarea, ca n exemplul urmtor:

class C extends B implements I1,I2,I3;

Aa cum vom vedea n continuare, facilitatea ca interfeele i clasele s poat extinde oricte
interfee reprezint modalitatea prin care Java rezolv problema motenirii multiple.
Dac s-ar permite ca o clas s extind mai multe clase, ar aprea neclariti legate de semnificaia
numelor. Astfel, dac ar fi posibil urmtoarea structur de clase extinse:
W

X Y

i n clasele W, X i Y ar fi definit (respectiv redefinit) un cmp c, atunci pentru un obiect Ob de


tipul Z semnificaia lui Ob.c ar fi neclar.
Faptul c n Java o clas poate extinde cel mult o clas nu rezolv ns automat problema
conflictelor de nume, problem care va fi tratat n continuare.

Suntem acum n msur s completm discuia despre supertipuri i subtipuri.


Supertipurile unei clase sunt clasa pe care o extinde, interfeele pe care le implementeaz, precum i
supertipurile acestei clase i acestor interfee. Drept urmare o referin la un obiect de tipul clasei
poate fi folosit oriunde este ateptat un obiect al oricrui supertip al su (vezi i discuia despre
upcasting din capitolul referitor la extinderea claselor).

Mai menionm c putem declara variabile avnd ca tip numele unei interfee. Unei astfel de
variabile i poate fi atribuit un obiect care implementeaz interfaa (are ca tip real o clas ce
implementeaz interfaa).

60
Un exemplu ce ilustreaz aceste elemente va fi prezentat n paragraful destinat implementrii
interfeelor.

ntrebare: Se tie c o clas poate avea un singur printe. Este valabil aceast afirmaie i in
cazul interfeelor, in sensul ca o interfa poate implementa o singur interfa?

Rspuns: Nu. O interfa poate implementa oricte interfee. De asemenea o clas poate
implementa oricte interfee.

Extinderea interfeelor
Ca i clasele, interfeele pot fi extinse. O interfa I poate extinde oricte interfee, n acest mod
adugndu-se la I noi constante i (anunuri de) metode.
Este permis ca o interfa ce extinde alt interfa s conin o constant cu acelai nume. De
exemplu pentru urmtoarea structur de interfee:
W

X Y

este posibil ca n una sau mai multe dintre interfee s fie declarat o constant c. Deosebim dou
cazuri:
1) Constanta c este redeclarat n interfaa Z : o referire la c constituie o referire la constanta c
din Z. Putem face ns referire i la constantele din celelalte interfee prin X.c, Y.c i W.c.
2) Constanta c nu este redeclarat n interfaa Z : o referire la c este corect dac exist un
unic drum de interfee ce "coboar" n Z, drum n care c poate fi declarat de mai multe ori; n acest
caz referirea are ca obiect cea mai "recent" declarare a cmpului, adic cea din interfaa cea mai
apropiat de Z. Dac c este declarat pe mai multe drumuri de interfee ce "coboar" n Z,
compilatorul va semnala c este vorba de o referire ambigu. Dac n Z constanta c nu poate fi
regsit pe nici un drum de interfee ce ajunge n Z, atunci va fi semnalat din nou eroare.

Rmnnd la structura de interfee de mai sus, s presupunem acum c n X i n Y (sau n


supertipuri ale lor) apare o metod cu acelai nume. Deosebim situaiile:
1) dac metodele au signaturi diferite, vor fi motenite ambele metode;
2) dac metodele au aceeai signatur i acelai tip pentru valoarea ntoars, va fi motenit o
singur metod;
3) dac metodele au aceeai signatur, dar tipurile valorilor ntoarse difer, atunci motenirea
nu va fi posibil (eroare de compilare).

Este posibil ca de exemplu n X i n Z (sau, mai general, ntr-un drum de interfee extinse) s
anunm cte o metod cu acelai nume i aceeai signatur. Atunci o clas care implementeaz
interfaa Z va implementa ambele metode.

61
Exemplul 3 Programul urmtor:

interface W { char c='a'; }


interface X extends W { int c=1; void met(); }
interface Y { boolean c=true; }
interface Z extends X,Y { int c=99; void met(); }

class C implements X {
public void met() { System.out.println("++++++");
}
}

class D implements Z {
public void met() { System.out.println("******");
}
}

class Interfete1 implements Z {


public void met() { }
public static void main (String[] s) {
C Ob1 = new C(); Ob1.met();
D Ob2 = new D(); Ob2.met();
int c=-88; // met();
System.out.println(c+" "+W.c+" "+X.c+" "+Y.c+"
"
+Z.c );
}
}

produce la ieire:

+++++
*****
-88 a 1 true 99

Se impun urmtoarele observaii:


1) n clasele C i D, redefinirea metodei met s-a fcut cu precizarea modificatorului public.
Acest lucru este obligatoriu, pentru c altfel ar fi fost folosit modificatorul implicit, dar o redefinire
nu poate fi mai restrictiv n privina drepturilor de acces;
2) Din metoda principal nu putem invoca implementarea lui met din Interfete1, deoarece o
metod static poate accesa numai cmpurile i metodele statice ale clasei; pe de alt parte ns, o
metod anunat ntr-o interfa nu poate fi redefinit printr-o metod static, deci nu putem preciza
atributul static pentru metoda met din Interfete1.

Implementarea interfeelor
n subcapitolul de fa prezentm modul n care sunt rezolvate conflictele de nume ce pot aprea la
implementarea interfeelor.

Fie C o clas care implementeaz una sau mai multe interfee i extinde eventual o clas.

62
Presupunem mai nti c n unul sau mai multe dintre aceste tipuri apare un cmp (constant n
cazul interfeelor) cu acelai nume c. Atunci discuia este analoag cu cea referitoare la extinderea
interfeelor, cu urmtoarea adugire: dac c este declarat att n Z, ct i n clasa pe care o extinde,
va trebui s specificm super.c pentru cmpul din superclas.

Trecem acum la cazul metodelor. Motenirea metodelor interfeelor are loc n modul descris la
extinderea interfeelor. Drept urmare, toate metodele motenite din interfee trebuie implementate.
Dac o metod cu acelai nume i aceeai signatur apare n superclas i n interfeele
implementate, atunci:
- dac precizm n C o implementare a metodei, ea va constitui o redefinire a metodei din
superclas; la aceasta din urm putem face ns apel prin super;
- dac n C nu este precizat o implementare a metodei, atunci metoda (motenit) din superclas
constituie implementarea metodei din interfee, cu condiia ca ea s aib modificatorul public.

Exemplul 4 Programul urmtor:

interface A {
int x=1; void scrie(); A B C
}

interface B {
D
int x=2; void scrie();
}

class C {
int x=3;
public void scrie() {
System.out.print(A.x+" "+B.x+" "+x);
}
}
class D extends C implements A,B {
int x=4;
}

class Interfete2 {
public static void main(String[] w) {
D Ob = new D(); Ob.scrie();
System.out.println(" "+Ob.x);
A Ob1 = new D(); Ob1.scrie();
System.out.println(" "+Ob1.x);
}
}

produce la ieire:
1 2 3 4
1 2 3 1

Sunt necesare explicaii doar referitor la obiectul Ob1. El are tipul declarat A
i tipul real D, ceea ce face ca invocarea metodei scrie prin intermediul acestui
obiect s se refere la metoda scrie din clasa C, iar referina Ob1.x s se
adreseze constantei x din interfaa A.

63
Clase interne
Pn acum am lucrat sub restricia c o clas nu poate conine o alt clas. Dar Java permite s
definim clase nu numai ca membri ai pachetelor, dar i ca membri ai unei clase, n interiorul unei
metode sau a unui bloc. Mai mult, aa cum vom vedea mai jos, pot aprea clase fr nume.
Clasele care sunt membrii unui pachet sunt considerate clase de nivel superior.
Clasele declarate ntr-o clas se mpart n dou categorii:
- clase de nivel superior: este vorba de membrii statici ai unei clase de nivel superior; aceste clase
au deci acelai statut cu clasele membre ale unui pachet;
- clase interne: clasele care nu sunt de nivel superior.

ntr-o clas de nivel superior putem plasa i o interfa.


Aa cum am menionat, ntr-un bloc sau corpul unei metode putem defini clase la fel cum putem
defini variabile locale; aceste clase sunt clase interne. O clas intern poate conine la rndul ei o
clas intern.

Instanierea unei clase interne este asociat instanierii curente a clasei care o conine; drept urmare
clasa intern poate accesa direct cmpurile clasei ce o cuprinde.
Cele de mai sus nu mai rmn valabile pentru clasele de nivel superior: o clas care este membru
static al unei clase nu poate folosi direct cmpurile clasei ce o cuprinde (dar putem realiza acest
lucru n mod indirect, prin crearea unui obiect ce instaniaz clasa al crui membru este).

O clas intern nu poate fi folosit direct dect n clasa n care a fost declarat i n descendenii (n
arborele de clase ai) acesteia. Domeniul ei de vizibilitate este cel al unui cmp, respectiv al unei
variabile locale.

Avantajul utilizrii claselor locale const n primul rnd n faptul c permite includerea lor exact
acolo unde trebuie s apar din punct de vedere logic, dar i n uurina folosirii lor (reamintim c
din interiorul unei clase interne putem s ne referim direct la cmpurile clasei ce o conine).

Observaie. Crearea de clase anonime permite extinderea implicit a unei clase i implementarea
implicit a unei interfee (fr a folosi extends sau implements). Drept urmare codul devine
mai scurt i mecanismul este folosit "la locul potrivit". Aceast tehnic este larg folosit de exemplu
n lucrul cu interfee grafice.

Exemplul 5 S considerm urmtorul program:

abstract class A {
A(int i) { System.out.println(i); }
void met() { };
}

class A_C {
static A ObA;
public static void main(String[] s) {
ObA = new A(3) {
void met() { System.out.println("O.K."); }
};
ObA.met();
}
}

64
Clasa abstract A are un constructor i o metod care nu prevede nici o aciune. Pare ciudat faptul c
dei metoda nu este abstract, clasa a fost declarat ca fiind abstract; acest "artificiu" este de fapt o
invitaie la a extinde clasa i a preciza aciuni specifice pentru metode.

n clasa A_C apare metoda principal, n care obiectul ObA (avnd tipul declarat A) este creat ca
avnd ca tip real o clas anonim care extinde clasa abstract A. Clasa anonim este o clas intern.
Dup invocarea constructorului este invocat metoda met; este vorba bineneles de metoda met
redefinit n clasa anonim. Drept urmare la ieire va aprea:

3
O.K.

O interfa nu poate avea constructori explicii. Exist ns constructorul implicit cu aciune nul;
acest constructor a fost folosit n exemplul de mai sus.

Este interesant de subliniat nc un aspect. Clasa I_C are modificatorul de acces implicit, dar n
interiorul ei apare o metod cu modificatorul (mai permisiv) public. Acesta se datoreaz faptului
c metoda redefinete o metod (public) dintr-o interfa.

Clasele interne se dovedesc un instrument foarte util i uor de mnuit i se va face apel la ele n
continuare. Clasele anonime apar iniial ca fiind mai puin "naturale", dar avantajele (menionate
mai sus) ale acestei tehnici fac ca ea s fie foarte util i deci folosit, aa cum vom face n lucrul cu
interfee grafice.

Aplicatie 1
Scriei o surs Java definete o interfa ConstateMatematice cu urmtoarele constate matematice:

double PI = 3.14159265358979323846;
double SQRT_2 = 1.41421356237;
double SQRT_3 = 1.73205080757;
double LN_2 = 0.69314718056;

Definii clasele TriunghiEchilateral i Cerc care sunt extinse din clasa abstract
FiguraGeometricaPlan i implementeaz interfaa ConstanteMatematice. n fiecare din clasele
concrete se ncapsulez cte o metod de calcul a ariei.

package Interfete;

public interface ConstanteMatematice {


double PI = 3.14159265358979323846;
double SQRT_2 = 1.41421356237;
double SQRT_3 = 1.73205080757;
double LN_2 = 0.69314718056;
}

package Interfete;

public abstract class FiguraGeometrica {


protected double dim1, dim2;
public FiguraGeometrica(double dim1, double dim2)
{
65
this.dim1=dim1;
this.dim2=dim2;
}

public double getDim1() {


return dim1;
}

public void setDim1(double dim1) {


this.dim1 = dim1;
}

public double getDim2() {


return dim2;
}

public void setDim2(double dim2) {


this.dim2 = dim2;
}

public abstract double arie();

package Interfete;

public class Cerc extends FiguraGeometrica implements


ConstanteMatematice{
public Cerc(double dim1, double dim2)
{
super(dim1, dim1);
}
public double arie()
{
return ConstanteMatematice.PI*dim1*dim2;

public String toString()


{
return "Cerc: ";
}

package Interfete;

public class TrEchilateral extends FiguraGeometrica implements


ConstanteMatematice{
public TrEchilateral(double dim1, double dim2)
{
super(dim1, dim1);
}

66
public double arie()
{
return (dim1*dim2*ConstanteMatematice.SQRT_3)/4;
}

public String toString()


{
return "Triunghi: ";
}
}

package Instantieri;

import Interfete.*;
import java.util.Scanner;

public class TestFigGeo {


public static void main(String args[])
{
FiguraGeometrica tab[]=new FiguraGeometrica[10];
Scanner in=new Scanner(System.in);
int n, x, dim;
System.out.print("n= ");
n=in.nextInt();

for(int i=0;i<n;i++)
{
System.out.print("optiune: 1(tr)/2(cerc)?");
x=in.nextInt();

if(x==1)
{
System.out.print("Lat tr: ");
dim=in.nextInt();
tab[i]=new TrEchilateral(dim, dim);
}
else
if(x==2)
{
System.out.print("Raza cerc: ");
dim=in.nextInt();
tab[i]=new Cerc(dim, dim);
}

for(int i=0;i<n;i++)
System.out.println(tab[i]+" "+tab[i].arie());
}

67
Tem de autoinstruire
Consultai bibliografia pentru :

1. A vedea alte exemple care utilizeaz clase abstracte, interfee i clase interne.

2. A aprofunda motenirea multipl n Java prin intermediul interfeelor.

Teste de control
1. Pot exista metode implementate (cu corp) ntr-o clas abstract? Dar ntr-o interfa?

2. ntr-o clas care implementeaz o interfa se poate modifica valoarea unui cmp din aceast
interfa?

3. Unde poate fi folosit o clas intern ?

4. Ce putei spune despre urmtorul program?

interface I1{
int a=5;
int f(int x);
}
interface I2 extends I1{
float b=10;
float f(float x);}
class C implements I2{
public int f(int x){return x+a;}
public float f(float x){return x/b;}}
class Test{
public static void main(String sir[]){
I2 ob=new C();
System.out.print(ob.f(1)+" "+ob.f(1.5f)); }}

a) Apare eroare la compilare deoarece metoda f din interfaa I1 intr n contradicie cu


metoda f din interfaa I2;
b) Apare eroare la compilare deoarece n clasa C nu este definit variabila a.
c) Apare eroare la compilare deoarece nu se pot defini obiecte avnd ca tip o interfa.
d) Este corect i afieaz la execuie: 6 0.15
e) Este corect i afieaz la execuie: 6 0.15f

5. Scriei un program care s conin o clas abstract cu o metoda abstract sort care primete
ca parametru un vector de ntregi, precum i o metod implementat care msoar timpul de
execuie a metodei sort; dou clase care extind aceast clas abstract, fiecare dintre aceste
clase implementnd metoda sort prin modaliti diferite de a sorta un vector de ntregi.
Afiai timpul necesar pentru ca metodele din cele dou clase s sorteze un vector dat (folosind
metoda motenit de la clasa abstract).

68
Unitatea de nvare nr. 7

EXCEPII I CONVERSII

Obiectivele Unitii de nvare nr. 7

Dup ce vei parcurge aceast unitate de nvare, vei reui s:


nelegei conceptul de excepie i utilitatea folosirii
excepiilor pentru a asigura robusteea programelor;
lansai o excepie prin instruciunea throw i s tratai o
excepie prin construcia try;
scriei programe ce trateaz excepii.

Excepii
Un aspect important de care trebuie inut cont ori de cte ori scriem un program este de a asigura
robusteea sa. Prin aceasta nelegem identificarea situaiilor nedorite (de exemplu introducerea unor
date eronate, eecul la ncercarea de a avea acces la Internet etc.) i specificarea aciunile
corespunztoare.

Exist ns i reversul aspectului descris mai sus. Introducerea de verificri prin instruciuni de
control face programul greu de citit i afecteaz buna sa structurare.

Ceea ce dorim este s avem un mecanism care:


- s permit ca fiecare condiie legat de robusteea programului s fie verificat exact acolo unde
poate s apar;
- atunci cnd condiia apare (suntem n situaia c s-a ntmplat ceva nedorit), controlul s fie trecut
automat unei seciuni de cod aflat n program "ntr-un loc potrivit" (care poate fi "departe" de locul
unde condiia a fost detectat), cod care realizeaz aciunea ce trebuie ntreprins. Acest cod va fi
numit handler (mnuitor) de excepie.
Limbajul Java rezolv problema de mai sus printr-un mecanism numit excepie. Excepia
semnaleaz faptul c a intervenit o anumit condiie special (nedorit); spunem c segmentul de
cod care a detectat condiia lanseaz o excepie de tipul corespunztor. Lansarea unei excepii
atrage dup sine captarea ei de ctre un handler de excepie; n lipsa acestuia, programul se va
ncheia cu un mesaj de eroare.

Mai precis, trebuie s realizm urmtoarele:


- s definim tipurile de excepie care s permit lansarea excepiilor dorite;
- s lansm o excepie la "locul potrivit" n program;
- s prevedem la "locul potrivit" un handler de excepie, care s capteze excepia i s
ntreprind aciunile corespunztoare.
O excepie este n fapt o instan a unei clase derivate din clasa java.lang.Exception. Rezult
c o excepie este un obiect, care are cmpurile sale, constructorii si i metodele sale. Cnd un

69
program detecteaz o condiie care cere ca o excepie s fie raportat, el creeaz un obiect
corespunztor excepiei, care poate fi folosit pentru a invoca metode ale a clasei respective.
Trebuie subliniat c o excepie poate fi o eroare, dar i orice situaie pentru care vrem s
ntreprindem aciuni specifice. Pentru situaiile n care consider c este vorba de o eroare, Java
lanseaz automat o excepie care, dac nu este captat de un handler de eroare, conduce la tiprirea
unui mesaj, dup care programul se termin; este ns posibil s captm excepia i s ntreprindem
ce aciune dorim.

Un prim exemplu
Exemplul se refer la metoda System.in.read() care lanseaz, atunci cnd are
Exemplul 1 loc o eroare la citire (nu poate fi citit un caracter), o excepie de tipul
IOException. Exist dou posibiliti de a trata aceast situaie:

1) Se precizeaz, n antetul metodei care execut apelul respectiv, clauza:


throws IOException
dup lista de parametri a metodei. Drept urmare ia natere un obiect de tipul IOException care
tiprete un mesaj de eroare i ntrerupe executarea programului; putem gndi c este executat
implicit o metod care ntreprinde aceste aciuni.

2) Se prevede o aciune explicit specificat de programator prin:


try {
... System.in.read();...
}
catch (IOException e){
handler de excepie
}
prin care este creat obiectul e de tipul IOException, care poate fi folosit n prelucrrile prevzute
de handlerul de excepie. Aciunea respectiv poate consta de exemplu n tiprirea unui mesaj
edificator, atribuirea unor valori prin lips, invocarea unor metode (presupunnd c acestea exist)
ale clasei IOException prin intermediul obiectului e etc.

n aceast a doua variant nu mai este necesar s declarm clauza throws IOException n
antetul metodei. De asemenea trebuie observat c nu mai este ntreprins o aciune implicit,
deoarece este prevzut explicit un cod ce trebuie executat (cel din handlerul de excepie). De
exemplu aciunea poate fi:
System.out.println("Eroare : " + e);
prin care este tiprit mesajul "Eroare" urmat de numele excepiei.
Clasa Exception are un constructor implicit cu zero argumente, un constructor cu un argument de
tip String i o metod fr nume care se execut implicit la lansarea unei excepii i care const n
tiprirea unui mesaj de eroare specific (la care se poate aduga irul transmis constructorului, n
cazul n care a fost folosit acest constructor).

Cel mai brutal mod de utilizare a clauzei throws este:


throws Exception

70
prin care are loc terminarea programului pentru toate excepiile prevzute de Java. Nu este ns
indicat s procedm n acest mod, deoarece n general nu vom obine suficiente informaii pentru
depanarea programului.

Clauza throws i instruciunea throw


Pentru a lansa o excepie, este folosit instruciunea throw, ce are forma:
throw Ob;
Obiectul excepie Ob poate fi creat ca de obicei, folosind operatorul new:
tip_exceptie Ob = new tip_exceptie(...);
drept urmare lund natere o instan a clasei tip_exceptie ce extinde clasa Exception.
Crearea este nsoit de invocarea acelui constructor al clasei tip_exceptie, ce are signatura
respectiv. O excepie fiind un obiect, ea trebuie nti creat i apoi lansat.

De obicei, lansarea ntr-o metod a unei excepii se face din cadrul unei instruciuni if sau a unei
instruciuni switch, ca de exemplu n:
tip Met(...)throws Exceptie {
...
if(...) throw new Exceptie(...);
...
}
unde Exceptie este o clas ce extinde clasa Exception. Dac este ndeplinit condiia din if,
atunci este creat, folosind un constructor, un obiect avnd tipul (de excepie) Exceptie. Observm
c n antetul metodei Met de mai sus apare clauza "throws Exceptie".

S remarcm c mecanismul seamn cu crearea obinuit a unui obiect:

class ... {
tip Met(...) {
...
if(...) Exceptie Ob = new Exceptie(...);
...
}
}

Lucrurile nu sunt ns identice: nu exist constructorii de care am vorbit mai sus i nu au loc
automat tiprirea unui mesaj de excepie i terminarea programului.

Sunt importante urmtoarele precizri:


- precizarea tipului de excepie prin clauza throws este important pentru c programatorul (ca i
compilatorul) trebuie s tie ce excepie poate fi lansat i care este tipul ei, la fel cum trebuie s
cunoasc tipul valorii ntoarse de o metod;
- dac din interiorul metodei dorim s prevedem lansarea mai multor excepii, atunci toate tipurile
lor trebuie precizate n clauza throws, desprite ntre ele prin virgul;
- o metod poate lansa numai excepiile care sunt precizate n antetul su (mai precis n clauza
throws); lansarea poate avea loc din interiorul metodei sau din interiorul altei metode pe care ea o
invoc;
- nu este permis s lansm excepii din interiorul iniializrilor
statice; n schimb acest lucru este permis din interiorul
constructorilor;
- la redefinirea unei metode ntr-o subclas, nu putem preciza n
throws excepii suplimentare.

71
Construcia try
Mecanismul incipient descris mai sus permite crearea unei excepii i invocarea unui constructor al
su. Dar o excepie lansat n corpul unei metode trebuie s aib drept consecin executarea unor
aciuni cuprinse ntr-un handler de excepie prezent tot n corpul metodei. Tipul de excepie
respectiv este ns o clas, care poate avea i metode. n handlerul de excepie este posibil
invocarea unor metode ale clasei a crei instaniere este obiectul n discuie. Toate aceste aspecte
sunt rezolvate de construcia try.
Construcia try are forma:

try bloc
catch(E_1 e_1) bloc1
catch(E_2 e_2) bloc2
...
finally bloc_final

unde:
- E_1, E_2, ... sunt tipuri de excepie (clase ce extind Exception);
- e_1, e_2, ... sunt identificatori;
- clauza finally este opional;
- blocurile reprezint tocmai handlerele de excepie.
Dac n blocul bloc asociat lui try nu este lansat nici o excepie, atunci se trece de ultimul
catch. S presupunem acum c din bloc este lansat o excepie; fie E tipul su. Se ncearc pe
rnd, n ordinea n care apar clauzele catch, asocierea ei cu una dintre ele. Dac E coincide cu E_1
sau este derivat din (extinde pe) E_1, atunci se execut blocul bloc_1, dup care se trece de
ultima clauz catch. n caz contrar se ncearc pe rnd asocierea excepiei cu E_2, E_3 etc. Dac
nu s-a reuit o asociere, se merge "la un nivel superior" ntr-o construcie try care o cuprinde pe
cea n discuie etc. Dac nici n acest mod nu s-a identificat o asociere, se trece n codul care a
invocat metoda curent etc. n final se va reui o asociere, deoarece altfel ar apare o eroare chiar n
faza de compilare.

Tot o eroare la compilare va apare i dac de exemplu E_2 este derivat din E_1; explicaia const
n faptul c lansarea unei excepii de tipul E_2 nu va putea conduce la captarea ei de ctre clauza
identificat prin E_2 (excepia va fi captat de clauza catch precedent). Conform celor de mai
sus, este posibil ca o construcie try s nu aib ataat nici o clauz catch.
S mai observm c la lansarea unor excepii din bloc (vezi forma general a construciei try),
instruciunile care i urmeaz n acest bloc nu vor mai fi executate. Mai este clar i c o construcie
try poate fi utilizat pentru captarea mai multor excepii.

Aa cum am anunat anterior, o construcie try poate avea i o clauz finally. Aceasta permite
executarea unei secvene de instruciuni indiferent dac din blocul bloc este lansat sau nu o
excepie. Odat inclus, clauza finally nu poate fi n nici un fel ocolit i blocul bloc_final
este totdeauna executat. Un caz limit este de exemplu urmtorul:
try { ... return 0; ... }
finally { return 1; }
pentru care valoarea ntoars este totdeauna 1.

De obicei clauza finally este folosit pentru a elibera anumite resurse, ca de exemplu resurse
grafice sau fiiere (prin nchiderea lor).

72
Tratarea excepiilor
Descriem n continuare modul tipic de utilizare a excepiilor. Pentru simplificare vom considera un
singur tip de excepie cu un unic constructor i o unic metod.

La construcia urmtoarei clase:

class Clasa {
Clasa(..) {..}
.. Met(..)throws Exceptie {
...
if(..) throw new Exceptie(..)
..
}
}

programatorul a identificat n metoda Met o condiie deosebit care ar putea interveni i de aceea a
conceput i clasa Exceptie pentru a putea prevedea aciunile ce trebuie ntreprinse la ndeplinirea
condiiei:
class Exceptie extends Exception {
Exceptie(...) {...}
... MetExc(...) {...}
}

n mod normal, aceste activiti sunt ntreprinse o singur dat, n vederea unor aplicaii ce urmeaz
a fi dezvoltate. Pe de alt parte, clasa Exceptie poate fi folosit i de alt clas dect Clasa; de
exemplu att pentru lucrul cu stive, ct i pentru cel cu cozi, prelucrrile prevzute pentru o
ncercare de adugare a unui element n stiva/coada plin pot fi aceeai. De aceea de multe ori este
natural ca cele dou clase s se afle n uniti de compilare separate.
Ulterior, programatorul scrie un program care cuprinde o clas C, din care este invocat metoda Met
a clasei Clasa, ceea ce poate conduce la lansarea excepiei respective. Este clar c aici este locul
cel mai potrivit pentru a specifica aciunea ce trebuie ntreprins la lansarea excepiei. Pentru
aceasta este folosit construcia try, care capteaz obiectul excepie i prin intermediul lui invoc
metoda MetExc a clasei Exceptie:

class C {
Clasa Ob = new Clasa(...);
...
try {
....
Ob.Met(...);
....
}
catch (Exceptie e){
... e.MetExc(...); ...
}
.....
}

S-a prevzut invocarea metodei Met a clasei Clasa din interiorul construciei try. n cazul n care
apare condiia n discuie, este creat un obiect de tipul Exceptie prin invocarea constructorului
su. Apoi controlul este trecut clauzei catch care capteaz (primete n parametrul su) obiectul
creat, ceea ce permite invocarea metodei MetExc din Exceptie.

73
Acum discuia de la nceputul capitolului capt consisten: o excepie de tipul Exceptie este
lansat din clasa Clasa i este captat n clasa C.

Un exemplu
Vom aplica cele de mai sus la rezolvarea urmtoarei
Exemplulprobleme:
2

Un vector a de lungime n conine n caractere. Ele trebuie mutate ntr-o ordine oarecare n vectorul
b, prin intermediul unui vector auxiliar stack de lungime lung, care implementeaz o stiv.
Operaiile permise sunt:
- mutarea unui element din a n vectorul stack : elementul curent (cel cu numrul de ordine cel
mai mic) din a este mutat dup elementele deja existente n stiv;
- extragerea (inclusiv tergerea) unui element din vrful stivei i nscrierea sa n b, dup ultimul
element nscris n b.
Dificultatea problemei const n tratarea cazului n care se ncearc extragerea unui element din
stiva vid i a cazului n care se ncearc introducerea unui element n stiva plin.

Prezentm n continuare programul, urmat de explicaiile necesare.


Cod surs Unitatea de compilare Plina.java :

class Plina extends Exception {


void print(String s) { System.out.print(s); }
}

Unitatea de compilare Vida.java :


class Vida extends Exception {
void print(String s) { System.out.print(s); }
}

Unitatea de compilare S.java :


class S {
int lung, ns; char[] stack;
S(int lung) { this.lung=lung ; stack = new char[lung]; }

void pune(char c) throws Plina {


if (ns==lung) throw new Plina();
else { System.out.print(" P"+c); stack[ns]=c; ns++; }
}

char ia() throws Vida {


if (ns==0) throw new Vida();
else {
System.out.print(" I"+stack[--ns]); return
stack[ns];
}
}
}

74
Unitatea de compilare Stiva.java :
import java.util.*;
class Stiva {
public static void main(String[] sir) {
int n=10,na,nb,i; char[] a,b; char c;
a = new char[n]; b = new char[n];
Random R = new Random();
for (c='a',i=0; i<n; i++,c++) a[i]=c;
na=0; nb=0; S Ob = new S(3);
while (nb!=n) {
try {
if (R.nextInt()<0 && na<n) { Ob.pune(a[na]); na++;
}
else { b[nb] = Ob.ia(); nb++;} }
catch (Vida e) {e.print(" ~I");}
catch (Plina e) {e.print(" ~P");}
}
System.out.println();
for (i=0; i<n; i++) System.out.print(b[i]+" ");
System.out.println();
}
}

Explicaii Clasa principal este Stiva. Metoda sa main folosete, n afar de vectorii a i b,
urmtoarele:

- variabila na desemneaz poziia din a de pe care va fi mutat un element n stiv;


- variabila nb desemneaz poziia din b pe care va fi nscris urmtorul element;
- obiectul R de tipul Random (clas din pachetul java.util) este folosit pentru apelarea metodei
nextInt fr argumente, ce ntoarce n mod aleator un numr ntreg;
- obiectul Ob de tipul S, unde clasa S implementeaz operaiile asupra stivei: metoda pune are un
parametru de tip char pe care l adaug stivei, iar metoda ia fr parametri ntoarce elementul din
vrful stivei.

Metoda main din Stiva repet, atta timp ct n b nu au fost nscrise n caractere, urmtoarele
aciuni:
- este generat aleator un nou numr ntreg;
- dac valoarea sa este negativ i mai exist elemente n a, este invocat metoda pune din clasa S
cu intenia de a muta un element din a n stiv; invocarea este urmat de mrirea lui na cu o unitate.
n caz contrar este invocat metoda ia cu intenia de a obine un element din stiv i de a-l muta n
vectorul b;
- n final sunt listate elementele lui b.

Observm c nu sunt tratate aici cazurile de excepie (adugare la stiv plin sau extragere din stiva
vid), aceste verificri cznd n sarcina clasei S. Utilizarea clasei Random permite un
nedeterminism n succesiunea de operaii asupra stivei, ceea ce va conduce la vectori b diferii de la
o executare la alta.
n clasa S este folosit vectorul stack de lungime lung pentru implementarea stivei. n ns este
memorat numrul de elemente din stiv. n antetul metodei pune este declarat tipul de excepie
plina, cruia i corespunde clasa plina ce extinde clasa Exception. Deosebim dou situaii:

75
- dac stiva este plin (ns=lung), atunci prin throw este creat o excepie (un obiect de tip
Plina). Controlul este trecut acelei clauze catch din Stiva care este identificat prin tipul Plina
al excepiei. Obiectul creat este transmis n e. Prin invocarea e.print(...) este apelat metoda
print a clasei Plina care tiprete mesajul primit la invocare. S observm c n acest mod se
evit incrementarea lui na;
- dac stiva nu este plin, atunci este nscris un nou element n stiv.

Modul n care acioneaz metoda ia este analog.

Este uor de observat c s-a folosit exact schema descris anterior, cu clasele Plina i Vida n
rolul clasei Exceptie, cu S n postura clasei Clasa i cu Stiva n locul clasei C.

76
Tem de autoinstruire

Consultai bibliografia pentru a afla despre :

1. Alte exemple legate de tratare a excepiilor i crearea de excepii proprii


2. Clasele din pachetul java.lang care extind clasa Exception
3. Diferena dintre clasa Exception i clasa Error (dintre excepii i erori)

Teste de control

1. Ce este o excepie n Java?


2. Cum se poate lansa o excepie n interiorul unei metode ?
3. O metoda poate lansa mai multe excepii? Cum se specific ce excepii lanseaz o metod?
4. Presupunem c avem urmtoarea clas cu o metod afisFisier care citete datele dintr-un
fiier linie cu linie i le afieaz pe ecran. Metoda lanseaz excepiile
FileNotFoundException dac fiierul nu este gsit i IOException dac apar probleme la
citire. Scriei o clas care s conin metoda main n care sa afiai datele dintr-un fiier cu
numele "exceptii.txt" folosind metoda afisFisier i care s trateze erorile lansate de
aceasta, afind un mesaj corespunzator: "Fisier inexistent" sau "Eroare la
citire".

import java.util.*;
import java.io.*;
class Fisier{
void afisFisier(String numeFisier)
throws FileNotFoundException,IOException{
Scanner sc=new Scanner(new File(numeFisier));
while(sc.hasNextLine())
System.out.println(sc.nextLine());
sc.close();
}}

5. Scriei o clas care s implementeze o coad de numere strict pozitive, innd cont de
urmtoarele precizri:
- coada va avea o capacitate maxim;
- clasa va conine metode de adugare a unui element, interogare i tergere a unui element,
afiare a cozii. Metoda de adugare a unui numr va lansa excepie dac se ncearc adugarea
unui numr care nu este strict pozitiv sau dac numrul de elemente din coad este deja egal cu
capacitatea cozii. Metoda de eliminare va lansa excepie dac nu exist nici un element n
coad;
- folosii aceast clas pentru numere citite de la tastatur utiliznd metoda nextInt a clasei
Scanner, tratnd excepiile pe care le pot lansa operaiile asupra cozii, dar i excepia
InputMismatchException din pachetul java.util lansat de metoda nextInt a clasei
Scanner dac nu este introdus un ntreg corect.

77
Unitatea de nvare nr. 8

FLUXURI DE INTRARE/IEIRE

Obiectivele Unitii de nvare nr. 8

Dup ce vei parcurge aceast unitate de nvare, vei reui s:


nelegei conceptul de flux n Java;
ierarhia de clase dedicate din pachetul java.io;
scriei programe care folosesc fluxuri de intare/ieire

Suprapunerea obiectelor
Fie clasa:
class A {
... met(...) { ... }
}

Dorim ca o clas B s poat utiliza metoda met.O modalitate este oferit de mecanismul de
extindere a claselor: declarm o clas B care extinde A, construim un obiect b de tipul B i putem
invoca b.met().
Exist ns limitri de aplicare, innd de context sau de limbaj, dintre care menionm:
- de multe ori invocarea lui met trebuie fcut ntr-un anumit context, de exemplu printr-un
anumit obiect de tipul A, cu anumite cmpuri;
- este posibil s dorim ca din clasa B s utilizm i metode din alte clase; dar o clas poate
extinde o singur clas.

O alt modalitate, folosit n lucrul cu fluxuri, o constituie cea de suprapunere de obiecte (n cazul
fluxurilor va fi numit suprapunere de fluxuri).
Pentru simplificare, ilustrm aceast variant pentru cazul unei singure metode:
class B {
A a;
B(A a) { this.a = a; }
... met(...) { ...; a.met(); ... }
}
situaie n care procedm astfel:
B b = new B(new A()); b.met(...).

Spunem c obiectul b suprapune obiectul a, respectiv c (prin suprapunere) clasa B adaug noi
faciliti clasei A.

78
Schema general
Clasele ce ofer faciliti de intrare/ieire se gsesc n pachetul java.io.
Facilitile de intrare/ieire din Java au la baz noiunea de flux. Un flux este un obiect asociat unei
succesiuni de elemente (octei sau caractere), citite i scrise secvenial.

Pentru un flux de intrare sursa datelor poate fi un fiier, dar i un ir sau tablou de octei, respectiv
caractere. Pentru un flux de ieire, datele transmise sunt stocate ntr-un fiier sau ntr-un tablou de
octei, respectiv caractere.

Dac la citire nu sunt nc date disponibile n flux i nu s-a detectat sfritul datelor, atunci firul de
executare care realizeaz citirea va fi blocat pn cnd vor exista date disponibile.
O prim clasificare a fluxurilor are n vedere elementele de baz care sunt transmise: caractere sau
octei.
Object
InputStream (clas abstract pt. citire la nivel de octet)
OutputStream (clas abstract pt. scriere la nivel de octet)
Reader (clas abstract pentru citire la nivel de caracter)
Writer (clas abstract pt. scriere la nivel de caracter)

Toate clasele, interfeele i metodele din pachetul java.io au modificatorul public, iar n plus
aproape toate metodele conin clauza throws IOException.

Fluxuri ce lucreaz la nivel de octet


O structur simplificat, dar cea mai frecvent utilizat, de clase este urmtoarea:

Object
DataInput (interfa)
InputStream (clas abstract)
FileInputStream
FilterInputStream
DataInputStream implements DataInput
DataOutput (interfa)
OuputStream (clas abstract)
FileOutputStream
FilterOutputStream
DataOutputStream implements DataOutput

Menionm c n clasele neabstracte, afar de FileInputStream i FileOutputStream, apare


un constructor cu un parametru de tipul InputStream, respectiv de tipul OutputStream.

Observaie. Vom restrnge n continuare discuia la a prezenta cele mai simple faciliti pentru a
scrie n fiiere, respectiv de a citi din fiiere:
- octei : clasele FileOutputStream i FileInputStream ;
- date de tipuri primitive i iruri de caractere : clasele DataOutputStream i
DataInputStream;
- obiecte : vezi "Serializarea obiectelor".

79
Scrierea i citirea de octei
Clasele FileInputStream i FileOutputStream permit crearea unui flux de intrare, respectiv
ieire, asociat unui fiier cu un nume dat. Ele permit, printre altele, citirea i scrierea de octei.

Exemplul 1

Dorim s copiem un fiier cu un nume dat sub un alt nume.


Se ncearc nti crearea unui flux asociat fiierului cu numele citit de la intrare. Dac acest fiier nu
exist, programul se oprete.

Este apoi citit numele noului fiier i acesta este creat, tergnd eventuala versiune anterioar. Apoi
din primul fiier este citit consecutiv cte un octet (prin invocarea metodei read), care este copiat
n al doilea fiier. Sfritul fiierului este atins atunci cnd metoda read ntoarce valoarea -1.

import java.io.*;
import java.util.*;
class Copiere {
public static void main(String[] args) throws IOException {
Scanner sc = new Scanner(System.in);
System.out.print("Fisier cerut: ");
String fisier = sc.next();
InputStream is = null;
try { is = new FileInputStream(fisier); }
catch(FileNotFoundException e) {
System.out.println("Fisier inexistent");
System.exit(0);
}
System.out.print("Numele copiei : ");
fisier = sc.next();
OutputStream os = new FileOutputStream(fisier);
int c = 123;
while( (c=is.read()) != -1) os.write(c);
System.out.println("\nFisier copiat!");
is.close(); os.close();
}
}

Interfaa DataOutput
Conine metode menite a scrie, ntr-un flux de ieire neprecizat, date de tipuri primitive, precum i
iruri de caractere.
void write(int b)
void write(byte[] b) throws NullPointerException
void write(byte[] b, int init, int lung)
throws NullPointerException, IndexOutOfBoundsException
void writeBytes(String s) throws NullPointerException
void writeChars(String s) throws NullPointerException
void writeUTF(String s) void writeBoolean(boolean v)
void writeByte(int v) void writeShort(int v)
void writeChar(int v) void writeInt(int v)

80
void writeLong(long v) void writeFloat(float v)
void writeDouble(double v)

Interfaa DataInput

Este "complementara" interfeei DataOutput. Metodele citesc octei din fluxul de intrare; pe baza
acestor octei sunt reconstituite date de tipuri primitive sau iruri de caractere.
int skipBytes(int n) boolean readBoolean()
byte readByte() short readShort()
char readChar() int readInt()
long readLong() float readFloat()
double readDouble() String readLine()
String readUTF()
Observaie. Dac s-a ajuns la sfritul fluxului de intrare nainte de a se fi citit numrul dorit de
octei, va fi lansat excepia EOFException.
Se presupune c datele citite au fost scrise n fiier cu metodele complementare anunate n
interfaa DataOutput.

Clasa abstract OutputStream


Aceast clas include metodele:
void write(byte[] b) throws NullPointerException
void write(byte[] b, int init, int lung)
throws NullPointerException, IndexOutOfBoundsException
void flush()
void close()

Clasa abstract InputStream


Aceast clas cuprinde metodele:
void read(byte[] b) throws NullPointerException
void read(byte[] b, int init, int lung)
throws NullPointerException, IndexOutOfBoundsException
long skip(long n)
int available()
void close()

Clasele FilterInputStream i FilterOutputStream


class FilterOutputStream extends OutputStream {
protected OutputStream out;
FilterOutputStream(OutputStream out)
redefiniri ale metodelor clasei OutputStream
}
class FilterInputStream extends InputStream {
protected InputStream in;
FilterInputStream(InputStream in)

81
redefiniri ale metodelor clasei InputStream
}

Clasele FileOutputStream i FileInputStream

Metodele clasei FileOutputStream implementeaz, respectiv redefinesc metodele cu aceleai


nume i signatur din OutputStream, aplicndu-le pentru fluxul de ieire primit ca argument de
constructor.
class FileOutputStream extends OutputStream {
FileOutputStream(String nume)
throws SecurityException,FileNotFoundException
FileOutputStream(String nume, boolean adaug)
throws SecurityException,FileNotFoundException
redefiniri ale metodelor write, flush i close din OutputStream
}
Constructorul cu un parametru deschide fluxul de ieire nume.
class FileInputStream extends InputStream {
FileInputStream(String nume)
throws SecurityException,FileNotFoundException
int read()
redefiniri ale metodelor read, skip, available i close
din OutputStream
}
Constructorul clasei deschide fluxul de intrare constituit de fiierul precizat prin irul de caractere
nume.

Scrierea i citirea de date primitive

Dac dorim s scriem/citim tipuri primitive sau iruri de caractere, vom folosi clasele
DataOutputStream i DataInputStream.

Exemplul 2

ntr-o prim etap vom citi de la intrarea standard un numr natural n i apoi n numere reale; vom
crea n directorul curent un fiier cu numele out.dat n care vom scrie datele citite. ntr-o a doua
etap vom citi din fiierul out.dat valoarea n i cele n numere i le vom tipri la ieirea standard.
Prima etap este realizat de urmtorul program:
import java.io.*;
import java.util.*;
class Unu {
public static void main(String[] sir) throws Exception {
int n;
Scanner sc = new Scanner(System.in);
DataOutputStream dos = new DataOutputStream(
new FileOutputStream("out.dat"));
System.out.println("n= "); n = sc.nextInt();
dos.writeInt(n);
82
System.out.println("Introduceti " +n+ " numere reale:");
for(int i=0; i<n; i++) dos.writeInt(sc.nextInt());
dos.close();
}
}
unde:
- prin new FileOutputStream("out.dat") este creat fiierul out.dat;
- fluxul dos de tipul DataOutputStream folosete metodele writeInt i writeDouble
(anunate n interfaa DataOutput i implementate n clasa DataOutputStream) pentru a scrie n
fiierul out.dat;
- pentru nchiderea fiierului este invocat metoda close a clasei FilterInputStream
(motenit din DataOutputStream).
A doua etap este realizat de urmtorul program:
import java.io.*;
class Doi {
public static void main(String[] ss) throws Exception {
double d; int n;
DataInputStream dis = new DataInputStream(
new FileInputStream("out.dat") );
n = dis.readInt();
for (int i=0; i<n; i++)
System.out.print(dis.readInt() + "\t" );
System.out.println(); dis.close();
}
}
unde:
- prin new FileInputStream("out.dat") este deschis fiierul out.dat;
- fluxul dis de tipul DataInputStream folosete metodele readInt i readDouble
(anunate n interfaa DataInput i implementate n clasa DataInputStream) pentru a citi din
fiierul out.dat;
- pentru nchiderea fiierului este invocat metoda close a clasei FilterInputStream
(motenit din DataInputStream).

Clasele DataOutputStream i DataInputStream

Clasele DataOutputStream i DataInputStream ofer n plus posibilitatea ca fluxurile s nu


mai fie privite la nivel de octet, ci ca succesiuni de date primitive sau iruri de caractere. Datele vor
fi scrise n fluxul de ieire ntr-un format independent de modul de reprezentare al datelor n
sistemul pe care se lucreaz.
class DataOutputStream extends FilterOutputStream
implements DataOutput {
DataOutputStream(OutputStream out)
protected int written;
implementarea metodelor write din interfaa DataOutput
void flush()
final int size()
}

class DataInputStream extends FilterInputStream

83
implements DataInput {
DataInputStream(InputStream in)
implementarea metodelor read i skipBytes din interfaa DataOutput
}

Fluxuri ce lucreaz la nivel de caracter


O structur simplificat de clase este urmtoarea:
Object
Writer (clas abstract)
OutputStreamWriter
FileWriter
PrintWriter
Reader (clas abstract)
InputStreamReader
FileReader

din care vom folosi numai clasa PrintWriter, care ofer facilitatea de a scrie date n fluxul de
ieire ntr-un mod formatat, specific metodelor toString. Nu este lansat niciodat excepia
IOException.

class PrintWriter extends Writer {


protected Writer out;
PrintWriter(Writer out)
PrintWriter(Writer out, boolean adaug)
PrintWriter(OutputStream out)
PrintWriter(OutputStream out, boolean adaug)
void flush() void close()
void write(int c) void write(String s)
void write(String s, int init, int lung)
void print(boolean b) void println(boolean b)
void print(char c) void println(char c)
void print(int i) void print(int i)
void print(long l) void println(long l)
void print(float f) void println(float f)
void print(double d) void println(double f)
void print(char[] s) void println(char[] s)
void print(String s) void println(String x)
void print(Object obj) void println(Object obj)
void println()
}

Exemplul 3. Utilizarea clasei PrintWriter pentru scrierea n fiiere text.


irul cifrelor este scris att la ieirea standard, ct i n fiierul out.

import java.io.*;
class Print {
public static void main(String[] args) throws IOException {

84
FileOutputStream fos = new FileOutputStream("out");
PrintWriter out = new PrintWriter(fos);
PrintWriter stdout = new PrintWriter(System.out);
out.println("Cifrele zecimale sunt:");
for(int i=0; i<10; i++) out.print(i + "\t");
out.println();
stdout.println("Cifrele zecimale sunt:");
for(int i=0; i<10; i++) stdout.print(i + "\t");
stdout.println();
out.close(); // stdout.close();
}
}

Facem observaia c nenchiderea explicit a unui flux poate conduce la nenregistrarea n fiier a
tuturor datelor prevzute a fi scrise n el prin program.

85
Tem de autoinstruire

Consultai bibliografia pentru a afla despre :

1. Alte exemple legate de utlizare a fluxurilor de intare/iesire


2. Clasele din pachetul java.io
3. Metodele dedicate procesrii informaiei din fiiere de intare/ieire

86
Unitatea de nvare nr. 9

JAVA DATABASE CONNECTIVITY (JDBC)

Obiectivele Unitii de nvare nr. 9

Dup ce vei parcurge aceast unitate de nvare, vei reui s scriei


aplicaii utiliznd JDBC cu ajutorul crora vei putea s:
deschidei conexiunea ctre baza de date folosit;
creai un "obiect instruciune" prin care s transmitei
instruciuni SQL ctre gestionarul bazei de date;
regsii rezultatele interogrii.

Necesitatea folosirii Java DataBase Connectivity


JDBC (Java Database Connectivity) este o interfa standard SQL de acces la baze de date. API-ul
JDBC conine un set de clase i interfee pentru funcii folosite n manipularea bazei de date SQL,
cum ar fi conexiuni la baze de date, instruciuni SQL sau seturi de rezultate.
Folosind JDBC este uor de realizat transmiterea secvenelor SQL ctre baze de date relaionale. Cu
alte cuvinte, nu este necesar scrierea unui program pentru a accesa o baz de date Oracle, alt
program pentru a accesa o baz de date SQL Server i aa mai departe. Este de ajuns scrierea unui
singur program folosind API-ul JDBC i acesta va fi capabil s comunice cu drivere diferite,
trimind secvene SQL ctre baza de date dorit. Bineneles, scriind codul surs n Java, este
asigurat portabilitatea programului.
Principalele clase i interfee se gsesc n pachetul java.sql. Dintre acestea vom prezenta doar
urmtoarele interfee:
public interface Connection - stabilete conexiunea la baza de date;
public interface Statement - creaz un obiect instruciune ce conine o instruciune
SQL i l transmite bazei de date;
public interface ResultSet - permite regsirea rezultatelor interogrii;
public interface PreparedStatement - permite lucrul cu instruciuni SQL cu
parametri.

Vom prezenta n continuare numai principalele aspecte legate de JDBC.


Pentru a putea ajunge la o aplicaie efectiv, presupunem c cititorul este familiarizat cu forma
instruciunilor SQL i c baza de date este creat folosind Microsoft Access. De asemenea,
presupunem pentru moment c baza de date este local.

87
Crearea bazei de date cu Microsoft Access
Fie Agenda numele bazei de date, n care folosim tabelul Persoane. Secvena standard de
aciuni ce trebuie ntreprins este urmtoarea:
se deschide Microsoft Access;
Blank Access Database;
se selecteaz directorul de lucru;
File Name: Agenda;
Create;
se selecteaz Create Table in Design view i Tables;
Open;
se introduc numele cmpurilor + tipul lor;
se nchide;
se salveaz sub numele Persoane;
nu se alege cheie primar;
se selecteaz Persoane: se introduc nregistrri;
se nchid toate ferestrele.

Pentru exemplificare, plecm de la urmtorul coninut al tabelei Persoane:

nregistrarea bazei n driver-ul ODBC


Baza de date astfel creat este ns particular i nu este recunoscut ca atare de orice sistem. De
aceea trebuie folosit un "intermediar" care s permit accesarea i exploatarea ei. Un astfel de
intermediar este ODBC (Open DataBase Connectivity). Baza de date trebuie conectat la o surs de
baze de date ODBC, prin nregistrarea ei la driver-ul ODBC. Adresa sursei de date se precizeaz
prin:
String url="jdbc:odbc:surs_date"
Presupunem c numele sursei de date este AgendaODBC. Mergem succesiv n:
Administrative Tools;
Data Sources (ODBC);
88
System DSN sau UserDSN (baza de date a sistemului sau a utilizatorului);
Add;
selectez *.mdb;
Data Source Name: AgendaODBC;
Select;
merg n directorul meu;
selectez Agenda.mdb;
OK;
OK;
nchid.

ncrcarea driver-ului ODBC se realizeaz prin:


Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");

Conectarea la baza de date


Conectarea la baza de date se realizeaz prin crearea unui obiect de tipul Connection (interfa care
ncearc s realizeze o conexiune la baza de date asociat sursei de date ODBC). Modalitatea tipic
de conectare este urmtoarea:
try {
String url="jdbc:odbc:AgendaODBC";
Connection con =
DriverManager.getConnection(url,"user","parola");
}
catch (SQLException e) {...}

Se observ c trebuie trimis numele utilizatorului i o parol, pentru o eventual validare a


accesului la baza de date.

ntrebare: Care sunt operaiile implicate de procesul de conectare la o baz de date?


O conexiune (sesiune) la o baz de date reprezint un context prin care sunt trimise secvene SQL i
primite rezultate. ntr-o aplicaie pot exista mai multe conexiuni simultan la baze de date diferite
sau la aceeai baz.

Rspuns: Procesul de conectare la o baz de date implic dou operaii:


1. ncrcarea n memorie a unui driver corespunztor
2. realizarea unei conexiuni propriu-zise

89
Executarea de instruciuni SQL
Pentru executarea de instruciuni SQL trebuie mai nti creat un "obiect instruciune", adic un
obiect de tipul interfeei Statement:
Statement stmt = con.createStatement();
unde createStatement este o metod a interfeei Connection. Pe baza acestui obiect este posibil
executarea de instruciuni SQL, cu primirea rezultatelor cutrii.
n continuare trebuie creat un ir de caractere care s reprezinte o comand SQL valid:
String sql = "...";
Urmeaz transmiterea cererii i obinerea rezultatului interogrii folosind una dintre metodele:
public ResultSet executeQuery(String sql) throws
SQLException
unde sql reprezint o instruciune SQL de tip SELECT. Este ntors un obiect de tipul
ResultSet care permite regsirea rezultatelor cererii;
public int executeUpdate(String sql) throws SQLException
unde sql reprezint o instruciune SQL de unul dintre tipurile INSERT, UPDATE, sau DELETE.
Este ntors numrul liniei (nregistrrii) afectate.

Interfaa:
public interface ResultSet
permite regsirea, sub forma unui tabel, a rezultatelor cutrii la executarea unei metode
executeQuery. Un obiect de acest tip menine un cursor la linia curent din tabel, iniial la prima
linie a acestuia. Dintre metodele interfeei ResultSet descriem deocamdat numai urmtoarele:
public boolean next()
ntoarce true dac i numai dac mai exist linii n rs, caz n care se trece la urmtoarea nregistrare;
public gettip(String s)
ntoarce coninutul cmpului cu numele s din nregistrarea curent ca o valoare de tipul tip din Java;
tip poate fi String, Int etc.

Observaie Obiectele con i stmt trebuie "nchise" n final prin invocarea metodei
close().

nregistrrile (liniile) din baza de date cu care lucrm corespund informaiilor


Exemplul 1 despre o persoan i au cmpurile Nume, Prenume, Localitate i Salariu,
cu semnificaii evidente. Corespunztor, scriem clasa Persoana n care
constructorul iniializeaz cmpurile, iar metodele ntorc valorile lor.

class Persoana {
private String nume,prenume,localitate;
private int salariu;
public Persoana(String n, String p, String l, int s)
{
nume=n; prenume=p; localitate=l; salariu=s;
}
public String rNume() { return nume; }

90
public String rPrenume() { return prenume; }
public String rLocalitate() { return localitate; }
public int rSalariu() { return salariu; }
public String toString() {
return "\t"+ nume+"\t"+prenume+"\t"+
localitate+"\t"+salariu;
}
}

Asupra bazei de date vom executa doar dou operaii:


selectarea tuturor nregistrrilor cu un nume i o localitate date:
SELECT * FROM PERSOANE WHERE NUME='...' AND LOCALITATE='...'
pentru care vom folosi metoda executeQuery;
inserarea unei noi nregistrri:
INSERT INTO PERSOANE (NUME,PRENUME,LOCALITATE,
SALARIU)VALUES('...','...','...','...')
pentru care vom folosi metoda executeUpdate.
Aceste operaii corespund metodelor caut i adaug din clasa BD, clasa care are un cmp stmt de
tipul Statement, care primete valoare prin constructor:

import java.sql.*;
class BD {
Statement stmt;
BD(Statement s) { stmt = s; }

public void cauta (String nume, String loc)


throws Exception {
Persoana p = null;
String my_query = "SELECT * FROM PERSOANE WHERE NUME='" +
nume + "' AND LOCALITATE='" + loc + "'";
ResultSet rs = stmt.executeQuery(my_query);
while ( rs.next() ) {
p = new Persoana(rs.getString("Nume"),
rs.getString("Prenume"),
rs.getString("Localitate"),
rs.getInt("Salariu") );
System.out.println(""+p);
}
}

public void adauga(Persoana p) throws Exception {


String my_stmt =
"INSERT INTO PERSOANE (NUME,PRENUME,LOCALITATE,SALARIU)"
+ " VALUES('" + p.rNume() + "','" + p.rPrenume() + "','"
+ p.rLocalitate()+"','" + p.rSalariu() + "');";
int i = stmt.executeUpdate(my_stmt);
System.out.println(""+p);
}
}

91
Clasa Agenda de mai jos conine numai metoda principal. Aceast metod prevede crearea unei
conexiuni con la baza de date, a unui "obiect instruciune" stmt i a unui obiect bd de tipul BD. n
continuare sunt citite de la intrare iruri de caractere i se ntreprind urmtoarele aciuni:
dac primul ir de caractere citit este "INSERT", mai sunt citite 3 iruri de caractere i un numr
ntreg;
dac primul ir de caractere citit este "SELECT", atunci mai sunt citite dou iruri de caractere
nume i loc;

import java.sql.*;
class Agenda {
public static void main(String[] args) throws Exception {
String id,nume,prenume,loc; int sal; Persoana P;
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
String url = "jdbc:odbc:AgendaODBC";
Connection con =
DriverManager.getConnection(url,"Vasile","Sile");
Statement stmt = con.createStatement();
BD bd = new BD(stmt);
Scanner sc = new Scanner(System.in);
for ( ; ; ) {
System.out.println("*** Comanda noua : ***");
id = sc.next();
if (id.equals("STOP")) break;
else if (id.equals("SELECT")) {
nume = sc.next(); loc = IO.readString();
bd.cauta(nume,loc);
}
else if (id.equals("INSERT")) {
nume = sc.next(); prenume = sc.next();
loc = sc.next(); sal = sc.next();
P = new Persoana(nume,prenume,loc,sal);
bd.adauga(P);
}
else System.out.println("Comanda incorecta");
}
con.close(); stmt.close();
}
}

De exemplu, dac vom introduce:


SELECT Ionescu Sibiu
va fi afiat:

Ionescu Ion Sibiu 510


Ionescu Vasile Sibiu 560
Ionescu Dan Sibiu 460

92
Tem de autoinstruire

1. Consultai bibliografia pentru a afla cum se lucreaz cu toate clasele i interfeele pentru funcii
folosite n manipularea bazelor de date SQL.

Teste de control

1. Scriei un program pentru interogarea unei baze de date care ine evidena produselor unui
magazin sportiv. Baza de date conine urmtoarele informaii: nume produs, tip produs, nr
buci, pre, disponibil n stoc. S se introduc produse noi n baza de date i s se verifice
adugarea lor ca noi nregistrri n baza de date. S se afieze toate produsele de tipul
nclminte disponibile n stoc.

93
Unitatea de nvare nr. 10

SERVLET-URI

Obiectivele Unitii de nvare nr. 10

Dup ce vei parcurge aceast unitate de nvare, vei reui s:


s gestionai servlet-uri folosind server-ul Tomcat;
cunoatei ciclul de viaa al unui servlet;
transmitei date ctre un server folosind formulare HTML;
prelucrai date folosind un servlet.

Despre servlet-uri
Servlet-urile sunt aplicaii Java aflate pe server i executate de ctre acesta. Serverul de Web, la
executarea servlet-ului, trimite napoi browser-ului un fiier HTML, pe care acesta n afieaz
corespunztor; n particular, browser-ul nu trebuie s tie nici mcar ce nseamn un servlet.

n modalitatea clasic, serverul de Web primete - de exemplu - o cerere de tipul:


GET nume_fisier
i ntoarce fiierul respectiv. Aici nume_fisier este numele unei clase (servlet) a crei executare
ntoarce browser-ului un fiier HTML pe care browser-ul l afieaz clientului. Acesta poate
completa unele informaii i retrimite o cerere nou serverului de Web, care prelucreaz
informaiile primite i retrimite rezultatul din nou sub forma unui document HTML. Procesul se
poate repeta de oricte ori. Un pas al acestui proces poart numele de tranzacie. Este momentul s
precizm c serverul nu pstreaz datele de la o tranzacie la alta dect (firete) dac le stocheaz
explicit (de exemplu ntr-un fiier sau ntr-o baz de date).

Partea din serverul de Web care ateapt cereri (n cazul nostru cereri de executare a unui servlet)
este numit demon HTTP, deoarece are caracteristicile unui fir de executare demon. Serverul poate
efectua "simultan" tranzacii cu mai muli clieni, pornind pentru fiecare un fir de executare. Mai
menionm c schimbul de informaii ntre server i fiecare client se face n esen prin socket-uri,
dar la un nivel superior i n mod transparent pentru utilizator.

Servlet-urile nu sunt subiectul unor restricii. Servlet-urile creaz documente HTML dinamice prin
succesiunea de tranzacii descrise mai sus. Independena de platform a limbajului Java se extinde
n mod natural i logic asupra servlet-urilor (spre deosebire de script-urile CGI care sunt
independente de platform i care sunt n plus mult mai lente).

94
Gestionarea servlet-urilor
Reamintim c am creat directorului nostru propriu myapp de aplicaii C:\Tomcat3\jakarta-
tomcat-3.3.2\webapps cu urmtoarea structur:
myapp
WEB-INF (*)
classes (**)
i c n (*) am copiat fiierul web.xml din
C:\Tomcat3\jakarta-tomcat-3.3.2\webapps\examples\WEB-INF
Aplicaiile noastre (servlet-urile) vor fi plasate n (**).
Mai sunt necesare urmtoarele:

nainte de compilarea servlet-urilor facem setarea:


set classpath=
C:\Tomcat3\jakarta-tomcat-3.3.2\lib\common\servlet.jar;.
Variant: adugm calea de mai sus n comanda set classpath din autoexec.bat.

Dac vrem s executm C.class obinut prin compilarea unui servlet aflat n directorul
myapp, deschidem Internet Explorer i specificm:
http://localhost:8080/myapp/servlet/C (***)
cu observaia c servlet nu este director, ci informaie c lucrm cu servlet-uri.

Dac n (**) crem un pachet HG, n interiorul su cu clasele publice A (principal), B i C,


atunci:
- clasele A, B, C vor ncepe cu: package HG;
- din interiorul pachetului HG la setarea de mai sus adugm sufixul: ;..
i compilm normal clasa A;
- (***) devine: http://localhost:8080/myapp/servlet/HG.A

Un prim exemplu
Prezentm n continuare un prim exemplu, cu cteva explicaii necesare, urmnd ca unele interfee,
clasele i metode referitoare la servlet-uri s fie descrise n continuare n detaliu.

Considerm urmtorul servlet:


import java.io.*;
import javax.servlet.*; import javax.servlet.http.*;
public class Salut extends HttpServlet {
public void doGet(HttpServletRequest req,
HttpServletResponse resp)
throws IOException, ServletException {
resp.setContentType("text/html");
PrintWriter out = resp.getWriter();
String s = req.getParameter("nume");
int val = Integer.parseInt(req.getParameter("val"));
resp.setContentType("text/html");
out.println("<html>");
out.println("<body>");
out.println("<head>");
out.println("<title>Salut!</title>");

95
out.println("</head>");
out.println("<body>");
out.println("<h1>Salutare!</h1>");
s += " Vasilica" + " " + val;
out.println(s);
out.println("</body>"); out.println("</html>");
System.out.println("O.K.");
}
}

Salut este un servlet deoarece extinde clasa HTTPServlet.

Pentru lucrul cu servlet-uri trebuie incluse declarrile:


import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

Servlet-ul Salut conine metoda doGet care este invocat la o cerere HTTP de tipul GET.
Variabilele resp i req sunt obiecte de tipul indicat, care corespund cererii primite de la client,
respectiv rspunsului care va fi transmis clientului.

Considerm urmtoarea cerere a clientului:


http://adresa_server:8080/myapp/servlet/Salut?nume=Vasile&val=20
prin care se cere executarea servlet-ului Salut cu precizarea a doi parametri (iruri de caractere):
nume cu valoarea Vasile i val cu valoarea 20. n mod implicit, cererea este de tipul GET;
corespunztor, va fi invocat metoda doGet a servlet-ului.

Prin invocarea metodei setContentType se precizeaz c tipul MIME al rspunsului ntors


clientului este un document HTML.

Prin invocarea metodei getWriter obiectul resp creeaz un flux de ieire out n care va fi
introdus documentul HTML.

n continuare obiectul req invoc metoda getParameter pentru a capta n variabilele locale s i
val valorile parametrilor din cererea HTTP care au numele nume i val. Apoi n fluxul out este
introdus un ir de caractere ce reprezint documentul HTML ce va fi transmis clientului.

Browserul va afia pe ecranul clientului:

n plus, n fereastra nou deschis de Tomcat va aprea:


O.K.

96
Formulare n HTML
n exemplul de mai sus, clientul a trimis (prin intermediul browser-ului) o cerere severului de Web,
care a rspuns cu un document HTML, pagina Web respectiv fiind afiat de browser. Dorim ns
mai mult i anume s realizm un dialog "continuu" ntre client i server. O posibilitate const n a
folosi formularele din HTML, variant studiat n acest paragraf. O alt posibilitate, dezvoltat ntr-
un paragraf ulterior, const n a folosi applet-uri pe partea de client.

Formulare
Formularele stau la baza crerii, cu ajutorul servlet-urilor, a paginilor HTML dinamice i a
procesrii de ctre server a datelor transmise de client prin intermediul lor. Pot fi create formulare
multiple, dar independente. Ele au forma:

<form method=metoda action=clasa>


elemente de control
</form>

Despre metoda i clasa vom vorbi mai trziu.

Principalele elemente de control sunt:


cmpurile de text:
<input name=nume type=text value=val maxlength=n >

ariile de text:
< textarea name=nume cols=m rows=n >

butoane de validare:
<input name=nume type=checkbox value=val checked >
permit alegerea multipl (a mai multor opiuni), care sunt iruri de caractere. Toate opiunile trebuie
s aib acelai nume nume i pentru fiecare poate fi precizat, prin prezena lui checked, dac este
selectat.

butoane radio:
<input name=nume type=radio value=val checked >
difer de butoanele de validare prin aceea c exact o opiune poate fi aleas.

meniuri (liste derulante):


<select>
<option value =val selected> text </option>
. . . . . . .
<option value =val selected> text </option>
</select>
unde opiunile iniial selectate sunt precizate prin selected.

butoane de comand:
<input name=nume type=tip value=val >
unde tip poate fi:
reset : cmpurile formularului revin la valorile iniiale;
submit : cmpurile formularului sunt trimise ctre server (vom reveni);
push : este ntreprins aciunea definit de autorul formularului.

97
nume de fiier:
<input type=file name=nume >
unde nume este numele unui fiier care este transmis; va aprea i un buton Browse a crui
acionare va permite selctarea fiierului prin navigare n structura de directoare.

Exemplul 1 S considerm urmtorul document HTML cu numele form.html:

<html>
<head> <title> Formular </title> </head>
<body>
<form method=GET action=???>
<p> Numele <input type=text name="Nume">
<p>
Ai studiat Informatica in liceu?
<input type=radio name="radio" value="Da" checked>
Da &nbsp &nbsp
<input type=radio name="radio" value="Nu"> Nu
<p>
Selecteaza cursurile favorite <br>
<input type=checkbox value="1"> Programare <br>
<input type=checkbox value="2" checked> Algoritmi <br>
<input type=checkbox value="3" checked>
Baze de date <br>
<p>
Forma de invatamant:
<Select name="valuta">
<option value="Inf"> Informatica </option>
<option selected value="MI"> Mat-Inf </option>
<option value="Col"> Colegiu </option>
</Select>
<p> Fisier catre server:<br>
<input type=file value="fisier" size=30>
<p>
Butoane:<br>
<input type=reset name="Exit" value="Iesire">
<input type=submit name="Cerere" value="Cerere">
</form>
</body>
</html>

Browser-ul va afia:

98
Trimiterea de date ctre server

Reamintim c marcajul form are forma:

<form method=metoda action=clasa>

Exist dou modaliti de trimitere (corespunztoare celor dou tipuri de cereri HTTP), dup cum
metoda este:

GET : datele din formular sunt adugate n URL-ul trimis, sub forma de perechi
(nume,valoare). Ele vor fi accesibile servlet-ului prin metodele:
getQueryString, getParameter i getParameterValues;

POST : datele sunt nglobate n antetele cererii. Ele vor fi accesibile servlet-ului prin
metoda getParameterValues sau prin citire din ServletInputStream.

n funcie de metoda aleas, servlet-ul specificat prin clasa va executa metoda doGet sau metoda
doPost. Alte detalii despre cele dou tipuri de cereri HTML, respectiv despre metodele doGet i
doPost, vor fi furnizate ulterior.

Dorim s trimitem iruri de caractere ctre server. Vom folosi un formular care conine doar un
cmp de text i un buton submit. La completarea cmpului de text i apsarea butonului, va fi
ntors mesajul transmis.

import java.io.*;
import java.awt.*; import java.awt.event.*;
import javax.servlet.*; import javax.servlet.http.*;

public class TF extends HttpServlet {


public void doGet(HttpServletRequest req,
HttpServletResponse resp)
throws ServletException,IOException {
String t=""; // t = documentul HTML
PrintWriter out = resp.getWriter();
resp.setContentType("text/html");
t += "<html><head><title>Camp de text</title>"
+"</head><body>";
t += "<form method=GET action=/myapp/servlet/TF>";
String s = req.getParameter("tf");
if (s != null) t += "Ati trimis : " + s;
t += "<p><input type=text name=tf" +
" maxlength=20>";
t += "<p><input type=submit name=Buton" +
" value=Apasa>";
t += "</body></html></form>";
out.println(t);
}
}

99
Observaie. O alternativ la executarea servlet-ului TF n modul precizat este de folosi urmtorul
document HTML:

<html>
<head><title>Camp de text</title>
</head>
<body>
<form method=GET
action=http://localhost:8080/myapp/servlet/TF>
<p><input type=text name=tf maxlength=20>
<p><input type=submit name=Buton value=Apasa>
</form>
</body>
</html>

Reamintim c acest document (fie D.html numele su) va fi plasat n mod tipic pe serverul de
Web n directorul myapp, iar el va fi cerut de client prin:
http://adresa_server:8080/myapp/D.html.

100
Clase i interfee folosite n lucrul cu servlet-uri
Clasele i interfeele pe care le-am ales pentru a fi prezentate apar n urmtoarele dou pachete:

- Pachetul javax.servlet

Interfee:
public interface Servlet
public interface ServletRequest
public interface ServletResponse
Clase:
public abstract class ServletInputStream
public abstract class ServletOutputStream
public abstract class GenericServlet
implements Servlet, Serializable

- Pachetul javax.servlet.http

Interfee:
public interface HttpServletRequest extends ServletRequest
public interface HttpServletResponse extends ServletResponse
Clase:
public abstract class HttpServlet extends GenericServlet

Prezentarea va fi fcut tratnd separat clasele/interfeele referitoare la: servlet-uri, cereri,


rspuns, fluxuri.

Servlet-uri

Ne vom ocupa n principal de clasa HTTPServlet, care extinde GenericServlet, care la


rndul su implementeaz interfaa Servlet. Precizm c GenericServlet definete un
servlet independent de protocol, iar HttpServlet este specific protocolului HTTP.

Restrngem prezentarea la dou metode de serviciu ale servlet-urilor:

protected void doGet(HttpServletRequest req,


HttpServletResponse resp) throws ServletException,
IOException

Aceast metod este invocat de server n momentul n care primete o comand HTTP de tip
GET. n mod normal, metoda trebuie ca, folosind informaia din parametrul req, s ntreprind
aciunile corespunztoare i s plaseze rezultatele n fluxul de ieire creat pe baza parametrului
resp.

protected void doPost(HttpServletRequest req,


HttpServletResponse resp) throws ServletException,
IOException

Aceast metod difer de doGet prin aceea c este invocat de server n momentul n care
primete o comand HTTP de tip POST. Alte diferene vor fi prezentate n continuare.

101
Ciclul de via al unui servlet
Servlet-ul este un program Java care ruleaz n cadrul unui server de Web. De fapt serverul de Web
creaz un container n cadrul cruia este executat servlet-ul. Pentru simplificare, vom considera c
acest container este chiar serverul de Web.

n literatura de specialitate apare afirmaia "servlet-ul este un applet pe partea de server". Afirmaia
se bazeaz pe analogia ntre ciclul de via al unui applet i ciclul de via al unui servlet.

Principalele metode care guverneaz lucrul cu servlet-uri sunt:

Metoda init()
este declarat n clasa GenericServlet prin:
public void init() throws ServletException
Metoda este invocat numai la crearea servlet-ului. Un servlet este creat prima dat cnd un
utilizator invoc URL-ul corespunztor servlet-ului. n concluzie, la invocri ulterioare
metoda init() nu mai intr n aciune. Prin aceast metod putem face diverse iniializri,
ca de exemplu stabilirea unei conexiuni la o baz de date.
Observaie. Din momentul executrii metodei init, modificrile fcute pe server asupra
servlet-ului nu sunt efective dect dup oprirea i repornirea serverului de Web.

Metoda service()
este declarat n clasa GenericServlet prin:
public abstract void service(ServletRequest req,
ServletResponse resp)
throws ServletException, java.io.IOException

De fiecare dat cnd serverul de Web primete o cerere pentru un servlet, lanseaz un nou
fir de executare i invoc metoda service. Metoda detecteaz tipul cererii HTTP i
invoc n mod corespunztor una dintre metodele de serviciu doGet i doPost. Posibila
existen mai multor fire de executare care folosesc servletul ridic probleme de concuren,
a cror rezolvare cade n sarcina programatorului.

Putem evita metoda service furniznd implementri pentru metodele doGet i doPost,
aa cum vom proceda de obicei n continuare. Totui metoda service i gsete utilitatea
n situaia existenei unei condiii n funcie de care se invoc doGet sau doPost. Dac
dorim ca ambele tipuri de cerere s fie tratate identic, specificm n doGet aciunea
corespunztoare i introducem metoda doPost urmtoare:

public void doPost(HttpServletRequest req,


HttpServletResponse resp)
throws ServletException, IOException {
doGet(req,resp);}

Metoda destroy()
este declarat n clasa GenericServlet prin:
public void destroy()
Aceast metod este invocat de serverul de Web la cererea administratorului sau n cazul n
care servlet-ul nu primete cereri o perioad ndelungat de timp. n metod sunt precizate
de obicei eliberri de resurse alocate prin init(), ca de exemplu ntreruperea unei
conexiuni cu o baz de date. Instana servlet creat prin init() este distrus.

102
Recapitulnd, ciclul de via al unui servlet poate fi figurat astfel:

Prima init
cerere

Cerere
service
Rspuns

destroy

Cereri

Prezentm n continuare cteva metode ale interfeei HTTPServletRequest, preciznd care


dintre ele este motenit de la interfaa ServletRequest.

Interfaa HTTPServletRequest definete un obiect care permite servlet-ului s identifice


informaia trimis de client. Containerul servlet creaz un obiect de acest tip, coninnd cererea
ctre servlet, pe care l transmite ca argument metodelor de serviciu. Sunt incluse aici numele i
valorile parametrilor din cerere, atribute i fluxul de intrare.

public String getMethod()


ntoarce numele metodei coninut n cerere;
public String getQueryString()
ntoarce irul de parametri ce urmeaz cii din n URL. Dac nu apar parametri, metoda
ntoarce null. Cum de obiciei prima tranzacie se face fr parametri, metoda poate fi folosit
pentru a identifica aceast prim tranzacie;
public String getRequestURI()
ntoarce poriunea din cerere dintre numele protocolului i querystring;
public String getContextPath()
ntoarce poriunea din URI care precizeaz contextul cererii;
public String getServletPath()
ntoarce poriunea din URI care invoc servlet-ul.

Urmtoarele metode sunt motenite de la interfaa ServletRequest:


public String getRemoteAddr()
ntoarce adresa IP numeric a clientului;
public String getServerName()
ntoarce adresa IP simbolic a serverului;
int getServerPort()
ntoarce portul prin care comunic serverul;
public String getContentType()
ntoarce tipul MIME al cererii sau null (dac acest tip nu a fost precizat).

Metoda getInputStream va fi prezentat atunci cnd vom vorbi despre fluxuri.

103
Urmtoarele dou metode permit accesarea parametrilor din irul de parametri adugai comenzii
HTTP, de exemplu prin acionarea unui buton de tip submit.

public String getParameter(String nume)


ntoarce valoarea parametrului-cerere nume, sau null dac acesta nu exist. n cazul n care
parametrului-cerere i sunt asociate mai multe valori (caz n care de fapt trebuie folosit metoda
getParameterValues), metoda ntoarce prima informaie ntoars de metoda
getParameterValues.

public String[] getParameterValues(String nume)


ntoarce un tablou cu valorile asociate parametrului-cerere nume. Metoda este folosit atunci
cnd parametrul-cerere are mai multe valori (de exemplu cele selectate n cadrul unui meniu).
Dac nume nu exist, este ntors null.

Exemplul 2 Considerm urmtorul servlet:

import java.io.*;
import javax.servlet.*; import javax.servlet.http.*;
public class Ex1 extends HttpServlet {
public void doGet(HttpServletRequest req,
HttpServletResponse resp)
throws ServletException,IOException {
resp.setContentType("text/html");
ServletOutputStream out = resp.getOutputStream();
String RemoteAddr = req.getRemoteAddr();
String Method = req.getMethod();
String ServerName = req.getServerName();
int ServerPort = req.getServerPort();
String RequestURI = req.getRequestURI();
String ContextPath = req.getContextPath();
String ServletPath = req.getServletPath();
out.println(
"<html><head><title>Info_Client</title></head>" +
"<body> <p> RemoteAddr : " + RemoteAddr +
"<br> Method : " + Method +
"<br> ServerName : " + ServerName +
"<br> ServerPort : " + ServerPort +
"<br> RequestURI : " + RequestURI +
"<br> ContextPath : " + ContextPath +
"<br> ServletPath : " + ServletPath +
"</body></html>");
}}

La executarea sa de pe calculatorul local, browser-ul va afia:


RemoteAddr : 127.0.0.1
Method : GET
ServerName : localhost
ServerPort : 8080
RequestURI : /myapp/servlet/Ex1
ContextPath : /myapp
ServletPath : /servlet/Ex1

104
Rspuns
Interfeele:

public interface ServletResponse


public interface HttpServletResponse extends ServletResponse

definesc un obiect prin intermediul cruia servlet-ul transmite un rspuns clientului, rspuns dirijat
ctre fluxul de ieire ataat acestui obiect. HttpServletResponse furnizeaz n plus
funcionalitate HTTP.
Dintre metode menionm doar urmtoare;e:
public void setContentType(String tip)
n care tip precizeaz versiunea protocolului MIME (de exemplu "text/html") folosit la
transmiterea rspunsului;
public void addHeader(String s1, String s2)
prin care se adaug antetul (header-ul) cu numele s1 i cu valoarea s2. Un exemplu va fi
prezentat n capitolul referitor la transmiterea de fiiere.

Fluxuri
Pentru fluxurile de intrare este folosit clasa:

public abstract class ServletInputStream extends InputStream

Un flux de intrare poate citi date la nivel de octet, furniznd n plus metoda readLine pentru
citirea de linii:
public int readLine(byte[] octeti, int depl, int nr)
citete n octeti cte o linie din fluxul de intrare, plecnd de la poziia curent, cu deplasarea
depl. Metoda se termin fie la detectarea sfritului de linie dup citirea a maximum nr octei
(caz n care rezultatul ntors este numrul de octei citii), fie la citirea a nr octei fr detectarea
sfritului de linie (caz n care ntoarce valoarea -1).

Pentru un obiect-cerere (de unul dintre tipurile ServletRequest sau


HttpServletRequest) putem regsi fluxul de intrare prin invocarea urmtoarei metode a
clasei ServletRequest :
public ServletInputStream getInputStream()

Pentru fluxurile de ieire este folosit clasa:


public abstract class ServletOutputStream extends
OutputStream

Pentru un obiect-rspuns (de unul dintre tipurile ServletResponse sau


HttpServletResponse) putem regsi fluxul de ieire prin invocarea uneia dintre metodele:

public ServletOutputStream getOutputStream()


din interfaa ServletResponse. Este folosit dac dorim ca transmiterea s se fac la nivel
de octet;

105
public PrintWriter getWriter()
din interfaa HttpServletResponse. Este folosit dac dorim ca transmiterea s se fac la
nivel de octet. Invocarea metodei flush() ncheie acest rspuns. Setarea versiunii MIME (prin
setContentType) trebuie fcut nainte de a folosi acest flux de ieire.

Dorim s trimitem serverului un nume de fiier, folosind metoda POST.


Exemplul 3
Servletul va folosi fluxul su de intrare pentru a citi din el numele fiierului.

Vom afia nti urmtorul document HTML:

<html>
<head> <title> Formular </title> </head>
<body>
<form method=POST
action=http://adresa_server:8080/myapp/servlet/File>
<p> Fisier catre server:<br>
<input type=file name=fisier >
<p>
Buton:<br>
<input type=submit name=Buton value=Apasa>
</form>
</body>
</html>

Vor aprea un cmp de text, un buton cu eticheta Browse i un al doilea buton cu eticheta Apasa.

Acionarea butonului Browse permite alegerea unui fiier al crui nume (cu calea complet) este
nscris n cmpul de text. Acionarea butonului Apasa transmite serverului aceste informaii, care
le prelucreaz prin urmtorul servlet:

import java.io.*; import java.util.*;


import javax.servlet.*;
import javax.servlet.http.*;

public class File extends HttpServlet {


public void doPost(HttpServletRequest req,
HttpServletResponse resp)
throws IOException, ServletException {
ServletInputStream f = req.getInputStream();
String s=""; int c;
while( (c=f.read()) != -1) s += (char) c;
StringTokenizer st = new StringTokenizer(s,"&");
106
while( st.hasMoreTokens() )
System.out.println(st.nextToken());
System.out.println( req.getParameter("Buton") );
}
}

Sunt necesare mai multe observaii. Am citit, informaia din fluxul de intrare. Aceat informaie
este prelucrat cu StringTokenizer, pentru care am prevzut delimitatorul '&'.

Presupunnd c am ales s trimitem numele de fiier autoexec.bat din C:, informaia afiat
de server n fereastra Tomcat va avea forma:

fisier=C%3A%5CAUTOEXEC.BAT
Buton=Apasa
null

deoarece :
- la transmiterea informaiei, caracterul ':' este nlocuit prin irul de caractere "%3A", iar
caracterul '\' este nlocuit prin irul de caractere "%5C", conform schemei de codare implicite;
- metoda getParameter ntoarce null pentru c am ales s citim din fluxul de intrare; altfel
spus, metodele getInputStream i getParameter sunt incompatibile.

107
Tem de autoinstruire

Consultai bibliografia pentru a afla despre :

1. Alte exemple de servlet-uri


2. Toate clasele utilizate pentru realizarea servle-urilor
3. Exemple complexe de formulare HTML i modul n care ele pot fi realizate

Teste de control

1. Fiierul text agenda.txt conine numerele de telefon ale mai multor persoane. Fiecare linie din
agend este de forma nume prenume,telefon. Realizai un servlet care s primeasc, prin
intermediul unui parametru transmis folosind metoda GET, un prenume i s genereze o pagin
HTML care s conin numele i numerele de telefon ale tuturor persoanelor din agend care au
prenumele respectiv, precum i numrul lor. Coninutul agendei telefonice se va ncrca din
fiierul text ntr-o structur de date adecvat o singur dat, n momentul iniializrii servlet-
ului.

2. Fiierul text dictionar.txt conine traducerile unor cuvinte din limba romn n limba englez.
Prima linie din fiier conine numrul cuvintelor din dicionar, iar pe fiecare din urmtoarele
linii sunt perechi de forma nume cuvnt romn,cuvnt englez. Scriei un servlet care s
primeasc, prin intermediul unui parametru transmis folosind metoda GET, un cuvnt n limba
romn i s genereze o pagin HTML care s conin traducerea cuvntului respectiv n limba
englez sau un mesaj corespunztor dac respectivul cuvnt nu se gsete n dicionar.
Coninutul dicionarului se va ncrca din fiierul text ntr-o structur de date adecvat o singur
dat, n momentul iniializrii servlet-ului.

108
Bibliografie
[1] Georgescu Horia, Introducere n universul Java, Editura Tehnic,
Bucureti, 2002
[2] Georgescu Horia, Boriga Radu, Programare distribuit n Java, Editura
Universitii din Bucureti, 2008
[3] Mahmoud Qusay, Distributed Programming with Java, Manning, 2000
[4] Tanas tefan, Andrei tefan, Olaru Cristian, Java de la 0 la expert (ediia
a II-a), Editura Polirom, 2007
[5] Arnold K., Gosling J., The Java Programming Language. Second Edition,
Addison - Wesley, 1997

109

S-ar putea să vă placă și