Sunteți pe pagina 1din 12

15

Proiectare Web Lucrarea de laborator Nr. 3



PROGRAMAREA OBIECTUALA IN JAVA


Limbajul Java este un limbaj n ntregime orientat pe obiecte: n Java (spre deosebire de C++) nu
exista variabile sau functii care sa nu fie membre ale unei clase. Conceptele de programare obiectuala sunt
aceleasi ca si n C++: programele sunt organizate ca si colectii de obiecte cooperante, fiecare obiect fiind o
instanta a unei clase. Fiecare clasa reprezinta abstractizarea unui tip de entitate din realitatea modelata, iar
clasele sunt membre ale unei ierarhii de clase, corelate ntre ele prin relatii de mostenire. Orice obiect este
ncapsulat, ceea ce nseamna ca reprezentarea lui (adica structura interna a acelui obiect) nu este vizibila
utilizatorilor, care au acces doar la functiile (metodele) pe care acel obiect este capabil sa le execute.
3.1. CLASE SI OBIECTE
Forma completa de definire a unei clase este urmatoarea:
lista_modificatori class nume_clasa extends nume_clasa_de_baza
implements lista_interfete
{
// corpul clasei;
}
Definitia unei clase trebuie sa contina n mod obligatoriu cuvntul cheie class, numele clasei si
corpul clasei. Toti ceilalti termeni din definitie sunt optionali. nainte de cuvntul class poate exista o lista
de modificatori (despartiti prin spatiu) care atribuie anumite proprietati clasei definite. Acesti modificatori
pot fi din categoria cuvintelor cheie: public, abstract si final. Pentru a deriva o clasa dintr-o clasa de
baza (superclasa) se foloseste cuvantul cheie extends urmat de numele clasei de baza.
n Java, spre deosebire de C++, poate exista o singura clasa de baza (Java nu supporta mostenirea
multipla) si n lipsa mostenirii multiple se folosesc interfete Java. O interfata Java (interface) este un tip
de date abstract, un fel de clasa n care nici una din metode nu este definita n intregime (lipseste corpul
metodei, doar s-a declarat metoda). O clasa implementeaza o interfata daca declara acest lucru n declaratia
clasei prin cuvntul cheie implements urmat de numele interfetei si daca defineste toate metodele declarate
n interfata. O clasa poate implementa mai multe interfete utilizand cuvntul cheie implements urmat de
numele interfetelor separate de virgula.
n Java nu poate exista o declaratie de clasa independenta de corpul clasei. Corpul unei clase contine
o serie de declaratii de membrii ai clasei si constructori. Membrii unei clase pot fi att atribute ct si metode.
Un membru declarat ntr-o clasa este disponibil prin numele sau oriunde n interiorul acelei clase.
Atributele unei clase (variabile membru) pot fi de orice tip de data primitiv sau referinta (clasa sau
tablou). Declaratia atributelor are urmatoarea forma generala:
lista_modificatori_atribut tip_data lista_declaratori_variabile;
unde lista_declaratori_variabile cuprinde o serie de declaratori de variabila separati prin virgula.
Un declarator de variabila are una din urmatoarele forme generale:
nume_variabila = expresie_initializare;
nume_tablou[] = expresie_initializare;
Expresiile de initializare pot lipsi dintr-un declarator de variabila. Lista modificatorilor poate contine
o serie de cuvinte cheie delimitate prin spatiu. Acesti modificatori stabilesc proprietatile unui atribut si pot fi
unul din urmatoarele cuvinte cheie: public, protected, private, final, static, transient si
volatile. Primii trei sunt modificatori de acces si nu poate exista dect unul dintre ei ntr-o declaratie.
O metoda are urmatoarea forma generala de definitie:
lista_modificatori tip_returnat nume(lista_parametri)
throws lista_exceptii
{
//corp_metoda
}



