P. 1
POO

POO

|Views: 72|Likes:
Published by Vitali Tihon

More info:

Published by: Vitali Tihon on Oct 07, 2011
Copyright:Attribution Non-commercial

Availability:

Read on Scribd mobile: iPhone, iPad and Android.
download as PDF, TXT or read online from Scribd
See more
See less

08/29/2014

pdf

text

original

Sections

  • 1. INTRODUCERE IN PROGRAMAREA ORIENTATA SPRE OBIECTE
  • OBIECTE
  • CLASE DE OBIECTE
  • 2. RELATII DE ASOCIERE INTRE CLASE
  • 3. RELAŢIA DE GENERALIZARE/SPECIALIZARE ÎNTRE CLASE
  • 4. ARRAY-URI
  • INIŢIALIZAREA UNUI ARRAY
  • ARRAY-URI MULTIDIMENSIONALE
  • LUCRUL CU ARRAY-URI
  • ARRAY ÎN METODE
  • 5. CLASE ABSTRACTE
  • 6. INTERFETE
  • 7. CLASE INTERNE
  • DEFINIREA CLASELOR INTERNE
  • CLASE INTERNE STATICE
  • CLASE INTERNE ŞI MOŞTENIREA
  • UTILIZAREA CLASELOR INTERNE ÎN APLICAŢII OO
  • 8. INPUT/OUTPUT ÎN JAVA
  • 9. GESTIUNEA EXCEPŢIILOR
  • 10. COLECTII
  • COLECŢII ÎN JAVA
  • 11. APPLET
  • 12. INTERFETE GRAFICE
  • 13. EVENIMENTE
  • 14. PROGRAMAREA INTERFETELOR GRAFICE CU SWING
  • FERESTRE INTERNE
  • CLASA JVIEWPORT
  • 15. BIBLIOGRAFIE

LUCA DAN ŞERBĂNAŢI

CRENGUŢA BOGDAN

PROGRAMAREA ORIENTATĂ SPRE OBIECTE

NOTE DE CURS

2006

CONŢINUT 1. INTRODUCERE IN PROGRAMAREA ORIENTATA SPRE OBIECTE...3
OBIECTE .....................................................................................................................................3 CLASE DE OBIECTE ......................................................................................................................6

2. RELATII DE ASOCIERE INTRE CLASE ................................................9
CARACTERISTICILE ABORDARII ORIENTATE PE OBIECTE ...............................................................14

3. RELAŢIA DE GENERALIZARE/SPECIALIZARE ÎNTRE CLASE .........15
MOŞTENIREA ÎN JAVA ................................................................................................................16

4. ARRAY-URI ..........................................................................................22
INIŢIALIZAREA UNUI ARRAY .........................................................................................................22 ARRAY-URI MULTIDIMENSIONALE ................................................................................................23 LUCRUL CU ARRAY-URI ..............................................................................................................24 ARRAY ÎN METODE .....................................................................................................................25

5. CLASE ABSTRACTE............................................................................27 6. INTERFETE ..........................................................................................31 7. CLASE INTERNE .................................................................................35
DEFINIREA CLASELOR INTERNE ..................................................................................................35 CLASE INTERNE STATICE ...........................................................................................................36 CLASE INTERNE ŞI MOŞTENIREA .................................................................................................37 UTILIZAREA CLASELOR INTERNEÎN APLICAŢII OO.........................................................................38

8. INPUT/OUTPUT ÎN JAVA.....................................................................41 9. GESTIUNEA EXCEPŢIILOR ................................................................53 10. COLECTII .............................................................................................60
STRUCTURI DE DATE DINAMICE ..................................................................................................60 TIPOLOGII DE COLECŢII ..............................................................................................................60 COLECŢII ÎN JAVA ......................................................................................................................74

11. APPLET ................................................................................................90 12. INTERFETE GRAFICE .........................................................................98 13. EVENIMENTE.....................................................................................104 14. PROGRAMAREA INTERFETELOR GRAFICE CU SWING ...............105
FERESTRE INTERNE.................................................................................................................109 CLASA JVIEWPORT..................................................................................................................110 CLASA JSCROLLPANE ...........................................................................................................112

15. BIBLIOGRAFIE ...................................................................................116

2

1. INTRODUCERE IN PROGRAMAREA ORIENTATA SPRE OBIECTE
OBIECTE D. Un obiect este un un mod simplificat de a identifica într-un program un lucru, o entitate din lumea reală sau imaginată. Din punctul de vedere al paradigmei pe obiecte, un obiecte este o combinatie de: - informatii de structura, descrise de o multime de atribute ale obiectului, si - functionalitate descrisa de o multime de operatii ce actioneaza asupra atributelor obiectului si eventual, asupra altor obiecte. D. Un atribut este o abstractizare a unei proprietati a unui obiect din lumea reala. Un atribut se caracterizeaza prin: nume, tip, valoare si eventual constrangeri. De exp, magazinul Tomis, ca orice magazin se caraterizeaza prin urmatoarele proprietati: denumire, numele proprietarului, ora de deschidere si ora de inchidere. In plus, am putea avea si un numar de identificare care sa diferentieze unic magazinul Tomis de orice alt magazin. D. Valorile curente ale tuturor atributelor unui obiect formeaza starea obiectului. De exemplu, starea magazinului Tomis ar putea fi urmatoarea:
numar de identificare= 10 denumire= Tomis numele proprietarului= Ionescu Pop ora de deschidere= 10 ora de inchidere= 18

Atributele unui obiect sunt descrise in momentul analizei si proiectarii programului OO folosind limbajul UML si apoi sunt implementate cu ajutorul variabilelor intr-un limbaj de programare (in particular, Java): Nivelul specificarii (limbajul UML) Nivelul implementarii (limbajul Java) - nrIdentificare: Integer = 10 {valoare unica private int nrIdentificare; pentru fiecare obiect} - denumire: String private String denumire; - numeProprietar: String private String numeProprietar; - oraDeschidere: Integer = 9 private int oraDeschidere= 9; - oraInchidere: Integer = 18 private int oraInchidere= 18; D. O operatie este un algoritm privat al obiectului, adica se executa in mediul său si care opereaza asupra valorilor atributelor sale sau ale altor obiecte pentru a furniza un serviciu unui alt obiect numit client. Operatiile se deduc din responsabilitatile obiectului pe care trebuie sa le indeplineasca. De exemplu, obiectul magazinul 10 trebuie sa furnizeze acces la ora de inchidere a magazinului, adica sa furnizeze informatii de stare a obiectului, deoarece proprietarul magazinului vrea sa stie la ce ora se inchide magazinul. In plus, proprietarul magazinului (ca orice client al obiectului) poate sa modifice ora de inchidere a magazinului, modificand astfel starea obiectului Magazin. Sau proprietarul ar vrea sa stie care este intregul orar al magazinului. Nivelul specificarii (limbajul UML) Nivelul implementarii (limbajul Java) public int getOraInchidere(){ + obtineOraInchidere(): Integer + modificaOraInchidere(nouaOra: Integer)
return oraInchidere; } public void setOraInchidere(int oraNoua){ oraInchidere=oraNoua; }

3