16
Modificatori de metoda care definesc proprietatile metodei pot fi urmatoarele cuvinte cheie:
public, protected, private, abstract, static, final, synchronized sau native. Se pastreaza
principiul suprancarcarii (overloading) metodelor din C++. O functie poate arunca o serie de exceptii. Acest
lucru trebuie specificat prin cuvntul cheie throws urmat de o lista a tipurilor de exceptii care pot fi
aruncate. Corpul metodei defineste operatiile pe care le va executa metoda la apelul ei.
Constructorul este (ca si n C++) metoda cu nume identic cu numele clasei si care nu returneaza
nici un tip de date. Ca orice metoda, si constructorii contin o lista de parametrii formali. Exista astfel
posibilitatea suprancarcarii constructorilor prin modificarea listei parametrilor formali. n functie de
variabilele (tipurile lor) utilizate ca si parametri la instantierea unui obiect prin operatorul new, se apeleaza
constructorul corespunzator. n cazul n care nu se declara nici un constructor (doar n acest caz)
compilatorul creaza un constructor implicit, avnd numele clasei, fara nici un parametru formal si avnd
corpul constructorului gol. Corpul constructorului poate contine ca prima linie (doar ca prima linie) una din
urmatoarele instructiuni:
this(lista_parametri) sau super(lista_parametri)
Cuvntul cheie this reprezinta referinta la obiectul curent. Prin this(lista_parametri) se
poate apela un alt constructor (al aceleiasi clase) cu o lista de parametri diferita de cea a constructorului
curent. Cuvntul cheie super reprezinta referinta la clasa de baza a clasei actuale. Prin instructiunea
super(lista_parametri) se apeleaza constructorul superclasei (clasa de baza directa). Cele doua
instructiuni nu pot exista simultan. Un exemplu de suprancarcare a constructorilor si utilizare a cuvntului
cheie this ntr-un constructor este urmatorul:
public class Masina{
public Masina(int nr){. . .} // primul constructor
public Masina(int nr, String marca){ // al doilea constructor
this(nr); // apelul primului constructor
. . . . . .
}
}
Cuvntul cheie this poate fi utilizat nu numai la apelul constructorului, ci si n alte metode. O
situatie mai des ntlnita este aceea de accesare a unui atribut al clasei din interiorul unei metode a clasei n
care exista o variabila (de regula, un parametru formal) cu nume identic cu cel al atributului clasei. Ca
urmare, n doemniul de vizibilitate al metodei, numele respectiv va referi parametrul formal, nu atributul
clasei. Situatia acesta se rezolva n modul urmator:
int width; // atribut al clasei
int setWidth(int width) // parametru formal
{
this.width = width; // this.width refera atributul clasei
// iar width parametrul formal al metodei
}
Obiecte. n crearea unui obiect dintr-o clasa sunt trei etape: declararea, instantierea si initializarea.
Daca declararea unui obiect se poate face separat, instantierea si initializarea sunt operatii ce au loc simultan
prin folosirea operatorului new.
Operatorul new aloca memoria necesara stocarii obiectului respectiv (atributelor lui) si apeleaza un
constructor, care initializeaza obiectul conform operatiilor specificate n corpul constructorului. La
instantierea unei clase se aloca memorie fiecarui atribut din clasa respectiva, se initializeaza la valoarea
implicita (0 pentru tipurile primitive numerice, false pentru tipul boolean, si null pentru tipurile
referinta), se atribuie valoarea din expresia de initializare din declaratia atributului (daca aceasta exista) si
dupa aceea se apeleaza constructorul. Variabilele sunt initializate n ordinea definirii lor si naintea apelului
oricarei metode inclusiv a constructorului. Doar dupa terminarea executiei constructorului obiectul este
disponibil. n schimb referinta this poate fi utilizata n interiorul lui imediat dupa alocarea memoriei
necesare stocarii lui.
De multe ori este necesara eliberarea unor resurse n momentul distrugerii unui obiect. n limbajul
C++ aveam la dispozitie destructorul. n Java, masina JVM contine o componenta numita Garbage Colector
care se ocupa de dezalocarea zonelor de memorie alocate prin new, n momentul n care acele zone nu mai
sunt referite de nici o variabila. Exista cazuri nsa n care e nevoie de dezalocarea altor resurse atasate unui
obiect dect cele de memorie, ca de exemplu conexiuni la fisiere sau conexiuni n retea. O solutie este



17
utilizarea metodei finalize mostenita din clasa Object. Metoda finalize este apelata automat de JVM
dupa ce obiectul nu mai este referit, dar nainte de eliberarea zonei de memorie alocata acestuia.
Membrii statici ai unei clase. Utilizarea modificatorului static la declararea unui atribut sau la
declararea unei metode nseamna apartenenta membrului respectiv la clasa si nu la o instanta a ei (la un
obiect). n cazul unui atribut static, se aloca memorie o singura data, la prima initializare a clasei. La
urmatoarele instantieri ale clasei nu se mai aloca memorie pentru un atribut static, dar toate obiectele din
acea clasa pot accesa aceeasi variabila statica, aflata n aceeasi zona de memorie. Un exemplu de utilizare a
unei variabile statice este de a contoriza obiectele create din acea clasa:
class Contor{
static int contor = 0;
public Contor(){
contor++;
System.out.println(Acesta este obiectul nr. + contor);
}
}
...
Contor c1 = new Contor(); // Acesta este obiectul nr. 1
Contor c2 = new Contor(); // Acesta este obiectul nr. 2
...
Metodele statice ale unei clase sunt un fel de functii globale si se pot folosi fara sa fie necesara
crearea unei instante a clasei (obiect). Un exemplu de metoda statica este metoda main() a clasei
principale a aplicatiilor. Metodele statice nu pot utiliza atribute si metode care nu sunt statice.
Specificatorii de acces. n cazul n care o clasa este declarata de tipul public, ea poate fi utilizata
din exteriorul package-ului n care a fost definita. Specificatorul public permite declararea unui obiect de
tipul clasei respective (referinta obiectului). Pentru a putea fi nsa instantiata, clasa trebuie sa aiba si un
constructor declarat de tip public. n cazul n care cuvntul cheie public lipseste din definitia clasei, clasa
devine clasa friend si poate fi accesata doar din interiorul package-ului n care a fost creata.
n cazul metodelor, atributelor si constructorilor unei clase, se poate vorbi despre patru niveluri de
acces, prezentate n tabelul urmator.

Acces
Specificator
n clasa n clase derviate n package
n exteriorul
package-ului
public DA DA DA DA
DA DA DA NU
protected DA DA NU NU
private DA NU NU NU
3.2. MOSTENIREA CLASELOR
Prin mostenire se pot crea clase noi (numite clase derivate sau subclase) care extind clasa de baza
(superclasa). Clasa derivata mosteneste de la clasa de baza toate metodele si toate atributele. Constructorii nu
se mostenesc. Ca urmare se poate spune ca un obiect din clasa derivata este si un obiect de tipul clasei de
baza. Pe lnga metodele si atributele pe care le mosteneste de la clasa de baza, clasa derivata poate sa adauge
altele noi. Clasa derivata este o specizalizare a clasei de baza.
Derivarea unei clase n Java se face utiliznd cuvntul cheie extends urmat de numele clasei de
baza. Dupa cuvntul cheie extends nu poate exista dect o singura clasa deoarece limbajul Java nu admite
mostenirea multipla. n cazul claselor derivate compilatorul adauga la inceputul constructorului un apel al
constructorului fara argumente al clasei de baza daca si numai daca nu exista un apel explicit al unui
constructor al clasei de baza introdus n programul sursa. n cazul n care apelul se face explicit, este
obligatoriu ca acest apel sa se faca naintea oricaror alte instructiuni. Apelul explicit se face prin intermediul
cuvantului cheie super si este util n cazul n care dorim apelul unui alt constructor al clasei de baza dect
cel fara parametru. La instantierea unei clase derivate, ordinea initializarilor este urmatoarea:
Initializarea atributelor statice ale clasei de baza
Initializarea atributelor statice ale clasei derivate
Initializarea atributelor nestatice ale clasei de baza
Apelul constructorului clasei de baza