sau 4 . int oraCurenta=c. identitatea acestuia este data de valoarea atributului numar de identificare. In cazul obiectului 10. spunem ca atributul (proprietatea) numar de identificare furnizeaza un criteriu de identitate pentru obiectele de acelasi tip. Elementele de structura si functionalitate ale unui obiect pot fi proiectate pentru a fi accesibile din afara obiectului. Pana acum. Conform acestui principiu. Implementarea unei operatii in limbajul Java se numeste metoda. Desi obiectele se diferentiaza prin stare. Rezulta ca starea unui obiect poate fi modificata numai prin intermediul interfetei lui. Totalitatea elementelor ce pot fi accesate din exteriorul obiectului formeaza interfata acestuia. orice client (inclusiv proprietarul) are acces la operatiile obiectului 10 deoarece operatiile respective sunt publice.getInstance().definitia metodei = corpul metodei ce contine instructiuni ce implementeaza algoritmul operatiei. ca orice client al obiectului 10. else return “Este inchis!”. O metoda se caracterizeaza prin urmatoarele elemente: . Adica.semnatura metodei = combinatie intre numele metodei si tipul parametrilor in ordinea declararii lor . trebuie sa ascundem in interiorul obiectului ( folosind modificatorul de acces private) toate elementele (atribute sau operatii) care nu sunt utile altor obiecte (numite obiecte client: se afla in exteriorul obiectului si comunica cu el prin mesaje) si sa lasam numai acele informatii in care clientii sunt interesati.} D.unor entitati concrete: lucruri care ne inconjoara sau fapte care se petrec de-a lungul timpului. De exemplu. aceasta din urma nu asigura identitatea obiectelelor. Solutia este ca obiectul 10 sa aiba o metoda publica care sa-i spuna proprietarului ca este deschis sau nu in functie de momentul apelarii metodei esteDeschis(): Nivelul specificarii Nivelul implementarii (limbajul Java) (limbajul UML) public String getMesaj(){ + obtineRaspuns(): String } private boolean esteDeschis(){ Calendar c=Calendar. D. puteam avea doua obiecte cu aceeasi stare.HOUR_OF_DAY). if (oraCurenta>=oraDeschidere && oraCurenta<=oraInchidere) return true. dar care sa fie diferite. In acest caz ele sunt variable private. Un alt exemplu il constituie cazul in care proprietarul.prototipul metodei = contine elementele de declarare a metodei . } if (esteDeschis()) return “Este deschis!”.get(Calendar. D. Observatie. Principiul OO care sta la baza definirii interfetei unui obiect este cel al incapsularii informatiilor (“information hiding”). interfata obiectului 10 este formata din metodele publice fara sa dam acces direct la variabilele instanta. return false.Nivelul specificarii (limbajul UML) + obtineOrar(): String Nivelul implementarii (limbajul Java) public String getOrar(){ return oraDeschidere+”:00-” +oraInchidere+”:00”. vrea sa stie daca magazinul cu numarul de identificare 10 este deschis sau nu. In acest caz. Un concept este o idee sau o notiune care se aplica: . CONCEPTE Un obiect este o instanta (sau exemplificare) a unui concept.

pisica.semantica: ideea sau notiunea la care se refera numele. rezervare. .unor entitati abstracte cum ar fi constructiile noastre mentale. înscriere la universitate. angajat casatorie. Conceptele pot fi clasificate in mai multe categorii: Categorie Exemple de concepte tangibil persoana. profesor. caine artefact. Torent Computers colegul Ionescu. medic. scaun intangibil fiinta din lumea reala lucru din lumea reala descriere a unui alt obiect organizatie loc rol in scenarii reale sau imaginare relational tranzactie elementele ce compun o tranzactie eveniment proces agregat entitate continuta intr-un agregat dispozitiv sistem extern timp. fundatie magazin. specificatia unei aplicatii OO. profesor. sistemul de contabilitate. memorarea sosirii unui mesaj in sistem. inchiriere articol dintr-o vanzare de mai multe produse. inregistrator de casa sistemul informatic al serviciului personal. cumparare. documentatie de proiect firma. vizita medicala. contractare. masina mea 17:23.o extensie data de multimea instantelor conceptului. . fereastra de componente grafice. autor. comanda de 5 Instante de concepte colegul Ionescu. casa. proprietar.nume: cuvantul pe care-l folosim cand ne referin la acel concept. Un concept se caracterizeaza prin trei elemente: . roi de albine elev intr-o clasa. administrator. inregistrare automobil achizitie on-line a unor produse. masa. masina. firma persoana. modem. masina. motor.. port. banca. buton intr-o fereastra. albina vitezometru. masina. sistemul de autorizare a utilizarii unui card bancar factura. portul Constanta inregistrari de contracte sau evenimente . oras pilot. Azor Mercedes Fundatia Oamenilor de afaceri Magazinul Tomis. student. copac marca de masina. admitere clasa de elevi. picior de masa. asociatie familiala vanzare. log-are. rezervarea pentru o persoana in rezervarea unei excursii in grup trimitere mesaj. agentie de voiaj. revizie.

un concept putand sa apartina mai multor categorii. public int getOraInchidere(){ return oraInchidere. return false. O variabila de clasa implementeaza un atribut al clasei si nu al obiectelor sale. pentru a implementa in Java constrangerea ca valoarea variabilei nrIdentificare este unica avem nevoie de o variabila statica care sa numere instantele (obiectele) clasei Magazin: private static int idCurent=1. ecuatie Observatie. } private boolean esteDeschis(){ Calendar c=Calendar. Asadar. integrala. valoarea unei variabile de clasa este partajata de toate obiectele clasei respective. private String denumire. int oraCurenta=c. un program Java contine cel putin o clasa. Din acest motiv. Valoarea reprezinta numarul de identificare al noului obiect. Unitatea de baza a limbajului Java (ca orice limbaj orientat spre obiecte) este clasa. CLASE DE OBIECTE D. aceleaşi relaţii cu alte clase şi aceeaşi semantică. independente intre ele).HOUR_OF_DAY).get(Calendar. Nivelul conceptual Magazin Nivelul specificarii (limbajul UML) Magazin nrIdentificare : Integer denumire : String numeProprietar : String oraDeschidere : Integer oraInchidere : Integer obtineOraInchidere() : Integer obtineOraDeschidere() : Integer modificaOraDeschidere(nouaOra : Integer) modificaOraInchidere(nouaOra : Integer) obtineOrar() : String obtineRaspuns() : String Categorie Nivelul implementarii (limbajul Java) public class Magazin{ private int nrIdentificare. O clasa poate defini variabile si metode de clasa. aceleaşi operaţii. 6 . if (oraCurenta>=oraDeschidere && oraCurenta<=oraInchidere) return true. O clasă este o descriere a unei mulţimi de obiecte care au aceleaşi atribute.Exemple de concepte Instante de concepte achizitie concepte abstracte calendar gregorian. respectiv metode instanta. Categoriile de concepte nu sunt ortogonale (adica.getInstance(). } } Observatie. else return “Este inchis!”. } public int getOraDeschidere(){ return oraDeschidere. O clasă descrie instantele unui concept. numeProprietar. multime. De exemplu. oraInchidere. Atributele si operatiile obiectelor sunt implementate in Java ca variabile instanta. } public String getMesaj(){ if (esteDeschis()) return “Este deschis!”. private int oraDeschidere. O metoda de clasa este o metoda care apartine clasei si din acest motiv este definita ca fiind statica si la care au acces toate obiectele clasei.

De exemplu. Un constructor este o metoda cu ajutorul careia sunt create obiecte din care clasa in care este definit constructorul si initializeaza variabilele instanta ale noului obiect. oraInchidere=18. De exemplu.are acelasi nume ca numele clasei . denumire=numeM. Alte caracteristici ale unui constructor: . De exemplu. adica au acelasi nume si difera prin numarul si/sau tipul parametrilor. Se numeste constructor implicit deoarece este furnizat de Java. clasa Magazin are un constructor. numeP. numere reale. D. int oraI) { //Constructor nrIdentificare=idCurent++ . } public Magazin(String numeM. O clasa poate defini explicit unul sau mai multi constructori care sa realizeze initializarea variabilelor instanta si eventual modificarea variabilelor de clasa. O clasa este un model pentru obiectele sale. caractere.este apelat prefixandu-l cu operatorul new. Se numesc clase utilitare si furnizeaza servicii globale. Folosirea acestui operator determina crearea unei zone de memorie in Heap in care se aloca spatiu pentru fiecare variabila de instanta a obiectului nou creat. } this = Cuvânt cheie care se utilizează în interiorul corpului unei metode instanţă şi care furnizează referinţa la obiectul pentru care a fost apelată metoda. clasa Arrays contine metode de sortare a elementelor unui array de numere intregi. O clasa este o fabrica pentru obiectele sale. oraDeschidere=oraD. al doilea constructor ar putea fi definit astfel: public Magazin(String numeM. clasa Magazin ar putea avea doi constructori: public Magazin(String numeM.nu are tip al rezultatului . oraDeschidere=10. In cazul in care o clasa are mai multi constructori. String numeP) { //Constructor nrIdentificare=idCurent++ . semnatura lor difera numai prin numarul si/sau tipul parametrilor. String numeP. Intr-un constructor se poate apela un alt constructor al aceleaşi clase.Se pot proiecta si implementa clase care au numai metode statice. acestia vor fi spuraincarcati. De exemplu. Sau altfel supus. oraInchidere=oraI. inclusiv obiecte dupa diferite criterii. 18). int oraD. numeProprietar=numeP. String numeP) { this(numeM. daca este necesar. } În UML reprezentăm relaţia de instanţiere dintre o clasă şi un obiect al său ca o dependenţă clasă instanţă a Magazin Tomis: Magazin obiect 7 . numeProprietar=numeP. deoarece orice clasa are cel putin un constructor. Acesta nu are parametri si initializeaza cu valori implicite sau cu valorile definite in sectiunea de declarare a variabilelor instanta. 10. Asadar. denumire=numeM. toate obiectele clasei Magazin. vor avea aceeasi structura: atribute si operatii.

De exemplu. ele sunt modificate sau folosite cu NumeClasa. La sfarsitul executiei metodei apelate. Magazin m2 = new Magazin(“Constanta”. m1. Apelarea unei metode se face cu ajutorul operatorului binar “. Accesarea variabilelor Variabilele m1 si m2 ar putea fi folosite pentru a accesa valorile variabilelor instanţă. Ca si in cazul variabilelor-membru. aceasta valoare poate participa la calculul unei expresii devenind un operand in acea expresie. In cazul variabilelor de clasa. Apelul metodei intrerupe executia metodei curente si trece controlul metodei apelate.getMesaj(). De exemplu.numeVariabilaClasa. Acest obiect este subinteles a fi obiectul curent in care ne aflam cu executia. Apel de metoda = mecanism oferit de un limbaj de programare prin care o entitate din program (in cazul nostru un obiect) cere executia unei metode. “Popescu”. clasa Magazin are metoda getMesaj() care intoarce un sir care indica daca magazinul este deschis (“Este deschis!”) sau inchis (“Este inchis!”) in momentul apelarii metodei esteDeschis(). In acest sens putem spune ca obiectele comunică între ele prin intermediul metodelor.“Ion”). poate sa apartina unui alt obiect. in cazul general.”. De obicei un apel de metoda are loc in momentul in care obiectul apelant executa o metoda a sa. Este cazul in care apelul de metoda apare in interiorul unei expresii sau in locul unei expresii. sunt create două obiecte din clasa Magazin şi se memoreaza referinţele la ele în variabile de acelaşi tip: Magazin m1 = new Magazin(“Tomis Mall”.Diagrama 1. Aceasta metoda poate sa apartina obiectului apelant (apel intern) sau. Relaţia de instanţiere O clasa furnizeaza un tip de date cu care putem declara variabile referinta de acest tip. Pentru a putea apela o metoda M a unui obiect B. daca aceastea furnizeaza acces. vom scrie o alta clasa TestMagazin care. Apelul unei metode poate fi vazut si ca un mesaj pe care obiectul apelant il trimite obiectului apelat. controlul revine la metoda intrerupta. daca ne dau voie. un obiect A trebuie sa aiba acces la metoda M.” si fara a utiliza referinta la obiectul destinatie. In cazul in care o variabila instanta furnizeaza acces. regula de construire a apelului este aceeasi doar ca primul operand trebuie sa fie chiar numele clasei. “Ionescu Pop”). In cazul apelurilor de metode ale clasei (este cazul metodelor declarate static). atunci puteam folosi operatorul punct pentru a accesa valorile acestora. Accesul la o metoda este stabilit de regulile de vizibilitate din Java. Al doilea operand este chiar numele metodei urmat de lista parametrilor efectivi. exact in punctul de intrerupere. 8 . Nota. Apelul de metodă D. Daca metoda apelata restituie (intoarce) o valoare metodei apelante. Primul operand al apelului trebuie sa fie o variabila-reference sau o expresie a carui valoare sa fie de tip reference catre un obiect in memorie. De exemplu. apelul unei metode apartinand unui obiect din interiorul unei metode che apartine aceluiasi obiect se face fara a utiliza operatorul “. in metoda main().

clientul (sau oricine este interesat) actioneaza butonul “Date despre magazin”. a. adresa acestuia este citita din fisier si afisata in campul de text: Adresa. Pentru a gestiona automat facturile emise de magazin. 9 . aplicatia atentioneaza clientul ca este nou si trebuie sa introduca adresa. proprietarul magazinului a decis sa cumpere de la o firma de software o aplicatie care se realizeze acest lucru. aplicatia afiseaza fereastra principala: Pentru a vizualiza date despre magazin. iar aplicatia va afisa urmatoarea interfata grafica: Pentru a realiza o vanzare.txt”.2. Specificatia proiectului Magazinul Tomis emite facturi pe baza produselor vandute clientilor. clientul sau casiera trebuie sa actioneze butonul “Comandati produse” din ferestra principală. la urmatoarele operatii. Daca este vorba de un client nou.i. Daca este vorba de un client “vechi”. aplicatia va afisa urmatoarea interfata grafica: Datele clientilor sunt memorate intr-un fisier numit “clienti. In acest moment. si actionarea tastei Enter. dupa introducerea numelui si prenumelui său. RELATII DE ASOCIERE INTRE CLASE Pe parcursul acestui curs vom trata problema de a gestiune a facturilor dintr-un magazin a carei descriere este prezentata in cele ce urmeaza. Cand este executata. acestia vor fi recunoscuti.

nume. in tabelul aflat pe interfata sistemului. la care se apoi adauga un tva de 20% din suma obtinuta si se obtine totalul general. atunci programul afiseaza un mesaj de eroare. daca nu a fost apasat butonul Submit. Pentru fiecare articol al facturii. In acel moment. in cazul unui client nou. factura memorata in fisierul “arhiva. Factura poate fi tiparita la imprimanta. cantitatea comandata si pretul articolului. poate fi memorata intr-un fisier (butonul PrintToFile). Daca uită sa adauge cantitatea. 10 . Operatia de vanzare este anulata daca se actioneaza butonul Cancel. Aceasta operatie poate fi efectuata si de catre casieră. butonul Adauga este activat si clientul isi poate alege produse (pe rand. cantitate si pretul unitar al acestuia. la sugestiile clientului. Actionarea butonului Adauga determina afisarea informatiilor despre produsul comandat: nume. Aceste informatii (numele si pretul unitar al produsului) sunt preluate dintr-un fisier numit “produse. La sfarsit. respectiv poate fi arhivata (butonul Arhivare). datele acestuia (adica. In plus. daca se actioneaza butonul Print. Dupa cum se observa. pretul unitar. atributele facturii sunt numar factura (care este unic) si data la care s-a emis factura. se afiseaza numele. se actioneaza butonul Executa care determina crearea si vizualizarea facturii.txt”.txt” ce contine toate facturile furnizate de magazin. se face totalul (=suma pretului articolelor) din care se scade 5% din total daca cumpararea s-a facut intr-o zi de lucru (luni-vineri). dintr-o lista de produse) si trebuie sa specifice cantitatea.Clientul nu poate efectua o vanzare. prenume si adresa) vor fi memorate in fisierul “client.txt”. Dupa ce au fost alese toate produsele ce vor fi cumparate. al carei continut va fi afisat in fereastra Factura. In ultimul caz.

configuraţii sau grupuri. o legătură reprezintă un mod de a conecta. procesul de rationare este realizat prin aplicarea principiilor paradigmei OO. In cazul analizei. In cazul nostru. 11 . Identificarea atributelor obiectelor claselor Magazin: denumire. Legăturile sintactice între semne sunt induse de relaţiile dintre înţelesul semnelor ce furnizează semantica limbajului natural folosit.Pas 1. logice şi semantice. cantitate Vanzare: tva. semiotice. Identificarea conceptelor Magazin Vanzare Produs Interfata grafica Proprietar Fisier Data Vanzatoare Factura Lista de produse Client Program Fereastra Articol Buton Imprimanta Pasul 2. Legăturile conceptuale sau mentale sunt deduse din observarea lumii reale şi aplicarea unui proces de raţionare asupra ei. Legăturile semantice au loc între semne şi înţelesul lor pentru cei care le utilizează. prenume. prin transmiterea de forţe sau mişcări de la o entitate la alta. ne interesează numai primele două. asocia sau raporta între ele două sau mai multe entitati. Identificarea claselor prin analizarea conceptelor obtinute la pasul anterior. Legăturile ne oferă capacitatea de a reuni elementele în ansambluri. Dintre acestea ne intereseaza numai ultimele doua tipuri de legaturi sintactice. identificarea se realizează prin experimente fizice în urma cărora se deduce faptul că mobilitatea entităţilor respective este limitată. contine. Putem clasifica legăturile în mai multe categorii: fizice. Dintre aceste categorii. oraInchidere Factura: numar (unic). dataEmiterii SpecificatieProdus: denumire. total Pasul 4. de generalizare (este_un) şi mereologice (constructii sintactice: este compus din. pretUnitar Client: nume. adresa Proprietar: nume. face parte din). Construirea diagramei de clase Identificarea relatiilor dintre clase Relatia de asociere intre clase In general. este vorba de descrierea problemei si specificatia proiectului. conceptuale. Ele se împart în legături sintactice. concrete între entităţi sunt identificate în lumea reală. semantice şi morfologice (gramaticale). de similaritate (bazate pe sinonime). prenume Articol (sau ElementVanzare): specificatieProdus. oraDeschidere. este format din. asupra căreia aplicăm un raţionament. Legăturile semiotice sunt deduse din descrierea în limbaj natural a elementelor din lumea reală. Pasul 3. În unele cazuri. Legăturile logice sunt deduse din descrierea în limbaj natural a elementelor din lumea reală. Astfel avem relaţii de contrarietate (bazate pe antonime). Legăturile fizice.

de aceea exista intotdeauna posibilitatea ca un obiect sa-si trimita sieşi un mesaj.o cunoastere unilaterala sau bilaterala.bilateral (cele doua obiecte se cunoasc intre ele) D. cerandu-i acestuia din urma sa-si modifice starea? .D. . atunci intre cele doua obiecte trebuie sa existe un link. O asociere este o relatie intre doua clase ce descrie o multime de link-uri cu o structura si o semantica comune intre obiectele claselor implicate. fiindca are nevoie de informatii de la acesta din urma? . Daca un obiect care partine unei clase trebuie sa trimita un mesaj unui obiect ce apartine unei altei clase. multiplicitate.Un obiect anunta un alt obiect? O asociere se caracterizeaza prin urmatoarele elemente: nume.Un obiect foloseste un alt obiect. numarul de obiecte care participa in relatia de asociere si roluri. latime : Integer) : String 12 .* 1 getAdresa() estePentru Factura nrFactura : Integer data : Calendar formatare(sir : String.unilateral (primul obiect il cunoaste pe al doilea. . Relatiile de asociere (ca orice tip de relatie) se identifica din analiza verbelor din descrierea problemei sau/si specificatia de proiect sau/si raspunzand la urmatoarele intrebari: . O asociere intre doua clase poate indica: . . Orice clasa are implicit o relatie de asociere cu ea insasi. ElementVanzare cantitate : Integer ElementVanzare(p : SpecificatieProdus.o cale de comunicare intre obiectele celor doua clase. directia de folosire. dar al doilea nu) . O legatura (link) in abordarea orientata spre obiecte este o conectare fizica. sintactica (semantica sau sintactica) sau logica intre doua obiecte. Link-ul poate fi: . conceptuala.obiectele unei clase partajeaza cu alte obiecte obiectele celei de-a doua clase.un raport de tip client-furnizor intre obiectele celor doua clase. c : Integer) getProdus() : SpecificatieProdus getCantitate() : Integer calculeazaCost() : Long foloseste SpecificatieProdus produs 1 denumire : String pretUnitar : Integer SpecificatieProdus() getDenumire() getPret() * Vanzare tva : Integer addElementVanzare(a : ElementVanzare) getElementeVanzare() : Collection getClient() : Client calculeazaTotal() : Long areLoc Client adresa : String 1.Un obiect trimite mesaje unui alt obiect..

3). private int pretUnitar.getPret()*cantitate. } public int getPret(){ return pretUnitar. public class SpecificatieProdus{ private String denumire. } public SpecificatieProdus getProdus(){ return produs. } } public class TestArticol{ public static void main(String[] args){ ElementVanzare a1=new ElementVanzare(new SpecificatieProdus("tastatura". } } public ElementVanzare(SpecificatieProdus p.pretUnitar=pret.Nivelul de implementare Orice asociere va fi implementata cu ajutorul unui atribut de tip clasa B.denumire=denumire. Proces care capteaza caracteristicile esentiale ale unui obiect. System. Numele atributului este dat de rolul asocierii. daca acesta a fost specificat. 13 . } public int getCantitate(){ return cantitate. in clasa A.println(a1. public SpecificatieProdus(String denumire. Magazin nrIdentificare : Integer denumire : String oraDeschidere : Integer oraInchidere : Integer esteCondus Persoana +proprietar nume : String prenume : String create() getNume() getPrenume() * } public class ElementVanzare{ private SpecificatieProdus produs. int pret){ this.out. private int cantitate.Abstractizare.calculeazaCost()). this. } Principiile paradigmei orientarii spre obiecte Orice aplicaţie orientată pe obiecte trebuie să fie construită folosind patru mecanisme conceptuale: 1. caracteristici ce diferentiaza acest obiect de toate celelalte tipuri de obiecte. cantitate=c. 1000). } public String getDenumire(){ return denumire. } public long calculeazaCost(){ return produs. int c){ produs=p.

Polimorfism.Ierarhie. Proprietatea unei operatii de a putea fi aplicata în moduri diferite mai multor clase. Este o relaţie de ordine între abstractizari care sunt tipuri abstracte de date. Specializarea este o relatie între clase în care o clasa (superclasa) îsi transmite structura si functionalitatea uneia sau mai multor clase (subclase). Este o constrângere pentru clasele de obiecte care le obliga sa schimbe între ele obiecte de tipuri diferite sau sa le schimbe dar într-un mod controlat (este cazul polimorfismului de exemplu). Serveste la separarea interfetei vizibile a unei abstractizari de implementarea sa. Alte două concepte de importanta mai mica caracterizeaza obiectele intr-o modelare pe obiecte: 1. Există două tipuri de ierarhii: bazate pe relaţia de generalizare/specializare şi cele bazate pe relaţia de agregare. Un obiect care trimite un mesaj nu trebuie sa se preocupe de structurile interne de date ale obiectului destinatar. Aceasta reduce propagarea efectelor in cazul modificarilor. În general.Modularitate. iar clasele se clasifica prin intermediul superclaselor. • Structurile de date si operatiile sunt definite intr-o entitate cu nume: clasa. Metoda utilizata pentru ordonarea cunostintelor despre obiecte. 2. deriva avantaje importante: • Detaliile interne de implementare si ale procedurilor sunt invizibile in exterior (information hiding). Din faptul ca clasele si obiectele derivate din clase incapsuleaza într-un singur “pachet” datele si operatiile. 4. Aceasta din urma va fi supraclasa pentru primele clase.Typing.Incapsulare. • Interfetele intre obiecte sunt simplificate. atribute. 4. polimorfismul este un concept in teoria tipurilor in care un unic identificator poate denumi obiecte ce apartin unor clase diferite si care sunt inrudite la o superclasa. Proprietate a unui obiect care il diferentiaza de alte obiecte. Proprietatea unei aplicaţii care a fost descompusă într-un ansamblu de module (pachete) cu o mare coeziune interna si cu legaturi slabe intre ele. Persistenta (persistence). Polimorfismul este două tipuri: static (prin supraincarcarea metodelor) şi dinamic (prin redefinirea metodelor). Generalizare/Specializare. Generalizarea este o relatie intre clase in care structura si comportamentul comun a doua sau mai multor clase este incapsulat intr-o singura clasa. 3. 1. Clasificare. Identitate. Generalizarea/specializarea reprezinta un al doilea mecanism de clasificare: obiectele se clasifica în clase. 3. Cunostintele sunt descrise în termeni de clase. Reprezinta proprietatea unui obiect de a continua sa existe dupa ce creatorul său a incetat sa mai existe sau de a fi mutat din locul în care a fost creat în altul. operatii. 14 . instante. Se reduce astfel incarcarea sistemului.2. Aceasta faciliteaza reutilizarea componentelor. Toate obiectele au o identitate proprie: obiectele sunt distincte intre ele. Caracteristicile abordarii orientate pe obiecte Proprietatilor obiectelor si a mecanismelor de structurare a universului OO au drept consecinte urmatoarele caracteristici ale abordarii OO: 1. Proces mental executat pe o abstractizare în care elementele structurale ale abstractizarii sunt izolate de cele ce constituie comportamentul sau.

această relaţie între clase este arătată astfel: X X se mai numeşte superclasă (sau supraclasă). dar au ceva în plus (sau ceva specific) faţă de X. Sef. Mai general. clasa Angajat. În UML. iar Y este conceptul derivat. X este conceptul de bază. Specializarea tipului client determina aparitia a inca 3 concepte: Angajat. Persoana nume : String prenume : String Client adresa : String Angajat salariu : Double costOra : Double catVechime : Integer calculeazaSalariu(nrOreLucrate : Integer) Somer procentCalcul : Integer calculeazaAjutorSomaj() Sef sporDeConducere : Double 15 . Somer. În această relaţie. in aplicatia Magazin clientul este o persoana care are o adresa. Y Într-o relaţie de generalizare/specializare un obiect al unei subclase este şi obiect al supraclasei clasei respective. De exp. ce poate fi diferit în subclasă faţă de supraclasă? Una sau mai multe proprietăţi (variabile) specifice subclasei respective. unde X şi Y sunt concepte. Se mai spune că X este generalizarea lui Y.3. vom spune că Y este un tip de X care …. având aceeaşi structură şi aceleaşi operaţii cu cele ale obiectelor din supraclasă. Această relaţie particulară dintre concepte se numeşte relaţia de generalizare/specializare şi indică faptul că toate instanţele lui Y sunt şi instanţe ale lui X. RELAŢIA DE GENERALIZARE/SPECIALIZARE ÎNTRE CLASE Am văzut că a program spre obiecte înseamnă a raţiona în termeni de concepte. iar Y subclasă. Relaţia de generalizare/specializare se păstrează şi între clasele care reprezintă cele două concepte. iar Y este specializarea lui X. dar au ceva diferit sau în plus. Dar. De exemplu.

} } public class Angajat extends Client{ private double costOra. public void setCostOra(double c){ costOra=c. public void setAdresa(String n){adresa=n. else if(3<=catVechime && catVechime<7) salariu+=7*salariu/100. salariu. else if (7<=catVechime && catVechime<10) salariu+=10*salariu/100. se propune un mecanism numit moştenire. o clasă poate extinde o singură clasă. 16 . subclasa poate adăuga unul sau mai multe comportamente specifice sau să le modifice pe cele moştenite din supraclasă. În Java.} public String getPrenume(){return prenume. MOŞTENIREA ÎN JAVA Relaţia de generalizare/specializare dintre concepte sau clase induce ideea unei moşteniri pe care o subclasă o primeşte de la supraclasa sa. iar NumeSuperClasa este superclasa sa.} public void calculeazaSalariu(int nr){ salariu=nr*costOra. Aşadar. Declararea că o clasă extinde o altă clasă este indicată în Java prin cuvântul cheie extends în declaraţia clasei respective: class Identificator extends NumeSuperClasa { //definim variabile şi metode specifice subclasei } unde Identificator este numele subclasei. Pentru a reprezenta relaţia de generalizare/specializare în limbajele de programare spre obiecte. private int catVechime. Această moştenire are două aspecte: structura obiectelor şi modul lor de comportament. else salariu+=15*salariu/100.. Iată structura celor două clase: public class Persoana{ private String nume.} } public class Client extends Persoana{ private String adresa. clasa Manager este o subclasă a clasei Angajat. precum Java.Apoi. subclasa respectivă trebuie să definească propriile variabile şi metode.} } public class Somer extends Client{ private int procentDeCalcul. Apoi. şi aproape întotdeauna în aceste situaţii. Regulă. In Java. } public String getAdresa(){return adresa. moştenirea este simplă. if(catVechime<3) salariu+=5*salariu/100. subclasele pot adăuga ceva specific. public String getNume(){return nume. Acest mecanism permite unei noi clase să beneficieze de structura şi comportamentul definite într-o clasă deja existentă prin declararea că moştenim acea clasă.} public void setCatVechime(int c){ catVechime=c. mecanismul de moştenire se numeşte extensia clasei existente şi cere subclasei să declare ce clasă extinde. } public double getSalariu(){return salariu. prenume. De exp. În aplicaţia noastră.

lang.} public void calculeazaSalariu(int nr){ salariu=super. public class Sef extends Angajat{ private double sporConducere. Dacă doreşte. public void setSporConducere(double s){ sporConducere=s. Ierarhia claselor Java În Java. Exemplu. Un obiect al unei subclase este alocat in memorie intr-o zona care include atat spatiul alocat obiectului superclasei. clasele formează o structură de arbore în care rădăcina este clasa Object.metoda redefinită trebuie sa aibă exact aceeaşi semnătură.lang. acesta trebuie să dea cel puţin la fel de mult acces ca metoda moştenită din supraclasă.să adauge membri noi si/sau . Aşadar.metoda redefinită trebuie să aibă acelaşi tip al rezultatului întors. o clasă poate redefini una sau mai multe metode moştenite din clasa Object. trebuie să îndeplinească următoarele condiţii: . cat si spatiul necesar variabilelor declarate in subclasa.dacă metoda redefinită îşi schimbă modificatorul de acces. Structura clasei Object este următoarea: public class Object { public java. Dacă o metodă este redefinită în subclasă. Rămâne posibilitatea accesării variabile private prin intermediul metodelor set şi get. super = Cuvânt cheie care se utilizează în interiorul corpului unei metode a unei instanţe a unei clase pentru a indica obiectul superclasei ce intra in structura instantei curente. 17 . a cărei definiţie apare în pachetul java. Nota. redefinirea este folosită mai puţin şi este vorba de fapt de ascunderea variabilelor din supraclase.Object().public void setProcent(int p){procentDeCalcul=p. } } Vizibilitatea membrilor în subclase Variabilele instanţă private ale unei supraclase nu sunt moştenite în subclasele ei. Orice clasă extinde direct (implicit sau explicit) sau indirect clasa Object.calculeazaSalariu(nr).} public double calculeazaAjutor(double salariuMediu){ return salariuMediu*procentDeCalcul/100. .să redefinească membrii superclasei. toate clasele definite de programator care nu extind o altă clasă sunt automat subclase ale clasei Object. Redefinirea membrilor în subclase O subclasă care doreste sa se deosebeasca de superclasa sa (pentru ca altfel ce rost ar avea sa o introducem?) are două posibilităţi: .0. salariu+=sporConducere. } } În cazul variabilelor instanţă. . De aici putem concluziona că: O subclasă moşteneste toate variabilele şi metodele neprivate ale supraclasei pe care o extinde. Variabila salariu este protected in Angajat.

Când este vorba de un obiect al unei subclase este important să ştim cum va fi iniţializată partea obiectului ce aparţine structurii supraclasei.prenume=prenume. De exemplu.Object clone() throws CloneNotSupportedException. setPrenume(prenume). int) throws InterruptedException. public final native java. Dar. De aceea. oricare din aceste metode poate fi apelată asupra oricărui obiect. String prenume){ nume=n.adresa=adresa. O soluţie ar fi să apelăm metode setNume() şi setPrenume() care sunt moştenite de clasa Client şi am avea următorul constructor: public Client (String nume. vom avea aceeaşi eroare de compilare. Presupunem că clasa Persoana contine următorul constructor: public Persoana(String n.lang. dar la compilare vom avea eroare: nu cunoaşte constructorul fără parametri al supraclasei Persoana. Cunoaştem deja unele metode din clasa Object.lang. Constructori şi moştenirea După cum ştim. } Codul este corect. cum ar fi de exemplu toString() sau equals(). clasa String redefineşte această metodă pentru a compara lexicografic şirurile conţinute în cele două obiecte care se “compară”. public final native void wait(long) throws InterruptedException.adresa=adresa. protected void finalize() throws Throwable. } Datorită observaţiei anterioare. this.} public java. În consecinţă. String adresa){ setNume(nume). metodele clasei Object sunt moştenite de toate clasele Java.String toString(). String prenume.lang. public final native void notify(). protected native java. String adresa){ super(nume. O soluţie bună ar fi să folosim cuvântul cheie super şi apelăm constructorul cu doi parametri din clasa Persoana: public Client (String nume.Object).lang. public final native void notifyAll(). 18 . mai ales când variabilele instanţă ale supraclasei nu sunt moştenite. atunci va fi afişată numele clasei din care face parte obiectul respectiv împreună cu un şir ce reprezinta codul hash al obiectului în memoria heap. public final native void wait(long. oridecâte ori se doreşte afişarea unor informaţii despre un obiect (cum ar fi starea obiectului) se va rescrie metoda toString(). Rezultatul este true numai dacă cele două obiecte sunt de fapt acelaşi obiect. String prenume. Dacă această metodă nu este redefinită. Chiar dacă schimbăm modificatorul de vizibilitate al variabilelor nume şi prenume. this. deoarece sunt private. Datorită ierarhiei claselor Java. prenume). nu putem scrie un constructor în clasa Client care să iniţializeze direct variabilele nume şi prenume. public boolean equals(java. public native int hashCode(). this. se poate redefi această metodă dacă dorim ca metoda să realizeze un alt tip de comparare. Metoda toString() furnizează o “reprezentare” sub formă de şir a unui obiect. constructorii încapsulează algoritmi de iniţializare a obiectelor ce vor fi create. Metoda equals() permite compararea oricăror două obiecte. public final void wait() throws InterruptedException.Class getClass().

Aşadar avem două soluţii: . care nu are parametri. Din acelaşi motiv.calculeazaSalariu(200). Mecanismul de iniţializare a obiectelor Apelul unui constructor nu este un apel al unei metode oarecare.folosim super şi apelăm un anumit constructor din supraclasă .//metoda mostenita din Angajat s1. putem crea obiecte ale clasei Sef şi apela metodele lor astfel: Sef s1=new Sef("Ionescu". Dacă intr-un constructor al unei subclase se apelează un constructor al supraclasei sale. fără parametri.//constructorul s1. atunci caută constructorul fără parametri al supraclasei clasei respectiv.//se apeleaza metoda definita in clasa Sef Apelurile de metode sunt în regulă pentru că un obiect al clasei Sef este automat un obiect al clasei Angajat şi din această cauză pot fi apelate metodele moştenite din supraclasa Angajat.} Regulă. Constructor X(…) Clasa X 7: algoritmul lui X(…) 1: X(…) new X(…) Crearea unui obiect în Java algoritmilor din constructorii supraclaselor până la clasa respectivă (Figura 6-2). mediul Java apelează automat constructorul fără parametri al supraclasei dacă acesta poate fi apelat. până când clasa Object este supraclasa clasei respective. Aceasta are un singur constructor. atunci acest apel (folosindu-se super) se face pe prima linie a corpului constrcutorului respectiv. Utilizarea obiectelor ale subclaselor Având clasa Sef definită ca subclasă a clasei Angajat. Cu această clasă este creat obiectul şi apoi este iniţializat pe drumul invers al apelului cu executarea Constructor Object() Clasa Object 4: Object() 5: initializeaza obiect …. „Aleea rozelor”. Constructor predefinit A() Clasa A 2: A() 6: algoritmul lui A() ….setSporConducere(100).în supraclasa Angajat introducem încă un constructor. putem memora într-o variabilă de tip Angajat o referinţă la un obiect al clasei Sef: 19 . „Pop”.setCatVechime(25).//metoda instanta definita in clasa Sef s1. Şi tot aşa. Dacă supraclasa nu are un constructor fără parametri. deoarece înainte de a executa algoritmul respectiv. 7).

//eroare la compilare! După cum se observă. dacă avem o variabilă de tip supraclasă nu suntem siguri că obiectul referit de variabilă este de tip supraclasă.calculeazaSalariu(160). putem folosi operatorul instanceof pentru a accesa variabilele şi metodele obiectului referit de variabilă. 20 . Aşadar. „Marin”. un obiect al unei subclase poate fi folosit pentru a apela metode definite în clasa respectivă. dar şi metode definite în supraclasa sa directă sau în supraclasele sale îndirecte şi moştenite de clasa sa. Altfel. dacă vrem să folosim pe deplin obiectul respectiv (adică. „Aleea stejarilor”. valoarea expresiei ar fi fost false. pierde temporar specificul subclasei. De exemplu.//metoda mostenita din Persoana s2. Atunci ar trebui să vedem cum va fi rezolvat un apel de metodă aplicat unui obiect dintr-o subclasă. metoda este definită iniţial în clasa Clasa1 şi redefinită în Clasa3. dacă apelăm o metodă ce aparţine numai clasei Sef şi nu clasei Angajat. Astfel presupunem că un obiect a apelează o metodă a obiectului b din Clasa5 din figura următoare.Angajat s2=new Sef("Marinescu". s2.//se apeleaza metoda definita in clasa Sef s2. Atunci. expresia s2 instanceof Sef are valoarea true deoarece referinţa memorată în variabila s2 indică un obiect al clasei Sef.metoda respectivă este moştenită din clasa Clasa1 şi nu a fost redefinită în ierarhia sa directă: Clasa5 şi Clasa3. va fi metoda din Clasa3.setNume("Georgescu"). Atunci metoda care va fi executată va fi metoda din Clasa1 (Figura 6-3 a). atunci obiectul accesat prin intermediul varibilei referinţă. subclasele pot redefini aceeaşi metodă de mai multe ori. comportându-se ca un obiect al supraclasei. După cum se observă avem două cazuri: . În acest caz. Regulă. în funcţie de propriile necesităţi.setSporConducere(150). … } Mecanismul apelarii metodelor într-o ierarhie de clase Am văzut că în cazul moştenirii. compilatorul va genera o eroare pentru că variabila s2 a fost declarată de tip Angajat. Atunci metoda care va fi executată. În plus. Dacă într-o variabilă de tip supraclasa unei clase va fi memorată o referinţă la un obiect al subclasei respective. adică de tip supraclasă. 10). conform clasei din care face parte) folosim operatorul instanceof împreună cu operatorul cast la clasa originală: if (s2 instanceof Sef){ Sef s3=(Sef) s2.

21 . apelul unei metode a unui obiect aparţinând unei subclase. este transmis în sus în ierarhia de clase până când este găsită o primă definiţie a metodei apelate. dacă metoda apelată nu este definită in subclasă.Definiţia metodei Definiţia iniţială a metodei Clasa1 4 Clasa2 3 Clasa3 3 Clasa1 Metoda redefinită Clasa2 Clasa3 Clasa4 Clasa5 2 Clasa4 Clasa5 2 Obiect a 1 Obiect b Obiect a 1 Obiect b Obiect Observăm că.

un array este uni. iar cele ale array-ului personal cu valoarea null.length este 1000.i++) personal[i]=new Persoana(). Dupa numarul de dimensiuni. for (int i=0. numere = new int[5]. O dimensiune a unui array este indicata printr-o pereche de []. array-urile propriu-zise nu exista in memorie. Sintaxa este urmatoarea: TipDeDate[] id={listaDeInitializatori} 22 . In cazul array-ului de tip referinta personal. De exemplu. Dupa executarea acestor declaratii. elementele array-ului se pot umple cu valori. toate elementele array-ului numere sunt initializate cu 0. In acest moment. Nota. De exemplu. fie o expresie cu valoare dreapta un numar intreg. valoarea expresiei personal. umplerea array-ul cu aceste valori se face astfel: for (int i=0. Aceste valori se numesc elementele array-ului.sau multidimensional. Referinţa la un array va fi memorată într-o variabilă array. Elementele unui array sunt ordonate dupa unul sau mai multe criterii numite dimensiuni. Elementele unui array pot fi initializate in declararea variabilei array printr-o lista de initializatori cuprinsa intre {} ce le contine si care este atribuita variabilei array asociata. i<5. ci numai variabilele array asociate. un array trebuie să fie creat (alocat) cu new. putem declara două variabile array numere şi personal astfel: int[] numere. De exemplu. sau TipDeDate id[]. Sintaxa declararii unei variabile array unidimensional este urmatoarea: TipDeDate[] id.4. După creare. Persoana personal[]. valorile lui sunt referinte catre obiecte de tip Persoana. Pentru a exista într-un program. iar expresie este fie un literal intreg. elementelor sale le sunt atribuite valoarea zero (tipuri primitive numerice). daca arrayul numere contine primele 5 numere pare naturale. Grafic. lungimea unui array este egala cu numărul de elemente ale array-ului. Un array furnizează spaţiu pentru valorile de tip primitiv sau referinţă la obiectele de un acelaşi tip. Sintaxa alocarii memoriei unui array este: id = new tip[expresie] unde tip este tipul de date al variabilei array cu identificatorul id. Astfel un array cu 10 elemente va avea indicele de la 0 la 9. i<1000. INIŢIALIZAREA UNUI ARRAY Am vazut ca la momentul creării unui array.i++) numere[i]=2*i. false (tipul boolean) sau null (tipuri referinţă). Pentru a determina lungimea unui array se foloseste variabila length. personal = new Persoana[1000]. \u0000 (tipul char). care trebuia sa fie create. cele doua array-uri arata astfel: array-ul personal array-ul numere 0 2 4 6 8 4 0 1 2 … … 999 obiecte Persoana 0 array unidimensional de 53 1 2 întregi array unidimensional de 1000 obiecte Persoana Prin definitie. ARRAY-URI Array = O colecţie liniară de elemente în care fiecare element este accesibil prin intermediul unui indice. cu observatia ca indicele unui array începe de la 0. Astfel. De exemplu.

Alocarea memoriei necesare memorarii matricii m se face astfel: m=new[3][3]. j< a2[i]. De exemplu. unde listaInitializatori este o multime de elemente de acelasi tip cu tipul array-ului. elementele lui m nu vor fi memorate ca intr-o matrice ci liniar adica. int[][] b=new int[2][].// prima linie are 3 coloane sau elemente b[1]=new int[4].nextInt())%mod. //b are 2 linii b[0]=new int[3].length furnizeaza numarul de linii ale lui b. for(int i = 0.length. i++) for(int j=0. iniţializate şi afişate diferite array-uri multidimesionale: import java. liste separate prin virgula. } for(int i=0.*.length=4. In memorie.Aceasta este de fapt o forma prescurtata pentru TipDeDate[] id=new TipDedate[]{listaDeInitializatori}. pe cand b[1].length. ce sunt valorile elementelor array-ului id. Următorul exemplu arată cum pot fi create. public class ArrayMultiDimensionale{ static Random aleator= new Random(). De exemplu.length.4. {0. tipul elementelor trebuie sa fie acelasi. k<a3[i][j]. Exemplu.length.util. b. for(int i = 0. static int pRand(int mod) { return Math. //array 3-D cu vectori de lungime diferită pentru cele trei dimensiuni int[][][] a3 = new int[pRand(7)][][].// a doua linie are 4 elemente Nota: Daca numarul coloanelor poate sa difere.6. un array multidimensional poate fi initializat si la declarare folosind o listă ce contine un numar de liste de initializatori egal cu numarul de dimensiuni ale array-ului.length. for(int j=0. putem declara si construi array-uri multidimensionale de dimensiuni diferite. i<a3. Similar. De aceea. In cazul array-urilor multidimensionale variabila length are valori diferite.abs(aleator.8}. ARRAY-URI MULTIDIMENSIONALE Array-urile multidimensionale sunt declarate prin adaugarea dimensiunilor. i++) for(int j = 0. astfel ca fiecare dimensiune este memorata ca un array diferit. j++) for(int k=0. De exemplu.k++) afiseaza("a2[” + i+"]["+j+"]["+k+"] = " + a2[i][j][k]). k<a2[i][j]. De exemplu. Numarul de elemente din lista de initializatori funrizeaza valoarea variabilei length pe variabila array asociata. De exemplu.2. un array multidimensional este memorat ca un array de array-uri (si la randul lor pot fi de array-uri). elementele array-ul indicat prin variabila numere pot fi initializate de la declararea variabilei numere astfel: int[] numere={0.length. i < a2. i++){ a3[i] = new int[pRand(5)][]. declararea unei matrici m cu elemente de tip intreg se realizeaza astfel: int[][] m.length. adică 2.length. j<a3[i].0}. } public static void main(String[] args){ //array 3-D cu dimensiuni fixe: int[][][] a2 = new int[2][2][4]. k++) afiseaza("a3["+i+ "]["+j+"]["+k+"]= " 23 . int[][] a={{1. i<a3.1}} memoreaza matricea unitate bidimensionala. j<a3[i]. j++)a3[i][j] = new int[pRand(5)]. j++) for(int k=0.

random()*30). public static void initializeaza(){ a=new int[20]. } static void afiseaza(String s){ System. } } Cautarea unei valori intr-un array folosind metoda Divide et Impera se realizeaza astfel: 24 . //array 3x2 de obiecte Integer Integer[][] a4={{new Integer(1). int nr. arrayDest. for(int i=0.j). sortarea elementelor unui array folosind metoda QuickSort se face astfel in Java: public class Ordonare{ static int[] a.length.out. nrElemente) In mod obisnuit. do{ while(a[i]<temp)i++. array-urile sunt folosite in probleme de sortare si de cautare.19). a[j]=t. } if (i<=j) {i++. a[i]=a[j]. j < a4[i].length. new Integer(2)}. a[i]=nr.} }while (i<j). } public static void main(String[] args){ initializeaza().i++){ nr=(int)(Math. i++) for(int j = 0. {new Integer(3).out.length.out.length. {new Integer(5). j++) afiseaza("a4[" + i + "][" + j + "] = “ + a4[i][j]). new Integer(6)}}. int temp=a[(p+u)/2]. pozSursă. i < a4.+a3[i][j][k]). } afiseaza().i++) System.println(s).println(). i<a.print(a[i]+" "). }} LUCRUL CU ARRAY-URI Cand lucram cu array-uri putem folosi urmatoarea metodă statică a clasei System ce permite copierea unui număr de elemente consecutive ale unui array într-un alt array: static void arrraycopy(arraySursă.j--. } public static void afiseaza(){ for(int i=0.u). for(int i = 0. quickSort(0. System. j=u. if(i<u) quickSort(i. afiseaza().i<a. pozDest. if(p<j) quickSort(p. if (i<j){ int t=a[i]. new Integer(4)}. De exemplu. int u){ int i=p. while(a[j]>temp)j--. } public static void quickSort(int p.

println("Nu a gasit="+nr). i=j. m=(p+u)/2. public static void initializeaza(){ a=new int[20]. } public static boolean cauta(int val){ int p=0.out. } public static void afiseaza(){ for(int i=0. Pentru a realiza într-adevăr schimbarea două valori transmise prin valoare. metoda schimba() trebuie să fie scrisă astfel: public static int[] schimba(int i. a[j]) nu ar fi realizat operatia respectiva. } afiseaza(). i<a. System. } } ARRAY ÎN METODE Daca parametrul unei metode este o variabila array. int nr. Integer n2=new Integer(j).out. if(cauta(nr)) System.println().random()*30). else p=m+1.length.print(a[i]+" "). int j){ Integer n1=new Integer(i).length. a[i]=nr. } apelul acestei metode schimba(a[i]. adica orice modificare efectuata asupra elementelor array-ului respectiv se memoreaza. atunci transferul se face prin referinta. n2=n3. 25 .i++) System. Elementele unui array de tip primitiv se transmit prin valoare.random()*30).public class Cautare{ static int[] a. int j){ int t=i. De exemplu. exact ca niste variabile simple. while(p<u && val!=a[m]){ if(val<a[m]) u=m-1. int[] n=new int[2]. } return a[m]==val. daca in programul Ordonare anterior am fi avut metoda public static void schimba(int i. m=(p+u)/2. j=t.out.out. else System. n1=n2. Integer n3=n1. } public static void main(String[] args){ initializeaza(). u=a.println("A gasit="+nr).i++){ nr=(int)(Math. for(int i=0. int nr=(int)(Math.length-1.i<a.

return n. i++) System. if (i<j){ int[] n=schimba(a[i].00. } În metoda main. int temp=a[(p+u)/2].println(personal[i]). dintre care unul este Manager. In acest caz. afiseazaDate(). // creaza si memoreaza 1 angajat si un // afiseaza date despre fiecare membru // creste salariul cu 2% // afiseaza date despre fiecare membru } } { manager ca personal al intreprinderii al personalului al personalului Cum afişăm de două ori date despre angajaţi.j). do{ while(a[i]<temp)i++. Apoi.println("\nLISTA PERSONAL"). datorită relaţiei de generalizare/specializare dintre Angajat şi Manager.. când avem nevoie. if(i<u) quickSort(i. " "). am utilizat o variabilă array personal pentru a crea un array de doi angajaţi. for (int i = 0. metoda quickSort ar putea apela metoda schimba() astfel: public static void quickSort(int p. int u){ int i=p. a[i]=n[0].} n[0]=n1. 2500. 26 . 3000. Putem să facem acest lucru. afişăm date despre cei doi angajaţi. if(p<j) quickSort(p. personal[0] = new Angajat(" ".length. după care le mărim salariul cu 2% şi le afişăm din nou datele pentru a verifica creşterea salariului. public static void main(String[] args) .u). i < personal..maresteSalariu(0. while(a[j]>temp)j--.. } Lucrul cu colectii de obiecte legate intre ele prin relatia de moştenire Presupunem ca vrem sa completam programul Angajaţi cu o clasă de test a cărei metodă main contine un array de doi angajaţi pentru a memora un angajat şi un manager.00). for (int i = 0.out. public static void afiseazaDate() { System. i++) personal[i]. ar trebui să scriem algoritmul de afişare într-o metoda statică şi s-o apelăm din metoda main. a[j]=n[1]. } public static void main(String[] args) { personal= new Angajat[2].intValue().j--.02).} }while (i<j). j=u. n[1]=n2. i < personal. personal[1] = new Manager(" ". public class TestAngajati { static Angajat[] personal.out. } if (i<=j) {i++. afiseazaDate().a[j]).length.intValue().

o clasă abstractă poate avea metode concrete. Exemple: abstract void metoda().1. Sintaxa declarării unei clase abstracte: ClasăAbstractă ::= [modificator de vizibilitate] abstract class Identificator{…} unde Identificator este numele clasei abstracte. numai cu numele proprietarului ⇒ ContBancar(numeProp: String) 27 . Înţelegerea modului în care se comportă obiectele clasei. O clasă abstractă este declarată cu modificatorul abstract. adică declarate şi definite în clasa respectivă. În schimb. Un cont bancar poate fi creat vid. chiar dacă o clasă abstractă conţine unul sau mai mulţi constructori. 3. dar are subclase care sunt clase concrete.1 Dezvoltarea unei aplicatii pe obiecte Aplicaţia Cont bancar Se consideră definirea unei clase care descrie comportamentul unui cont bancar. dacă incercăm să-I apelăm vom avea eroare de compilare. Atunci. De aceea. subclasa respectivă trebuie să fie declarată abstractă şi este responsabilitatea subclaselor ei să implementeze metodele care au rămas abstracte din supraclasă. atunci obiectele unei clase abstracte au un comportament parţial definit. Care sunt operaţiile care se pot face asupra unui cont bancar? Responsabilitatea clasei ContBancar: Depune o sumă de bani ⇒ depune(suma:long) Scoate o sumă de bani ⇒ scoate(suma:long) Cere soldul curent ⇒ getSold():long Cere numele proprietarului ⇒ getProprietar():String 4. În caz contrar. metodele abstracte dintr-o clasa abstractă oferă o interfaţă comună tuturor subclaselor clasei abstracte. CLASE ABSTRACTE O clasa abstractă este o clasă fără instanţe directe. public abstract int read() throws IOException. constructorul unei clase abstracte nu poate fi apelat. 1. Sintaxa declarării unei metode abstracte este următoarea: MetodaAbstractă::=[Modificator de vizibilitate] abstract Tip numeMetoda([parametri formali]). o clasă abstractă poate avea variabile ce pot fi moştenite de subclasele clasei respective. Definirea modurilor in care vor fi create obiecte ContBancar. deoarece el diferă în funcţie de fiecare subclasă a clasei respective. 5.5. O clasă abstractă trebuie să conţină cel puţin o metodă abstractă adică metodă care nu defineşte algoritmul de implementare. Determinarea proprietăţilor clasei. rolul unei clase abstracte este de a facilita elaborările polimorfice asupra obiectelor subclaselor sale. O subclasă a unei clase abstracte are obligaţia de a defini (implementa) metodele abstracte ale supraclasei. Cum comportamentul obiectelor unei clase este dat de mulţimea tuturor metodelor clasei. Aşadar. Aşadar. În plus. Fiind fără instanţe directe. putem declara variabile de tip o supraclasă abstractă care să conţină referinţe la obiectele subclaselor concrete ale clasei respective. Definirea numelui clasei: ContBancar. 2. adică pot fi instanţiate direct. Se inserează variabilele: sold de tip long şi proprietar de tip String. care caracterizează obiectele clasei.

Orice persoană care vrea să-şi deschidă un cont bancar trebuie să specifice tipul contului: de economii sau curent. rata : Double) ContEconomii(prop : String. 28 . ct : Integer) descarcaCheltuieli() Implementarea în Java public abstract class ContBancar{ protected long sold.Fiecare tranzacţie efectuată are un cost constant exprimat în euro.sold=sold. Un cont curent are un număr de tranzacţii gratuite. sold : Long. Acest număr este memorat în constanta NR_TRANZACTII_GRATUITE. ntg : Integer. suma : Long. La anumite intervale de timp. public ContBancar(String numeProp){ proprietar=numeProp. rata : Double) aplicaDobanda() ContCurent nrTranzactii : Integer NR_TRANZACTII_GRATIS : Integer COST_TRANZACTII : Integer ContCurent(prop : String. ntg : Integer. Costul unei tranzacţii este constant. iniţializată la crearea contului curent. Această operaţie este realizată de metoda aplicăDobânda(). clasa ConBancar este o clasă abstractă cu metodele abstracte depune şi scoate. proprietar=numeProp. ct : Integer) ContCurent(prop : String. obţinem următoarea diagramă de clase în UML: ContBancar sold : Long proprietar : String ContBancar(numeProp : String) ContBancar(sold : Long. } public abstract void depune(long suma). este iniţializat la crearea unui cont curent şi memorat în constanta COST_TRANZACTIE. când trebuie să fie calculată şi adăugată la soldul curent. protected String proprietar. restul tranzacţiilor trebuie să fie plătit. numeProp : String) depune(suma : Long) scoate(suma : Long) getSold() : Long getProprietar() : String ContEconomii rataDobanda : Double ContEconomii(prop : String. } public ContBancar(long sold. costul tranzacţiilor va fi extras din cont şi numărul tranzacţiilor porneşte de la zero. După ce am analizat problema. Tinând cont de această cerinţă. După efectuarea acestui număr de tranzacţii. Un cont curent este un cont bancar caracterizat de un număr de operaţii sau tranzacţii efectuate asupra contului într-o anumită perioadă de timp. Dobânda este utilizată la anumite intervale de timp. Un cont de economii este un cont bancar caracterizat de o dobândă ce poate fi vizualizată la cerere. numeProp:String) Un cont bancar este de două tipuri: cont de economii sau cont curent. String numeProp){ this.Un cont bancar poate fi creat iniţializând soldul şi numele proprietarului ⇒ ContBancar(sold: Long sold.

} public ContEconomii(String prop. } public ContCurent(String prop. prop). public ContCurent(String prop. int ct){ super(suma.public abstract void scoate(long suma). } public void depune(long suma){ sold+=suma. } } public class ContCurent extends ContBancar{ private int nrTranzactii. public ContEconomii(String prop. private final int NR_TRANZACTII_GRATIS. double rata){ super(prop). int ntg. } public String toString(){ return super. nrTranzactii++. 0. } public void aplicaDobanda(){ sold+=sold*rataDobanda. dobanda: "+rataDobanda. private final int COST_TRANZACTIE. } public void depune(long s){ sold+=s. long sold. rataDobanda=rata. public long getSold(){ return sold. ntg. } public void scoate(long suma){ if (suma<=sold) sold-=suma. } public void scoate(long s){ 29 . } } public class ContEconomii extends ContBancar{ private double rataDobanda. } public String getProprietar(){ return proprietar. int ct){ this(prop.toString()+". COST_TRANZACTIE=ct. NR_TRANZACTII_GRATIS=ntg. long suma. int ntg. } public String toString(){ return "Cont cu proprietarul: "+proprietar+" si suma curenta: "+sold. prop). rataDobanda=rata. ct). double rata){ super(sold.

println(cc). 20000.out.out.15). În schimb. System.out. cost tranzactie: "+COST_TRANZACTIE. } } public String toString(){ return super. 30 . ContCurent cc=new ContCurent("Popescu". } } Pentru a testa ierarhia de clase construită vom scrie clasa TestContBancar care crează un cont de economii şi un cont curent. executăm 2-3 tranzacţii pentru fiecare cont şi vizualizăm situaţia.println(cc). 2000).println(ce). să se modifice clasa TestContBancar. Odată ce s-a îndeplinit termenul de scadenţă a contului. } } Exerciţiu. În acest cont. la început şi după efectuarea tranzacţiilor.out.toString()+".depune(15000). probabil în schimbul unei dobânzi mai mari. nrTranzactii++. numar de tranzactii gratis: "+ NR_TRANZACTII_GRATIS+". System.if(s<=sold){ sold-=s. } } private void descarcaCheltuieli(){ if (nrTranzactii>NR_TRANZACTII_GRATIS){ scoate((nrTranzactii-NR_TRANZACTII_GRATIS)*COST_TRANZACTIE). Să se îmbogăţească ierarhia clasei ContBancar cu o nouă clasă ContDepozitTemporar. public class TestContBancar{ public static void main(String[] args){ ContEconomii ce=new ContEconomii("Ionescu". nrTranzactii=0. cc. System.10000.scoate(2000). nu există nici o penalizare pentru operaţia de extragere.depune(5000). modificând un cont de economii într-un cont de perioadă limitată (utilizaţi polimorfismul metodelor). 0. ce.println(ce). un tip particular de ContEconomii. dacă suma este scoasă înainte de scadenţă. ea va fi eliberată fără dobândă. Apoi. titularul se obligă să lase banii un anumit număr de luni. System. ce.scoate(12000). 5. cc.

compareTo(cont304)>0) then . Fiecare clasă trebuie să implementeze în mod personalizat metoda: public class ContEconomii implements Comparable { . // metode abstracte } Exemplu. se poate scrie simplu. . Cele două clase implementează interfaţa Comparable care are o metodă compareTo(Object).dobanda > o. . O interfaţă poate moşteni de la o altă interfaţă. . public in compareTo(Object o) { return (this. 31 . } } Atunci. . clasa Angajat va implementa interfaţa Comparable care are o metodă compareTo(Object). . .” Pentru rezolvarea acestor probleme avem două soluţii: 1. . . . . Implementarea unei interfeţe O clasă care decide să implementeze o interfaţă trebuie să declare acest lucru în definiţie. Interfeţe în Java Interfaţă = Listă de metode publice şi abstracte. . Exemplu. tipuri de date.. ca şi clasele. Ordonarea se poate face în mod personalizat. Interfeţele în Java trebuie să fie declarate. Clasa trebuie să implementeze în mod personalizat metoda: public class Angajat implements Comparable { . ContEconomii sau Angajat au obiecte care nu sunt comparabile.} Pentru fiecare declaraţie de interfaţă compilatorul crează un fişier .dobanda)?-1:0.{ CorpClasa } O clasă care doreşte să implementeze o interfaţă. public interface Comparable {public int compareTo (Comparable b). . Dacă vrem sa ordonăm angajaţii unei întreprinderi după salariu pentru a putea face o statistică legată de taxele de plătit. în loc să prezinte date+servicii. 2. Interfaţa în Java este o entitate distinctă de clase şi array-uri..6. O interfaţă poate conţine şi membri-date constante. trebuie să implementeze toate metodele interfeţei. “Să se ordoneze angajaţii unei întreprinderi după salariu pentru a putea face o statistică legată de taxele de plătit. Interfeţele reprezintă. . având două conturi cont122 şi cont304: if(cont122.. O interfaţă este o colecţie de comportamente abstracte care pot fi implementate de o clasă pentru adăugarea unui comportament care nu este furnizat de superclasa clasei respective. Sintaxa: class Identificator implements NumeInterfata.dobanda < o.. numai că aceste tipuri.” 2. prezintă numai servicii. INTERFETE Conceptul de interfaţă Presupunem că avem următoarele două probleme: 1.dobanda)?1:(this. Declaraţia unei interfeţe: [Modificator] interface Identificator [extends NumeInterfata. // date-membru [Modificator] SemnaturaMetoda. “Să se ordoneze conturile de economii după dobânda pentru a decide care dintre ele este mai bun pentru a depune o sumă de bani disponbila.class.] { Tip Identificator= . pentru fiecare clasă..

public interface Serializable {}. Exemplu. în interiorul unei astfel de metode putem invoca orice metodă a interfeţei. if (s. la invocarea unei metode pentru acel obiect determină executarea unei implementări particulare a metodei ce aparţine clasei obiectului. public Object citesteObiect(String cheie).1. În acest caz: 2. .). se poate transmite ca argument orice obiect al unei clase care implementează interfaţa 2.io.getNume(). .compareTo(d) < 0) . if (s.3. la fel cum face şi o variabilă a unei clase. rezultatul v2 = (Vector) v.*.compareTo(d) < 0) . Interfeţe Java standard Interfaţa Cloneable trebuie să fie implementată de toate clasele care se clonează. . . Vector v2.clone(). . .util. protected native Object clone() //clone restituie un Object generic throws CloneNotSupportedException. . transmiţând unui alt apel un obiect al unei alte clase care implementează interfaţa se detrmină o execuţie care poate fi complet diferită de prima. Vector v = new Vector(). } import java. public class OperatiiSpecificatiiProdus implements OperatiiObiecte{ private PrintWriter pw. . . 2. } . Utilizaţi interfeţele ca parametri ai metodelor. . // Eroare!! Cum utilizăm interfeţele 1. String nume = s. O interfaţă poate fi implementată de mai multe clase. s = new Angajat(. public interface OperatiiObiecte{ public void scrieObiect(Object o). ). O variabilă interfaţă poate memora referinţa la o instanţă a oricărei clase care implementează acea interfaţă. Variabilele interfaţă sunt în special utilizate ca parametri în metode pentru a permite upcasting al obiectelor ce provin din clase diferite între ele. . ca de exemplu: Comparable s. . // va fi convertit la tipul dorit Interfaţa Serializable nu are metode: package java. 2. la execuţie. Utilizaţi o interfaţă pentru a separa un comportament care este implementat în orice clasefurnizor ale claselor client care le utilizează. .4. } O clasă poate implementa mai multe interfeţe. //Pentru a-l putea utiliza. Angajat d = new Angajat(.getSalariu()). . . 2. public OperatiiSpecificatiiProdus(){ try{ 32 .2. import java. .*.public int compareTo(Object o) { return (int)(getSalariu() – ((Angajat)o). Variabile-interfaţă Intr-un program se pot declara variabile de tip interfaţă.io. //Angajat promovat ca tip Comparable O variabilă interfaţă poate fi accesată numai cu metodele interfeţei. O variabilă interfaţă poate participa în calcule la fel ca orice variabilă referinţă.

}catch(IOException io){io.*.getPrenume()+" "+c. public OperatiiClient(){ try{ oos=new ObjectOutputStream(new FileOutputStream("clienti. while (c!=null){ if (cheie. pw. "_").} catch(ClassNotFoundException io){io. }catch(IOException io){} } public void scrieObiect(Object o){ if (!(o instanceof Client)) {System.} else {try{oos. } } public Object citesteObiect(String cheie){ SpecificatieProdus sp=null.nextToken().}catch(IOException io){io.flush().txt")).} return null.println(p. } }catch(IOException io){io.util. pw=new PrintWriter(new FileWriter("produse.getNume()+" "+c.txt")).parseInt(st.out.getAdresa()))return c. Integer.*.writeObject(o). } } import java.readLine())!=null){ st=new StringTokenizer(linie.printStackTrace(). StringTokenizer st. break.printStackTrace().} 33 .readObject().} public void scrieObiect(Object o){ if (!(o instanceof SpecificatieProdus)) { System. try{ c=(Client)ois.} return sp.txt"). private ObjectInputStream ois.readObject(). String linie.println("instanta invalida"). }else { SpecificatieProdus p=(SpecificatieProdus)o. try{ BufferedReader br=new BufferedReader(new FileReader("produse.io. return. } } }catch(IOException io){io.}} } public Object citesteObiect(String cheie){ Client c.getPret()). pw. public class OperatiiClient implements OperatiiObiecte{ private ObjectOutputStream oos.printStackTrace().return. c=(Client)ois.equals(cheie)) { sp=new SpecificatieProdus(cheie. if(st.printStackTrace().getDenumire()+"_"+p.equals(c. true). import java.txt")).nextToken())).println("instanta invalida"). while((linie=br. ois=new ObjectInputStream(new FileInputStream("clienti.out.printStackTrace().

getNume()+" "+c. oo. } } 34 .println("pret= "+sp.getPrenume()). System.scrieObiect(new Client("Marin". SpecificatieProdus sp=(SpecificatieProdus)oo.scrieObiect(new SpecificatieProdus("miere". "Ion".citesteObiect("Marin Pop alea crizantemelor"). oo. "alea stejarilor")). "Pop".out. oo.getPret()). System.scrieObiect(new Client("Ionescu".citesteObiect("miere").} } public class TestOperatii{ public static void main(String args[]){ OperatiiObiecte oo=new OperatiiSpecificatiiProdus(). "alea crizantemelor")).println("date client= "+c. "alea rozelor")).scrieObiect(new Client("Popescu". oo. 120000)).scrieObiect(new SpecificatieProdus("branza". "Pop". oo=new OperatiiClient(). 150000)). oo. Client c=(Client)oo.out.

} Dacă clasa internă este privată şi vrem să dăm acces clienţilor clasei externe la obiectele primei clase. spunem că am definit clasa internă celei de-a doua clase. } String getNume(){ return nume. Manager. putem crea obiecte din această clasă. De exemplu.new Secretara("Maria"). long salariu.println(s. public Secretara(String nume){ this. acesta poate accesa orice variabilă şi pot apela orice metodă (indiferent ce modificator de vizibilitate au) ale obiectului înconjurător.7. Astfel. salariu). Exemplu.out. CLASE INTERNE DEFINIREA CLASELOR INTERNE Într-un program Java este posibil să plasăm o definiţie a unei clase în spaţiul de nume al altei clase. Din afara clasei externe. 500. System. } public class Secretara{ private String nume. În acest caz. Continuând aplicaţia GestiuneAngajaţi din ultimele două cursuri. vechime=v. int v){ super(nume.nume=nume. clasa externă trebuie să conţină o metodă ce returnează o referinţă la un nou obiect al clasei interne: public Secretara obtineObiectSecretara(String nume){//in clasa Manager return new Secretara(nume). } } Dintr-o clasă externă putem crea fără probleme obiecte ale oricărei clase internă a sa. care este clasă externă pentru aceasta. în clasa Secretara putem defini următoarea metodă: 35 . ca în exemplul următor: public static void main(String[] args){//in clasa Manager Manager m=new Manager("Ionescu". Orice obiect al unei clase interne este legat automat de un obiect din clasa externă din care face parte şi din acest motiv. } Notă. public Manager(String nume. presupunem că clasa Manager are o clasă internă numită Secretara: public class Manager extends Angajat{ private int vechime.NumeClasaInterna. dacă clasa internă oferă acces.Secretara s=m.getNume()). 7). Clasele interne ne permit să grupăm clasele care sunt conectate logic între ele şi să controlăm vizibilitatea acestora. instanţierea clasei interner depinde de modificatorul de vizibilitate a acesteia din urmă. O clasă internă privată furnizează o modalitate de a ascunde informaţii despre implementarea realizată de clasa externă. cu ajutorul unei variabile instanţă de tip clasa externă şi tipul noii variabile instanţă este un tip compus: NumeClasaExterna.

} }.} Clasele interne pot fi definite într-o metodă sau chiar într-un bloc arbitrar clasei din care fac parte. respectiv metodele. deoarece clasa externă rezolvă o problemă mai grea şi avem nevoie de o clasă ajutătoare pe care să o folosim local.clasa internă anonimă nu defineşte un constructor propriu . } }.out. Acest obiect poate fi folosit pentru a acesa. public String getNume(){return n. } CLASE INTERNE STATICE O clasă internă statică se declară folosind modificatorul static: 36 . O astfel de decizie apare din două motive: .getVechime()). } public String getNume(){return nume.putem declara variabile instanţă şi le putem iniţializa cu valorile transmise prin parametrii metodei. neprivate ale clasei externe: public Manager getManager(){return Manager. Într-o clasă internă putem scrie o metodă care să returneze o referinţă la obiectul înconjurător.this. } Mai mult. toate variabilele. De exemplu. respectiv apela. private SecretaraE(String nume){ this. numai că aceştia trebuie să fie declaraţi finali: public Secretara obtineObiectSecretara(final String n){ return new Secretara(){ private String nume=n. { nume=n. putem defini clasa SecretaraE în corpul metodei obtineObiectSecretara(String): public Secretara obtineObiectSecretara(String nume){ class SecretaraE extends Secretara{ private String nume.public int getVechime(){return vechime.clasa internă extinde o clasă abstractă sau implementează o interfaţă şi astfel putem crea şi returna o referinţă la aceasta .} care poate fi apelată din metoda main: System. o clasă internă definită în corpul unei metode poate fi facută clasă anonimă în următoarele condiţii: . } public String getNume(){ return n. } Iniţializarea variabilelor instanţă ale clasei interne poate fi facută într-un bloc de iniţializare: public Secretara obtineObiectSecretara(final String n){ return new Secretara(){ private String nume.nume=nume.} }//clasa interna return new SecretaraE(nume).este o decizie de proiectare sau chiar de implementare.println(“vechime manager= ”+ s.

//in main System. putem crea în metoda main un obiect al clasei SecretaraE astfel: Secretara s=new SecretaraE("Maria"). putem obţine un obiect din clasa SecretaraE astfel: 37 .getNume()). De exemplu. } }//clasa interna Clasele interne statice îndeplinesc următoarele condiţii: 1.} In metoda main. Manager.getNume()). De exp. } }//clasa interna }//interfata public static void main(String[] args){//din Manager ISecretara s=new ISecretara.private static class SecretaraE extends Secretara{//in clasa Manager private String nume. private SecretaraE(String nume) } public Secretara obtineObiectSecretara(String nume){. } public String getNume(){ return nume. Fiind statică.out. System.nume=nume. putem declara clasa internă SecretaraE privată şi atunci este o clasă ascunsă oricărui client al clasei externe. private SecretaraE(String nume){ this. } În acest caz. } CLASE INTERNE ŞI MOŞTENIREA Un motiv pentru care putem folosi clase interne este de a obţine în Java moştenirea multiplă: o clasă internă extinde o clasă concretă sau abstractă sau implementează o interfaţă. Mai departe.nume=nume. static class SecretaraEI implements ISecretara{ private String nume.println(s. } public String getNume(){ return nume.SecretaraEI("Maria").. putem declara următoarea clasa abstractă: abstract class Secretara{ public abstract String getNume().println(s.. respectiv apela nici o variabilă. de exemplu. În schimb.. private class SecretaraE extends Secretara{ . numai variabile şi metode statice. se poate obţine o referinţă la clasa de bază Secretara (sau la interfaţa implementată) care furnizează funcţionalitatea declarată. public SecretaraEI(String nume){ this.. clasele interne statice pot fi incorporate în interfeţe: interface ISecretara{ public String getNume(). respectiv metodă instanţă a clasei înconjurătoare.out. Pentru a crea un obiect al clasei interne statice nu avem nevoie de un obiect al clasei externe 2. dintr-un obiect al unei astfel de clase nu putem accesa un obiect al clasei înconjurătoare şi astfel nu putem accesa.

println(s.getNume()). System.getNume()). cele generate de utilizator în interacţiunea sa cu aplicaţia noastră şi 38 .obtineObiectSecretara(m.this). long salariu. clasa ManagerE extinde clasa Manager: public class ManagerE extends Manager{ public ManagerE(String nume. De exemplu.Secretara{ public SecretaraE(Manager m.super(nume). } } public static void main(String[] args){ Manager m=new ManagerE("Ionescu".Secretara s=m. salariu. } public static void main(String[] args){ ManagerE m=new ManagerE("Ionescu"."Maria").evenimente externe. aplicaţia noastră trebuie să execute o acţiune. } public class SecretaraE extends Manager.super(nume). salariu. în momentul în care apare un eveniment.obtineObiectSecretara("Maria").out. System. Acţiunea depinde de tipul evenimentului apărut. 7).Secretara{ public SecretaraE(String nume){ (ManagerE. long salariu.Secretara s=m. 500. Cu alte cuvinte.//in main O clasă internă poate extinde orice clasă concretă sau abstractă. } UTILIZAREA CLASELOR INTERNE ÎN APLICAŢII OO Clasele interne au fost introduse pentru a trata evenimentele gestionate de aplicaţiile programate orientat spre obiecte. String nume){ m. } } O altă soluţie ar fi ca constructorul clasei interne SecretaraE să conţină o variabilă referinţă la clasa înconjurătoare a clasei externe extinsă.nume).out. String nume){ return new SecretaraE(m. 7). v). Mai mult. Manager. Cu acest constructor putem apela constructorul supraclasei extinse: public class ManagerE extends Manager{ public ManagerE(String nume.obtineObiectSecretara("Maria").SecretaraE s=m. v). int v){ super(nume. } } În acest caz putem introduce o nouă metodă (overloaded cu cea moştenită) care să returneze un obiect al subclasei interne SecretaraE: public SecretaraE obtineObiectSecretara(ManagerE m. int v){ super(nume.println(s. 500. } public class SecretaraE extends Manager. ManagerE. Evenimentele sunt în general de două tipuri: . o clasă A internă clasei B poate extinde o clasă internă a supraclasei lui B. Un eveniment este o entitate conceptuală care spune că ceva are loc în timp şi spaţiu şi are consecinţe asupra unei aplicaţii.

println(e. public abstract String descriere(). } public void gestioneaza(){ while(true) if (e. } public class SchimbareCuloare extends Eveniment{ int culoare.e=e. this. } 39 . public SchimbareCuloare(long timp. break. } şi un gestor generic de evenimente: public class Controller{ private Eveniment e. toate evenimentele tratate de clasa GestorSemafor sunt de acelaşi tip SchimbareCuloare: public class GestorSemafor extends Controller{ private Semafor s. Aşadar.- evenimente interne. System. cele generate în interiorul aplicaţiei. public Eveniment(long mT){ moment=mT. } public abstract void executaActiune().aAparut()){ e.currentTimeMillis()>=moment. Vom avea clasa Semafor care conţine o variabilă instanţă privată culoare.out.} } Semaforul este controlat de clasa GestorSemafor care extinde clasa Controller şi tratează fiecare eveniment produs de schimbarea culorii la semafor.s=s. public GestorSemafor(Semafor s){ this. int culoare){ super(timp). Să scriem de exemplu o aplicaţie care simulează funcţionarea unui semafor de circulaţie. Atunci putem defini o clasă abstractă Eveniment ca o clasă generică de evenimente: public abstract class Eveniment{ private long moment.executaActiune().descriere()).culoare=culoare.} public String getCuloare(){return culoare. } public boolean aAparut(){ return System. e=null. public void setEveniment(Eveniment e){ this. public void setCuloare(String c){culoare=c. } } } Exemplu. ce reprezintă culoarea curentă aratată de semafor: public class Semafor{ private String culoare.

} } } Observăm că clasa SchimbareCuloare este o clasă internă şi este o subclasă a clasei Eveniment.new SchimbareCuloare(timp+3000*i+2000. i++){ long timp=System.gestioneaza().setEveniment(gs. } } public String descriere(){ return "Culoarea aratata de semafor este "+s.currentTimeMillis().gestioneaza(). 2)).setCuloare("galben").setEveniment(gs.setEveniment(gs. case 2: s.public void executaActiune(){ switch(culoare){ case 1: s. for (int i=1. case 3: s. GestorSemafor gs=new GestorSemafor(s). gs.break.setCuloare("verde"). gs.break. gs. 1)).setCuloare("rosu"). gs.getCuloare(). gs. 3)). } } } 40 . gs.new SchimbareCuloare(timp+2000*i+1000. i<=10.new SchimbareCuloare(timp+1000*i.gestioneaza(). Clasa Test crează un obiect Semafor în metoda main şi produce la intervale scurte de timp evenimente generate de schimbarea culorii la semafor: public class Test{ public static void main(String[] args){ Semafor s=new Semafor().

Clase de citire a caracterelor Unicode: Reader. FileReader şi StringReader sunt derivate din clasa abstractă Reader. BufferedWriter. PrintStream şi StringBufferOutputStream. Clase de fluxuri de ieşire: OutputStream. DataInputStream. Claselor FileInputStream şi FileOutputStream se adaugă alte două clase destinate gestiunii fişierelor: File şi RandomAccessFile.clase de gestiune a fişierelor . BufferedReader. 2. 41 . Sunt derivate de clasa abstractă Writer. 4. Sunt derivate din clasa OutputStream. Conţine 4 categorii de clase: . Derivate din clasa abstractă InputStream. Clase de scriere a caracterelor în Unicode: Writer. BufferedOutputStream. 3.8. FileOutputStream. INPUT/OUTPUT ÎN JAVA Pachetul java.clasa StreamTokenizer 1.clase de fluxuri de ieşire şi clase de scriere . Clasa StreamTokenizer permite convertirea unui flux de intrare a datelor într-un flux de token-i şi conţine metode pentru definirea sintaxei token-ilor. Clase de fluxuri de octeţi: BufferedInputStream. FileInputStream şi StringBufferInputStream.io Furnizează suport pentru citirea şi scrierea datelor de la şi la dispozitive diferite. FileWriter şi PrintWriter.clase de fluxuri de intrare şi clase de citire .

Ierarhia claselor I/O DataInput Serializable Externalizable InputStream ObjectInputValidation ObjectInput ObjectOutput File FileDescriptor ByteArrayInputStream FileInputStream FilterInputStream ObjectInputStream PipedInputStream SequenceInputStream StringBufferInputStream BufferedInputStream DataInputStream LineNumberInputStream Object OutputStream DataOutput Throwable RandomAccessFile Writer FilenameFilter StreamTokenizer Reader ByteArrayOutputStream FileOuptputStream FilterOutputStream ObjectOutputStream PipedOutputStream BufferedReader CharArrayReader InputStreamReader FilterReader PipedReader StringReader BufferedWriter CharArrayWriter FilterWriter OutputStreamWriter PipedWriter PrintWriter StringWriter LineNumberReader FileReader PushbackReader BufferedOutputStream DataOutputStream PrintStream FileWriter Exception ObjectInputValidation InvalidClassException InvalidObjectException NotActiveException NotSerializableException OptionalDataException StreamCorruptedException IOException ObjectStreamException EOFException FileNotFoundException InterruptedIOException SyncFailedException UTFDataFormatException CharConversionException UnsupportedEncodingException WriteAbortedException 42 .

citeşte caractere de pe fluxul de intrare şi îi memorează în array-ul b. se lansează o exceptie. sintaxa metodelor read() a fost modificată astfel: Semnătura metodei int read() throws IOEXception Semnificaţie –Valoarea returnată citeşte un caracter de pe fluxul de intrare şi returnează codul său Unicode. int poz. ignoră maxim n octeţi din fluxul de intrare şi întoarce numărul de octeţi cu care s-a avansat in flux.txt”). întoarce true dacă fluxul suportă operaţia de marcare şi revenire la poziţia marcată. Metoda returnează numărul de octeţi citiţi efectiv. citeşte maxim nr octeţi de pe fluxul de intrare şi îi memorează în array-ul b.Clasa InputStream InputStream = clasă abstractă din care derivează toate clasele fluxului de intrare. Dacă se detectează sfârşitul fluxului atunci metoda intoarce –1.setIn(InputStream) astfel: FileInputStream fi = new FileInputStream(“input. dar poate fi setată cu System. citeşte octeţi de pe fluxul de intrare şi îi memorează în array-ul b. citeşte maxim nr caractere de pe fluxul de intrare şi îi memorează în array-ul b. Dacă b este mai mic decât numărul de caractere citite. int nr) throws IOEXception long skip(long n) throws IOException int available() throws IOException void mark(int poz) void reset() throws IOException boolean markSupported() void close() throws IOException Clasa Reader Aceeaşi structură are clasa abstractă Reader.in = variabilă statică a clasei System care memorează o instanţă a clasei InputStream. int nr) throws IOEXception System. int read(char[] b) throws IOEXception abstract int read(char[] b. int poz. de la poziţia poz. Dacă b este mai mic decât numărul de octeţi citiţi. Dacă se detectează sfârşitul fluxului atunci metoda intoarce –1. Metodele clasei InputStream sunt prezentate în următorul tabel: Semnătura metodei abstract int read() throws IOEXception Semnificaţie –Valoarea returnată returnează un octet citit de pe fluxul de intrare. închide fluxul de intrare şi eliberează resursa alocată. această instanţă reprezintă fluxul standard de intrare (tastatura). Nu toate fluxurile de intrare oferă această operaţie. De aceea. de la poziţia poz.setIn(fi). System. repoziţionează fluxul la ultima poziţie marcată. specializată în citirea caracterelor. int read(byte[] b) throws IOEXception int read(byte[] b. se lansează o exceptie. De obicei. Metoda returnează numărul de caractere citite efectiv. Metoda returnează numărul de octeţi citiţi efectiv. Dacă b este mai mic decât numărul de octeţi citiţi. se lansează o exceptie. returnează numărul de octeţi disponibili pentru citire fără blocare. se lansează o exceptie. Metoda returnează numărul de caractere citite efectiv. Crearea unui flux de date de intrare 43 . marchează poziţia poz în flux pentru ca ulterior să se poată reveni la ea. Dacă b este mai mic decât numărul de caractere citite.

println(e.} return c. . BufferedInputStream (InputStream in): . 2. FileInputStream (String nume): - execută operaţii de intrare simple asupra fişierelor (pentru operaţii mai avansate se utilizează RandomAccessFile). la metodele furnizate de InputStream se adaugă metodele interfeţei DataInput readxxx() (xxx = Boolean. } Clase de flux de octeţi de intrare 1.funcţionează ca un InputStream. - 44 . Byte. PushBackInputStream (InputStream in) . Int. utile dacă se extinde clasa BufferedStream.in.skip(2).in. . 3. . Short. Char. try{ c=(char)System.//nu se citeşte caracterul generat de apăsarea lui Enter }catch(IOException e){System. Long.funcţionează ca InputStream. Se crează o instanţă a unei clase de flux de intrare.out. Metoda urmatoare citeşte un caracter de la tastatură şi-l returnează: public char citeste(){ char c='0'. metoda readInt() citeşte patru octeţi din fluxul de intrare şi întoarce o valoare de tip int.construieşte un flux cu un caracter lookahead.are o metodă unread(int ch).când nu mai sunt date disponibile. moşteneşte atât interfaţa DataInput cât şi clasa abstractă FilterInputStream.furnizează un flux de intrare buffer-izat permiţând astfel o citire mult mai rapidă. Se indică locul din care vor fi citite datele.include numai metodele furnizate de InputStream. Pentru a citi date în Java procedura este întotdeauna aceeaşi: 1.construieşte fluxul şi cu un obiect File sau FileDescriptor. int markpos şi int marklimit. . dar operează asupra unui fişier. Float sau Double) care citesc un număr de octeţi din fluxul de intrare necesar pentru a obţine o valoare de tip primitiv specificat în numele metodei. UnsignedShort. 4. long etc. instanţa clasei se blochează în aşteptarea ca datele să devină disponibile. int pos.read(). .getMessage()). Caracteristicile citirii: .are unele variabile membru: byte buf[].Crearea unui flux de date de intrare respectă modelul pipeline Unix: face parte dintr-o sursă de date cu interfaţa InputStream şi se crează succesiv cu filtri ai aceleaşi interfeţe. 2. char. De exemplu.este un flux continuu. System. DataInputStream (InputStream in): - utilizată pentru citirea datelor primitive (int. . int count. .). FileInputStream BufferedInputStream DataInputStream byte int File File system (Sursă date) Bytes Buffer de bytes Date formatate char float long Memoria Exemplu.

in)). Citirea dintr-un fisier BufferedReader in2 = new BufferedReader( new FileReader("intrare. FileReader.close().println("Am ajuns la sfarsitul fisierului").out.out.out.println("Fisier inexistent"). while(true) System. //4. scrie pe fluxul de ieşire octeţii din array-ul b scrie nr octeţi pe fluxul de ieşire începând de la poziţia poz a array-ului b.close(). PushBackReader. //2. Citirea unei linii de la tastatura BufferedReader in1 = new BufferedReader( new InputStreamReader(System.*.io.print((char)c). } catch(EOFException e){ System. StringReader. Semnătura metodelor write() se modifică şi apar două forme noi ale acestei metode: Semnătura metodei Semnificaţie –Valoarea returnată void write(int IOEXception void write(char[] n) b) throws scrie valoarea lui n pe fluxul de ieşire.txt")). String s1. Citirea din memorie StringReader in3 = new StringReader(s2).txt")).close(). in3. //3. Clasa Writer Clasa Writer specializată în scrierea fluxurilor de caractere are o ierarhie similară cu ierarhia lui OutputStream.Clasa abstractă Reader are subclase asemănătoare cu cele ale clasei abstracte InputStream: BufferedReader. Metodele clasei OutputStream sunt prezentate în următorul tabel: Semnătura metodei abstract void write(int n) throws IOEXception void write(byte[] b) throws IOEXception void write(byte[] b. int poz. s2 = new String(). throws scrie pe fluxul de ieşire caracterele din array-ul b 45 . } } } Clasa OutputStream OutputStream = clasă abstractă din care derivează toate clasele fluxului de ieşire.readByte()).out.print((char)in4. in1. while((c = in3. } catch (IOException e){ System. Citirea din memorie formatata DataInputStream in4 = new DataInputStream( new FileInputStream("intrare. BufferedReader are o metoda String readLine(). In plus. public class FluxDeIntrareIesire{ public static void main(String[] args) { try { //1.readLine())!= null) s2 += s1 + "\n".println("Exceptie IO"). int c. } catch (FileNotFoundException e){ System. in2. while((s1 = in2. goleşte fluxul de ieşire închide fluxul de intrare şi eliberează resursa alocată.readLine().out. există clasa InputStreamReader care face legătura dintre o clasa de tip InputSream şi un Reader.read() ) != -1) System. String s=in1. int nr) throws IOEXception void flush() throws IOException void close() throws IOException Semnificaţie –Valoarea returnată scrie valoarea lui n pe fluxul de ieşire. Următorul exemplu arată mai multe modalitaţi de a face o citire folosind clasele derivate din InputStream şi Reader: import java.

long. deoarece obiectul obţinut are caracteristicile dorite: buffer-izat. BufferedWriter derivează din Writer.out = variabilă statică a clasei System care memorează o instanţă a clasei PrintStream ce reprezintă de obicei ecranul monitorului. include: print(tip) şi println(tip) unde tip ia una din valorile: Object. public void write(String str) scrie şirul str pe fluxul de ieşire. împreună cu numărul liniei curente. - PrintWriter derivează din Writer afişează date-text (şiruri sau numere). Instanţa se poate crea plecând de la destinaţie şi compunând fluxul din obiecte-flux încuibate. float şi double. funcţionează ca Write. int. furnizează un flux de ieşire buffer-izat.Semnătura metodei Semnificaţie –Valoarea returnată IOEXception abstract void write(char[] b. 2. true). dar operează pe fişiere. construieşte un obiect numai cu un şir.setOut(new printStream(fs)). în stare să scrie date primitive etc. un obiect File sau un FileDescriptor. la destinaţie. . int nr) throws IOEXception poziţia poz a array-ului b. int scrie nr caractere pe fluxul de ieşire începând de la poz. Scrierea cu clasele Output Stream şi Writer Primul exemplu din această subsecţiune arată cum se poate determina numărul de linii ale unui fişier şi scrierea fiecărei linii citite într-un alt fişier.setOut(OutputStream): FileOutputStream fs = new FileOutputStream(“log. byte DataInputStream BufferedInputStream int char float long Memoria Buffer de bytes FileInputStream File Bytes File system Flux de bytes (Sursă date) Date formatate Clase de flux de caractere în ieşire 1. poz. are două variabile membru utile: byte buf[] şi int count. char[]. altele decât cele furnizate de Write. 46 . int scrie pe fluxul de ieşire subşirul de lungime nr pe care-l extrage de la poziţia poz a şirului str.txt”). FileWriter execută operaţii simple de ieşire de caractere pe fişiere (pentru operaţii mai avansate pe fişiere se utilizează RandomAccessFile). metodele sale. Este setată cu System. Se indică locul unde vor fi scrise datele. Procedura de scriere a datelor cu o clasă de fluxuri de ieşire este întotdeauna aceeaşi: 1. boolean.txt”). - 3. System. PrintWriter out= PrintWriter(new FileWriter(“personale. int nr) throws IOException System.instanţa clasei de flux trimite date cât timp acestea sunt disponibile. throws IOException public void write(String str. nu conţine alte metode în afară de cele furnizate de Writer. char. Caracteristicile scrierii: . constructorul are ca argument un obiect Writer. String. Se crează o instanţă a clasei fluxului de ieşire specificând fluxul final. 2.este un flux continuu.

} catch(IOException ioe){System.} Clasa următoare furnizează două metode care citesc.} catch(IOException ioe){System. while((s = lnr.out. } } } 47 .close().readDouble()).charAt(i). String s="".out.println("Linia " +lnr. if(c==0) more=false.readLine()) != null) out. i++.out.readChar().writeDouble(3. subclasă a lui BufferedReader. DataOutput out) throws IOException{ for(int i=0.txt"))). PrintWriter out=new PrintWriter(new BufferedWriter( new FileWriter("iesire.println("Eroare de intrare/iesire").println("Sfarsitul fluxului").println(inbr.out.Observaţie. if(i<s. return buffer.} Următorul exemplu arată cum scriem şi citim date formatate într-un/dintr-un fişier.readLine()). public class DataIO{ public static String citesteSirFix(int size. }catch(EOFException e) {System.io.skipBytes(2*(size-i)).length()) c=s. out.getLineNumber()+ " "+ s).i++){ char c=0.out. else buffer.println("Sfarsitul fisierului").writeBytes("Valoarea lui PI"). } public static void scrieSirFix(String s. int size. boolean more=true.toString().close(). out. while(more&& i<size){ char c=in. respectiv scriu date formatate pe linii de lungime fixă: import java.close(). try{ LineNumberReader lnr = new LineNumberReader(new FileReader("intrare. Vom folosi instanţe ale claselor DataOutputStream şi DataInputStream pentru a scrie numărul 3. DataInput in)throws IOException{ StringBuffer buffer=new StringBuffer(size).txt"))).println(in.txt")).writeChar(c). }catch(EOFException e){System. Adică vom folosi o instanţă a clasei LineNumberReader.append(c). System.14159 şi şirul “Valoarea lui PI”: try{ DataOutputStream out=new DataOutputStream(new BufferedOutputStream( new FileOutputStream("Data. lnr. } in. System. DataInputStream in = new DataInputStream(new BufferedInputStream( new FileInputStream("Data. out. BufferedReader inbr = new BufferedReader(new InputStreamReader(in)).println("Eroare de intrare/iesire"). out.out. int i=0.i<size. Pentru a afla numărul liniei curente vom folosi un cititor buffer-izat ce păstrează numărul liniei citite.*.txt"))).14159). out.

235.out).out.id=id. "r").877). for(int i=n-1. "ionescu pop".Această clasă poate fi folosită de exemplu. System. this. a[1]. SIZE_NUME.899). a[1]=new Angajat(2. "marinescu marin". out. } public void writeData(DataOutput out) throws IOException{ out.citesteSirFix(SIZE_NUME. } public void readData(DataInput in)throws IOException{ id=in. nume=DataIO. nume. try{ DataOutputStream out=new DataOutputStream(new FileOutputStream("angajat.*.writeData(out).RECORD_SIZE).i--){ an[i]=new Angajat().writeInt(id). in. a[2].dat")).RECORD_SIZE). class Angajat{ public static final int SIZE_NUME=40. salariu) a trei angajati ai unei companii şi apoi le afişeaza în ordinea inversă scrierii lor: import java. 45. public Angajat(){} public Angajat(int id.writeData(out). private String nume.scrieSirFix(nume.readInt().readDouble(). i>=0. private double salariu.io.writeDouble(salariu).close(). this.877).dat". } public String toString(){ return id+" "+nume+" "+salariu. 435. a[0]. 48 . "popescu ion".salariu=salariu. int n=(int)(in.nume=nume. out. DataIO. a[0]=new Angajat(1. double salariu){ this. }catch(IOException ioe){} try{ RandomAccessFile in=new RandomAccessFile("angajat.in).writeData(out). public static final int RECORD_SIZE=2*SIZE_NUME+4+8. String nume. a[2]=new Angajat(2.seek(i*Angajat.length()/Angajat. pentru a scrie un scrie un program care salveaza intr-un fisier datele (id. } } public class TestAngajat{ public static void main(String[] arg){ Angajat[] a=new Angajat[3]. private int id. Angajat[] an=new Angajat[n]. salariu=in.println("n="+n).

“\\” pentru sistemele Windows . Separatorul unei căi depinde de sistemul de operare pe care rulează programul si anume: .} Clasa File Clasa File prezintă o vedere abstractă a numelor fişierelor şi a directoarelor. precum si locaţiilor unde se găsesc acestea într-un sistem de fişiere.an[i]. Calea poate fi absolută sau relativă la directorul în care se găsesc class-urile programului. System. Constructori: File(String cale)//crează un obiect File ce contine o cale absolută sau relativă şi care poate conţine numele fişierului File(String cale.println(e.“/” pentru sistemele Unix. în biţi returnează true dacă a fost creat directorul specificat in cale returnează true dacă au fost create directoarele specificate in cale redenumeşte fişierul cu curent cu numele dest şi returnează true şterge fişierul sau directorul curent întoarce într-un array de şiruri numele fişierelor şi directoarelor din directorul curent.out. String nume)//crează un obiect File ce conţine separat numele fişierului şi calea directorului în care se află fişierul File(File dir. întoarce într-un array de şiruri numele fişierelor şi directoarelor din directorul curent care îndeplinesc criteriul filtru 49 . Acesta este memorat în constantele String separator şi char separatorChar.readData(in). } } } } catch(IOException e){System. văzut ca un String.println(an[i]).getMessage()). respectiv ca un caracter.out. Locaţia unui fişier reprezintă calea în sistemul de fişiere unde este memorat acesta. returnează true dacă fişierul respectiv poate fi modificat returnează true dacă fişierul respectiv poate fi citit returnează true dacă şirul indicat ca fişier există pe disc şi este un fişier returnează true dacă şirul indicat ca director există pe disc şi este un director returnează data şi ora ultimei modificări returnează mărimea fişierului. String nume)//calea directorului părinte este dat ca un obiect File Metodele mai importante ale clasei File sunt prezentate în următorul tabel: Semnătura metodei String getName() String getPath() String getAbsolutePath() String getParent() boolean exists() boolean canWrite() boolean canRead() boolean isFile() boolean isDirectory() long lastModified() long length() boolean mkdir() boolean mkdirs() boolean renameTo(File dest) boolean delete() String[] list() String[] list(FilenameFilter filtru) Semnificaţie –Valoarea returnată returnează numele fişierului sau directorului curent returnează calea unde se află fişierul sau directorul curent pe disc returnează calea absolută unde se află fişierul sau directorul curent pe disc întoarce directorul părinte a directorului sau în care se găseşte fişierul curent returnează true dacă fişierul indicat in constructor există pe disc.

if(nume.append("parinte "+nume.println("Dati numele fisierului/directorului"). } public String analizeaza(String sir){ File nume=new File(sir). etc.equals("java").getName()+" exista\r\n"). locaţia sa pe disc.getParent()+"\r\n"). return br.io.getAbsolutePath()+"\r\n").isDirectory())buffer.append("este un director\r\n"). else buffer. PrintWriter pw.java)". StringBuffer buffer=new StringBuffer().append("calea "+nume. int i=nume.txt: import java.append("calea absoluta "+nume. } } Următorul exemplu citeşte numele unui fişier/director de la tastatură şi-l scrie informaţii despre el.append("data ultimei modificari "+nume. } public String getDescription(){ return "fisiere java(*. buffer. scrie(analizeaza(citeste())). if(i>0 && i<nume. în fişierul analiza. buffer.append("lungimea "+nume. if(nume. public Fisier(){ try{ br=new BufferedReader(new InputStreamReader(System.isFile()){ 50 .getPath()+"\r\n").txt").substring(i+1). buffer. if(nume. pentru a crea un filtru trebuie să scriem o clasă care implementează interfaţa FilenameFilter. următoarea clasa filtreaza fişierele dintr-un director si le acceptă numai pe cele care sunt programe Java: import java. buffer. buffer. if(nume.append("nu este o cale absoluta\r\n").isFile()) buffer. String nume){ String sufix="".in)). cum ar fi: dacă este fişier sau director.append(nume. return sufix.append("este o cale absoluta\r\n").io.lastModified()+"\r\n"). true).lastIndexOf('. pw=new PrintWriter(new FileWriter("analiza.readLine(). public class Fisier{ BufferedReader br.*. }catch(IOException ioe){} } public String citeste()throws IOException{ System.length()-1) sufix=nume.exists()){ buffer.*.De exemplu. data ultimei modificări.isAbsolute())buffer. if(nume. public class Filtru implements FilenameFilter{ public boolean accept(File dir. De exemplu.length()+"\r\n").').out.append("este un fisier\r\n").

etc. respectiv cuvântul citit se folosesc următoarele variabile instanţă: public double nval //conţine valoarea numărului întors ca token public String sval //conţine caracterele cuvântului întors ca token Pentru a obtine un token din fluxul analizat se apelează metoda instanţă: public int nextToken() care returnează tipul token-ului citit ca un numar intreg. dar spre deosebire de prima clasă. Fisier: Lucrul cu clasa File Clasa StreamTokenizer Ca şi StringTokenizer. pw. "r"). try{ RandomAccessFile in=new RandomAccessFile(nume. } } Programul 1. iar pentru a trata sfarsitul fluxului de intrare folosim constanta public static finale int TT_EOF //token-ul citit conţine sfârşitul fluxului de intrare Deosebirea faţă de clasa StringTokenizer este ca aceasta clasă diferenţiaza token-ii obtinuti din fragmentare.isDirectory()){ buffer. } public static void main(String[] a){ new Fisier(). adică a fost apelată metoda void eolIsSignificant(boolean val) cu val=true. }catch(IOException ioe){} } else if(nume.readLine())!=null) buffer. 51 . Constructorul clasei: public StreamTokenizer(Reader r)//creaza un tokenizer care imparte fluxul de intrare r într-un şir de token-i.i<dir. while((s=in. sfârşitul unei linii. in. Pentru a sti daca s-a ajuns la sfarsitul liniei curente se foloseste constanta: public static finale int TT_EOL //token-ul citit conţine sfarşitul liniei curente (“\r” sau “\n”) dacă acesta este tratat ca un token. } } else buffer. clasa ofera urmatoarele constante: public static finale int TT_NUMBER //token-ul citit este un număr public static finale int TT_WORD //token-ul citit este un cuvânt Pentru a obtine numărul.append("acest nume nu exista").append(dir[i]+"\r\n"). String s="". return buffer. Acesta este memorat dupa apelul metodei si în variabila instanţă public int ttype.close().print(sir).’ si ‘–‘. } public void scrie(String sir) throws IOException { pw. for(int i=0.close().append(s+"\r\n").toString(). această clasă imparte un flux in token-i.length. diferenţiază între tipuri de token-i: şiruri.buffer. i++) buffer.append("Continutul directorului\r\n"). Clasa oferă si alte metode utile în analizarea unui flux de intrare specializat: public void parseNumbers()//sunt analizate numerele si caracterele ‘. Astfel. public int lineno()//întoarce numărul liniei curente. sfârşitul fişierului. String[] dir=nume. numere.append("Continutul fisierului\r\n").list().

println(io. respectiv numere.print("numar= "+st.exit(0).} } public void imparte(){ if(st==null) System.print("cuvant= "+st. max] sunt tratate ca spatii.txt” si afiseaza tipul fiecarui token si valoarea sa. import java.out. In acest caz. } } 52 . public void ordinaryChars(int min. fara sa mai verifice tipul sau si-l intoarce ca un token de tip TT_WORD. precum şi numarul de cuvinte. Dacă a doua apariţie a caracterului ch nu este găsită pana la sfarşitul liniei. Sa scriem un program care citeste continutul fisierului “intrare. try{ st=new StreamTokenizer(new BufferedReader(new FileReader("intrare. t.TT_WORD: System. public void whitespaceChars(int min. public Tokenizer(){ String linie.out.println("Total cuvinte= "+w). public void commentChar(int ch) //caracterul ch indica inceputul unui comentariu. int max) // toate caracterele ce au codul Unicod in intervalul [min. se iau caracterele de la ch pana la sfarsitul fisierului.} } public static void main(String[] args){ Tokenizer t=new Tokenizer(). Daca ch apare o singură dată in fluxul de intrare. din fisierul respectiv.println(). private int w.} catch(IOException io){System.nextToken()!=StreamTokenizer. } System.println(nf. n++. int max) // toate caracterele ce au codul Unicod in intervalul [min. token-ii fluxului de intrare aflati pana la sfarsitul liniei vor fi ignoraţi. break.sval+" "). System.println(io. max] sunt tratate ca parte din cuvinte. }catch(IOException io){System.getMessage()). int max) //toate caracterele ce au codul Unicod in intervalul [min. public void pushBack()//token-ul curent va fi obtinut si la urmatorul apel al metodei nextToken() Exemplu.imparte().out.out.ttype){ case StreamTokenizer. w++.nval+" "). } System. n.public void ordinaryChar(int ch) //trateaza caracterul dat la apelul metodei ca unul oarecare. break.println("Total numere= "+n).*. }catch(FileNotFoundException nf){System.io.out.out. max] sunt tratate ca oarecare. case StreamTokenizer. public class Tokenizer{ private StreamTokenizer st.txt"))). se iau caracterele pana la acesta. public void quoteChar(int ch) //caracterele gasite intre două apariţii a lui ch sunt tratate ca un literal String si intoarse ca un token de tip TT_WORD. public void wordChars(int min. try{ while(st.TT_NUMBER: System.TT_EOF){ switch(st.out.getMessage()).out.getMessage()).

cu excepţia lui RuntimeException şi a subclaselor sale. referinţă la un obiect null. } static void metoda2(int[] b){ System. public void printStackTrace(java.situaţie particulară apărută în timpul execuţiei programului care poate fi de unul din următoarele tipuri: .io. De exemplu. public void printStackTrace().main(Exceptie.PrintWriter pw).out. indică situaţii particulare care nu sunt erori. împreuna cu numărul liniei pe care se găseşte declaraţia metodei. public void printStackTrace(java.PrintStream ps).NullPointerException at Exceptie.metoda1(Exceptie. De exemplu. împreună cu alte informaţii. Toate excepţiile ce pot fi generate sunt împărţite în două clase: Exception şi Error. public Throwable(String mesaj). public String getMessage().println(b[0]).excepţii controlate: erori de intrare/ieşire precum continuarea operaţiei de citire după ce s-a ajuns la sfârşitul fişierului.java:9) Mesajul afişat conţine următoarele informaţii: .condiţie de eroare provocată de erori interne sau lipsa resurselor mediului de executie Java.tipul de exceptie aruncat. .excepţii necontrolate cauzate de erori de programare: cast greşit. Dacă nu sunt tratate de programator.metoda2(Exceptie. . } } determină afişarea mesajului: java.9. Toate 53 . încercarea de a deschide un URL greşit.io. ce vor ajuta la tratarea exceptiei. clasa Throwable implementează mai multe metode printre care şi metoda getMessage() care returnează un şir care descrie situaţia care a cauzat excepţia. public String toString(). dacă apare o astfel de excepţie se va apela metoda printStackTrace() a clasei Throwable.stiva apelurilor metodelor.lang: public class Throwable{ public Throwable(). clasa RunTimeException conţine tipuri de excepţii lansate automat de JVM.java:3) at Exceptie. GESTIUNEA EXCEPŢIILOR O excepţie este o condiţie exceptională care întrerupe execuţia unui program şi care poate fi: . cast care depăşeşte limita unui array. Când apare o excepţie este important să captăm cauza ce a dus la apariţia ei. } După cum observăm. RuntimeException şi subclasele lor indică condiţii care în general nu sunt corecte şi care de obicei generează terminarea unui program. toate excepţiile în Java sunt reprezentate de obiecte ale subclaselor clasei Throwable din pachetul java. ambele derivate din clasa Throwable. public Throwable fillInStackTrace().lang.java:6) at Exceptie. . executarea următorului program public class Exceptie{ static void metoda1(int[] a){ metoda2(a). } public static void main(String[] args){ metoda1(null). fiecare cu clasa şi unitatea de compilare de care aparţine. Error. Subclasele lui Exception. De aceea. Metoda din vârful stivei este cea care a aruncat excepţia respectivă. cum ar fi valoarea variabilelor folosite.

Erori generale de I/O. Clasa respectivă trebuie să fie importată sau scrisă de către programator. Programul incearcă să acceseze un caracter de pe o poziţie care nu există în şir. Un applet înacearcă să realizeze o acţiune care nu este permisă de browser. Memorie insuficientă creării unui obiect nou. cum ar fi incapacitatea de citi dintr-un fişier.pachetele incluse în JDK generează diferite tipuri de excepţii. Depăşirea stivei de execuţie. Se încearcă folosirea unei clase pe care compilatorul nu o cunoaşte. Referirea unui obiect null. O conversie eşuată între şiruri şi numere. Se accesează un fişier care nu există în locaţia specificată de program. Se memorează într-un array o valoare de tip diferit de tipul de date al array-ului. 54 . O parte din acestea sunt prezentate în figurile de mai jos şi unele din acestea sunt explicate în următorul tabel: Exceptie ArithmeticException ArrayIndexOutOfBoundsException ArrayStoreException ClassNotFoundException FileNotFoundException IOException NullPointerException NumberFormatException OutOfMemoryException SecurityException StackOverflowException StringIndexOutOfBoundsException Cauzată de Erori matematice cum ar fi imparţirea la zero. Indicele unui array este în afara array-ului.

Excepţii şi erori ClassNotFoundException CloneNotSupportedException Object Throwable Exception IllegalAccessException InstantiationException InterruptedException NoSuchMethodException NoSuchFieldException RunTimeException IOException ClassCircularityError ClassFormatError ArithmeticException ArrayStoreException ClassCastException IllegalArgumentException IllegalStateException IllegalMonitorStateException IndexOutOfBoundsException NegativeArraySizeException NullPointerException SecurityException AbstractMethodError IllegalAccessError InstantiationError NoSuchFieldError NoSuchMethodError ArrayIndexOutOfBoundsException StringIndexOutOfBoundsException IllegalThreadStateException NumberFormatException ExeptionInInitializerError LinkageError IncompatibleClassChangeError NoClassDefFoundError Object Throwable Error UnsatisfiedLinkError ThreadDeathError VerifyError InternalError VirtualMachineError OutOfMemoryError StackOverflowError UnknownError 55 .

Dacă nu se doreşte ca metoda respectivă să fie abandonată. . Argumentul metodei poate să nu fie utilizat în codul gestorului. Blocul crează un mediu (spaţiu de nume) în interiorul metodei. Interceptarea şi tratarea excepţiilor Interceptarea şi tratarea excepţiilor se realizează de către gestorii de excepţii (exception handler). De exemplu. chiar dacă apare o excepţie şi furnizează un spaţiu util de a scrie cod care să fie executat indiferent ce se întâmplă. în mod normal. Mecanismul de gestiune a excepţiilor furnizează reguli care impun cine este capabil să genereze excepţii (throws) şi când (throw). controlul abandonează metoda. iar restul se ignoră. deoarece în cazul apariţiei unei excepţii. iar alegerea gestorului este în întregime bazată pe tipul excepţiei. Această situaţie va fi detectată de compilatorul Java şi va reporta o eroare. . . Dacă apare o excepţie ca rezultat al executării uneia din instrucţiunile blocului. deoarece primul este mai general şi va trata şi excepţiile de intrare/ieşire (deoarece IOException este o subclasă a lui Exception). instrucţiunile ce pot genera cel puţin o excepţie se includ într-un bloc try care “încearcă” să le execute.corectarea problemei şi apelarea metodei care a cauzat excepţia. Aceasta e desigur o investiţie bună pe termen scurt (pentru debugging) şi pe termen lung (pentru robusteţea programului). In exemplul următor.elaborarea unui rezultat alternativ raportat la cel produs în mod normal de metodă. Pentru acelaşi bloc try putem avea mai mulţi gestori. cine va încerca excepţiile (try.simplifică dacă schema de elaborare a excepţiilor aleasă complică lucrurile. Când în interiorul unei metode va fi lansată o excepţie sau apelul unei metode lansează o excepţie. ea poate fi “prinsă” (catch) de gestorul excepţiei respective. Gestorii excepţiilor pentru un bloc try sunt introduşi cu cuvântul cheie catch şi urmează blocul try.se termină programul.catch) şi ce trebuie să facă pentru a împiedica apariţia unei excepţii.Cum utilizăm excepţiile? Există mai multe alternative pentru programator: . void metoda1(){ try{ //cod care poate produce o exceptie }catch(IOException ioe){ //cod care gestioneaza exceptia ioe } catch(Exception e){ //cod care gestioneaza exceptia e } } Un bloc try poate fi urmat eventual şi de un bloc declarat cu finally. Un bloc finally conţine instrucţiuni ce vor fi executate întotdeauna.se face tot ce se poate în contextul curent şi se relansează aceeaşi excepţie în contextul superior. Tratarea excepţiilor prezintă următoarele avantaje: . Fiecare gestor de excepţii este ca o metodă care primeşte un unic argument care are tipul unei excepţii şi va fi executată în cazul în care apare o excepţie de tipil respectiv. In acest caz este importantă ordinea gestorilor. următoarea metodă gestionează interceptarea unei excepţii şi a unei erori şi indiferent dacă acestea apar sau nu.se încearcă repararea unei greşeli şi se continuă fără să se reapeleze metoda. se verifică tipul excepţiei cu fiecare gestor în ordinea în care apar dupa blocul try. . . . acest lucru înseamnă că al doilea gestor niciodată nu va trata nici o excepţie. Se va executa primul gestor care verifică excepţia.se face tot ce se poate în contextul curent şi se relansează o excepţie diferită în contextul superior.. se va executa codul din blocul finally: void metoda2(){ try{ //cod care poate produce o exceptie }catch(Exception e){ 56 .face mai fiabile programul şi librăriile utilizate.

//cod care gestioneaza exceptia e } catch(Error er){ //cod care gestioneaza eroarea er } finally{ //cod ce va fi executat indiferent daca apar sau nu exceptia e sau eroarea er } }

Gestorul poate prinde o excepţie de tip: - Exception pentru orice excepţie din bibliotecile Java; - specializat pentru un pachet Java (de exemplu IOException); - definit de programator. Declaraţii throws Dacă o metodă nu tratează toate excepţiile ce pot apare atunci când este executat corpul său, atunci ea trebuie să declare în header-ul său toate tipurile de excepţii care pot să apară şi nu le tratează. Pentru aceasta se inserează o declaraţie throws după parametrii metodei şi înainte de corpul său:
modificatori numeTip numeMetoda(listaParametri) throws listaNumeTip{ //lista de instructiuni }

unde listaNumeTip::=numeTip [, numeTip]* Excepţiile declarate cu throws se vor propaga metodei superioare în stivă, aceleia care a apelat-o. In acest caz, metoda apelantă trebuie să se afle în una din următoarele situaţii: - metoda este apelată dintr-un bloc try care are gestori capabili să prindă toate tipurile de excepţii ce pot fi aruncate de metoda apelată. - metoda este apelată dintr-un bloc try care are gestori capabili să prindă numai unele din tipurile de excepţii ce pot fi aruncate de metoda apelată. Pentru celelalte tipuri de excepţii, metoda apelantă trebuie să le declare cu throws şi ele vor fi propagate mai departe. - metoda este apelată din afara unui bloc try şi atunci toate tipurile de excepţii ce pot fi aruncate trebuie să apară în declaraţia throw a metodei apelante. Notă: Excepţiile de tip Error, RuntimeException şi a subclaselor sale nu trebuie să fie declarate cu throws. Următoarea metodă returnează un caracter citit de la tastatură:
public char citesteCaracter() throws IOException{ return (char)System.in.read(); }

Lansarea excepţiilor În timpul proiectării programului sau în timpul depanării, dacă se consideră necesar ca o metodă să lanseze o excepţie, se execută următorii paşi: - căutarea clasei de excepţii corespunzătoare; - dacă metoda nu tratează excepţia apărută, se declară că apelul metodei va lansa o excepţie (cu ajutorul lui throws şi clasa de exceptie găsită la pasul anterior); - crearea unui obiect al acelei clase; - lansarea obiectului creat imediat după punctul în care se verifică excepţia, folosind instrucţiunea throw; Exemplu. Metoda următoare citeşte caracter cu caracter o linie de la tastatură pe care o returnează metodei apelante care trebuie să trateze excepţia de tip IOException sau s-o arunce mai departe metodei apelante:

57

import java.io.*; public class Linie{ StringBuffer sb=new StringBuffer(); void readLine() throws IOException{ char c; while(true){ c=(char)System.in.read(); if (c==13) throw new IOException("Caracterul citit este CR"); sb.append(c); } } public static void main(String[] args){ Linie f=new Linie(); try{ f.readLine(); }catch(IOException e){System.out.println(e.getMessage());} System.out.println(f.sb.toString()); } }

Procesul de reportare a unei excepţiei în sus continuă până când excepţia va fi interceptată de o metodă activă care se angajează să o rezolve sau până când ajunge în vârful stivei şi aplicaţia se termină. Următorul exemplu arată cum se poate citi conţinutul unui fişier şi să detectăm sfârşitul fişierului aruncându-se o excepţie de tip EOFException:
String readData(BufferedReader in){ StringBuffer sb=new StringBuffer(); String s; try{ while(true){ s=in.readLine(); if (s==null){ in.close(); throw new EOFException("Am ajuns la sfarsitul fisierului"); } sb.append(s); } }catch(IOException ioe){ System.out.println("Exceptie de citire: "+ioe.getMessage()); } finally{ return sb.toString(); } }

Observaţie: Cum EOFException este o subclasă a lui IOException, metoda readData() tratează excepţia apărută, deci ea nu va fi aruncată metodei apelante. Important: lansând o excepţie, metoda nu o returnează apelului. Se pot crea clase de excepţii noi. Trebuie să avem o clasă care extinde clasa Exception sau un alt tip apropiat ca semantică cu excepţia noastră, în care să redefinim constructorii. De exemplu, ne definim o clasă excepţie numită FileFormatException:
public class FileFormatException extends IOException{ public FileFormatException(){} public FileFormatException(String mesaj){ super(mesaj); } }

Atunci, metoda readData() de mai sus ar putea fi rescrisă astfel:
58

String readData(BufferedReader in){ StringBuffer sb=new StringBuffer(); String s; try{ while(true){ s=in.readLine(); if (s==null){ in.close(); throw new FileFormatException("Am ajuns la sfarsitul fisierului"); } sb.append(s); } }catch(IOException ioe){ System.out.println("Exceptie de citire: "+ioe.getMessage()); } finally{ return sb.toString(); } }

O excepţie poate fi rearuncată şi dintr-un bloc catch. Atunci putem avea mai multe metode din lanţul de metode active care să trateze excepţia, poate fiecare din acestea indeplinindu-si partea sa din restaurarea stării programului astfel încât acesta din urmă să-şi poată continua execuţia după ce excepţia a fost tratată.

59

Arborele Dezavantaje Căutare lentă. Deseori trebuie să executăm operaţii care privesc întregul grup. relaţiile dintre componentele unei colecţii nu mai sunt de ordine totală. cu avantajele şi dezavantajele lor de utilizare. Tabelul 10-1 reaminteşte principalele structuri de date. ci de oridne parţială. În alte situaţii. în schimb. nu este unica posibilitate de a găsi un element fie prin navigarea componentelor sau prin identificarea lui prin intermediul un număr de ordine. cum ar fi: . capacitate limitată Căutare lentă. mult mai complexe. Pentru fiecare tip de colecţie. în al doilea caz. conturile bancare ale clienţilor unei bănci sau comenzile făcute în ultima perioadă. fie din natura sa: colecţia de obiecte sau relaţii de tipuri funcţionale între două colecţii. . Este cazul relaţiilor care sunt colecţii de legături între o cheie şi componenta asociată (tipul Map). eliminare lentă. În schimb. acces rapid dacă indexul este cunoscut Căutare mai rapidă decât într-un array neordonat Inserare şi eliminare rapide Acces “last-in.adăugarea la grup sau eliminarea din grup a unui grup de obiecte.eliminarea tuturor obiectelor din grup. avem tipul mulţime (Set).adăugarea unui nou obiect la grup. De exemplu.verificarea dacă grupul este vid sau conţine cel puţin un obiect.eliminarea unui obiect existent din grup. În anumite aplicaţii poate fi util să găsim o componentă prin intermediul proprietăţilor ei. inserare şi eliminare rapidă (dacă arborele rămâne balansat) Căutare. trebuie să proiectăm algoritmi şi structuri de date corespunzătoare. eliminare lentă. Este cazul arborilor şi a grafurilor care necesită modalităţi sofisticate de abordare. Structura de date Array Array ordonat Listă înlănţuită Stivă Coadă Arbore binar Arbore binar de Avantaje Inserare rapidă.verificarea că un anumit obiect există în grup. dar atunci când este navigată se pot întâlni duplicate care pot crea confuzie.10.conţinutul obiectelor conţinute. pot fi oferite servicii care satisfac exigenţele programatorilor. first-out” Acces “first-in. programatorul poate fi interesat de o colecţie în care fiecare componentă se găseşte într-o poziţie bine stabilită în raport cu alte componente sau colecţia nu impune nici o ordine poziţională. Diferenţele dintre colecţii se datorează fie din exigenţele ce privesc navigarea într-o colecţie. capacitate limitată Căutare lentă Acces lent la componentele care nu sunt în vârf Acces lent la componentele care nu sunt în vârf Algoritm de eliminare complex pentru ca arborele să rămână balansat Este complex. Utilizarea unui astfel de grup este necesară din următoarele motive: . COLECTII STRUCTURI DE DATE DINAMICE Presupunem că avem nevoie să utilizăm grupuri de obiecte care au unele proprietăţi comune. first-out” Căutare. ca în cazul listelor. În primul caz avem tipul listă (List) de colecţie. care formează întodeauna o colecţie. . cum ar fi personalul unei întreprinderi. Numărul componentelor din grup nu este cunoscut de obicei cunoscut de la început şi poate varia după necesităţile aplicaţiei. TIPOLOGII DE COLECŢII Pentru a găsi soluţii standard la problema colecţiilor este mai întâi necesar să identificăm tipurile de colecţii după care modul în care se doreşte elaborarea colecţiei. . sintetizate de o dată cheie. inserare şi eliminare rapidă. . . Astfel de grupuri de obiecte se numesc colecţii şi pentru a le putea elabora. 60 .

Poate fi utilizat pentru file systems Căutare. an). atunci pentru orice i şi j a. spunem că lista este de tip T. Implementarea listelor Modul cel mai uşor de a implementa o lista este să folosim o lista de noduri legate între ele. Implementarea in Java a unui nod al listei este: 61 . …. acces lent dacă cheia nu este cunoscută. a2 al doilea. Avem eroare daca L este de lungime mai mica decat i. esteVida(L) returnează true daca L nu contine nici un element. Lungimea unei liste este numărul de apariţii a elementelor listei. Acces rapid la componente mai mari. Putem cauta un element intr-o lista L. Principalele structuri de date 10. utilizează ineficient memoria. a2. Prefixul unei liste este orice sublista care incepe la inceputul unei liste. Daca numarul este zero. 2. 29) O linie de text este o lista de caractere. Daca x nu apare in lista. 19. an este ultimul element in lista. …. 1≤i≤j≤n. Notatie () sau ε. concateneaza(L1. 9. 7. atunci primul element se numeste capul listei. Ca un caz special. atunci lista este vidă. Inserare şi eliminare rapide Modelează situaţii frecvente în lumea reală Dezavantaje Este complex. (ai. Aceasta operatie este logică. atunci operatia de stergere nu are nici un efect. Daca L=(a1. Exp. an) şi n≥1 atunci a1 este primul element.11. Fiecare nod contine doua campuri: – primul contine un element al listei. 13. Inserarea unui element x într-o listă L. ai+1. In principiu x ar putea să apară oriunde in listă şi nu contează dacă x apare de mai multe ori. elementAt(i. Exp.Structura de date căutare Arbore rosu-negru Tabel hash Heap Graf Avantaje este întotdeauna balansat. a2. L=(x. …. samd. returnand true daca x se gaseste in lista. Inserare rapidă. an) Exemple: Lista numerelor prime 10 numere prime naturale: (2. 6. a1.1. 8. Stergerea unui element din listă. iar restul listei formează coada listei. Ambele genereaza o eroare daca lista este vida. lungime(L) returneaza lungimea listei L. L2) două liste L1 şi L2. Dacă toate elementele sunt de acelaşi tip T. Stergerea tuturor elementelor din lista. o lista este este scrisă specificandu-se elementele sale ai: (a1. 17. 4. Acces lent la alte componente. – al doilea contine o referinta la urmatorul nod al listei.5. putem spune că aI apare la poziţia i in lista.1 Structura de date listă O listă este o secvenţa finită de zero sau mai multe elemente.3.i. …. Daca o lista este nevidă. 23. De obicei. 7. L) returneaza elementul de pe pozitia i a listei L. putem insera pe x la inceputul listei şi atunci x va fi capul noii liste. Sufixul unei liste este o sublista care se termină la sfarşitul listei. Se va sterge prima apariţie a elementului x în listă. Asadar. fiecare element din listă are asociată o poziţie. Acces foarte rapid dacă se cunoaşte cheia. Orice algoritm este complex şi lent Tabelul 10-1. numarul de poziţii ale unei liste formeaza lungimea listei. an) este o listă. 5. Eliminare lentă. Operaţii asupra listelor 1. iar lista initiala va deveni coada. …. inserare şi eliminare rapidă. Notatie. Dacă L=(a1. 3. a2. aj) este o sublista a lui L. Arborele este întotdeauna balansat. a2. De asemenea. Un document este o lista de linii de text. prim(L) intoarce primul element al listei şi ultim(L) intoarce ultimul element al listei .

nr). n-1. return. } public Nod(Object o.next=curent.nr++.next=cap.} if (verificaPozitie(index)){ Nod n=new Nod(o). } nr++. next=n. } public int lungime(){ return nr. Nod n){ element=o. pentru fiecare element al listei avem cate un nod. an) este reprezentata ca o listă linked-itata astfel: a1 a2 … an Implementarea în Java a operaţiilor asupra listelor linked-itate este realizată în următorul program: public class Lista{ private Nod cap. } //inserarea unui element la o anumita pozitie public void insereazaElement(Object o. } } //verificarea pozitiei unui element private boolean verificaPozitie(int index){ if (index>lungime() || index<0) return false. } else { Nod curent=nodLa(index-1). private Nod next. Variabila next din nodul i contine o referintă la nodul (i+1). cap=n. pt i=1. n. a2.public class Nod{ private Object element. int index){ if (esteVida() && index==0){adaugaElement(o). if (esteVida()){cap=n. } //adauga un element la sfarsitul listei public void adaugaElement(Object o){ Nod n=new Nod(o). 62 . private Lista coada. if(index==0){ n.next. curent. Variabila next al ultimul nod este null.next=n. private int nr. De exemplu: lista L=(a1.} else insereazaElement(o. public boolean esteVida(){ return lungime()<=0. indicând sfarşitul listei. } } Atunci. public Nod(Object o){ element=o. …. elementul ai apare în campul element al nodului i.

return true; } //returneaza nodul de la o anumita pozitie public Nod nodLa(int index){ if (verificaPozitie(index)){ if (index==0) return cap; Nod n=cap; for(int i=0; i<index;i++) n=n.next; return n; } return null; } //returneaza elementul de la o anumita pozitie public Object elementulDeLa(int index){ Nod n; if ((n=nodLa(index))!=null) return n.element; return null; } //cauta un element in lista public int cauta(Object o){ Nod n=cap; for (int i=0;i<nr;i++){ if (n.element.equals(o)) return i; else n=n.next; } return -1; } //returneaza primul element din lista public Object prim(){ return cap.element; } //returneaza ultimul element din lista public Object ultim(){ return nodLa(nr-1).element; } //sterge un element din lista daca acesta exista public boolean stergeElement(Object o){ int poz=cauta(o); if(poz==-1) return -1; Nod curent=nodLa(poz); if(poz==0) cap=curent.next; else{ Nod anterior=nodLa(poz-1); anterior.next=curent.next; } curent=null; nr--; return true; } //sterge toate elementele listei public void stergeToateElementele(){ if (!esteVida()){ cap=null; coada=null; nr=0; 63

} } //afiseaza lista sub forma (o1, o2, ..., on) public String toString(){ StringBuffer sb=new StringBuffer(); sb.append("["); IteratorLista it=new IteratorLista(cap); while (it.hasNext()){ sb.append(it.next().toString()); if (it.hasNext()) sb.append(", "); } sb.append("]"); return sb.toString(); } //converteste lista la un array public Object[] getListaArray{ Object[] o=new Object[lungime()]; int poz=0; IteratorLista it=new IteratorLista(cap); while(it.hasNext()){ o[poz]=it.next(); poz++; } return o; } //concateneaza lista curenta cu o alta lista public Lista concateneaza(Lista l){ Lista rez=this; IteratorLista it=new IteratorLista(new Nod(l.prim())); while (it.hasNext()) rez.adaugaElement(it.next()); return rez; } }//clasa Lista public class IteratorLista{ private Nod curent; public IteratorLista(Nod c){ curent=c; } public boolean hasNext(){ return curent!=null; } public Object next(){ Object ret=curent.element; curent=curent.next; return ret; } } public class TestLista{ public static void main(String[] args){ Lista l=new Lista(); Lista p=new Lista(); Student[] s=new Student[3]; s[0]=new Student(“Ionescu”, “Ion”, “Informatica”); s[1]=new Student(“Popescu”, “Mircea”, “Matematica-Informatica”); 64

s[2]=new Student(“Marinescu”, "Ciorica", “Informatoca”); l.adaugaElement(s[0]); l.adaugaElement(s[1]); System.out.println(l); l.stergeElement(s[0]); System.out.println("sterge= "+l); l.insereazaElement(s[2],0); System.out.println(l); System.out.println("primul element= "+l.prim()); System.out.println("ultimul element= "+l.ultim()); if(l.cauta(s[0])) System.out.println("elementul se gaseste in lista"); else System.out.println("elementul nu se gaseste in lista"); p.adaugaElement(s[1]); Lista rez=l.concateneaza(p); System.out.println(rez); Object o=rez.elementulDeLa(1); if (o!=null) { ((Student)o).setMedie(9.35); System.out.println(o); } System.out.println(rez); l.stergeToateElementele(); System.out.println(l); } } 10.1.2 Structura de date stivă

O stivă este un model de date bazat pe modelul listă în care toate operaţiile sunt realizate la un capăt al listei, care se numeşte vârful stivei. Stiva este o structură de date LIFO adică “last-in first-out (ultimul intrat, primul ieşit)”. Modelul abstract al unei stivei este acelaşi cu cel al unei liste – adică o secvenţă de elemente a1, a2,…, an de un anumit tip. Ceea ce deosebeşte o stivă de o listă este setul de operaţii permise aupra unei stive.
Operaţii asupra unei stive

Inserarea unui element x într-o stivă S, push(x, S), determină punerea elementului x în vârful stivei S. Dacă stiva are vârful capătul stâng al stivei, operaţia push(x) aplicată listei (a1, a2,…, an) generează lista (x, a1, a2,…, an). Stergerea elementului din vârful stivei este realizată de metoda pop(S). Aceasta va sterge elementul din vârful stivei şi va fi returnat de către metodă. Dacă stiva este vidă, metoda va genera o eroare. Stergerea tuturor elementelor din stivă va fi realizată de metoda stergeToateElementele(S). Metoda lungime(S) va returna lungimea stivei S, iar metoda esteVida(S) returnează true dacă S nu contine nici un element.
Implementarea stivelor

Pentru a implementa static o stivă vom folosi un array de 10 obiecte:
public class StivaArray{ private Object[] lista; private Object varf; 65

i++) lista[i]=null. 1. } public void push(Object x){ if (esteVida()) lista[0]=x. private int poz. } varf=lista[0]. lista. i<poz-1. i<poz. } public Object pop() throws ListaException{ if (esteVida()) throw new ListaException("Stiva este vida"). poz--. return o. else { System. 0. s+=lista[poz-1]+")". vom implementa dinamic o stivă cu ajutorul listelor simplu înlănţuite. Object o=varf.private static int nr=10. private Object varf. varf=null.adaugaElement(x). poz=0. 0. } public void push(Object x){ if (esteVida()) l. ". return s. public StivaArray(){ lista=new Object[nr]. public class Stiva{ private Lista l.arraycopy(lista. System. 1. } } In continuare. lista. 66 . poz-1). } //verifica daca stiva este vida public boolean esteVida(){ return lungime()<=0. } public String toString(){ String s="(". public Stiva(){ l=new Lista(). private int nr. lista[0]=x. } //returneaza lungimea stivei public int lungime(){ return poz. } else s+=")".arraycopy(lista. if(poz!=0){ for (int i=0. poz). i++) s+=lista[i]+". } public void stergeToateElementele(){ for (int i=0. poz++.

a2. Dacă coada începe din capătul stâng al listei. şi şterse pe la celălalt capăt al listei numit început. } //returneaza lungimea stivei public int lungime(){ return nr. try{ varf=l. an) generează lista (a2.elementulDeLa(1). } public void stergeToateElementele(){ l. return o. x). 67 . Dacă coada este vidă. stergeToateElementele(C). try{ varf=l. iar operaţia introduce(x) generează lista (a1. 0). }catch(ListaException le){varf=null. Mai precis. public class Coada{ private Lista l.…. x) adaugă elementul x la sfârşitul cozii. } public String toString(){ return l. operaţia extrage() aplicată listei (a1.insereazaElement(x. a2. }catch(ListaException e){} nr++.else l.stergeToateElementele().3 Structura de date coadă O coadă este un model de date bazat pe modelul listă în care elementele sunt inserate pe la un capăt al listei.toString().….stergeElement(l.1. an). } public Object pop() throws ListaException{ if (esteVida()) throw new ListaException("Stiva este vida").…. extrage(C) extrage elementul de la începutul cozii. an. Operaţii asupra unei cozi - introduce(C.} l.elementulDeLa(0)). o coadă este o structură de elemente în care putem insera şi sterge elemente după politica FIFO: first-in. numit sfârşit. nr--.prim(). } //verifica daca stiva este vida public boolean esteVida(){ return lungime()<=0. atunci operaţia va genera o eroare. stergerea tuturor elementelor din coadă. first-out. lungime(C) returneaza lungimea coadă C. nr=0. } } 10. esteVida(C) returnează true dacă C nu contine nici un element Implementarea unei cozi Vom implementa operaţiilor ce pot fi executate asupra unei cozi cu ajutorul unei liste simplu înlănţuită. varf=null. Object o=varf.

nr--. } public String toString(){ return l. “Informatica”).elementulDeLa(0)).println(st).out.prim(). st. s[1]=new Student(“Popescu”. “Mircea”. 68 .adaugaElement(x).out.toString(). l. try{ Student o=(Student)st.push(s[2]). nr++. } } public class TestStivaSiCoada{ public static void main(String[] args) throws ListaException{ Student[] s=new Student[3]. sfarsit=l.println("scoate= "+o). private int nr. st. s[2]=new Student(“Marinescu”. nr=0. } //verifica daca stiva este vida public boolean esteVida(){ return lungime()<=0.elementulDeLa(1). “Matematica-Informatica”).push(s[1]). System. try{ if (nr==1) inceput=l. } public void introduce(Object x){ l. System. sfarsit=null.out. "Viorica".stergeToateElementele(). inceput=null. sfarsit.println(st). } //returneaza lungimea stivei public int lungime(){ return nr.push(s[0]). Object o=inceput.ultim(). public Coada(){ l=new Lista(). st. inceput=l. }catch(ListaException e){} } public Object extrage() throws ListaException{ if (esteVida()) throw new ListaException("Stiva este vida"). System. Stiva st=new Stiva().stergeElement(l. s[0]=new Student(“Ionescu”.private Object inceput. “Ion”. } public void stergeToateElementele(){ l.pop(). return o. “Informatica”).

println(c). prin convenţie. putem defini înălţimea unui arbore ca fiind maximul dintre nivelurile nodurilor frunză.1. 69 . try{ Student o=(Student)c.println(c). c. In cazul în care un nod nu are noduri fii.conţine un nod special. are un singur nod părinte şi poate avea mai mulţi fii. 1.extrage(). n5.out.getMessage()). n7 şi n4 sunt noduri frunză. System. c. al cărei nivel este. Aşadar.out. iar p este un fiu al lui c. fiecare cu rădăcina n2. Valoarea n reprezintă nivelul pe care se găseşte nodul faţă de rădăcină. orice nod c diferit de rădăcină este legat de un alt nod p al arborelui printr-o muchie. n6) este calea de la rădăcină la nodul n6. are trei subarbori.(n3.} Coada c=new Coada(). nodurile n2.st. c.stergeToateElementele(). }catch(ListaException e){System.4 Structura de date arbore Un arbore este format dintr-o mulţime de noduri legate prin muchii ce îndeplinesc următoarele condiţii: . nodul c este părintele lui p.getMessage()). datorită relaţiei de “subordonare” faţă de rădăcină. în sensul că accesul de la rădăcina unui (sub)arbore nevid la oricare al nod presupune parcurgerea unei căi formate din a muchii (a≥0) pe care se găsesc n noduri (n=a+1). un arbore este conectat. O muchie este indicată prin perechea de noduri pe care le leagă. cu excepţia nodului rădăcină.out. De exemplu. c. System. orice nod. n3). nodul n3 este părinte pentru nodurile n5 şi n6 şi fiu pentru rădăcină. în sensul că orice două muchii succesive din cale au un nod comun. System.out.introduce(s[1]).} } } 10.println("scoate= "+o). System.introduce(s[2]). numit nod rădăcină. un arbore A se poate defini ca fiind format dintr-un nod rădăcină de care este legată o mulţime finită de arbori. In plus.println(c). System. (n1. In acest caz.stergeToateElementele().introduce(s[0]). }catch(ListaException e){System.out.println(st). orice muchie leagă două noduri distincte. putem caracteriza următorul arbore astfel: n1 n2 n3 n4 - n5 n6 n7 - rădăcina arborelui este n1.out. Aceştia sunt numiţi subarborii lui A. n3 şi n4.println(e. De aceea.println(e.out. se numeşte nod frunză (sau terminal). Aşadar. o cale într-un arbore este o succesiune de muchii adiacente două cate două.

stergerea unui element din arbore cu returnarea unei valori logice care ia valoarea true dacă elementul există în arbore. adică nodul curent este vizitat după ce au fost parcurşi cei doi subarbori. Operaţia va începe cu rădăcina arborelui şi va returna valoarea false dacă elementul nu a fost găsit.info=info. afişarea arborelui. cei doi potenţiali subarbori ai unui arbore nevid se numesc subarbore stâng şi subarbore drept. respectiv fiu drept. 2. căutarea unui element în arbore. Nod r){ info=inf. modificarea informaţiei memorată în rădăcina arborelui. } } Operaţii asupra aborilor binari Asupra unui arbore binar putem executa următoarele operaţii: 1. } public Nod getNodDrept(){ return drept.postordine. In continuare. Implementarea in Java a unui nod al unui arbore binar este dată în continuare: public class Nod{ private int info. } public Nod(int inf. 4. După cum ştim. stang=l.adăncimea arborelui este egală cu 4. cei doi potenţiali fii ai unui nod al unui arbore binar se numesc fiu stâng. Similar.. In acest caz. adică cu arbori ai căror noduri au cel mult doi fii (direcţi).preordine. 6. drept=r. } public int getInformatie(){ return info. public Nod(int inf){ info=inf. } public void setInformatie(int info){ this. 70 . informaţia din nodurile unui arbore va fi afişată în funcţie de ordinea în care arborele binar a fost parcurs. . } public void setNodDrept(Nod s){ drept=s. începând cu rădăcina arborelui: . inserarea unui element în arbore. . Nod l. ştergerea întregului arbore.inordine presupune parcurgerea subarborelui stâng al nodului curent. . 3. apoi a acestuia din urmă şi pe urmă subarborele drept. adică vizitarea nodului curent si apoi a subarborelui stâng. } public void setNodStang(Nod s){ stang=s. private Nod stang. vom lucra numai cu arbori binari. } public Nod getNodStang(){ return stang. respectiv drept al acestuia.arborele este de nivel 4. 5. drept.

Dacă A este vid. if (p==null || p. Dacă unul din subarbori nu există şi ne aflăm pe un nivel nou al arborelui. } } else{ Nod n1=n. cautare şi ştergere a unui element in/dintr-un arbore binar ce îndeplineşte următoarea proprietate: informaţiile nodurilor sunt ordonate astfel încăt informaţia unui nod oarecare este “mai mare” decât informaţia oricărui nod al subarborelui stâng al său şi este “mai mică” decât informaţia oricărui nod al subarborelui drept al său. adică nodul curent (care iniţial va fi rădăcina) analizat este null atunci x nu se găseşte în arbore.getInformatie()) { Nod n1=n. else { n. if (n1!=null) insereaza(element. 71 . atunci se crează un nod ce conţine elementul x şi acesta va fi rădăcina arborelui. else { n. avem nevoie să ştim nodul părinte al nodului curent. Ordonarea este cea obişnuită dacă informaţiile sunt numerice sau este de tip lexicografică dacă avem de-a face cu caractere sau şiruri de caractere. Nod p.setNodDrept(new Nod(element. if (n1!=null) insereaza(element. null. } } if (nou) inaltime++. începând bineînţeles cu rădăcina acestuia: Baza. null)). n1. false). Metoda următoare implementează în Java acest algoritm: private void insereaza(int element.getInformatie()==element) return.setNodStang(new Nod(element. null. n1. n. n. else if(element<n. } } Căutarea unui element într-un arbore binar de căutare Următorul algoritm recursiv descrie paşii necesari căutării unui element x în arborele A. atunci înălţimea arborelui este incrementată cu o unitate. } else { if(n. boolean nou){ if (esteVid()){ rad=new Nod(element). Dacă A nu este vid şi x nu se găseşte ca înformaţie a unui nod oarecare al arborelui. if (p==null || p. Nod n.getNodStang()==null) nou=true. Pas recursiv. inaltime=1. null)). Altfel. nou=false. atunci x este deja în arbore şi operaţia se termină. atunci se inserează x în subarborele stâng al rădăcinii dacă x este mai mic decât informaţia rădăcinii sau se inserează în subarborele drept al rădăcinii dacă x este mai mare decât informaţia conţinută în rădăcină.getNodDrept()==null) nou=true.getNodDrept(). Inserarea unui element într-un arbore binar de căutare Următorul algoritm recursiv descrie paşii necesari pentru ca un element x să fie inserat în arbore A: Baza.getNodStang().In continuare vom exemplifica implementarea operaţiilor de inserare. Pentru aceasta. Dacă A este vid. dacă un nod conţine o informaţie egală cu x. false).

n. Dacă A nu contine nici un nod ce conţine x. ne aflăm în unul din următoarele cazuri: dacă nodul curent este nod frunză. if (poz=="s") p.getNodStang(). Dacă nu suntem în condiţiile bazei. } else return stergeMinim(n. Dacă x<y. dacă nodul curent este un nod interior. Nod p. else return cauta(element.setNodDrept(null).getNodDrept().setNodDrept(n). else if(n.getInformatie()) return sterge(element. else //aici ambele noduri fii nu sunt null 72 . Altfel. fie y informaţia nodului curent. atunci primul este înlocuit cu al doilea nod.getInformatie()) return sterge(element. if (p. Altfel. Metoda următoare implementează în Java acest algoritm: private boolean cauta(int element. îl căutăm în subarborele drept. n. după ce informaţia conţinută de el este memorată în nodul curent. else if(element<n.getNodDrept()==null) inaltime--. atunci se caută nodul y ce conţine cea mai mică informaţie din subarborele drept al nodului curent.getInformatie()==element) return true. Nod n){ if (n==null) return false. 2. else if(element>n. } else if(n. n.setNodStang(n).getNodDrept(). trebuie să ştim ce tip de fiu era pentru nodul părinte: stâng sau drept. String poz){ if(n!=null){ if(element<n. De aceea."d"). dacă nodul curent are un singur nod fiu. } iar metoda următoare implementează întregul algoritm descris mai sus: private boolean sterge(int element. Apoi nodul y se şterge din arbore. Nod n. - Metoda ce determină nodul cu informaţia cea mai mică.getNodDrept()==null) { if (poz=="s") p. else if (n.getNodStang().setNodStang(null). informaţia mai mare decât x.getInformatie()) return n. else p. } cauta(element. n.getNodStang()==null){ min=n. Stergerea unui element într-un arbore binar de căutare Următorul algoritm descrie paşii necesari ştergerii unui element x în arborele A: 1.n. else //nodul este un nod frunza if(n. atunci căutăm x numai în subarborele stâng al nodului curent. else p.getNodStang()==null && n.getNodStang()==null) n=n.getNodDrept()). "s"). Nod p. return min. if(n.getInformatie().Pas recursiv. n=n.getNodStang()==null && p. atunci algoritmul se termină cu valoarea false. dar mai mare decât x este: int stergeMinim(Nod n.getNodDrept()==null) n=n. String poz){ int min. atunci acesta se şterge şi referinţa nodului părinte la nodul respectiv este setată la null.getNodStang().getNodStang()).getNodDrept(). n. "s").

preordine(n.out. } private void preordine(Nod n){ if (n==null) return. "d")).equals("inordine")) inordine(rad).setInformatie(stergeMinim(n.getNodDrept(). } public void stergeArbore(){ rad=null. System.getInformatie()).n. dr).getNodStang()).setInformatie(info). else afiseaza(rad. st. } } Celelalte operaţii nu necesită explicaţii. iar metodele asociate furnizează interfaţa clasei Arbore: public class Arbore{ private Nod rad. private int inaltime. Nod st.getNodDrept()). inordine sau postordine. inaltime=1.getNodDrept()). inordine(n. } private void inordine(Nod n){ if (n==null) return.println(n.equals("postordine")) postordine(rad). else if (forma. Nod dr){ rad=new Nod(inf.getInformatie()). System. inordine(n. System. } return false. } private void postordine(Nod n){ if (n==null) return. postordine(n.getNodStang()). public void afiseaza(String forma){ if (forma. public Arbore(){} public Arbore(int inf.println(n. return true.println(n.getNodStang()). else if (forma. 73 .equals("preordine")) preordine(rad). postordine(n. } public boolean esteVid(){ return rad==null. 0).out.getNodDrept()).out.n. } public void modificaInformatie(int info){ rad. } public Nod getRadacina(){ return rad. preordine(n.getInformatie()). } Afişarea informaţiilor unui arbore binar de căutare Următoarele metode recursive arată diferite modalităţi de a afişa informaţiile unui arbore binar de căutare prin parcurgerea acestuia din urmă în preordine.

Exemple de mapări sunt: . } public boolean cauta(int element){ return cauta(element. 74 . chiar dacă colecţia a fost definită având o semnificaţie mai generală. 0). null. } public void insereaza(int element){ insereaza(element. În schimb. mulţimi.} public int getInaltime(){ return inaltime. } public void afiseaza(String forma){ if (forma.. clasele din Collections Framework încapsulează atât structura de date cât şi algoritmii asociaţi acestor abstractizări.mulţimea literelor mari de la 'A' la 'Z' ..mulţimea cuvintelor cheie din Java: {'import'. arbori. liste..mulţimea angajaţilor unei întreprinderi . null.} . 2 . rad).. else if (forma. etc. . de grup de elemente. 'protected'. Exemple de mulţimi sunt numeroase.1. rad. Iată unele: . null). în Collections Framework o mulţime este o colecţie de elemente unice. } } COLECŢII ÎN JAVA Java furnizează o structură de clase şi interfeţe numită Collections Framework specializată în memorarea şi elaborarea colecţiilor de obiecte. mapping). adică o colecţie fără elemente duplicat.equals("postordine")) postordine(rad).equals("preordine")) preordine(rad).} .mulţimea obiectelor Component dintr-un Container .conversia unui sistem de numeraţie la un alt sistem de numeraţie (sistemul arabic la cel roman). . false). Este o mulţime de legături în care fiecare legătură reprezintă o conexiune de la un element la un altul. fără nici o legătură între ele. else afiseaza(rad. Datorită orientării spre obiecte. 'class'. Collections Framework furnizează un API convenabil oricăror tipuri de date abstracte utilizate frecvent în informatocă: relaţii.maparea adreselor IP la nume dintr-un domeniu de nume DNS.mulţimea vidă {} Un caz particular de mulţime este relaţia funcţională sau maparea (în engleză. 'public'. array.mulţimea numerelor nenegative: {0. 1. 10.5 Teoria de bază a colecţiilor La baza teoriei colecţiilor stă conceptul matematic de mulţime.dicţionar (maparea cuvintelor la înţelesurile lor). else if (forma.equals("inordine")) inordine(rad). rad. } public boolean sterge(int element){ return sterge(element.

1. Figura 10-1.6 Collections Framework Collections Framework este furnizat în pachetul java.util.O mapare (Figura 10-1) poate servi la navigarea de la un element al unei legături la un alt element. Pentru mapare. Aceste Collection Map Set List SortedMap SortedSet clase reprezintă colecţii de obiecte sau relaţii între obiecte şi sunt prezentate în Tabelul 10-2. biblioteca Java conţine clase ce furnizează rapid obiectele Cheie1 Cheie2 Cheie3 Cheie4 Cheie5 legatura1 legatura2 legatura3 legatura4 legatura5 Valoare1 Valoare2 Valoare3 Valoare4 Valoare5 căutate indicând numai cheia asociată. Unele interfeţe sunt implementate de clase Java ce aparţin aceluiaşi pachet java. Interfeţe de colecţii şi implementările lor 75 . Figura 10-2. Interfete ale Collections Framework Interfaţa Set SortedSet List Map SortedMap HashMap TreeMap ArrayList HashSet TreeSet LinkedList Vector Stack Hashtable Properties Implementare Precedenţi istorici Tabelul 10-2.util şi conţine interfeţe care se găsesc în relaţii de generalizare/specializare ca cea prezentată în Figura 10-2. Maparea între chei şi valori 10.

1.1 Interfeţe fundamentale Clase concrete utile HashSet TreeSet <interface> Map Vector ArrayList <abstract> AbstractSequentialList HashMap Stack LinkedList Figura 10-3. Collections Framework mai conţine şi alte interfeţe cum ar fi Iterator. clasele abstracte şi clasele concrete din Collections Framework şi relaţiile dintre ele.Schema completă a lui Collections Framework este prezentată în Figura 10-3. <interface> Iterator produce <interface> Collection produce <interface> Map <abstract> Dictionary <interface> ListIterator <interface> List <interface> Set <abstract> AbstractMap <interface> SortedMap Hashtable <interface> Comparator <abstract> AbstractCollection HashMap TreeMap Properties <interface> Comparable <abstract> AbstractList <abstract> AbstractSet <interface> SortedSet Legenda Hashtable Clase din versiunile 1. numite elementele colecţiei.Collection este o interfaţă standard ce reprezintă un grup de elemente. Stack. ListIterator. În plus. Această interfaţă este utilizată ca numitor comun al altor interfeţe. Comparator şi Comparable care permit navigarea colecţiilor şi compararea elementelor dintr-o colecţie. pentru a permite transferul colecţiilor de la un tip de colecţie la un alt tip şi elaborarea lui cu generalitate maximă. Schema prezintă în diferite nuanţe de gri interfeţele. Collections Framework Interfaţa Collection java. Operaţiile interfeţei Collection sunt prezentate în tabelul următor.0. 76 .util. sunt marcate clasele care provin din versiuni mai vechi cum ar fi Vector. Hashtable şi Properties. Biblioteca Java nu conţine o implementare directă a interfeţei Collection.

să filtrăm o colecţie. În caz negativ. boolean remove(Object o) boolean contains(Object o) Iterator iterator() int size() boolean isEmpty() Operaţii pe grupuri de obiecte boolean addAll(Collection c) boolean removeAll(Collection c) boolean retainAll(Collection c) void clear() Operaţii cu array Object[] toArray() Object[] toArray( Object []) Iterfaţa Iterator Iterator este o interfaţă implementată de un obiect obţinut prin invocarea metodei iterator() a unui obiect din clasa Collection. este eliminat şi meoda returnează true.Declaraţie metodă Operaţii de bază boolean add(Object o) Semnificaţie Verifică dacă colecţia conţine elementul o. de exemplu.remove(). } } Interfaţa Set Collections Framework include o interfaţă Set şi numeroase clase concrete care implementează Set. Returnează true dacă colecţia conţine elementul o Întoarce un obiect de tip Iterator care se poate utiliza pentru navigarea colecţiei. Elimină toate elementele colecţiei c. Returnează un array ce conţine toate elementele colecţiei.. Interfaţa conţine trei metode: boolean hasNext()//verifică dacă colecţia mai mai are elemente de parcurs Object next() //returnează următorul element al colecţiei void remove() //poate fi apelată numai o singură pentru fiecare obiect //obţinut cu metoda next() Iteratorul ne permite să navigăm într-o colecţie pănă la terminarea elementelor conţinute. În timpul navigării putem.. adaugă elementul al colecţie şi returnează true.next(). filtrul va fi implementat astfel: Collection colectie = . nu mai adaugă elementul o şi întoarce false. Presupunem că avem o metodă verificaEliminare(Object o) care întoarce true dacă obiectul transmis ca parametru va fi efectiv eliminat. Array-ul returnat este de acelşi tip cu array-ul transmis ca parametru. metoda returnează false. if (verificaEliminare(element)) { iterator. Adaugă toate elementele colecţiei c. Dacă operaţia are loc cu succes. În caz pozitiv. Întoarce numărul de elemente ale colecţiei Returnează true dacă colecţia nu are elemente. while (iterator. Goleşte colecţia Returnează un array ce conţine toate elementele colecţiei. Interfaţa Set extinde interfaţa Collection şi împiedică crearea de elemente duplicat în colecţie..iterator(). metoda întoarce true. Dacă elementul o se găseşte in colecţie. Elimină toate elementele care nu fac parte din colecţia transmisă ca argument. Iterator iterator = colectie. Dacă operaţia are loc cu succes. Nu introduce alte metode diferite de cele din Collection. Verificarea claselor de implementare se 77 . metoda întoarce true.hasNext()) { Object element = iterator. Altfel. adică să eliminăm din colecţie acele elemente care nu îndeplinesc o anumită condiţie. Folosind interfaţa Iterator.

numărul de cuvinte distincte. Vom scrie un program care preia cuvinte din linia de comandă şi vizualizează cuvintele duplicat. Elementul identificat poate conţine null.*. Majoritatea claselor standard redefinesc implementarea predefinită de clasa Object. f i Figura 10-4. Dacă nu este găsit în listă.util. Obiectele care se adaugă la un TreeSet trebuie să fie ordonabile. Clasa TreeSet este utilizată când vrem să lucrăm cu elementele unei colecţii ordonate. Figura 10-4 prezintă schematic ideea care stă la baza unei structuri de de date de tip hash table.util. Interfaţa Set este implementată de două clase concrete Java: java. având într-o listă cuvintele unice: import java. şi atunci obiectul căutat nu se găseşte în colecţie şi. dar această ordine rămâne întotdeauna aceeaşi. Într-o tabelă hash nu se poate prevede care va fi ordinea de navigare între elemente.bazează pe metoda equals() a obiectului care este adăugat la colecţie.HashSet şi java. Odată găsit codul. Indexul tabelului variază între 0 şi un k-1. se poate adăuga. int incr)//creaza o colectie HashSet de capacitate //initiala şi factor de încărcare transmise ca argumente Exemplu. Obiectele ce vor fi adăugate la un HashSet trebuie să implementeze metoda hashCode() astfel încât obiectele vor fi egal distribuite în mod uniform cu ajutorul codurilor hash. el va fi folosit ca indice al array-ului central. înseamnă că nu se găseşte în colecţie şi poate fi adăugat la lista de bucket. Obiectele din clasa HashSet sunt utilizate pentru memorarea colecţiilor fără duplicate. adică să poată fi comparate între ele după o relaţie de ordine totală. sau este vorba de un indicator la o listă “bucket” în care obiectul va fi căutat secvenţial. adcă este necesar.TreeSet. Clasa HashSet Clasa implementează interfaţa Set şi este construită intern de un “hash table”. public class Duplicate { 78 . Structura unui hash table Constructorii clasei HashSet sunt: HashSet() //creaza o colectie HashSet vida HashSet (Collection c) //creaza o colectie de tip HashSet ce contine //elementele lui c HashSet(int capacitate)//creaza o colectie HashSet de capacitate initiala //transmisa ca argument HashSet(int capacitate. Acest cod este un număr întreg calculat după un algoritm particular care implică toate câmpurile obiectului văzute ca nişte combinaţii de biţi. Clasa permite utilizarea unui element null în colecţie. În centrul structurii se găseşte un array ale cărui elemente conţin indicatori la lista înlănţuită ale cărei noduri indică elemente ale colecţiei. Căutarea într-o astfel de structură începe cu calculul indicelui hash al obiectului care este căutat.util.

length.add(args[i])) System.add("Maria"). Set dupl = new HashSet(). public class ExempluSet { public static void main(String args[]) { Set set = new HashSet().out. i++) if (!unice.size()+" cuvinte distincte identificate: "+s). Într-un obiect memorăm cuvintele liniei de comandă şi în al doilea obiect memorăm numai cuvintele duplicat.println(sortedSet).out.println(s.out.*. dar le afişăm numai o singură dată. } } Clasa TreeSet Clasa implementează SortedSet care este o subinterfaţă a lui Set şi garantează că mulţimea este ordonată în ordine crescătoare.length.out. set. import java.out.add("Andreea"). for (int i=0. Constructorii clasei TreeSet sunt: TreeSet() TreeSet (Collection c) TreeSet(Comparator comp) TreeSet(SortedSet ss) Al doilea constructor va fi utilizat în următorul program în care transmit elementele unei colecţii HashSet unui TreeSet: import java. set. Set sortedSet = new TreeSet(set). System. unice. // Diferenta dintre multimi System. } } Un alt exemplu de utilizare a clasei TreeSet este prezentat în continuare şi ilustrează utilizarea elementelor ce pot fi comparate (Comparable) şi pot fi păstrate ordonate în 79 . i<args. System. set. public class Duplicate1 { public static void main(String args[]) { Set unice = new HashSet().add("George"). i<args. set.removeAll(dupl). set.add("Clara"). i++) if (!s.add("Maria").println("Duplicat: "+args[i]).add(args[i])) dupl.*.println("Cuvinte unice: " + unice). for (int i=0.add(args[i]).println("Cuvinte duplicat: " + dupl).out.util. Putem utiliza două obiecte din clasa Set. Ordonarea este cea naturală între elemente (care trebuie să implementeze Comparable) sau va fi specificată prin intermediul unui obiect comparator (face parte dintr-o interfaţă Comparator) la crearea lui TreeSet. System. System. Cuvintele care apar numai o singură dată se deduc din diferenţa celor două mulţimi.util.println(set).public static void main(String args[]) { Set s = new HashSet(). Presupunem că vrem să ştim care din cuvintele din linia de comandă au apărut o singură dată şi care au apărut de mai multe ori. } } Exemplu.

Articol articolB = (Articol)b. parti.interiorul unui TreeSet. 4562)). } public boolean equals(Object alt){ if (alt instanceof Articol){ Articol altArticol = (Articol)alt. class ComparatorArticole implements Comparator { public int compare(Object a. } else return false.numarParte.println(parti). } public int compareTo(Object alt){ Articol altArticol = (Articol)alt. return numarParte .compareTo(descrB). } } public class TestTreeSet { public static void main(String[] args) { SortedSet parti = new TreeSet().add(new Articol("Monitor". return descrA. Object b){ Articol articolA = (Articol)a. Fiind şi un Set. parti. return descriere.int unNumarParte){ descriere = oDescriere. parti.out.addAll(parti).add(new Articol("Imprimanta".hashCode() + 17 * numarParte.descriere) && numarParte == altArticol.util. SortedSet ordoneazaDupaDescriere = new TreeSet(new ComparatorArticole()). } public int hashCode() { return 13 * descriere. ordoneazaDupaDescriere. numarParte = unNumarParte.getDescriere().println(ordoneazaDupaDescriere).*. 1234)).out. } } 80 .getDescriere(). public Articol(String oDescriere. private int numarParte. System. } public String getDescriere(){ return descriere.numarParte. System.equals(altArticol. un TreeSet poate fi configurat la creare pentru accesarea obiectelor care respectă o anumită relaţie între ele: import java.altArticol.add(new Articol("Modem". 9912)). numarParte=" + numarParte + "]". } public String toString(){ return "[descriere=" + descriere + ". } } class Articol implements Comparable{ private String descriere. String descrA=articolA. String descrB=articolB.

rnd.size(). i-1.get(i).set(i.equals(e2)) şi acceptă şi elemente null. } O variabilă de tip List poate conţine referinţe la obiecte ArrayList sau LinkedList care sunt implementări ale interfeţei. a. În acest mod căutăm mai uşor în lista. elemente e1 şi e2 care verifică e1. i>1. Object get(int indice) boolean add(int indice. Returnează poziţia ultimei apariţii a obiectului o din listă. Interfaţa ListIterator 81 . Crează o sublistă formată din elementele listei între cei doi indici transmişi ca parametri.Interfaţa List List este o interfaţă care reprezintă o colecţie ordonată (numită şi secvenţă).get(j)). Object o) Object remove(int indice) void set(int indice.set(j. Random rnd) { for (int i=list. Collection c) Căutarea unui obiect int indexOf(Object o) int lastIndexOf(Object o) Iterare ListIterator listIterator() ListIterator listIterator(int indice) Operaţie globală List subList(int in. Algoritmul polimorfic utilizat parcurge lista şi generează numere aleatoare pentru a identifica locuri noi din care putem lua elementul cu care înlocuim elementul curent: public void permuta(List list.nextInt(i)). Dacă nu-l găseşte. int j) { Object t = a. a. putem implementa în mod polimorfic algoritmi valizi pentru toate obiectele claselor care implementează interfaţa. Prin intermediul acestei interfeţe. returnează -1. List are următoarele metode: Declaraţie metodă Acces după poziţie Semnificaţie Întoarce obiectul de la indicele transmis ca parametru Inserează obiectul o la poziţia indice Elimină obiectul de la poziţia indice Înlocuieşte obiectul de la poziţia indice cu obiectul o Inserează începând cu poziţia indice elementele colectiei c Returnează poziţia obiectului o din listă. În afara declaraţiilor de metode din interfaţa Collection. Listele acceptă elemente duplicat (adică. t). Cei doi iteratori sunt folosiţi de LinkedList. Object o) boolean addAll(int indice. i--) schimba(list. Returnează un obiect de tip ListIterator al lui List Returnează un obiect de tip ListIterator al lui List. pentru a schimba locul între două elemente ale unei liste poate fi utilizată următoarea metodă: private void schimba(List a. Dacă nu-l găseşte. returnează -1. int sf) Ca întotdeauna când este vorba de o interfaţă. int i. a. } Vom utiliza metoda schimba() pentru a permuta elementele unei liste. Aceşti algoritmi sunt independenţi de clasa utilizată pentru implementarea listei. utilizatorul are un control exact al locului în care este inserat fiecare element. De exemplu. Utilizatorul poate accesa elementele prin intermediul iteratorilor şi a indicilor întregi care reprezintă poziţia în listă.

listIterator(). să o modificăm în timpul traversării şi să obţinem poziţia curentă a iteratorului. i. un alt fapt: la primul apel al lui previous() după o secevnţă de apeluri next() întoarce acelaşi element al ultimului apel al lui next. Apoi. // returnează indicele elementului succesiv } Spre deosebire de metoda Collection. în schimb previousIndex() returnează poziţia elementului întors la un apel al lui previous(). În mod similar. Modelează o listă cu elemente enumerate. direct. // returnează indicele elementului succesiv int previousIndex(). metoda ListIterator.listIterator(). //poziţionează cursorul şi returnează elementul //precendent boolean hasPrevious(). } In schimb.hasNext().iterator().next())) { i. metoda următoare implementează un algoritm polimorfic care returnează toate apariţiile valorii val specificată ca parametru. cu o secvenţă de valori noi conţinute într-o listă: public static void replace(List l.remove(). nextIndex() == previous()+1.hasNext(). Exemplu următor este cel al unei metode statice care implementează un algoritm polimorfic care înlocuieşte într-o listă oarecare toate apariţiile unui obiect val cu un obiect nou: public static void replace(List l.next())) i.add. Object val.set(nou). primul apel al lui next() după o serie de apeluri ale lui previous() returnează acelaşi element al utlimului apel al lui previous() .next()).next()==null : val. care ne permite să traversăm lista în ambele direcţii. ) { if (val==null ? i. j.equals(i.Interfaţa List furnizează un iterator mai bogat: ListIterator.next()==null : val.add(j. List valoriNoi) { for (ListIterator i = l. // suprascrie elementul curent cu elementul transmis // ca parametru int nextIndex(). La metodele interfeţei List. Metoda nextIndex() returnează întotdeauna elementul care va fi restituit de un apel succesiv al lui next(). clasa ArrayList adaugă următoarele metode: ArrayList(Collection)//construieşte un ArrayList dintr-un Collection Object clone() //clonează obiectul ArrayList void ensureCapacity(int) //garantează un număr minim pentru listă void trimToSize() //Elimină spaţiile libere din array 82 . ) if (val==null ? i. for (Iterator j = nuoviValori. Object nou) { for (ListIterator i = l.equals(i. deoarece are un acces obişnuit. // verifica dacă există un element precedent void set(Object elem). i. În consecinţă. // adaugă un element în poziţia curentă Object previous(). } } } Clasa ArrayList ) ArrayList este o clasă concretă care implementează interfaţa List şi se sprijină pe un array fără limite de creştere. Object val.hasNext(). i.add nu returnează o valoarea de tip boolean. relativ rapid. Interfaţa ListIterator este prezentată în continuare: interface ListIterator extends Iterator { void add(Object elem).

println(coada). coada.removeLast(). coada.size(). List listaNoua = pachet. George] 83 . Cu un obiect LinkedList putem implementa cod deoarece garantează o politică FIFO în elaborarea listei. lista.add("Clara"). lista. List cartiJucator = new ArrayList(listaNoua).addFirst("Andreea").n cărţi pentru un jucător şi le furnizează întotdeauna ca o listă: public static List furnizeazăCarte(List pachet. } Clasa LinkedList LinkedList este o clasă concretă care furnizează un acces secvenţial optim cu operaţii economice de eliminare şi inserare în interiorul listei.println("2: " + lista. listaNoua.out.addFirst("George").add("George").addFirst("Clara"). prezentăm un program care extrage virtual dintr-un pachet de cărţi – reprezentat ca o listă . } } Rezultat: [Andreea.println(coada). Are un acces aleator relativ lent (dacă accesul aleator este frecvent trebuie să fie utilizat ArrayList).subList(dimPachet-n.get(0)).println("0: " + lista. dimPachet). George.out. George. Clara] 2: George 0: Andreea [Clara.out. lista. public class ExempluLista { public static void main(String[] args) { List lista = new ArrayList(). int n) { int dimPachet = pachet. coada. LinkedList aadaugă următoarele metode la cele declarate de interfaţa List : void addFirst( Object o) //adaugă o la începutul listei void addLast(Object o) //adaugă o la sfârşitul listei Object getFirst( ) //furnizează primul element din listă Object getLast( ) //furnizează ultimul element al listei Object removeFirst( ) //elimină primul element al listei Object removeLast( ) //elimină ultimul element al listei Următorul program ilustrează ilustrează trasferul uşor de la o implementare a unei liste al o alta şi modul diferit în care cele două tipologii de liste îşi gestionează elementele: import java. Eliza. System. System. System. return cartiJucator.addFirst("Eliza"). coada.addFirst("Eliza"). coada.get(2)).println(lista).removeLast().add("Andreea"). Eliza.add("Eliza").util. System. lista. coada.add("Eliza").clear().*. coada. Andreea] [Clara. System.out. lista. LinkedList coada = new LinkedList(). Eliza.În continuare.out. Eliza. Eliza.

Este de ajuns să utilizeze o variabilă interfaţă în care să memoreze referinţa la unul din cele două obiecte (Figura 10-5). În consecinţă. pentru un client.Cum utilizăm interfaţa Collection 1. Utilizarea variabilelor interfaţă Interfaţa Map Map este o interfaţă care păstrează o asociere chei-valoare şi care permite căutări bazate pe chei. 3.o altă implementare a lui Collection b Client a Înlocuirea unei implementări a lui Collection cu o alta Figura 10-5. Declaraţie metodă Operaţii de bază Semnificaţie Întoarce obiectul cu cheia transmisă ca parametru Inserează o legătură cheie-valoare Elimină legătura indicată de cheie Verifică existenţa cheii cheie în Map Object get(Object cheie) void put(Object cheie. construită pe baza lui colecţie: List lista = new ArrayList(colectie). În continuare. Implementările colecţiilor (ArrayList. Object o) Object remove(Object cheie) Boolean containsKey(Object cheie) 84 . Acest parametru este un obiect dintr-o clasă care implementează interfaţa Collection şi care va fi utilizat pentru a iniţializa noua colecţie. elementele unice ale lui HashSet pot fi căutate în ordine şi poate accepta duplicate. noua colecţie va fi iniţializată cu elementele colecţiei utilizată ca parametru. 4. HashSet sau TreeSet: colectie = new HashSet(). fără să necesite nici o modificare din parte clientului. În acest mod. lista conţine elementele din colec•ie memorate în HashSet. colectie. . ArrayList. dacă două obiecte a şi b implementează aceiaşi interfaţă.add(o1). Variabilă de tip Collection a – implementare a lui Collection b. HashSet. dar va avea un comportament diferit. Ştim că utilizarea interfeţelor este obligatorie atunci când obiectele client nu trebuie să ştie provenienţa obiectului (clasa care l-a generat) şi în general orice detalii de implementare care su fost utilizate. . va fi prezentat un scenariu posibil de utilizare a varaibilelor de tip Collection: 1. 2. colectie memorează o referinţă la un obiect care implementează o colecţie.add(o2). LinkedList. se poate utiliza obiectul b în locul obiectului a. precum un LinkedList. Într-un List. 3. În acest mod. Se crează o lista de tip List ce se bazează pe un array. Se adaugă obiecte la colectie cu metoda add(): colectie. TreeSet) au toate un constructor cu un parametru de tip Collection. Declarăm o variabilă colectie de tip Collection (poate fi un List sau un Set): Collection colectie. schimbând numai punctul de vedere. . nu contează ce obiect Java este utilizat pentru a reprezenta o colecţie şi dacă în mod succesiv. acest obiect este înlocuit cu un altul care implementează aceeaşi interfaţă. 2.

De aceea.Entry.next().iterator().util.hasNext(). Clasa HashMap Următorul exemplu verifică numerele aleatoare furnizate de metoda Math. ) { Map. System.Entry este o interfaţă statică internă a lui Map care reprezintă toate legăturile cheievaloare din Map.toString(i).random()*20)).*. putem parcurge o astfel de mulţime şi să afişăm fie cheia. i < 10000.keySet(). //Produce un număr între //0 şi 19 inclusiv 85 . Acest lucru este realizat de următoarea secvenţă de cod: Map m=…//crearea unui obiect al unei clase ce implementează interfaţa Map for (Iterator i=m.println(e.Entry) i. i.getKey() + ": " + e.println(cheie + ": " + map. i.entrySet(). } Map.iterator(). Map. i++) { Integer r = new Integer((int)(Math.hasNext().random(). ) { Object cheie = i. class Counter { //Obiectele acestei clase vor fi folosite ca numărători int i = 1. System. } } public class FreqHashMap { public static void main(String[] args) { HashMap ht = new HashMap(). import java.getValue()).Entry are următoarele trei metode: Object getKey() Object getValue() Object setValue(Object val) Fiecare element din Set-ul de legături returnat de metoda entrySet()este văzut ca un element de tip Map.out.Entry e = (Map.out.get(cheie)). fie valoarea fiecărei legături.Declaraţie metodă Semnificaţie Verifică existenţa valorii o în Map Returnează numărul de legături Verifică dacă mulţimea legăturilor este vidă sau nu Adaugă legăturile găsite în m Goleşte un Map Furnizează Set-ul tuturor legăturilor cheie-valoare Furnizeaza un Set compus din chei Furnizează o colecţie a tuturor valorilor din Map Boolean containsValue(Object o) Int size() Boolean isEmpty() Operaţii globale Boolean putAll(Map m) Void clear() Vederi ca colecţii Set entrySet() Set keySet() Collection values() Vederile (views) ale unui Map ne permit să utilizăm interfetele Collection (pentru valori) sau Set (pentru chei) pentru eleborarea întregului Map: for (Iterator i=map. public String toString() { return Integer. } Interfaţa Map are două implementări principale: HashMap şi TreeMap şi una moştenită din prima versiune de Java: Hashtable. for(int i = 0.next().

i++) { String cheie=args[i]. String header) list(PrintStream out) list(PrintWriter out) load(InputStream in) De exemplu. valorile se numesc proprietăţi. Integer unu=new Integer(1). Următorul program ilustrează diferenţele dintre HashMap şi TreeMap: import java.println(map.containsKey(r)) ((Counter)ht. O legătură cheie-proprietate este adăugată la un Properties cu metoda Object setProperty(String key.length. memorarea într-un fişier a conţinutului unui obiect Properties se realizează prin următoarea secvenţă de cod: 86 . } } Clasa TreeMap Clasa TreeMap furnizează o implementare a interfeţei Map în care colecţia de legături chei-valoare este ordonată după chei. } map. if (frecventa==null) frecventa = unu. String proprietateImplicita) Persistenţa colecţiei permite memorarea şi încărcarea pe şi de pe suport persistent (sistem de fişiere). else ht.out. new Counter()).*. for (int i=0.put(cheie. Din acest motiv. System.get(r)).out. Map mapSortat = new TreeMap(map). n=args. } } Clasa Properties Furnizează o colecţie persistentă de legături chei-valori in care cheile şi valorile sunt String-uri. String value) şi se poate obţine cu metoda overloaded getProperty(): String getProperty(String cheie) String getProperty(String cheie.println(mapSortat). ordonarea este crescătoare (conform interfeţei Comparable).if(ht.util.put(r. else { int valoare = frecventa.out. public class FreqTreeMap { public static void main(String args[]) { Map map=new HashMap().i++. implementând şi interfaţa SortedMap.out. i<n. Integer frecventa=(Integer)map. System. Implicit. dar criteriul de comparare poate fi specificat prin constructor: TreeMap (Comparator c) Alţi constructori: TreeMap () TreeMap (Map m) TreeMap (SortedMap m) Exemplu.println(map). } System.size()+" cuvinte distincte gasite:").intValue(). frecventa).println(ht).get(cheie). clasa Properties furnizează următoarele metode instanţă: public public public public void void void void store(OutputStream out. } System. frecventa = new Integer(valoare + 1). În acest sens.

87 .add(new SpecificatieProdus("Calculator". System.hasNext()) osp. import java. public class Catalog extends TreeSet{ private static Catalog c. private Catalog(){osp=new OperatiiSpecificatiiProdus().*.} Ieşire: # Colectie de proprietati #Tue Jan 04 10:03:53 EET 2005 4=Maria 1=Ioana Colecţia de legături şi proprietăţi memorată într-un obiect Properties poate fi afişată şi pe ecran prin apelarea metodei list.util. } sp=(SpecificatieProdus)osp. try{ p.getMessage()). c.} public SpecificatieProdus getProdus(String nume){ Iterator it=iterator().println(sp).add(sp). SpecificatieProdus sp=null. 1300)). "Ioana"). Exemplu.getInstanta().util.hasNext()){ sp=(SpecificatieProdus)it. } } import java.scrieObiect(it.add(new SpecificatieProdus("Imprimanta".out.out). } public void descarca(){ Iterator it=iterator(). if(sp. unde p este variabila referinţă din exemplul anterior. private OperatiiSpecificatiiProdus osp.txt").println(sp). "Maria"). }catch(IOException e){System. System. astfel: p.next().setProperty("1".equals(nume)) return sp. p. SpecificatieProdus sp=c.out. c.Properties p=new Properties().getDenumire(). while(it. " Colectie de proprietati"). public static Catalog getInstanta(){ if(c==null) c=new Catalog().list(System..out. } public void add(SpecificatieProdus sp){super.println(e. sp=c. return c. return sp.citesteObiect(nume).setProperty("4".next()). if (sp!=null) add(sp).*. 250)). p.store(new FileOutputStream("proprietati. while(it.getProdus("miere").getProdus("Imprimanta"). } } } public class TestCatalog{ public static void main(String[] args){ Catalog c=Catalog.

} public ArrayList getProduse(){return this. for (int i=latime-sir. return total+calculeazaTVA().getTime())+"\r\n" sir+="-----------------------------------------------------------------------\r\n\r\n".length().} public Client getClient(){return c.LONG). ElementVanzare ev. c=v. Client c.getPrenume()+"\r\n".0.getProduse().calculeazaTotal(). ArrayList articole.DAY_OF_WEEK)<=6)total=5*total/100.public class Vanzare extends ArrayList{ private Client c. articole=v.} public double calculeazaTotal(){ ListIterator li=listIterator().text. } } import java.getInstance(). sir+=formatare("Denumire". Vanzare v. 20)+formatare("Pret/articol".calculeazaCost().getDateInstance(DateFormat.iterator(). } public String formatare(String sir.util. while(li. } public double calculeazaTVA(){return total*tva/100. int nrFactura.getNume()+" "+c.*. Iterator it=articole. while(it. private double total.v=v.} public void addProdus(ElementVanzare ev){super.next(). Calendar data.0.get(Calendar.DAY_OF_WEEK)>=2&&cl. public static int tva=20. return temp. public Vanzare(Client c){this. sir+="Data emiterii: "+ DateFormat.format(data.import java. ElementVanzare el. 15)+ formatare("Pret unitar".getInstance(). } Calendar cl=Calendar. int latime) { String temp=sir. } public String toString(){ String sir="Factura: "+nrFactura+"\r\n".hasNext()) { ev=(ElementVanzare)li.*. 88 .add(ev).hasNext()){ public Factura(Vanzare v){ nrFactura=id++. sir+="Cumparator: "+c. 15)+formatare("Cantitate". public class Factura{ private private private private private private static int id=1.getAdresa()+"\r\n". --i) temp += " ". total+=ev.getClient().c=c. sir+="Adresa: "+c. if(cl.get(Calendar. data=Calendar. 25)+"\r\n". sir+="-----------------------------------------------------------------------\r\n\r\n". i>0. double t=v. this.

sir+=formatare(""+el.calculeazaTVA()+" lei \r\n". 123). "Pop". }} 89 .getProdus(). return sir.println(f). 6)). sir+="TOTAL\t\t"+t+" lei \r\n".el=(ElementVanzare)it. Factura f=new Factura(v). 15)+formatare(""+el. "aleea stejarilor")).getProdus().} sir+="-----------------------------------------------------------------------\r\n\r\n".out. System. 15)+formatare(""+el. 25)+"\r\n".getPret().getDenumire(). 20)+formatare(""+el.getCantitate().calculeazaCost().next(). sir+="Din care TVA 20%\t"+v.addProdus(new ElementVanzare(new SpecificatieProdus("Calculator". v. } public class TestVanzare{ public static void main(String[] args){ Vanzare v=new Vanzare(new Client("Ionescu". sir+="\r\n\r\nTOTAL GENERAL\t"+t+" lei \r\n".

Modificatorii sunt atribute. Documentul poate fi scris cu word processor oarecare. HTML = Limbaj de comenzi cu care se scriu paginile Web. Context pentru executarea applet-urilor Java. <H2>text</H2>. Suportă plug-ins. Utilizează protocolul HTTP.11. Pagină Web = Document de text cu extensia .URI (Uniform Resource Identifier) sau URL. Cere resurse de la server-ele din reţea.html sau .. Pagini Web Paginile Web sunt resurse Web care au o adresă URL (Uniform Resource Locator). Un fişier HTML simplu Un tag poate avea modificatori. . Suport pentru orice mecanisme de scripting. .html sau .. <H6>text</H6> Alinearea textului: <CENTER>text</CENTER> sau ca atribut: <H1 ALIGN=CENTER>text</H1> Trecerea pe linia următoare în paragraful curent: <BR> Text afisat asa cum este scris în pagină: <pre>text</pre> Separarea paragrafelor: <P>text</P> sau cu un atribut: <P ALIGN=LEFT> Liste ale căror elementele sunt prefixate de un punct: <UL> <LI> text <LI> text </UL> <OL> <LI> text introduce o lista introduce un element în listă termină lista Liste ale căror elemente sunt numerotate: introduce un element în listă 90 .htm. Utilizează tag-uri (comenzi între < şi >) care au un înţeles bine precizat pentru browser. Identifică resursele utilizând adrese unice .htm al cărui conţinut va fi citit şi interpretat de un browser. de obicei perechi nume=valoare: <BODY BGCOLOR=“yellow”> <HTML> <HEAD> <TITLE>Arhitectura Internet</TITLE> </HEAD> Structura unei pagini Web: Header + Corp <HTML> <HEAD> Header </HEAD> <BODY> Corp </BODY> Structura header-ului: <HEAD> <TITLE>text </TITLE> </HEAD> Structura corpului: <BODY TEXT=” “ LINK=” “ ALINK=” “ VLINK=” “ BACKGROUND=” “> tag-uri +text </BODY> </HTML> <BODY BACKGROUND="" BGCOLOR="#ffffff" VLINK="#800080" ALINK="#ff0000"> <P>Bine ati venit în site-ul nostru!</P> </BODY> </HTML> TEXT="#000000" LINK="#0000ff" Tag-uri de formatare a textelor Titluri de secţiune: <H1>text</H1>. APPLET Browser – program cu urmatoarele functiuni: - vizualizează resursele codificate în HTML. este de ajuns să fie salvat în format text cu extensia .

awt.swing. linii poligonale. cercuri.Applet. 2. Structura unui applet: 91 .class” codebase=”classes" Când întâlneşte tag-ul APPLET.funcţioneaza ca parte integrantă a unui browser. 4. } } În pagina HTML: <applet name=”primul applet" width=”100” height="60”> </applet> code=”PrimulApplet. Clasa Applet este un Container (componentă grafică Java utilizată pentru a include.CLASS] HEIGHT=ÎNĂLŢIMEA ÎN PIXELI [HSPACE=SPAŢIUL ORIZONTAL DINTRE APPLET ŞI TEXTUL CARE-L ÎNCONJOARĂ] WIDTH=LĂRGIMEA ÎN PIXELI [VSPACE=SPAŢIUL VERTICAL ÎNTRE APPLET ŞI TEXTUL CARE-L ÎNCONJOARĂ] [NAME=NUMELE APPLET-ULUI] > [<PARAM NAME=PARAMETRU1 VALUE=VALOARE PARAMETRU1>] [<PARAM NAME=PARAMETRU2 VALUE=VALOARE PARAMETRU2>] </APPLET> Clasa Applet Applet-urile sunt programe Java care se pot descarca din internet. aceasta descarcare este realizata de browser. Incarcă fişierul PrimulApplet.} public void paint(Graphics g){ g.magenta).CLASS” [CODEBASE=URL-UL FIŞIERULUI . putem desena caractere de un anumit font si o anumita culoare.20. paint etc. Instanţiază clasa PrimulApplet. import java. Alocă aria în care se vizualizează applet-ul.<LI> text </OL> termină lista Linie de separare: <HR> Tag-ul APPLET <APPLET [ALT=TEXT] CODE=“NUMEAPPLET. Asadar. precum si alte forme precum dreptunghiuri. Exemplu: import java.drawString(“Buna ziua!”. 3. elipse. un applet are urmatoarele proprietati: . gestiona şi vizualiza alte componente grafice) care utilizează metoda paint pentru vizualizarea desenelor şi componentelor grafice pe o suprafaţă dreptunghiulară.prezinta utilizatorului o interfaţă grafică şi poate capta evenimente declanşate de utilizatori. Orice applet este un obiect al unei clase definită de utilizator care extinde clasa Applet a pachetului java.applet sau clasa JApplet a pachetului javax. public class PrimulApplet extends Applet { public void init(){setBackground(Color. apare intr-o fereastra a broser-ului ca un dreptunghi (panel-panou) in care avem o prezentare grafica cu un fond (background). browser-ul execută următorii paşi: 1. .class din directorul classes al directorului curent.*. Cere executarea metodelor standard implementate în applet: init.applet.30).

Acest obiectul reprezintă contextul grafic al applet-ului. vizualizează întreaga pagină 4. va fi apelată metoda destroy() Desenarea cu paint() . Browser-ul lansează pagina şi cheamă stop() applet-ul se opreşte din rulare 5. în particular într-un applet vizualizat în pagina HTML. un fond de o anumită culoare sau o imagine. Applet-ul a fost încărcat în sistem şi iniţializat Browser-ul cheamă init() start() applet-ul rulează… paint() apoi cheamă 3.. class NumeApplet extends Applet{ void init(){…} void start(){…} void stop(){…} void destroy(){…} void paint(Graphics g){…}//mostenita din supraclasa Container Browser 1.. Pentru a putea utiliza metoda paint() trebuie importată clasa Graphics din pachetul java. 92 .Applet.pentru a vizualiza orice lucru avem nevoie să redefinim metoda paint mostenita de clasa Applet din clasa Container: public void paint(Graphics g){ //cod pentru desenat } . În aceste metode trebuie să descriem cum trasăm în dreptunghiul applet-ului un text. o linie.parametrul g este iniţializat cu un obiect al clasei Graphics care este creat şi transmis lui paint() de către browser... .paint(Graphics g). . repaint() şi update(Graphics g) sunt utilizate pentru desenarea pe un Container.awt.applet. Browser-ul revine în pagina applet-ului sau browser-ul eliberează definitiv pagina conţinută 6.import public public public public public public } java. Accesează pagina care conţine un applet Applet Cere încărcarea applet-ului Applet-ul este încărcat în sistem Pentru a-l iniţializa. browser-ul cheamă 2. .

Cine furnizează obiecte Graphics? Obiectele Graphics sunt întoarse de metodele getGraphics() existente în clasele Component. y) al sistemului curent de coordonate. public class Dreptunghiuri extends Applet{ public void paint(Graphics g) { g. Când acelaşi applet trebuie să fie redesenat (de exemplu când am schimbat culoarea fondului cu setBackground()). . int) drawPolygon(int[]. Metoda dispose() getColor() setColor(Color) getFont() setFont(Font) getFontMetrics() getFontMetrics(Font) translate(int.awt. int. Desenează o linie între două puncte ale sistemului de coordonate al contextului grafic. int. int) drawPolyline(int[]. 35).setColor(new Color(0.Applet. . int[]. Desenează un arc înscris în dreptunghiul specificat.fillRect (10. . int. . int. Întoarce dimensiunile tipului curent de font.coordonatele originii translatării pentru desenat şi pentru operaţia de clipping. int) Semnificaţie Elimină contextul grafic. int) drawImage(Image. de exemplu). g. boolean) drawArc(int. 20. 0. int. 65). int.culoarea curentă. .funcţia logică curentă a operaţiei în pixeli (XOR sau Paint).Metoda paint() va fi apelată automat de către browser când se desenează în applet. Întoarce culoarea curentă. import java. Cele mai importante metode ale clasei Graphics sunt prezentate în tabelul urm. Trasează o elipsă în interiorul dreptunghiului specificat. int. Trasează o secvenţă de linii conexe specificate de array-urile de coordonate x si y. import java.Color. } } Graphics Graphics = Clasă abstractă. 30).applet. Informaţiile de stare necesare pentru desenarea în Java sunt: . int) drawOval(int. int. int) draw3DRect(int. Setează culoarea curentă ca fiind culoarea specificată. 15.Graphics. Color.awt.font-ul curent. 15. int.translate(20. int.obiectul Component pe care se desenează (un applet. Desenează atâta cât din imagine specificată este disponibilă. g. Întoarce dimensiunilr tipului de font specificat. int. 40. Image şi PrintJob. ImgObs) drawLine(int. Desenează un dreptunghi în 3-D. int. se utilizează repaint(). bază pentru toate contextele grafice care aparţin unei aplicaţii de desenat. int[].clip-ul curent. int. Trasează un poligon definit de doua array-uri de puncte x şi y. Setează font-ul contextului curent ca fiind font-ul specificat. Un applet care desenează import java. g.drawRect (10. Pune originea contextului grafic în punctul (x. Întoarce font-ul curent. 255)). Fiecare pereche 93 .

int. int. int) specificate. boolean hasAlpha) Color.green. TimesRoman. int. fillArc(int. Font f) int getSize() int getStyle() boolean isBold() boolean isItalic() boolean isPlain() static final int BOLD=1. Trasează un dreptunghi cu colţurile rotunjite int. Color. int) Desenează şirul specificat cu culoarea contextului grafic curent. int. Color. static final int ITALIC=2. xxx b. Helvetica. xxx b) r. int[]. int. int. int. drawRoundRect(int. static final int PLAIN=0.1: Dialog. Color. int) Umple cu culoarea curentă un poligon definit de două array-uri de coordonate x şi y. int) Setează clip-ul curent dreptunghiul specificat cu coordonatele date ca parametri actuali ai metodei. int. Shape getClip() Întoarce aria de lucru curentă ca un obiect de tip interfata Shape getClipBounds() Intoarce dreptunghiul circumscris ariei de lucru. Color. int.blue. fillRoundRect(int. Color Color este o clasă care reprezintă o culoare. fill3DRect(int. int.4. int stil. y[i]) defineşte un punct.12).Font. Font static Font getFont(String nm)//returneaza un obiect de tip Font cu numele specificat static Font getFont(String nm. xxx g. int dim) Font f=new Font(“SansSerif”. Umple un sector de cerc continut in dreptunghiul int) specificat cu culoarea curenta. Umple dreptunghiul cu colţuri rotunde specificat cu int. drawString(String. Se poate impune unui context grafic un font nou astfel: void Graphics. int. fillPolygon(int[]. int) culoarea curentă.magenta etc Color. int) Umple cu culoarea curentă o elipsă continută în dreptunghiul specificat. setClip(int. int. DialogInput. xxx alpha) rgb) rgb.setFont(Font f) Applet pentru ora exactă 94 . int) Trasează dreptunghiul specificat.BOLD.Metoda Semnificaţie (x[i]. int. Exemple de font-uri din JDK 1. SansSerif. int. int.cyan. xxx g. int. Serif. xxx=int sau float Clasa Color conţine câmpuri constante iniţializate cu culori fundamentale: Color. int. Dimensiunile sunt specificate în puncte tipografice (1/72”): Font (String nume. drawRect(int.yellow. int. fillOval(int. Colorează interiorul dreptunghiului 3D cu culoarea boolean) curentă.white. int. int.red. Monospaced. fillRect(int. int. int) Umple dreptunghiul specificat cu culoarea curentă. Culorile pot fi construite cu constructori ca: Color Color Color Color (xxx (xxx (int (int r. int.

}catch(InterruptedException e) {} oraPrec=ora.drawString(oraPrec.util. 25).sleep(1000). Font tip=new Font (“Monospaced”. 102).getTime().applet. 20).setColor(beige). g2D. g2D. repaint().setColor(Color.util.drawString(ora. GregorianCalendar azi=new GregorianCalendar(). private String oraPrec = “”.applet. Font. culoareFond=Color. </html> import java.setFont(tip). 25).*.Applet{ private Color beige = new Color(255.*. g2D. 5.BOLD. try {Thread. private String oraPrec=“”.awt.BOLD.sleep(1000). 102). }catch(InterruptedException e){ } oraPrec = ora. } public void paint(Graphics g) { Graphics2D g2D = (Graphics2D) g.*.awt.decode(in). 25). String ora=azi. <html> } <applet code="CeasNou" width=350 } height=50> Applet pentru ora exactă cu parametri <param name="fond" value="#996633"> </applet> import java.toString().black).setFont(tip).black). 25).getTime(). Font. } } FontMetrics 95 . String ora=azi.*.drawString(oraPrec.drawString(ora. g2D. 5. 20). public void init() { setBackground(Color. 204. g2D. Font tip=new Font(“Monospaced”.Applet { private Color beige=new Color(255. 204. public class CeasNou extends java. 5. g2D. g2D. if (in != null) { try{ culoareFond=Color. Color culoareFond.toString(). } public void paint(Graphics g) { Graphics2D g2D=(Graphics2D) g. 5.setColor(beige).black). repaint(). try {Thread.black. }catch(NumberFormatException e) {showStatus(“Parametru eronat “ + in). import java. g2D.setColor(culoareFond). public void init() { String in=getParameter(“fond”). g2D. g2D. public class Ceas extends java. GregorianCalendar azi=new GregorianCalendar().import java.} } setBackground(Color.

int len) int bytesWidth(byte data[]. int w3 = fm.right-in.getFontMetrics(Font) FontMetrics Toolkit.int off. cy). Programarea cu obiecte Font Exercitiu.".getFontMetrics() FontMetrics Graphics.stringWidth(s2).left.top.BOLD+Font. private Font fi.getFontMetrics(f).BOLD + Font. cx.ITALIC.getFontMetrics(Font) FontMetrics Graphics.”).height-in. Cum să scriem textul: Acesta este un program pentru testarea font-urilor poziţionat în mijlocul unui frame utilizând două font-uri diferite? Solutia o gasiti în Programul 2.getFontMetrics(fi). Font. g.BOLD. 12). Insets in = getInsets().14). public class TestFont2 extends Frame{ private Font f.FontMetrics Component.int off. fontsSet = true.drawString(s1. FontMetrics fm=g.getFontMetrics(f).clientWidth-1. fm=g. private boolean fontsSet = false.drawRect(in.bottom-in. int cy=clientHeight/2+in.int len) int charWidth(char ch) int charWidth(int ch) int getAscent() getDescent() getLeading() getHeight() getMaxAscent() getMaxDescent() int stringWidth(String s) Cum se determină lungimea unui şir pe ecran? Font f=new Font(“SansSerif”.left. cx += w1. 96 .Font. int w1 = fm.top. public void setFonts(Graphics g){ if (fontsSet) return. private FontMetrics fm. String s2 = " un program pentru". Dimension d = getSize(). clientHeight-1).ITALIC. int w2 = fim. g.top.setFont(f). int clientHeight =d. private FontMetrics fim. String s3 = " testarea font-urilor. fim=g.Font.width-in. String s1 = "Acesta este". int clientWidth=d.in. cx=fm. } public void paint(Graphics g){ setFonts(g). f=new Font("SansSerif". int cx=(clientWidth-w1-w2-w3)/2 + in.stringWidth(s3). g.stringWidth(s1). fi=new Font("SansSerif".left.stringWidth(“Un şir lung de 31 de caractere. 14).getFontMetrics(Font) int charsWidth(char data[].

drawString(s3. } public static void main(String args[]){ Frame f = new TestFont2(). cx += w2. TestFont2: Utilizarea lui Font şi FontMetrics 97 .setFont(f). cy). cx.g. f. cy).setFont(fi). cx. } } Programul 2. g. g. g.drawString(s2.show().

dimensiune .awt.Desenează figuri în 2D . Fiecare componentă are ciclul său de viaţă.Component java. menu-urile şi ferestrele de dialog. Ierarhia de container-e poate avea orice nivel de complexitate. Frame = Fereastra de nivel cel mai înalt într-o aplicaţie. Un mecanism de evenimente care gestionează evenimentele sistemului şi evenimentele utilizatorului.un obiect Graphics . Grafica . Ierarhia claselor AWT Object Component Canvas Container List Button TextComponent CheckBox ScrollBar Label Choice Panel Window TextField TextArea Applet Frame Dialog FileDialog java. Mecanisme pentru aranjare a componentelor într-un mod care permite obţinerea unui GUI independent de platformă.Controlează culorile .un peer nativ . exceptând menu-urile. Gestionează ferestrele. Container-ele sunt gestori ai componentelor conţinute. INTERFETE GRAFICE AWT-Abstract Window Toolkit Serie completă de componente ale interfeţei grafice utilizator (GUI) Suport pntru “container-e” de componente grafice.Controlează font-urile Java 2D API - Posibilitatea de grafică mai laborioasă .Desenează figuri în 2D personalizate .Umple figurile cu culori şi modele Container-e Ideea fundamentală: O fereastră Java este un container care conţine o colecţie de componente încuibate.un container părinte . independent de al altora.localizare .Component = Clasă abstractă care generalizează toate componentele AWT. Applet = Container de componente grafice care poate fi executat de un browser. Unei componente i se asociază următoarele elemente: .12.font şi dimensiunile font-ului (font metrics) 98 .awt.

awt.Component boolean isVisible() <<Interface>> void setVisible(boolean b) ImageObserver boolean isShowing() boolean isEnabled() void setEnabled(boolean b) Font getFont() void setFont(Font f) Font Point getLocation() void setLocation(int x. //creaza un Button add(buton2).// importa toate clasele AWT public class Primul extends Applet { TextField text.applet.//adauga Button-ul la fereastra buton2=new Button("Cancel").awt.//declara doua Button public void init(){ text = new TextField(20). bg Point getLocationOnScreen() Color 2 Graphics getGraphics() void setBackground(Color c) Graphics void setForeground(Color c) 1 Dimension getSize() void setSize(int w. int h) * void setSize(Dimension d) java.Container Component add(Component c) Component add(String name. //adauga Button-ul la fereastra } } 99 .*.//creaza un Button add(buton1).//declara campul de text ca TextField Button buton1. Component c) Component getComponentAt(int x.awt.awt.awt.//adauga TextField-ul la fereastra buton1=new Button ("Apasa").Frame void setResizable(boolean b) void setTitle(String s) <<Interface>> MenuContainer <<Interface> Serializable Component vizible : boolean enabled : boolean valid : boolean x : int y : int width : int height : int +peer ComponentPeer +parinte Container 1 <<Interface>> LayoutManager +panelLayout Panel FlowLayout Applet Adăugarea componentelor grafice import java. int y) 1 void setLocation(Point p) +fg.Window void toFront() void toBack() Toolkit getToolkit() void show() java. int y) Component getComponentAt(Point p) Window Component[] getComponents() LayoutManager getLayout() void setLayout(LayoutManager mgr) Insets getInsets() Frame void paint(Graphics g) void print(Graphics g) java.//creaza un TextField add(text).Applet. import java. buton2.- culori pentru foreground şi background specific lingvistic dimensiuni maxime şi minime Component⇒Container ⇒Window⇒Frame java.

20).setCheckboxGroup(cBG). import java. vSB. import java. Canvas şi Label import java. import java.applet.*. import java.Applet.applet.applet. add(text2). add(c).addItem(“Verde”). add(text1). } add(c2). 100). O arie de text public void init() { //declaratii/alocari de componente public void init() { //adaugarea componentelor in applet tArea=new TextArea(10.awt. import java. import java. import java.*.100). vSB=new Scrollbar(Scrollbar. list1.Applet.Applet.Applet. public class Container7 extends Applet{ Canvas c.*. public class Container5 extends Applet { Scrollbar hSB. c2: public void init() { public void init() { butoane radio text1=new TextField(20). add(vSB). true).10).awt.TextArea. CheckboxGroup cBG=new CheckboxGroup().applet.awt. c2.*. Checkbox c1.Applet.20).setState(false).awt. } } List. import java. Scrollbar.applet.applet. c2=new Checkbox(“AlDoilea”).*. add(text1).*.applet. c1=new Checkbox(“Primul”.VERTICAL.*.awt. Canvas public void init() { c=new Canvas(). add(hSB). 1.cBG. add(c1).1. } } import java.awt.setBackground(Color.0.addItem(“Rosu”).applet.awt. } } } import java. } } import java.awt .resize(40.1. TextField şi Checkbox import java. true). text1=new TextField(“Ion Pop”. c.Applet. } add(tArea). public class Container1 extends Applet{ public class Container3 extends Applet{ TextField text1. import java. un grup de TextField text2.Applet. } c2. Lista public void init(){ list1=new List(2. MenuComponent MenuBar MenuItem Menu PopupMenu CheckboxMenuItem 100 . import java.1.40).0.Applet. public class ContainerX extends Applet{ public class Container2 extends Applet{ //declaratii/alocari de componente TextArea tArea. } } Menu In Diagrama 1 se prezinta conceptele principale pe care trebuie sa le cunoastem pentru a programa menu-uri cu java. list1.addItem(“Albastru”). } } import java. public class Container6 extends Applet{ Label etic=new Label(“Nume si Prenume”).HORIZONTAL. list1.awt. text2=new TextField(“Buna”. public void init(){ Etichetă add(etic). add(list1). public class Container4 extends Applet{ List list1. c.*. Bare de defilare public void init(){ verticală şi orizontală hSB=new Scrollbar(Scrollbar.black).

add(fileMenu). public MenuFrame() { super(“Exemplu de menu”). MenuBar menubar=new MenuBar(). public class MenuFrame extends Frame { MenuItem fileNew=new MenuItem(“Nou”).awt. editCopy.300)).setHelpMenu(helpMenu). Menu editMenu=new Menu(“Modifica”). editMenu.add(editUndo).add(editPaste). editMenu. editUndo.add(helpAbout). MenuItem fileExit=new MenuItem(“Iesire”).add(helpContents).add(editMenu). } } Programul 3. MenuItem helpContents=new MenuItem(“Rezumat”). menubar. helpMenu. helpMenu. 101 . Ierarhia componentelor de menu Din Programul 3 se poate vedea care este în esenta modalitatea de programare a menu-urilor..Diagrama 2. fileMenu.addSeparator(). setSize(new Dimension(400. Menu helpMenu=new Menu(“?”). } public static void main(String[] args){ MenuFrame meu=new MenuFrame(). MenuItem editUndo=new MenuItem(“Cancel”). show().add(fileExit). LayoutManager2 extinde LayoutManager şi este folosit pentru asocierea de constrângeri aşezării componentelor. editPaste. MenuItem fileOpen=new MenuItem(“Deschide”).setEnabled(false).add(editCut).addSeparator().setEnabled(false). editMenu. setMenuBar(menubar). import java. fileSave. MenuItem helpAbout=new MenuItem(“Info. fileMenu. fileMenu. editMenu. MenuItem editCopy=new MenuItem(“Copy”). menubar.setEnabled(false).add(editCopy). editMenu. editCut. menubar. MenuItem fileSave=new MenuItem(“Salveaza”).add(fileSave). fileMenu.add(fileNew).add(helpMenu).addSeparator(). fileMenu.setEnabled(false). Menu fileMenu=new Menu(“Fisier”).add(fileOpen).setEnabled(false). MenuItem editCut=new MenuItem(“Cut”). menubar. helpMenu..”). MenuFrame: Programarea menu-urilor Grafica cu LayoutManager Layout Manager = Interfaţă utilizată pentru asezarea diferitelor componente într-un container după un şablon de aranjare. MenuItem editPaste=new MenuItem(“Paste”).*.

În orice moment. addComponent(arie. factura=f.*. public class FacturaFrame extends Frame {Button print. panel=new Panel(). dar componentele pot fi “răsfoite” şi să controlăm care din ele să devină vizibilă. gbc=new GridBagConstraints(). printF=new Button("PrintToFile"). AppletViewer: GestoreLayout Applet setLayout(new BorderLayout()). panel. addComponent(print. care formează aria de vizualizare a componentei.1. addComponent(printF.1.setEditable(false).0.1).awt.setLayout(gb).20.3. AppletViewer: GestoreLayout Applet setLayout(new GridLayout(3. addComponent(cancel.NORTH.2)). addComponent(arhivare.1. gbc. print=new Button("Print"). Panel panel. precum cărţile într-un pachet de cărti. cancel. 50).1).arhivare.1.1.toString().1.1).Cele mai folosite clase de gestori de layout care implementează interfaţa LayoutManager sunt: FlowLayout. arie. gbc. Exemplu. GridBagLayout. public FacturaFrame(Factura f) {super("Factura").1.1. import java. CardLayout.1.HORIZONTAL. fără să fie nevoie ca componetele să aibă aceleaşi dimensiuni. AppletViewer: GestoreLayout Applet North W e s t Center South E a s t Clasa GridBagLayout este un gestor flexibil care aliniază componentele pe verticală şi orizontală. setLayout(new FlowLayout()). private GridBagConstraints gbc.0. TextArea arie.anchor=GridBagConstraints. Acest layout este util căn o aceeaşi suprafaţă trebuie partajată de mai multe paneluri care trebuie să fie vizualizate în momente diferite de timp. CardLayout aşează componentele (de obicei paneluri) în straturi. BorderLayout.5). arhivare=new Button("Arhivare"). Fiecare obiect GridBagLayout păstrează o grilă dreptunghiulară dinamică de celule în care fiecare componentă ocupă una sau mai multe celule. private Factura factura.1. cancel=new Button("Cancel").fill=GridBagConstraints. GridLayout. gb=new GridBagLayout(). arie=new TextArea(factura. private GridBagLayout gb.printF. este vizibilă numai o componentă.1).2.4. 102 .

int col. gb.addProdus(new ElementVanzare(new SpecificatieProdus("mousepad". "alea rozelor")). int lat. int inal) { gbc. 2)). gbc.setConstraints(c. panel. 50).gridwidth=lat.}} 103 . 400). f.gbc). v. } public static void main(String[] args){ Vanzare v=new Vanzare(new Client("Ionescu". "Pop".add(c).gridx=col. 11). int linie. 3)). gbc. f. Frame f=new FacturaFrame(new Factura(v)). gbc.setVisible(true). v.gridy=linie.addProdus(new ElementVanzare(new SpecificatieProdus("mouse".add(panel). } void addComponent(Component c.setSize(480.gridheight=inal.

bk.getSource()==cancel) setVisible(false).out.arie.100+i).dat")). EVENIMENTE class Controller implements ActionListener{ private PrintWriter out.getSource()==print){ PrinterJob imprimanta=PrinterJob.repaint().printDialog()){ try{imprimanta. PageFormat pf. int i=0.} catch (PrinterException pe){arie. out.setColor(Color. while((sir=br.} } } else if (e.13.} catch(ArrayIndexOutOfBoundsException ae){System. } } 104 .write(factura. g.i+= 20. if(imprimanta.setPageable(bk). public int print(Graphics g.PAGE_EXISTS. }catch(FileNotFoundException fe){} catch(IOException ioe){} } else if (e. try{ StringReader continut=new StringReader(arie.int pageIndex) throws PrinterException{ g.getSource()==arhivare){ facturi. br=new BufferedReader(continut).println("Ce se printeaza???"). out.black).drawString(sir.print().} } class ContinutPanel extends Panel implements Printable { private BufferedReader br. } else if (e.close(). } }catch(IOException io){} catch (IllegalArgumentException ie){} return Printable.getText()). imprimanta.getSource()==printF){ try{ out=new PrintWriter(new FileOutputStream("factura. Book bk=new Book(). out. private String sir="".getPrinterJob().100. imprimanta.adaugaFactura(factura).defaultPage()).flush().append(new ContinutPanel().length()==0) sir=" ".toString()). public void actionPerformed(ActionEvent e){ if (e.append("Imprimanta nu exista").readLine())!=null) { if (sir.

exceptiile sunt container-ele de nivel inalt: .add(new JButton(“Buton”)). . 2. . panel. componentele usoare pot avea background-uri transparente.add(panel. JPanel – succesorul lui Panel si Canvas.*. opaca. PROGRAMAREA INTERFETELOR GRAFICE CU SWING Swing este un tehnologie API care extinde AWT-ul pentru construirea interfetelor grafice. container. ci in fereastra container-ului lor greu (2). JFrame public class Fereastra extends JFrame{ public Fereastra(){ Container container=getContentPane().add(new JLabel(“Label”)). De aceea. Aproape toate componentele Swing-ului sunt usoare.Container.implementeaza o arie dreptunghiulara in fereastra browser-ului .awt.JDialog – implementeaza o fereastra secundara Din (2) rezulta ca componentele usoare trebuie sa stea in ultima instanta intr-un container greu. adica o subclasa a clasei java. Din (1) rezulta ca. . are un rol dublu: este un simplu container si un canvas pentru afisarea graficelor.JWindow – o fereastra externa.14.NORTH). JRootPane – este continut in orice container greu. BorderLayout. } } Content pane JPanel JButton JLabel Container-e usoare: 1. nativa (1). Spre deosebire de componentele grele nu sunt incadrate intr-o fereastra (window) proprie.swing. Swing este o multime de componente usoare aflate in pachetul javax.furnizeaza o ierarhizare a continutului: Panel radacina stratPanel continutPanel menuBar sticlaPanel Componenta stratPanel continutPanel menuBar sticlaPanel Clasa Descriere JLayeredPane contine continutPanel si menuBar JPanel contine componentele aplicatiei sau applet JMenuBar sta deasupra lui continutPanel JPanel capteaza evenimentele mouse-ului si poate fi transparent 105 .JApplet.JFrame – implementeaza o fereastra principala. panel. JPanel panel=new JPanel().

for (int li=i. int i=f. f.Exemplu.stringWidth(sir). f. f. public Prob1(){ panelSticla=new PanelSticla().setColor(Color. Straturile cu valori mai mari sunt plasate deasupra straturilor cu valori mai mici. private JButton buton. Dimension d= getSize().awt.blue). li+=i) for (int c=0. import java. Sa se scrie un program care contine un buton care determina afisarea/ascunderea unui panel de sticla ce afiseaza textul “Buna ziua” pe toata suprafata sa. pe acest strat sunt plasate componentele PALETTE_LAYER 100 Folosit pentru palete si toolbar-uri MODAL_LAYER 200 Folosit de catre ferestrele de dialog POPUP_LAYER 300 Pentru menu-urile popup DRAG_LAYER 400 Util in deplasarea componentelor sau a celor care trebuie sa stea deasupra tuturor celorlalt Obs.drawString(sir.setVisible(true).*. buton.add(buton).awt. buton=new JButton("".addActionListener(this). } public void actionPerformed(ActionEvent e){ panelSticla. FontMetrics f=g.setVisible(true).200).setSize(200. public class Prob1 extends ActionListener { private Component panelSticla.getFontMetrics(). c.height. c<d. }}). unde bar menu-ul si content pane sunt asezate DEFAULT_LAYER 0 Implicit. c+=l) g. Plasarea componentelor poate fi controlata si in cadrul unui acelasi strat prin urmatoarele 106 . } } 3.*. li). Container content=getContentPane().EXIT_ON_CLOSE).width.gif")).event. } public void paintComponent(Graphics g){ String sir="Buna ziua". setGlassPane(panelSticla). import java.small.swing. JLayeredPane –nu are un layout manager implicit si permite plasarea componentelor pe diferite straturi: Strat Valoare Descriere FRAME_CONTENT_LAYER -3000 Stratul de baza. g. int l=f. }} JFrame implements class PanelSticla extends JPanel{ public PanelSticla(){ setOpaque(false). li<d. addMouseListener(new MouseAdapter(){ public void mousePressed(MouseEvent e){ setVisible(false). content. new ImageIcon("swing. } public static void main(String[] arg){ JFrame f=new Prob1().setDefaultCloseOperation(JFrame. import javax.getHeight().*.

gif"). tp.}}). Componentele cu pozitii mai mici sunt afisate deasupra celor cu pozitii mai mari.DEFAULT_LAYER. straturi[i].addTab("Al doilea panel". import java.getText().POPUP_LAYER. import java.add(new JButton("buton in panelul 2")). public class Prob3 extends JFrame{ private JTabbedPane tp. Stratul pe care se afla componenta respectiva. JLayeredPane. JPanel panel1=new JPanel().awt.add(tp). new JButton("Default1").addWindowListener(new WindowAdapter(){ public void windowClosing(WindowEvent e){System. Pozitia unei componente relativa la celelalte componente din acelasi strat.setPosition(butoane[i].PALETTE_LAYER.awt. private Integer[] straturi={ JLayeredPane. JLayeredPane. f.event.intValue()). if (sir.DEFAULT_LAYER.*.exit(0). import javax. JLayeredPane.setBounds(i*50.length. new JButton("Default0").getPosition(butoane[i]). import java. "Primul panel"). JLayeredPane. sir=butoane[i]. 350. panel2. import javax. 1). tp.swing. i*50.*. public Prob3(){ tp=new JTabbedPane(). i<butoane.setSize(600.setText(sir). } for(int i=0. i++){ lp.add(panel1.480).setLayer(butoane[i].swing.*.equals("Default1")) lp. 75).DRAG_LAYER }. i++){ String sir=butoane[i].add(butoane[i]).FRAME_CONTENT_LAYER. Descriere Indexul intr-un vector de componente pastrat de panelul stratificat. new JButton("Drag") }.equals("Default0")) lp. Fereastra cu 2 pagini de panel-uri de contin cate un buton. Exemplu3. JLayeredPane.MODAL_LAYER. i<butoane. f. Componentele de pe un strat cu numar mai mic sunt afisate sub componentele ce se afla pe straturi cu numar mai mare. butoane[i]. new JButton("Popup"). new JButton("Palette"). panel1. JTabbedPane – panel ce contine pagini (tab-uri) de paneluri. } Container contentPane=getContentPane().length.proprietati: Proprietate Index -getIndexOf(comp) Strat -getLayer(comp) Pozitie -getPosition(comp) Exemplu2.awt.*. butoane[i]. } } public static void main(String[] arg){ JFrame f=new Prob2(). setContentPane(lp). f.event.add(new JButton("buton in panelul 1")).setVisible(true). panel2. for(int i=0.*. 107 .getText()+"-"+lp.}} public class Prob2 extends JFrame{ private JLayeredPane lp. 4. Indicele are legatura cu ordinea componentelor: cele cu indice mai mic sunt plasate deasupra celor cu indice mai mare. new ImageIcon("ok. else if (sir. public Prob2(){ lp=new JLayeredPane(). "Panelul 2"). private JButton[] butoane={ new JButton("Frame content"). 0). JPanel panel2=new JPanel(). lp. new JButton("Modal"). contentPane.setPosition(butoane[i]. JLayeredPane.

layout continuu – controleaza daca componentele continute sunt incontinuu actualizate in timp ce separatorul este deplasat. Container contentPane=getContentPane(). JSplitPane – afiseaza doua componente (initial. Metoda: setContinuousLayout(boolean) .add(sp).5.HORIZONTAL_SPLIT). Controlul permite marirea sau micsorarea componentelor cand este click-at. butoane) separate de un despartitor (divider). } 108 .setOneTouchExpandable(true).HORIZONTAL_SPLIT sau VERTICAL_SPLIT). sp. //sp. sp.setContinuousLayout(true). public Prob4(){ sp=new JSplitPane().redimensionare la comanda (one-touch expandable) determina daca afiseaza un control in separator. public class Prob4 extends JFrame{ private JSplitPane sp.setDividerSize(15).setOrientation(JSplitPane. Panelul foloseste doua proprietati booleene: . Metoda: setOneTouchExpandable(boolean) Exemplu 4. sp. Componentele pot fi orientate vertical sau orizontal (JSplitPane. contentPane. Metoda: setOrientation(constanta).

Ferestrele interne sunt: .ferestre deoarece furnizeaza multe din caracteristicile unei ferestre (inchidere. maximizare. ER Implicit este DEFAULT_LAYER layeredPane JLayeredPan SG JLayeredPane Panelul stratificat asociat panelului e radacina al ferestrei interne maximizable boolean C4S false Indica daca fereastra poate fi G maximizata printr-un clic pe butonul corespunzator maximum boolean SG false Determina daca fereastra este maximizata jMenuBar JMenuBar SG null Bara de menu asociata panelului radacina al ferestrei interne resizable boolean C2S false Determina daca fereastra poate fi G redimensionata.interne deoarece stau. care stau pe desktop -clasa JDesktopPane. minimizare. intr-un alt container Swing. Daca este maximizata nu poate fi redimensionata rootPane JRootPane SG JRootPane Panelul radacina asociat ferestrei 1 C-poate apare in constructor. G-getter 109 . deschidere. S-setter. . de obicei un desktop pane. redimensionare). Proprietati: Nume Proprietate Tip de data Acc Valoarea Descriere es implicita closable boolean C3S false Indica daca fereastra interna poate 1 G fi inchisa de catre utilizator closed boolean SG false indica daca fereastra este inchisa la momentul respectiv contentPane Container SG instanta de JPanel container-ul ce contine componentele din fereastra defaultCloseOper int SG WindowConstant indica operatia care are loc cand fereastra este inchisa ation s.FERESTRE INTERNE Swing ofera functionalitate MDI (Multiple Documente Interface) prin ferestre interne. iconificare.HIDE_ON_CL OSE desktopIcon JDesktopIcon SG L&F Icon-ul afisat pe desktop cand fereastra este redusa la icon desktopPane JDesktopPan G O instanta a lui JDesktopPane ce e contine una sau mai multe ferestre interne frameIcon Icon SG L&F Icon-ul afisat in bara de titlu al ferestrei glassPane Component SG instanta JPanel Panelul de sticla asociat cu panelul radacina al unei ferestre interne icon boolean SG false Determina daca fereastra interna este (poate fi) redusa la icon – setIcon(boolean) iconifiable boolean C5S false Determina daca fereastra interna G poate fi redusa la un icon prin apelul metodei setIcon(boolean) layer Integer SG DEFAULT_LAY Stratul pe care sta fereastra interna.clasa JInternalFrame. fiind componente usoare.

trees.add(p).CENTER).selected Selecteaza sau deselecteaza fereastra interna title String C1S null Titlul afisat in bara de titlu al G ferestrei Exemplul 1. liste) este mai mare decat spatiul de afisare. dp=new JDesktopPane(). dp. Pentru aceasta putem folosi urmatoarele clase: .pentru a muta vederea la dreapta: descrestem coordonata X a vederii Proprietati Nume Proprietate Tip de Acc Valoarea Descriere data es implicita scrollMode int SG SIMPLE moduri de a realiza scroll-area: _SCROL BLIT_SCROLL_MODE.add(fi). JPanel p=new JPanel().getContentPane(). fi. contentPane. buton=new JButton("creaza Frame").pentru a muta vederea in jos: descrestem coordonata Y a vederii . contentPane.pentru a muta vederea la stanga: crestem coordonata X a vederii .} boolean SG false Scroll-area componentelor Este necesara in cazul in care o componenta (tabele. private JInternalFrame fi. imagini.setVisible(true). p.150)).addActionListener(this). true).add(dp.add(new JLabel(new ImageIcon("swing.setPreferredSize(new Dimension(250. /*Container content=fi. content. fi. true. true. BorderLayout. L_MOD BACKINGSTORE_SCROLL_MODE.small.interfata Scrollable . buton. Sa cream o fereastra care la actiunea unui buton vor fi create ferestre interne (ce vor contine o eticheta) public class Prob1 extends JFrame implements ActionListener{ private JDesktopPane dp. SIMPLE_SCROLL_MODE E extentSize Dimension SG Este o instanta a clasei Dimension care reprezinta partea vizibila a vederii view Componen SG Componenta afisata in viewport 110 - . BorderLayout.container-ele usoare JViewport si JScrollPane (inlocuieste si imbogateste componenta grea AWT ScrollPane) .setFrameIcon(new ImageIcon("ok. Pozitia vederii poate fi manevrata pentru a afisa regiuni diferite ale vederii astfel: . //fi.revalidate().true.JScrollBar folosit pentru implementarea manuala a barelor de scroll-are CLASA JVIEWPORT instantele sale furnizeaza un obiectiv (porthole) prin care se afiseaza o anumita regiune a vederii.add(buton.pentru a muta vederea in sus: crestem coordonata Y a vederii . dp.gif")).gif"))). texte. public Prob1(){ Container contentPane=getContentPane(). private JButton buton.*/ dp.NORTH). } public void actionPerformed(ActionEvent e){ fi=new JInternalFrame("O noua fereastra interna".setLayout(new FlowLayout()).

JPanel p=new JPanel(). BorderLayout. listener=new DragListener(obiectiv). if (e.add(p.CENTER). MouseMotionListener{ contentPane. class DragListener extends MouseAdapter implements p. ultim.x. obiectiv=new JViewport(). (glisarea unei imagini) public class Prob3 extends JFrame implements ActionListener{ public class Prob4 extends JFrame { private JViewport obiectiv. dreapta. jos.contains(drag)){ nou.} ultim.y-ultim. dreapta.x=drag.Este un punct ce reprezinta coordonatele vederii din coltul stanga sus al obiectivului viewRect Rectangle G O instanta a lui Rectangle care reprezinta dimensiunea si pozitia partii vizibile a vederii.CENTER).addMouseListener(listener). private JButton sus.addMouseMotionListener(listener).} Point drag=e.y-dist. stanga.y).setScrollMode(JViewport. stanga.add(dreapta).y. Daca nu este setata explicit. private DragListener listener. jos. JPanel p1=new JPanel(). Exemplul 4. v.addActionListener(this). Sa se creeze o fereastra care afiseaza o imagine si o deplaseaza cu ajutorul a patru butoane: sus.getSource()==stanga){punct.addActionListener(this).} Point dist=new Point(drag. //obiectiv. Point punct=obiectiv.} public void mouseDragged(MouseEvent e){ if (e. obiectiv. sus=new JButton("Sus"). }} viewPosition t Point SG - 111 .add(obiectiv. JPanel p=new JPanel().y=drag.x-dist. p. if(v.y=e.x-ultim. stanga. nou.getSource()==jos){punct.setViewPosition(nou).y. sus.add(new JLabel(new ImageIcon("setup.setViewPosition(punct). p. obiectiv. obiectiv. ultim=new Point(). private JViewport obiectiv.BACKINGSTORE_SCROLL_MOD p.} ultim.x.x-=5.getViewPosition(). if (e. p.addActionListener(this).add(sus). //BLIT_SCROLL_MODE jos=new JButton("Jos").x.add(new JLabel(new ImageIcon("setup. } } public void mousePressed(MouseEvent e){ public void actionPerformed(ActionEvent e){ ultim.getSource()==dreapta){punct. obiectiv=new JViewport().add(new JLabel(new ImageIcon("setup.add(jos). nou=new Point().addActionListener(this). Container contentPane=getContentPane(). contentPane.x+=5. } //main dreapta=new JButton("Dreapta").x.y+=5.add(stanga). } if (e.x=pozViewport. public Prob4(){ public Prob3(){ Container contentPane=getContentPane(). obiectiv. Latimea si inaltimea dreptunghiului sunt egale cu extent viewSize Dimension SG O instanta a lui Dimension care reprezinta dimensiunea vederii.y-=5. private JViewport v. drag.y=pozViewport.setView(p). stanga=new JButton("Stanga").getViewPosition().x=e. obiectiv.gif"))). public DragListener(JViewport o){ p1. Point pozViewport=v. nou.y.gif"))). contentPane. BorderLayout.add(obiectiv. private Point ultim.getPoint(). BorderLayout.gif"))).getSource()==sus){punct.NORTH). jos. dreapta .getPoint().setView(p1). v=o.getPoint(). este egala cu dimensiunea preferred a vederii Exemplul 3. obiectiv. E).

VERTICAL_SCROLLB 112 .HORIZONTAL_SCRO LLBAR_NEVER ScrollPaneConstants.VERTICAL_SCROLLB ne. Elementele unui JScrollPane: Proprietati Nume Proprietate columnHeader Tip de data JViewport Acc es SG S SG Valoarea implicita null null null Descriere o instanta a lui JViewport pentru header-ul de coloane o instanta a lui Component folosita ca header de coloane pentru vederea viewport-ului o componenta care este afisata in unul din cele patru colturi: ScrollPaneConstants.container uşor ce contine un viewport cu scrollbar-uri si header-e de coloane si linie optionale.HORIZONTAL_SCRO LLBAR_AS_NEEDED ScrollPaneConstants. Constante: ScrollPaneConstants.HORI ZONTA L_SCRO LLBAR_ AS_NEE DED null null rowHeader rowHeaderView verticalScrollbar verticalScrollbarP olicy JViewport Component JScrollBar int SG G SG CSG JScrollPa ScrollPaneConstants.LOWER_LEFT_CORN ER ScrollPaneConstants.LOWER_RIGHT_COR NER Scrollbar-ul orizontal folosit de panel Politica folosita pentru detrminaea circumstantelor in care scrollbar-ul orizontal este afisat.HORI AR_AS_NEEDED ZONTA ScrollPaneConstants.JSCROLLPANE .HORIZONTAL_SCRO LLBAR_ALWAYS o instanta a lui JViewport pentru header-ul de linii o instanta a lui Component folosita ca header de linii pentru vederea viewport-ului columnHeaderVie Component w corner Component horizontalScrollb ar horizontalScrollb arPolicy JScrollBar int SG CSG JScrollPa ne.UPPER_LEFT_CORNE R ScrollPaneConstants.UPPER_RIGHT_CORN ER ScrollPaneConstants.

p.gif"))). pot fi incadrate cu o bordura prin executarea a doi pasi: . BorderLayout.gif"))). sp. obiectiv.swing. contentPane.gif"))).UPPER_RIGHT_CORNER. sp=new JScrollPane(obiectiv). Pozitia ABOVE_TOP.setScrollMode(JViewport. sp.il transmitem cu metoda JComponent. . listener=new DragListener(obiectiv). JPanel p=new JPanel().setCorner(ScrollPaneConstants.setBorder(Border) Tipuri de bordura Tip de bordura Descriere Opaca Constante asociate Bevel O Bordura 3D da RAISED.add(sp. obiectiv. new JLabel(new ImageIcon("palette_hand.construim tipul de bordura dorit.BACKINGSTORE_SCROLL_MODE).VERTICAL_SCROLLB AR_ALWAYS O instanta a lui JViewport folosita pentru afisarea componentei scroll-ata de panel O bordura pentru viewport componenta afisata in viewport-ul panelului public Prob5(){ //prob 4 modificata Container contentPane=getContentPane().CENTER).add(new JLabel(new ImageIcon("setup. LOWERED Compound contine o burdura variaza interioara si una exterioara Empty O bordura nu transparenta Etched bordura formata da dintr-o linie colorata a carei grosime poate fi setata Matte O bordura ce da afiseaza o culoare solida sau incadreaza o imagine cu margini SoftBevel nu RAISED.addMouseListener(listener). JViewport Border Component SG SG CSG L_SCRO LLBAR_ AS_NEE DED JViewpo rt null null AR_NEVER ScrollPaneConstants.setView(p).* Toate componentele (de tip JComponent) cu exceptia lui JViewport.border.setColumnHeaderView(new JLabel(new ImageIcon("sus. obiectiv=new JViewport(). LOWERED Titled O bordura cu nu DEFAULT_POSITION. TOP. obiectiv.viewport viewportBorder viewportView Exemplul 5. titlu.addMouseMotionListener(listener).pachetul javax. 113 . } Borduri . obiectiv.

titlului poate fi setata BELOW_TOP. RIGHT Ierarhia claselor Border <<Interface>> Border AbstractBorder BevelBorder CompoundBorder EmptyBorder EtchedBorder MatteBorder LineBorder TitledBorder 114 . CENTER. BOTTOM. DEFAULT_JUSTIFICATION. LEFT. BELLOW_BOTTOM. ABOVE_BOTTOM.

Color.red)))).LOWERED))).lastIndexOf(".swing. f. String nm = b. JFrame f=new JFrame().setBorder(b).*. add(showBorder(new LineBorder(Color.*. new LineBorder(Color.awt.swing. import java.setSize(300. jp.setVisible(true).toString().Exemplul 6. public class Prob6 extends JPanel { static JPanel showBorder(Border b) { JPanel jp = new JPanel(). Border b2=BorderFactory. }} Clasa BorderFactory . BorderLayout. import javax. f. 115 . atunci conditia (b1= =b2) intoarce true.30. nm=nm.CENTER).DISPOSE_ON_CLOSE).createRaisedBevelBorder().createRaisedBevelBorder().5.")+1). import javax.* .blue))). add(showBorder(new EtchedBorder())). add(showBorder(new SoftBevelBorder(BevelBorder.swing.*. jp.awt. JLabel. deci utilizarea este mai eficienta. add(showBorder(new BevelBorder(BevelBorder. import java.setDefaultCloseOperation(WindowConstants.setLayout(new BorderLayout()). De exp: Border b1=BorderFactory.300). add(showBorder(new TitledBorder("Titlul meu"))).add(new JLabel( nm.*. } public static void main(String args[]) { JPanel p=new Prob6(). add(showBorder(new MatteBorder(5. f.contine metode statice de construire a bordurilor ce vor fi partajate de componente. add(showBorder(new CompoundBorder( new EtchedBorder().substring(nm.CENTER).getClass(). jp.30.este in pachetul javax. } public Prob6() { setLayout(new GridLayout(2.event.getContentPane(). 4)).RAISED))). f.magenta))). return jp.border.add(p).

note de curs. Bogdan. Horstmann. O perspectivă pragmatică. Olaru. Athanasiu si colectiv. 1998 B. Prentice Hall. S. Limbajul Java. D. Andrei. John Wiley&Sons. C. 2006 S. 1998 C. 2000 L. 2003 116 . Serbănaţi. Computing Concepts with Java 2 Essentials. Programare orientată spe obiecte (Limbajul Java). C. Eckel. S. BIBLIOGRAFIE I. Java de la 0 la expert.15. Editura Teora. Editura Polirom. Thinking in Java. Tănasă. Second Edition.

You're Reading a Free Preview

Download
scribd
/*********** DO NOT ALTER ANYTHING BELOW THIS LINE ! ************/ var s_code=s.t();if(s_code)document.write(s_code)//-->