18
Initializarea atributelor nestatice ale clasei derivate
Apelul constructorului clasei derivate
O clasa derivata poate declara o metoda cu acelasi nume si semnatura cu a unei metode din clasa de
baza si aceasta metoda din clasa derivata substituie metoda din clasa de baza. Tehnica se numeste redefinire
sau dominare (redefinition, overriding). La apelul respectivei metode dintr-un obiect de tip clasa derivata se
va executa metoda declarata n clasa derivata. Accesul la metoda clasei de baza din interiorul clasei derivate
se poate face folosind cuvntul cheie super. Nici atributele statice, nici metodele statice nu pot fi redefinite.
n clasa derivata poate exista o metoda statica sau un atribut cu acelasi nume cu al unei metode sau al unui
atribut din clasa de baza, dar nu le substituie pe acestea din urma.
Modificatorul final. O clasa declarata final nu poate fi derivata. O metoda declarata final nu
poate fi redefinita. Unul din motivele specificarii final al unei metode este eficienta executiei. n
momentul n care compilatorul ntlneste un apel de metoda declarata final, el poate sa substituie apelul cu
secventa de instructiuni din corpul metodei final. Metodele final din Java sunt corespondentele
metodelor inline din C++.
Un atribut declarat final reprezinta o constanta de program. Odata initializat el nu mai poate fi
modificat. De multe ori modificatorul static se utilizeaza mpreuna cu modificatorul final pentru a
declara o constanta a clasei.
Clase si metode abstracte. O clasa poate fi declarata de tip abstract, caz n care ea nu poate fi
instantiata. O clasa abstracta poate fi utilizata doar ntr-o relatie de derivare. O clasa poate contine o serie de
metode abstracte. O clasa care are o metoda abstracta trebuie sa fie declarata abstracta. Clasele care sunt
derivate din clase abstracte trebuie sa implementeze metodele abstracte ale acestora din urma sau sa fie
declarate la rndul lor abstracte. O clasa este declarata abstracta pentru a oferi suport de implementare a
polimorfismului pentru o ierarhie de clase derivate din ea.
Conversii ntre tipuri referinta. ntre tipuri de date referinta ntre care exista relatii de mostenire se
pot face conversii de tipuri. Conversia unui tip derivat ntr-un tip de baza se numeste conversie de largire
(widening sau upcasting) si se face implicit. Conversia unui tip de baza ntr-un tip derivat se numeste
conversie de ngustare (narrowing, downcasting) si se face explicit folosind operatorul cast. La
downcasting pot aparea erori n timpul executie n cazul n care obiectul care se converteste nu a fost
instantiat ca si tip derivat.
3.3. IERARHII DE CLASE
Folosind mostenirea claselor, ntr-un program se pot crea ierarhii de clase pe mai multe niveluri.
n figura urmatoare este data diagrama UML a claselor unei aplicatii simple de muzica. n aceasta
aplicatie se pot urmari mai multe din aspectele de definire a claselor prezentate n lucrare: definirea claselor,
crearea (instantierea) obiectelor, extinderea claselor, clase abstracte si concrete, conversie ntre tipurile
derivate si tipul de baza.




















19
Clasa de baza a ierarhiei, clasa Instrument (care, la rndul ei este derivata implicit din clasa
Object, dar acest lucru nu s-a mai reprezentat n diagrama) are toate metodele declarate abstract, deci si
ea trebuie sa fie declarata abstract. Clasele derivate din aceasta (clasele Suflatori, Coarde, Percutie)
sunt clase concrete, care definesc toate cele trei metode mostenite de la clasa de baza. Implementarea acestor
metode este foarte simpla, doar scriu la consola numele unei operatii (canta(), ajusteaza()), sau
returneaza numele clasei instrumentului (getNume()). La fel, clasele de pe nivelul al treilea al ierarhiei
create (clasele Vioara si Violoncel, care extind clasa Coarde), redefinesc metodele mostenite canta()
si getNume(). Codul programului (Muzica.java) este urmatorul:

//
// Muzica.java
//
import java.util.*;
abstract class Instrument {
abstract public void canta();
abstract public String getNume();
abstract public void ajusteaza();
}
class Suflatori extends Instrument {
public void canta() {
System.out.println("Suflatori.canta()");
}
public String getNume() { return "Suflatori"; }
public void ajusteaza() {}
}
class Percutie extends Instrument {
public void canta() {
System.out.println("Percutie.canta()");
}
public String getNume() { return "Percutie"; }
public void ajusteaza() {}
}
class Coarde extends Instrument {
public void canta() {
System.out.println("Coarde.canta()");
}
public String getNume() { return "Coarde"; }
public void ajusteaza() {}
}
class Vioara extends Coarde {
public void canta() {
System.out.println("Vioara.canta()");
}
public String getNume() { return"Vioara";}
}
class Violoncel extends Coarde {
public void canta() {
System.out.println("Violoncel.canta()");
}
public String getNume() { return "Violoncel"; }
}
public class Muzica {
static void acordare(Instrument[] e) {
for(int i = 0; i < e.length; i++)
e[i].canta();
}
public static void main(String[] args) {
Instrument[] orchestra = new Instrument[5];
int i = 0;
// Conversie de largire - upcast
orchestra[i++] = new Suflatori();
orchestra[i++] = new Percutie();



20
orchestra[i++] = new Coarde();
orchestra[i++] = new Vioara();
orchestra[i++] = new Violoncel();
acordare(orchestra);
}
}

n diagrama claselor nu este trecuta si clasa Muzica, folosita ca si clasa princpala (care contine
functia main()) si care este legata de toate celelalte clase printr-o legatura de dependenta de utilizare .
Toate metodele claselor reprezentate mai sus sunt metode virtuale, redefinite n fiecare clasa, care
substituie (nlocuiesc, domina) metodele din clasele de baza.
Obiectele create ca instante a diferitelor clase (Suflatori, Coarde, Percutie, Vioara si
Violoncel) sunt organizate ca un tablou de referinte la clasa de baza (Instrument[] orchestra =
new Instrument[5];). La crearea acestor obiecte, referintele returnate de operatorul new sunt convertite
implicit (upcasting) n referinte la clasa de baza (de exemplu, orchestra[i++] = new Suflatori(); ).
La executia programului se obtine urmatorul rezultat:













3.4. INTERFETE JAVA
Interfetele Java reprezinta colectii de metode (fara corp) si constante. O interfata este declarata prin
cuvntul cheie interface. O interfata Java poate mosteni alte interfete Java utiliznd cuvntul cheie
extends. Spre deosebire de clase, interfetele suporta mostenire multipla.
La fel ca si o clasa abstracta, o interfata Java nu poate fi instantiata. O interfata java poate fi
implementata insa de o clasa utilizand cuvntul cheie implements. O clasa poate implementa mai multe
interfete. O clasa care implementeaza o interfata trebuie sa defineasca toate metodele acelei interfete.
Ca exemplu, se poate relua programul precedent si se transforma clasa abstracta Instrument n
interfata, pastrnd restul programului aproape nemodificat (Muzica1.java):

//
// Muzica1.java
//
import java.util.*;
interface Instrument {
public void canta();
public String getNume();
public void ajusteaza();
}
class Suflatori implements Instrument {. . .}
class Percutie implements Instrument {. . .}
class Coarde implements Instrument {. . .}
class Vioara extends Coarde {. . .}
class Violoncel extends Coarde {. . .}
public class Muzica1 {. . . }




21
Metodele declarate n interfata sunt implicit abstracte si nu mai este necesar introducerea
specificatorului abstract. La executia acestui program se obtin aceleasi rezultate ca si la programul
precedent.
2.5 COLECTII DE OBIECTE
Java dispune de mai multe metode de pastrare a obiectelor. O prima metoda o reprezinta tablourile,
care sunt tipuri predefinite (built-in) ale limbajului, care au fost studiate n lucrarea precedenta. Pe lnga
tablouri, exista librarii (pachete) care contin mai multe categorii de clase de colectii (clase container) care
ofera o mare varietate de modele de date si structuri de reprezentare a acestora. ntr-o colectie, numarul de
elemente poate varia prin introducerea unor elemente noi sau sau prin extragerea unor elemente.
Modelele de date cele mai folosite (si implementate n arhitectura colectiilor Java Java Collections
Framework) sunt: lista (list - o secventa de elemente, memorate ntr-o anumita ordine), multimea (set - o
grupare de elemente n care nu exista doua sau mai multe elemente de acelasi fel) si vectorul asociativ (map
o grupare de elemente, n care fiecare element contine doua parti asociate, cheia si valoarea). La rndul lui,
fiecare model de date (forma colectiei) poate fi realizat prin diferite structuri de date. De exemplu, o lista
poate fi realizata printr-un tablou sau printr-o lista nlantuita; o multime poate fi realizata printr-o lista
nlantuita, printr-un arbore sau printr-o tabela de dispersie etc.
Arhitectura colectiilor Java consta din mai multe interfete, clase abstracte si clase instantiabile n
pachetul java.util, prin care se diferentiaza doua categorii de containere, n functie de numarul de valori
pe care l contine fiecare element al containerului:
Tipul Collection defineste cte o valoare n fiecare element (denumirea este putin
confuza, dat fiind ca ntraga colectie de clase se numeste colectii). Aceast tip cuprinde mai
multe subtipuri (prin interfete derivate), n functie de restrictiile impuse. Tipul List (List
este o interfata care extinde interfata Collection) defineste modelul de date lista, adica un
container care contine o secventa de elemente aflate ntr-o anumita ordine; tipul Set (Set
este o interfata care extinde Collection) defineste modelul de date multime, adic[ un
container n care nu exista elemente duplicat.
Tipul Map defineste modelul de date vector asociativ, adica un container n care fiecare
element contine doua parti asociate (cheie, valoare).
Forma unui container (modelul de date) este impusa prin interfata (List, Set, Map) pe care o
implementeaza clasa containerului, iar structura de date a containerului este definita n clasa, obtinndu-se
astfel mai multe clase de colectii care difera att prin modul de organizare ct si prin structura de date
folosita. n figura urmatoare este reprezentata diagrama partiala a claselor si interfetelor arhitecturii de
colectii Java. Denumirile claselor de colectii sunt formate din doua parti, prima parte reprezinta structura de
date folosita, iar cea de a doua parte reprezinta forma colectiei (interfata implementata). De exemplu, clasa
ArrayList (care este o lista reprezentata printr-un tablou de elemente) si clasa LinkedList (care este o
lista reprezentata printr-o lista nlantuita de elemente) implementeaza interfata List.









Asa cum se vede din figura, interfata Collection este extinsa de interfetele List si Set; clasele
ArrayList si LinkedList implementeaza interfata List; clasele TreeSet si HashSet implementeaza
interfata Set; clasele TreeMap si HashMap implementeaza interfata Map.



22
Interfata Collection contine mai multe declaratii de metode care sunt definite n toate clasele care
implementeaza interfetele List si Set (derivate din interfata Collection). Dintre acestea, metodele
add(Object o) si remove(Object o) permit adaugarea unui nou element, respectiv eliminarea unui
element existent n colectie. Metoda int size() returneaza numarul de elemente al colectiei.
O caracteristica importanta a claselor de colectii l reprezinta faptul acestea contin referinte la
Object (orice obiect poate fi referit printr-o astfel de referinta). Acest lucru nseamna ca n aceeasi colectie
se pot introduce obiecte de orice clasa (dat fiind ca toate clasele sunt derivate din clasa Object) si nu se pot
introduce date de tipuri primitive (care nu sunt derivate din nici o clasa). Restrictia colectiilor de a nu admite
date primitive se rezolva utiliznd clasele echivalente tipurilor primitive (Character, Integer etc).
Acesta caracteristica a containerelor Java (de a stoca referinte de tip Object) are totusi un
dezavantaj, deoarece, dupa introducerea unui obiect ntr-o colectie (memorarea referintei acestuia ntr-un
element al colectiei) se pierde tipul exact al referintei (care se memoreaza ca referinta la Object). Deoarece
informatia de tip a referintei se pierde, trebuie sa fie facuta o conversie cast atunci cnd se utilizeaza
elementele din colectie si, daca conversia nu se face pentru tipul exact al obiectului, atunci poate sa apara
exceptii n timpul executiei.
2.5.1 Clasa ArrayList
Clasa ArrayList implementeaza interfata List si, indirect, interfata Collection, definind toate
metodele prevazute n aceste interfete.
Metodele de inserare permit adaugarea unui element la sfrsitul listei (add (Object o)) sau ntr-o
pozitie dorita (add(int index, Object o)). Metodele de stergere permit eliminarea unui element de la
o pozitie data (remove(int index)), sau eliminarea tuturor elementelor dintr-un interval dat de pozitii
(remove(int fromIndex, int toIndex)). Elementele se pot citi (fara a fi eliminate din lista) cu
metodele get() si get(int index).
Exemplul urmator (Colectie.java) evidentiaza modul de utilizare a unei colectii de tipul
ArrayList, precum si problemele care pot sa apara n cazul conversiilor incorecte.

//
// Colectie.java - Exemplu de container ArrayList
//
import java.util.*;
class Mar {
private int nr;
Mar(int i) { nr = i; }
void print() { System.out.println("Mar #" + nr); }
}
class Para {
private int nr;
Para(int i) { nr = i; }
void print() { System.out.println("Para #" + nr); }
}
public class Colectie {
public static void main(String[] args) {
ArrayList mere = new ArrayList();
for(int i = 0; i < 7; i++)
mere.add(new Mar(i));
// Se adauga pere la mere
mere.add(new Para(7));
for(int i = 0; i < mere.size(); i++)
((Mar)mere.get(i)).print();
// Eroarea este detectata in timpul executiei
}
}

Colectia este creata ca o instanta a clasei ArrayList. n aceasta colectie se intoduc mai multe
referinte de tip Mar si mai multe referinte de tip Par folosind metoda add. Dupa citirea elementelor din
colectie (cu functia get()), trebuie sa fie facuta conversia referintei din referinta la tipul Object (asa cum a
fost memorata) la tipul obiectului. Daca aceasta conversie se face incorect (ca n exemplul de mai sus, cnd



23
referinta la un obiect de clasa Para este convertita n referinta de clasa Mar), apare o excepte in cursul
executiei. Rezutatul executiei acestui program se poate vedea n imaginea de mai jos :












2.5.2 Iteratori
Un iterator este un obiect dintr-o clasa care implementeaza interfata Iterator si care permite
parcurgerea elementelor unei colectii. Interfata Iterator prevede trei metode care se pot folosi pentru
parcurgerea colectiilor: hasNext(), next() si remove().
boolean hasNext() returneaza valoarea true daca mai exista elemente de parcurs.
Object next() returneaza referinta la urmatorul element din colectie.
void remove() sterge din colectie ultimul element returnat de iterator.
Un iterator se creeaza cu ajutorul metodei Iterator iterator() apelata pentru un obiect
container. Acesta metoda este declarata n interfata Collection si implementata n fiecare clasa de colectii.
Parcurgerea unei colectii folosind un iterator n locul functiei get()de citire a elementelor este, n
general mai usoara, deoarece nu mai este necesar sa se compare numarul de elemente extrase cu numarul de
elemente disponibile n container (aceasta operatie o face metoda hasNext() a iteratorului). n plus,
interfata Iterator este aceeasi indiferent de tipul containerului, si deci metodele folosite pentru
parcurgerea elementelor colectiei ramn aceleasi chiar daca se schimba tipul containerului.
n exemplul urmator (Iteratori.java) se foloseste un iterator pentru parcurgerea si afisarea
elementelor unei colectii ArrayList.

//
// Iteratori.java
//
import java.util.*;
class Numar{
int n;
public Numar(int k){ n = k; }
public String toString(){ return "n = " + n; }
}
public class Iteratori {
public static void main(String[] args) {
ArrayList numere = new ArrayList();
for(int i = 0; i < 7; i++)
numere.add(new Numar(i));

// Se listeaza elementele folosind un iterator
Iterator it = numere.iterator();
while (it.hasNext()){
Numar nr = (Numar)it.next();
System.out.println(nr);
}
}
}

La executia acestui program se obtin urmatoarele date:



24










2.5.3 Clasa LinkedList
Clasa LinkedList modeleaza o lista (secventa de elemente memorate ntr-o anumita ordine) printr-
o structura de date de tip lista nlantuita.
Pe lnga metodele de inserare, stergere si citire definite de interfata List (descrise la clasa
ArrayList), clasa LinkedList mai defineste cteva metode utile de acces la elementele colectiei:
adaugarea unui element la nceputul listei (void addFirst(Object o) sau la sfrsitul listei (void
addLast(Object o)), eliminarea primului element (Object removeFirst()) sau a ultimului element
din lista (Object removeLast()), citirea primului element (Object getFirst()) si a ultimului element
(Object getLast()).
Clasa LinkedList poate fi folosita pentru crearea altor modele de date mai speciale, cum sunt
stivele (stacks) si cozile (queues)..
Implementarea unei stive folosind clasa LinkedList. O stiva (stack) este un container de tipul
ultimul introdus, primul extras LIFO: Last In, First Out) n care ultimul element (introdus cu operatia
push) este extras cu operatia pop. O stiva se poate realiza foarte simplu folosind clasa LinkedList, asa cum
se poate vedea n exemplul de mai jos (Stiva.java).

//
// Stiva.java
//
import java.util.*;
public class Stiva {
private LinkedList list = new LinkedList();
public void push(Object v) {list.addFirst(v); }
public Object top() { return list.getFirst(); }
public Object pop() { return list.removeFirst();}
public static void main(String[] args) {
Stiva st = new Stiva();
for(int i = 0; i < 5; i++){st.push(new Integer(i));}
System.out.println(st.pop());
System.out.println(st.pop());
System.out.println(st.pop());
System.out.println(st.pop());
System.out.println(st.pop());
}
}

La executia acestui program se obtine urmatorul rezultat:









25
Implementarea unei cozi folosind clasa LinkedList. O coada (queue) este un container de tipul
primul introdus, primul extras FIFO: First In, First Out) n care primul element (introdus cu operatia put)
este extras cu operatia get.
La fel ca si o stiva, o coada se poate realiza foarte simplu folosind clasa LinkedList, asa cum se
poate vedea n exemplul de mai jos (Coada.java).

//
// Coada.java
//
import java.util.*;
public class Coada {
private LinkedList list = new LinkedList();
public void put(Object v) { list.addFirst(v);}
public Object get() { return list.removeLast(); }
public static void main(String[] args) {
Coada cd = new Coada();
for(int i = 0; i < 5; i++){ cd.put(new Integer(i)); }
System.out.println(cd.get());
System.out.println(cd.get());
System.out.println(cd.get());
System.out.println(cd.get());
System.out.println(cd.get());
}
}

La executia acestui program se afiseaza numerele exact n ordinea n care au fost introduse
(0, 1, 2, 3, 4).


EXERCITII


3.1 Sa se creeze o clasa care sa contina ca data membra privata un vector (tablou unidimensional) de
numere ntregi de dimensiune variabila, care se stabileste pentru fiecare obiect la constructia acestuia. n
aceasta clasa redefiniti functia toString(), care sa afiseze numerele continute. n functia main() a clasei
principale construiti un obiect din clasa creata care sa contina numerele 2, 9, 4, 5, 7, 8 si afisati continutul
acestuia folosind functia toString() a clasei respective.

3.2 Sa se creeze o clasa Complex, pentru definirea unui numar complex, cu partea reala si imaginara ca
numere de tip double. Definiti constructorii, functia de afisare (toString()), functia de testare a egalitatii
a doua obiecte (equals()) , o functie care realizeaza adunarea a doua numere complexe. n functia main()
creati doua obiecte din clasa Complex, cu valorile 2, 4, respectiv 5, 6 a partilor reale si imaginare. Verificati
daca cele doua obiecte sunt egale si afisati rezultatul la consola. Calculati si afisati suma celor doua numere
complexe.

3.3 Creati si executati programele Muzica.java si Muzica1.java, asa cum sunt descrise n lucrare.
Testati diferitele cerinte de spacificatii ale claselor si metodelor abstracte (daca este posibil ca o metoda
abstracta sa fie definita, ce se ntampla daca o clasa derivata nu defineste o metoda abstracta mostenita etc.).
Comparati clasa abstracta cu interfata. Ce diferenta exista ?

3.4 Sa se creeze un program care sa contina urmatoarele clase si interfete:
Clasa Flori care are o variabila membra private int petale; si functiile necesare pentru
citirea si scrierea acestei variabile, constructori, functii utilitare (de ex. toString(), etc).
Interfata Sepale care declara functiile int getSepale() si void setSepale(int s);
Clasa Lalea derivata din clasa Flori, care implementeaza interfata Sepale.
Clasa Ghiocel derivata din clasa Flori, care implementeaza interfata Sepale.
n functia main() a programului sa se creeze un vector de referinte n care sa se introduca un obiect Lalea
cu 4 petale si 5 sepale si un obiect Ghiocel cu 6 petale si 7 sepale. Afisati la consola obiectele din vector.



26

3.5 Sa se creeze un program care sa contina urmatoarele clase si interfete:
Clasa Persoana care contine variabila membra private String nume, functiile necesare
pentru citirea si scrierea acestei variabile, constructori, etc.
Interfata Adresa care declara functiile abstracte String getAdresa() si void
setAdresa(String s);
Clasa Student care extinde clasa Persoana si implementeaza interfata Adresa.
Clasa Profesor care extinde clasa Persoana si implementeaza interfata Adresa.
n functia main() a programului sa se creeze un obiect Student, cu numele Marinescu si adresa
Bucuresti si un obiect Profesor cu numele Popescu si adresa Ploiesti. Afisati la consola datele celor
doua obiecte (numele si adresa).

3.6 Introduceti si executati programele de colectii prezentate n lucrare (Colectie.java,
Iteratori.java, Stiva.java, Coada.java). Modificati programul Colectie.java, astfel nct
elementele din lista sa fie parcurse folosind un iterator.

3.7* Clasa Collections contine mai multe metode statice care opereaza asupra colectiilor (la fel cum
clasa Arrays contine metode statice care opereaza asupra tablourilor). Folosind documentatia Sun (docs)
scrieti un program n care creati o colectie de obiecte de tip String, apoi gasiti si afisati sirul cel mai mare,
cel mai mic sau un sir dat. ncercati aceeasi operatie pentru o colectie de obiecte dintr-o clasa proprie (de
exemplu clasa Mar, din programul Colectie.java). Identificati cauza exceptiei care se obtine n timpul
executiei si completati clasa Mar astfel nct sa suporte operatiile de comparatie necesare si sa otineti
rezultatul corect.

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