Limbaje de programare III [628176]

Limbaje de programare III
Suport de curs
prof.univ.dr.Mariana Marinescu

Curs 1
Cuvinte importante:
– tehnologia Java si componentele sale: masina virtuala; limbajul Java propriu -zis;
compilatorul Java; biblioteca de clase Java;
– implementarea firmei Sun a limbajului Java: Platforma J2SE (Java 2 Platform, Standard
Edition);
– tipuri de programe implementate de Java: aplicatii Java, applet -uri;
– etapele dezvoltarii unei aplicatii Java; structura unei aplicatii Java; metoda main( );
– utilizarea claselor d e obiecte din pachetele predefinite (pachete API) Java; directiva import ;
instructiunea package;
– elemente de baza ale limbajului Java: identificatori, variabile, tipuri primitive de date;
constante;
– citirea datelor de la tastatura si afisarea datelo r pe ecran: metodele print, println, readLine,
read.
Notiuni introductive
Istoric Java:
– proiectul Java a fost initiat inca din 1990 dar firma Sun Microsystems a facut publica
specificatia noului limbaj abia in 1995 la SunWorld in San Francisco; parintel e noului limbaj Java a fost
James Gosling, cunoscut ca autor al editorului emacs ; numele initial al limbajului a fost Oak, numele
unui copac care crestea in fata biroului lui James Gosling; acest nume a fost abandonat ulterior si
inlocuit cu Java ;
– speci ficatia noului limbaj Java a fost facuta publica, de catre firma Sun Microsystems, in anul
1995 la SunWorld in Sun Francisco; in momentul lansarii sale, Java a revolutionat Internetul, deoarece a
fost gandit pentru a imbunatati continutul paginilor web pri n adaugarea unui aspect dinamic: animatie,
multimedia etc;
– incepand cu anul 1998, cand a aparut versiunea 2 a limbajului (Java 2 Platform), Java a fost
extins, acoperind si alte directii de dezvoltare: programarea aplicatiilor enterprise (aplicatii de t ip server)
precum si a celor adresate dispozitivelor cu resurse limitate, cum ar fi telefoanele mobile, pager -e sau
PDA -uri (Personal Digital Assistant) (mici dispozitive de calcul, de dimensiuni putin mai mari decat ale
unui telefon mobil, cu facilitati d e agenda si capabile sa execute aplicatii intr -un mod relativ asemanator
cu cel al unui PC).

Lansarea versiuni 2 a limbajului Java a adaugat multe facilitati, dar limbajul a pastrat si posibilitatile de a
crea aplicatii standard, de tipul aplicatiilor in l inie comanda sau a aplicatiilor bazate pe GUI (Graphical
User Interface).
Caracteristicile de baza ale limbajului Java
– Java este un limbaj simplu de folosit. Aceasta caracteristica poate fi considerata ca o reactie
directa la complexitatea considerabila a limbajului C/C++. Au fost indepartate din Java aspectele cele
mai derutante din C++ precum supraincarcarea operatorilor, mostenirea multipla sau pointer -rii.
– Java este independent de arhitectura calculatorului pe care lucreaza si foarte portabil .
Com pilatorul Java genereaza o secventa de instructiuni ale unei masini virtuale Java. Executia aplicatiilor
Java este interpretata . Singura parte din mediul de executie Java (JRE) care trebuie portata de pe o
arhitectura pe alta cuprinde interpretorul Java si o parte din bibliotecile standard care depind de sistem.
In acest fel aplicatii Java compilate pe o arhitectura SPARC de exemplu, pot fi rulate fara recompilare pe
un sistem bazat pe procesoare Intel. De altfel, mediul de executie Java (JRE) este scris in C ceea ce il face
foarte portabil.
– Interpretorul Java este gandit sa lucreze pe masini mici (memorie mica de ordinul sutelor de
KB), precum ar fi procesoarele cu care sunt dotate aparatele casnice si telefoanele mobile.
– Limbajul Java este orientat obiect . Cu el se pot crea clase de obiecte si instante ale acestora, se pot
incapsula informatiile, se pot mosteni variabilele si metodele de la o clasa la alta etc. Singura
caracteristica care lipseste este mostenirea multipla, dar pentru a suplini aceast a lipsa, Java ofera o
facilitate mai simpla, numita interfata, care permite definirea unui anumit comportament pentru o clasa
de obiecte, altul decat cel definit de clasa de baza. In Java orice element este un obiect, in afara de
datele primare. Din Java l ipsesc functiile si variabilele globale.
– Limbajul Java este distribuit , avand implementate biblioteci pentru lucrul in retea.
– Limbajul Java este un limbaj cu securitate ridicata .
– Java are inclus suport nativ pentru aplicatii care lucreaza cu mai multe fire de executie
(programare paralela si concurenta). Acest suport este independent de sistemul de operare.
Tehnologia Java si componentele sale
In tehnologia Java sunt cuprinse patru componente:
1. Masina virtuala , denumita JVM (Java Virtual Machin e) care interpreteaza fisierele cu extensia .class
ce contine “bytecode”.
“Bytecode” reprezinta cod compilat care este procesat de un program, denumit masina virtuala, si nu
cod executabil care ruleaza pe masina reala ce dispune de un procesor harwarde.
“Bytecode” este format din instructiuni generice care sunt convertite (transformate) de masina virtuala
in instructiuni specifice procesorului masinii reale. De aceea se spune ca aplicatiile Java sunt
independente de platforma (hardware si software).
Masina virtuala Java mai este denumita si interpretor Java.

2. Limbajul Java propriu -zis. Limbajul Java este orientat pe obiecte si se aseamana din punct de vedere
al sintaxei cu C++.
3. Un compilator care genereaza fisiere cu extensia .class . Compilatorul Java traduce instructiunile
scrise in limbajul Java (stocate in fisiere cu extensia .java ) in instructiuni generice “bytecode”(stocate in
fisiere cu extensia .class ) care sunt “intelese” de masina virtuala.
. Biblioteca de clase Java, denumita si Java API . Aceasta biblioteca contine un set de componente utile
care pot fi reutilizate de programatori in diverse aplicatii informatice.
Implementari ale limbajului Java
Cele mai importante implementari ale limbajului Java sunt realizate de firmele Sun si IBM.
Microsoft a creat propria sa implementare Java, disponibila numai pe platforme Windows.
Implementarea firmei Sun a limbajului Java
Implementarea Java a firmei Sun este cea mai frecvent utilizata.
Firma Sun a grupat tehnologia Java in trei editii:
1. Java 2 Platform, Micro Edition (platforma J2ME ) reprezinta mediul de dezvoltare al aplicatiilor pentru
dispozitive cu resurse mai reduse decat un calculator PC obisnuit. Printre aceste dispozitive se pot
enumera: carduri Smart, pager -e telefoane mobile, anumite tipuri de televizoare, PDA -uri (Personal
Digital Assistant).
2. Java 2 Platform, Standard Edition (platforma J2SE ) reprezinta mediul de dezvoltare al aplicatiilor de tip
“client -side” (care ruleaza pe PC -ul client).
3. Java 2 Platform, Enterprise Edition ( platforma J2EE ) reprezinta mediul de dezvoltare al aplicatiilor de
tip “server -side” (care ruleaza pe un server si pot fi accesate de mii de clienti simultan); usureaza enorm
crearea de aplicatii internet industriale scalabile.
Obiectul de studiu pentru cu rsul nostru este platforma Java J2SE
Platforma J2SE (Java 2 Platform, Standard Edition)
Produsul informatic (software -ul) care implementeaza platforma J2SE si care este folosit pentru
dezvoltarea de aplicatii specifice acesteia este J2SDK (Java 2 Software Development Kit, Standard
Edition) in diverse versiuni pe care le scoate firma si care este livrat gratuit (este un soft liber).
Pentru a fi la curent cu ultimele versiuni ale produsului J2SDK se poate accesa adresa de internet
http://java.sun.com.
Produs ul J2SDK include uneltele de creare a programelor Java (compilatorul si alte unelte necesare
pentru dezvoltare de programe) si unelte de executie ale acestora (masina virtuala, biblioteca de clase
Java API etc). Cele mai importante unelte incluse in J2SDK sunt:
– javac – compilatorul Java;
– java – interpretorul Java;

– appletviewer – folosit pentru testarea applet -urilor (aplicatii care ruleaza dintr -un navigator de
internet).
Pachetul Java 2 SDK este un set de programe care ruleaza, din lina de comanda a sistemului de operare,
utilitare bazate pe text, care nu au nevoie de o interfata grafica pentru utilizator.
Produsul informatic J2RE (Java 2 Runtime Environment, Standard Edition) este folosit numai cand se
executa aplicatii scrise in Java. El este de stinat celor care doresc sa poata executa aplicatii Java, fara a
avea nevoie de intreg mediul de dezvoltare.
J2RE este un produs care poate fi instalat separat, dar si ca o componenta a J2SDK.
Mediul de programare Java si medii integrate IDE (Integrated De velopment Environments).
Pachetul Java 2 SDK este destul de departe de instrumentele de programare moderne denumite si medii
integrate de dezvoltare de programe (IDE).
Folosind un mediu IDE, programatorului ii sunt puse la dispozitie toate elementele de c are are nevoie
pentru a crea aplicatii Java profesionale: debugger -e pentru executarea pas cu pas a aplicatiilor,
modalitati de a vedea in orice moment ierarhia de clase si metode existente in cadrul unui proiect,
completarea automata a codului, compilare incrementala (codul este compilat in timp ce este scris) etc.
Exista mai multe astfel de medii IDE care pot ingloba pachetul Java 2SDK cum ar fi:Eclipse, Forte for Java,
JBuilder, NetBeans IDE.
Nota: Instrumentul de dezvoltare de programe folosit in acest curs este Java 2 SDK, Standard Edition, v
6.16 realizat de catre firma Sun Microsystem (soft liber) iar ca mediu IDE este folosit produsul NetBeans
v 6.7.1 (soft liber).
Tipuri de programe implemen tate de Java
Cu ajutorul limbajului Java se pot dezvolta doua tipuri de programe:
1. Programe Java care se executa individual prin intermediul unui interpretor Java. Acestea se
incadreaza in programele “clasice” scrise in diverse limbaje de programare, cum ar fi:C/C++, Pascal etc.
Acest tip de programe Java sunt denumite aplicatii .
2. Programe Java care se executa in interiorul unui navigator Internet, dintr -un document HTML. Acest
tip de programe Java sunt denumite applet -uri.
Nota: In acest curs se vor i nvata notiunile si conceptele fundamentale de programare necesare pentru
dezvoltarea de aplicatii Java.
Etapele dezvoltarii unei aplicatii Java
1. Editarea setului de instructiuni de programare cu ajutorul unui editor de texte. In acest fel este creat
un fisier sursa, care are extensia .java .
2. Compilarea programului . Pentru aceasta operatie se lanseaza in executie un program special,
denumit compilator Java . Compilatorul analizeaza textul sursa al programului din punct de vedere

sintactic, semnaland event ualele erori. Daca programul nu contine erori sintactice, compilatorul traduce
acest program in codul masina pentru masina virtuala Java (un fel de calculator intr -un alt calculator).
Rezultatul compilarii este unul sau mai multe fisiere de tip “bytecode” – o secventa de instructiuni de
asamblare pentru masina virtuala Java. Fisierul “bytecode” nu depinde de masina gazda si de sistemul
de operare pe care va fi executat programul. Masina virtuala mai este cunoscuta si ca interpretor Java
sau executor (runtim e) Java .
Extensia fisierului “bytecode” rezultat in urma compilarii are extensia .class .
3. Conversia (transformarea), de catre interpretorul Java, a instructiunilor “bytecode” in instructiuni
inteligibile masinii gazda care apoi sunt executate . Conversia are loc la lansarea executiei si anume
instructiune cu instructiune.
In acest mod este asigurata portabilitatea si independenta de platforma.Un dezavantaj poate fi
considerat timpul mai mare de executie.
Structura unei aplicatii Java
O aplicatie Java este compusa din una sau mai multe clase care interactioneaza intre ele prin
intermediul metodelor. In grupul de clase, care formeaza o aplicatie Java, trebuie sa existe o clasa care
sa contina o metoda statica avand numele main .
Atunci cand se executa o apli catie Java, masina virtuala va cauta si invoca automat metoda statica avand
numele main .
Nota : Metoda main poate fi considerata ca fiind echivalentul Java a functiei main din C/C++.
Cel mai simplu program Java (care nu face nimic) arata astfel:
class NuFacNimic
{
public static void main (String [ ] args)
{}
}
Nota : Tipul parametrilor metodei (functiei) main cat si tipul metodei, static void , sunt obligatorii.
Metodele folosite in programele Java reprezinta in mare masura echivalentul functiilor sau procedurilor
din alte limbaje de programare. O definitie completa a conceptului de metoda va fi data intr -o lectie
separata cand se va discuta despre conceptele de clasa si obiect.
In aceasta lectie prezentam doar cateva notiuni elementare despre metode pe ntru a putea scrie functii
de genul celor din limbajul C/C++ pe care sa le folosim in cateva programe simple.
O metoda se defineste prin:
– antetul metodei;

– corpul metodei.
Antetul metodei contine numele metodei, tipul valorii returnate de metoda si o lista de parametri
(eventual vida), fiecare avand un tip precizat, prin care metoda comunica cu exteriorul ei, incadrata intre
paranteze rotunde:
Corpul metodei este constituit din declaratii si instructiuni cara executa diferite sarcini. Toate
declaratiile si instructiunile din corpul functiei sunt incadrate intre paranteze acolade.
Sintaxa definirii unei metode este:
<tip_rezultat> nume_metoda (<lista_parametri>)
{ <corpul_functiei> }
Nota: Prin prefixarea metodelor cu ajutorul cuvintelor cheie public static se poate spune ca metodele
sunt aproape similare cu functiile din limbajul C. Aceasta tehnica nu trebuie utilizata insa in mod abuziv.
Instructiunea return este utilizata pentru a intoarc e o valoare catre codul apelant.
Sintaxa instructiunii return este:
return [<expresie>];
unde:
– <expresie> – specifica valoarea returnata de metoda; in anumite situatii pentru iesirea fortata dintr -o
metoda care are tipul void se foloseste instructiunea r eturn fara <expresie>.
Daca tipul metodei este void atunci nu se returneaza nici o valoare si deci instructiunea return nu este
necesara.
La apelul unei metode parametrii actuali (reali) sunt trecuti in parametrii formali utilizand exclusiv
transmiterea p rin valoare .
Nota: Java permite supraincarcarea (overloading) numelui metodelor. Aceasta inseamna ca mai multe
metode cu acelasi nume pot fi declarate in cadrul aceleiasi clase atata timp cat lista de parametrii
formali difera ca numar si tip.
Utilizarea claselor de obiecte din pachetele predefinite (pachete API) Java
Pot exista unele operatii care sunt frecvent utilizate in cadrul unei aplicatii Java. (cum ar fi: citirea
datelor, scrierea datelor, extragerea radicalului, desenarea de obiecte grafice etc) pentru care nu exista
instructiuni specifice ale limbajului Java.
Din acest motiv, s -au construit pachete predefinite de clase de obiecte (pachete API) (elaborate de
firma proiectanta a mediul de programare folosit) care contin colectii de clase de obiect e de utilitate
generala grupate pe categorii.
Mediul de programare J 2 SDK ofera peste 70 de pachete predefinite, printre care, mai des utilizate sunt:
– java.lang care ofera clase fundamentale pentru limbajul Java: clasa Integer, clasa Math, clasa
System, clasa String etc;

– java.io care ofera modalitati de citire/scriere a datelor prin intermediul fluxurilor de date, a
fisierelor etc;
– java.util care contine clase pentru utilizarea colectiilor de date abstracte de tip stiva si coada,
pentru manevra rea datelor calendaristice si a timpului;
– java.util.jar pentru citirea/scrierea fisierelor in format jar (Java Archive);
– java.math care ofera clase specializate in calcul matematic;
– java.text care ofera clase pentru manevrarea textului, a datelor calendaristice, a timpului si a
mesajelor intr -o maniera independenta de limba utilizata;
– java.net care pune la dispozitie clase pentru implementarea aplicatiilor de retea.
Directiva import pentru utilizarea claselor din pachetele API Java in propria a plicatie.
Sa presupunem ca se doreste folosirea unei clase oarecare C dintr -un pachet P. Atunci referirea la acea
clasa in cadrul programului se face cu numele P.C, adica plasand numele pachetului urmat de semnul
punct (.) inaintea numelui clasei. Utiliza rea permanenta a numelui pachetului din care fac parte clasele
poate crea dificultati de scriere a programului. Pentru a evita acest lucru se foloseste directiva import .
Sintaxa directivei import este :
import <nume_pachet>.<nume_clasa>;
sau
import <nume_pachet>.*;
Pentru a doua forma a directivei, toate clasele din pachet vor putea fi abreviate cu numele lor
neprecedat de numele pachetului.
Directivele import trebuie sa apara inainte de orice declarare a unei clase. Pachetul java.lang este
automat in clus in intregime. Acesta este motivul pentru care putem folosi prescurtari de genul
Integer.parseInt ()
Crearea de pachete cu clase de obiecte proprii aplicatiei. Instructiunea package
Daca dorim sa includem o clasa de obiecte intr -un pachet trebuie sa re alizam urmatoarele:
– sa scriem o instructiune package inaintea unei eventuale directive import ;
– apoi, sa stocam fisierul cu extensia .class ce contine clasa respectiva in director care are
numele pachetului.
Sintaxa instructiunii package este:
package <nume_pachet>;
Observatie: In cazul folosirii IDE NetBeans, instructiunea package este inclusa automat, atunci cand se
creaza o noua aplicatie Java (proiect Java).
Elemente de baza ale limbajului Java

Setul de caractere folosit de limbajul Java
Limbajul J ava lucreaza in mod nativ folosind setul de caractere Unicode. Acesta este un standard
international care inlocuieste vechiul set de caractere ASCII. Vechiul standard ASCII este insa un subset
al setului Unicode, ceea ce inseamna ca vom regasi caracterele ASCII cu exact aceleasi coduri ca si mai
inainte. Java foloseste setul Unicode in timpul executiei aplicatiilor dar si in timpul compilarii acestora.
La citirea fisierului sursa, compilatorul Java foloseste secventele escape Unicode . Secventele escape sunt
secvente de caractere ASCII care incep cu caracterul backslash ( \). Pentru secventele escape Unicode , al
doilea caracter din secventa trebuie sa fie caracterul u sau U. Dupa caracterul u sau U urmeaza o
combinatie de patru cifre hexazecimale care for meaza impreuna doi octeti de memorie reprezentand un
caracter Unicode.
De exemplu, cifrele de la 0 la 9 sunt reprezentate prin secvente escape Unicode de la \u0030 la \u0039
si sunt interpretate ca cifre ISO -LATIN -1.
Spatiile albe folosite in programele Java sunt: caracterele blanc (spatiu), tab, return (retur de linie), line –
feed (linie noua) si return + line -feed.
Anumite caractere sunt reprezentate prin secvente escape speciale:
\n = \u000a – linie noua; \b = \u0008 – backspace;
\t = \u0009 – tab; \r = \u000d – return;
\\ = \u005c – backslash; \” = \u0022 – ghilimele.
\’ = \u0027 – apostrof.
Identificatori
Identificatorii, intalniti si sub denumirea de nume simbolice, au rolul de a denumi elemente ale
programului Java: constante, variabile, clase m etode etc.
Din punct de vedere sintactic, un identificator este constituit dintr -o succesiune nelimitata de litere si
cifre Unicode, primul caracter fiind obligatoriu o litera (inclusiv ‘_’).
Limbajul Java este “case -sensitive”, adica face diferenta intre literele mici si literele mari. De aceea,
identificatorii sunt diferiti in functie daca sunt scrisi cu litere mici si mari.
Cuvintele -cheie (keywords) sunt identificatori speciali, cu inteles predefinit, care pot fi utilizati numai in
constructii sintacti ce in care sunt specificati. De exemplu: if, while etc. Toate cuvintele -cheie se scriu
numai cu litere mici.
Separatori
Separatorii au rolul de a separa unitatile sintactice:
– Ca separatori “generali” se utilizeaza caracterele albe: spatiu (‘ ‘), TAB (‘ \t’), sfarsit de linie (‘ \n’)
si comentariile.

– Separatorii specifici sun folositi, de exemplu, pentru a separa unele constructii sintactice:
variabilele sunt separate prin c aracterul virgula (‘,’). Alti separatori specifici sunt ( ) { } [ ] .
– Delimitatorii sunt folositi, de exemplu, pentru:
– a delimita sfarsitul unei instructiuni sau al unei declaratii – caracterul punct si virgula
(‘;’);
– a delimita o constanta de tip caracter – caracterul apostrof (‘);
– a delimita constantele sir de caractere(ghilimelele).
Comentarii
Comentariile sunt texte care vor fi ignorate de compilator, dar au rolul de a explicita si de a face mai
lizibil pentru programator anumite secvent e de program.
In Java exista trei tipuri de comentarii:
– o succesiune de caractere incadrata intre /* si */ ; aceste comentarii pot fi formate din mai
multe linii;
– o succesiune de caractere pe mai multe linii care tin de documentatie, incadrate intre /** si */;
textul dintre cele doua secvente este automat mutat in documentatia aplicatiei de catre generatorul
automat de documentatie (javadoc);
– o succesiune de caractere care incepe cu // si se termina la sfarsitul unei singure linii.
Variabile
Varia bila este o zona temporara de stocare, rezidenta in memoria RAM, care are un nume simbolic
(identificator) si stocheaza un anumit tip de date. Ea poate fi modificata pe parcursul executiei
programului.
In ciuda denumirii, in Java exista variabile care isi pot modifica valoarea si variabile care nu si -o pot
modifica, numite variabile finale . Asupra variabilelor finale vom reveni ulterior dupa intelegerea
conceptelor de clasa de obiecte.
Pentru utilizarea unei variabile intr -un program Java trebuie ca aceas ta sa fie declarata. La declararea
variabilei trebuie specificat numele simbolic al variabilei, tipul acesteia si, eventual, o valoare initiala
care se atribuie variabilei.
Tipurile primitive de date definite in Java
Un tip de date defineste multimea de v alori pe care variabila poate sa le stocheze, modul de
reprezentare a acestora in memorie, ca si setul de operatii pe care programul poate sa le realizeze cu
aceste date.
In limbajul Java a fost exact definita modalitatea de reprezentare a tipurilor primi tive de date in
memorie. In acest fel, variabilele Java devin independente de platforma hardware si software pe care
lucreaza .

De asemenea, Java defineste o valoare implicita pentru fiecare tip de date, in cazul in care variabila de
un anumit tip nu a pri mit nici o valoare de la utilizator. Este o practica buna insa aceea ca programele sa
nu depinda niciodata de aceste initializari implicite. Regula ar fi deci urmatoarea: nici o declararie fara
initializare.
Limbajul Java accepta urmatoarele tipuri de baza : byte, short, int, long, float, double, char, boolean,
void .
Tabelul de mai jos prezinta o descrie generala a tipurilor primitive de date utilizate de Java.
Tip Valori Reprezentare in memorie
byte [-128, 127] Intreg pe 1 byte
short [-32768, 32767] Intreg pe 2 bytes
int [2.147.483.648,
2.147.483.648] Intreg pe 4 bytes
long [-263, 263 -1] Intreg pe 8 bytes
float 6 cifre semnificative
[10-46, 1038] Virgula mobila pe 4 bytes
double 15 cifre semnificative
[10-324, 10308] Virgula mobila pe 8 bytes
char coduri Unicod Pe 2 byte
boolean false sau true Pe un bit

Tipul boolean este folosit pentru memorarea unei valori de adevar sau fals. In Java aceste doua valori le
vom nota prin constantele (literali) true si respectiv false .
Orice variabila booleana nou creata primeste automat valoarea implicita false .
Tipul char este folosit pentru a reprezenta caractere de tip Unicode.
Orice variabila de tip caracter nou creata primeste automat ca valoare implicita caracterul null al
codului Unicode, “ \u0000’.
Tipurile de date intregi sunt folosite pentru memorarea unor valori intregi cu semn. Conventia folosita
de Java pentru valorile intregi cu semn este reprezentarea in complement fata de doi. Tipurile de date
intregi sunt: byte , short , int, long .
Orice variabila de tip intreg ( byte , short , int si long ) nou creata primeste automat valoarea implicita 0.
Tipurile de date reale sunt folosite pentru memorarea unor valori reale sub forma de mantisa si
caracteristica. Tipurile de date reale sunt: float si double.
Valoarea implicita pentru variabilele de tip float este 0.0f, iar pentru variabilele de tip double este 0.0d.
In Java sunt definite cateva valori reale speciale :
1. Valoarea NaN (Not a Number) se obtine atunci cand se efectueaz a o operatie a carei rezultat nu este
definit, de exemplu 0.0 / 0.0.
2. Valori folosite pe post de infinit pozitiv si negativ. Aceste valori pot rezulta in urma unor calcule.
Valorile descrise la pct. 1 si 2 sunt definite sub forma de constante si in ierarhia de clase predefinite Java,
si anume in clasa java.lang.Float si respectiv in clasa java.lang.Double . Numele constantelor este: NaN,
POSITIVE_INFINITY, NEGATIVE_INFINITY.
Pentru tipurile intregi si intregi lungi, precum si pentru tipurile flotante exista definite clase in ierarhia de
clase predefinite Java si anume:
– java.lang.Integer – pentru tipul int;
– java.lang.Long – pentru tipul long ;
– java.lang.Float – pentru tipul float ;
– java.lang.Double – pentru tipul double .
In fiecare dintre clase numerice prezentate sunt definite doua constante care reprezinta valorile minime
si maxime pentru tipurile respective. Aceste doua constante se numesc in mod uniform MIN_VALUE si
MAX _VALUE.
Tipul void
Tipul void este un tip special, pentru care multimea valorilor este vida. Acest tip se utilizeaza cand este
necesar sa se specifice absenta oricarei valori. De exemplu: pentru tipul de data a metodelor care nu
intorc nici un rezult at, cum a fost cazul metodei main ().

Constante
O constanata este folosita pentru a exprima in program o valoare pe care o poate lua tipurile primitive
de date si tipul sir de caractere.
Constantele intregi pot fi reprezentate in baza 10, 16 sau 8. Cons tantele intregi pot fi intregi normale
sau lungi. Constantele lungi se recunosc prin faptul ca se termina cu sufixul l sau L.
Pentru a reprezenta o constanta intreaga in baza 16 trebuie sa se adauge prefixul 0x sau 0X in fata
numarului.
Pentru a reprezent a o constanta intreaga in baza 8 trebuie sa se adauge prefixul 0 (cifra zero) in fata
numarului.
Constantele reale care se pot reprezenta in memoria calculatorului sunt numere rationale din
intervalele specificate la tipurile float si double . Constantele reale pot fi specificate in notatia obisnuita
sau in format stiintific.
Sufixul care indica tipul float poate fi f sau F iar sufixul care indica tipul double poate fi d sau D. Daca nu
este specificat nici un sufix, valoarea implicita este de tip double .
Constantele de tip caracter sunt utilizate pentru a reprezenta caracterele Unicode.
Reprezentarea se face fie folosind o litera sau o cifra, fie o secventa escape .
Caracterele care au reprezentare grafica pot fi scrise intre apostroafe. Pentru cele care nu au
reprezentare grafica, se folosesc secventele escape sau secventele escape predefinite prezentate deja.
Intern, Java interpreteaza constantele de tip caracter ca pe un numar (codul Unicode al caracterului
respectiv). Ulterior, functiile de scriere vor transforma acest numar in caracterul corespunzator.
Constantele de tip sir de caractere sunt cuprinse intre ghilimele. Caracterele care formeaza sirul de
caractere pot fi caractere grafice sau secvente escape ca cele prezentate la constantele de tip carac ter.
Daca se doreste introducerea de caractere terminatoare de linie intr -un sir de caractere, atunci se
foloseste secventa escape \n in sirul de caractere respectiv.
Observatie: Un sir de caractere este, de fapt, o instanta a clasei de obiecte String declarata standard in
pachetul java.lang . Vom reveni asupra sirurilor de caractere intr -o lectie separata.
Sintaxa folosita pentru declararea de variabile este:
<tip> <nume_v1> [= <expresie>] [, <nume_v2> [= <expresie2>] … ];
unde:
– <tip> – specifica tipul d e data al variabilelor;
– <nume_v1>, <nume_v2>, … – specifica numele simbolic al variabilelor care se declara (adica,
identificatorii);
– <expresie1>, <expresie2>, … – specifica o expresie de initializare; expresia trebuie sa fie evaluabila in
momentul dec lararii; sunt optionale si sunt folosite pentru a atribui unor variabile anumite valori initiale.

Nota: Se pot declara simultan mai multe variabile de acelasi tip, separand numele lor prin virgula.
O variabila trebuie sa fie declarata imediat inainte de a fi folosita . Locul unde este declarata o variabila
determina domeniul de vizibilitate si semnificatia ei.
Limbjul Java permite si definirea de constante. Modul cum se face definirea constantelor va fi
prezentata intr -o lectie separata destinata descrieri atributelor statice.
Exemple de declaratii de variabile ce pot fi folosite intr -un program:
int a, b=7, c=8;
char g;
float x=b*5.6, y;
Citirea datelor de la tastatura si afisarea datelor pe ecran
In limbajul Java nu exista instructiuni specializate pentru citirea/scrierea datelor. Aceste operatii se
realizeaza prin intermediul unor metode existente in pachetele API ale limbajului. Intrarea si iesirea in
Java se realizeaza cu ajutorul claselor de obiecte din pachetul predefinit java.io . Orice program care
foloseste rutinele de intrare/iesire trebuie sa cuprinda instructiunea:
import java.io.*
Conceptul fundamental in operatiile de intrare/iesire in limbajul Java este fluxul de intrare/iesire
(stream).
Daca stream -ul este de intrare, succesiunea de bit i “curge” dinspre exterior (in acest caz, de la tastatura)
catre memoria calculatorului.
Daca stream -ul este de iesire, secventa de biti “curge” dinspre memoria calculatorului catre exterior (in
acest caz, catre ecran).
Java ofera trei fluxuri predefinite pentru operatii I/O standard:
– System.in pentru intrarea standard de la tastatura;
– System.out pentru iesirea standard la ecranul calculatorului;
– System.err pentru fluxul de erori.
Pentru afisarea datelor la ecranul calculatorului se folosesc metode le print si println . Spre deosebire
de C/C++ care dispun de un numar foarte mare de optiuni de formatare, afisarea in Java se face exclusiv
prin concatenare de String -uri fara nici o optiune de formatare.
Observatie: String -urile sunt obiecte Java care de scriu sirurile de caractere si le vom studia separat intr -o
lectie viitoare. Sa retinem ca prin concatenarea a doua siruri se obtine un nou sir de caractere care
uneste cele doua siruri initiale. Operatorul de concatenare a doua siruri de caractere folosit de Java este
semnul + (plus).
Sintaxa folosita la apelul metodei print este:

System.out.print (<expresie>); unde:
– <expresie> – este numele unei variabile de un tip de data sau este o expresie care foloseste operatorul
de concatenare pentru siruri de caractere; daca nu toti operanzii din expresie sunt siruri de caractere, ci
alte tipuri primitive de date atunci Java face o conversie temporara la tipul String.
Efectul apelului metodei print este acela ca se realizeaza afisarea la ecran a variabilei data ca parametru
si nu se face salt la o linie noua.
Sintaxa folosita la apelul metodei println este:
System.out.println (<expresie>); unde:
– <expresie> – este numele unei variabile de un tip de data sau este o expresie care foloseste operatorul
de concate nare pentru siruri de caractere.
Efectul apelului metodei println este acela ca se realizeaza afisarea la ecran a variabilei data ca
parametru si se face salt la o linie noua.
Metoda println se poate apela si fara parametrii, adica in forma:
System.out.pri ntln( );
caz in care se face numai un salt la o linie noua fara sa se afiseze nimic.
Se poate folosi urmatoarea combinatie de apeluri care este echivalenta cu println( ):
System.out.print(<expresie>);
System.out.println();
Pentru citirea datelor de la tastatura procedura este mai anevoioasa. Acest lucru se datoreaza in primul
rand faptului ca programele java nu sunt concepute pentru a citi de la tastatura. In majoritatea cazurilor,
programele Java isi preiau datele dintr -o interfata grafica, din forme H TML sau din fisiere.
Citirea datelor de la tastatura se realizeaza cu metoda readLine . Insa pentru citire trebuie sa construim
un obiect BufferedReader dintr -un obiect InputStreamReader care la randul sau este construit din
System.in . Descrierea detaliata a acestor obiecte o vom face intr -o lectie viitoare dupa intelegerea
conceptelor de clase si obiecte.
Sintaxa folosita la apelul metodei readLine este:
<nume_obiect>.readLine(); unde:
– <nume_obiect> – reprezinta o variabila de tipul obiectului BufferedRea der.
Efectul apelului metodei readLine este urmatorul: preia caracterele de la intrare pana cand intalneste
un terminator de linie sau sfarsit de fisier. Metoda returneaza caracterele citite (din care extrage
terminatorul de linie ) ca sir de caractere de tip String . Daca primul caracter citit este terminatorul de
linie, atunci metoda readLine returneaza valoarea null.
Urmatorul program (Afiseaza.java) ilustreaza modul de folosire al metodelor println si readLine pentru
afisarea si respectiv citirea unor si ruri de caractere:

/**
* Afiseaza.java
*/
package afiseaza;
import java.io.*;
public class Afiseaza
{
public static void main(String[] args) throws IOException
{
System.out.println("Bun venit in universul Java");
System.out.print ln ("Introduceti un numar ");
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(isr);
String s = br.readLine();
int a = Integer.parseInt(s);
System.out.println(s);
}
}
Nota: Metoda Integer.parseInt(s) aplicata sirului de caractere de la intrare realizeaza conversia sirului de
caractere s intr -un numar intreg de tip int. Pentru a converti un sir de caractere la un numar de tip
double se poate folosi metoda Double.par seDouble() , iar pentru a converti un sir de caractere la un
numar de tip float se poate folosi metoda Float.parseFloat() . Asupra acestor metode vom reveni in lectia
despre siruri de caractere.
Observatie: Clauza throws utilizata in antetul metodei main este folosita pentru a specifica toate
exceptiile (erorile) de I/O care nu sunt tratate in cadrul metodei main ci de catre alte metode din clasele
java.io.*. Modurile de tratare a exceptiilor (erorilor) vor fi descrise intr -o lectie viitoare.
Metoda System .in.read() citeste urmatorul caracter din fluxul de intrare (care poate contine mai multe
caractere citite de la tastatura) si returneaza caracterul citit ca un intreg (cuprins intre 0 si 65535) sau -1
daca s -a intalnit terminatorul de linie (caracterul ‘ \r’- carriage return).
Programul urmator (Afiseaza1.java) ilustreaza modul de folosire a acestei metode:
import java.io.*;
public class Afiseaza1

{
public static void main(String[] args) throws IOException
{ char b;
System.out.println("Bun venit in universul Java");
b = (char) System.in.read();
System.out.println(b);
}
}
Curs 2
Cuvinte importante:
– expresii si operatori; prioritatea operatorilor si evaluarea expresiilor; conversii implicite si
explicite;
– instruc tiuni simple si blocuri de instructiuni;
– structuri fundamentale de control: instructiunea if; instructiunea switch, instructiunea while,
instructiunea do -while, instructiunea for, instructiunile break si continue.
Expresii si operatori
O expresie este c ompusa dintr -o succesiune de operanzi, legati prin operatori.
Un operand poate fi o constanta, o variabila, un apel de metoda, o expresie incadrata intre paranteze
rotunde.
Operatorii desemneaza operatiile care se executa asupra operanzilor si pot fi grupati pe categorii, in
functie de tipul operatiilor realizate.
Operatorii limbajului Java sunt unari (se aplica unui singur operand) sau sunt binari (se aplica asupra a
doi operanzi).
A. Operatorii aritmetici
Operatorii aritmetici sunt: ‘*’ – inmultirea; ‘/’ – impartirea; ‘%’ – restul impartirii intregi; ‘+’ – adunarea; ‘ -’
– scaderea.
De asemenea este folosit operatorul unar ‘ -’ (minus) pentru schimbarea semnului, precum si operatorul
unar ‘+’ (plus) (introdus pentru simetrie).
Nota:
1. Operatorul ‘%’ nu poate fi aplicat decat operanzilor intregi.
2. Operatorul ‘/’ poate fi aplicat atat operanzilor intregi, cat si operanzilor reali, dar functioneaza diferit
pentru operanzii intregi, fata de operanzii reali. Daca cei doi operanzi sunt numere intregi, operandul ‘/’

are ca rezultat catul impartirii int regi (fara parte fractionara). Daca cel putin unul dintre cei doi operanzi
este un numar real, operandul ‘/’ furnizeaza rezultatul impartirii reale (cu parte fractionara).
De exemplu:
Fie declaratiile de variabile:
int a=5, b=7
float x=3.5

Expresie Rezult at
b%2 1
a/2 2
x/2 1.75

B. Operatorii de incrementare/decrementare
Operatorul de incrementare este ‘++’. Operatorul de decrementare este ‘ –’. Acesti operatori sunt unari
si au ca efect marirea (respectiv micsorarea) valorii operandului cu 1.
Limbajul Java permite doua forme pentru operatorii de incrementare / decrementare: forma prefixata
(inaintea operandului) si forma postfixata (dupa operand).
Instructiunile care urmeaza incrementeaza variabila total cu 1:
total++;
++total;
Instructiunile c are urmeaza decrementeaza variabila total cu 1:
total –;
–total;
In cazul cand se foloseste operatorul de incrementare / decrementare in forma prefixata (inaintea
operandului) , limbajul Java va incrementa / decrementa mai intai valoarea variabilei si apoi va utiliza
variabila intr -o alta expresie.
In cazul cand se foloseste operatorul de incrementare / decrementare in forma postfixata (dupa
operand) , limbajul Java va utiliza mai intai valoarea variabilei intr -o alta expresie si apoi va efectua
operatia de incrementare / decrementare.

De exemplu, daca valoarea curenta a lui x este 5, atunci:
– evaluarea expresiei 3 * ++x conduce la rezultatul 18;
– evaluarea expresiei 3 * x++ conduce la rezultatul 15,
dupa care valoarea lui x va fi in ambele cazuri 6.
Operatorii de incrementare / decrementare pot fi aplicati operanzilor intregi, operanzilor in virgula
mobila si operanzilor de tipul char.
C. Operatori relationali
Operatorii relationali sunt operatori binari si desemneaza relatia de ordine in care se gas esc cei doi
operanzi: <, >, <=, >=.
Rezultatul aplicarii unui operator relational este true daca cei doi operanzi sunt in relatia indicata de
operator, si false , altfel.
De exemplu, expresiile logice:
4 > 6 are ca rezultat valoarea false ,
8 <= 3+13 are ca rezultat valoarea true .
Un alt operator relational este instanceof care testeaza daca un anumit obiect este sau nu instanta a
unei anumite clase de obiecte (adica, apartine unei clase de obiecte).
De exemplu:
Object o = new Object( );
String s = new String( );
o instanceof Object – are ca rezultat valoarea true ,
s instanceof String – are ca rezultat valoarea true
o instanceof String – are ca rezultat valoarea false .
D. Operatori de egalitate
Operatorii de egalitate sunt folositi pentru testarea unei egalitati sau inegalitati intre doua valori. Sunt
operatori binari si arata relatia de egalitate (==) sau inegalitate (!=).
Rezultatul aplicarii unui operator de egalitate este true , daca cei doi operanzi sunt in relatia indicata de
operator si false altfel.
De exemplu, expresiile logice:
5 == 2+3 are ca rezultat valoarea true ,
5 != 2+3 are ca rezultat valoarea false .
E. Operatori logici globali se aplica asupra unor operanzi de tip boolean .

Exista trei operatori logici globali:
– negatia logica (not) reprezentata cu !;
– conjunctie logica (si) reprezentata cu &&;
– disjunctie logica (sau) reprezentata cu | | .
Rezultatul aplicarii operatorilor logici este tot boolean . Iata toate posibilitatile de combinare:
true && true == true ! true == fals e
true && false == false ! false = true
false && true == false
false && false == false
true | | true == true
true | | false == true
false | | true == true
false | | false == false
Nota: O regula importanta este ca operatorii logici && si | | folosesc evaluarea booleana partiala
(scurcircuitata). Aceasta inseamna ca daca rezultatul poate fi determinat evaluand prima expresie, a
doua expresie nu mai este evaluata.
De exemplu, in expresia:
x != 0 && 1/x != 5
Daca x este 0, atunci prima jumatate are valoarea false . Aceasta inseamna ca rezultatul conjunctiei va fi
fals, deci a doua expresie nu mai este evaluata.
F. Operatori la nivel de biti
Operatorii logici pe biti se aplica numai operanzilor intregi (de tipul byte , short , int si long ) si au acelasi
rezultat ca si operatorii logici studiati (negatie, conjunctie, disjunctie si disjunctie exclusiva) dar bit cu
bit. De fapt, operatorii se aplica reprezentarii binare a numerelor implicate
Operatori logici pe biti:
Operator Denumire Tip
~ Complementare
(negatie) pe biti unar

& Conjunctia
logica (si) pe
biti binar
^ Disjunctie
exclusiva (sau
exclusiv) pe biti binar
| Disjunctie
logica (sau) pe
biti binar

Rezultatul aplicarii operatorilor de complementare pe biti, de disjunctie logica pe biti si de conjunctie
logica pe biti este acelasi cu cel prezentat la operatorii logici globali, daca consideram ca 1 ar reprezenta
adevarul si 0 falsul. Rezultatul aplicar ii operatorului de disjunctie exclusiva pe biti este:
^ 0 1
0 0 1
1 1 0

Operatiile logice la nivel de biti constau in aplicarea operatiei respective perechilor de biti de pe pozitii
egale in cele doua numere (cu exceptia operatiei de negare care este unara). In situatia in care numerele
nu au reprezentare binara de aceeasi lungime, reprezentarea mai scurta este completata cu zerouri
nesemnificative (inserate in fata reprezentarii) pana se obtin dimensiuni egale.
Iata cateva exemple de folosire:
3 | 4 = = 7 5 ^ 7 == 2
3 0…011 5 0…101
4 0…100 7 0…111
––– –––
7 0…111 2 0…010
5 & 7 == 5 ~5 == -6
5 0…101 5 0…0101
7 0…111 –––-

––– -6 1…1010
5 0…101
Operatorii de deplasare pe biti au ca efect deplasarea reprezen tarii interne binare a primului operand cu
semn spre stanga (<<) cu n pozitii, spre dreapta (>>) cu n pozitii sau deplasarea primului operand fara
semn spre dreapta (>>>) cu n pozitii. Numarul n de pozitii care se deplaseaza este specificat de cel de -al
doilea operand.
La deplasarea la stanga (<<), pozitiile ramase libere in dreapta se completeaza cu 0.
La deplasarea la dreapta (>>), in pozitiile ramase libere in stanga se copiaza in mod repetat bitul de
semn.
La deplasarea la dreapta fara semn (>>>), pozitiile ramase libere in stanga se completeaza cu 0.
Observatie:
Expresia x << n are ca efect inmultirea operandului x cu 2n. Expresia x >> n are ca efect impartirea
intreaga a operandului x cu 2n. Aceasta afirmatie este valabila pentru numere intregi p ozitive.
De exemplu:
5 >> 1 = 2 adica reprezentarea binara 101 devine dupa deplasarea cu un bit la dreapta 010.
5 << 1 = 10 adica reprezentarea binara 101 devine dupa deplasarea cu un bit la stanga 1010.
H. Operatori de atribuire
Operatorii de atribuire su nt operatori binari care permit modificarea valorii unei variabile.
Exista un operator de atribuire simplu (=) si 10 operatori de atribuire compusi cu ajutorul operatorului
‘=‘ si al unui alt operator binar (aritmetic sau logic pe biti) .
O varianta de sin taxa folosita este:
<nume_variabila> = <expresie>
Efectul aplicarii operatorului este: Se evalueaza <expresie>, apoi se atribuie variabilei <nume_variabila>
valoarea expresiei.
Nota: <expresie> poate fi la randul ei o expresie de atribuire, caz in care se realizeaza o atribuire
multipla. Atunci cand compilatorul intalneste o operatie de atribuire multipla, el atribuie valorile de la
dreapta la stanga.
<nume_variabila1> = <nume_variabila2> = … = <nume_variabilan> = <expresie>;
Se foloseste atunci cand se do reste sa se atribuie aceeasi valoare mai multor variabile.
De exemplu:
total = 0;
suma = 0;

a = 0;
folosind atribuirea multipla rezulta:
total = suma = a = 0
A doua varianta de sintaxa folosita este:
<nume_variabila> <operator_binar> = <expresie>;
unde:
– <operator_binar> – este din multimea {*, /, %, +, -, <<, >>, &, |, ^}.
Efectul aplicarii operatorilor de atribuire compusi este echivalent cu instructiunea:
<nume_variabila> = <nume_variabila> <operator_binar> <expresie>;
De exemplu instructiunile:
total = total + 100;
jumatate = jumatate/2;
b = a = a*2;
sunt echivalente cu:
total+ =100;
jumatate/ =2;
b = a* = 2;
I. Operatorul de concatenare ( + ) de siruri de caractere este un operator binar folosit pentru lipirea mai
multor siruri de caractere
La concat enarea sirurilor de caractere, lungimea sirului rezultat este suma lungimii sirurilor care intra in
operatie. Carcterele din sirul rezultat sunt caracterele din primul sir, urmate de cele dintr -al doilea sir in
ordine. Daca cel de -al doilea operand este un tip primitiv de data, acesta este convertit la un sir de
caractere care sa reprezinte valoarea operandului.
De exemplu:
“Acesta este ” + “un sir” este echivalent cu “Acesta este un sir”
“Variabila a are valoarea ” + 3 este echivalent cu “Variabila are va loarea 3”
J. Operatorul conversie de tip (sau conversie explicita de tip sau cast) este un operator unar utilizat
pentru a genera o variabila temporara de un nou tip.
Rezultatul unui cast este valoarea operandului convertita la noul tip de data exprimat de cast.
O conversie explicita de tip (un cast) este de forma:

(<tip_nou>) <expresie>
unde:
– <tip_nou> – este noul tip de data al expresiei <expresie> altul decat cel declarat initial sau implicit;
– <expresie> – este o variabila sau o expresie care se doreste a fi convertita la tipul nou.
De exemplu, in secventa de instructiuni:
double f = 7.8;
int i = (int)f;
valoarea variabilei f este convertita la o valoare intreaga si anume 7, si noua valoare este atribuita
variabilei i.
Observatie: Nu toate cast-urile sunt valide in Java. Vom reveni la descrirea conversiilor explicite intr -un
paragraf separat a acestei lectii.
K. Operatorul conditional ?:
Operatorul conditional examineaza o conditie si returneaza o valoare daca conditia este adevarata si alta
daca conditia este falsa.
Sintaxa operatorului conditional este:
(<conditie>) ? <rezultat_adevar> : <rezultat_fals>
unde:
– <conditie> – o expresie de evaluat ;
– <rezultat_adevar> -rezultatul returnat daca conditia are valoarea true ;
– <rezultat_fals> – rezultatul returnat daca conditia are valoarea false .
De exemplu:
int i = 5;
int j = 4;
double f = (i < j) ? 100.5 : 100.4;
Instructiunea este similara unei instructiuni if-else.
Prioritatea operatorilor si evaluarea expresiilor
Ordinea in care are loc efectuarea prelucrarilor determinate de operatori este data in urmatorul tabel de
prioritati (de la prioritate maxima la prioritate minima):
Categorie operator Exemple de operatori di n categorie Regula de asociativitate la
prioritate egala

Operatori de referinta . [ ] Stanga la dreapta
Unari ++ – ! operatorii + si – unari cast -ul Dreapta la stanga
Multiplicativi * / % Stanga la dreapta
Aditivi + – Stanga la dreapta
Deplasare pe biti << >> >>> Stanga la dreapta
Relationali < <= > >= instanceof Stanga la dreapta
Egalitate == != Stanga la dreapta
AND pe biti & Stanga la dreapta
XOR pe biti ^ Stanga la dreapta
OR pe biti | Stanga la dreapta

Categorie operator Exemple de operatori Regula de
asociativitate la
prioritate egala
AND logic && Stanga la dreapta
OR logic | | Stanga la dreapta
Conditional ?: Dreapta la stanga
Atribuire = si cei 10 operatori de
atribuire compusi Dreapta la stanga

Evaluarea expresiilor
Evaluarea unei expresii presupune calculul valorii expresiei, prin inlocuirea in expresie a fiecarei variabile
cu valoarea ei si a fiecarei functii cu valoarea returnata de functia respectiva si efectuarea operatiilor
specificate de o peratori. In timpul evaluarii expresiei se tine cont de existenta parantezelor, de
asociativitate si de prioritatea operatorilor:

1. In cadrul unei expresii fara paranteze, se efectueaza operatiile in ordinea prioritatii operatorilor;
2. La prioritate egal a, operatorii “vecini” actioneaza conform regulilor de asociativitate prezentate in
tabelul de mai sus.
3. Utilizarea parantezelor rotunde este mai puternica decat prioritatea operatorilor.
De exemplu, programul urmator (operatori.java) ilustreaza cativa o peratori Java inclusiv operatorul de
concatenare pentru sirurile de caractere care se afiseaza la ecran.
/** Utilizarea operatorilor. */
public class Operatori
{
public static void main(String[] args)
{
int a = 6, b = 7, c = 3;
System.out.println("a=" + a);
System.out.println("b=" + b);
System.out.println("c=" + c);
System.out.println();
b += c;
System.out.println("a=" + a);
System.out.println("b=" + b);
System.out.println("c=" + c);
System.out.println();
c++;
System.out.println("a=" + a);
System.out.println("b=" + b);
System.out.println("c=" + c);
System.out.println();
++a;
System.out.println("a=" + a);
System.out.println("b=" + b);

System.out.println("c=" + c);
System.out.println();
b = ++a – c++;
System.out.println("a=" + a);
System.out.println("b=" + b);
System.out.println("c=" + c);
System.out.println();
}
}
In urma executiei programului “Operatori.class” pe ecran sunt afisate valorile:
a=6 a=7
b=7 b=10
c=3 c=4
a=6 a=8
b=10 b=4
c=3 c=5
a=6
b=10
c=4
Conversii
Java acorda o atentie deosebita tipurilor. Fiecare expresie are un tip ce poate fi dedus din structura
expresiei si din tipul operanzilor ce intra in alcatuirea sa: constante, variabile si apeluri de metode. Sunt
insa permise, in anumite conditii bine precizate, conversii de la un tip la un alt tip.
Conversiile pot aparea in urmatoarele situatii:
– la atribuire, cand tipul unei expresii trebuie convertit la tipul variabilei ce primeste valoarea expresiei;
– la apelul unei metode cand are loc transferul parametrilor actuali (reali) catre parametrii formali;
– la conversii ce implica tipul String : ori ce tip poate fi convertit la tipul String ;
– la evaluarea unei expresii aritmetice: operanzii trebuie adusi la un tip comun, astfel incat expresia sa
poata fi evaluata;
– la o conversie explicita.

Conversii implicite la evaluarea expresiilor
In aceasta categorie intra conversiile efectuate automat, fara vreo precizare explicita in program.
Pentru tipurile primitive de date, urmatoarele conversii sunt implicite:
byte la short, int, long, float, double ;
short la int, long, float, double ;
int la long, float, double ;
char la int, long, float, double ;
long la float, double ;
float la double .
Regula conversiilor implicite la evaluarea expresiilor este: operandul care are un domeniu de valori mai
restrans este convertit la tipul operandului care are multimea valorilor mai ampla.
Observatii :
1. Unele din aceste conversii pot conduce la o pierdere a preciziei. De exemplu, la conversia unui long
intr-un float , caz in care se pierde o parte din cifrele semnificative pastrandu -se insa ordinul de marime.
Precizia se pierde si in cazul conversiei long la double sau int la float pentru ca, desi dimensiunea zonei
alocate pentru cele doua tipuri este aceeasi, numerele flotante au nevoie de o parte din aceasta zona
pentru a reprezenta exponentul. In aceste situatii, se va produce o rotunjire a numerel or convertite.
2. Conversiile implicite legate de tipul String se aplica numai operanzilor cu tipuri primitive asupra carora
se aplica operatorul de concatenare (+); in acest caz operanzii de un anumit tip diferit sunt convertiti la
String .
3. Conversiile implicite la tipul referinta vor fi abordate intr -o lectie viitoare.
Conversii implicite la operatia de atribuire
Pentru tipurile primitive sunt admise urmatoarele conversii implicite la atribuire:
– tipul char poate fi atribuit unei variabile de tip char, byte, short, int, long, float, double ;
– tipul byte poate fi atribuit unei variabile de tip char, byte, short, int, long, float, double ;
– tipul short poate fi atribuit unei variabile de tip char, short, int, long, float, double ;
– tipul int poate fi atri buit unei variabile de tip int, long, float, double ;
– tipul long poate fi atribuit unei variabile de tip long, float, double ;
– tipul float poate fi atribuit unei variabile de tip float, double ;
– tipul double poate fi atribuit unei variabile de tipul double.
– tipul boolean nu poate fi atribuit la o variabila de alt tip.

Observatii :
1. Valorile de tip primitiv nu pot fi atribuite variabilelor de referinta si, la fel, valorile de tip referinta nu
pot fi memorate in variabile de tip primitiv.
2. Convers iile implicite intre tipurile referinta vor fi descrise intr -o lectie viitoare dupa prezentarea
tipului referinta si a conceptului de clasa de obiecte.
Conversii explicite
Conversiile explicite sunt realizate de programator folosind operatorul de conversie explicita (sau cast –
ul).
Pentru tipurile primitive sunt admise, in plus fata de cele implicite, urmatoarele conversii explicite:
byte la chart ;
char la byte, short ;
short la byte, char ;
int la byte, short, chart ;
long la byte, short, char, int ;
float la byte, short, char, int, long ;
double la byte, short, char, int, long, float .
Conversiile explicite pot produce pierderi de precizie si, de asemenea, pot conduce la o modificare a
ordinului de marime.
Observatii :
1.Nu se pot face conversii explicite intre valorile de tip referinta si valorile de tip primitiv.
2. Valorile de tip boolean nu pot fi convertite la nici un alt tip.
3. Conversiile explicite intre tipurile referinta vor fi descrise intr -o lectie viitoare dupa prezentarea tipului
referinta si a conceptului de clasa de obiecte.
Instructiuni simple si blocuri de instructiuni
O instructiune simpla este o singura instructiune, cum ar fi aceea prin care se atribuie o valoare unei
variabile (instructiunea de atribuire) sau se apeleaza o metoda.
Un bloc de instructiuni (numit si instructiune compusa ) este o secventa de instructiuni simple si
declaratii de variabile locale. Aceste instructiuni se executa in ordinea in care apar in interiorul blocului.
Sintactic, blocurile de instructiuni sunt delimitate d e acolade. Blocurile de instructiuni pot fi incluse
(imbricate) in cadrul altor blocuri de instructiuni.
Sintaxa unui bloc de instructiuni este:
{

<declaratii_de_variabile_locale>;
<instructiune_1>;
<instructiune_2>;

<declaratii_de_variabile_locale>;
<instructiune_n>;
}
unde:
– <declaratii_de_variabile_locale> – reprezinta instructiuni de declarare a unor variabile locale ; o
instructiune de declarare poate sa apara oriunde in interiorul unui bloc.
Nota: Declaratiile de variabile locale care apar intr -un bloc sunt valabile numai in interiorul blocului, din
momentul declararii lor pana la sfarsitul blocului.
Instructiunea vida este o instructiune care nu executa nimic. Ea este formata numai din ; si se foloseste
atunci cand este obligatoriu sa avem o instructiune, dar nu dorim sa executam nimic in acea
instructiune.
Structuri fundamentale de control
A. Structuri alternative (de decizie)
Instructiunea if
Sintaxa instructiunii este:
if (<expresie>) <instructiune_1>;
[else <instructiune_2>];
unde:
– <expresie> – specifica expresia de evaluat;
– <instructiune_1>, <instructiune_2> – specifica instructiunile (simple sau compuse) de executat.
Semantica : se evalueaza <expresie> si daca valoarea expresiei este true , se executa <instructiune_1>,
altfel se executa <instructiune_2>.
Nota: Instructiunea if poate sa faca parte dintr -o alta instructiune if sau else, adica instructiunile if pot fi
incluse (imbricate) in alte instructiuni if.
De exemplu, urmatorul program (denumit ArieTriunghi.java) testeaza daca trei numere pot forma
laturile unui triunghi si daca da calculeaza aria triunghiului folosind formula lui Heron.
/** Utilizarea instructiunii if pentru determinarea ariei triunghiului*/

import java.io.*;
public class ArieTr iunghi
{
public static void main(String[] args) throws IOException
{
double x, y, z, p, aria;
String s;
System.out.print ("Introduceti x= ");
InputStreamReader isrx = new InputStreamReader(System.in);
BufferedReader brx = new Buffe redReader(isrx);
s = brx.readLine();
x = Double.parseDouble(s);
System.out.print ("Introduceti y= ");
InputStreamReader isry = new InputStreamReader(System.in);
BufferedReader bry = new BufferedReader(isry);
s = bry.readLine();
y = Double.parseDouble(s);
System.out.print ("Introduceti z= ");
InputStreamReader isrz = new InputStreamReader(System.in);
BufferedReader brz = new BufferedReader(isrz);
s = brz.readLine();
z = Double.parseDouble(s);
if (x<=0 || y<=0 || z<=0)
System.out.println("Numerele introduse nu sunt laturi ale unui triunghi");
else
if (x+y<=z || x+z<=y || y+z<=x)
System.out.println("Numerele introduse nu sunt laturi ale unui triunghi");
else
{

p = (x+y+z)/2;
aria = Math.sqrt(p*(p -x)*(p -y)*(p -z));
System.out.println("Aria triunghiului = " + aria);
}
}
}
Observatie : Metoda sqrt() face p arte din clasa de obiecte Math care este implementata in pachetul
java.lang . Metoda sqrt() este de tip double si are un parametru de tip double .
Instructiunea switch
Sintaxa instructiunii este:
switch (<expresie>)
{ case <constanta_1> : < grup_de_instructiuni_1>;
case <constanta_2> : <grup_de_instructiuni_2>;

case <constanta_n> : <grup_de_instructiuni_n>;
[default: <grup_de_instructiuni_n+1>;]
}
unde:
– <expresie> – specifica variabila sau expresia de evaluat;
– <constanta_1> , <constanta_2>, …, <constanta_n> – specifica valorile constantelor cu care se face
compararea rezultatului evaluarii expresiei;
– <grup_de_instructiuni_1>, … – o instructiune sau un grup de instructiuni care se executa in cazul in care
o alternativa case se potriveste.
Semantica : se evalueaza <expresie>; se compara succesiv valoarea expresiei cu valorile constantelor
<constanta_1>, <constanta_2>, …, <constanta_n> din alternativele case :
– daca se intalneste o constanta din alternativa case cu valoarea e xpresiei, se executa secventa
de instructiuni corespunzatoare si toate secventele de instructiuni care urmeaza, pana la intalnirea
instructiunii break sau pana la intalnirea acoladei inchise (}) care marcheaza sfarsitul instructiunii switch ;
– daca nici u na dintre valorile constantelor din alternativa case nu coincide cu valoarea
expresiei, se executa secventa de instructiuni din alternativa default (alternativa implicita sau
prestabilita).
Observatii:

1. Spre deosebire de if-else, care permite selectare a unei alternative din maximum doua posibile, switch
permite selectarea unei alternative din maximum n+1 posibile.
2. In instructiunea if-else se executa instructiunea (instructiunile) corespunzatoare valorii expresiei si
atat, in timp ce in instructiunea switch se executa si toate secventele de instructiuni ale alternativelor
case urmatoare.
Nota: Mai general, o alternativa poate avea mai multe valori, ca in exemplul urmator:
case 1 : case 2 : case 3: case 5: a=b; b=c; c= a;
Instructiunea break din switch
Sintaxa instructiunii este:
break;
Semantica : determina iesirea neconditionata din instructiunea switch , adica opreste executia
secventelor de instructiuni ale alternativelor case urmatoare.
Exemplu urmator (VocaleConsoane.java) citeste de la tastatura o l itera si determina daca aceasta este o
vocala sau o consoana.
// Exemplu pentru instructiunea switch
import java.io.*;
public class VocaleConsoane {
public static void main(String[] args) throws IOException {
InputStreamReader isr = new Inp utStreamReader(System.in);
BufferedReader br = new BufferedReader(isr);
System.out.print("Introduceti o litera mica: ");
char c = (char) br.read();
System.out.print(c + ": ");
switch(c)
{
case 'a': ca se 'e': case 'i': case 'o': case 'u': System.out.println("vocala");
break;
case 'y': case 'w': System.out.println("Uneori vocale "); break; default:
System.out.println("consoana");
}
}

}
B. Structuri repetitive (iterative)
Instructiunea while
Sintaxa instructiunii este:
while (<expresie>)
<instructiune>;
unde:
– <expresie> – specifica expresia de testat;
Semantica : se evalueaza <expresie>:
– daca valoarea expresiei este false se iese din ciclul while ;
– daca valoarea expresiei este true , se executa instructiunea atat timp cat valoarea expresiei
este true .
Nota:
1. Daca testul initial este false, instructiunea din corpul ciclului nu este executata niciodata.
1. Pentru ca ciclul sa nu fie infinit, este o bligatoriu ca una din instructiunile care se executa in ciclul while
sa modifice cel putin una dintre variabilele care intervin in <expresie>, astfel incat aceasta sa poata lua
valoarea false sau sa contina o operatie de iesire neconditionata din ciclu fol osind instructiunea break .
2. Instructiunea while poate contine o secventa de instructiuni si atunci aceasta secventa se grupeaza
intr-o singura instructiune compusa (incadrata intre acolade).
Exemple:
1. Urmatorul program (SumaCifre.java) citeste de la ta statura un numar natural x (folosind fluxul de
intrare System.in) si calculeaza suma cifrelor lui x.
Pentru a calcula suma cifrelor lui x se procedeaza astfel:
– pasul 1 – se obtine ultima cifra din numar (cifra unitatilor) ca fiind restul impartirii numa rului x la 10
(x%10), iar aceasta cifra se adauga la suma;
– pasul 2 – se elimina din numar ultima cifra (x=x/10); cifra zecilor a devenit acum ultima cifra;
– pasul 3 – se repeta pasul 1 si pasul 2 pana cand numarul x nu mai are cifre.
/** Utilizarea instructiunii while pentru calculul sumei
cifrelor unui numar natural x*/
import java.io.*;
public class SumaCifre

{
public static void main(String[] args) throws IOException
{
int x, suma=0;
String s;
System.out.print ("Introduceti numarul natura l= ");
InputStreamReader isrx = new InputStreamReader(System.in);
BufferedReader brx = new BufferedReader(isrx);
s = brx.readLine();
x = Integer.parseInt(s);
while (x !=0)
{
suma+=x%10; // obtin ultima cifra si adun la s ultima cifra a lui x
x/=10; //elimin ultima cifra a lui x
}
System.out.println("Suma cifrelor este: " + suma);
}
}
mici si determina daca acestea sunt consoane sau vocale:
// Exemplu pentru instructiunea While – citire de litere si stabil ire vocale sau consoane
import java.io.*;
public class VocaleConsoane1 {
public static void main(String[] args) throws IOException {
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(is r);
System.out.print("Introduceti litere mici despartite de spatii sau nu: ");
char c = (char) br.read();
while (c !=' \r' )
{

switch (c)
{
case 'a': case 'e': case 'i': case 'o': case 'u': System.out.printl n(c+":" +"vocala");
break;
case 'y': case 'w': System.out.println(c+":" +"Uneori vocale "); break;
case ' ': break;
default: System.out.println(c+":"+"consoana");
}
c = (char) br.read();
}
}
}
Instructiunea do -while
Sintaxa instructiunii este:
do
<instructiune>;
while (<expresie>);
unde:
– <instructiune> – o instructiune simpla de executat;
– <expresie> – specifica expresia de testat (de evaluat);
Semantica : se executa instructiunea si apoi se evalueaza expresia:
– daca valoarea expresiei este false se iese din ciclul do-while ;
– daca valoarea expresiei este true se executa instructiunea (din ciclul do-while ) atit timp cat valoarea
expresiei este adevarata.
Nota:
1. Spre deosebire de instruc tiunea while , instructiunea do-while executa instructiunea specificata in
corpul ciclului cel putin o data, chiar daca de la inceput valoarea expresiei este false , deoarece evaluarea
expresiei se face dupa executia instructiunii.
2. Pentru ca ciclul sa nu fie infinit, este obligatoriu ca una din instructiunile care se executa in ciclul do-
while sa modifice cel putin una dintre variabilele care intervin in <expresie>, astfel incat aceasta sa

poata lua valoarea false sau sa contina o operatie de iesire necond itionata din ciclu folosind
instructiunea break .
3. Instructiunea do-while poate contine o secventa de instructiuni si atunci aceasta secventa se
grupeaza intr -o singura instructiune compusa (incadrata intre acolade).
Instructiunile while si do -while sunt folosite in functie de momentul la care dorim sa testam o conditie
care determina efectuarea unor prelucrari repetate.
Cand este necesar sa testam o conditie inainte de efectuarea unor prelucari repetate atunci se foloseste
instructiunea while .
Cand condi tia depinde de la inceput de prelucrarile repetate din ciclu (prin urmare, este necesar sa fie
testata dupa executarea prelucrarilor din ciclu) atunci se foloseste instructiunea do-while .
Urmatorul program (CifraControl.java) citeste de la tastatura un num ar natural x si calculeaza cifra de
control a lui x. Cifra de control a unui numar natural se obtine calculand suma cifrelor numarului, apoi
suma cifrelor sumei obtinute, s.a.m.d. pana la obtinerea unei singure cifre. De exemplu, pentru x = 335
calculam su ma cifrelor 3+3+5 = 11. Cum suma nu este formata dintr -o singura cifra, repetam procedeul:
1+1=2. Deci 2 este cifra de control a lui 335.
/** Utilizarea instructiunii while pentru calculul cifrei de control a unui numar natural x */
import java.io.*;
publi c class CifraControl
{
public static void main(String[] args) throws IOException
{
int x, suma=0;
String s;
System.out.print ("Introduceti numarul natural= ");
InputStreamReader isrx = new InputStreamReader(System.in);
BufferedReader brx = new BufferedReader(isrx);
s = brx.readLine();
x = Integer.parseInt(s);
do
{
while (x !=0)
{

suma+=x%10; // adun la s ultima cifra a lui x
x/=10; //elimin ultima cifra a lui x
}
System.out.println ("Suma cifrelor numarului: " + suma);
x = suma; //actualizez numarul cu suma cifrelor sumei
suma = 0;
} while (x >9); // suma cifrelor sumei trebuie sa aiba o singura cifra
System.out.println("Cifra de control a numarului este: " + x);
}
}
Instructiunea for
Este folosita pentru efectuarea unor prelucrari de un anumit numar de ori.
Sintaxa instructiunii este:
for (<valoare_initiala>; <conditie_sfarsit>; <valoare_increment>)
<instructiune>;
Instructiunea for foloseste, de obicei, o variabila denumita variabila de control care indica de cate ori s –
a executat instructiunea (<instructiune>) din corpul ciclului. Instructiunea for contine patru sectiuni:
– sectiunea <valoare_initiala> atribuie variabilei de con trol o valoare initiala, care, de cele mai
multe ori, este 0 sau 1;
– sectiunea <conditie_sfarsit> testeaza valoarea variabilei de control pentru a stabili daca
programul a executat instructiunea de atatea ori cat s -a dorit;
– sectiunea < valoare_increment> adauga (scade), de obicei, valoarea 1 la variabila de control, de
fiecare data, dupa ce se executa instructiunea din corpul ciclului; valoarea de incrementare sau
decrementare poate fi diferita de 1;
– sectiunea <instructiune> reprezint a instructiunea (sau instructiunile) care se doreste (doresc) a
fi repetata (repetate).
Pentru intelegerea efectului instructiunii for , sa luam de exemplu urmatoarea instructiune for, care va
afisa pe ecran numerele de la 1 la 10:
for ( contor = 1; conto r <= 10; contor++)
System.out.println(contor);
In acest exemplu, contor este variabila de control a ciclului for. Instructiunea for se executa astfel:

– pasul 1: se atribuie valoarea 1 variabilei contor ;
– pasul2: se evalueaza conditia (de sfarsit a c iclului) contor <= 10 :
– pasul 3: – daca contor > 10 (valoarea conditiei este false ) se iese din
instructiunea repetitiva for;
– daca contor <= 10 (valoarea conditiei este true ):
– se executa instructiunea imediat urmatoare (din
corpul ciclu lui) care, in exemplul dat, este println ;
– se incrementeaza valoarea variabilei contor cu 1;
– se revine la pasul 2.
Nota:
1. Instructiunea for poate contine o secventa de instructiuni si atunci aceasta secventa se grupeaza intr –
o singura instructi une compusa (incadrata intre acolade).
2. Atat <valoare_initializare> cat si <valoare_increment> pot folosi operatorul virgula (,) pentru a
permite expresii multiple. Urmatorul fragment de cod ilustreaza aceasta tehnica:
for (i = 0, sum = 0; i <= n; i++, s um +=i)
{
System.out.println(i + “ \t” +sum);
}
3. Oricare dintre primele trei sectiuni care intervin in for poate sa fie omisa. Dar si in acest caz,
caracterul separator punct si virgula (;) trebuie sa apara; daca <conditie_sfarsit> lipseste valoarea sa
implicita este true .
4. Poate fi omisa si sectiunea de instructiuni din corpul ciclului (buclei) for, caz in care se spune ca avem
o bucla for vida.
Pentru a exemplifica instructiunea for, programul urmator (VocaleConsoaneRandom.java) creaza 10
litere aleat or si determina daca acestea sunt vocale sau consoane.
Metoda Math.random face parte din clasa Math care se gaseste in pachetul java.lang si este folosita in
program pentru a genera o valoare aleatoare in intervalul [0, 1). Prin inmultirea valorii returna te de
aceasta functie cu numarul de litere din alfabet (26 litere) se obtine un numar in intervalul [0, 26).
Adunarea cu prima litera (‘a’, care are de fapt valoarea 97, codul ASCII al literei ‘a’) are ca efect
transpunerea in intervalul [97, 123). In fina l se foloseste operatorul de conversie explicita de tip pentru a
trunchia numarul la o valoare din multimea 97, 98, …, 122, adica un cod ASCII al unui caracter din
alfabetul englez.
// Program demonstrativ pentru instructiunea For – vocale/consoane

public class VocaleConsoaneRandom
{
public static void main(String[] args)
{
for (int i = 0; i < 10; i++)
{
char c = (char) (Math.random() * 26 + 'a');
System.out.print(c + ": ");
switch(c)
{ case 'a': case 'e': case 'i': case 'o': case 'u':
System.out.println("vocala");
break;
case 'y': case 'w':
System.out.println("Uneori vocale ");
break;
default: System.out.println("consoana");
}
}
}
}
Instructi unile break si continue
Instructiunea break permite intreruperea instructiunilor care se repeta in corpul ciclului for, while sau
do-while . De obicei, instructiunea break apare in cadrul unei instructiuni if, ca in exemplul urmator:
while (…)
{

if (conditie)
{
break;

}

}
In cazul in care sunt doua cicluri imbricate, instructiunea break intrerupe doar ciclul cel mai interior.
Instructiunea breack etichetata este folosita cand sunt mai mult de doua cicluri imbricate. In acest caz, o
anumita instructiune de ciclare este etichetata si instructiunea breack poate fi aplicata acelei
instructiuni de ciclare, indiferent de numarul de cicluri imbricate.
Un exemplu:
eticheta:
while (…)
{
while (…)
{

if (conditie)
{
breack eticheta;
}
}
}
Instructiunea continue permite terminarea iteratiei curente din ciclu for, while sau do -while si trecerea
la urmatoarea iteratie a ciclului. Se aplica doar ciclului cel mai interior, in cazul ciclurilor imbricate.
Urmatorul fragment de cod tipareste primele 50 de numere intregi, cu exceptia celor divizibile cu 10:
for (int i=1; i<=50; i++)
{
if (i%10 == 0)
{
continue;
}
System.out.println(i);

}
Curs 3
Cuvinte importante:
– terminologia de baza pentru progrmarea orientata obiect: obiecte reale si reprezentarea lor
in calculator, proprietati (atribute) specifice, set de operatii specifice;
– programarea orientata obiect – gandire in termeni de obiecte: structura unui program
orientat obiect; clasa de obiecte, atributele clasei, comportamentul clasei (metode);
– despre obiecte si referinte in Java: variabile de tip referinta; operatii care se pot aplica
referintelor; declararea si crearea obiectelor; operatorul new; gestiunea memoriei si colectarea de
gunoaie (garbage collection); transmiterea de parametrii referinta la obiecte catre metodele unui
obiect;
– tipuri structurate de date – tablouri: declararea si crearea unui tablou unidimensional;
declararea si crearea unui tablou bidimensional; lungimea tablourilor; transmiterea de parametrii
tablou catre metodele unui obiect.
Terminologia de baza pentru programarea orientata obiect
Obiectele fizice din lumea reala sau n otiunile sunt reprezentate in memoria calculatorului in asa fel
incat informatiile specifice lor sa fie pastrate la un loc si sa se poata prelucra ca un tot unitar .
1. Pentru a reprezenta in memoria interna obiecte fizice sau notiuni, este necesar sa anal izam intergul
set de proprietati (atribute) specifice fiecaruia dintre acestea si sa il reprezentam prin numere intr -o
zona compacta de memorie.
Va trebui insa sa avem intodeauna o imagine clara a deosebirii fundamentale dintre un obiect fizic sau o
notiun e si reprezentarea acestora in memoria calculatorului. De exemplu, in memoria calculatorului este
simplu sa cream un nou obiect, identic cu altul deja existent, prin simpla duplicare a zonei de memorie
folosita de obiectul pe care dorim sa il duplicam. In realitate insa, este mult mai greu sa obtinem o copie
identica a unui obiect fizic.
2. Atunci cand analizam un obiect fizic sau o notiune pentru a le reprezenta in memoria calculatorului,
trebuie sa analizam, nu numai proprietatile fiecaruia dintre acestea dar, si setul de operatii specifice
care pot fi executate asupra lor sau cu ajutorul lor .
Setul de operatii specifice unui obiect real sau unei notiuni va fi reprezentat in memoria calculatorului
avand in vedere valorile care formeaza proprietatile obiec tului. Apoi, acest set de operatii va fi
descompus in operatii numerice predefinite in calculator.
De exemplu, dorim sa reprezentam in memoria calculatorului un obiect care sa descrie o minge de
forma sferica, de o anumita culoare si in spatiu.
Pentru acea sta reprezentare:

– vom defini o valoare pentru raza sferei, o valoare pentru culoarea mingii si 3 valori care sa reprezinte
coordonatele x, y si z relativ la un sistem de axe dat ; aceste valori numerice vor face parte din setul de
proprietati ale obiectul ui minge .
– vom defini operatiile specifice obiectului minge , cum ar fi: mutarea in spatiu a obiectului si umflarea
obiectului ; de exemplu, la definirea operatiei care reprezinta mutarea in spatiu a obiectului minge este
suficient sa folosim operatiile pr edefinite cu numere pentru a modifica valorile coordonatelor x, y, z.
In concluzie, din punct de vedere al programarii calculatoarelor, un obiect este o reprezentare in
memoria calculatorului:
– a proprietatilor, si
– a setului de operatii specifice un ui obiect real sau unei notiuni.
Observatie: Descriere proprietatilor si a setului de operatii specifice ale obiectului depind de problema
de rezolvat . In exemplul de mai sus, obiectul minge este insuficient descris si pentru a simula in
calculator obiectul real este nevoie de proprietati suplimentare cum ar fi: materialul din care este
confectionat mingea etc, precum si de multe operatii in plus, cum ar fi: aruncarea mingei, deformarea
ming ei etc.
Daca problema de rezolvat nu necesita anumite proprietati si operatii ale unui obiect real, este
preferabil sa nu le definim in obiectul folosit pentru reprezentarea in memoria calculatorului . Cu alte
cuvinte, vom defini acelasi obiect real in dif erite feluri pentru a -l reprezenta in memoria interna, in
functie de scopul probemei de rezolvat.
Programarea orientata obiect – gandire in termeni de obiecte
Programarea orientata obiect (OOP – Object Oriented Programming) este, in principiu, un mod de a
concepe un program. Ideea centrala a programarii orientate obiect este aceea de a organiza programele
in asa fel incat sa oglindeasca modul in care sunt organizate obiectele din lumea reala.
Astfel, un program este considerat de OOP ca un set de obiecte c are lucreaza impreuna intr -un mod
prestabilit, cu scopul de a indeplini o sarcina .
De exemplu, programarea orientata obiect seamana intr -un fel cu asamblarea unui PC. Intern, fiecare
din componentele calculatorului poate fi extrem de complexa, realizata de diferite firme care folosesc
diferite metode de proiectare. Totusi nu trebuie sa stim cum functioneaza fiecare dintre aceste
componente, ce rol are fiecare chip de pe placa etc. Fiecare componenta (obiect in OOP) este
independenta, iar noi care asamblam s istemul general suntem interesati doar de modul cum aceste
unitati interactioneaza:
– daca se va potrivi placa video in conectorul de pe placa de baza;
– daca va functiona monitorul impreuna cu acesta placa video;
– daca va sti fiecare componenta sa “di alogheze “ corect cu celelalte componente cu care
interactioneaza, astfel incat sa se inteleaga unele cu altele etc. Realizarea sistemului final devine usoara
odata ce cunoastem interactiunile dintre componente si putem sa le potrivim corect.
Cea mai impo rtanata dintre caracteristicile OOP o reprezinta clasa de obiecte .

O clasa este un model (un sablon) folosit pentru a crea mai multe obiecte inrudite care au aceleasi
caracteristici (proprietati si set de operatii specifice). Obiectele individuale create poarta denumirea de
instante ale clasei .
Un program, intr -un limbaj orientat obiect, defineste clase de obiecte folosite pentru a crea instante
(obiecte) ale acestor clase . Cu aceste instante se va lucra direct in program in functie de problema de
rezolva t.
De exemplu, fie clasa Femeie care descrie caracteristicile tuturor femeilor:
– inaltime;
– greutate;
– culoare ochi;
– culoare par;
– culoarea pielii;
– varsta;
– nume.
Clasa Femeie reprezinta un model abstract pentru conceptul de femeie. Pentru a reprezenta (in
memoria calculatorului), de fapt, un anumit obiect din clasa Femeie care sa poata fi utilizat direct intr –
un program, trebuie sa cream instanta concreta a clasei Femeie . O c lasa de obiecte nu poate fi utilizata
direct in program.
In figura de mai jos se prezinta clasa Femeie si mai multe obiecte (instante) create dupa acest model
abstract:

Atributele (proprietatile) unei clase de obiecte
Atributele sau proprietatile reprezinta caracteristici care diferentiaza o clasa de obiecte de o alta si care
descrie modul de prezentare si starea familiei de obiecte care formeaza clasa.
De exemplu, atributele unei clase ipotetice denumita Copil ar putea fi:
– culoare piele (alb, negru, galben etc);
Clasa Femeie
Regina Elisabeta
Regina Maria
Regina Margareta

– sex (barbatesc, femeiesc);
– starea de hrana (satul, flamand);
– dispozitie (cuminte, neastamparat).
Intr-o clasa, atributele sunt descrise de variabile (campurile) care stocheaza diferite valori particulare ale
atributelor. Le putem considera ca fiind echivalentul unor variabile globale pentru fiecare obiect al
clasei.
Variabilele care definesc atributele unei clase sunt de doua tipuri:
– variabile de i nstanta;
– variabile de clasa.
O variabila de instanta este o valoare, stocata in memoria calculatorului, care defineste un atribut al
unui anumit obiect. Clasa obiectului defineste ce fel de atribut este (spre exemplu: culoare piele) si
fiecare instanta isi pastreaza propria valoare pentru acel atribut (spre exemplu: alb) . Variabilele de
instanta mai sunt denumite si variabilele obiectului sau campurile obiectului .
Variabilele de instanta pot lua o singura valoare atunci cand se creaza un obiect care n u isi modifica
atributele pe toata durata lui de existenta sau poate lua diferite valori atunci cand obiectul este folosit
pe parcursul executiei programului.
O variabila de clasa este o valoare, stocata in memoria calculatorului, care defineste un atribut al unei
clase in ansamblul ei. Variabila se aplica clasei insesi si tuturor instantelor acesteia, deci pastreaza o
singura valoare, indiferent cate obiecte ale clasei au fost create.
De exemplu, o variabila de clasa este variabila care pastreaza numarul d e obiecte Copil ce traiesc intr -o
comunitate. In acesata variabila de clasa este pastrata o singura valoare si fiecare obiect Copil poate
accesa aceasta variabila.
Comportanentul unei clase de obiecte
Comportamentul unei clase de obiecte este dat de ansamb lul operatiilor definite pentru acea clasa.
Comportamentul unei clase descrie ce obiecte ale clasei isi modifica atributele, precum si ce fac
obiectele clasei atunci cand alte obiecte le cer sa faca ceva.
De exemplu, comportamentul unui obiect Copil ar put ea fi:
– mananca lapte;
– sare din pat;
– se odihneste etc
Comportamentul unei clase de obiecte este descris cu ajutorul metodelor.
Metodele sunt grupuri de instructiuni dintr -o clasa de obiecte (instructiuni scrise intr -un limbaj de
programare) care actioneaza asupra acestei clase de obiecte sau asupra altor clase sau obiecte. Ele sunt

folosite pentru a realiza diferite operatii (sarcini) in acelasi fel in care in alte limbaje de programare se
folosesc functiile.
Obiectele comunica unele cu altele fol osind metodele . O clasa sau un obiect poate apela metode dintr -o
alta clasa sau obiect pentru mai multe motive, cum ar fi:
– pentru a raporta o modificare de atribute unui alt obiect;
– pentru a comunica altui obiect sa modifice ceva in legatura cu el;
– pentru a cere unui alt obiect sa faca ceva.
De asemenea, metodele unei clase sunt intodeauna aceleasi dar rezultatul aplicarii lor poate sa difere in
functie de:
– valorile variabilelor obiectului asupra caruia au fost aplicate;
– unele valori exterioar e obiectului denumite parametrii metodei .
Observatie : Nu are nici un rost sa transmitem ca parametrii ai unei metode valorile variabilelor unui
obiect pentru ca acestea sunt intodeauna disponibile metodei.
Metodele care descriu comportamentul unei clase su nt de doua tipuri:
– metode de instanta;
– metode de clasa.
Metodele de instanta sunt aplicate doar asupra unui obiect al clasei. O metoda de instanta efectueaza
schimbari doar asupra unui obiect individual.
Metodele de clasa sunt aplicate unei clase in ansamblul ei si nu instantelor sale. Metodele de clasa sunt
utilizate de obicei drept metode de uz general, care nu pot opera direct asupra unei instante a clasei, dar
se potrivesc conceptual in cadrul clasei. De exemplu, clasa Math , definita in pachetul java.lang contine
un set larg de operatii matematice definite ca metode de clasa. Nu exista instante ale clasei Math .
Vom reveni cu amanunte despre variabilele si metodele unei clase de obiecte intr -o lectie viitoare.
Despre obiecte si referinte in Java
In primele lectii am descris cele opt tipuri primitive de date din limbajul Java impreuna cu operatiile care
pot fi realizate pe variabile avand aceste tipuri. Toate celelalte tipuri de date din Java sunt referinte.
O variabila referinta in Java (numita sim plu referinta) este o variabila care pastreaza adresa de memorie
la care se afla un anumit obiect.
Nota: Exista o exceptie, in situatia in care o referinta nu puncteaza catre nici un obiect. In acest caz
referinta va stoca valoarea null. Valoarea null reprezinta valoarea implicita atribuita automat oricarei
variabile de tip referinta care nu a fost initializata. Limbajul Java nu permite referinte catre tipurile
primitive (cum ar fi int sau float ).
Categorii de operatii care se pot aplica variabilelor refer inta

1. Prima categorie de operatii, cu variabile referinta, permite examinarea si manipularea valorii
referinta. In Java, singurele operatii care sunt permise asupra referintelor (cu o singura exceptie pentru
String -uri) sunt atribuirea prin intermediul o peratorului = si comparatia prin intermediul operatorilor ==
si !=.
De exemplu, prin atribuirea nr2 = nr1 vom face ca nr2 sa refere acelasi obiect pe care il refera nr1, iar
expresia nr1 == nr2 este adevarata, deoarece ambele referinte stocheaza aceeasi valoare a adresei de
memorie la care se afla obiectul referit.
Observatie : Alte limbaje de programare, cum ar fi C, definesc notiunea de pointer care este similar cu
cel al unei variabile referin ta. In limbajul C este permisa aritmetica pointerilor, pe cand in Java aceasta
nu este permisa.
2. A doua categorie de operatii, cu variabile referinta, se aplica obiectului care este referit. Exista trei
actiuni fundamentale care pot fi realizate:
– aplicarea unei conversii explicite de tip;
– accesul la o variabila a obiectului sau apelul unei metode prin operatorul punct ( .);
– verificarea daca obiectul referit are un anumit tip cu ajutorul operatorului instanceof .
In Java, un obiect este orice variabil a care nu este de tip primitiv . Variabilele obiect sunt manipulate prin
referinte, spre deosebire de variabilele de tipuri primitive care sunt manipulate prin valoare.
Obiectul in sine este stocat undeva in memorie, iar variabila referinta stocheaza adres a de memorie a
obiectului.Astfel, variabila referinta devine un nume pentru acea zona de memorie.
Operatorul punct (.)
Este folosit pentru a apela o metoda care se aplica unui obiect. De exemplu, sa presupunem ca avem un
obiect ce apartine clasei Cerc ( adica de tip Cerc ) care defineste metoda arie. Daca variabila cerculMeu
este o referinta catre un obiect de tip Cerc , atunci putem calcula aria cercului referit prin apelul metodei
arie astfel:
Double arieCerc = cerculMeu.arie();
In terminologia OOP, at unci cand apelam o metoda a obiectului spunem ca “trimitem un mesaj”
obiectului.
Operatorul punct poate fi folosit si pentru a accesa atributele individuale ale unui obiect, daca cel care a
proiectat obiectul permite acest lucu.
Declararea si crearea obiec telor
Declararea si crearea (initializarea) obiectelor se realizeaza in doi pasi de catre compilatorul Java:
1. Se declara o variabila referinta la obiect (instanta a unei clase). Prin declaratia unei referinte se aloca
zona de memorie necesara stocarii re ferintei in sine (adica a unei adrese de memorie). In consecinta,
dupa ce se declara o variabila referinta, aceasta va contine valoarea null, ceea ce inseamna ca referinta
inca nu indica o instanta valida.

Sintaxa folosita pentru declararea unei variabile referinta catre un obiect este:
<nume_clasa> <nume_obiect>;
unde:
– <nume_clasa> – reprezinta numele clasei dupa modelul careia se doreste crearea unei instante;
– <nume_obiect> – reprezinta numele unei variabile referinta la un obiect oarecare de tipul
<nume_clasa>; acesta variabila referinta la un obiect contine valoarea null.
2. Se aloca, efectiv, zona de memorie pentru obiectul declarat la pasul 1si se initializeaza obiectul cu
ajutorul operatorului new . In acest fel, se creaza o noua instana a clasei date.
Sintaxa folosita pentru alocarea memoriei si crearea efectiva a unei instante a clasei este:
<nume_obiect> = new <nume_constructor>(); sau
<nume_obiect> = new <nume_constructor>(arg1, arg2, …);
unde:
– <nume_obiect> – reprezinta numele variabilei r eferinta declarata la pasul 1;
– <nume_constructor>() sau <nume_constructor>(arg1, arg2, …) – metoda speciala a clasei obiectului,
numita constructor, care are acelasi nume cu cel al clasei obiectului urmat de paranteze rotunde goale
sau care pot contine a rgumente; numarul si tipul argumentelor folosite sunt definite de clasa de obiecte.
Nota : Parantezele rotunde plasate dupa <nume_constructor> sunt importante si ele nu trebuie omise
chiar daca sunt fara argumente.
Daca se foloseste prima forma a operatorul ui new , in care constructorul este urmat de paranteze goale,
este creat un obiect simplu fara a se initializa anumite valori ale variabilelor de instanta; de regula acest
tip de constructor este implicit.
Daca se foloseste a doua forma a operatorului new , in care constructorul este urmat de paranteze care
contin argumente, atunci aceste argumente determina valorile initiale ale variabilelor de instanta sau ale
altor variabile folosite de obiectul astfel creat.
Nota: De cele mai multe ori programatorii combi na declararea si crearea efectiva a obiectului intr -o
singura instructiune, astfel:
<nume_clasa> <nume_obiect> = new <nume_constructor>(); sau
<nume_clasa> <nume_obiect> = new <nume_constructor>(arg1, arg2, …);
Iata cateva exemple in care constructorul este folosit fara argumente:
1.
Random nrAleatoare;
nrAleatoare = new Random();

sau
Random nrAleatoare = new Random();
2.
Copil c;
c = new Copil();
sau
Copil c = new Copil();
Urmatoarele exemple prezinta modalitati de crearea a unor obiecte cu anumite valori initiale, adica
folosind argumente in metoda speciala numita constructor :
1.
Punct pt = new Punct(0,0);
Obiectul de tip Punct cu numele pt este construit cu doua argumente pentru coordonatele initiale ale
punctului.
2.
Cerc cerculMeu = new Cerc (0, 0, 10);
Obiectul de tip Cerc cu numele cerculMeu este construit cu trei argumente, doua pentru coordonatele
initiale ale centrului si unul pentru lungimea razei.
Un alt exemplu de creare a mai multor tipuri de obiecte care folosesc diferite tipuri de argumente
impreuna cu operatorul new si metoda speciala a clasei numita constructor :
clasa Random , care face parte din pachetul java.util , creaza obiecte folosite pentru generarea de
numere aleatoare intr -un program. Aceste obiecte sunt numite generatoare de numere aleatoare si au
valori cuprinse in intervalul [0, 1).
De fapt, un obiect de tip Random extrage un numar dintr -o multime foarte mare de numere. Aceasta
tehnica este denumita generare de numere pseudo -aleatoare si este folosita in diferite limbaje de
programare.
Pentru a extrage un numar diferit din secventa de numere aleatoare, obiectul de tip Random trebuie sa
primeasca o valoare initiala denumita “samanta” (“seed”). Aceasta “samanta” poate fi transmisa
obiectului la construirea sa.
Programul urmator (NrAleator.java) creaza obiecte de tip Random folosind operatorul new in doua
moduri cu si fara argumente ale constructorului .
import java.io.*;
import java.util.*;
class NrAleato r

{
public static void main(String args[])
{
Random r1, r2;
r1 = new Random();
System.out.println("Valoarea aleatoare 1: " + r1.nextDouble());
// valoarea afisata se schimba
int numar1 = (int) (r1.nextDouble() * 11);
System.out.println("Intreg aleator 1 in intervalul 0 si 10: " + numar1);
r2 = new Random(8600000);
System.out.println("Valoarea aleatoare 2: " + r2.nextDouble());
// valoarea afisata nu se schimba
int numar2 = (int) (r2.nextDouble() * 11);
System.out.println("Intreg aleator 2 in intervalul 0 si 10: " + numar2);
}
}
Dupa executia programului, pe ecranul calculatorului se afiseaza:
Valoarea aleatoare 1: 0.6053135148135541
Intreg aleator 1 in intervalul 0 si 10: 9
Valoarea aleatoare 2: 0.7258826590374842
Intreg aleator 2 in intervalul 0 si 10: 9
In acest exemplu doua obiecte Random diferite sunt create folosind argumente diferite pentr u
constructorul clasei Random introdus dupa operatorul new .
Primul obiect, cu numele r1, a fost creat cu new Random() fara argumente, deci acest obiect are ca
“samanta” ceasul calculatorului (ora curenta).
Apelarea metodei nextDouble() a obiectului de ti p Random produce extragerea urmatoarei valori din
secventa de numere pseudo -aleatoare.
Valoarea obtinuta prin folosirea metodei nextDouble() difera de la o executie la alta a programului.
Al doilea obiect, cu numele r2, a fost creat cu new Random(8600000) deci, cu un argument dat de un
numar intreg. De aceea, numarul aleator obtinut prin folosirea metodei nextDouble() ramane

intotdeauna acelasi, indiferent de cate ori se executa programul. Acest lucru poate fi folositor pentru
crearea unor date de test pen tru programe.
Nota: In programul de mai sus s -au mai introdus doua instructiuni care inmultesc un numar aleator cu
11 si stocheaza produsul ca intreg:
int numar1 = (int) (r1.nextDouble() * 11);
int numar2 = (int) (r2.nextDouble() * 11);
Intregul continut d e variabilele numar1 si numar2 va fi un numar aleator cuprins intre 0 si 10.
Rolul operatorului new
La folosirea operatorului new se executa urmatoarele:
– se creaza o noua instanta a clasei date;
– se aloca memorie pentru aceasta instanta;
– se apeleaza o metoda speciala a clasei numita constructor .
Constructorii reprezinta metode speciale pentru crearea si initializarea noilor instante ale claselor.
Constructorii initializeaza noul obiect si variabilele sale, creaza orice alte obiecte de care are nevoie
obiectul creat si realizeaza orice alte operatii de care obiectul are nevoie la initializarea sa.
Intr-o clasa pot exista mai multe definitii de constructori , fiec are avand un numar diferit de argumente
sau de tipuri.
Cand se foloseste operatorul new , se pot specifica diferite argumente in lista de argumente si va fi
apelat constructorul corespunzator pentru acele argumente.
Intr-o clasa pot fi definiti oricati co nstructori se doresc pentru a implementa comportamentul clasei.
Detalii despre modul de lucru cu constructorii unei clase vom prezenta intr -o lectie viitoare. Sa retinem
ca ei pot fi impliciti sau creati explicit intr -o clasa.
Gestiunea memoriei si colect area de gunoaie (garbage collection)
Gestiunea memoriei in Java se face dinamic si automat . Atunci cand se creaza un obiect nou, Java aloca
automat o zona de memorie de dimensiunea corespunzatoare obiectului. Nu trebuie sa se aloce explicit
memorie pentru obiecte.
Deoarece gestiunea memoriei in Java se face automat, nu este nevoie sa dezalocam explicit memoria
ocupata de obiect atunci cand am terminat de lucru cu aceasta. In Java cand un obiect din memorie nu
mai este referit de nici o variabila, memoria pe care o consuma va fi eliberata automat . Aceasta tehnica
se numeste colectare de gunoaie .
Interpretarea operatorului de atribuire (=) pentru referinte
Daca x si y sunt referinte (de tipuri compatibile) atunci instructiunea
x = y

inseamna ca valoarea adr esei stocata in y este transferata in variabila referinta x. Rezuta ca, dupa
operatia de atribuire, x va referi acelasi obiect ca si y. Ceea ce se copiaza in acest caz sunt adrese.
Obiectul pe care x il referea inainte de operatia de atribuire nu mai este referit de x dupa operatia de
atribuire. Daca x a fost singura referinta catre acel obiect, atunci obiectul respectiv nu mai este referit de
nici o variabila si este disponibil pentru colectarea de gunoaie.
Nota: Sa retinem faptul ca, obiectele nu se copi aza prin operatorul de atribuire (=).
De exemplu, secventa de instructiuni de mai jos:
Cerc cerc1 = new Cerc (0,0,10); // un cerc de raza 10
Cerc cerc2 = cerc1;
ne spune ca s -a construit un singur obiect de tip Cerc , cu numele cerc1 (prima instruc tiune) si ca cerc2
este un alt nume dat pentru cerc1 (a doua instructiune).
Pentru a putea fi copiate obiecte se foloseste metoda clone() . Aceasta metoda va fi explicata intr -o
lectie viitoare.

Transmiterea de parametrii referinta la obiecte catre metode le unui obiect
In Java transmiterea parametrilor se face prin valoare . Datorita acestui fapt, parametrii actuali (de apel)
se transpun in parametrii formali, din definitia metodei, folosind atribuirea obisnuita.
Daca parametrul transmis este un tip referi nta, atunci se stie deja ca, prin atribuire, atat parametrul
formal, cat si parametrul de apel vor referi acelasi obiect. Orice metoda aplicata obiectului referit prin
parametrul formal este, implicit, aplicata si obiectului referit prin parametrul de apel .
De exemplu, sa presupunem ca dorim sa modificam raza unui cerc folosind o metoda denumita
modifica() . Secventa de cod care apeleaza metoda modifica() este:
int v = 4;
Cerc cerc = new Cerc();
modifica(cerc, v);
Metoda modifica() de mai jos primeste ca pa rametri o referinta la un obiect de tip Cerc si o valoare
intreaga:
public void modifica (Cerc cerculMeu, int val)
{
cerculMeu.setRaza (val); //modifica raza obiectului apelant
val += 4; //nu are nici un efect asupra parametrului actual
}

Observatie: Metoda setRaza() modifica raza unui cerc oarecare si codul -sursa al acesteia nu este necesar
a fi prezentat in acest context.
Secventa de cod care apeleaza metoda modifica() va avea ca efect modificarea razei obiectului cerc la
4,deoarece atat variabila referinta cerc cat si variabila referinta cerculMeu indica acelasi obiect, dar
valoarea lui v va ramane nemodificata.
Interpretarea operatorului de egalitate (==) pentru referinte
Doua variabile referinta sunt egale via == daca ele refera acelasi obiect (sau ambele sunt valori null).
De exemplu:
Cerc cerc1 = new Cerc(0, 0, 15) //un cerc de raza 15;
Cerc cerc2 = new Cerc(0, 0, 15) //un cerc de raza 15;
Cerc cerc3 = cerc2;
In acest caz avem doua obiecte: un obiect cu numele cerc1 si un obiect cu doua nume cerc2 si cerc3 .
Expresia cerc2 == cerc3 este adevarata.
Expresia cerc1 == cerc2 este falsa, desi variabila cerc1 si variabila cerc2 refera obiecte care au valori
egale (ambele sunt cercuri cu centrul in origine si raza 15).
Nota: Pentru a verifica faptul ca un obiect (de exemplu, obiectul cu numele cerc1 ) este identic cu un alt
obiect (de exemplu, obiectul cu numele cerc2 ) se foloseste metoda equals() care va fi descrisa cand vom
prezenta tipul String .
Un exemplu simplu de aplic atie Java care foloseste variabile si metode de instanta
Programul urmator (Copil.java) ilustreaza cum sunt definite variabilele si metodele de instanta intr -o
clasa numita Copil , cum este folosit operatorul new pentru crearea unei instante a clase Copil cu numele
c si cum sunt apelate metodele de instanta in cadrul aplicatiei.
Variabilele de instanta sunt definite astfel:
String culoare_piele;
String sex;
boolean flamand;
Doua dintre variabile care desemneaza culoarea pielii si sexul contin obiecte de tip String (sir). Un obiect
String in Java este creat folosind una din clasele standard din biblioteca de clase Java. Clasa String este
folosita pentru pastrarea textului si pentru diferite functii de manipulare a textului.Vom reveni la clasa
String intr-o lectie viitoare.
A treia variabila desemneaza starea de flamand a copilului si pastreaza doua valori: true (pentru
flamand) si false (pentru hranit).

Comportamentul clasei Copil poate fi dat de o multitudine de metode care sa descrie actiuni pe care le –
ar putea face un copil (se hraneste, se joaca, se imbraca etc).
Totusi, in program sunt definite doar doua metode: una pentru a hrani copilul (denumita hranescCopil )
si una pentru a verifica si afisa atributele (proprietatile) copilului (denumita afisezAtribu teCopil ).
Iata codul -sursa al aplicatiei:
class Copil
{
String culoare_piele;
String sex;
boolean flamand;
void hranescCopil()
{
if (flamand==true)
{System.out.println("Bun – lapte");
flamand = false;}
else
System.out.println("Nu, multumesc – am mancat deja");
}
void afisezAtributeCopil()
{
System.out.println("Acesta este un copil de sex " + sex + " si " +
culoare_piele + " .");
if (flamand == true)
System.out.println("Co pilul este flamand.");
else
System.out.println("Copilul este satul");
}
public static void main(String args[])
{

Copil c = new Copil();
c.culoare_piele = "alb";
c.sex = "masculin";
c.flamand = true;
System.ou t.println("Atribute copil");
c.afisezAtributeCopil();
System.out.println("Hranesc copilul");
c.hranescCopil();
System.out.println("Atribute copil");
c.afisezAtributeCopil();
System.out.println("Hranesc copilul");
c.hranescCopil();
}
}
Tipuri structurate de date: tablouri
Un tablou este o structura de date care poate sa pastreze mai multe valori de acelasi tip (primitiv sau
referinta), memorate intr-o zona de memorie contigua si reunite sub un nume simbolic comun (numele
tabloului).
Un tablou poate fi:
– unidimensional sau vector;
– bidimensional sau matrice;
– multidimensional.
In Java, un tablou este tratat ca un obiect, deci el este un tip referinta.
Declararea si crearea unui tablou unidimensional
Declarar ea si crearea tablourilor unidimensionale se realizeaza in doi pasi de catre compilatorul Java:
1. Se declara o variabila referinta la tablou de un anumit tip (primitiv sau referinta). Prin declaratia unei
referinte se aloca zona de memorie necesara stocar ii referintei in sine (adica a unei adrese de memorie).
In consecinta, dupa ce se declara o variabila referinta la un tablou, aceasta va contine valoarea null, ceea
ce inseamna ca referinta inca nu indica un tablou valid.
Sintaxa folosita pentru declarare a unei variabile referinta catre un tablou unidimensional este:

<tip> <nume_tablou> [];
sau
<tip> [] <nume_tablou>;
unde:
– <tip> – specifica tipul de date primitiv sau tipul de obiecte (dat de clasa) al elementelor tabloului;
– <nume_tablou> – reprezinta numele unei variabile referinta la tabloul de tipul <tip>; acesta variabila
referinta la un tablou contine valoarea null.
Nota : parantezele drepte sunt obligatorii, nu delimiteaza o constructie optionala
2. Se aloca, efectiv, zona de memorie pentru tablou l declarat la pasul 1si se initializeaza tabloul. Exista
doua modalitati pentru a face acest lucu:
a) folosind operatorul new ;
b) initializand direct continutul tabloului.
a) Sintaxa folosita pentru alocarea zonei de memorie a unui tablou unidimensional folosind operatorul
new este:
<nume_tablou> = new <tip> [<nr_elem>];
unde:
– <nume_tablou> – reprezinta numele variabilei referinta declarata la pasul 1;
– <tip> – specifica tipul de date primitiv sau tipul de obiecte (dat de clasa) al elementelor tabloul ui;
– <nr_elem> – reprezinta numarul de elemente ale tabloului; poate fi o variabila de un tip primitiv, o
expresie de un tip primitiv sau o constanta de un tip primitiv.
Nota:
1. De cele mai multe ori programatorii combina declararea si alocarea zonei d e memorie pentru un
tablou intr -o singura instructiune, astfel:
<tip> <nume_tablou> [] = new <tip> [<nr_elem>]; sau
<tip> [] <nume_tablou> = new <tip> [<nr_elem>];
2. La crearea unui tablou folosind operatorul new , toate elementele sale vor fi initializa te automat (cu 0
pentru cele numerice, cu false pentru boolean, cu ‘\0’ pentru tablouri tip caracter si cu null pentru
obiecte).
De exemplu, pentru declararea si alocarea zonei de memorie pentru un tablou unidimensional cu
numele temp de tipul int cu 100 d e elemente se foloseste instructiunea:
int [] temp = new int[100];

b) Alocarea zonei de memorie pentru tablou se poate face initializand direct continutul tabloului (la fel
ca in limbajul C/C++), dupa urmatoarea sintaxa :
<tip> [] <nume_tablou>;
<nume_tablo u> = {<valoare1>, <valoare2>, ….}; sau
<tip> [] <nume_tablou> = {<valoare1>, <valoare2>, ….};
unde:
– <valoare1>, <valoare2>, …. – reprezinta valorile de initializare al caror numar determina si numarul de
elemente ale tabloului.
De exemplu, pentru decla rea si alocarea zonei de memorie pentru un tablou unidimensional cu numele
temp de tip int cu patru elemente se foloseste instructiunea:
int [] temp = {3, 4, 6, 19};
Declararea si alocarea zonei de memorie pentru un tablou unidimensional de obiecte (deci nu tipuri
primitive) foloseste aceeasi sintaxa.
Trebuie retinut insa ca dupa alocarea zonei de memorie pentru tabloul de referinte la obiectele
respective, fiecare element (de tip referinta) din tablou va avea valoarea null.
Apoi, pentru fiecare element -tip referinta din tablou trebuie alocata memorie, separat, corespunzatoare
fiecarui obiect referit. Aceasta se intampla, deoarece un tablou de obiecte in Java este un tablou de
referinte la obiectele respective.
De exemplu, pentru declararea si alocarea memoriei pentru un tablou de tip Cerc cu numele
tablouDeCercuri care are ca elemente 5 obiecte (instante) se foloseste urmatoarea secventa de
instructiuni:
Cerc [] tablouDeCercuri; // declaram un tablou de referinte de tip Cerc
tablouDeCercuri = new Cerc[ 5]; //alocam memorie pentru 5 referinte
la obiecte de tip Cerc
for (int i = 0; i < 5; i++)
{
tablouDeCercuri[i] = new Cerc(); // se aloca memorie pentru un obiect
de tip Cerc in elementul i al tabloului cu numele tablouDeCercuri
}
Lungimea tablourilor unidimensionale
Tablourile Java sunt alocate dinamic, ceeace inseamna ca ele isi pot schimba dimensiunile pe parcursul
executiei programului. Numarul de elemente care pot fi stocate intr -un tablou oarecare, este permanent
retinut in variabila <nume_tablou> .length .

De exemplu:
float [] tablou = new float [25];
int dimensiune = tablou.length; // dimensiune primeste valoarea 25.
Accesarea (identificarea) unui element al tabloului unidimensional
Deoarece elementele unui tablou sunt memorate in ordine, unul dupa altul, intr -o zona contigua, pentru
a accesa (sau a referi) un element al unui tablou se specifica numele tabloului din care face parte
elementul si pozitia sa in tablou , prin numarul sau d e ordine (numerotarea incepe de la 0), astfel:
<nume_tablou>[<indice>]
in care:
– <indice> reprezinta numarul de ordine al elementului in tablou, cuprins intre 0 si <nr_elemente> – 1;
parantezele patrate ([]) constituie operatorul de indexare.
Exemplu:
int punctaje[5];
elementele tabloului sunt: punctaje[0], punctaje[1], punctaje[2], …. punctaje[4].
Nota: Toate pozitiile unui tablou sunt verificate, de interpretorul Java, daca se incadreaza in limitele
tabloului asa cum s -au specificat la crearea tablou lui. In Java este imposibil sa se acceseze sau sa se
atriubuie o valoare unei pozitii a tabloului aflata in afara granitelor acestuia.
Pentru a se evita, in programe, depasirea accidentala a sfarsitului tabloului se testeaza lungimea
acestuia prin folosir ea variabilei de instanta length .
O parcurgere a unui tablou unidimensional se face cu ajutorul instructiunii for astfel:
for (int i = 0 ; i< numere.length; i++)
numere[i] = i;
Observatie: Dat fiind ca tabloul este un tip referinta, operatorul de atribuir e (=) nu copiaza tablouri. De
aceea, daca x si y sunt tablouri, efectul secventei de instructiuni:
int [] x = new int [50];
int [] y = new int [50];

x = y;
este ca x si y refera acum al doilea tablou cu numele y.
Tablourile bidimensionale in Java sunt tablouri unidimensionale de referinte catre tablouri
unidimensionale (adica, sunt tablouri de referinte la tablouri unidimensionale).
Declararea si crearea tablourilor bidimensionale se realizeaza tot in doi pasi:

1. declararea tabloului de un anumit tip (primitiv sau referinta);
2. alocarea zonei de memorie pentru tabloul declarat si initializarea lui.
1. Sintaxa folosita pentru declararea unei variabile referinta catre un tablou bidimensional este:
<tip> <nume_tablou> [][];
sau
<tip> [] [] <nume_tablou>;
sau
<tip> [] <nume_tablou> [];
unde:
– <tip> – specifica tipul de date primitiv sau tipul de obiecte (dat de clasa) al elementelor tabloului;
– <nume_tablou> – reprezinta numele unei variabile referinta la tabloul de tipul <tip>; acesta v ariabila
referinta la un tablou bidimensional contine valoarea null, la fel ca si variabila referinta
<nume_tablou>[i] care contine valoarea null pentu referinta la linia i a tabloului.
Nota : parantezele drepte sunt obligatorii, nu delimiteaza o constructi e optionala.

2. Alocarea zonei de memorie pentru tabloul declarat si initializarea lui se face in doua feluri ca si la
tablourile unidimensionale:
a) folosind operatorul new ;
b) initializand direct continutul tabloului.
a) Sintaxa folosita pentru alocar ea zonei de memorie unui tablou bidimensional folosind operatorul
new este:
<nume_tablou> = new <tip> [<nr_linii>][<nr_coloane>];
unde:
– <nume_tablou> – reprezinta numele variabilei referinta declarata la pasul 1;
– <tip> – specifica tipul de date primiti v sau tipul de obiecte (dat de clasa) al elementelor tabloului;
– <nr_linii> – reprezinta numarul de linii ale tabloului; poate fi o variabila de un tip primitiv, o expresie de
un tip primitiv sau o constanta de un tip primitiv;
– <nr_coloane> – reprezinta numarul de coloane ale tabloului; poate fi o variabila de un tip primitiv, o
expresie de un tip primitiv sau o constanta de un tip primitiv.

Nota: De cele mai multe ori programatorii combina declararea si alocarea zonei de memorie pentru un
tablou intr -o singura instructiune, astfel:
<tip> <nume_tablou> [][] = new <tip> [<nr_linii>][<nr_coloane>]; sau
<tip> [][] <nume_tablou> = new <tip> [<nr_linii>][<nr_coloane>];
De exemplu, urmatoarea instructiune de declarare si alocare de memorie pentru un tablou
bidimensional de caractere:
char [][] caractere = new char [5][];

Variabila referinta numita caractere contine deocamdata un tablou de 5 referinte la tablouri de
caractere. Cele cinci referinte sunt initializate impl icit la valoarea null. Putem aloca cele 5 tablouri de
caractere folosind operatorul new astfel:
caractere[0] = new char [3];

caractere[4] = new char[5];
Noile tablouri sunt referite din interiorul tabloului original. Elementele noilor tablouri sunt caractere.
La fel, putem scrie:
char [] tablouDeCaractere = caractere[0];
Variabilele de tip referinta caractere[0] si tablouDeCaractere trimit spre acelasi tablou de caractere
rezervat in memorie.
Un alt exemplu se refera la declararea si alocarea zonei de memorie pentru un tablou bidimensional cu
numele temp de tipul int cu 100 de elemente pe linie si 100 de elemente pe coloane:
int [][] temp = new int[100] [100];
b) Alocarea zonei de memorie pentru un tablou bidimensional se poate face initializand dire ct
continutul tabloului (la fel ca in limbajul C/C++).
De exemplu, pentru declarea si alocarea zonei de memorie pentru un tablou bidimensional cu numele b
de tip int cu doua linii si trei coloane se foloseste instructiunea:
int b[][]={{1, 2, 3}, {7, 8, 9} };
Eliberarea memoriei ocupate de un tablou
Tabloul de referinte
caractere

Pentru eliberarea memoriei ocupate de un tablou, este suficient sa anulam toate referintele catre
tablou. Interpretorul Java va sesiza automat ca tabloul nu mai este referit si mecanismul de colectare de
gunoaie va elibera zona. Pentru a anula o referinta catre un tablou se da o alta valoare variabilei care
refera tabloul. Valoarea poate fi null sau o referinta catre un alt tablou.
Lungimea tablourilor bidimensionale
Numarul de linii care pot fi stocate intr -un tablou bidimensional oarecare, este permanent retinut in
variabila <nume_tablou> .length , iar numarul de coloane ale fiecarei linii i este pernament retinut in
variabila <nume_tablou>[i] .length
De exemplu:
float [][] matrice = new float [3][4];
int dimensiune1 = matrice.length; // dimensiune1 stocheaz a valoarea 3
int dimensiune2 = matrice[1].length; // dimensiune2 stocheaza valoarea 4 pentru
linia 1
Accesarea (identificarea) unui element al tabloului bidimensional
Pentru a accesa un element al unei matrice se specifica numele matricei din care face parte elementul si
pozitia sa in matrice, prin numarul liniei si numarul coloanei corespunzatoare (numerotarea incepe de la
linia 0 si coloana 0), astfel:
<nume_tablou>[<indice_linie>] [<indice_coloana]
Nota: Parantezele patrate reprezinta operat orul de indexare.
Exemplu:
int a[4][3];
elementele tabloului sunt: a[0][0], a[0][1], a[0][2], a[1][1], a[1][2], …, a[3][2].
O parcurgere a unui tablou bidimensional se face cu ajutorul instructiunii for astfel:
for (int i = 0 ; i < matrice.length; i++)
for (int j = 0; j < matrice[i].length; j++)
matrice[i][j] = j;
Transmiterea de parametrii tablou catre metodele unui obiect
Sa presupunem, ca avem o metoda numita functie care are ca parametru un tablou unidimensional de
tip int. Apelul si definitia met odei arata astfel:
functie(tablouActual); //apelul metodei
void functie(int [] tablouFormal); //declaratia metodei

Conform conventiilor de transmitere a parametrilor in Java pentru tipurile referinta, variabilele
tablouActual si tablouFormal refera acela si obiect -tablou. Adica, la transmiterea parametrului se copiaza
valoarea lui tablouActual , care este o adresa. Astfel, accesul metodei la elementul tablouFormal[i] este
de fapt un acces la elementul tablouActual[i] . Aceasta inseamna ca valorile continute in tablou pot fi
modificate de catre metoda.
Observatie: Deoarece tablourilor sunt de tip referinta, o metoda poate sa returneze un tablou.
Prelucrari elementare pe tablouri
Programul urmator (loto.java) ilustreaza modul de folosire al tablourilor in Java. In jocul de loterie, se
selecteaza saptamanal sase numere de la 1 la 49. Programul alege aleator numere pentru 1000 de jocuri
si afiseaza apoi de cate ori a aparut fiecare numar in cele 1000 de jocuri.
public class Loto
{
public static void main(String[] args)
{
int[] numere = new int[50];
for (int i = 0; i < numere.length; ++i)
numere[i] = 0;
for (int i = 0; i < 1000; ++i)
for (int j = 0 ; j < 6; ++j)
//genereaza numere de loterie in tre 1 si 49
//numara aparitiile de numere pe joc
numere[(int) (Math.random() * 49) +1]++ ;
for (int k = 1; k <= 49; ++k)
System.out.println(k + ": " + numere[k]);
}
}
Programul urma tor (prelMatrice.java) arata cum se creaza o matrice si cum se pot accesa elementele ei.
import java.io.*;
class PrelMatrice
{
public static void main(String[] args) throws IOException

{
BufferedReader br1 = new BufferedReader(new InputStreamReader(Syst em.in));
System.out.println ("Introduceti numarul de linii");
String s1 = br1.readLine();
System.out.println ("Introduceti numarul de coloane");
String s2 = br1.readLine();
int n = Integer.parseInt(s1);
int m = Integer.parseInt(s2);
int [][] matrice = new int [n][m];
for (int i = 0; i<n; i++)
{ System.out.println();
for (int j = 0; j<m; j++)
System.out.print(matrice[i][j]);
}
}
}
Curs 4
Cuvinte importante:
-siruri de caractere ( String -uri): reguli de folosire; crearea de noi obiecte de tip String folosind
constructorii clasei String ;
– concatenarea sirurilor de caractere; compararea sirurilor de caractere; metode folosite;
– extragerea de caractere sau subsiruri dintr -un sir; cautare a unor aparitii de subsiruri intr -un
sir; metode folosite;
– inlocuirea aparitiilor unui caracter sau unui subsir dintr -un sir cu un alt caracter sau subsir;
eliminarea caracterelor albe de la inceputul si sfarsitul unui sir de caractere; metode folosite;
– clase înfășurătoare pentru tipurile primitive de date ; conversii intre siruri de caractere
(String) si alte tipuri de date primitive; metode folosite;
– folosirea clasei Math pentru calcule matematice ;
– separarea elementelor lexicale (”tokens”) dist incte din cadrul unui șir de caractere; clasa
StringTokenizer ; metode folosite.

Siruri de caractere (String -uri)
Sirurile de caractere in Java sunt definite folosind clasa String .
Limbajul Java face sa para ca String este un tip primitiv, deoarece pentru el sunt definiti operatorii + si
+= pentru concatenare,desi, stim, din lectia 2, ca operatorii, in general, nu pot fi aplicati obiectelor.
Totusi, String este singurul tip referinta pentru care Java a permis supraincarcarea operatorilor.
Reguli fundamenta le privind obiectele de tip String :
1. Obiectele de tip String se comporta ca orice alt obiect Java, exceptand faptul ca asupra lor se poate
aplica operatorul de concatenare;
2. Obiectele de tip String sunt nemodificabile (sunt constante), in sensul ca, da ca doua variabile
referinta indica acelasi sir de caractere, modificarea valorii sirului de caractere catre care refera una
din variabile nu va avea nici un efect asupra valorii sirului de caractere pe care o refera cealalta
variabila.
Aceasta inseamna ca , odata construit un obiect de tip String nu mai poate fi modificat. Din aceasta
motivatie operatorul de atribuire se foloseste pentru String -uri la fel ca pentru un tip de data primitiv,
adica creaza un nou String .
De exemplu:
String mesaj1 = “Java”;
String mesaj2 = “NetBeans”;
String mesaj2_repet = mesaj2;
Dupa aceste atribuiri exista doua obiecte de tip String:
– sirul “Java”, referit de variabila mesaj1 si
– sirul “NetBeans” referit de variabilele mesaj 2 si mesaj2_repet.
Deoarece string -urile sunt obiecte care nu pot fi modificate, singura posibilitate de a modifica
valoarea catre care refera variabila mesaj2_repet este aceea de a construi un nou obiect de tip String
si de a -l atribui variabilei mesaj2_repet . Aceasta operatie nu va avea nici u n efect asupra valorii pe
care o refera mesaj2 .
Crearea de noi obiecte de tip String folosind constructorii clasei String
Clasa String se afla in pachetul java.lang si are definiti mai multi constructori pentru crearea si
initializarea de obiecte de tip St ring.
Vom descrie cativa dintre constructorii clasei String , mai des folositi.
1. Constructor utilizat pentru alocarea unui nou String care contine o secventa de caractere stocata
intr-un tablou unidimensional de caractere.
Antetul constructorului este:

public String (char[] <valoare>)
unde:
– <valoare> – tabloul de caractere care reprezinta sursa secventei de caractere a noului String.
De retinut este faptul ca, modificarea tabloului de caractere nu afecteaza noul sir de caractere creat
astfel.
De exempl u:
char[] caractere1 = {‘a’, ‘b’, ‘c’, ‘d’, ‘e’, ‘f’};
String sir1 = new String(caractere1);
2. Constructor utilizat pentru alocarea unui nou String care contine o secventa de caractere stocata
intr-o portiune a unui tablou unidimensional de caractere.
Antetul constructorului este:
public String (char[] <valoare>, int <deplasament>, int <lungimeSecventa>)
unde:
– <valoare> – tabloul de caractere care reprezinta sursa secventei de caractere a noului String;
– <deplasament> – indexul primului caracter din ta bloul de caractere de la care se va incepe
initializarea noului String;
– <lungimeSecventa> – lungimea secventei de caractere preluata din tabloul de caractere pentru
initializarea noului String.
De retinut este faptul ca, modificarea subtabloului de carac tere preluat nu afecteaza noul sir de
caractere creat astfel.
De exemplu:
char[] caractere1 = {‘a’, ‘b’, ‘c’, ‘d’, ‘e’, ‘f’};
String sir1 = new String(caractere1, 0, 3);
3. Constructor utilizat pentru alocarea unui nou String care contine aceeasi secventa de caractere care
este stocata intr -un alt sir. Cu alte cuvinte, noul sir creat este o copie a unui alt sir. De regula, se
foloseste pentru a crea duplicatul unui sir.
Antetul constructorului este:
public String (String <sirOriginal>)
unde:
– <sirOriginal> – sirul care este copiat in noul sir creat.
De exemplu:

char[] caractere1 = {‘a’, ‘b’, ‘c’, ‘d’, ‘e’, ‘f’};
String sir1 = new String(caractere1);
String sir2 = new String(sir1);
Concatenarea sirurilor de caractere
Atunci cand cel putin unul dintre operanz i este de tip String , operatorul plus (+) realizeaza
concatenarea. Rezultatul este o referinta catre un obiect nou construit de tip String .
Exemple:
1. sir1_concatenat = “x” + “y” + “z”; // sir1_concatenat are valoarea “xyz”
2. sir2_concatenat = “Ana are “ + 5 + “ ani”; /* sir2_concatenat are valoarea
“Ana are 5 ani”, cifra 5 este convertita la String */
Observatie : String -urile formate dintr -un singur caracter nu trebuie confundate si nici inlocuite cu
constantele de tip char (care sunt de fapt numer e).
Operatorul += este, de asemenea, folosit pentru concatenarea sirurilor.
Efectul instructiunii:
sir1 += sir2; este acelasi cu sir1 = sir1 + sir2;
Deci, sir1 va referi un nou obiect de tip String a carui valoare este sir1 + sir2 .
Metoda concat poate fi folosita, de asemenea, pentru concatenarea a doua siruri.
Antetul metodei este:
public String concat (String <sirConcat>) unde:
– <sirConcat> – sirul care se concateneaza la sfarsitul sirului curent.
Metoda concat returneaza un nou sir de caractere care este format din sirul de caractere curent urmat
de sirul de caractere specificat in parametrul <sirConcat>. Daca lungimea sirului specificat in
parametru <sirConcat> este 0, atunci se returneaza sirul curent.
De exemplu:
String nume = “Ionescu ”;
String prenume = “Ion”;
String numePrenume = nume.concat(prenume); // returneaza “Ionescu Ion”
sau:
String sirNou = “la ”.concat(“Ionescu ”).concat(“Ion”); // returneaza “la Ionescu Ion”
Compararea sirurilor de caractere

Operatorii relationali (<, <=, >, > =) nu functioneaza pentru obiecte de tip String .
De asemenea, operatorii de egalitate si inegalitate (==, !=) pentru siruri de caractere au semnificatia
precizata la obiecte de tip referinta, adica compara adrese (referinte catre obiecte de tip String) si nu
valorile continute de obiectele de tip String.
A. Pentru a testa egalitatea (identitatea) a doua obiecte de tip String , se foloseste metoda equals .
Antetul metodei este:
public boolean equals (Object <unObiect>)
unde:
– <unObiect> – reprezinta un obiec t de tip String cu a carui valoare se compara sirul curent.
Metoda equals returneaza valoarea true daca si numai daca parametrul unObiect nu este null si este
un obiect de tip String care are ca valoare aceeasi secventa de caractere ca si a sirului curent.
De exemplu, urmatoarea secventa de cod (EqualsSiruri.java) arata modul de apel al metodei equals
pentru compararea continutului a doua siruri de caractere, introduse de la tastatura:
import java.io.*;
class EqualsSiruri
{
public static void main(String[] args) throws IOException
{
char[] caractere1 = new char[20];
char[] caractere2 = new char[20];
for (int i=0; i <=19; i++)
caractere1[i] = ' ';
for ( int i=0; i <=19; i++)
caractere2[i] = ' ';
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println ("Introduceti primul sir");
br.read(caractere1, 0, 20);
String sir1 = new String(caractere1);
System.out.println ("Introduceti al doilea sir");
br.read(caractere2, 0, 20);

String sir2 = new String(car actere2);
boolean rezultat = false;
rezultat = sir1.equals(sir2);
if (rezultat ==true)
System.out.println ("siruri egale");
else
System.out.println ("siruri diferite"); }
}
Nota: Vom face cateva consideratii asupra folosirii metodei read din clasa BufferedReader , definita in
pachetul java.io.Reader . Aceasta metoda a fost folosita in exemplul de mai sus.
Antetul metodei read este:
public int read (char[] <cbuf>, int <deplasament>, int <lungime>)
unde:
– <cbuf> – tablou de caractere unde se face stocarea secventei de caractere citita din buffer -ul fluxului
de intrare;
– <deplasament> – indexul din tabloul de caractere <cbuf> de la care va incepe stocarea;
– <lungime> – numarul maxim de caractere care se doresc a fi citite si depuse in tablou l de caractere
dat de parametrul <cbuf>.
Metoda read citeste un numar de caractere, dat de parametrul <lungime>, din buffer -ul de intrare si
stocheaza aceste caractere citite intr -o portiune a unui tablou unidimensional de caractere dat de
parametrul <cbuf >.
Atunci cand se foloseste metoda read pentru citirea unui flux de intrare cu tampon (“buffer”) de la
tastatura (System.in) este indicat ca valoarea din parametrul <lungime> sa fie mai mare decat
lungimea secventei de caractere citita de la tastatura. Alt fel, trebuie reapelata metoda read pentru a
prelua si restul caracterelor citite din buffer -ul (zona de memorie tampon) de intrare.
Sa retinem ca, la citirea de la tastatura prin apelul metodei read sunt preluate in tabloul de caractere
dat de parametrul <cbuf> si caracterele ‘ \r’ (cod ASCII -13) si ‘ \n’ (cod ASCII – 10). In functie de
necesitati uneori este necesar ca aceste 2 caractere sa fie eliminate din tabloul de caractere <cbuf>.
Metoda equalsIgnoreCase este folosita pentru a testa egalitatea a doua obiecte de tip String fara a
face distinctie intre literele mici si literele mari ale alfabetului.
Antetul metodei este:
public boolean equalsIgnoreCase (String <altSir>)
unde:

– <altSir> – un alt obiect de tip String cu care se face comparatia sirului cu rent.
Metoda equalsIgnoreCase returneaza valoarea true daca parametrul <altSir> nu este null si daca cele
doua siruri de caractere au aceeasi lungime si sunt formate din aceeasi secventa de caractere, fara a
se face distinctie intre literele mari si mici a le alfabetului.
De exemplu:
boolean rezultat = false;
rezultat = sir1.equalsIgnoreCase(sir2);
B. Metoda compareTo este folosita pentru a realiza un test mai general intre doua siruri din punct de
vedere al ordinii lexicografice. Compararea a doua siruri de caractere se bazeaza pe valoarea Unicode
a fiecarui caracter din sirurile de caractere.
Antetul metodei este:
public int compareTo (String <altSir>) unde:
– <altSir> – un alt obiect de tip String cu care se face comparatia sirului curent.
Metoda compareT o returneaza:
– o valoare intreaga mai mica decat 0 daca sirul curent este mai mic, din punct de vedere al
ordinii lexicografice, decat sirul de caractere din parametrul <altSir>;
– valoarea 0 daca sirul curent este egal, din punct de vedere al ordinii lexicografice, cu sirul de
caractere din parametrul <altSir>;
– o valoare intreaga mai mare decat 0 daca sirul curent este mai mare, din punct de vedere al
ordinii lexicografice, decat sirul de caractere din parametrul <altSir>.
De exemplu:
int rezultat = sir1.compareTo(sir2);
C. Metoda compareToIgnoreCase este folosita pentru a compara doua siruri de caractere, din punct de
vedere al ordinii lexicografice, fara a face distinctie intre literele mici si mari ale alfabetului.
Antetul metodei este:
public int compareToIgnoreCase (String <altSir>) unde:
– <altSir> – un alt obiect de tip String cu care se face comparatia sirului curent.
Metoda compareToIgnoreCase returneaza:
– o valoare intreaga mai mica decat 0 daca sirul curent este mai mic, din punct de vede re al
ordinii lexicografice, decat sirul de caractere din parametrul <altSir>;
– valoarea 0 daca sirul curent este egal, din punct de vedere al ordinii lexicografice, cu sirul de
caractere din parametrul <altSir>;

– o valoare intreaga mai mare decat 0 daca sirul curent este mai mare, din punct de vedere al
ordinii lexicografice, decat sirul de caractere din parametrul <altSir>.
De exemplu:
int rezultat = sir1.compareToIgnoreCase(sir2);
Determinarea lungimii sirurilor de caractere
Lungimea unui obiect de tip String (un sir vid are lungimea 0) poate fi obtinuta cu metoda length(),
care returneaza numarul de caractere, de tip Unicode, din sir.
Extragerea unui caracter dintr -un sir de caractere
Metoda charAt este folosita pentru a extrage un caracter aflat l a o anumita pozitie intr -un sir de
caractere. Precizam ca, primul caracter dintr -un sir se afla pe pozitia 0.
Antetul metodei este:
public char charAt (int <index>) unde:
– <index> – pozitia caracterului in sir, intre 0 si length() – 1.
Metoda charAt retur neaza o valoare de tip char care reprezinta caracterul aflat la pozitia specificata
de parametrul <index> in sir.
De exemplu:
String mesaj = “un nefericit”;
int lungimeSir = mesaj.length(); // lungimeSir are valoarea 12
char carExtras = mesaj.charAt(3); // carExtras are valoarea ‘n’
Extragerea unui subsir dintr -un sir de caractere
Metoda substring este folosita pentru a construi un nou sir de caractere obtinut prin extragerea unui
subsir dintr -un sir de caractere. Exista doua variante ale acestei metode.
Antetul metodei substring in prima varianta este:
public String substring (int <indexInceput>) unde:
– <indexInceput> – pozitia in sirul de caractere de la care incepe extragerea subsirului.
Metoda substring returneaza un nou sir format dintr -un subsir al vechiul sir. Subsirul incepe cu
caracterul aflat pe pozitia specificata in parametrul <indexInceput> si se extinde pana la sfarsitul
vechiului sir.
Antetul metodei substring in a doua varianta este:
public String substring (int <indexInceput>, int <indexSfa rsit>) unde:
– <indexInceput> – pozitia in sirul de caractere de la care incepe extragerea subsirului;

– <indexSfarsit> – pozitia in sirul de caractere pana la care se face extragerea (caracterul de pe aceasta
pozitie nu este inclus in subsir)
Metoda s ubstring in a doua varianta returneaza un nou sir format dintr -un subsir al vechiul sir.
Subsirul incepe cu caracterul aflat pe pozitia specificata in parametrul <indexInceput> si se extinde
pana la caracterul aflat pe pozitia specificata in parametrul <in dexSfarsit> – 1.
Deci, lungimea noului sir creat este: <indexSfarsit> – <indexInceput>
De exemplu:
String sirVechi = “un nefericit”;
String sirNou = sirVechi.substring(5); // sirNou are valoarea “fericit”
String sirNou1 = sirVechi.substring(5, 9); //sirNou1 are valoarea “feri”
Cautarea primei aparitii a unui sir intr -un alt sir
Metoda startsWith este folosita pentru a cauta prima aparitie a unui sir in sirul curent.
Antetul metodei este:
public boolean startsWith (String <sirCautare>) unde:
– <sirC autare> – sirul de cautat in sirul curent.
Metoda startsWith returneaza valoarea true, daca secventa de caractere din sirul specificat de
parametrul <sirCautare> este aceeasi cu cea din sirul curent, si valoarea false, altfel. Daca parametrul
<sirCautare> este sirul vid, metoda returneaza, de asemenea, valoarea true .
Cautarea primei aparitii a unui sir intr -un alt sir folosind o pozitie de inceput a cautarii
Metoda startsWith poate fi folosita si pentru a cauta prima aparitie a unui sir in sirul curent fol osind o
pozitie de inceput a cautarii in sirul curent.
Antetul metodei startsWith in a doua varianta este:
public boolean startsWith (String <sirCautare>, int <indexInceputCautare>)
unde:
– <sirCautare> – sirul de cautat in sirul curent;
– <indexInceputCau tare> – indexul, in sirul curent, de la care incepe cautarea.
Metoda startsWith returneaza valoarea true daca secventa de caractere din sirul specificat de
parametrul <sirCautare> este aceeasi cu cea din sirul curent, incepand de la pozitia specificata in
parametrul <indexInceputCautare>. Altfel, metoda returneaza valoarea false .
Rezultatul aplicarii metodei, in acest caz, este acelasi cu cel al expresiei:
<sirCurent>.substring(<indexInceputCautare>).startsWith(<sirCautare>)
unde: – <sirCurent> specifica sirul curent in care se face cautarea.

Determinarea pozitiei primei aparitii a unui sir intr -un alt sir
Metoda indexOf este folosita pentru a determina pozitia de inceput, in sirul curent, la care se afla
prima aparitie a unui sir.
Antetul metodei este:
public int indexOf(String <sirCautare>) unde:
– <sirCautare> – sirul de cautat in sirul curent.
Metoda indexOf returneaza indexul, din sirul curent, la care se afla prima aparitie a sirului specificat in
parametrul <sirCautare> , daca secventa de caractere din sirul specificat de parametrul <sirCautare>
este aceeasi cu cea din sirul curent, si valoarea -1, altfel.
Determinarea pozitiei primei aparitii a unui sir intr -un alt sir folosind o pozitie de inceput a cautarii
Metoda indexOf poate fi folosita si pen tru a determina indexul primei aparitii a unui sir in sirul curent
folosind pozitia de inceput a cautarii in sirul curent.
Antetul metodei indexOf in a doua varianta este:
public int indexOf (String <sirCautare>, int <indexInceputCautare>)
unde:
– <sirCautare> – sirul de cautat in sirul curent;
– <indexInceputCautare> – indexul, in sirul curent, de la care incepe cautarea spre sfarsitul sirului
curent.
Metoda indexOf returneaza indexul, din sirul curent, incepand de la pozitia specificata in parametr ul
<indexInceputCautare>, la care se afla prima aparitie a sirului specificat de parametrul
<sirCautare>.Altfel, metoda returneaza valoarea -1.
Rezultatul aplicarii metodei, in acest caz, este acelasi cu cel al expresiei:
<sirCurent>.substring(<indexIncepu tCautare>).indexOf(<sirCautare>)
unde: – <sirCurent> specifica sirul curent in care se face cautarea.
Cautarea ultimei aparitii a unui sir intr -un alt sir
Metoda endsWith este folosita pentru a cauta ultima aparitie a unui sir in sirul curent.
Antetul meto dei este:
public boolean endsWith (String <sirCautare>) unde:
– <sirCautare> – sirul de cautat in sirul curent.
Metoda endsWith returneaza valoarea true, daca secventa de caractere din sirul specificat de
parametrul <sirCautare> este aceeasi cu cea din si rul curent, si valoarea false, altfel. Daca parametrul
<sirCautare> este sirul vid, metoda returneaza, de asemenea, valoarea true .

Determinarea pozitiei ultimei aparitii a unui sir intr -un alt sir
Metoda lastIndexOf este folosita pentru a determina pozitia ultimei aparitii a unui sir in sirul curent.
Aceasta metoda se poate aplica in doua variante.
Antetul metodei in prima varianata este:
public int lastIndexOf(String <sirCautare>) unde:
– <sirCautare> – sirul de cautat in sirul curent.
Metoda lastIndexOf returneaza indexul, din sirul curent, la care se afla ultima aparitie a sirului
specificat in parametrul <sirCautare> , daca secventa de caractere din sirul specificat de parametrul
<sirCautare> este aceeasi cu cea din sirul curent, si valoarea -1, altfel .
Nota: Sirul vid (“”) cel mai din dreapta este considerat ca apare la indexul <sirCurent>.length().
Antetul metodei lastIndexOf in a doua varianata este:
public int lastIndexOf (String <sirCautare>, int <indexInceputCautare>)
unde:
– <sirCautare> – sirul de cautat in sirul curent;
– <indexInceputCautare> – indexul, in sirul curent, de la care incepe cautarea spre inceputul sirului
curent.
Metoda lastIndexOf returneaza indexul, din sirul curent, incepand de la pozitia specificata in
parametrul <indexIncep utCautare>, la care se afla ultima aparitie a sirului specificat de parametrul
<sirCautare>.Altfel, metoda returneaza valoarea -1Inlocuirea aparitiilor unui caracter dintr -un sir cu
un alt caracter
Metoda replace este folosita pentru a construi un nou sir de caractere obtinut prin inlocuirea
aparitiilor unui caracter cu un alt caracter, in sirul curent.
Antetul metodei este:
public String replace (char <caracterVechi>, char <caracterNou>)
unde:
– <caracterVechi> – caracterul de inlocuit;
– <caracterNou> – caracterul cu care se inlocuieste.
Metoda replace returneaza un sir nou de caractere construit cu caracterele inlocuite, date de
parametrul <caracterNou>, daca caracterele specificate in parametrul <caracterVechi> sunt gasite in
sirul curent sau returneaza un sir nou de caractere care este identic cu cel initial, daca caracterul
specificat in parametrul <caracterVechi> nu apare in sirul curent.
De exemplu:
String sir1 = “Ionescu Ion”;

String sir2 = sir1.replace(‘I’, ‘J’); // sir2 va avea valoarea “Jone scu Jon”
Inlocuirea aparitiilor unei secvente de caractere (subsir), dintr -un sir, cu o alta secventa de caractere
(subsir)
Metoda replace este folosita si pentru a construi un nou sir de caractere obtinut prin inlocuirea
aparitiilor unei secvente de carac tere cu o alta secventa de caractere, in sirul curent.
Antetul metodei replace in aceasta varianta este:
public String replace (String <secventaVeche>, String <secventaNoua>)
– <SecventaVeche> – secventa de caractere de inlocuit;
– <secventaNoua> – secvent a de caractere cu care se inlocuieste.
Metoda replace , in aceasta varianata, returneaza un sir nou de caractere construit cu secventele de
caractere inlocuite, date de parametrul <secventaNoua>, daca secventele de caractere specificate in
parametrul <secve ntaVeche> sunt gasite in sirul curent sau returneaza un sir nou de caractere care
este identic cu cel initial, daca secventa de caractere specificata in parametrul <SecventaVeche> nu
apare in sirul curent.
Eliminarea caracterelor albe de la inceputul si s farsitul unui sir de caractere
Metoda trim este folosita pentru eliminarea caracterelor albe de la inceputul si sfarsitul sirului de
caractere curent.
Antetul metodei este:
public String trim ()
Metoda trim() returneaza un nou sir de caractere din care sunt eliminate caracterele albe de la
inceputul sau sfarsitul sirului curent, daca acestea exita in sirul curent, sau returneaza sirul curent,
daca caracterele albe nu exista in sir. Daca in sirul curent exista numai caractere albe atunci sirul nou
creat este sirul vid (“”).
Convertirea unui sir de caractere la un tablou de caractere
Metoda toCharArray converteste un sir de caractere la un nou tablou de caractere.
Antetul metodei este:
public char[] toCharArray ()
Metoda toCharArray aloca o zona de memorie pentru un tablou de caractere al carui continut este
initializat cu secventa de caractere reprezentata de sirul de caractere.
Urmatorul program (ReplaceSiruri.java) ilustreaza modul de folosire a metodei repla ce in varianta
inlocuiri unui subsir de caractere cu un alt subsir de caractere, citite de la tastatura, intr -un sir de
caractere, de asemenea citit de la tastatura, a metodei trim pentru inlocuirea caracterelor albe (‘ \r’ si
‘\n’) dintr -o secventa de cara ctere, precum si a metodei toCharArray pentru convertirea sirului, din

care s -au eliminat caracterele albe, la un tablou de caractere. De asemenea, programul arata si modul
de apelare a metodei length() pentru obtinerea lungimii unui sir de caractere.
import java.io.*;
class ReplaceSiruri
{ public static void main(String[] args) throws IOException {
char[] caractere = new char[20];
for (int i=0; i <=19; i++)
caractere[i] = ' ';
BufferedReader br1 = new BufferedReader(new InputStreamReader(System.in));
System.out.println ("Introduceti sirul supus modificarii:");
br1.read(caractere, 0, 20);
for (int i = 0;i <= (caractere.length – 1); i++)
System.out.print((int) caractere[i] + " ") ;
System.out.println();
String sirVechi = new String(caractere).tri m();
char [] caractereVechi = sirVechi.toCharArray();
for (int i = 0;i <= (caractereVechi.length – 1); i++)
System.out.print((int) caractereVechi[i] + " ") ;
System.out.println();
for (int i=0; i <=19; i++)
caractere[i] = ' ';
BufferedReader br2 = new BufferedReader(new InputStreamReader(System.in));
System.out.println ("Introduceti secventa de caractere de inlocuit:");
br2.read(caractere, 0, 20);
String subsirVechi = new String(caractere).trim();
char [] caractereSubsirVechi = subsirVechi.toCharArray();
for (int i = 0;i <= (caractereSubsirVechi.length – 1); i++)
System.out.print((int) caractereSubsirVechi[i] + " ") ;
System.out.println();

for (int i=0; i <=19; i++)
caractere[i] = ' ';
BufferedReader br3 = new BufferedRe ader(new InputStreamReader(System.in));
System.out.println ("Introduceti secventa de caractere cu care se face inlocuirea:");
br3.read(caractere, 0, 20);
String subsirNou = new String(caractere).trim();
char [] caractereSubsirNou = subsirNou.toCharArr ay();
for (int i = 0;i <= (caractereSubsirNou.length – 1); i++)
System.out.print((int) caractereSubsirNou[i] + " ") ;
System.out.println();
String sirNou = sirVechi.replace(subsirVechi, subsirNou);
System.out.println("Lungimea noului sir este:" + sirN ou.length());
System.out.println("Sirul nou este: " + sirNou);
} }
Dupa executia programului pe ecran se afiseaza urmatoarele rezultate:
Introduceti sirul supus modificarii:
Ionescu Ion
73 111 110 101 115 99 117 32 73 111 110 13 10 32 32 32 32 32 32 32
73 111 110 101 115 99 117 32 73 111 110
Introduceti secventa de caractere de inlocuit:
Io
73 111
Introduceti secventa de caractere cu care se face inlocuirea:
Mari
77 97 114 105
Lungimea noului sir este:15
Sirul nou este: Marinescu Marin
Convertirea unui caracter la un sir de caractere
Metoda valueOf converteste un caracter la un sir de caractere.

Antetul metodei este:
public static String valueOf (char <c>)
unde:
– <c> – un caracter.
Metoda valueOf returneaza un sir de caractere cu lungimea de 1 continand un singur caracter dat de
parametrul <c>.
Convertirea unui tablou de caractere la un sir de caractere
Metoda valueOf poate fi folosita si pentru conversia unui tablou de caractere la un sir de caractere.
Antetul metodei este:
public static String valueOf (char [] <tablouCaractere>)
Metoda valueOf returneaza un nou sir de caractere in care este copiat continutul tabloului de
caractere. Modificari ulterioare ale tabloului de caractere nu afecteaza continutul noului sir de
caractere creat.
Convertirea, in sir ul de caractere, a literelor mari in litere mici
Metoda toLowerCase este folosita pentru a transforma literele mari in litere mici, in sirul curent.
Antetul metodei este:
public String toLowerCase ()
Convertirea, in sirul de caractere, a literelor mici in litere mari
Metoda toUpperCase este folosita pentru a transforma literele mici in litere mari, in sirul curent.
Antetul metodei este:
public String toUpperCase ()
Clase înfășurătoare pentru tipurile primitive de date
Pachetul Java.lang conține clase de obiecte care corespund fiecărui tip de date primitive, astfel:
– clasa Byte este folosită pentru a crea obiecte care să rețină valori de tip byte ;
– clasa Short este folosită pentru a crea obiecte care să rețină valori de tip short ;
– clasa Integer este folosită pentru a crea obiecte care să rețină valori de tip int;
– clasa Long este folosită pentru a crea obiecte care să rețină valori de tip long ;
– clasa Float este folosită pentru a crea obiecte care să rețină valori de tip float ;
– clasa Double este folosită pentru a crea obiecte care să rețină valori de tip double ;
– clasa Character este folosită pentru a crea obiecte care să rețină valori de tip char ;

– clasa Boolean este folosită pentru a crea obiecte care să rețină valori de tip boolean .
Totuși, clasele înfășurătoare sunt interpretate diferit față de tipurile primitive corespondente și de
aceea ele nu pot fi folosite în locul tipurilor primitive și nici invers.
Un obiect al oricarei clase infășutătoare menționată mai sus conține un singur câmp al cărui tip este
tipul primitiv corespondent.
Pentru a crea un obiect de un tip ca: Byte, Short, Integer, Long, Float, Double, Character, Boolean , se
folosește operatorul new și un constructor corespunzător.
Exemple:
Integer numarInt = new Integer(44);
Double x = new Double( -44.23);
Character c = new Character(`a`);
Boolean adevar = new Boolean(true);
La fel se procedează și pentru celelalte clase de obiecte care corespund tipurilor primitive. Obiectele
astfel create se poate folosi ca oricare alte obiecte, beneficiind, în același timp și de toate metodele
claselor respective.
Conversia de la un tip da t de clasele înfășurătoare la un tip de data primitiv
Pentru a folosi valoarea dintr -un obiect de un tip: Byte , Short , Integer , Long , Float , Double , Character ,
Boolean , ca valoare de tip primitiv corespunzătoare, se pot apela metode adecvate ale acestor c lase.
În acest sens, menționăm câteva metode des folosite:
byte byteValue () – pentru valori de tip byte ;
short shortValue () – pentru valori de tip short ;
int intValue () – pentru valori de tip int;
long longValue () – pentru valori de tip long ;
float floatVa lue() – pentru valori de tip float ;
double doubleValue () – pentru valori de tip double ;
char charValue () – pentru valori de tip char ;
boolen booleanValue () – pentru valori booleene ;
De exemplu, pentru a extrage o valoare int reținută de obiectul numarInt , creat mai sus, se folosește
următoarea instrucțiune:
int numar = numarInt.intValue(); // returneaza valoarea 44.
Conversia de la tipurile primitive de date numerice la tipul String si invers

Tipul de data byte poate fi reprezentat in Java ca un obiect din clasa Byte (din pachetul java.lang ). Un
obiect de tip Byte contine un singur camp al carui tip este byte .
A. Pentru conversia de la tipul de data byte la tipul de data String se poate folosi metoda toString a
clasei de obiecte Byte.
Antetul metodei este:
public static String toString (byte <b>)
Metoda returneaza un nou sir de caractere continand valoarea precizata in parametrul <b>. Baza de
numeratie folosita este 10.
B. Pentru conversia de la tipul de data String la tipul de data byte se poate folosi metoda parseByte a
clasei de obiecte Byte.
Antetul metodei este:
public static byte parseByte (String <sir>)
Metoda returneaza reprezentarea de tipul byte , in baza 10, a continutului sirului de caractere din
para metrul <sir>. Aceasta metoda genereaza o exceptie (eroare) daca String -ul de convertit nu
contine o valoare de tip byte .
Metoda parseByte poate fi folosita si pentru conversia unui sir de caractere intr -o valoare de tip byte
intr-o baza de numeratie specificata.
Antetul metodei, in aceasta forma, este:
public static byte parseByte (String <sir>, int <baza>)
De exemplu:
String s1 = Byte.toString(45);
byte x = Byte.parseByte(“75”);
Tipul de data Short poate fi reprezentat in Ja va ca un obiect din clasa Short (din pachetul java.lang ).
Un obiect de tip Short contine un singur camp al carui tip este short .
A. Pentru conversia de la tipul de data short la tipul de data String se poate folosi metoda toString a
clasei de obiecte Shor t.
Antetul metodei este:
public static String toString (short <s>)
Metoda returneaza un nou sir de caractere continand valoarea precizata in parametrul <s>. Baza de
numeratie folosita este 10.
B. Pentru conversia de la tipul de data String la tipul de dat a short se poate folosi metoda parseShort a
clasei de obiecte Short.
Antetul metodei este:

public static short parseShort (String <sir>)
Metoda returneaza reprezentarea de tipul short , in baza 10, a continutului sirului de caractere din
parametrul <sir>. A ceasta metoda genereaza o exceptie (eroare) daca String -ul de convertit nu
contine o valoare de tip short .
Metoda parseShort poate fi folosita si pentru conversia unui sir de caractere intr -o valoare de tip
short, intr-o baza de numeratie specificata.
Antetul metodei, in aceasta forma, este:
public static short parseShort (String <sir>, int <baza>)
De exemplu:
String s1 = Short.toString(100); // si contine valoarea “100”
short x = Short.parseShort(“75”, 2); // x contine valoarea 75 in baza 2
Tipul de data int poate fi reprezentat in Java ca un obiect din clasa Integer (din pachetul java.lang ). Un
obiect de tip Integer contine un singur camp al carui tip este int.
A. Pentru conversia de la tipul de data int la tipul de data String se poate fol osi metoda toString a
clasei de obiecte Integer.
Antetul metodei este:
public static String toString (int <i>)
Metoda returneaza un nou sir de caractere continand valoarea precizata de parametrul <i>. Baza de
numeratie folosita este 10.
Metoda toString pentru numere de tip int poate fi folosita si sub forma:
public static String toString (int <i>, int <baza>)
In acest caz, metoda returneaza un nou sir de caractere continand valoarea precizata de parametrul
<i>, in baza de numeratie specificata in parametrul <baza>.
De exemplu:
String s1 = Integer.toString(20,2)); //s1 contine reprezentarea in baza 2 a numarului
20 sub forma de sir de caractere
B. Pentru conversia de la tipul de data String la tipul de data int se poate folosi metoda parseInt a
clasei de obiecte Integer.
Antetul metodei este:
public static int parseInt (String <sir>)

Metoda returneaza reprezentarea de tipul int, in baza 10, a continutului sirului de caractere din
parametrul <sir>. Aceasta metoda genereaza o exceptie (eroare) d aca String -ul de convertit nu
contine o valoare de tip int.
Metoda parseInt poate fi folosita si pentru conversia unui sir de caractere intr -o valoare de tip int,
intr-o baza de numeratie specificata.
Antetul metodei, in aceasta forma, este:
public static int parseInt (String <sir>, int <baza>)
Urmatorul program (ParseIntSiruri.java) arata cum se face conversia unui sir de caractere ( String ) intr –
un numar de tip intreg ( int) prin folosirea metodei Integer.parseInt .
import java.io.*;
class ParseIntSiruri
{
public static void main(String[] args) throws IOException
{
char[] caractere = new char[20];
for (int i=0; i <=19; i++)
caractere[i] = ' ';
BufferedReader br1 = new BufferedReader(new InputStreamReader(System.in));
System.out.println ("Introduceti primul numar");
br1.read(caractere, 0, 20);
String sir1= new String(caractere).trim();
int x = Integer.parseInt(sir1);
System.out.println("Sirul transformat in numar este:" + x);
for (int i=0; i <=19; i++)
caractere[i] = ' ';
System.out.println ("I ntroduceti al doilea numar");
BufferedReader br2 = new BufferedReader(new InputStreamReader(System.in));
br2.read(caractere, 0, 20);
String sir2 = new String(caractere).trim();
int y = Integer.parseInt(sir2);

System.out.println("Sirul transformat in numar este:" + y);
int z = x+y;
System.out.println("Suma numerelor este:" + z); }
}
Dupa executia programului pe ecran se afiseaza urmatoarele rezultate:
Introduceti primul numar
123
Sirul transformat in numar este:123
Introduceti al doilea numar
23
Sirul transformat in numar este:23
Suma numerelor este:146
Tipul de data long poate fi reprezentat in Java ca un obiect din clasa Long (din pachetul java.lang ). Un
obiect de tip Long contine un singur camp al carui tip este long .
A. Pentru conversia de la ti pul de data long la tipul de data String se poate folosi metoda toString a
clasei de obiecte Long, in cele doua variante descrise la tipul Integer. Modul de folosire a acestei
metode este la fel ca la tipul de obiecte Integer.
B. Pentru conversia de la ti pul de data String la tipul de data long se poate folosi metoda parseLong a
clasei de obiecte Long, in cele doua variante descrise la tipul Integer. Modul de folosire a acestei
metode este la fel ca la tipul de obiecte Integer.
De exemplu:
parseLong("473" , 10) returneaza 473L parseLong("1100110", 2) returneaza 102L
Tipul de data float poate fi reprezentat in Java ca un obiect din clasa Float (din pachetul java.lang ). Un
obiect de tip Float contine un singur camp al carui tip este float .
A. Pentru conversia de la tipul de data float la tipul de data String se poate folosi metoda toString a
clasei de obiecte Float.
Antetul metodei este:
public static String toString (float <f>)
Metoda returneaza un nou sir de caractere continand valoarea pr ecizata de parametrul <f>.
De exemplu:
String s1 = Float.toString(20.3); // s1 contine valoarea “20.3”

B. Pentru conversia de la tipul de data String la tipul de data float se poate folosi metoda parseFloat a
clasei de obiecte Float.
Antetul metodei este:
public static float parseFloat (String <sir>)
Metoda returneaza reprezentarea de tipul float , a continutului sirului de caractere din parametrul
<sir>. Aceasta metoda genereaza o exceptie (eroare) daca String -ul de convertit nu contine o valoare
de tip float.
De exemplu:
float y = Float.parseFloat(“1.10”); // y contine valoarea numerica 1.10
Tipul de data double poate fi reprezentat in Java ca un obiect din clasa Double (din pachetul
java.lang ). Un obiect de tip Double contine un singur camp al carui tip este double .
A. Pentru conversia de la tipul de data double la tipul de data String se poate folosi metoda toString a
clasei de obiecte Double. Modul de folosire a acestei metode este la fel ca la tipul de obiecte Float.
B. Pentru conversia de la tipul d e data String la tipul de data double se poate folosi metoda
parseDouble a clasei de obiecte Double. Modul de folosire a acestei metode este la fel ca la tipul de
obiecte Float.
Tipul de data char poate fi reprezentat in Java ca un obiect din clasa Character (din pachetul
java.lang ). Un obiect de tip Character contine un singur camp al carui tip este char .
Din clasa Character vom prezenta metoda isDigit , utilizata pentru a testa daca o valoare de tip char
reprezinta o cifra sau nu.
Metoda isDi git are urmatorul antet:
public static boolean isDigit (char <ch>)
Metoda returneaza valoarea true daca parametrul <ch> este o cifra, altfel returneaza valoarea false .
Aceasta metoda este important de folosit pentru conversiile de la tipul String la tipuri le primitive de
date, deoarece in cazul valorilor nenumerice, metodele de conversie prezentate “arunca” exceptii
(dau erori).
Programul prezentat anterior se poate modifica astfel incat sa putem verifica daca datele introduse de
la tastatura sunt numere sa u nu. Prezentam mai jos secventa de cod care face aceasta verificare
(isDigitTest1.java).
import java.io.*;
class isDigitTest1
{public static void main(String[] args) throws IOException
{char[] caractere = new char[20];

for (int i=0; i <=19; i++)
carac tere[i] = ' ';
BufferedReader br1 = new BufferedReader(new InputStreamReader(System.in));
System.out.println ("Introduceti numarul");
br1.read(caractere, 0, 20);
int j = 0;
while (caractere [j] != ' \r' )
{if (!Character.isDigit(caractere[j]))
{System.out.println("Nu este numar");
return;}
j++;}
}
}
Folosirea clasei Math pentru calcule matematice
Clasa Math face parte din pachetul java.lang . Aceast ă clasă conține mai multe metode statice (de
clasa) prin care se calculează valorile unor funcții clasice din matematică (logaritmice, exponențiale,
trigonometrice, etc.). In tabelul de mai jos sunt descrise formatele metodelor mai des folosite din
clasa Math .

Metoda
Descriere
long abs (long x)
Returnează modulul numărului de tip long dat
in parametrul x.
int abs (int x)
Returnează modulul numărului de tip int dat in
parametrul x.
double abs (double x)
Returnează modulul numărului de tip double
dat in parametrul x.
float abs (float x)
Returnează modulul numărului de tip float dat
in parametrul x.
double cos (double x)
Calculează cos (x)

double sin (double x)
Calculează sin (x)
double tan (double x)
Calculează tg (x)
double acos (double x)
Calculează arcos (x)
double asin (double x)
Calculează arsin (x)
double ceil (double x)
Returnează cel mai mic întreg mai mare sau egal
cu numărul dat in parametrul x.
double floor (double x)
Calculează cel mai mare întreg mai mic sau egal
cu numărul dat de parametrul x.
double pow (double a, double b)
Calculează ab
double sqrt (double x)
Calculează radicalul numărului dat de parametrul
x.
long round (double x)
Rotunjește x de tip long la cel mai apropiat întreg
de x.
int round (float x)
Rotunjește x de tip int la cel mai apropiat întreg
de x.
double random ()
Generează un număr aleator în intervalul [0,1)
double max (double x, double y)
Returnează maximul dintre două numere de tip
double .
float max (float x, float y)
Returnează maximul dintre două numere de tip
float.
int max (int x, int y)
Returnează maximul dintre două numere de tip
int.
long max (long x, long y)
Returnează maximul dintre două numere de tip
long.
double min (double x, double y)
Returnează minimul dintre două numere de tip
double .
float min (float x, float y)
Returnează minimul dintre două numere de tip
float.
long min (long x, long y)
Returnează minimul dintre două numere
de tip long.
int min (int x, int y)
Returnează minimul dintre două numere
de tip int.
double exp (double x)
Calculează ex
double log (double x)
Calculează logaritmul natural al unui
numar dat de parametrul x.
double E
constanta e
double PI
constanta л

Iată câteva exemple de apel al metodelor clasei Math :
Math.ceil(3.36) returnează 4; Math.ceil( -3.36) returnează –3;
Math.floor (3.36) returnează 3; Math.floor( -3.36) returnează –4;
Math.round(3.36) returnează 3; Math.round( -3.36) returnează –3;
Math.round(3.56) returnează 4; Math.round( -3.56) returnează –4;
Math.round( -3.5) returnează –3;
Math.round(3.5) returnează 4 ;
Separarea elementelor lexicale (”tokens”) distincte din cadrul unui șir de caractere. Clasa
StringTokenizer
Clasa StringTokenizer este inclusă în pachetul java.util și permite separarea elementelor lexicale
(“tokens”) distincte din cadrul unui șir de car actere.
Separarea în elemente lexicale (“tokenization”) înseamnă împărțirea într -un număr de elemente lexicale
distincte, printr -un caracter delimitator, a șirului inițial. Implicit, Java folosește ca delimitatori ai
elementelor lexicale caracterul tab, caracterul spatiu și caracterul de linie noua (“newline ”). Obiectele de
tip StringTokenizer pot fi construite pentru a accepta și alți delimitatori de elemente lexicale.
Metodele -constructor ale clasei StringTokenizer , mai des folosite, au forma:
a) StringTokenizer (String <str>)
unde: <str> – specifică șirul de caractere supus separării în elemente lexicale;

b) StringTokenizer (String <str>, String <delimitator>)
unde:
– <str> – specifică șirul de caractere supus separării în elemente lexicale;
– <delimit ator> – specifică o listă de caractere de delimitare; de exemplu, un parametru de felul
“,:” indică faptul că delimitatorii sunt virgula și două puncte.
Constructorul prezentat la pct. b) este folosit pentru a schimba delimitatorul implicit de elemente
lexicale.
Vom descrie câteva metode ale clasei StringTokenizer .
Metoda nextToken () este folosită pentru a extrage fiecare element lexical dintr -un șir de caractere
utilizând delimitatorii impliciți Java sau delimitatorii precizați explicit la crearea obiectului de tip
StringTokenizer . Antetul metodei este:
String nextToken ()
Metoda re turnează un șir de caractere care reprezintă elementul lexical extras.

Metoda nextToken () poate fi folosită și cu un parametru de tip String care are ca efect schimbarea
delimitatorului folosit pentru separarea elementelor lexicale din șirul curent după c e obiectul de tip
StringTokenizer a fost creat. În acest caz, metoda nextToken () are forma:
String nextToken (String <delimitator_nou>)
unde:
– <delimitator_nou> – specifică noul delimitator după care se va face extragerea unui element lexical , de
la poziț ia curentă în șirul curent supus separării până la întâlnirea delimitatorului precizat în parametrul
metodei.
Metoda returnează un șir de caractere care reprezintă elementul lexical extras pe baza noului
delimitator. Această metodă generează o excepție (er oare) de tip NoSuchElementException dacă nu mai
există nici un element lexical în șirul curent supus separării.
Metoda hasMoreTokens () este folosită pentru a afla dacă șirul curent supus separării conține mai multe
elemente lexicale. Antetul metodei este:
boolean hasMoreTokens ()
Metoda returnează valoarea true dacă șirul curent supus separării conține mai multe elemente lexicale
și false dacă nu.
Următoarea secvență de cod ilustrează folosirea metodei nextToken () cu un parametru, precum și a
metodei hasMore Tokens ():
StringTokenizer st = new StringTokenizer(“Nume si Prenume:Ionescu Florin”, “:”);
System.out.println(“Primul element – “ + st.nextToken());
while (st.hasMoreTokens()) {
System.out.println(“Urmatorul element – “ + st.nextToken(“ “));}
În acest caz, programul va afișa următorul rezultat:
Primul element – Nume si Prenume
Urmatorul element – Ionescu
Urmatorul element – Florin
Metoda countTokens () este folosită pentru a specifica numărul de elemente lexicale pe care le conține
șirul curent supus sep arării. Antetul metodei este:
int countTokens()
Metoda returnează un întreg care reprezintă numărul de elemente lexicale pe care le conține șirul
curent.
Vom prezenta un program (TestStringTokenizer.java) care ilustrează modul de folosire a unui obiect de
tip StringTokenizer pentru a separa un șir de numere citite de la tastatură pe aceeași linie folosind ca

delimitator caracterul spațiu sau tab. După citire, șirul de numere este stocat într -un tablou de numere
întregi.
Programul folosește două metode și a nume: citesteString () și citesteSeparaSir (). Metoda citesteString ()
citește de la tastatură un șir de numere pe o singură linie. Metoda citesteSeparaSir () separă șirul de
numere citit în elemente lexicale folosind ca delimitator caracterul spațiu și conver tește aceste
elemente lexicale într -un tablou de numere întregi.
import java.io.*;
import java.util.StringTokenizer;
class TestStringTokenizer {
public static void main(String[] args) throws IOException {
TestStringTokenizer tst = new T estStringTokenizer();
System.out.println("Introduceti un sir de numere pe aceeasi linie, despartite prin Tab:");
int [] tablouInt = tst.citesteSeparaSir();
System.out.println ("Tabloul de numere citit este: ");
for (int i = 0; i < tablouInt.length; i++)
System.out.println(tablouInt[i] + " ");
}
String citesteString() throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
return br.readLin e();
}
int [] citesteSeparaSir() throws IOException{
String sir = citesteString();
StringTokenizer st = new StringTokenizer(sir);
int[] tablou = new int[st.countTokens()];
for (int i = 0; i < tablou.length; ++i)
tablou[i] = Integer.parseInt(st.nextToken());
return tablou;
}
}

Curs 5

Cuvinte importante:
– concepte fundamentale ale programarii orientate obiect in Java: incapsulare, mostenire,
polimorfism;
– crearea claselor de obiecte: definirea claselor; modificatorii pentru tipurile de clasa;
modificatorii de acces;
– variabilele (campurile) clasei de obiecte: declararea variabilelor de instanta; declararea
variabilelor de clasa; declararea constantelor;
– domeniul de vizibilitate (a cces) al variabilelor folosite in clasele de obiecte: domeniul de
vizibilitate al variabilelor locale; domeniul de vizibilitate al variabilelor clasei; modificatorii de acces
(vizibilitate);
– metodele unei clase de obiecte: definirea si apelul metodelor; modificatorii de metoda;
– metode de instanta si metode de clasa;
– domeniul de vizibilitate (acces) al metodelor unei clase: modificatori de acces; referinta this;
– metode constructor: caracteristici, supraincarcarea metodelor constructor; cuvantul -cheie this
pentru constructori;
– initializatori statici.
Concepte fundamentale ale programarii orientate obiect (OOP) in Java
In Java un obiect este o variabila complexa care se caracterizeaza prin:
– o structura , descrisa de atributele (proprietatile) sale;
– o stare , descrisa de valorile pe care le ia la un moment dat atributele sale;
– un set de operatii prin intermediul carora se poate manevra (accesa sau modifica) starea sa.
1. Conceptul de incapsulare
Obiectul trebuie privit ca o unitate atomica la care utilizatorul nu ar trebui sa aiba acces direct. Acest
principiu al OOP este cunoscut sub numele de “ ascunderea informatiei ”. Acest principiu spune ca un
obiect poate fi accesat numai prin intermediul metodelor care au fost furnizate impreuna cu obi ectul.
In legatura cu principiul “ascundrii informatiei”, programarea orientata obiect a introdus conceptul de
incapsulare .
Incapsularea inseamna gruparea datelor si a operatiilor asupra acestor date in acelasi intreg (agregat)
avand grija sa se ascunda d etaliile de implementare (proiectare -realizare) ale acestui intreg. Deci, datele
sunt “ascunse”, iar accesul la aceste date se realizeaza numai prin intermediul metodelor incapsulate cu
ele.

2. Mostenirea este un alt concept fundamental al OOP.
Mostenirea permite unei clase sa mosteneasca atributele si metodele unei alte clase existente.
Prin mostenire, o clasa noua dobandeste imediat tot comportamentul unei clase existente. Aceasta clasa
noua se numeste clasa derivata din clasa existenta. O clasa de obie cte derivata dintr -o alta clasa
existenta pastreaza toate proprietatile si metodele acesteia din urma aducand, in plus, proprietati si
metode noi.
Prin mostenire, toate clasele sunt aranjate intr -o ierarhie stricta . De exemplu, intr -o ierarhie stricta sunt
aranjate si clasele provenite din biblioteca de clase Java.
In ierarhia de clase, clasa care mosteneste alta clasa este denumita subclasa , iar clasa care isi ofera
mostenirea se numeste superclasa .
Mostenirea da posibilitatea extinderii functionalitatii unui obiect. Cu alte cuvinte se pot crea noi clase de
obiecte care sa extinda proprietatile si metodele clasei originale.
Vom reveni asupra mecanismului de mostenire intr -o lectie viitoare.
3. Polimorfismul este al treilea concept fundamental in OOP.
Polimorfismul reprezinta capacitatea unui obiect de a aparea sub diferite forme. De exemplu, in lumea
reala, apa apare sub forma solida, sub forma lichida sau sub forma gazoasa.
In Java, polimorfismul inseamna ca o singura variabila referinta de tipul unei sup erclase poate fi folosita
pentru a referi mai multe obiecte (instante) din clase derivate direct sau indirect din aceeasi superclasa,
in diferite momente ale executiei unui program.
Unele dintre proprietatile si metodele definite in superclasa pot fi rede finite (rescrise) in subclasele de
obiecte derivate.
Redefinirea proprietatilor si metodelor in subclasele derivate direct sau indirect dintr -o superclasa ne
da, de fapt, o mare flexibilitate in constructia ierarhiei de clase pentru o problema de rezolvat, pentru ca
nici o proprietate sau metoda definita intr -un punct al ierarhiei nu este impusa definitiv pentru clasele
derivate din acest punct direct sau indirect.
Vom reveni asupra mecanismului de polimorfism intr -o lectie viitoare.
Conceptele fundamentale prezentate mai sus sunt folosite pentru a indeplini unul din principalele
scopuri ale OOP si anume reutilizarea codului (refolosirea obiectelor sau refolosirea unor programe) .
Crearea claselor de obiecte
O clasa contine membri care pot fi:
– atribute (ca mpuri, date);
– metode (functii).
Metodele pot actiona asupra atributelor si pot apela alte metode.
Definirea claselor de obiecte

O clasa este definita prin cuvantul cheie class urmat de numele clasei. Sintaxa folosita este:
[<modificatori_acces>] [<modif icatori_clasa>] class <nume_clasa> [<clauze_s>]
{
<corpul_clasei>
}
unde:
– <modificatori_acces> – specifica domeniul de vizibilitate (folosire sau acces) al clasei; modificatorul de
acces este optional si poate fi: public ;
– <modificatori_clasa> – speci fica tipul clasei definite; modificatorul clasei este optional si poate fi:
abstract , final ;
– <nume_clasa> – specifica numele clasei de obiecte; este de preferat ca numele clasei sa inceapa cu o
litera majuscula si daca numele clasei contine in interior mai multe cuvinte, aceste cuvinte sa inceapa cu
o litera majuscula;
– <clauze_s> – specifica anumite clauze referitoare la pozitia pe care o ocupa clasa in ierarhia de clase din
care face parte (clauza extends ) sau daca aceasta clasa foloseste o interfata (clauza inplements ); despre
aceste clauze vom vorbi intr -o lectie viitoare.
– <corpul_clasei> – variabilele clasei (de instana si de clasa) si metodele care lucreaza cu acestea, numite
la un loc membrii clasei.
Observatie: Continutul (corpul) unei clase nu este o succesiune de instructiuni.
Modificatorii pentru tipurile de clasa
O clasa poate fi:
– abstracta, caz in care folosim modificatorul abstract ;
– finala, caz in care folosim modificatorul final .
In cazul in care de claram o clasa de obiecte ca fiind abstracta , compilatorul va interzice instantierea
acestei clase, adica nu se permite crearea de obiecte din aceasta clasa. Vom reveni intr -o lectie viitoare.
In cazul in care declaram o clasa de obiecte ca fiind finala , compilatorul va interzice ca pornind de la
aceasta clasa sa se defineasca subclase. Vom reveni intr -o lectie viitoare.
Nota :In cazul in care se declara, in acelasi timp, o clasa de obiecte ca fiind abstracta si finala, eroarea va
fi semnalata la compilare, pentru ca cei doi modificatori se exclud.
Modificatorii de acces
In cazul in care declaram o clasa de obiecte ca fiind publica , atunci aceasta clasa poate fi folosita
(accesata) si din exteriorul pachetului din care face parte.

Daca o clasa nu este declar ata ca fiind de tip public atunci ea va putea fi folosita (accesata) doar de
clasele din cadrul aceluiasi pachet. Acest tip de acces la o clasa se numeste package -friendly si este
implicit in Java.
Nota: Toate clasele care nu fac parte din nici un pachet, sunt considerate automat ca facand parte din
acelasi pachet implicit. Ca o consecinta, accesul de tip friendly se aplica pentru toate aceste clase.
Acesta este motivul pentru care vizibilitatea nu este afectata daca se omite modificatorul public pentru
clasele care nu fac parte dintr -un pachet. Totusi, aceasta modalitate de folosire a accesului de tip
friendly nu este recomandata.
Variabilele (campurile) clasei de obiecte
Declararea variabilelor de instanta
O variabila este considerata ca variabila de insta nta daca este declarata in afara metodelor clasei
respective, insa valorile variabilelor de instanta se stocheaza individual in instantele (obiectele) clasei.
Rezulta ca, acestea pot lua valori diferite (se pot modifica) pentru fiecare obiect al clasei re spective.
Toate variabilele de instanta se declara imediat dupa prima linie a definitiei clasei (si dupa acolada
deschisa { ).
De exemplu:
class Copil
{
String culoarePiele;
String sex;
boolean flamand;
}
Clasa Copil contine trei variabile. Deoarece ace ste variabile sunt declarate in afara oricarei metode, ele
sunt variabile (campuri) de instanta.
Declararea variabilelor de clasa
O variabila este considerata ca variabila de clasa daca este declarata in afara metodelor clasei folosind
modificatorul stati c. Valoarea variabilei de clasa ramane aceeasi pentru toata clasa in ansamblul ei.
Rezulta ca, variabila de clasa are o singura valoare comuna tuturor instantelor clasei in care este
declarata.
Modificarea valorii variabilei de clasa din interiorul unui o biect face ca modificarea sa se reflecte in toate
celelalte instante ale clasei existente in acel moment al executiei programului.
Variabilele de clasa sunt folosite la comunicarea intre diferite obiecte ale aceleiasi clase sau pentru
pastrarea unor date c omune la nivelul intregii clase.

Variabilele statice sunt initializate la incarcarea codului specific unei clase si exista chiar si daca nu exista
nici o instanta a clasei respective.
De exemplu:
static int maxObiecte = 10;
O variabila statica poate fi accesata fie conform regulii generale prin crearea si utilizarea unei instante a
clasei din care provine (si precalificarea variabilei cu numele instantei), fie direct, prin precalificarea
variabilei cu numele clasei.
Referirea (accesul) la variabilele de instanta si de clasa
Accesarea unei variabile de instanta sau de clasa se realizeaza in mai multe moduri:
– prin crearea si utilizarea unei instante a clasei in care a fost declarata variabila sau a unei
subclase a clasei respective (ca regula generala) ; in acest caz se foloseste operatorul punct ( . ), in stinga
acestuia punandu -se numele instantei, iar in dreapa acestuia punandu -se numele variabilei;
– prin simpla folosire a numelui sau, in cazul in care clasa in care este accesata variabila este
acee asi cu clasa in care a fost declarata;
– prin folosirea operatorului punct ( . ), in stanga acestuia punandu -se numele clasei in care a
fost declarata, iar in dreapta acestuia punandu -se numele variabilei; aceasta modalitate este folosita
numai cand varia bila este declarata ca variabila de clasa.
Variabile locale
Declararea variabilelor locale
Stim ca, pin bloc intelegem o secventa (eventual, vida) de instructiuni, cuprinsa intre acolade. De
asemenea, ori ce bloc poate contine la randul sau un alt bloc, pu tand astfel lua nastere o structura
imbricata de blocuri.
Prin variabila locala intelegem o variabila declarata in interiorul unei metode, unui bloc, inclusiv intr -o
instructiune for.
De asemenea, parametrii metodei sunt considerati variabile locale.
Observatie: Numele variabilelor de instanta, de clasa sau locale este de preferat sa inceapa cu o litera
mica, iar fiecare cuvant incepand cu al doilea, in cazul in care exista, sa inceapa cu majuscule.
Constante
Declararea constantelor locale si ale clasei
Constanta este un tip special de variabila a carei valoare nu se modifica niciodata pe parcursul executiei
programului.
In Java, se pot declara constante pentru toate tipurile de variabile: de instanta, de clasa sau locale.
Pentru a declara o constanta s e foloseste modificatorul final . De asemenea, constantei i se atribuie o
valoare care nu se modifica pe parcursul executiei programului.

In cazul constantelor locale , atribuirea valorii acestora se face la declarare sau inainte de a fi folosita.
De exemp lu:
final float pi = 3.141592;
final numarMaxim = 12567;
Observatie: Numele constantelor locale este de preferat sa inceapa cu o litera mica, iar fiecare cuvant
incepand cu al doilea, in cazul in care exista, sa inceapa cu o majuscula.
In cazul constantelo r care definesc atributele unei clase , atribuirea valorii acestora se face fie prin
initializare, in afara corpului tuturor metodelor clasei, fie prin constructori.
Constantele pot fi folositoare pentru denumirea diferitelor stari ale unui obiect (instant a) sau pentru
testarea acestor stari.
De exemplu, sa presupunem ca avem o eticheta text care poate fi aliniata la stanga, la dreapta sau
centrat. Aceste constante se pot declara astfel:
final int LEFT = 0;
final int RIGHT = 1;
final int CENTER = 2;
Observatie: Numele constantelor care definesc proprietatile clasei este de preferat sa fie scris in
totalitate cu majuscule, iar daca sunt mai multe cuvinte in componenta unui nume de constanta, atunci
acestea sa fie separate prin linie de subliniere ( _ ) ca in exemplul de mai sus.
Daca constanta defineste un atribut al unei intregi clase (adica, al tuturor instantelor clasei) atunci
modificatorul final este folosit impreuna cu modificatorul static .
Programul urmator (LotoConstante.java) ilustreaza modul de folosire al constantelor pentru atributele
clasei . In jocul de loterie, se selecteaza saptamanal sase numere de la 1 la 49. Programul alege aleator
numere pentru 1000 de jocuri si afiseaza apoi de cate ori a aparut fiecare numar in cele 1000 de jocuri.
Se definesc trei constante de tip intreg pentru clasa LotoConstante : NUMERE care are valoarea 49,
NUMERE_PE_JOC care are valoarea 6 si JOCURI are valoarea 1000.
public class LotoConstante
{
static final int NUMERE = 49;
static final int NUMERE_PE_JOC = 6;
static final int JOCURI = 1000;
//genereaza numere de loterie intre 1 si 49
//afiseaza numarul de aparitii al fiecarui numar
public static void main(String[] args)

{
//genereaza numerele
int[] numere = new int[50];
for (int i = 0; i < numere. length; ++i)
numere[i] = 0;
for (int i = 0; i < JOCURI; ++i)
for (int j = 0 ; j < NUMERE_PE_JOC; ++j)
numere[(int) (Math.random() * NUMERE) +1]++ ;
// numara aparitiile de numere pe joc
//afisare rezultate
for (int k = 1; k <= NUME RE; ++k)
System.out.println(k + ": " + numere[k]);
}
}
Domeniul de vizibilitate (acces) al variabilelor folosite in clasele de obiecte. Modificatori de acces.
Domeniul de vizibilitate al variabilelor locale
Domeniul de vizibilitate al unei variabile lo cale este constituit din partea din blocul in care variabila a
fost declarata, parte ce urmeaza declararii, precum si din subblocurile blocului de instructiuni,
subblocuri care urmeaza declararii. Variabilele locale exista si pot fi folosite numai pe perio ada in care
blocul unde sunt declarate este in curs de executie.
O variabila locala nu poate fi redeclarata nici in blocul in care a fost declarata, nici intr -un bloc inclus in
acesta. O variabila locala poate fi redeclarata in blocuri disjuncte.
Domeniul de vizibilitate al parametrilor metodelor
Parametrii unei metode sunt vizibili (folosibili) doar in corpul metodei respective, deoarece se comporta
ca variabile locale. Este insa posibil ca intr -un bloc dintr -o metoda sa se redeclare parametrul respectiv.
In acest caz, in partea din bloc ce urmeaza redeclararii, parametrul respectiv este considerat ca avand
semnificatia data de redeclarare.
Domeniul de vizibilitate al variabilelor clasei
Variabilele de instanta si de clasa au un domeniu de vizibilitate ext ins la intreaga clasa in care au fost
declarate, deci ele pot fi folosite de oricare dintre metodele din cadrul clasei fara a fi prefixate cu
operatorul punct si numele instantei sau clasei.

Java verifica existenta unei declaratii a unei variabile de inst anta sau de clasa in clasa curenta. Daca Java
nu gaseste declaratia variabilei in clasa curenta , o cauta in superclasa corespunzatoare si asa mai
departe pe toata ramura din ierarhie pe care se afla clasa respectiva.
Daca o variabila de instanta sau de c lasa este redeclarata intr -o metoda (adica, este folosita ca un
parametru sau ca o variabila locala) atunci declararea cea mai interioara este cea care primeaza cand se
face o referire la acea variabila. Se spune ca variabila redeclarata cu un domeniu de v izibilitate interior
“ascunde” (inlocuieste) valoarea originala a variabilei si poate produce erori greu de depanat.
De exemplu, urmatorul program (TestDomeniu.java):
class TestDomeniu {
int test = 10;
void printTest(int test) {
System.out.println(" test = " + test);}
public static void main (String args[]) {
TestDomeniu st = new TestDomeniu();
st.printTest(20);}
}
Programul are declarate doua variabile cu acelasi nume. Prima, o variabila de instanta, are numele test si
a fost initializata cu valoarea 10. A doua este un parametru cu acelasi nume al metodei printTest , insa cu
valoarea 20. Parametrul test din cadrul metodei printTest ascunde variabila de instanta test. Metoda
printTest apelata in metoda main afiseaza parametrul test cu valoare a 20 si nu variabila de instanta.
Se poate evita aceasta eroare folosind referinta this ca o referinta la obiectul curent. Astfel, this.test
refera variabila de instanta si numele simplu test refera parametrul metodei printTest. Programul de mai
sus se poa te, astfel, modifica (TestDomeniuThis) pentru a afisa valoarea 10 a variabilei de instanta si nu
valoarea parametrului.
class TestDomeniuThis {
int test = 10;
void printTest(int test) {
System.out.println("test = " + this.test);}
public static vo id main (String args[]) {
TestDomeniuThis st = new TestDomeniuThis();
st.printTest(20);}
}
Vom reveni asupra referintei this dupa descrierea metodelor si a modificatorilor aplicati acestora.

Modificatorii de acces (vizibilitate) ai variabilelor un ei clase
In Java exista trei modificatori de acces ai variabilelor unei clase:
– modificatorul public ;
– modificatorul protected ;
– modificatorul private .
Putem spune ca, prin acesti modificatori de acces, un obiect poate controla modul cum este vazut si cum
se poate interactiona cu el din exterior.
Revenind la incapsulare , aceasta poate fi definita ca procesul de prevenire a folosirii sau a modificarii
directe a unor variabile apartinand unei clase de catre alte clase. Singura metoda de folosire a acestor
variabile este prin apelarea metodelor clasei, daca si acestea sunt disponibile.
Modificatorul public face ca variabila respectiva sa fie accesibila, pri n intermediul operatorului punct,
oriunde este accesibila clasa variabilei.
Modificatorul protected face ca variabila respectiva sa fie accesibila in orice clasa din pachetul careia ii
apartine clasa in care a fost declarata. In acelasi timp, variabila este accesibila in toate subclasele clasei
date, chiar daca ele apartin altor pachete.
Modificatorul p rivate face ca variabila respectiva sa fie accesibila doar in interiorul clasei in care a fost
declarata.
Daca pentru o variabila a unei clase nu se precizeaza nici un modificator de acces din cei descrisi mai sus,
atunci variabila respectiva devine packag e-friendly . O variabila friendly este accesibila in pachetul din
care face parte clasa in interiorul careia a fost declarata, dar nu este accesibila in subclasele clasei date
daca acestea apartin altor pachete.
Nota : Modificatorii de acces ( public , protec ted, private ) sunt plasati primii in declaratia variabilei,
urmeaza apoi modificatorii care determina felul variabilei ( static , final ) si apoi tipul de data al variabilei
(referinta sau tip primitiv), ca mai jos:
[<modificatori_acces>] [<modificatori_varia bila>] <tip_variabila> <nume_variabila>
Metodele unei clase de obiecte
Definirea metodelor
Definitia unei metode cuprinde patru parti:
– numele metodei;
– o lista de parametrii (definiti prin nume si tip);
– tipul obiectului sau tipul primitiv de date returnat de metoda;
– corpul metodei
Primele trei parti ale definitiei metodei formeaza ceea ce se numeste semnatura metodei .

In plus, o metoda mai poate contine:
– modificatorii care descriu proprietatile metodei si modul de lucru al acesteia;
– clauze throws care indica exceptiile (erorile) pe care le poate semnala metoda.
Sintaxa definitiei unei metode este:
[<modificatori_acces>] [<modificatori_metoda>] <tip_returnat> <nume_metoda> ([<param1>,
<param2>, …]) [<clauze_specifice>]
{
<corpul_metodei>
}
– <modificatori_acces> – specifica domeniul de vizibilitate (folosire sau acces) al metodei; modificatorul
de acces este optional si poate fi: public ; protected ; private ;
– <modificatori_metoda> – specifica proprietatile metodei si modul de lucru al acesteia; modificatorul
este optional si poate fi: static , abstract , final ;
– <tip_returnat> – specifica unul din tipurile primitive, un nume de clasa sau cuvantul cheie void (cand
metoda nu returneaz a nici o valoare);
– <nume_metoda> – specifica numele metodei; este de preferat ca numele metodei sa inceapa cu o
litera mica si daca numele metodei contine in interior mai multe cuvinte, aceste cuvinte sa inceapa cu o
litera majuscula;
– <param1>, <param2 >, … – specifica lista de parametrii ai metodei, care reprezinta un set de definitii de
variabile separate prin virgula;
– <clauze_specifice> – specifica anumite clauze throws care indica exceptiile (erorile) pe care le poate
semnala (“arunca”) metoda; des pre aceste clauze vom vorbi intr -o lectie viitoare;
– <corpul_metodei> – instructiuni, apelari de metode etc.
Observatii :
1. Daca o metoda returneaza o referinta la un tablou de valori sau de obiecte, trebuie folosite
parantezele drepte ([]) fie dupa <tip _returnat>, fie dupa lista de parametrii.
2. In afara cazurilor cand este declarata cu tipul void , o metoda returneaza la terminarea sa o valoare de
un anumit tip.Acesata valoare trebuie specificata explicit intr -o instructiune return .
3. In aceeasi clasa pot exista metode cu acelasi nume si acelasi tip al valorii returnate, dar care difera
prin numarul si tipul parametrilor din lista de parametrii. Acest mecanism poarta denumirea de
supraincarcarea ( overloading ) metodei.
Apelul metodelor
Apelul unei metod e definita intr -o clasa de obiecte se realizeaza in mai multe moduri:

– prin crearea si utilizarea unei instante a clasei in care a fost definita metoda sau a unei subclase
a clasei respective (ca regula generala de invocare a unei metode); in acest caz s e foloseste operatorul
punct ( . ), in stinga acestuia punandu -se numele instantei, iar in dreapa acestuia punandu -se numele
metodei;
– prin simpla folosire a numelui sau, in cazul in care clasa in care este apelata metoda este
aceeasi cu clasa in care a fost definita; aceasta modalitate este folosita daca atat metoda apelanta cat si
metoda apelata sunt fie numai metode de instanta, fie numai metode de clasa;
– prin folosirea operatorului punct ( . ), in stanga acestuia punandu -se numele clasei in care a
fost definita, iar in dreapta acestuia punandu -se numele metodei; aceasta modalitate este folosita
numai daca metoda este definita ca metoda de clasa.
Programele urmatoare (ClasaTablou1.java si ClasaTablou2.java) prezinta un exemplu de creare a unei
clase care defineste o metoda numita creareTablou . Aceasta preia doua numere naturale (o limita
inferioara si una superioara) si creaza un tablou unidimensional care contine toate numerele naturale
aflate intre cele doua limite, inclusiv aceste limite.
Varianta de apel a unei metode prin crearea si utilizarea unei instante a clasei in care a fost definita
metoda .
public class ClasaTablou1 {
int [] creareTablou(int inf, int sup) {
int [] tabl = new int[(sup – inf) +1];
for (int i = 0 ; i < tabl.length; i++)
tabl[i] = inf++;
return tabl; }
public static void main(String args[]) {
ClasaTablou1 unTablou = new ClasaTablou1();
int [] tablou = unTablou.creareTablou(1,10);
System.out.print("Tabloul: [ ");
for (int i = 0; i < tablou .length; i++)
System.out.print(tablou[i] + " ");
System.out.println("]");}
}
Varianta de apel a unei metode prin simpla folosire a numelui metodei, deoarece metoda este definita si
apelata in aceeasi clasa . Totusi metoda creareTablou trebuie sa fie declarata ca metoda de clasa
(modificatorul static ) pentru a putea fi apelata dintr -o alta metoda de clasa.

public class ClasaTablou2 {
static int [] creareTablou(int inf, int sup)
{
int [] tabl = new int[(sup – inf) +1];
for ( int i = 0 ; i < tabl.length; i++)
tabl[i] = inf++;
return tabl;
}
public static void main(String args[])
{
int [] tablou = creareTablou(1,10);
System.out.print("Tabloul: [ ");
for (int i = 0; i < tablou.length; i++)
System.out.print(tablou[i] + " ");
System.out.println("]");
}
}
Modificatorii de metoda specifica proprietati suplimentare pentru o metoda.
In Java exista mai multi modificatori de metoda, dintre care mentionam:
– modificatorul static – pentru metode de clasa;
– modificatorul abstract – pentru metode abstracte, ce vor fi descrise intr -o lectie viitoare;
– modificatorul final – pentru metode finale, ce vor fi descrise intr -o lectie viitoare.
Metode de instanta si metode de clasa
Meto de de instanta
Ca regula generala, o metoda definita intr -o clasa se poate apela prin crearea unei instante a clasei
respective sau a unei subclase a clasei respective. Aceasta se datoreaza faptului ca metoda lucreaza cu o
serie de variabile ale clasei car e sunt memorate in interiorul instantei si care au valori diferite in instante
diferite (numite variabile de instanta). Astfel de metode se numesc metode ale instantelor clasei .
Metodele de instanta sunt aplicate unui anume obiect, nu unei clase intregi. M ajoritatea metodelor
definite intr -o clasa sunt metode de instanta.

Metode de clasa
Dupa cum stim deja, exista si un alt tip de variabile si anume variabilele de clasa sau variabilele statice
care sunt comune tuturor instantelor clasei respective. Aceste variabile pot fi accesate fara a avea
nevoie de o instanta a clasei in care au fost declarate.
In mod similar exista si metode de clasa sau metode statice . Pentru a fi apelate, aceste metode, definite
intr-o clasa, nu au nevoie sa fie creata o instanta a clasei respective sau a subclasei derivata din clasa
respectiva. Metodele de clasa sunt disponibile oricarei instante a clasei.
Metodele de clasa nu folosesc variabilele de instanta, in schimb pot sa foloseasca variabilele de clasa
(variabile statice) decl arate in interiorul clasei in care au fost definite.
Intr-o metoda de clasa se pot apela metode de instanta dar cu precalificarea acestora cu numele
instantei.
Pentru a defini metode de clasa se foloseste modificatorul static , pozitionat in fata definitiei metodei, la
fel ca in cazul declararii variabilelor de clasa.
Ca si in cazul variabilelor de clasa, o metoda de clasa poate fi apelata fie conform regulii generale prin
precalificarea numelui metodei cu numele instantei (despartite de operatorul punct), fie direct, prin
precalificarea numelui metodei cu numele clasei (despartite de operatorul punct).
De exemplu, Java contine clase pentru fiecare dintre tipurile de baza: Byte , Integer , Long , Float , Double ,
Boolean , Character , Short . Fiecare din aceste clas e contin metode care se aplica oricarei instante a
clasei respective. De exemplu, putem folosi metodele de clasa care realizeaza conversia obiectelor in
tipuri primitive si invers ( parseInt , parseFloat etc sau toString ).
Metodele de clasa pot fi de asemene a folositoare pentru adunarea intr -un singur loc (o clasa) a unor
metode generale. De exemplu, clasa Math contine un set larg de operatii matematice definite cu
metode de clasa – nu exista instante ale clasei Math .
Domeniul de vizibilitate (acces) al metod elor unei clase. Modificatori de acces
O metoda este accesibila (apelabila) daca este definita in clasa din care este apelata sau intr -una din
subclasele acesteia. Atunci cand se apeleaza metoda unui obiect, Java cauta definitia metodei respective
in clasa obiectului. Daca nu o gaseste, cauta mai sus in ierarhia de clase pana cand gaseste o definitie.
In acelasi timp pentru a “vedea” o metoda si pentru a o putea apela, este nevoie sa avem drepturile de
acces necesare (date de modificatorii de acces).
Modif icatorii de acces (vizibilitate) ai metodelor unei clase
In Java exista trei modificatori de acces ai metodelor unei clase:
– modificatorul public ;
– modificatorul protected ;
– modificatorul private .

Modificatorul public face ca metoda respectiva sa fie ac cesibila oriunde este accesibila clasa din care
face parte metoda.
Modificatorul protected face ca metoda respectiva sa fie accesibila in orice clasa din pachetul careia ii
apartine clasa in care a fost definita. In acelasi timp, metoda este accesibila in toate subclasele clasei
date, chiar daca ele apartin altor pachete.
Modificatorul private face ca metoda respectiva sa fie accesibila doar in interiorul clasei in care a fost
definita.
Daca pentru o metoda a unei clase nu se precizeaza nici un modificator de acces din cei descrisi mai sus,
atunci metoda respectiva devine package -friendly . O metoda friendly este accesibila in pachetul din
care face parte clasa in interiorul careia a fost definita, dar nu este accesibila in subclasele clasei date
daca acestea apartin altor pachete.
Nota : Modificatorii de acces ( public , protected , private ) sunt plasati primii in definitia metodei, urmeaza
apoi modificatorii care determina felul metodei ( static , abstract , final ) si apoi semnatura metodei.
Urmatorul program (TestCerc.java) ilustreaza modul de folosire al variabilelor de instanata, precum si al
metodelor de instanta. In clasa Cerc variabila de instanta este raza care este vizibila numai in clasa in
care a fost declarata (are modificatorul private ). De aceea, accesul la aceasta variabila (pentru
examinare si modificare) se face numai prin intermediul metodelor setRaza si getRaza care sunt publice.
class Cerc
{
private double raza;
public void setRaza(double r) {
raza = r; }
public double getRaza() {
return raza; }
public double arie() {
return Math.PI * raza * raza; }
public double lungime() {
return 2 * Math.PI * raza; }
}
public class TestCerc
{
public static void main(String[] args) {
Cerc cerculMeu = new Cerc();

cerculMe u.setRaza(10);
System.out.println("Raza=" + cerculMeu.getRaza());
System.out.println("Aria=" + cerculMeu.arie());
System.out.println("Lungimea=" + cerculMeu.lungime());
}
}
Observatie: Deoarece fisierul -sursa TestCerc.java contine o clasa publi ca, TestCerc , numele fisierului
trebuie sa fie identic cu numele clasei publice, altfel compilarea nu se va face cu succes. Intr -un fisier –
sursa nu se poate defini decat o singura clasa publica.
Referinta this
Cuvantul -cheie this se refera la obiectul cure nt, adica obiectul a carei metoda a fost apelata. Metoda
poate folosi variabilele de instanta ale obiectului curent sau poate transmite obiectul curent ca
parametru unei alte metode. Iata cateva exemple de folosire a cuvantului this:
t = this.x; // variabi la de instanta x pentru obiectul curent
this.resetRaza(this); // apeleaza metoda resetRaza, definita in clasa curenta si
// transmite obiectul curent
return this; // returneaza obiectul curent
In cele mai multe cazuri nu este nevoie sa se foloseasca exp licit cuvantul -cheie this, deoarece este
presupus. De exemplu, ne putem referi atat la variabilele de instanta, cat si la apelurile de metode
definite in clasa curenta prin simpla folosire a numelui lor, deoarece this este implicit folosit de aceste
referi nte.
De aceea, primele doua exemple se pot rescrie astfel:
t = x; // variabila de instanta x pentru obiectul curent
resetRaza(this); // apeleaza metoda resetRaza, definita in clasa curenta si transmite obiectul curent.
Nu se omite cuvantul -cheie this daca in domeniul de vizibilitate al obiectului curent au fost definite
variabile locale cu acelasi nume ca cel al unei variabile de instanta sau au fost transmisi unei metode, a
obiectului curent, parametrii cu acelasi nume ca cel al unei variabile de instanta . Aceste aspecte au fost
explicate la paragraful referitor la domeniul de vizibilitate al variabilelor clasei.
Nota : Deoarece this este o referinta a instantei curente a clasei, trebuie sa se foloseasca doar in corpul
unei definitii de metoda de instanta. Metodele de clasa, declarate cu modificatorul static , nu pot folosi
this.
Metode constructor
Pe langa metodele obisnuite, in clase se pot include si metode constructor.

O metoda constructor este o metoda apelata atunci cand obiectul este creat si initializat, folosind
operatorul new .
Spre deosebire de alte metode, o metoda constructor nu poate fi apelata direct in cadrul programului ;
Java apeleaza metodele constructor in mod automat.
Atunci cand este folosit operatorul new pentru crearea unei instante a unei clase, Java executa trei
activitati:
– aloca memorie pentru obiect;
– initializeaza variabilele de instanta ale obiectului f ie la valorile initiale date de programator, fie
la cele implicite ( 0 pentru numere, null pentru obiecte, false pentru valori booleene, si ‘\0’ pentru
caractere);
– apeleaza metodele constructor ale clasei.
Daca la definirea clasei nu se furnizeaza nici u n constructor, compilatorul creaza automat un constructor
implicit care initializeaza fiecare membru al clasei cu valorile implicite.
Prin definirea unor metode constructor in interiorul unei clase, se pot seta valorile initiale ale
variabilelor de instant a, se pot apela metode pe baza acestor variabile, se pot apela metode ale altor
obiecte etc.
Metodele constructor au doua caracteristici de baza:
– au intotdeauna acelasi nume cu cel al clasei;
– nu returneaza nici o valoare.
Urmatorul program (TestCercC ons.java) prezinta clasa Cerc care are trei variabile de instanta: raza si
coordonatele centrului cercului, x si y. Clasa Cerc foloseste o metoda constructor pentru a -si initializa
variabilele de instanta pe baza argumentelor primite de new .
class Cerc
{
private double raza;
private int x, y;
Cerc(int coordX, int coordY, double lungRaza) {
x = coordX;
y = coordY;
raza = lungRaza;
}
public void setRaza(double r) {

raza = r; }
public double getRaza() {
return raza; }
public int getX() {
return x; }
public int getY() {
return y; }
public double arie() {
return Math.PI * raza * raza; }
public double lungime() {
return 2 * Math.PI * raza;}
}
public class TestCercCons
{
public static void main(String[] args) {
Cerc cerculMeu = ne w Cerc(3, 9, 20);
System.out.println("Raza=" + cerculMeu.getRaza());
System.out.println("Centrul cercului este in punctul: x= " +
cerculMeu.getX() + " y= " + cerculMeu.getY());
System.out.println("Modificarea razei cercului");
cerculMeu.set Raza(10);
System.out.println("Raza=" + cerculMeu.getRaza());
System.out.println("Aria=" + cerculMeu.arie());
System.out.println("Lungimea=" + cerculMeu.lungime());
}
}
Supraincarcarea metodelor constructor

Ca si metodele obisnuite, constructori i pot avea un numar diferit de parametrii sau tipuri diferite pentru
acestia desi au acelasi nume. Folosirea mai multor constructori cu acelasi nume dar cu parametrii care
difera prin numar si/sau tip poarta denumirea de supraincarcarea metodelor construct or.
Aceasta tehnica ne permite sa cream un obiect cu proprietatile dorite sau ne da posibilitatea sa cream
obiecte care sa isi seteaza proprietatile pornind de la date de intrare diferite.
Cuvantul -cheie this pentru constructori
Multe clase dispun de mai multi constructori care au un comportament similar. Putem folosi cuvantul –
cheie this in cadrul unei metode constructor pentru a apela ceilalti constructori ai clasei.
Apelul unei metode constructor definita in clasa curenta, folosind this se face astfel:
this(<arg1>, <arg2>, <arg3>, …)
unde:
– <arg1>, <arg2>, <arg3>, … – specifica parametrii metodei constructor.
Intotdeauna apelul lui this trebuie sa fie prima instructiune din metoda constructor, celelalte instructiuni
urmand dupa aceasta.
Urmatorul progra m (TestCercCons.java) prezinta clasa Cerc care are trei variabile de instanta: raza si
coordonatele centrului cercului, x si y. Clasa Cerc foloseste doua metode constructor: unul in care sunt
initializate variabilele de instanta pe baza datelor furnizate d e parametrii lui new , si unul in care
coordonatele x si y sunt preluate pe baza datelor furnizate de new dar variabila raza primeste valoarea
prestabilita 1.
class Cerc
{
private double raza;
private int x, y;
Cerc(int coordX, int coordY, double lungRaz a) {
x = coordX;
y = coordY;
raza = lungRaza;
}
Cerc(int coordX, int coordY) {
this(coordX, coordY, 1);
}
public void setRaza(double r) {

raza = r; }
public double getRaza() {
return raza; }
public int getX() {
return x; }
public int ge tY() {
return y; }
public double arie() {
return Math.PI * raza * raza; }
public double lungime() {
return 2 * Math.PI * raza;}
}
public class TestCercCons
{
public static void main(String[] args) {
{System.out.println("Crearea obiectului cu primul constructor");
Cerc cerculMeu = new Cerc(3, 9, 20);
System.out.println("Raza=" + cerculMeu.getRaza());
System.out.println("Centrul cercului este in punctul: x= " +
cerculMeu.getX() + " y= " + cerculMeu.getY());}
System.out.println("Crearea obiectului cu al doilea constructor");
Cerc cerculMeu = new Cerc(3, 9);
System.out.println("Raza=" + cerculMeu.getRaza());
System.out.println("Centrul cercului este in punctul: x= " +
cerculMeu.getX() + " y= " + cerculMeu.getY());
System.out.println("Modificarea razei cercului");
cerculMeu.setRaza(10);
System.out.println("Raza=" + cerculMeu.getRaza());
System.out.println("Aria=" + cerculMeu.arie());

System.out.println("Lungimea=" + cerculMeu.lungime());}
}
Dupa executia programului pe ecran se afiseaza urmatoarele:
Crearea obiectului cu primul constructor
Raza=20.0
Centrul cercului este in punctul: x= 3 y= 9
Crearea obiectului cu al doilea constructor
Raza=1.0
Centrul cercului est e in punctul: x= 3 y= 9
Modificarea razei cercului
Raza=10.0
Aria=314.1592653589793
Lungimea=62.83185307179586
Initializatori statici
La incarcarea in memorie a unei clase (deci inainte de a fi creata prima instanta) sunt automat initializate
toate variabilele statice declarate in interiorul clasei. In plus, sunt apelati toti initializatorii statici ai
clasei.
Un initializator static ar e urmatoarea sintaxa :
static {<set_instructiuni>}
Setul de instructiuni din initializatorul static este executat automat la incarcarea clasei in memorie.
De exemplu, putem defini un initializator static in felul urmator:
class A {
static double a;
static int b;
static {
a = Math.random(); // numar aleator intre 0.0 si 1.0
b = (int) (a * 500); // numar intreg intre 0 si 500
}
// restul clasei

}
Declaratiile de variabile statice si initializatorii statici sunt exe cutate in ordinea in care apar in clasa.
De exemplu:
class A {
static int i = 11;
static {
i += 100;
i %= 55;
}
static int j = i + 1;
// restul clasei
}
Valoarea finala a lui i va fi 1 ((11+100) % 55) iar valoarea lui j va fi 2.

Curs 6
Cuvinte importante:
– mostenire: derivare; superclase si subclase; ierarhie de clase; clasa Object ; mostenire simpla si
multipla; sintaxa pentru derivarea unei clase dintr -o superclasa; controlul accesului si mostenirea;
metode -constructor pentru clase derivate si cuvantul -cheie super ; supraincarcarea (overloading)
metodelor; redefinirea (override) met odelor;
– polimorfism: caracteristicile polimorfismului; legarea statica si legarea dinamica;
– metode si clase finale; metode si clase abstracte;
– exemplu de folosire a mostenirii, a polimorfismului, a claselor si metodelor finale si abstracte.
Most enirea – concept fundamental al programarii orientata obiect
Conceptul de mostenire este folosit in Java la organizarea claselor si a comportamentului acestora.
Mostenirea este mecanismul fundamental pentru refolosirea codului.
Mostenirea este un mecanism care permite unei clase sa mosteneasca atributele si comportamentul
unei alte clase cu care este inrudita. Mostenirea modeleaza relatii de tipul ESTE -UN (sau ESTE -O). Intr -o
relatie de tip ESTE -UN, spunem despre o clasa nou creata ca ESTE -O variatiune a un ei clase existente
(originala, din care provine). De exemplu, Masina ESTE -UN Vehicul .

Practic, prin mostenire o clasa noua dobandeste toate atributele si comportamentul unei clase existente
(clasa originala). Din acest motiv, noua clasa poate fi creata pr in simpla specificare a diferentelor fata de
clasa originala din care provine.
Datorita relatiilor de mostenire clasele de obiecte sunt organizate intr -o ierarhie bine precizata.
In cadrul ierarhiei claselor de obiecte, operatia de definire a unei noi cl ase de obiecte pe baza uneia deja
existente se numeste derivare . Clasa originala (mai generala) se va numi superclasa a noii clase, iar noua
clasa de obiecte se va numi subclasa a clasei din care deriva.
Uneori, in loc de derivare se foloseste termenul de extindere . Termenul vine de la faptul ca o subclasa isi
extinde superclasa cu noi variabile si metode.
De exemplu, putem extinde clasa Masina la MasinaStraina (pentru care se plateste vama) si
MasinaAutohtona (pentru care nu se plateste vama) etc.
Observa tie importanta: Un alt tip de relatie intre obiecte este relatia ARE -UN sau ESTE -COMPUS -DIN. De
exemplu, Masina ARE -UN volan. Aceasta relatie nu este o relatie de mostenire, ci este de agregare .
Componentele care pot fi agregate devin simple campuri (atrib ute) de tip private ale clasei nou create.
Intr-o ierarhie de clase, o clasa poate avea o singura superclasa , insa poate avea un numar nelimitat de
subclase. Subclasele mostenesc toate atributele si metodele superclasei lor, care la randul ei mosteneste
toate atributele si metodele de la superclasa ei si asa mai departe, urcand in ierarhie. Rezulta ca o clasa
nou creata contine toate atributele si metodele claselor aflate deasupra sa in ierarhie, si in plus contine
propriile atribute si metode.
Figura de mai jos prezinta o ierarhie de clase .

Clasa A este superclasa a clasei B. Clasa B este subclasa a clasei A.
Clasa B este superclasa pentru clasele C, D si E. Clasele C, D si E sunt subclase ale clasei B.
In varful ierarhiei de clase Java se afla clasa Object , iar toate clasele de obiecte, care se creaza, sunt
derivate din aceasta unica superclasa.
Object reprezinta clasa initiala, sa -i spunem clasa de obiecte generice, care defineste atributele si
comportamentul (metodele) mostenite de toate clasele din biblioteca de clase Java. In varful ierarhiei se
Clasa A
Clasa B
Clasa D
Clasa C
Clasa E

definesc concepte (clase) abstracte, foarte generale. Aceste concepte generale devin din ce in ce mai
concrete, mai particularizate, odata cu “cobo rarea” spre subclasele de pe nivelele de mai jos in ierarhie.
Cand clasa nou creata defineste un comportament complet nou si nu este o subclasa a unei alte clase,
atunci ea mosteneste direct clasa Object . Astfel, noua clasa se integreaza corect in ierarhia claselor Java.
De asemenea, daca se defineste o clasa care nu specifica o superclasa, Java presupune ca noua clasa
mosteneste direct clasa Object . Clasele definite in exemplele de pana acum au mostenit direct clasa
Object .
De exemplu, se poate construi o ierarhie Om care deriva direct din clasa generica Object si are doua
clase derivate: clasa barbatilor ( Barbat ) si clasa femeilor ( Femeie ).

Daca la nivelul clasei de obiecte Om am definit forma bipeda a acestuia si capacitatea de a vorbi si de a
intelege, toate aceste caracteristici vor fi mostenite si de clasele derivate din clasa Om, si anume clasa
barbatilor si cea a femeilor. Fiecare din aceste clase de obiecte derivate isi vor defini propriile lor
proprietati si operatii pentru a descrie diferenta dintre ele si clasa originala.
Caracteristicile unei ierarhi de clase
Organizarea unei aplicatii informatice intr -o ierarhie de clase presupune o planificare atenta. Proiectarea
arborelui de clase de obiecte necesare rezolvarii unei anumite probleme este un talent pe care fiecare
programator trebuie sa si -l descopere si sa si -l cultive cu atentie. De alegerea claselor si de proiectarea
arborelui acestor clase depinde eficienta si fl exibilitatea aplicatiei.
Principalele caracteristici ale unei ierarhie de clase sunt:
– atributele si metodele comune mai multor clase pot fi definite in superclase, care permit
folosirea repetata a acestora pentru toate clasele aflate pe nivelele mai jo ase din ierarhie;
– modificarile efectuate in superclasa se reflecta automat in toate subclasele ei, subclasele
acestora si asa mai departe; nu trebuie modificat si recompilat nimic in clasele aflate pe nivelurile
inferioare, deoarece acestea primesc noil e informatii prin mostenire;
– clasa derivata poate sa adauge noi atribute si metode si poate modifica semnificatia metodelor
mostenite (prin polimorfism, despre care vom vorbi mai incolo in acesta lectie);
– superclasa nu este afectata in nici un fel de modificarile aduse in clasele derivate;
Obiect (Object)
Om
Barbat
Femeie

– o clasa derivata este compatibila ca tip cu superclasa, ceea ce inseamna ca o variabila referinta
de tipul superclasei poate referi un obiect al clasei derivate, dar nu si invers; clasele derivate dintr -o
supercla sa nu sunt compatibile ca tip.
Mostenirea simpla si multipla
Forma de mostenire folosita in Java este denumita mostenire simpla (single inheritance), deoarece
fiecare clasa de obiecte Java nou creata poate fi derivata dintr -o singura superclasa (poate av ea o
singura superclasa).
Mostenirea multipla inseamna ca o clasa nou creata pot fi derivata din doua sau mai multe superclase,
mostenind variabilele si metodele combinate din toate aceste superclase. Mostenire multipla (multiple
inheritance) ofera mijloace de creare a unor clase care cuprind aproape orice comportament imaginabil.
Acest lucru complica semnificativ definitia clasei si a codului necesar acesteia.
Mostenirea simpla poate fi restrictiva , mai ales atunci cand exista un comportament similar, care trebuie
duplicat pe diferite “ramuri” ale i erarhiei de clase (nu pe aceeasi ramura a ierarhiei).
De exemplu, omul poate fi privit ca un mamifer care naste pui vii sau poate fi privit ca un obiect spatio –
temporal care are propria lui forma si pozitie in functie de timp. Aceasta inseamna ca trebuie sa dam
definitii de metode despre ce inseamna faptul ca un om poate fi privit ca un mamifer sau ca un obiect
spatio -temporal. Dar, aceste definitii de metode sunt comune nu numai clasei de obiecte Om dar si altor
clase de obiecte derivate sau nu din clasa Om, superclase sau nu ale clasei Om. Putem sa gasim o
multime de clase de obiecte ale caror instane pot fi privite ca obiecte spatio -temporale dar care sa nu
aiba mare lucu in comun cu omul (de exemplu clasa Minge ).
Pentru rezolvarea problemei mostenirii m ultiple , Java foloseste interfetele .
Declaratiile de metode si atribute comune mai multor clase de obiecte care nu sunt mostenite de la
superclasele lor poarta denumirea de interfeta . Interfetele vor fi prezentate in totalitate intr -o lectie
viitoare.
Sintaxa folosita pentru a deriva o clasa noua dintr -o superclasa
O clasa derivata (numita si subclasa) mosteneste toate atributele (variabilele de instanta si de clasa) si
metodele superclasei din care provine. Clasa derivata poate apoi sa adauge noi atribute, sa redefineasca
metode ale superclasei sau sa adauge noi metode. Fiecare clasa derivata este o clasa complet noua.
Pentru a declara o clasa derivata se foloseste clauza extends , astfel:
[<modificatori_acces>] [<modificatori_clasa>] class <nume_subclasa> extends
<nume_superclasa>
{
<corpul_clasei>
}
unde:

– <modificatori_acces> – specifica domeniul de vizibilitate (folosire sau acces) al subclasei; modificatorul
de acces poate fi: public ;
– <modificatori_clasa> – specifica tipul subclasei defini te; modificatorul clasei poate fi: abstract , final ;
– <nume_subclasa> – specifica numele clasei derivate dintr -o superclasa;
– <nume_superclasa> – specifica numele unei superclase din care deriva subclasa;
– <corpul_clasei> – variabilele clasei si metodel e care lucreaza cu acestea, adaugate sau redefinite in
subclasa .
Observatii:
1. Orice metoda neprivata (adica publica, protejata sau prietenoasa) din superclasa, care nu este
redefinita (suprascrisa) in clasa derivata, este mostenita nemodificat, cu exce ptia constructorilor.
Metoda poate fi apoi apelata ca si cum ar face parte din clasa derivata.
2. Clasa derivata contine atribute si metode suplimentare (fata de cele mostenite din superclasa) care
pot fi declarate: private , protected , public sau fara mod ificator de acces.
Controlul accesului si mostenirea
Ca regula generala, toti membrii de tip public ai superclasei devin membrii de tip public ai clasei
derivate.
De asemenea, membrii de tip private ai superclasei sunt mosteniti, dar acestia nu sunt accesi bili in mod
direct (adica, folosind operatorul “punct” sau direct numele membrului) in clasa derivata, ci prin
intermediul altor metode publice mostenite de la superclasa care fac posibil accesul.
Metodele speciale care examineaza si modifica valoarea fiec arui atribut de tip private sunt denumite
“accesori” si, respectiv, “ modificatori ”.
Se foloseste conventia ca numele metodelor “accesor” sa inceapa cu get, cum ar fi getRaza() din
programul TestCerc.java prezentat in lectia 5. De asemenea, se foloseste c onventia ca numele
metodelor “modificator” sa inceapa cu set, cum ar fi setRaza() din programul TestCerc.java prezentat in
lectia 5.
Folosirea metodelor “accesori” si “modificatori” este foarte raspandita in programarea orientata obiect.
Acest mod de abordare mareste gradul de reutilizare a codului, evitand folosirea lui necorespunzatoare.
Metode -constructor pentru clase derivate si cuvantul -cheie super
Metodele -constructor nu se mostenesc. Fiecare clasa derivata trebuie sa isi defineasca propriile met ode-
constructor.
Daca nu se defineste nici un constructor, Java va genera un constructor implicit (fara parametri). Acest
constructor implicit al clasei derivate:
– va apela automat constructorul implicit (fara parametrii) al superclasei (aflata pe nivelul
imediat superior) pentru membrii care au fost mosteniti, apoi

– va aplica initializarea implicita pentru atributele adaugate in clasa derivata (adica 0/false
pentru tipurile primitive numerice/booleene si null pentru tipurile referinta).
Asadar, c onstruirea unui obiect al unei clase derivate are loc prin construirea prealabila a portiunii
mostenite (constructorul clasei derivate apeleaza automat constructorul superclasei aflata pe nivelul
imediat superior). Acest lucu este normal, deoarece mecanism ul incapsularii afirma ca partea mostenita
este un “intreg”, iar constructorul superclasei ne spune cum sa initializam acest “intreg”.
Metodele -constructor ale superclasei pot fi apelate explicit in clasa derivata prin metoda super() .
Metoda super poate s a apara doar in prima linie dintr -o metoda -constructor a clasei derivate.
Apelul unei metode -constructor a superclasei dintr -o clasa derivata, folosind super se face astfel:
super(<arg1>, <arg2>, <arg3>, …)
unde:
– <arg1>, <arg2>, <arg3>, … – specifica par ametrii metodei -constructor a superclasei.
De exemplu, sa presupunem ca o superclasa (ClasaSuper) are un constructor cu doi parametri de tip int.
Constructorul clasei derivate va avea, in general, forma:
public class ClasaDerivata extends ClasaSuper
{
public ClasaDerivata(int x, int y);
{
super (x, y);
// alte instructiuni
}

}
Observatie: Daca in superclasa este definit explicit cel putin un constructor, atunci trebuie apelat explicit
(prin super ) constructorul superclasei respective din interiorul c onstructorului clasei derivate. Altfel se
obtine eroare de compilare.
Supraincarcarea (overloading) metodelor. Redefinirea (override) metodelor
Supraincarcarea metodelor permite existenta in interiorul aceleiasi clase a mai multor metode cu
acelasi nume, d ar cu lista diferita de parametrii (ca numar si tip), deci cu semnatura diferita .
Supraincarcarea metodelor este permisa si daca unele dintre metode sunt definite intr -o superclasa si
altele in clasele derivate din superclasa respectiva.

De exemplu, putem avea o metoda int max(int a, int b) si o metoda int max(int a, int b, int c) , ambele in
cadrul aceleasi clase sau putem defini prima metoda in cadrul unei superclase si cea de a doua metoda
in cadrul unei clase derivate din superclasa.
Atunci cand se face un apel al unei metode supraincarcate, compilatorul alege definitia de metoda
examinand lista parametrilor de apel (adica, semnatura).
Redefinirea (suprascriere) metodelor permite existenta in interiorul claselor derivate dintr -o superclasa
a mai multor metode cu acelasi nume, tip de rezultat si aceeasi lista de parametrii , deci cu aceeasi
semnatura .
Atunci cand se face un apel al unei metode redefinite, compilatorul foloseste definitia metodei care este
gasita prima (incepand din partea de jos a ierarhiei de clase si mergand in sus).
Programul urmator (AfisareSubClasa.java) prezinta o clasa ce contine o metoda afisareDate() , care
afiseaza numele clasei si valorile variabilelor de instanta. De asemenea, in acelasi fisier -sursa este inclusa
si clasa denumi ta AfisareSubClasa derivata din clasa AfisareClasa . A fost creat un obiect de tip
AfisareSubClasa si a fost apelata metoda afisareDate() . Deoarece clasa AfisareSubClasa nu defineste
aceasta metoda, Java o cauta in superclasele clasei AfisareSubClasa , incep and cu superclasa
AfisareClasa , unde gaseste metoda afisareDate() si o executa.
class AfisareClasa {
int x = 0;
int y = 1;
void afisareDate() {
System.out.println("x este " + x + ", y este " + y);
System.out.println("Sunt un obiect al clasei " +
this.getClass().getName());
}
}
class AfisareSubClasa extends AfisareClasa {
int z = 3;
public static void main(String [] args) {
AfisareSubClasa ob = new AfisareSubClasa();
ob.afisareDate();
}
}
Rezultatul programului este:

x este 0, y este 1
Sunt un obiect al clasei AfisareSubClasa
Deoarece metoda afisareDate() a superclasei AfisareClasa nu afiseaza si variabila de instanta z specifica
subclasei AfisareSubClasa , metoda afisareDate() va fi redefinita (suprascrisa) in interiorul subclasei. Iata
noul program (AfisareSubClasa.java):
class AfisareClasa {
int x = 0;
int y = 1;
void afisareDate() {
System.out.println("x este " + x + ", y este " + y);
System.out.println("Sunt un obie ct al clasei " +
this.getClass().getName()); } }
class AfisareSubClasa extends AfisareClasa {
int z = 3;
void afisareDate() {
System.out.println("x este " + x + ", y este " + y + ", z este " + z);
System.out.println("Sunt un obiect al clasei " +
this.getClass().getName()); }
public static void main(String [] args) {
AfisareSubClasa ob = new AfisareSubClasa();
ob.afisareDate();} }
Rezultatul programului este:
x este 0, y este 1, z e ste 3
Sunt un obiect al clasei AfisareSubClasa
Nota: Apelul de metoda:
this.getClass().getName());
este folosit pentru aflarea numelui clasei din care face parte un obiect, in cazul de fata obiectul curent.
Vom reveni cu amanunte in ce priveste obtinerea d e informatii despre o clasa.
Redefinirea partiala a unei metode

Redefinirea partiala inseamna ca metoda din clasa derivata nu redefineste complet metoda cu aceeasi
semnatura din superclasa, ci extinde operatiile pe care aceasta le realizeaza. Cu alte cuvin te, metoda din
clasa derivata face ceva in plus fata de cea originala din superclasa.
Pentru a apela metoda din superclasa in interiorul metodei din clasa derivata se foloseste referinta
super .
Urmatorul program (AfisareSubClasa1.java) ilustreaza modul de redefinire partiala a metodei
afisareDate() din subclasa AfisareSubClasa1 si apelul in cadrul acesteia a metodei afisareDate() din
superclasa AfisareClasa .
class AfisareClasa {
int x = 0;
int y = 1;
void afisareDate() {
System.out.println("Sunt un obiect al clasei " +
this.getClass().getName());
System.out.println("x este " + x);
System.out.println("y este " + y);
}
}
class AfisareSubClasa1 extends AfisareClasa {
int z = 3;
void afisareDate() {
super.afisareDate();
System.out.println("z este " + z);
}
public static void main(String [] args) {
AfisareSubClasa1 ob = new AfisareSubClasa1();
ob.afisareDate();
}
}
Accesul la metodele din superclasa si redefinirea metodelor in clasele derivate

Atunci cand s e creaza o clasa derivata si se redefineste (suprascrie) o metoda declarata intr -o
superclasa, trebuie sa se ia in considerare tipul de acces dat pentru metoda originala.
Astfel, in cazul metodelor mostenite, pentru care se doreste redefinirea (suprascrier ea) in clasa derivata
se impun urmatoarele reguli:
– metodele de tip public dintr -o superclasa trebuie sa fie, de asemenea, de tip public in toate
clasele derivate; ele nu pot fi redefinite de tip private in clasele derivate;
– metodele de tip protected dintr -o superclasa pot fi de tip protected sau de tip public in clasele
derivate; ele nu pot fi redefinite de tip private in clasele derivate;
– metodele de tip private dintr -o superclasa nu pot fi redefinite (suprascrise) in clasele derivate.
Polimorfism
Polimorfismul reprezinta capacitatea unui obiect de a aparea sub diferite forme. De exemplu, in lumea
reala, apa apare sub forma solida, sub forma lichida sau sub forma gazoasa.
In Java, polimorfismul inseamna ca o singura variabila referinta x de tipul u nei superclase poate fi
folosita pentru a construi diferite obiecte (instante) ale claselor derivate, direct sau indirect din acea
superclasa, in momente diferite ale executiei unui program. Cand variabila referinta x este folosita
pentru a apela o metoda a unui obiect apartinand unei clase derivate, metoda adecvata care va fi
selectata depinde de tipul obiectului pe care variabila referinta x il stocheaza in acel moment. Se spune
ca variabila referinta x este polimorfica .
De exemplu, sa presupunem ca s -au definit clasele: AnimalDeCasa , Pisica , Caine. Se doreste sa se afiseze
la ecran (programul Polimorfism.java) caracteristicile principale ale claselor Pisica si Caine , atunci cand
instantele lor sunt infometate.
class AnimalDeCasa
{
private boolean stareSu parare;
public boolean flamand;
protected void hranesc()
{
System.out.println("Nu se cunoaste");
}
public void caracteristici()
{
System.out.println("Caracteristici necunoscute");
}

public boolean getStare()
{
return stareSuparare;
}
public void setStare(boolean stare)
{
stareSuparare = stare;
}
}
class Pisica extends AnimalDeCasa
{
public void caracteristici()
{
String starePisica;
if (getStare() == true)
starePisica = "miauna";
else
starePisica = "nu miauna";
if (flamand == true)
System.out.println("Pisica " + starePisica + ". Este flamanda.");
else
System.out.println("Pisica " + starePisica + ". Este satula.");
}
public void hranesc()
{
if (flamand==true)
{System.out.println("Pisica mananca lapte.");
flamand = false;
setStare(false);}

else
System.out.println("Pisica a mancat deja.");}
}
class Caine extends AnimalDeCasa
{
public void caracteristici()
{
String stareCaine;
if (getStare() == true)
stareCaine = "latra";
else
stareCaine = "nu latra";
if (flamand == true)
System.out.println ("Cainele " + stareCaine + ". Este flamand.");
else
System.out.println("Cainele " + stareCaine + ". Este satul.");
}
public void hranesc()
{
if (flamand==true)
{System.out.println("Cainele mananca oase.");
flamand = false;
setStare(false);}
else
System.out.println("Cainele a mancat deja.");}
}
public class Polimorfism
{
public static void main(String args[])

{
AnimalDeCasa a = new Pisica();
a.flamand = true;
a.setStare(true);
System.out.println("Caracteristicile primului animal de casa: ");
a.caracteristici();
a.hranesc();
a.caracteristici();
a.hranesc();
a.caracteristici();
a = new Caine();
a.flamand = true;
a.setStare(true);
System.out.println("Caracteristicile celui de al doilea animal de casa: ");
a.caracteristici();
a.hranesc();
a.caracteristici();
}
}
Ceeace este specifi c acestui program este ca el contine trei metode cu numele caracteristici() care au
aceeasi semnatura (nume, tip valoare returnata si numar si tip parametrii) si trei metode cu numele
hranesc() care au, de asemenea, aceeasi semnatura. Dar, aceste metode se afla in clase diferite si
anume, intr -o superclasa numita AnimalDeCasa si in doua clase derivate numite Pisica si Caine care
extind clasa AnimalDeCasa .
Spunem ca metodele caracteristici() si hranesc() din clasele derivate redefinesc (override ) metodea
caracteristici() si, respectiv, hranesc() din superclasa.
Sa analizam acum instructiunea urmatoare:
AnimalDeCasa a = new Pisica();
Variabila referinta a care este de tipul AnimalDeCasa desemneaza un obiect de tipul Pisica , care ESTE –
UN AnimalDeCasa prin most enire.
Sa analizam si instructiunea:

a = new Caine();
Variabila a refera (la momente diferite de timp) obiecte de tipuri diferite, dar similare (adica derivate din
aceeasi superclasa: AnimalDeCasa ).
Pe baza celor prezentate mai sus, programul va afisa u rmatoarele rezultate:
Caracteristicile primului animal de casa:
Pisica miauna. Este flamanda.
Pisica mananca lapte.
Pisica nu miauna. Este satula.
Pisica a mancat deja.
Pisica nu miauna. Este satula.
Caracteristicile celui de al doilea animal de casa:
Cainele latra. Este flamand.
Cainele mananca oase.
Cainele nu latra. Este satul.
Dupa cum se poate observa, apelurile metodelor caracteristici() si hranesc() , prin intermediul referintei
a, au determinat apelarea metodelor corespunzatoare din clasa Pisica si Caine (si prin urmare doua
afisari diferite), deoarece la momentul fiecarui apel, variabila a refera un obiect de tip diferit (dar,
apartinand unei clase derivate din superclasa).
Trebuie de remarcat ca, inversarea rolurilor celor doua clase nu este po sibila, adica:
Pisica p = new AnimalDeCasa();
este incorecta (deoarece un animal nu este in mod obligatoriu o pisica).
In concluzie:
– pe de o parte, mostenirea permite tratarea unui obiect ca fiind de tipul propriu sau de tipul de
baza (din care este derivat tipul propriu). Aceasta caracteristica permite mai multor tipuri (derivate din
acelasi tip de baza) sa fie tratate ca si cum ar fi un singur tip, ceea ce face ca aceeasi secventa de cod sa
fie folosita de catre toate aceste tipuri . In cazul din exe mplul prezentat, clasa Pisica si clasa Caine au
doua atribute ( stareSuparare si flamand ) si doua metode setStare() si getStare() mostenite de la
superclasa AnimalDeCasa din care deriva.
– pe de alta parte, polimorfismul permite unui tip de obiect sa expri me distinctia fata de un alt
tip de obiect similar, atata timp cat amandoua sunt derivate din aceeasi superclasa. Distinctia este
exprimata prin redefinirea (suprascrierea) metodelor care pot fi apelate prin intermediul unei variabile –
referinta de tipul s uperclasei (in exemplul nostru este vorba despre metodele caracteristici() si
hranesc() ).

Legarea statica si legarea dinamica
Conectarea unui apel de metoda de un anumit corp de metoda poarta numele de legare (binding) .
Cand legarea are loc inainte de rul area programului respectiv (adica, in faza de compilare) spunem ca
este vorba despre o legare statica(early binding) . Termenul este specific programarii orientate pe
obiecte. In programarea procedurala (vezi limbajul C sau Pascal) notiunea de legare static a nu exista,
pentru ca toate legaturile se fac in mod static.
Cand legarea are loc in faza de executie a programului respectiv, spunem ca este vorba despre o legare
tarzie (late binding) sau legare dinamica . Legarea tarzie permite determinarea in faza de e xecutie a
tipului obiectului referit de o variabila referinta si apelarea metodei specifice acestui tip (in exemplul
prezentat, metodele caracteristici() si hranesc() din clasa Pisica sau din clasa Caine ).
Polimorfisul apare doar atunci cand are loc legare a tarzie a metodelor.
Metode si clase finale
Metodele finale sunt acele metode care nu pot fi redefinite niciodata intr -o subclasa. Acestea sunt
declarate folosind modificatorul final .
Metode finale sunt folosite pentru a mari viteza de executie a aplica tiei care le foloseste. In mod normal,
atunci cand interpretorul Java apeleaza o metoda, el cauta metoda mai intai in clasa curenta, dupa
aceea in superclasa si “urca” mai departe in ierarhie pana ce gaseste definitia acesteia. Prin acest proces
se pierde din viteza in favoarea flexibilitatii si a usurintei in dezvoltare.
In cazul metodelor finale legarea este statica, la compilare, si nu in timpul executiei aplicatiei. Astfel,
compilatorul Java poate introduce codul executabil (bytecode -ul) al metodei in locul instructiunii de apel
a acesteia in cadrul programelor care o apeleaza.
Nota: Metodele cu acces de tip private sunt implicit si de tip final , deoarece ele nu pot fi suprascrise in
nici o situatie.
Clasele finale sunt acele clase din care nu se pot d eriva subclase. Acestea sunt declarate folosind
modificatorul final .
Clasele finale sunt folosite pentru a mari viteza de executie a aplicatiei care le foloseste.
Majoritatea claselor mai des folosite din bibliotecile de clase Java sunt clase finale, cum ar fi:
java.lang.String, java.lang.Math, java.lang.Integer etc.
Nota: Toate metodele dintr -o clasa de tip final sunt automat finale.
Metode si clase abstracte
O me toda abstracta este o metoda din superclasa care are sens doar pentru clasele derivate direct din
superclasa, nu are implementare (nu are corp) ci numai antet, in superclasa si care in mod obligatoriu
trebuie definita (completata cu corpul ei) in clasele d erivate (altfel rezulta eroare de compilare).
O metoda abstracta este declarata cu modificatorul abstract .

Intr-o ierarhie de clase, cu cat clasa se afla pe un nivel mai inalt, cu atat definirea sa este mai abstracta.
O clasa aflata ierarhic deasupra alto r clase poate defini doar atributele si comportamentul comune celor
aflate sub ea pe ramura respectiva a ierarhiei.
In procesul de organizare a unei ierarhi de clase, se poate descoperi, uneori, cate o clasa care nu se
instantiaza direct (adica din ea nu se pot crea direct obiecte). De fapt, aceasta serveste, doar ca loc de
pastrare a unor metode si atribute pe care le folosesc in comun subclasele sale. Acesta clasa se numeste
clasa abstracta si este creata folosind modificatorul abstract .
Clasele abstrac te pot contine aceleasi tipuri de membri ca o clasa normala, inclusiv metodele –
constructor, deoarece subclasele lor pot avea nevoie sa apeleze aceste metode -constructor.
Clasele abstracte pot contine, de asemenea, metode abstracte. O clasa care are cel put in o metoda
abstracta este o clasa abstracta.
Nu se poate declara o metoda abstracta intr -o clasa non -abstracta.
Exemplu de folosire a mostenirii, a polimorfismului, a claselor si metodelor finale si abstracte
Un exemplu simplu de clasa abstracta este cla sa formelor geometrice. Din clasa formelor geometrice pot
deriva forme specifice cum ar fi: cerc, dreptunghi. Se poate, apoi, deriva clasa patratului ca un caz
particular de dreptunghi. Figura de mai jos prezinta ierarhia de clase care rezulta:

Clasa FormaGeo poate sa aiba membri care sa fie comuni pentru toate subclasele, cum ar fi, de exemplu
tipul formei geometrice, afisarea caracteristicilor formelor geometrice concrete (cerc, dreptunghi etc).
De asemenea, clasa poate defini metode care se aplica fiecarui obiect in parte, cum ar fi, calculul ariei
unui obiect oarecare (dreptunghi, cerc etc). In consecinta, metoda arie() va fi declarata ca abstracta.
Clasa FormaGeo fiind abstracta nu se poate ins tantia. Deci, nu se va putea crea un obiect de tip
FormaGeo, ci numai obiecte din clasele derivate. Totusi, o variabila referinta de tip FormaGeo poate sa
refere orice forma concreta derivata, cum ar fi: Dreptunghi , Cerc , Patrat .
Fisierul -sursa urmator (Fo rmaGeo.java) prezinta clasa abstracta FormaGeo . Constructorul acestei clase
nu va fi apelat niciodata direct, deoarece FormaGeo este o clasa abstracta. Avem totusi nevoie de
Cerc
Dreptunghi
Patrat
FormaGeo

constructor, care sa fie apelat din clasele derivate pentru a initializa atributul nume de tip private care
specifica tipul figurii geometrice.
Metoda cu numele arie() este o metoda abstracta, deoarece nu putem furniza nici un calcul implicit al
ariei pentru o clasa derivata care nu isi defineste propria metoda de calcul a ariei.
Metoda maiMic() de comparatie a ariei unui obiect curent de tip FormaGeo cu un alt obiect de tip
FormaGeo (preluat prin parametrul rhs) nu este abstracta, deoarece ea poate fi aplicata la fel pentru
toate clasele derivate. De fapt, definirea ei este invarianta de -a lungul ierarhiei, de aceea am declarat -o
cu tipul final .
Variabila rhs poate sa refere orice instanta a unei clase derivate din FormaGeo (de exemplu, o instanta a
clasei Dreptunghi ). Astfel, este posibil sa folosim aceasta metoda pentru a compara aria obiectului
curent (care poate fi, de exemplu, o instanta a clasei Cerc ) cu aria unui obiect de alt tip, derivat din
FormaGeo . Acesta este un exemplu de folosire a polimorfismului.
Metoda toString afiseaza numele formei geometrice si aria ei. Ea este invarianta de -a lungul ierarhiei si
de aceea a fost declarata cu tipul final .
Observatie: Vom face cateva precizari asupra folosirii metodei toString() in orice clasa in care se doreste
afisarea starii instantelor unei clase. In general, afisarea starii unui obiect se face utilizand metoda print()
din clasa System.out . Pentru a putea face acest lucru, trebuie ca in clasa obiectului care se doreste a fi
afisat sa existe o metoda cu numele de toString() . Aceasta metoda trebuie sa intoarca o valoare de tip
String (reprezentand starea obiectului) care poate fi afisata. Astfel, in cazul nostru, am definit o metoda
toString care permite sa afi sam un obiect oarecare de un tip derivat din clasa FormaGeo folosind
instructiunea System.out.println() . Practic, compilatorul Java apeleaza automat toString() pentru fiecare
obiect care se afiseaza cu metoda print().
/* Superclasa abstracta pentru forme F ormeGeo
*
* CONSTRUIREA: nu este permisa, FormaGeo fiind abstracta.
* Constructorul cu un parametru este necesar ptr. clasele
* derivate.
* ––––––- metode publice –––––––
* double arie() –> Intoarce aria (abstracta)
* boolean maiMic –> Compara doua forme dupa arie
* String toString –> Metoda uzuala pentru afisare
*/
abstract class FormaGeo {
private String nume;

abstract public double arie();
public FormaGeo(String numeForma) {
nume = numeForma;
}
final public boolean maiMic(FormaGeo rhs) {
return arie() < rhs.arie();
}
final public String toString() {
return nume + ", avand aria " + arie();
}
}
Pe baza clasei abstracte FormaGeo definite ne propunem sa rezolvam urmatoarea probl ema:
Se citesc N forme geometrice (patrate, dreptunghiuri, cercuri) de la tastatura. Sa se afiseze
formele geometrice ordonate dupa arie.
Mai intai, trebuie sa definim subclasele Cerc, Dreptunghi si Patrat . Definirea lor se face distinct in fisiere –
sursa separate (Cerc.java, Dreptunghi.java si Patrat.java).
/* clasa Cerc
* derivata din FormaGeo
* CONSTRUCTORI: cu raza ptr. cerc
* ––––––- metode publice –––––––
* double arie() –>Implementeaza metoda abstracta din FormaGeo
*/
public class Cerc extends FormaGeo {
private double raza;
public Cerc(double rad) {
super("Cerc");
raza = rad;
}
public double arie() {

return Math.PI * raza * raza;}
}
/* clasa Dreptunghi;
* derivata din FormaGeo
* CONSTRUCTORI: cu lungime si latime ptr. dreptunghi
* ––––––- metode publice –––––––
* double arie() –>Implementeaza metoda abstracta din FormaGeo
*/
public class Dreptunghi extends FormaGeo {
private double lungime;
private double latime;
public Dreptunghi(double lg, double lat) {
this(lg, lat, "Dreptunghi");
}
Dreptunghi(double lg, double lat, String nume) {
super(nume);
lungime = lg;
latime = lat;
}
public double arie() {
return lungime * latim e;
}
}
/* clasa Patrat
* derivata din Dreptunghi
* CONSTRUCTORI: cu latura ptr. patrat
* ––––––- metode publice –––––––
* double arie() –>Implementeaza metoda abstracta din FormaGeo
*/

public class Patrat extends Dreptunghi
{
public Patrat(double latura)
{
super(latura, latura, "Patrat");
}
}
Observatie: Clasa Patrat mosteneste de la clasa Dreptunghi metoda arie() si de aceea nu o mai defineste
in interiorul ei.
Pentru rezolvarea problemei ordonarii formelor geometrice dupa aria lor, se foloseste un tablou de tip
FormaGeo cu numele forme[] cu o dimensiune citita de la tastatura. Sa retinem ca tablou forme[] este
un tablou de referinte de tip FormaGeo pentru care s e aloca zona de memorie. Acest tablou nu
stocheaza obiecte din clasele derivate ale clasei FormaGeo (de tip Cerc, Dreptunghi, Patrat ) ci numai
referinte catre aceste obiecte.
Fisierul -sursa (TestForma.java) care realizeaza ordonarea si punerea in executie a aplicatiei se prezinta in
continuare.
Metoda citesteForma() citeste de la tastatura atributele obiectelor de tipul Cerc , Dreptunghi , Patrat , pe
baza unor optiuni care precizeaza tipul figurii, creaza un nou obiect de un tip derivat ( Cerc , Dreptunghi ,
Patrat) din tipul FormaGeo si returneaza o referinta catre obiectul creat.
In metoda main() , referinta la obiecte este apoi stocata in tabloul forme[] .
Metoda sortare() este folosita pentru a sorta formele geometrice referite prin tabloul forme[] in functi e
de aria calculata a fiecarui tip de figura geometrica. Metoda arie() este apelata prin intermediul metodei
maiMic() care la randul ei este apelata in metoda sortare() .
import java.io.* ;
class TestForma {
private static BufferedReader in;
public stati c void main(String[] args) throws IOException {
//Citeste numarul de figuri
in = new BufferedReader(new
InputStreamReader(System.in));
System.out.print("Numarul de figuri: ");
int numForme = Integer.parseInt(in.readLine());

//citeste formele
FormaGeo[] forme = new FormaGeo[numForme];
for (int i = 0; i < numForme; ++i)
{forme[i] = citesteForma() ;}
//sortare si afisare
sortare(forme);
System.out.println("Sortarea dupa arie: ");
for (int i = 0; i < numForme; ++i)
{System.out.println(forme[i]); }
}

//creaza un obiect adecvat de tip FormaGeo. Functie de datele de intrare.
//utilizatorul introduce 'c', 'p' sau 'd' pentru a indica forma, apoi introduce caracteristicile
//in caz de eroare se intoarce un cerc de raza 0
private static FormaGeo citesteForma() throws IOException {
double rad;
double lg;
double lat;
String s;
System.out.println("Introduceti tipul formei: ");
do
{
s = in.readLine();
} while (s.length() == 0);
switch (s.charAt(0))
{
case 'c':
System.out.println("Raza cercului: ");
rad = Integer.parseInt(in.readLine());

return new Cerc(rad);
case 'p':
System.out.println("Latura patratului: ");
lg = Integer.parseInt(in.readLine());
return new Patrat(lg);
case 'd':
System.out.println("Lungimea si latimea "
+ " dreptunghiului pe linii separate: ");
lg = Integer.parseInt(in.readLine());
lat= Integer.parseInt(in.readLine());
return new Dreptunghi(lg, lat);
default:
System.err.println("Tastati c, p sau d: ");
return new Cerc(0);
}
}
//sortare
private static void sortare(FormaGeo [] a) {
FormaGeo temp;
for (int i = 0; i <= a.length – 2; i++)
{for (int j = i+1; j <= a.length – 1; j++)
{if (a[j].maiMic(a[i] ))
{temp = a[i];
a[i] = a[j];
a[j] = temp;}
}}
}
}
Dupa executia programului TestForma.class pe ecran se afiseaza:

Sortarea dupa arie:
Cerc, avand aria 3.141592653589793
Dreptunghi, avand aria 6.0
Dreptunghi, avand aria 8.0
Dreptunghi, avand aria 24.0
Patrat, avand aria 36.0
Cerc, avand aria 78.53981633974483
Patrat, avand aria 100.0
Cerc, avand aria 314.1592653589793
Cerc, avand aria 452.3893421169302
Cerc, avand aria 452.3893421169302

Curs 7

Cuvinte importante:
– conversie de tip pentru obiecte: conversie implicita si explicita de tip (casting);
– conversia tipurilor primitive in obiecte si invers;
– pachete de clase de obiecte: utilizarea pachetelor existente de clase de obiecte; comanda
import; variabila CLASSPATH ; locul de dispunere a claselor in sistemul de fisiere; crearea propriilor
pachete de clase de obiecte; pachetele de clase si controlul accesului la clase;
– mostenire multipla;
– interfata Java: crearea interfetelor; folosirea interfetelor; implementarea unei interfete;
implementarea unor interfete multiple; derivarea interfetelor;
– implementarea de componente generice: programarea generica; clase generice.
Conversia explicita de tip (casting) pentru obiecte
Operatia de conv ersie a instantelor unor clase catre instante ale altor clase se poate face numai daca
clasele sursa si destinatie sunt inrudite prin mostenire, adica o clasa trebuie sa fie o subclasa a alteia.
Pentru ca mostenirea permite tratarea unui obiect ca fiind de tip propriu sau de tipul superclasei, unele
obiecte nu au nevoie de conversie explicita . Astfel, deoarece subclasele contin toate informatiile

superclasei lor, si chiar mai mult, se poate folosi o instanta a unei subclase acolo unde se doreste
referirea l a o instanta a superclasei.
La operatia de atribuire, conversia implicita inseamna ca unei variabile referinta de tipul unei superclase
i se poate atribui o referinta la o instanta de tipul oricarei subclase a ei. Variabila de tipul superclasei,
folosita i n acest fel, se spune ca este polimorfica.
Urmatorul exemplu arata o conversie implicita prin atribuirea valorii unei variabile referinta de tipul unei
subclase (clasa Pisica ) la o variabila de tipul unei superclase (clasa AnimalDeCasa ):
AnimalDeCasa a = n ew Pisica();
Variabila referinta a care este de tipul AnimalDeCasa desemneaza un obiect de tipul Pisica .
Conversia explicita intre tipurile obiectelor (sau casting -ul) este necesara atunci cand se foloseste o
instanta a superclasei acolo unde se doreste re ferirea la o instanta a subclasei.
Sintaxa folosita pentru conversia explicita de tip este:
(<nume_subclasa>) <nume_variabila_superclasa>
unde:
– <nume_subclasa> – numele subclasei catre care se doreste conversia;
– <nume_variabila_superclasa> – numele variabilei referinta care indica o instanta a unei
superclase din care face parte subclasa cu numele <nume_subclasa>.
Nota: Conversia unui tip derivat într -un tip de baza se numeste conversie de lărgire (upcasting) și se face
implicit. Conversia unui tip d e baza într -un tip derivat se numeste conversie de îngustare (narrowing,
downcasting) și se face explicit folosind operatorul cast ca mai sus . La downcasting pot aparea erori în
timpul execuție în cazul în care obiectul care se converteste nu a fost instan tiat ca și tip derivat.
De exemplu, daca avem o operatie care apeleaza metode ale obiectelor apartinand clasei Integer ,
folosirea unui obiect din clasa Object nu va dispune de multe din metodele definite in Integer si drept
urmare va fi necesara o conversi e explicita la tipul Integer , ca mai jos:
int elemVarf = ((Integer) s.top()).intValue();
In acest exemplu metoda s.top() returneaza un obiect de tip Object . Pentru a extrage valoarea retinuta
in acest obiect trebuie sa -l convertim explicit la tipul Integer , astfel incat sa dispunem de metoda
intValue() care returneaza valoarea obiectului convertit la Integer ca o valoare intreaga de tip int.
Conversia tipurilor primitive in obiecte si invers
Conversia de la un tip de data primitiv la un tip referinta si in vers nu este posibila in Java in mod implicit.
Tipurile primitive si obiectele sunt elemente foarte diferite in Java si nu se poate face conversie
automata intre cele doua. In acest sens se poate analiza si instructiunea prezentata mai sus.
Ca alternativa, pachetul Java.lang contine clase de obiecte care corespund fiecarui tip de date primitive:
Byte, Short, Integer, Long, Float, Double, Character, Boolean . Totusi, ele sunt interpretate diferit fata de
tipurile primitive corespondente si de aceea ele nu pot fi folosite in locul tipurilor primitive si nici invers.

Pentru a crea un obiect de un tip ca: Byte, Short, Integer, Long, Float, Double, Character, Boolean , se
foloseste operatorul new .
Urmatoarea instructiune creaza o instanta a clasei Integer cu valo area 44:
Integer numarInt = new Integer(44);
Obiectul numarInt se poate folosi ca orice alt obiect, beneficiind, in acelasi timp si de toate metodele
clasei Integer din biblioteca java.lang .
La fel se procedeaza si pentru celelalte clase de obiecte care c orespund tipurilor primitive.
Pentru a folosi valoarea dintr -un obiect de un tip: Byte, Short, Integer, Long, Float, Double, Character,
Boolean , ca valoare de tip primitiv corespunzator, se pot apela metode care realizeaza acest lucru.
Metodele des folosi te pentru transformarea valorii unui obiect de acest gen in valori de un tip primitiv
sunt:
byteValue() – pentru valori de tip byte ;
shortValue() – pentru valori de tip short ;
intValue() – pentru valori de tip int;
longValue() – pentru valori de tip long ;
floatValue() – pentru valori de tip float ;
doubleValue() – pentru valori de tip double ;
charValue() – pentru valori de tip char ;
booleanValue() – pentru valori booleene;
De exemplu, pentru a extrage o valoare int din obiectul numarInt , se foloseste urmatoa rea instructiune:
int numar = numarInt.intValue(); // returneaza valoarea 44.
Pachete de clase de obiecte
Un pachet (package) contine un numar de clase inrudite ca scop, ca domeniu sau din punct de vedere al
mostenirii.
Daca programele sunt mici si folose sc un numar limitat de clase, nu este necesar sa cream pachete. Insa
daca aplicatia noastra foloseste din ce in ce mai multe clase atunci este necesar sa le organizam in
pachete.
De ce sunt folositoare pachetele?
– Pachetele permit organizarea claselor in grupuri. Asa cum pe hard -disc avem directoare si
subdirectoare pentru a ne organiza fisierele si aplicatiile, pachetele ne permit sa organizam clasele in
grupuri din care putem folosi doar ceea ce avem nevoie pentru fiecare aplicatie.

– Pachetele reduc problemele datorate conflictelor de nume. Cu cat creste numarul claselor de
obiecte, cu atat creste posibilitatea de a folosi un nume de clasa deja existent, ceea ce va duce la
aparitia unor conflicte si erori la integrarea acestora in aplicatii. Pachetel e permit “ascunderea claselor”
si evitarea acestor conflicte.
– Pachetele protejeaza clasele, variabilele si metodele depasind nivelul de clasa.
– Pachetele pot fi folosite la identificarea claselor. De exemplu, daca implementam un set de
clase pentru a realiza o anumita sarcina, putem sa folosim pentru pachetul de clase respectiv un
identificator unic, care sa desemneze autorul sau organizatia din care provine.
Nota: Chiar daca un pachet este, in esenta, un grup de clase, acesta poate contine si alte pac hete, care
formeaza alt nivel ierarhic asemanator, cumva, ierarhiei de clase. Fiecare nivel reprezinta, de obicei, o
grupare mai mica de clase si cu sarcini mai precise. Biblioteca de clase Java este organizata si ea dupa
aceste principii.
Utilizarea pache telor existente de clase de obiecte
Stim ca pachetele grupeaza mai multe clase la un loc. Pana acum am folosit pachete din biblioteca Java
in legatura cu operatiile de I/O necesare citirii de la tastatura a datelor, pentru generarea unor obiecte
de tip Random etc.
Ca regula, putem alege unul dintre urmatoarele trei mecanisme pentru a utiliza o clasa continuta intr -un
pachet:
– cand clasa pe care dorim sa o folosim se afla in pachetul java.lang , ea se poate referi pur si
simplu prin numele ei;
– cand clasa pe care dorim sa o folosim se afla in alt pachet, ea se poate referi folosindu -i numele
complet, adica inclusiv pe cel al pachetului ( java.util.Random );
– pentru clasele din alte pachete folosite frecvent in aplicatie, se pot importa clasele individuale
sau intreg pachetul de clase folosit; dupa ce clasa sau pachetul au fost importate, se poate referi clasa
doar prin numele sau.
Nota: Clasele care nu sunt declarate ca facand parte dintr -un anumit pachet sunt automat incluse intr –
un pachet prestabilit. Ace ste clase pot fi referite prin numele lor, de oriunde din cod.
Comanda import
Pentru a importa clasele dintr -un pachet se foloseste comanda import , asa cum am vazut in multe
exemple prezentate pana acum.
Se poate importa o clasa ca in exemplul urmator:
import java.util.Random;
Se poate importa un intreg pachet de clase , folosind simbolul asterisc (*) in locul numelor de clasa,
astfel:
import java.io.*;

Nota: Comanda din exemplul de mai sus nu importa toate clasele pachetului; sunt importate doar acele
clase care au fost declarate public , si chiar si asa sunt importate doar acele clase care sunt referite in
cod. De asemenea, daca pachetul respectiv are si subpachete, prin comanda import din exemplul de mai
sus, nu se vor importa si subpachetele pachetului sp ecificat in comanda import .
Pentru a importa toate clasele dintr -o ierarhie complexa de pachete va trebui sa se importe explicit
fiecare nivel al ierarhiei.
Instructiunea import trebuie plasata inaintea oricarei definitii de clasa (insa dupa definitia pac hetului,
daca se doreste crearea unui pachet propriu, asa cu se va prezenta in sectiunea urmatoare).
Spre deosebire de directiva #include din limbajul C/C++, care include cod dintr -un alt fisier, instructiunea
import indica doar locul unde poate fi gasita o clasa si nu are nici un rol in marirea dimensiunii aplicatiei
proiectate.
Observatie: Trebuie evitate conflictele de nume de clasa, deoarece compilatorul va semnala o eroare.
Conflicul de nume de clasa are loc atunci cand doua clase din pachete diferite au acelasi nume. In
aceasta situatie, referirea la clasa dorita din aceste pachete trebuie sa se faca prin numele sau complet
(inclusiv numele pachetului).
Variabila CLASSPATH si locul de dispunere a claselor in sistemul de fisiere
Pentru ca programul nos tru sa poata folosi o clasa, trebuie sa afle locul unde este dispusa clasa in
sistemul de fisiere. Altfel, va fi generata o eroare referitoare la inexistenta clasei. Pentru gasirea claselor,
Java foloseste:
– numele pachetului;
– directoarele referite de variabile de mediu CLASSPATH.
Numele pachetelor corespund unor nume de directoare ale sistemului de fisiereDe exemplu, clasa
java.applet.Applet se va gasi in directorul applet care face parte si el din directorul java (adica,
java\applet \Applet.class).
Java cauta aceste directoare, pe rand, in cadrul cailor (path -urilor) incluse in variabila de mediu
CLASSPATH, daca aceasta este definita. Daca nu este configurata nici o variabila CLASSPATH, Java cauta
in directorul prestabilit, java \lib (aflat in directo rul cu versiunea de soft SDK folosita), precum si in
directorul curent.
Java cauta, in aceste directoare, clasa referita in fisierul -sursa folosindu -se de numele pachetului si al
clasei, iar daca nu o gaseste semnaleaza eroare de tip “ class not found ”.
Crearea propriilor pachete de clase de obiecte
Pentru crearea unor pachete proprii de clase de obiecte se parcurg urmatoarele etape:
1. Alegerea unui nume pentru pachet .
Numele ales pentru pachet depinde de modul in care dorin sa folosim aceste clase.

Conv entia de denumire a pachetelor, recomandata de Sun este de a folosi numele de domeniu Internet
cu elementele inversate. Ideea este de a ne asigura ca numele pachetului creat este unic.
Prin conventie, numele pachetelor incep cu litera mica, pentru a le de osebi de numele claselor, care
incep cu litera mare. De exemplu, in cazul denumirii complete a clasei String (adica, java.lang.String )
putem deosebi foarte usor numele pachetului de numele clasei. Aceasta conventie ajuta si ea la
reducerea conflictelor de nume.
2. Crearea structurii de directoare .
Se creaza pe hard -disc o structura de directoare conforma cu numele pachetelor.
Daca pachetul are un singur nume (cum ar fi: pachetulmeu ) este suficient sa cream un director cu acest
nume.
Daca numele pachetului este compus din mai multe parti (cum ar fi: ro.utcb.pachetulmeu ), trebuie
create si subdirectoarele respective.
De exemplu, pentru pachetul ro.utcb.pachetulmeu trebuie sa cream directorul ro, in cadrul acestuia
subdirectorul utcb , iar in cel din urma, subdirectorul pachetulmeu . Clasele si fisierele sursa vor fi
pastrate apoi in directorul pachetulmeu .
3. Adaugarea unei clase intr -un pachet .
Pasul final este de a introduce clasa intr -un pachet, folosind instructiunea package , plasata inainte de
orice instructiune import folosita.
Se poate adauga o clasa la un pachet ca in exemplul urmator:
package ro.utcb.pachetulmeu;
Nota: Folosirea unui mediu de dezvoltare de aplicatii de tipul IDE NetBeans usureaza crearea pachetelor
si a structuri i de directoare aferente acestora. Mediile de acest tip permit si crearea de proiecte care
inglobeaza pachetele si alte fisiere necesare aplicatiei, creand de fapt aplicatii de tip .jar.
Pachetele de clase si controlul accesului la clase
Controlul accesulu i la clase se poate realiza folosind modificatorul de acces public . Acest acces inseamna
ca respectiva clasa este vizibila si poate fi importata in afara pachetului. Clasele declarate publice pot fi
importate de orice alte clase din afara pachetului.
Atun ci cand folosim instructiunea import cu simbolul * , se vor importa numai clasele publice din
pachetul respectiv.
Daca nu este specificat nici un modificator pentru clasa, atunci acesteia i se atribuie un control
prestabilit al accesului de tip package -friendly . Acest acces presupune ca respectiva clasa este
disponibila (vizibila) tuturor claselor din acelasi pachet, insa nu si in afara pachetului – nici macar
subpachetelor. Clasa nu poate fi importata sau referita prin nume.
Exemplu de pachete proprii de c lase create pentru aplicatia TestFormaInterfata.class
Ne propunem sa rezolvam urmatoarea problema:

Se citesc N forme geometrice (patrate, dreptunghiuri, cercuri) de la tastatura. Sa se afiseze
formele geometrice ordonate dupa arie.
Pentru rezolvarea aces tei probleme s -au definit urmatoarele clase de obiecte:
– clasa abstracta a formelor geometrice cu numele FormaGeo ;
– clasele derivate din superclasa FormaGeo care caracterizeaza formele geometrice specifice:
Cerc , Dreptunghi si Patrat ;
– doua clase aju tatoare, care pot fi folosite si de alte aplicatii si anume:
– interfata Compra (despre folosirea interfetei vom vorbi ceva mai tarziu in aceasta
lectie) care declara o metoda publica cu numele comparaCu() , asemanatoare metodei din biblioteca
Java compareTo() , folosita pentru compararea ariei a doua obiecte de tip FormaGeo ;
– clasa Sort care realizeaza ordonarea formelor geometrice concrete (Cerc, Patrat si
Dreptunghi) dupa arie; acesta clasa are un caracter mai general si poate fi folosita pentr u ordonarea
altor obiecte dupa diferite criterii.
– clasa aplicatiei propriu -zise cu numele TestFormaInterfata folosita pentru citirea formelor de la
tastatura si afisarea formelor geometrice ordonate dupa arie.
Pentru o mai buna organizare, clasele de obiecte enumerate au fost impartite pe pachete, ceea ce
inseamna ca fiecare fisier de tip .class a fost stocat intr -un director corespunzator numelui pachetului.
Astfel, au fost create urmatoarele pachete de clase de obiecte:
– pachetul cu numele clasegen erice care contine fisierele de tip .class : Sort.class si
Compara.class ; acest pachet a fost stocat in directorul cu numele clasegenerice ;
– pachetul cu numele formegeometrice care contine fisierele de tip .class : Cerc.class ,
Dreptunghi.class , Patrat.class si FormaGeo.class ; acest pachet a fost stocat in directorul cu numele
formegeometrice .
Fisierul TestFormaInterfata.class corespunzator aplicatiei propriu -zise nu a fost inclus in nici un pachet si
a fost stocat in directorul curent de lucru aplicatiipachete . Pentru ca aplicatia sa functioneze, acest
director trebuie adaugat la variabila de mediu CLASSPATH. In directorul curent s -au creat si directoarele
corespunzatoare pachetelor descrise.
In concluzie, structura de directoare si pachetele cont inute in aceste directoare arata ca in schema de
mai jos:

Descrierea detaliata a programelor -sursa se va face in capitolul referitor la interfete

Mostenire multipla. Interfata
In cazul mostenirii multiple o clasa este derivata din doua sau mai multe superclase. De
exemplu, pot exista in ierarhie clase precum Student si Angajat . Din aceste doua clase ar putea fi
derivata o clasa cu numele AngajatStudent care sa contina atribute si metode combinate din clase le
Student si Angajat .
Mostenirea multipla poate conduce insa la dificultati de proiectare. De exemplu, cele doua
superclase din care deriveaza subclasa ar putea contine metode care au aceeasi semnatura, dar
implementari diferite sau ar putea avea atribute cu acelasi nume. Dificultatea rezolvarii unor astfel de
probleme a facut ca Java sa nu permita mostenirea multipla.
Alternativa oferita de Java pentru mostenirea multipla este folosirea interfetelor .
O interfata Java este o colectie de comportamente abstr acte, care pot fi combinate in orice clasa
pentru a introduce in acea clasa comportamente care nu sunt mostenite de la superclasa.
Tehnic, interfata Java este cea mai abstracta clasa posibila. Ea consta doar din metode publice
abstracte si din atribute st atice si finale.
Directorul de lucru
aplicatiipachete
Directorul
clasegenerice
Fisierul aplicatiei
TestFormaInterfata.class
Directorul
formegeometrice
Fisierele Sort.class si
Compara.class
Fisierele Cerc.class,
Dreptunghi.class, Patrat.class
si FormaGeo.class

O clasa implementeaza o anumita interfata daca furnizeaza definitii pentru toate metodele
abstracte din cadrul interfetei. O clasa care implementeaza o interfata se comporta ca si cand ar fi extins
o clasa abstracta specificata de acea int erfata.
Crearea si folosirea interfetelor Java
Sintaxa de definire a unei interfete este urmatoarea:
[<modificatori] interface <nume_interfata> [ extends <nume_interfata1> [,
<nume_interfata2>][, <nume_interfata3>], …]]
{
<corpul interfetei>
}
unde:
– <mo dificatori> – sunt specificati prin cuvintele -cheie public si abstract ; o interfata publica poate
fi accesata si de alte pachete decat cel care a definit -o; fiecare interfata este in mod implicit abstracta
deci cuvantul -cheie abstract poate lipsi;
– <nume_ interfata> – specifica numele interfetei; este de preferat ca numele interfetei sa
respecte aceeasi conventie de numire ca si cea de numire a claselor;
– <nume_interfata1>, <nume_interfata2>, .. – specifica numele superinterfetelor din care poate
deriva in terfata;
– <corpul_interfetei> – contine declaratii de variabile si declaratii de metode (numai antetul
acestora).
Variabilele interfetei sunt implicit statice si finale si deci trebuie specificate valori initiale pentru
acestea.
Metodele sunt declarate i n interfata numai cu antetul lor, fara corp. Ele sunt implicit abstracte.
Observatii:
1. Interfetele nu se pot instantia, adica nu se poate crea o instanta a unei interfete; deci, o
interfata nu are o metoda constructor.
2. Nu pot exista implementari diferite pentru aceeasi metoda declarata in doua interfete.
Interfetele trebuie sa posede o protectie de pachet sau publica. Interfetele care nu contin
modificatorul public nu-si vor converti automat metodele la accesul public si abstract si nici constante le
la accesul public . O interfata nepublica are metode si constante nepublice, acestea neputand fi folosite
decat in clasele sau interfetele din acelasi pachet.
Interfetele, ca si clasele, pot apartine unui pachet daca se foloseste instructiunea package in
prima linie din fisierul -sursa. De asemenea, interfetele pot importa interfete sau clase din alte pachete.
Un exemplu de interfata este Compara , prezentata mai jos:

/* INTERFATA folosita de mai multe clase pentru comparatii
* ––––––– Metode pu blice –––––
* int comparaCu –> Compara doua obiecte de tip Compara
* metoda trebuie definita in clasa care o implementeaza
*/
package clasegenerice;
public interface Compara
{
int comparaCu(Compara rhs);
}
Interfata Compara declara o metoda pe care orice clasa derivata din ea (in declaratia clasei se
foloseste cuvantul -cheie implements ) trebuie sa o implementeze. Metoda comparaCu () se va comporta
similar cu metoda compareTo() din clasa String . Metoda este implicit publica si abstracta si de ci nu
trebuie sa folosim modificatorii de acces public si de metoda abstract .
Implementarea unei interfete
O clasa implementeaza o interfata in doi pasi:
– declara ca implementeaza interfata, folosind cuvantul -cheie implements in antetul sau;
– defineste implementari pentru toate metodele din interfata.
Pentru a exemplifica implementarea unei interfete ne vom referi la clasa FormaGeo descrisa in
lectia 6.
Aceasta clasa implementeaza interfata Compara si, deci, trebuie sa definim si metoda
comparaCu() din interfata Compara . Implementarea metodei in clasa FormaGeo trebuie sa fie identica
cu declaratia din interfata si, din acest motiv, metoda comparaCu() are ca parametru un obiect de tip
Compara si nu un obiect de tip FormaGeo . Codul clasei este ilustrat in continuare (FormaGeo.java):
/* Superclasa abstracta pentru forme */
package formegeometrice;
import clasegenerice.*;
public abstract class FormaGeo implements Compara
{
private String nume;
abstract public double arie();

public FormaGeo(String numeForma) {
nume = numeForma;
}
public int comparaCu(Compara rhs) {
if (arie() < ((FormaGeo) rhs).arie())
return -1;
else
if (arie() == ((FormaGeo) rhs).arie())
return 0;
else
return 1;
}

final public String toString() {
return nume + ", avand aria " + arie();
}
}
Nota:
1. O clasa care implementeaza o interfata poate sa extinda si o alta clasa. In acest caz in
declaratia clasei se foloseste mai intai cuvantul -cheie extends urmat de numele clasei din care deriveaza
si apoi cuvantul -cheie implements urmat de numele interfetei pe care o implementeaza.
2. Retinem ca definirea metodelor declarate intr -o interfata trebuie obligatoriu sa fie facuta in
fiecare clasa in parte, care implement eaza interfata respectiva.
3. Metodele interfetei definite in clasa care o implementeaza sunt mostenite de toate subclasele
clasei respective. Aceste metode pot fi redefinite (suprascrise) in subclase.
4. Daca o clasa extinde o superclasa care implementea za o interfata, atunci si clasa respectiva
mosteneste interfata.
Implementarea unor interfete multiple
O clasa poate sa implementeze mai mult decat o singura interfata. O clasa poate implementa
mai multe interfe in doi pasi:

– declara toate interfetele pe care le implementeaza, folosind cuvantul -cheie
implements in antetul sau urmat de numele tuturor interfetelor separate prin virgula;
– defineste implementari pentru toate metodele din toate interfetele pe care le
implementeaza.
Folosirea unor interfete m ultiple poate crea totusi complicatii.
Derivarea interfetelor
Ca si in cazul claselor, interfetele pot fi organizate intr -o ierarhie. Atunci cand o interfata
mosteneste o alta interfata, subinterfata primeste toate metodele si constantele definite in
superinterfata.
Pentru a deriva (extinde) o interfata se foloseste tot cuvantul -cheie extends , la fel ca in cazul
definitiilor de clasa:
public interface <nume_interfata> extends <nume_superinterfata> {
…..
}
Nota: In cazul interfetelor nu exista o radacina comuna a arborelui de derivare asa cum exista
pentru arborele de clasa, clasa Object . Interfetele pot exista independent sau pot mosteni o alta
interfata.
Ierarhia de interfete este cu mostenire multipla. O singura interfata poate mosteni oricate
interfete are nevoie.
Implementarea de componente generice
Unul dintre s copurile principale ale programarii orientate pe obiecte este suportul pentru
reutilizarea codului. Unul dintre mecanismele importante folosite pentru indeplinirea acestui scop este
programarea generica.
Programarea generica ne spune ca, daca implementare a unei metode este identica pentru mai
multe clase (cu exceptia superclasei) se poate folosi o implementare generica a metodei.
De exemplu, putem defini o metoda care sa sorteze un sir de elemente. Algoritmul pentru
aceasta metoda este independent de tipul de obiecte care sunt sortate. Se poate deci folosi un algoritm
generic.
In Java programarea generica este implementata folosind conceptele de baza ale mostenirii si
interfetele.
Vom prezenta doua exemple care evidentiaza cum pot fi implementate metode si clase generice
folosind principiile de baza ale mostenirii.
1. Un prim exemplu este problema sortarii. Cum putem sorta un sir generic, care sa nu depinda
de tipul obiectelor supuse ordonarii?

Problema se poate rezolva cu ajutorul unei interfete in care est e declarata o metoda de
comparare a doua obiecte, care are un parametru de tipul interfetei . In acest fel se pot crea parametrii
generici care functioneaza pentru orice clasa care ar folosi aceasta interfata.
Exemplul urmator (programul Sort.java) prezint a o metoda de sortare generica denumita
sortareComp() care foloseste ca parametru un tablou de obiecte de tip Compara . Tipul Compara este
definit de interfata Compara prezentata deja in lectie.
/* Clasa generica pentru sortarea unor obiecte comparabile
*–––––––- Metode publice ––––––-
*void sortareComp – -> sorteaza un sir de obiecte de tip Compara
*/
package clasegenerice;
public final class Sort
{
public static void sortareComp(Compara [] a)
{
Compara temp;
for (int i = 0; i <= a.length – 2; i++)
{
for (int j = i+1; j <= a.length – 1; j++)
{
if (a[i].comparaCu(a[j]) == 1)
{
temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
}
}
}

Trebuie remarcat ca numai clasele care implementeaza interfata Compara pot fi sortate astfel.
De aceea, pentru a folosi metoda pentru ordonarea unui tablou de forme geometrice de tip FormaGeo,
clasa FormaGeo trebuie sa implementeze interfata Compara care d eclara metoda comparaCu() , care la
randul ei este folosita de metoda sortareComp() din clasa Sort.
In implementarea metodei din interfata (in cazul nostru comparaCu() ) intr -o clasa, putem
converti prin cast parametrul generic de tipul interfetei Compara in obiectul corespunzator.
Secventa de cod de mai jos prezinta implementarea metodei comparaCu() in clasa FormaGeo si
conversia explicita la tipul FormaGeo a unui obiect de tip Compara :
public int comparaCu(Compara rhs) {
if (arie() < ((FormaGeo) rhs).arie())
return -1;
else
if (arie() == ((FormaGeo) rhs).arie())
return 0;
else
return 1;
Exemplul urmator (TestFormaInterfata.java) arata cum poate fi folosita metoda generica de
sortare denumita sortareComp() pentru sortarea unui t ablou de forme geometrice:
import java.io.* ;
import clasegenerice.*;
import formegeometrice.*;
class TestFormaInterfata
{
private static BufferedReader in;
public static void main(String[] args) throws IOException
{
//Citeste numarul de figuri
in = new BufferedReader(new
InputStreamReader(System.in));
System.out.print("Numarul de figuri: ");
int numForme = Integer.parseInt(

in.readLine());
//citeste formele
FormaGeo[] forme = new FormaGeo[numForme];
for (int i = 0; i < numForme; ++i)
{
forme[i] = citesteForma();
}
//sortare si afisare
Sort.sortareComp(forme);
System.out.println("Sortarea dupa arie: ");
for (int i = 0; i < numForme; ++i)
{
System.out.println(forme[i]);
}
for (int i = 1; i < numForme; ++i)
{
if (forme[i -1].comparaCu(forme[i]) == -1)
System.out.println(forme[i -1] + " are o arie mai mica decat " +
forme[i]);
else
System.out.println(forme[i -1] + " are o arie egala cu sau mai mare
ca " + forme[i]);
}
}

//creaza un obiect adecvat de tip FormaGeo functie de
//datele de intrare.
//utilizatorul introduce 'c', 'p' sau 'd' pentru a indica
//forma, apoi introduce dimensiunile

//in caz de eroare se intoarce un cerc de raza 0

private static FormaGeo cites teForma() throws IOException
{
double rad;
double lg;
double lat;
String s;
System.out.println("Introduceti tipul formei: ");
do {
s = in.readLine();
} while (s.length() == 0);
switch (s.charAt(0)) {
case 'c':
System.out.println("Raza cercului: ");
rad = Integer.parseInt(in.readLine());
return new Cerc(rad);
case 'p':
System.out.println("Latura patratului: ");
lg = Integer.parseInt(in.readLine());
return new Patrat(lg);
case 'd':
System.out.println("Lungimea si latimea "
+ " dreptunghiului pe linii separate: ");
lg = Integer.parseInt(in.readLine());
lat= Integer.parseInt(in.readLine());
return new Dreptunghi(lg, lat);
default:
System.err.println("Tas tati c, p sau d: ");

return new Cerc(0); }}}
2. Un al doilea exemplu se refera la crearea unei clase generice folosind o superclasa adecvata,
cum ar fi Object . In java, daca o clasa nu extinde o alta clasa, atunci ea extinde implicit clasa Object .
Rezulta ca, fiecare clasa este o subclasa a lui Object .
De exemplu, structura de date abstracta stiva poate fi descrisa prin intermediul unei interfete
denumita Stiva . Clasa generica StivaAr care implementeaza aceasta interfata defineste toate metodele
specif icate in interfata Stiva . Clasa StivaAr foloseste obiecte de tip Object , deci poate sa stocheze orice
fel de obiecte.
Interfata Stiva descrie functiile disponibile; clasa concreta StivaAr trebuie sa defineasca aceste
functii. Aceasta abordare, separarea i nterfetei de implementarea ei , este o parte fundamentala a
orientarii pe obiecte. Programatorul care foloseste, de exemplu, structura de date stiva nu trebuie sa
vada implementarea ei, ci doar operatiile admisibile. Aceasta tine de partea de ascundere a in formatiei
din programarea orientata pe obiecte .
De asemenea, folosirea interfetelor mai are si avantajul ca interfetele fiind fixate, o serie de
inlocuiri facute in implementarile lor nu necesita practic nici o modificare in programele care utilizeaza
aceste interfete.
Sa ne reamintim ce este structura de date abstracta stiva.
O stiva este o structura de date in care accesul este permis doar pentru ultimul element inserat.
Comportamentul unei stive este foarte asemanator cu cel al unei gramezi de farfu rii. Ultima
farfurie adaugata va fi plasata in varf fiind, in consecinta, usor de accesat, in timp ce farfuriile puse cu
mai mult timp in urma (aflate sub alte farfurii) vor fi mai greu de accesat, putand periclita stabilitatea
intregii gramezi.
Deci, sti va este adecvata in situatiile in care avem nevoie sa accesam doar elementul din varf.
Toate celelalte elemente sunt inaccesibile.
Cele trei operatii care se pot face cu structura de date stiva sunt:
– inserare – denumita push;
– stergere – denumita pop;
– cautare – denumita top.
Interfata Java, pentru o structura de tip stiva, denumita Stiva , declara operatiile permise pe stiva
si este prezentata in continuare (programul Stiva.java).
/* Interfata pentru o stiva. Stiva expune metode pentru
* manipularea (adaugarea, stergerea, consultarea)
* elementului din varful ei*/
package clasegenerice;

public interface Stiva {
public void push(Object x);
public void pop();
public Object top();
public Object topAndPop();
public boolean isEmpty();
public void makeEmpty();
public boolean isFull();
}
Nota: Interfata declara si metodele: topAndPop() care combina doua operatii, consultare si
extragere; isEmpty() care verifica daca stiva este goala; makeEmpty() care goleste stiva; isFull() care
verifica daca stiva este plina.
Clasa generica StivaAr stocheaza elementele de tip Object (orice tip de obiecte) ale stivei intr -un
tablou unidimensional. Clasa StivaAr implementeaza interfata Stiva . Ea foloseste un tablou
unidimensional pentru a retine elementele din stiva. Mai exista si alte modalitati de implementare a
unei stive, cum ar fi listele inlantuite.
Codul sursa al clasei StivaAr (program StivaAr.java) se prezinta in continuare:
/* Implementarea unei stive folosind un tablou */
package clasegenerice;
public final class StivaAr implements Stiva
{
/* Tablou care retine elementele stivei*/
private Object[] elemStiva;
/*Dimensiunea maxima a stivei*/
private static int dimMax;
/*Pozitia varfului stivei */
private int pozitieVarf;
/* Constructor care aloca memorie pentru elemStiva si
* initializeaza varful stivei */
public StivaAr(int e)

{
dimMax = e;
elemStiva = new Object[dimMax];
pozitieVarf = -1;
}
/* Incrementeaza indicele pozitieVarf si adauga elementul x in stiva.*/
public void push(Object x)
{
elemStiva[++pozitieVarf] = x;
}
/* Extrage elementul din varful stivei si apoi decrementeaza indicele pozitieVarf. */
public void pop()
{
pozitieVarf –;
}
/* Returneaza elementul din varful stivei
* (ultimul adaugat).*/
public Object top()
{
return elemStiva[pozitieVarf];
}
/* Returneaza elementul din varful stivei si
* il elimina apoi din stiva.*/
public Object topAndPop()
{
return elemStiva[pozitieVarf –];
}
/* Verifica daca stiva e vida. */
public boolean isEmpty()

{
retu rn (pozitieVarf == -1);
}
/* Elimina toate elementele din stiva. */
public void makeEmpty()
{
pozitieVarf = -1;
}
/* Verifica daca stiva este plina */
public boolean isFull()
{
return (pozitieVarf == dimMax – 1);
}
}
Programul urmator (TestStiva.java) prezinta un exemplu de utilizare a structurii de tip stiva in
care se foloseste implementarea din clasa StivaAr a interfetei Stiva . Acest program afiseaza 10 numere
naturale, stocate intr -un tablou, in ordine inversa folosind structura de tip stiva.
/* Clasa de test simpla pentru o stiva, care adauga 10 numere
* dupa care le extrage in ordine inversa */
import clasegenerice.*;
public class TestStiva
{
public static void main(String[] args) {
Stiva s = new StivaAr(1 0);
//introducem elemente in stiva
for (int i = 0; i < 10; i++)
{
s.push(new Integer(i));
}

// Verificam daca stiva este plina
if (s.isFull())
System.out.println("Stiva este plina");
// Aflam elementul din varful stivei
int elemVarf = ((Integer) s.top()).intValue();
System.out.println("Elementul din varful stivei este:" + elemVarf);
//scoatem elementele din stiva si le afisam
System.out.print("Continutul stivei este: ");
while (!s.isEmpty())
{System.out.print(s. topAndPop() + " ");}
}
}

Curs 8
Cuvinte importante:
-determinarea clasei unui obiect: utilizarea operatorului de cast; utilizarea unui obiect
de tip class, metoda getname(); utilizarea operatorului instanceof;
– determinarea superclasei sau a interfet ei unui obiect: metoda getsuperclass() ; metoda
getinterfaces() ;
– tratarea erorilor: exceptii Java; ierarhia de exceptii predefinite de platforma Java;
verificarea consistentei exceptiilor Java;
– interceptarea (“prinderea”) si tratarea exceptiilor in cadrul aceleiasi metode: blocul try
… catch ;
– declararea metodelor care pot semnala (“arunca”) exceptii catre alte metode: clauza
throws ;
– crearea si semnalarea propriilor exceptii: definirea propriilor clase de exceptii;
semnalarea (“aruncarea”) propr iilor exceptii; instructiunea throw ;
– cum sa folosim exceptiile?
Determinarea clasei unui obiect
In Java, determinarea clasei unui obiect se poate realiza in mai multe modalitati:

– utilizand operatorul de cast;
– utilizand un obiect de tip Class ;
– utilizand operatorul instanceof .
Utilizarea operatorului de cast pentru determinarea clasei unui obiect
Am invatat in lectia 7 ca operatorul de cast este un operator unar prin care un obiect de tipul
unei clase este convertit la un alt tip corespunzator alt ei clase, in mod explicit.
Daca operatia de cast este incorecta (daca obiectul nu poate fi convertit la tipul specificat)
atunci va fi semnalata o exceptie (eroare) de tipul ClassCastException .
De exemplu, urmatoarea secventa de cod, semnaleaza o exceptie de tipul ClassCastException :
Object x = new Integer(12);
System.out.println((String)x);
In acest exemplu, variabila x pastreaza o referinta catre un obiect al clasei Integer care nu se afla
in ierarhia de clase Java pe aceeasi ramura cu clasa String .
Utilizarea unui obiect de tip Class
Un obiect de tip Class este o instanta a clasei Class, existenta in pachetul java.lang. Uneori clasa
Class mai este denumita si metaclasa . Masina virtuala Java ataseaza fiecarei clase, existente intr -un
program, un obiect de tipul Class , care este utilizat cand se creaza instante ale clasei respective. Acest
obiect de tip Class poate fi utilizat si de programator pentru a afla informatii de spre o clasa oarecare
folosita in program.
O posibilitate de obtinere a unui obiect de tip Class asociat unei clase este de a crea o instanta a
clasei respective care sa foloseasca metoda getClass() a clasei Object (acesta metoda poate fi folosita de
clasa respectiva pentru ca orice clasa creata deiveaza din clasa Object ).
Metoda getClass() returneaza un obiect de tip Class care reprezinta clasa din care face parte
obiectul respectiv (referit printr -o variabila referinta).
De exemplu:
AnimalDeCasa a = new Pisica();
Class clasa = a.getClass();
Dupa obtinerea obiectului de tip Class atasat clasei pentru care se doreste obtinerea unor
informatii se pot apela metode ale clasei Class pentru a obtine informatiile dorite.
O metoda des folosita din clasa Class este getName() care permite obtinerea numelui unei
clase.
De exemplu, se poate folosi urmatorul apel al metodei getName() pentru aflarea numelui clasei
din care face parte instanta referita cu numele a, in exemplul anterior:

String numeClasa = clasa.getName();
Metodele getClass() si getName() pot fi apelate in aceeasi instructiune, ca in exemplul urmator:
String numeClasa = a.getClass().getName();
Utilizarea operatorului instanceof
Operatorul instanceof da posibilitatea verificarii daca un obiect este instanta a unei clase
specificate.
Acesta are doi operanzi, un obiect in stanga si un nume de clasa in dreapta, ca in expresia de mai
jos:
<nume_obiect> instanceof <nume_clasa>
Expresia poate lua valoarea true sau false in functie de apartenenta sau neapartenenta
obiectului la clasa cu numele <nume_clasa> sau la oricare dintre subclasele sale.
Iata un exemplu de utilizare a operatorului instanceof pentru un obiect referit cu variabila a
pentru a determina daca el este o instanta a clasei Pisica sau a clasei Caine :
AnimalDeCasa a = new Caine();
if (a instanceof Pisica)
System.out.println("Animalul acesta de casa este o pisica.");
else
System.out.println("Animalul acesta de casa este un caine.");
Rezultatul executiei acestei secvente de cod este:
Animalul acesta de casa este un caine.
Operatorul instanceof poate fi folosit si pentru interfete. Daca un obiect implementeaza o
interfata, operatorul instanceof cu numele interfetei respective in partea dreapta va returna valoarea
true.
Determinarea supe rclasei sau a interfetei unui obiect
Din clasa Class mai pot fi folosite alte doua metode pentru aflarea superclasei unui obiect si a
interfetei pe care o implementeaza clasa obiectului , si anume: metoda getSuperclass() si metoda
getInterfaces() .
Metoda ge tSuperclass() din clasa Class returneaza un obiect de tip Class care reprezinta
superclasa clasei obiectului respectiv.
Pentru a realiza un apel corect al metodei trebuie mai intai sa se obtina un obiect de tip Class al
clasei obiectului.
De exemplu, se poate folosi urmatorul apel al metodei getSuperclass() pentru aflarea numelui
superclasei din care face parte instanta referita cu numele a:

AnimalDeCasa a = new Pisica();
String numeSuperclasa = a.getClass().getSuperclass().getName();
a = n ew Caine();
numeSuperclasa = a.getClass().getSuperclass().getName();
Metoda getInterfaces() din clasa Class returneaza un tablou de obiecte de tip Class care
reprezinta toate interfetele implementate de clasa obiectului respectiv. Ordinea in care se stoche za in
tabou obiectele care reprezinta interfetele clasei este data de ordinea in care ele au fost declarate in
instructiunea de declarare a clasei obiectului.
Daca clasa obiectului respectiv nu implementeaza o interfata, atunci metoda returneaza un
tablou de obiecte de tip Class de lungime 0.
Pentru a realiza un apel corect al metodei trebuie mai intai sa se obtina un obiect de tip Class al
clasei obiectului.
De exemplu, se poate folosi urmatorul apel al metodei getInterfaces() pentru aflarea numelor
interfetelor pe care le implementeaza clasa din care face parte instanta referita cu numele a:
Class [] interfata = a.getClass().getInterfaces();
if (interfata.length == 0)
System.out.println("Clasa " + numeClasa + " nu implementeaza o interfata ");
else
{
String numeInterfata = interfata [0].getName();
System.out.println("Numele interfetei este: " + numeInterfata);
}
Tratarea erorilor
Erorile care apar in faza de executie a unei aplicatii informatice sunt produse din diverse cauze
cum ar fi:
– programatorul nu a anticipat toate situatiile posibile in care ar putea ajunge aplicatia
informatica;
– existenta unor situatii aflate in afara controlului programatorului (date eronate primite
de la utilizatori, fisiere care nu mai contin date corecte, dispozitive hardware care nu mai functioneaza
etc).
Exceptii Java
In Java, exceptiile sunt evenimente anormale care au loc in timpul executiei unei aplicatii si care
pot duce la intreruperea executiei normale a acesteia.

Atunci cand aplicatia informatica isi interupe executia normala, inseamna ca a fost semnalata
(thrown – “aruncata” ) o exceptie . Faptul ca o excep tie a fost semnalata inseamna, in Java, ca “a aparut o
eroare”.
Exceptiile pot fi semnalate, implicit, de sistem sau, explicit, de aplicatia informatica realizata.
Exceptia poate fi si interceptata (caught – “prinsa”). Interceptarea unei exceptii inseamna
tratarea situatiilor speciale (erorilor) astfel incat aplicatia informatica proiectata sa nu se mai termine
anormal.
Ierarhia de exceptii predefinite de platforma Java
In Java, exceptiile sunt instante ale unor clase derivate din clasa Throwable .
Clasa Throwable , definita in pachetul java.lang , reprezinta clasa de baza pentru intreaga familie
de clase de exceptii. Cand se semnaleaza (este “aruncata”) o exceptie este creata o instanta a unei clase
de exceptii. Figura de mai jos ilustreaza ierarhia claselor de exceptii, pornind de la clasa de baza
Throwable si continuand cu cateva dintre subclasele cele mai importante.

Clasa Throwable are doua subclase directe:
– Error ;
– Exception.
Clasa Error , impreuna cu toate clasele derivate din ea, descrie exceptii grave, numite erori. Aceste erori
sunt rare si, de obicei, fatale. In general,ele nu pot fi interceptate de catre a plicatia informatica in care s –
au produs si determina intreruperea executiei programului (de exemplu, OutOfMemoryError ). Java este
cea care foloseste acest tip de erori daca are nevoie de ele.
Clasa Exception , impreuna cu toate clasele derivate din ea, rep rezinta exceptiile propriu -zise Java.
Exceptiile semnalate descriu conditii anormale, care sunt, de cele mai mute ori, tratate de aplicatie, desi
sunt anumite exceptii care nu pot fi tratate si atunci aplicatia va fi oprita din executie.
Object
Throwable
Exception
Error
RuntimeException
IOException
ArithmeticException
ClassCastException


……

Clasa Exception are multe subclase definite in cadrul pachetului java.lang . Aceste subclase indica diverse
tipuri de exceptii care pot aparea in cadrul unei aplicatii Java. De exemplu, tipul de exceptie
NoSuchFieldException semnaleaza ca programul a incercat sa foloseasca o variabila de instanta sau de
clasa care nu exista.
Clasa RuntimeException este foarte des folosita de programatori, deoarece ea este clasa de baza pentru
exceptiile care apar in timpul executiei unui program. De exemplu, tipul de exceptie ClassCastExcepti on
(prezentat la inceputul acestei lectii) indica faptul ca aplicatia noastra a incercat sa faca o conversie
explicita de tip pentru un obiect ce nu poate fi convertit la tipul specificat.
Nu toate exceptiile sunt definite in pahetul java.lang . De exemplu, toate exceptiile I/O (de intrare/iesire)
sunt derivate din clasa java.io.IOException si sunt definite in pachetul java.io .
Verificarea consistentei exceptiilor Java
In Java, o metoda poate indica tipurile de exceptii pe care le poate semnala (“arunca”). C ompilatorul
Java cat si masina virtuala Java verifica daca aceste exceptii “aruncate” in cadrul unei metode sunt fie
tratate in cadrul acelei metode, fie specificate ca fiind “aruncate” de metoda respectiva la alte metode
in care urmeaza a fi tratate. Aces te tipuri de exceptii se numesc exceptii verificate .
De exemplu, metodele care ciresc din fisiere sau de la tastatura pot “arunca” exceptii de tipul
IOException . Atunci cand se folosesc aceste metode in aplicatia Java, programatorul trebuie sa aiba grija
sa intercepteze (“sa prinda”) si sa trateze exceptiile de tipul IOException.Compilatorul este cel care il
obliga pe programator sa intercepteze si sa trateze exceptiile de tipul IOException .
In cazul exceptiilor neverificate de catre compilator, programator ul poate decide daca “prinde”
(intercepteaza) si trateaza exceptia sau trece cu vederea exceptia.
Exceptiile verificate sunt toate tipurile de exceptii derivate din clasa Exception (inclusiv clasa Exception ),
mai putin clasa RuntimeException si subclasele ei.
Exceptiile neverificate sunt de tipul clasei Throwable , de tipul clasei Error si al subclaselor ei, precum si
de tipul clasei RuntimeException si al subclaselor ei.
Interceptarea (“prinderea”) si tratarea exceptiilor in cadrul aceleiasi metode
In fiecare situatie de exceptie exista doua parti:
– partea care semnaleaza exceptia si
– partea care o intercepteaza si o trateaza.
O exceptie poate fi aruncata de la o metoda la alta de mai multe ori inainte de a fi interceptata, insa
pana la urma ea va fi interceptata si tratata.
Pentru a intercepta si trata o exceptie trebuie parcursi doi pasi:
– gruparea codului care contine metoda ce poate semnala (“arunca”) exceptia in cadrul unui bloc
try;
– interceptarea si tratarea exceptiei in cadrul unui bloc catch .

In cazul exceptiilor neverificate de catre compilator, programatorul poate decide daca “prinde”
(intercepteaza) si trateaza exceptia sau trece cu vederea exceptia.
Exceptiile verificate sunt toate tipurile de exceptii derivate din clasa Exception (inclusiv clasa Exception ),
mai putin clasa RuntimeException si subclasele ei.
Exceptiile neverificate sunt de tipul clasei Throwable , de tipul clasei Error si al subclaselor ei, precum si
de tipul clasei RuntimeException si al subclaselor ei.
Interceptarea (“prinderea”) si tratarea exceptiilor in cadrul aceleiasi metode
In fiecare situatie de exceptie exista doua parti:
– partea care semnaleaza exceptia si
– partea care o intercepteaza si o trateaza.
O exceptie poate fi aruncata de la o metoda la alta de mai multe ori inainte de a fi interceptata, insa
pana la urma ea va fi interceptata si tratata.
Pentru a intercepta si trata o exceptie trebuie parcursi doi pasi:
– gruparea codului care contine metoda ce poate semnala (“arunca”) excepti a in cadrul unui bloc
try;
– interceptarea si tratarea exceptiei in cadrul unui bloc catch .
Operatiile try (incearca) si catch (intercepteaza) inseamna, de fapt:
“Incearca aceasta portiune de cod, care poate cauza o exceptie. Daca se executa cu succes, c ontinua
aplicatia. Daca nu, intercepteaza exceptia si trateaz -o.”
Un bloc try este de forma :
try
{
//apeluri de metode care pot genera exceptii
<instructiuni>;
}
Blocul try contine instructiuni care sunt “incercate” a fi executate, urmand ca, in cazul in care ele nu se
pot executa cu succes, eroarea sa fie interceptata si tratata in blocul catch . Daca instructiunile se pot
executa cu succes, aplicatia se va executa normal fara a tine cont de partea de tratare a exceptiilor din
blocul catch .
Nota: Unui bl oc de instructiuni try i se asociaza in mod obligatoriu unul sau mai multe blocuri catch .
Blocurile catch de instructiuni sunt asociate cu un bloc try astfel:
try

{

}
catch (…)
{

}
catch (…)
{

}

Forma generala a unui bloc catch este:
catch (<nume_clasa_de_exceptii> <nume_variabila>)
unde:
– <nume_clasa_de_exceptii> – specifica tipul de exceptie care poate fi tratat, tip dat de numele clasei de
exceptie;
– <nume_variabila> – specifica numele prin care poate fi referita instanta ce reprezinta ex ceptia tratata
de blocul catch; aceasta variabila este recunoscuta si poate fi folosita doar in cadrul blocului catch .
Instructiunile din blocul catch se executa doar daca instructiunile din blocul try genereaza exceptii si
aceste exceptii sunt instante al e clasei cu numele <nume_clasa_de exceptii> precizat in antetul
instructiunii catch .
Dupa ce exceptia a fost tratata, se executa in continuare urmatoarea linie de cod aflata dupa secventa
catch .
Urmatorul exemplu citeste un sir de caractere si “incearca”, intr-un bloc try, sa il converteasca la un
numar intreg. In caz de nereusita, se “intercepteaza”, in blocul catch , o exceptie de tip
NumberFormatException , care este “aruncata” de metoda Integer.parseInt() atunci cand numarul
introdus nu este un numar intr eg. Tratarea acestui tip de eroare se face printr -un mesaj de avertizare si
returnarea valorii implicite 0 pentru un numar intreg.
De asemenea, atunci cand “se incearca” citirea sirului de caractere de la tastatura, intr -un bloc try, se
pot “intercepta”, i ntr-un bloc catch , eventualele exceptii de tip IOException, care sunt “aruncate” de
metoda readLine() . Tratarea acestui tip de eroare se face prin returnarea valorii implicite null pentru un
String.

package intrareiesire;
import java.io.*;
/* cieste un s ir de caractere si incerca sa il converteasca la tipul int */
public class CitesteDate
{
public static String citesteString() {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
try {
return br.readLine(); }
catch (IOExce ption ioe) {
return null; }
}
public static int citesteNrInt() {
try {
return Integer.parseInt(citesteString()); }
catch (NumberFormatException nfe) {
System.out.println("Nu este numar intreg.");
return 0; }
} }
Programul urmator (TestCitesteNumere.java) apeleaza metodele din clasa CitesteDate, (care
semnaleaza, intercepteaza si trateaza erorile care apar in cadrul lor) pentru a citi un sir de numere de la
tastatura.
import intrareiesire.*;
class TestCitesteNumer e {
public static void main(String[] args) {
CitesteDate valIntreg = new CitesteDate();
System.out.println("Introduceti numarul de elemente ale sirului:");
int n = valIntreg.citesteNrInt();
int [] numere = new int [n];

System.out.println ("Introdu ceti elementele sirului: ");
for (int i = 0; i < numere.length; i++)
numere [i] = valIntreg.citesteNrInt();
System.out.println ("Sirul de numere introdus este: ");
for (int i = 0; i < numere.length; i++)
System.out.print(numere[i] + " "); } }
Exempl ul, descris mai sus, prezinta modul de interceptare a unui anumit tip de exceptie. Deoarece
clasele de exceptii sunt organizate ierarhic, nu este necesar ca tipul de exceptie tratat de blocul catch si
tipul de exceptie “aruncat” de o metoda din blocul try sa fie identice. Un bloc catch , care trateaza un tip
de exceptii va intercepta si trata si clasele de exceptii derivate din exceptia respectiva.
In exemplul de fata, se poate intercepta in blocul catch , exceptia creata de tipul
NumberFormatException , folosind clasa Exception care este superclasa pentru NumberFormatException .
Astfel, codul ar putea arata astfel:
public static int citesteNrInt()
{
try {
return Integer.parseInt(citesteString()); }
catch (Exception nfe) {
System.out.println("Nu est e numar intreg.");
return 0; }
}
}
In aceasta situatie, blocul catch intercepteaza toate exceptiile Exception , dar si clase de exceptii derivate
din clasa Exception , cum este si cazul clasei de exceptii FormatNumberException .
Se prefera totusi, utiliz area blocurilor catch specializate, care ofera mai multe detalii despre situatia de
eroare, si nu a celor generale.
Nota : Toate clasele de exceptii mostenesc de la clasa Throwable cateva metode utile pentru aflarea de
informatii despre situatia de eroare. O folosire uzuala are metoda getMessage() . Ea afiseaza un mesaj
detaliat referitor la ce s -a intamplat.
Daca se doreste interceptarea si tratarea, in blocul catch , a unor tipuri foarte diferite de exceptii
semnalate in blocul try, care nu sunt inrudite prin mostenire, atunci se asocieaza blocului try mai multe
blocuri catch .

Blocurile catch sunt examinate in ordinea in care ele apar in fisierul sursa. In timpul procesului de
examinare, primul bloc catch care va corespunde exceptiei semnalate va fi executat, iar celelalte blocuri
vor fi ignorate.
Declararea metodelor care pot semnala (“arunca”) exceptii catre alte metode ( transmiterea exceptiilor
catre baza stivei de apel )
In paragraful anterior, am descr is cazul in care exceptiile sunt interceptate (“prinse”) si tratate in cadrul
aceleiasi metode, nefiind transmise altor metode care apeleaza metoda respectiva.
A doua posibilitate este aceea de a specifica exceptiile care nu sunt tratate in cadrul metodei respective,
fiind semnalate (“aruncate”) mai departe catre alte metode care le vor intercepta (“prinde”) si le vor
trata.
Atunci cand programatorul decide ca o metoda, din aplicatia informatica, sa nu intercepteze o anumita
exceptie care poate fi semnalata de codul din interiorul ei, trebuie sa se precizeze ca metoda respectiva
poate semnala (“arunca”) la randul ei exceptia respectiva catre alte metode care o apeleaza.
Pentru a indica faptul ca o metoda poate semnala (“arunca”) o exceptie, catre alte meto de care o
apeleaza, se foloseste in antetul metodei respective clauza throws in care se specifica numele
exceptiilor pe care le poate semnala (“arunca”) metoda respectiva.
Observatii :
1. Exceptiile specificate in clauza throws nu trebuie sa fie intercept ate (“prinse”) si tratate in cadrul
metodei respective care foloseste clauza throws .
2.Semnalarea (“aruncarea”) exceptiilor incepe cu metoda originala care daca nu intercepteaza si nu
trateaza exceptiile generate, le semnaleaza (“le arunca”) mai departe me todei care o apeleaza, care la
randul ei daca nu le intercepteaza si nu trateaza le semnaleaza (“le arunca”) mai departe unei alte
metode care o apeleaza pe aceasta din urma si asa mai departe. In final exceptia va trebui interceptata
(“prinsa”) si tratat a in cadrul unei metode. Astfel, masina virtuala Java cauta in stiva de apel metoda
care intercepteaza si trateaza exceptia, pornind de la metoda in care a aparut exceptia, deci dinspre
varful stivei spre baza stivei.
Forma antetului metodei care specifi ca tipurile de exceptii semnalate (“aruncate”) de metoda este:
[<modificatori_acces>] [<modificatori_metoda>] <tip_returnat> <nume_metoda> ([<param1>,
<param2>, …]) throws <nume_clasa_de_exceptii1>[, <nume_clasa_de_exceptii2>, …]
Nota : Specificarea prin cl auza throws a exceptiilor aruncate de metoda originala nu se poate omite,
daca metoda respectiva genereaza exceptii pe care nu le trateaza, deoarece compilatorul detecteaza
aceasta “scapare” si o raporteaza ca eroare de compilare, propunand doua solutii: t ratarea lor in cadrul
metodei (prin blocuri try…catch ) sau specificarea lor in clauza throws .
Exemplul prezentat anterior, al clasei CitesteDate , poate fi modificat astfel incat exceptiile de tipul
IOException care sunt semnalate (“aruncate”) in metoda citesteString (), de catre metoda readLine(), sa
fie semnalate (“aruncate”) mai departe in metoda citesteNrInt(), care apoi le semnaleaza metodei
main() din clasa TestCitesteNumereThrows (care reprezinta aplicatia Java).

Astfel, s -a creat o noua clasa Citest eDateThrows care are definitia:
package intrareiesire;
import java.io.*;
/* cieste un sir de caractere si incerca sa il converteasca la tipul int */
public class CitesteDateThrows
{
public static String citesteString() throws IOException
{
Buffere dReader br = new BufferedReader(new InputStreamReader(System.in));
return br.readLine();
}
public static int citesteNrInt() throws IOException
{
try
{
return Integer.parseInt(citesteString());
}
catch(NumberFormatException nfe)
{
System.out.println("Nu este numar intreg.");
return 0;
}
}
}
Clasa TestCitesteNumereThrows (care reprezinta programul principal) are definitia data de secventa de
cod:
import intrareiesire.*;
import java.io.*;
class TestCitesteNumereThrows

{
public s tatic void main(String[] args) throws IOException {
CitesteDateThrows valIntreg = new CitesteDateThrows();
System.out.println("Introduceti numarul de elemente ale sirului:");
int n = valIntreg.citesteNrInt();
int [] numere = new int [n];
System.out. println ("Introduceti elementele sirului: ");
for (int i = 0; i < numere.length; i++)
numere [i] = valIntreg.citesteNrInt();
System.out.println ("Sirul de numere introdus este: ");
for (int i = 0; i < numere.length; i++)
System.out.print(numere[i] + " ");
}
}
Crearea si semnalarea propriilor exceptii
Pe langa exceptiile definite de platforma Java, programatorul poate defini propriile clase de exceptii.
Aceste clase proprii de exceptii descriu situatii de exceptii particulare aplicatiei respective c are nu exista
in ierarhia de clase de exceptii oferita de platforma Java.
Clasele proprii de exceptii sunt derivate (direct sau indirect) din clasa Throwable .
De regula, se creaza propriile clase de exceptii derivate din clasa Exception .
Nota: In definirea noilor clase de exceptii, se recomanda adaugarea la numele clasei a sufixului
Exception , pentru toate clasele derivate (direct sau indirect) din clasa Exception (de exemplu,
MyNewException ).
Clasele proprii de exceptii sunt clase Java obisnuite.
Clasele proprii de exceptii poseda, de obicei, doi constructori:
– primul constructor nu primeste nici un parametru;
– al doilea constructor primeste ca parametru un sir de caractere care reprezinta un mesaj ce
evidentiaza situatia de eroare.
Definirea propriilor clase de exceptii
De regula, o clasa proprie de exceptii este definita ca in exemplul de mai jos:

package exceptii;
public class IndexException extends Exception
{
public IndexException()
{
super();
}
public IndexException(Strin g msg)
{
super(msg);
}
}
Clasa IndexException definita mai sus nu aduce practic nimic nou clasei Exception , deoarece defineste
doar doi constructori care apeleaza constructorii superclasei Exception . Totusi, tipul exceptiei in sine
este important pentr u ca ajuta programatorul sa intercepteze tipul respectiv de exceptie atunci cand
este necesar.
Semnalarea (“aruncarea”) propriilor exceptii
Sa ne reamintim ca, toate exceptiile sunt instante ale unei clase de exceptie oarecare, definite fie in
biblioteca J ava standard, fie de programator.
Pentru a semnala (“arunca”) un tip de exceptie definita de programator, trebuie sa se creeze, mai intai,
o instanta a sa .
Folosind definirea de clasa de exceptie prezentata, crearea unei instante a clasei de excepie
Inde xException poate fi facuta in doua moduri:
new IndexException();
new IndexException("Stiva vida. ");
In cel de al doilea caz situatia de eroare transmite si o informatie, sub forma mesajului “Stiva vida.”, care
poate fi folosit de codul care trateaza excep tia aparuta pentru a afisa un mesaj informativ.
Odata creata o instanta a unei clase proprii de exceptii, aceasta devine o exceptie Java si este semnalata
(“aruncata”) folosind instructiunea throw .
Instructiunea throw are un singur argument, care trebuie sa fie o instanta a unei clase de exceptii
derivate din clasa Exception .
Forma instructiunii throw este:

throw <instanta_clasa_de_exceptii>;
De exemplu, pentru semnalarea (“aruncarea”) unei exceptii din metoda topAndPo p() (exceptie care
poate fi generata cand o stiva este vida) se poate folosi urmatoarea secventa de cod:
public Object topAndPop() throws IndexException
{
if (isEmpty())
{
throw new IndexException("Stiva vida. ");
}
return elemStiva[pozitieVarf –];
}
Pentru transmiterea exceptiei semnalate (“aruncate”) in metoda topAndPop(), cu ajutorul instructiunea
throw , catre o alta metoda apelanta se foloseste clauza throws in antetul metodei topAndPop() . In
metoda apelanta exceptia IndexException se poate , eventual intercepta (“prinde”) si trata sau poate fi
transmisa mai departe la o alta metoda apelanta.
In exemplul prezentatat, interceptarea si tratarea exceptiei de tip IndexException este realizata in
metoda main() a aplicatiei (clasa TestStiva1 ). Iata codul -sursa in care se realizeaza acest lucru:
/* Clasa de test simpla pentru o stiva, care adauga 10 numere
* dupa care le extrage in ordine inversa */
import clasegenerice.*;
import exceptii.*;
public class TestStiva1
{
public static void main(String[] args) {
Stiva1 s = new StivaArr(10);

//introducem elemente in stiva
for (int i = 0; i < 10; i++)
{
s.push(new Integer(i));

}
//scoatem elementele din stiva si le afisam
System.out.print("Continutul stivei este: ");
try
{
while (true)
{
System.out.print(s.topAndPop() + " ");
}
}
catch(IndexException ie)
{
System.out.println();
System.out.print("Eroare: " + ie.getMessage());
}
}
}
Observatie: In secveta de mai sus, iesirea din bucla while se realizeaza in mo mentul in care stiva devine
vida si metoda topAndPop() semnaleaza (“arunca”) exceptia IndexException care este interceptata si
tratata in blocul catch .
Concluzii privind folosirea eficienta a exceptiilor
Cum sa folosim exceptiile?
1. Daca o metoda din aplicatia Java apeleaza o alta metoda in care s -a folosit clauza throws , avem trei
posibilitati:
– se trateaza exceptia folosind blocurile try si catch ;
– se transmite exceptia mai departe pe lant (spre baza stivei de apel), adaugand in metoda
respectiva clauza throws ;
– se realizeaza ambele metode descrise mai sus, atat pentru a intercepta (“prinde”) si trata
exceptia folosind blocurile try … catch , cat si pentru a o resemnala explicit folosind instructiunea throw .

2. Daca o metoda din aplicatia Java semnaleaza (“arunca”) propriile exceptii, aceasta metoda trebuie sa
fie declarata folosind clauza throws . De asemenea, exceptia trebuie semnalata explicit in corpul
metodei, folosind instructiunea throw .
3. Daca o metoda din aplicatia J ava suprascrie metoda unei subclase care contine clauza throws , atunci
se pot semnala numai aceleasi tipuri de exceptii sau subclase ale exceptiilor respective; nu se pot
semnala alte tipuri de exceptii.
Modul incorect de folosire a exceptiilor
1. Sistemul de exceptii al Java a fost proiectat in asa fel incat, daca apare o eroare, sa fim avertizati in
legatura cu aceasta. Ignorarea acestor avertismente si nerespectarea lor duce la posibila aparitie a unor
erori fatale in cadrul aplicatiilor.
Mai mult, folo sirea de clauze throws in propriile metode in scopul de a evita tratarea exceptiilor face ca
utilizatorii acestor metode (adica obiectele aflate mai sus pe lantul de apeluri) sa fie nevoiti sa le trateze.
Astfel metodele noastre se complica nejustificat. E rorile semnalate de compilator cu privire la exceptii
au rolul de a ne atrage atentia asupra acestor probleme.
2. Ca regula generala, nu este recomandata utilizarea exceptiilor in cazul in care situatia este previzibila
in aplicatia Java (de exemplu, sfar situl unui fisier, depasirea dimensiunii unui tablou etc).

Curs 9
Cuvinte importante:
-tipuri de fluxuri de intrare/iesire Java: fluxuri de octeti, fluxuri de caractere; System.in ,
System.out , System.err ; fluxuri -filtre;
– fluxuri de octeti si clase predefinite Java utilizate: fluxuri nefiltrate de intrare care folosesc ca
sursa un fiser; fluxuri nefiltrate de iesire care folosesc ca destinatie un fisier;
– filtrarea fluxurilor de octeti si clase predefinite Java utiliza te: zona tampon (“buffer”); fluxuri de
intrare cu o zona tampon; fluxuri de iesire cu o zona tampon; fluxuri filtrate cu date de tipuri primitive;
fluxuri filtrate cu date formatate;
– fluxuri de caractere si clase predefinite Java utilizate: fluxuri nef iltrate de intrare care folosesc
ca sursa un fisier; fluxuri filtrate de intrare cu o zona tampon; fluxuri filtrate de intrare cu o zona tampon
care tin evidenta numerelor de linie.
Tipuri de fluxuri de intrare/iesire Java
Toate datele din Java sunt scrise sau citite folosind fluxuri .
Un flux ( stream ) reprezinta o succesiune de octeti (bytes) sau de caractere transportat de la sau catre
memoria RAM in care se afla programul Java.

Un flux de intrare transporta datele de la o sursa externa (tastatura, fisie r pe hard -disc etc) catre
programul Java.
Un flux de iesire transporta datele din programul Java catre o destinatie externa (ecranul calculatorului,
fisier pe hard -disc etc).
Fluxurile de intrare/iesire in Java sunt create si manevrate cu ajutorul claselor din pachetul predefinit
java.io . Din acest motiv orice program care executa operatii de intrare/iesire trebuie sa includa
instructiunea:
import java.io.*;
Numarul claselor si a metodelor lor, definite in pachetul java.io , este foarte mare. De aceea se
recomanda programatorului sa consulte in permanenta documentatia ce insoteste versiunea de Java
folosita.
In aceasta lectie vom descrie doar cateva clase Java care sunt folosite mai des pentru fluxuri de octeti si
de caractere.
Java foloseste doua tipuri prin cipale de fluxuri:
– fluxuri de octeti;
– fluxuri de caractere.
Fluxurile de octeti pot pastra valori intregi din domeniul 0 – 255. In acest format pot fi reprezentate o
multitudine de date, cum ar fi: date numerice, programe executabile, comunicatii Int ernet sau cod Java
(bytecode) etc.
Generic, fluxurile de octeti sunt subclase ale claselor abstracte predefinite:
– InputStream – pentru fluxuri de octeti de intrare si
– OutputStream – pentru fluxuri de octeti de iesire.
Fluxurile de caractere reprezinta un tip special de flux de octeti, care se folosesc numai pentru date de
tip text (tiparibile). Ele difera de fluxurile de octeti prin faptul ca setul de caractere Java suporta
codificarea Unicode (cu doi octeti pe caracter).
Toate datele de ti p text, cum ar fi fisierele text, paginile Web, sau alte formate de text, este necesar sa
foloseasca fluxurile de caractere.
Generic, fluxurile de caractere sunt subclase ale claselor abstracte predefinite:
– Reader – pentru fluxuri de caractere de intra re si
– Writer – pentru fluxuri de caractere de iesire.
Java ofera trei fluxuri predefinite pentru operatii de I/O standard (de la tastatura, la ecranul
calculatorului sau pentru erori) care sunt campuri ale clasei System inclusa in pachetul java.lang :
– System.in – reprezinta intrarea standard (implicit, tastatura calculatorului); acest flux este de
tip InputStream ;

– System.out – reprezinta iesirea standard (implicit, ecranul calculatorului); acest flux este de tip
PrintStream ;
– System.err – reprezi nta fluxul standard de iesire pentru mesaje de eroare (implicit, ecranul
calculatorului); acest flux este de tip PrintStream .
Dintre metodele clasei System , referitoare la fluxurile predefinite descrise mai sus, mentionam:
– metoda setIn , care redirecteaz a fluxul de intrare standard catre o alta sursa decat tastatura (de
exemplu, un fisier pe disc); aceasta metoda are antetul:
void setIn (InputStream <in>)
– metoda setOut , care redirecteaza fluxul de iesire standard catre o alta destinatie decat ecranul
calculatorului (de exemplu, un fisier pe disc); aceasta metoda are antetul:
void setOut (PrintStream <out>)
– metoda setErr , care redirecteaza fluxul de iesire standard al mesajelor de eroare catre o alta destinatie
decat ecranul calculatorului (de exemplu, u n fisier pe disc); aceasta metoda are antetul:
void setErr (PrintStream <out>)
Asocierea fluxului de intrare sau de iesire cu un filtru
Majoritatea claselor Java folosite in prezent permit realizarea de operatii de intrare/iesire mai
performante prin asocie rea fluxului cu un filtru, inainte de a citi sau scrie date.
Un filtru este un tip de flux care schimba modul in care se lucreaza cu un flux existent.
Procedura de folosire a unui filtru pentru un flux presupune urmatorii pasi:
1. crearea (deschiderea) un ui flux asociat cu sursa de date sau cu destinatia datelor;
2. crearea (deschiderea) unui flux de tip filtru asociat cu fluxul deschis la pasul 1;
3. citirea/scrierea datelor de la /in filtru si nu direct in flux.
Fluxuri de octeti si clase predefinite J ava utilizate
A. Fluxuri nefiltrate de octeti si clase predefinite utilizate
In schema de mai jos se prezinta doar o parte a structurii de clase ce poate fi folosita in operatiile cu
fluxuri de intrare si iesire nefiltrate.

Clasa InputStream este o clasa abstracta si din ea deriveaza toate celelalte clase care creaza fluxuri de
octeti de intrare si realizeaza operatii de intrare pe aceste fluxuri.
Clasa OutputStream este o clasa abstracta si din ea deriveaza toate celelalte clase care creaza fluxuri de
octeti de iesire si realizeaza operatii de iesire pe aceste fluxuri.
Nota : Deoarece fluxurile de intrare/iesire semnaleaza exceptii de tipul IOException la aparitia unei er ori,
toate operatiile legate de fluxuri se incadreaza in blocuri try … catch , care sa intercepteze aceasta
exceptie.
Fluxuri nefiltrate de octeti de intrare care folosesc ca sursa un fisier
Sunt folosite pentru transferul de date de la fisierele aflate pe hard -discuri, pe CD -ROM sau pe alte
dispozitive de stocare (ce pot fi referite printr -o cale de director si un nume) catre aplicatia Java.
Crearea (deschiderea) unui flux de intrare de la un fisier se realizeaza cu ajutorul constructorului clasei
FileInput Stream , care are forma:
FileInputStream(String <sir>)
unde:
– <sir> – reprezinta numele, si eventual calea, fisierului; la specificarea caii fisierului trebuie sa se
foloseasca doua caractere backslash pentru a nu se confunda cu o secventa escape .
Daca fisierul nu poate fi deschis, atunci este lansata exceptia FileNotFoundException .
De exemplu, urmatoarea instructiune deschide un flux de intrare de la fisierul “test.dat”:
FileInputStream fis = new FileInputStream(“test.dat”);
Dupa deschiderea fluxul ui de intrare din fisier se pot folosi metodele acestui flux pentru realizarea
diverselor operatii de intrare. Descriem cateva dintre ele.
Metoda read() citeste un octet din fluxul de intrare; rezultatul intors este un intreg din intervalul 0 – 255.
Daca s -a detectat sfarsitul de fisier, rezultatul intors este -1.
Metoda read cu trei parametrii are forma:
read (byte [] <b>, int <poz_ini>, int <lungime>)
Object
FileInputStream
InputStream
FileOutputStream
OutputStream

unde:
– <b> – un tablou de octeti in care se vor memora datele citite;
– <poz_ini> – pozitia elementului din cadrul tabloului unde se va stoca primul octet de date;
– <lungime> – numarul de octeti care se vor citi din fluxul de intrare repetand metoda read fara
parametri.
Metoda returneaza un intreg care reprezinta numarul de octeti cititi sau -1 daca, de la inceput, fluxul de
intrare este la sfarsitul sau.
Metoda skip avanseaza cu n pozitii (octeti) in fluxul de intrare, nedepasind bineinteles sfarsitul fluxului.
Rezultatul intors de metoda este numarul de pozitii peste care s -a trecut efectiv.
Metoda skip are forma:
skip(long <n>)
unde :
<n> – nr de octeti sariti in fluxul de intrare.
Metoda available() este folosita pentru a returna numarul de octeti ce mai pot fi cititi la momentul
curent din fluxul de intrare.
Metoda close() inchide fluxul de intrare res pectiv si elibereaza resursele sistem asociate cu acesta.
De exemplu, programul “CitesteFiserOcteti .java” citeste octeti dintr -un flux de intrare al unui fisir cu
numele “test.dat”. Dupa citirea ultimului octet din fisier, pentru inchiderea fluxului de in trare se
foloseste metoda close() . Aceasta operatie trebuie realizata pentru a elibera resursele sistemului
asociate fisierului deschis.
Fisierul de intrare cu numele “test.dat” din care se citesc date in forma binara contine doua linii:
0123456789
Ionescu Florin
Acest fisier a fost creat cu utilitarul Notepad.
import java.io.*;
public class CitesteFisierOcteti
{
public static void main(String [] args)
{
try {
FileInputStream fis = new FileInputStream("test.dat");

int index = 0;
int octet = fis.read();
while (octet != -1)
{
System.out.print(octet + " ");
index++;
octet = fis.read();
}
fis.close();
System.out.println(" \nOcteti cititi: " + index);
}
catch (IOException e) {
System.out.println("Eroare – " + e.getMessage( ));
}
}
}
Dupa executia programului va fi afisat fiecare octet din fisierul “test.dat”, urmat de numarul total de
octeti cititi, ca mai jos:
48 49 50 51 52 53 54 55 56 57 13 10 73 111 110 101 115 99 117 32 70 108 111 114
105 110
Octeti cititi: 26
Observ atie: Se observa ca valorile octetilor afisati sunt codurile ASCII ale caracterelor din cele doua linii
existente in fisier.
Fluxuri nefiltrate de octeti de iesire care folosesc ca destinatie un fisier
Sunt folosite pentru transferul de date de la aplicati a Java catre fisierele aflate pe hard -discuri, pe CD –
ROM sau pe alte dispozitive de stocare (ce pot fi referite printr -o cale de director si un nume).
Crearea (deschiderea) unui flux de iesire catre un fisier se realizeaza cu ajutorul constructorului clasei
FileOutputStream , care are forma:
FileOutputStream(String <sir>)
unde:

– <sir> – reprezinta numele, si eventual calea, fisierului; la specificarea caii fisierului trebuie sa se
foloseasca doua caractere backslash pentru a nu se confunda cu o secventa escape .
Trebuie sa se aiba o grija deosebita atunci cand se specifica numele fisierului in care se scrie. Daca se
foloseste numele unui fisier deja existent, odata cu inceperea scrierii datelor, acesta va fi ste rs definitiv.
Constructorul cu doi parametrii are forma:
FileOutputStream(String <sir>, boolean <adauga>)
unde:
– <sir> – reprezinta numele, si eventual calea, fisierului; la specificarea caii fisierului trebuie sa se
foloseasca doua caractere backslash pentru a nu se confunda cu o secventa escape .
– <adauga> – poate avea valoare true, caz in care se face adaugarea datelor la sfarsitul fisierului, sau
poate avea valoarea false , caz in care nu se face adaugarea de date la sfarsitul fisierului ci suprascr ierea
datele existente; daca fisierul nu poate fi deschis, atunci este lansata exceptia FileNotFoundException .
De exemplu, urmatoarea instructiune deschide un flux de iesire catre fisierul “test1.dat”:
FileOutputStream fis = new FileOutputStream(“test1.dat ”);
import java.io.*;
public class CitesteFisierOcteti
{
public static void main(String [] args)
{
try {
FileInputStream fis = new FileInputStream("test.dat");
int index = 0;
int octet = fis.read();
while (octet != -1)
{
System.out.print( octet + " ");
index++;
octet = fis.read();
}
fis.close();

System.out.println(" \nOcteti cititi: " + index);
}
catch (IOException e) {
System.out.println("Eroare – " + e.getMessage());
}
}
}
Dupa executia programului va fi afisat fiecare octet din fisierul “test.dat”, urmat de numarul total de
octeti cititi, ca mai jos:
48 49 50 51 52 53 54 55 56 57 13 10 73 111 110 101 115 99 117 32 70 108 111 114
105 110
Octeti cititi: 26
Observatie : Se observa ca valorile octetilor afisati sunt coduril e ASCII ale caracterelor din cele doua linii
existente in fisier.
Fluxuri nefiltrate de octeti de iesire care folosesc ca destinatie un fisier
Sunt folosite pentru transferul de date de la aplicatia Java catre fisierele aflate pe hard -discuri, pe CD –
ROM sa u pe alte dispozitive de stocare (ce pot fi referite printr -o cale de director si un nume).
Crearea (deschiderea) unui flux de iesire catre un fisier se realizeaza cu ajutorul constructorului clasei
FileOutputStream , care are forma:
FileOutputStream(Strin g <sir>)
unde:
– <sir> – reprezinta numele, si eventual calea, fisierului; la specificarea caii fisierului trebuie sa se
foloseasca doua caractere backslash pentru a nu se confunda cu o secventa escape .
Trebuie sa se aiba o grija deosebita atunci cand se s pecifica numele fisierului in care se scrie. Daca se
foloseste numele unui fisier deja existent, odata cu inceperea scrierii datelor, acesta va fi sters definitiv.
Constructorul cu doi parametrii are forma:
FileOutputStream(String <sir>, boolean <adauga>)
unde:
– <sir> – reprezinta numele, si eventual calea, fisierului; la specificarea caii fisierului trebuie sa se
foloseasca doua caractere backslash pentru a nu se confunda cu o secventa escape .

– <adauga> – poate avea valoare true, caz in care se face ada ugarea datelor la sfarsitul fisierului, sau
poate avea valoarea false , caz in care nu se face adaugarea de date la sfarsitul fisierului ci suprascrierea
datele existente; daca fisierul nu poate fi deschis, atunci este lansata exceptia FileNotFoundException .
De exemplu, urmatoarea instructiune deschide un flux de iesire catre fisierul “test1.dat”:
FileOutputStream fis = new FileOutputStream(“test1.dat”);
Urmatoarea instructiune deschide un flux de iesire catre fisierul “test1.dat” pentru a adauga octeti la
sfarsitul fisierului:
FileOutputStream fis = new FileOutputStream(“test1.dat”, true);
Dupa deschiderea fluxului de iesire din fisier se pot folosi metodele acestui flux pentru realizarea
diverselor operatii de iesire. Descriem cateva dintre ele.
Metoda write cu un parametru scrie un octet in fluxul de iesire. Aceasta metoda are forma:
write(int <b>)
unde: <b> – variabila care contine octetul de scris in fluxul de iesire.
Metoda write cu parametru tablou scrie un tablou de octeti in fluxul de iesire si a re forma:
write (byte [] <b>)
unde:
– <b> – specifica un tablou de octeti care va fi scris in fluxul de iesire; in fisier vor fi scrisi b.length octeti.
Metoda write cu trei parametrii are forma:
write (byte [] <b>, int <poz_ini>, int <lungime>)
unde:
– <b> – specifica un tablou de octeti care va fi scris in fluxul de iesire;
– <poz_ini> – pozitia elementului din cadrul tabloului de la care se incepe scrierea in fluxul de iesire;
– <lungime> – numarul de octeti care se vor scrie in fluxul de iesire.
Metoda close() inchide fluxul de iesire respectiv.
Programul urmator (ScrieFisierOcteti.java) scrie un tablou de octeti intr -un flux de iesire intr -un fisier
dat, cu numele “test1.gif”. Dupa scrierea ultimului octet in fisier, pentru inchiderea fluxului de iesire se
foloseste metoda close() . Aceasta operatie trebuie realizata pentru a elibera resursele sistemului
asociate fisierului deschis.
import java.io.*;
public class ScrieFisierOcteti
{

public static void main (String [] args)
{
int [] octeti = { 71, 73, 70, 56, 57, 97, 15, 0, 15, 0,
128, 0, 0, 111, 111, 111, 0, 0, 0, 44, 0, 0, 0,
0, 15, 0, 15, 0, 0, 2, 33, 132, 127, 161, 200,
185, 205, 84, 128, 241, 81, 35, 175, 155, 26,
228, 25, 105, 33, 102, 0, 165, 201, 145, 169 ,
154, 142, 112, 0, 200, 200, 0, 200, 200, 200, 200 } ;
try {
FileOutputStream fis = new FileOutputStream("test1.gif");
for (int i = 0; i < octeti.length; i++)
fis.write(octeti[i]);
fis.close();
}
catch(IOException e) {
System.out.println("Eroare – " + e.getMessage());
}
}
}
B. Filtrarea fluxurilor de octeti si clase predefinite Java utilizate
Fluxurile filtrate sunt fluxuri care selecteaza si, astfel, modifica informatia transmisa pr intr-un flux
existent (de tip InputStream sau OutputStream ). Acestea sunt create folosind subclase ale claselor
FilterInputStream si FilterOutputStream .
Fluxurile FilterInputStream si FilterOutputStream nu realizeaza in mod direct nici un fel de operatie de
filtrare. Dar, din ele deriveaza subclase (de exemplu, BufferedInputStream ) care sunt folosite pentru
anumite tipuri de filtrari.
In schema de mai jos se prezinta doar o parte a structurii de clase ce poate fi folosita in operatiile cu
fluxuri de intra re si iesire filtrate.

B.1 Fluxuri de octeti cu o zona tampon (“buffer”)
Un tampon (“buffer”) reprezinta o zona de memorie RAM in care se pot pastra date din fluxul de
intrare sau de iesire pana la momentul citirii sau scrierii lor intr -o aplicatie Java. Prin folosirea unui
tampon se pot accesa (citi sau scrie) date fara a folosi sursa originala (fisierul) sau destinatia originala
(fisierul) de date.
Zona tampon este folosita ca o zona intermediara pentru citirea/ scrierea datelor din/in fluxul
de intrare/iesire. Pentru memoria tampon se mai foloseste si termenul de “memorie de lucru”.
Aceasta tehnica este mai eficienta intrucat utilizarea zonei tampon evita accesarea directa a
fisierului pentru fiecare citire/scriere, in acest mod micsorandu -se timpul de lucru al aplicatiei Java.
Nota : Deoarece fluxurile de intrare/ iesire cu tampon semnaleaza exceptia IOException la
aparitia unei erori, toate operatiile legate de fluxuri se incadreaza in blocuri try … catch , care sa
intercepteze aceasta exceptie.
Fluxuri de octeti de intrare cu o zona tampon
Un flux de intrare cu ta mpon poseda un tampon cu date din care se face citirea. Cand aplicatia
Java citeste date, acestea sunt cautate mai intai in zona tampon si apoi in sursa originara de intrare.
Fluxurile de octeti de intrare cu tampon folosesc clasa BufferedInputStream .
Crea rea (deschiderea) unui flux de intrare cu tampon se realizeaza cu ajutorul constructorilor
clasei BufferedInputStream . Cand este deschis un flux de intrare cu tampon se creaza si o zona tampon,
sub forma unui tablou de octeti, atasata acestuia.
Construct orii clasei BufferedInputStream au una din formele:
a)
FilterOutputStream
Object
DataOutputStream
BufferedOutputStream
PrintStream
FilterInputStream
DataInputStream
BufferedInputStream
InputStream
OutputStream

BufferedInputStream(InputStream <in>)
unde:
– <in> – reprezinta fluxul originar de tip InputStream .
Nota: Zona tampon are o lungime care este aleasa implicit (automat).
b)
BufferedInputStream(InputStream <in>, int <lg_buffer>)
unde:
– <in> – reprezinta fluxul originar de tip InputStream ;
– <lg_buffer> – reprezinta lungimea zonei tampon a fluxului de intare.
Dupa deschiderea fluxului de intrare cu tampon se pot folosi metodel e acestui flux pentru
realizarea diverselor operatii de intrare. Descriem cateva dintre ele.
Metoda read() citeste un octet din fluxul de intrare cu tampon; rezultatul intors este un intreg
din intervalul 0 – 255. Daca s -a detectat sfarsitul de fisier, rez ultatul intors este -1.
Metoda read cu trei parametrii are forma:
read (byte [] <b>, int <poz_ini>, int <lungime>)
unde:
– <b> – un tablou de octeti in care se vor memora datele citite;
– <poz_ini> – pozitia elementului din cadrul tabloului unde se va stoca primul octet de date;
– <lungime> – numarul de octeti care se vor citi din fluxul de intrare cu tampon repetand metoda
read fara parametri.
Metoda returneaza un intreg care reprezinta numarul de octeti cititi sau -1 daca, de la inceput,
fluxul de int rare este la sfarsitul sau.
Metoda skip avanseaza cu n pozitii (octeti) in fluxul de intrare cu tampon si descarca n octeti din
flux, nedepasind, bineinteles, sfarsitul fluxului. Rezultatul intors de metoda este numarul de pozitii peste
care s -a trecut efe ctiv.
Metoda skip are forma:
skip(long <n>)
unde :
<n> – nr de octeti sariti in fluxul de intrare si descarcati din fluxul de intare.
Metoda available () este folosita pentru a returna numarul de octeti ce mai pot fi cititi la
momentul curent atat din zon a tampon, cat si din fluxul de intrare.

Metoda close() inchide fluxul de intrare cu tampon si elibereaza resursele sistem asociate cu
acesta.
Fluxuri de octeti de iesire cu o zona tampon
Un flux de iesire cu tampon poseda un tampon cu date care nu au fost inca scrise in destinatia
originara a fluxului. Atunci cand datele sunt directionate intr -un flux de iesire cu tampon, continutul
acestuia nu va fi transmis catre destinatie decat dupa ce zona tampon atasata s -a umplut. Fluxurile de
octeti de iesire cu ta mpon folosesc clasa BufferedOutputStream .
Crearea (deschiderea) unui flux de iesire cu tampon se realizeaza cu ajutorul constructorilor
clasei BufferedOutputStream . Cand este deschis un flux de iesire cu tampon se creaza si o zona tampon,
sub forma unui ta blou de octeti, atasata acestuia.
Constructorii clasei BufferedOutputStream au una din formele:
a)
BufferedOuputStream(OutputStream <out>)
unde:
– <out> – reprezinta fluxul de iesire de tip OutputStream .
Nota: Zona tampon are o lungime care este aleasa implicit (automat).
b)
BufferedOutputStream(OutputStream <out>, int <lg_buffer>)
unde:
– <out> – reprezinta fluxul de iesire de tip OutputStream ;
– <lg_buffer> – reprezinta lungimea zonei tampon a fluxului de iesire.
Dupa deschiderea fluxului de iesire cu tampon se pot folosi metodele acestui flux pentru
realizarea diverselor operatii de iesire. Descriem cateva dintre ele.
Metoda write cu un parametru scrie un octet in fluxul de iesire cu tampon. Aceasta metoda are
forma:
write(int <b>)
unde: <b> – variabila care contine octetul de scris in fluxul de iesire cu tampon; valoarea acestei
variabile trebuie sa apartina intervalului 0 – 255; daca se incearca scrierea unei valori care este mai mare
decat 255 va fi stocat numai restul impartirii acestei valo ri la 256.
Metoda write cu trei parametrii are forma:
write (byte [] <b>, int <poz_ini>, int <lungime>)
unde:

– <b> – specifica un tablou de octeti care va fi scris in fluxul de iesire cu tampon;
– <poz_ini> – pozitia elementului din cadrul tabloului de la care se incepe scrierea in fluxul de
iesire cu tampon;
– <lungime> – numarul de octeti care se vor scrie in fluxul de iesire cu tampon.
Metoda skip avanseaza cu n pozitii (octeti) in fluxul de intrare cu tampon si descarca n octeti din
flux, nedepasind, b ineinteles, sfarsitul fluxului. Rezultatul intors de metoda este numarul de pozitii peste
care s -a trecut efectiv.
Metoda skip are forma:
skip(long <n>)
unde :
<n> – nr de octeti sariti in fluxul de intrare si descarcati din fluxul de intare.
Metoda avai lable () este folosita pentru a returna numarul de octeti ce mai pot fi cititi la
momentul curent atat din zona tampon, cat si din fluxul de intrare.
Metoda close() inchide fluxul de intrare cu tampon si elibereaza resursele sistem asociate cu
acesta.
Fluxu ri de octeti de iesire cu o zona tampon
Un flux de iesire cu tampon poseda un tampon cu date care nu au fost inca scrise in destinatia
originara a fluxului. Atunci cand datele sunt directionate intr -un flux de iesire cu tampon, continutul
acestuia nu va f i transmis catre destinatie decat dupa ce zona tampon atasata s -a umplut. Fluxurile de
octeti de iesire cu tampon folosesc clasa BufferedOutputStream .
Crearea (deschiderea) unui flux de iesire cu tampon se realizeaza cu ajutorul constructorilor
clasei BufferedOutputStream . Cand este deschis un flux de iesire cu tampon se creaza si o zona tampon,
sub forma unui tablou de octeti, atasata acestuia.
Constructorii clasei BufferedOutputStream au una din formele:
a)
BufferedOuputStream(OutputStream <out>)
unde:
– <out> – reprezinta fluxul de iesire de tip OutputStream .
Nota: Zona tampon are o lungime care este aleasa implicit (automat).
b)
BufferedOutputStream(OutputStream <out>, int <lg_buffer>)
unde:

– <out> – reprezinta fluxul de iesire de tip OutputStre am;
– <lg_buffer> – reprezinta lungimea zonei tampon a fluxului de iesire.
Dupa deschiderea fluxului de iesire cu tampon se pot folosi metodele acestui flux pentru
realizarea diverselor operatii de iesire. Descriem cateva dintre ele.
Metoda write cu un parametru scrie un octet in fluxul de iesire cu tampon. Aceasta metoda are
forma:
write(int <b>)
unde: <b> – variabila care contine octetul de scris in fluxul de iesire cu tampon; valoarea acestei
variabile trebuie sa apartina intervalului 0 – 255; daca se incearca scrierea unei valori care este mai mare
decat 255 va fi stocat numai restul impartirii acestei valori la 256.
Metoda write cu trei parametrii are forma:
write (byte [] <b>, int <poz_ini>, int <lungime>)
unde:
– <b> – specifica un tablou de octeti care va fi scris in fluxul de iesire cu tampon;
– <poz_ini> – pozitia elementului din cadrul tabloului de la care se incepe scrierea in fluxul de
iesire cu tampon;
– <lungime> – numarul de octeti care se vor scrie in fluxul de iesire cu tampon.
Metoda flush() transmite (scrie) continutul zonei tampon la destinatia fluxului de iesire originar
chiar daca aceasta zona tampon nu s -a umplut inca. Cu ajutorul acestei metode se realizeaza golirea
zonei tampon chiar daca aceasta nu s -a umplut inca.
Metoda close() inchide fluxul de iesire cu tampon si elibereaza resursele sistem asociate cu
acesta.
Urmatorul program (IOBinarTampon.java) scrie o serie de octeti intr -un flux de iesire cu tampon
asociat cu un fisier pe disc. Limita inferioara si limita superioara din s eria de numere sunt specificate in
doua argumente transmise prin linia de comanda, ca in exemplul urmator:
java IOBinarTampon 2 30
Daca nu se transmit argumente prin linia de comanda, implicit limita inferioara este 0 iar limita
superioara este 255.
Dupa s crierea in fisier, programul deschide un flux de intrare cu tampon si citeste octetii scrisi in
fisier.
import java.io.*;
public class IOBinarTampon {
public static void main (String [] args) {

int limInf = 0;
int limSup = 255;
try {
if (args.length > 1)
{
limInf = Integer.parseInt(args[0]);
limSup = Integer.parseInt(args[1]);
}
else
if(args.length > 0)
limInf = Integer.parseInt(args[0]);
FluxOcteti fo = new FluxOcteti(limInf, limSup);
System.out.println(" \nScrie: ");
boolean succesScrie = fo.scrieFlux();
System.out.println(" \nCiteste: ");
boolean succesCiteste = fo.citesteFlux();
}
catch(NumberFormatException nfe) {
System.out.println("Eroare: " + "Nu ati introdus un numar intreg");
}
}
}
boolean citesteFlux() {
try {
BufferedInputStream fluxTampon = new BufferedInputStream(
new FileInputStream("numere.dat"));
int i = 0;
do
{

i = fluxTampon.read();
if (i != -1)
System.out.print(" " + i);
} while (i != -1);
fluxTampon.close();
return tr ue;
}
catch(IOException e) {
System.out.print("Eroare: " + e.getMessage());
return false;
}
}
}Observatie: Aplicatia Java prezentata mai sus poate primi unul sau doua argumente atunci cand
este lansata. Modul de transmitere a unor argumente la aplicatii Java depinde de platforma pe care se
executa Java. In Windows si Unix se pot transmite argumente prin interm ediul liniei de comanda.
Argumentele trebuie adaugate la executie dupa numele programului si daca sunt mai multe
decat unul, atunci argumentele sunt separate prin spatii.
In cadrul aplicatiei Java, argumentele din linia de comanda sunt preluate de metoda main() sub
forma unui tablou de siruri:
public static void main(String [] args) {
//corpul metodei
}
Argumentele din linia de comanda sunt stocate in tabloul de siruri de caractere incepand cu
primul element din tablou (care are indexul 0). Deci, in tablou l de siruri de caractere al metodei main()
nu se preia si numele programului ca la C/C++.
B2. Fluxuri filtrate cu date de tipuri primitive
Clasele DataInputStream si DataOutputStream ofera, ca facilitate suplimentara, posibilitatea ca
fluxurile sa nu mai fie privite strict la nivel de octet, ci ca succesiuni de date primitive. Prin aceasta,
datele vor fi scrise in fluxul de iesire intr -un format independent de modul de reprezentare al datelor in
sistemul pe care se lucreaza.
Constructorul clasei DataInputStream creaza un nou flux de intrare ce suprapune pe cel existent
primit ca argument. Constructorul are forma :

DataInputStream(InputStream <in>) unde:
– <in> – specifica fluxul de int rare existent, de exemplu, un flux de intrare cu tampon sau un flux
de intrare din fisier.
Constructorul clasei DataOutputStream creaza un nou flux de iesire ce suprapune pe cel existent
primit ca argument. Constructorul are forma :
DataOutputStream(OutputS tream <out>) unde:
– <out> – specifica fluxul de iesire existent, de exemplu, un flux de iesire cu tampon sau un flux
de iesire in fisier.
Deoarece fluxurile filtrate de intrare/iesire cu date de tipuri primitive semnaleaza exceptia
IOException la aparitia unei erori, toate operatiile legate de fluxuri se incadreaza in blocuri try … catch ,
care sa intercepteze aceasta exceptie.
Urmatoarea lista prezinta metodele de citire si de scriere ce pot fi folosite pentru fluxurile de
tipul DataInputStream , si respect iv de tipul DataOutputStream :
– readBoolean(); writeBoolean(boolean <v>);
– readChar(); writeChar(char <v>);
– readDouble(); writeDouble(double <v>);
– readFloat(); writeFloat(float <v>);
– readInt(); writeInt(int <v>);
– readLong(); writeLong(long <v>);
– readShort(); writeShort(short <v>);
Fiecare dintre metodele de citire prezentate incearca sa citeasca un numar de octeti egal cu
lungimea pe care sunt reprezentate tipurile respective indicate in numele metodei. De exemplu, metoda
readBoolean() citeste un octet si returneaza true daca octetul citit este diferit de zero.
Fiecare dintre metodele de scriere prezentate incearca sa scrie un numar de octeti egal cu
lungimea pe care sunt reprezentate tipurile respective indicate in numele metodei. De exemplu, met oda
writeBoolean() scrie intr -un octet valoarea 1 sau valoarea 0, dupa cum parametrul <v> este true sau
false .
Observatii:
1. Datele citite folosind metodele clasei DataInputStream trebuie sa fi fost scrise in fisier cu
metodele complementare ale clasei DataOutputStream .
2. Nu toate metodele de citire dintr -un flux de tip DataInputStream returneaza o valoare ce
poate indica faptul ca s -a ajuns la sfarsitul fluxului. In astfel de cazuri se semnaleaza exceptia
EOFException care indica faptul ca s -a ajuns la sfarsitul fluxului de intrare.

Urmatorul program (IODataTampon.java) scrie o serie de valori de tip float intr-un flux de iesire
DataOutputStream cu tampon asociat cu un fisier pe disc. Limita inferioara si limita superioara din seria
de numere reale sunt specificate in doua argumente transmise prin linia de comanda, ca in exemplul
urmator:
java IOBinarData 2 30
Daca nu se transmit argumente prin linia de comanda, implicit limita inferioara este 0 iar limita
superioara este 255.
Dupa scrierea in fisier, pro gramul deschide un flux de intrare cu tampon si citeste datele de tip
float scrise in fisier.
import java.io.*;
public class IODataTampon {
public static void main (String [] args) {
float limInf = 0;
float limSup = 255;
try {
if (args.length > 1)
{
limInf = Float.parseFloat(args[0]);
limSup = Float.parseFloat(args[1]);
}
else
if(args.length > 0)
limInf = Float.parseFloat(args[0]);
FluxDatePrimitive fd = new FluxDatePrimitive(limInf, limSup);
boolean succesScrie = fd.scrieFlux();
System.out.println(" \nCiteste: ");
boolean succesCiteste = fd.citesteFlux();
}
catch(NumberFormatException nfe) {
System.out.println("Eroare: " + "Nu ati introdus un numar real");

}
}
}
class FluxDatePrimitive {
private float inceput = 0;
private float sfarsit = 255;
public FluxDatePrimitive(float inceput, float sfarsit) {
this.inceput = inceput;
this.sfarsit = sfarsit;
}
boolean scrieFlux() {
try {
DataOutputStream fluxDate = new DataOutputStream(
new BufferedOutputSt ream(new FileOutputStream("numere.dat")));
for (float i = inceput; i <= sfarsit; i+=0.5)
fluxDate.writeFloat(i);
fluxDate.close();
return true;
}
catch(IOException e) {
System.out.print("Eroare: " + e.getMessage());
return false;
}
}
boolean citesteFlux() {
try {
DataInputStream fluxDate = new DataInputStream(
new BufferedInputStream(new FileInputStream("numere.dat")));
float i = 0;

try {
while (true)
{
i = fluxDate.readFloat();
System.out.print(" " + i);
}
}
catch(EOFException eof) {
fluxDate.close();
}
return true;
}
catch(IOException e) {
System.out.print("Eroare: " + e.getMessage());
return false;
}
}
}
Aplicatia prezentata este un exemplu de suprapunere a mai multor filtre peste un flux originar
de tip FileInputStream. Fluxul filtrat este construit in trei etape:
– se creaza un flux de iesire in fisier, asociat cu fisierul “numere.dat”;
– se asocieaza fluxului de fisier un flux de iesire filtrat cu tampon;
– se asociaza f luxului de iesire cu tampon un flux de tip DataInputStream.
Instructiunea while(true) din metoda citesteFlux() creaza un ciclu infinit in aparenta, pentru ca la
un moment dat va fi atins sfarsitul fluxului si va fi semnalata o exceptie EOFException. Metoda
readFloat() citeste valorile reale din flux.
B3. Fluxuri filtrate cu date formatate
Clasa PrintStream furnizeaza un flux filtru de iesire care permite afisarea de numere, valori
boolean , String si alte tipuri de obiecte in format text. Filtrul de iesire PrintStream converteste numerele
si alte tipuri de date la reprezentari text, inainte de transmiterea datelor la fluxul de iesire. De exemplu,

atunci cand programul afiseaza valoarea intreaga 42, clasa PrintStream converteste numarul la
caracterele “4” si “2” si apoi transmite caracterele mai departe in flux.
In plus, fluxul PrintStream da posibilitatea (optional) de a goli automat zona tampon dupa ce a
fost scris un tablou de octeti sau un octet egal cu ‘\n’. Metodele acestei clase nu semnaleaza niciodata
exceptia IOException .
Fluxul System.out , pe care l -am folosit aproape in toate lectiile de pana acum pentru afisarea
mesajelor la ecranul calculatorului, este de fapt un flux de tip PrintStream .
Prezentam doi dintre constructorii acestei clase:
PrintStrea m(OutputStream <out>)
PrintStream(OutputStream <out>, boolean <auto_golire>)
unde:
– <out> – specifica fluxul de iesire existent;
<auto_golire> – specifica daca se goleste automat zona tampon dupa ce a fost scris un tablou de
octeti sau un octet egal cu ‘\n’ (daca valoarea este true).
Mentionam cateva metode ale acestei clase:
– print (String <s>)
– print (char <c>)
– print (boolean <b>)
– print (char <c>)
– print (int <i>)
– print (long <l>)
– print (float <f>)
– print (double <d>)
Pentru fiecare metoda pr int exista si perechea ei println , care adauga caracterul ‘ \n’ in fluxul de
iesire.
In plus, exista si metoda println fara parametrii , care scrie doar caracterul de sfarsit de linie ‘ \n’.
Metodele print si println scriu argumentul lor intr -un format de t ip text si anume identic cu cel
produs de apelurile metodei String.valueOf(x) .
Un flux PrintStream nu are ca destinatie numai ecranul calculatorului ci orice destinatie de flux,
inclusiv un fisier text ASCII. De exemplu, urmatoul program (PrintStreamFile.j ava) afiseaza un String , un
intreg si un numar in virgula mobila intr -un fisier, “print.txt”.
import java.io.*;

public class PrintStreamFile {
public static void main(String [] args) {
double nr1 = 234.5;
int nr2 = 120;
try {
PrintStream ps = new PrintStream(new FileOutputStream("print.txt"));
ps.println ("Date pentru testarea fluxului PrintStream");
ps.print(nr1);
ps.print(' ');
ps.print(nr2);
ps.println();
ps.println(Math.PI);
ps.close();
}
catch(IOException e) {
System.out.pr intln("Eroare la scrierea fisierului: " + e.getMessage());
}
}
}
Fluxuri de caractere si clase predefinite Java utilizate
Fluxurile de caractere se folosesc pentru lucrul cu orice text reprezentat in format ASCII sau
Unicode (set de caractere internatio nal care include si ASCII). Ele opereaza asupra sirurilor de caractere
si tablourilor de caractere.
Exemple de fisiere cu care putem lucra prin intermediul fluxurilor de caractere sunt fisierele de
text simplu, documentele HTML sau fisiere care contin cod sursa Java.
A. Fluxuri de caractere de intrare nefiltrate si filtrate
In schema de mai jos se prezinta doar o parte a structurii de clase ce poate fi folosita in
operatiile cu fluxuri de caractere de intrare nefiltrate si filtrate.
Clasa Reader este o clas a abstracta si din ea deriveaza toate celelalte clase care creaza fluxuri de
caractere de intrare si realizeaza operatii de intrare pe aceste fluxuri.

Nota : Deoarece fluxurile de intrare semnaleaza exceptia IOException la aparitia unei erori, toate
operati ile legate de fluxuri se incadreaza in blocuri try … catch , care sa intercepteze aceasta exceptie.
Este indicat sa folosim clasa Reader pentru lucru cu text si nu fluxuri de octeti.
A.1 Fluxuri nefiltrate de caractere de intrare care folosesc ca sursa un fisier
Sunt folosite pentru transferul de date de la fisierele aflate pe hard -discuri, pe CD -ROM sau pe
alte dispozitive de stocare (ce pot fi referite printr -o cale de director si un nume) catre aplicatia Java.
Principala clasa folosita pentru citirea de fluxuri de caractere dintr -un fisier este FileReader . Aceasta
clasa mosteneste clasa InputStreamReader , care citeste un flux de octeti si ii converteste in valori intregi
corespunzatoare caracterelor Unicode.
Crearea (deschiderea) unui flux de intrare de l a un fisier se realizeaza cu ajutorul constructorului
clasei FileReader , care are forma:
FileReader(String <sir>)
unde:
– <sir> – reprezinta numele, si eventual calea, fisierului; la specificarea caii fisierului trebuie sa se
foloseasca doua caractere backslash pentru a nu se confunda cu o secventa escape .
Daca fisierul nu poate fi deschis, atunci este lansata exceptia FileNotFoundException .
De exemplu, urmatoarea instructiune deschide un flux de intrare de la fisierul “test.doc”:
FileReader document = new FileReader(“test.doc”);
Dupa deschiderea fluxului de caractere de intrare din fisier se pot folosi metodele acestui flux
pentru realizarea diverselor operatii de intrare. Descriem cateva dintre ele.
Metoda read() citeste un caracter din fluxul de intra re; rezultatul intors este un intreg din
intervalul 0 – 65535. Daca s -a detectat sfarsitul de fisier, rezultatul intors este -1.
Metoda read cu trei parametrii are forma:
read (char [] <c>, int <poz_ini>, int <lungime>)
unde:
– <c> – un tablou de caractere in care se vor memora datele citite;
– <poz_ini> – pozitia elementului din cadrul tabloului unde se va stoca primul caracter de date;
– <lungime> – numarul de caractere care se vor citi din fluxul de intrare repetand metoda read
fara parametri.
Metoda ret urneaza un intreg care reprezinta numarul de caractere citite sau -1 daca, de la
inceput, fluxul de intrare este la sfarsitul sau.
Nota: Deoarece metoda read() a unui flux de caractere returneaza o valoare intreaga, trebuie sa
se converteasca explicit prin cast aceasta valoare inainte de a o afisa sau de a o salva intr -un tablou de

caractere. Fiecare caracter poseda un cod numeric care reprezinta pozitia sa in setul de caractere
Unicode. Valoarea intreaga citita din flux reprezinta chiar acest cod numeric.
Metoda skip avanseaza cu n pozitii (caractere) in fluxul de intrare, nedepasind bineinteles
sfarsitul fluxului. Rezultatul intors de metoda este numarul de pozitii peste care s -a trecut efectiv.
Metoda skip are forma:
skip(long <n>)
unde :
<n> – nr de car actere sarite in fluxul de intrare.
Metoda ready() specifica daca acest flux de caractere este disponibil pentru a fi citit. Un flux de
caractere dintr -un fisier este disponibil pentru a fi citit daca zona tampon de intrare nu este goala (in caz
ca ea exi sta) sau daca exista octeti disponibili de a fi cititi de la fluxul de octeti de tip InputStreamReader .
Metoda close() inchide fluxul de intrare respectiv si elibereaza resursele sistem asociate cu
acesta.
A.2 Fluxuri filtrate de caractere de intrare cu o zona tampon (“buffer”)
Fluxurile de caractere cu o zona tampon (“buffer”) permit utilizarea unei zone tampon pentru
cresterea eficientei operatiilor de citire.
Fluxurile de caractere de intrare cu tampon folosesc clasa BufferedReader .
Crearea (deschiderea) unui flux de caractere cu tampon se realizeaza cu ajutorul constructorilor
clasei BufferedReader .
Constructorii clasei BufferedReader au una din formele:
a)
BufferedReader(Reader <in>) unde:
– <in> – reprezinta fluxul original de tip Reader .
Nota: Zona tampon are o lungime care este aleasa implicit (automat).
b)
BufferedReader(Reader <in>, int <lg_buffer>) unde:
– <in> – reprezinta fluxul original de tip Reader ;
– <lg_buffer> – reprezinta lungimea zonei tampon a fluxului de intare.
Dintr -un flux d e caractere cu tampon se poate citi folosind metodele read () si
read (char [] <c>, int <poz_ini>, int <lungime>) , asemanatoare celor descrise pentru clasa
FileReader .
Metodele skip() , ready() si close() sunt asemanatoare celor descrise pentru clasa FileReader .

Programul urmator (CitesteSiruri.java) citeste doua siruri de caractere de la tastatura si le
stocheaza intr -un tablou de caractere de lungime 20. Daca dupa citirea primului sir, in zona tampon mai
exista caractere necitite (ceea ce inseamna ca s-a introdus un sir de lungime mai mare de 20) atunci
acestea vor fi sarite din fluxul de intrare pentru a permite eliberarea zonei tampon si citirea de la
tastatura a celui de al doilea sir.
import java.io.*;
class CitesteSiruri {
public static void mai n(String[] args)
{
char[] caractere1 = new char[20];
char[] caractere2 = new char[20];
for (int i=0; i <=19; i++)
caractere1[i] = ' ';
for ( int i=0; i <=19; i++)
caractere2[i] = ' ';
try {
BufferedReader br = new BufferedReader(new InputStrea mReader(System.in));
System.out.println ("Introduceti primul sir");
br.read(caractere1, 0, 20);
String sir1 = new String(caractere1);
System.out.println(sir1);
while ( br.ready() )
br.skip (1);
System.out.println ("Introduceti al doilea sir");
br.read(caractere2, 0, 20);
String sir2 = new String(caractere2);
System.out.println(sir2);
boolean rezultat = false;
rezultat = sir1.equals(sir2);
if (rezultat ==true)

System.out.println ("siruri egale");
else
System.out.println ("siruri difer ite");
}
catch(IOException e) {
System.out.println ("Eroare la sirul citit" + e.getMessage());
}
}
}
Metoda readLine () citeste din fluxul de intrare o linie de text. Metoda returneaza un obiect de
tip String care contine linia de text citita din flux , fara a include si caracterul (sau caracterele) care
reprezinta sfarsitul de linie. Daca se ajunge la sfarsitul fluxului, valoarea sirului returnat va fi null.
Sfarsitul de linie este indicat astfel:
– un caracter de linie noua (newline – ‘\n’);
– un c aracter de retur de car (carriage return – ‘\r’);
– un retur de car urmat de o linie noua.
Ca exemplu, putem ilustra deschiderile de flux de intare cu tampon si citirile de linii de text de la
tastatura, facute in aproape toate programele Java prezentate pana acum.
Dintr -un fisier se poate citi o intreaga linie de text, si nu caracter cu carecter, daca se foloseste
un flux de caractere cu tampon de tip BufferedReader suprapus peste un flux de tip FileReader .
Programul urmator (CitesteLiniiFisier.java) ilu streaza modul de citire linie cu linie dintr -un fisier
care contine instructiuni Java (numit “CitesteLiniiFisier.java”), folosind un flux de caractere cu zona
tampon.
import java.io.*;
public class CitesteLiniiFisier {
public static void main (String [] a rgs) {
try {
BufferedReader fisier = new BufferedReader(
new FileReader("CitesteLiniiFisier.java"));
boolean eof = false;
while(!eof)

{
String linie = fisier.readLine();
if (linie == null)
eof = true;
else
System.out.println(linie);
}
fisier.close();
}
catch(IOException e) {
System.out.println("Eroare: " + e.getMessage());
}
}
}
A.3 Fluxuri filtrate de caractere de intrare cu o zona tampon care tin evidenta nume relor de
linie
Fluxurile de caractere de intrare cu tampon care tin evidenta numerelor de linie dintr -un fisier
folosesc clasa LineNumberReader . Acest filtru al fluxului de intrare tine evidenta numarului de linie pe
masura citirii din fluxul de intrare.
Crearea (deschiderea) unui flux de caractere cu tampon care tin evidenta numerelor de linie se
realizeaza cu ajutorul constructorilor clasei LineNumberReader .
Constructorii clasei LineNumberReader au una din formele:
a)
LineNumberReader(Reader <in>) unde:
– <in> – reprezinta fluxul originar de tip Reader .
Nota: Zona tampon are o lungime care este aleasa implicit (automat).
b)
LineNumberReader(Reader <in>, int <lg_buffer>) unde:
– <in> – reprezinta fluxul originar de tip Reader ;
– <lg_buffer> – reprezinta lungimea zonei tampon a fluxului de intare.

Metodele pentru citirea, inchiderea, testarea unui flux de intrare cu tampon sunt mostenite de
la clasa BufferedReader si ele au fost prezentate deja.
In plus, aceasta clasa ofera metoda getLineNumber () care este folosita pentru a obtine numarul
liniei curente din fluxul de intrare atunci cand acesta este citit cu metoda readLine() .
Metoda returneaza un intreg care reprezinta numarul liniei curente din flux.
Dintr -un fisier se poate citi o intreaga li nie de text si se poate tine evidenta numerelor citite daca
se foloseste un flux de caractere cu tampon de tip LineNumberReader suprapus peste un flux de tip
FileReader .
Programul urmator (CitesteLiniiFisier.java) afiseaza numerele liniilor citite dintr -un fisier care
contine instructiuni Java (numit “CitesteLiniiFisier1.java”), folosind un flux de caractere cu zona tampon
tip LineNumberReader .
import java.io.*;
public class CitesteLiniiFisier1 {
public static void main (String [] args) {
try {
LineNu mberReader fisier = new LineNumberReader(new

FileReader("CitesteLiniiFisier1.java"));
boolean eof = false;
while(!eof)
{
String linie = fisier.readLine();
if (linie == null)
eof = true;
else
System.o ut.println(fisier.getLineNumber() + " " + linie);
}
fisier.close();
}
catch(IOException e) {
System.out.println("Eroare: " + e.getMessage());

}
}
}

Curs 10
Cuvinte importante:
– fluxuri de caractere de iesire nefiltrate si filtrate: fluxuri nefiltrate care folosesc ca destinatie
un fisier; fluxuri filtrate cu o zona tampon (“buffer”);
– fluxuri de intrare/iesire care perimt accesul direct la date (fluxuri cu acces direct sau
“random”): constructori; metode;
– clasa File: constructori; metode;
– clasa StringTokenizer folosita pentru analizarea lexicala (a cuvintelor) dintr -un flux de intrare:
constructori; metode;
– despre fire de executie in Jav a: proces, fir de executie; crearea firelor de executie; schimbarea
prioritatii firelor de executie.
B. Fluxuri de caractere de iesire nefiltrate si filtrate
In schema de mai jos se prezinta doar o parte a structurii de clase ce poate fi folosita in opera tiile cu
fluxuri de caractere de iesire nefiltrate si filtrate.

Clasa Writer este o clasa abstracta si din ea deriveaza toate celelalte clase care creaza fluxuri de
caractere de iesire si realizeaza operatii de iesire pe aceste fluxuri.
Nota : Deoarece fl uxurile de iesire semnaleaza exceptia IOException la aparitia unei erori, toate operatiile
legate de fluxuri se incadreaza in blocuri try … catch , care sa intercepteze aceasta exceptie.
Este indicat sa folosim clasa Writer pentru lucru cu text si nu fluxur i de octeti.
B.1 Fluxuri nefiltrate de caractere de iesire care folosesc ca destinatie un fisier
OuputStreamWriter
Object
BufferedWriter
Writer
FileWriter

Clasa FileWrite este folosita pentru crearea si scrierea unui flux de caractere intr -un fisier. Aceasta este o
subclasa a clasei OutputStreamWriter , care are rolul de a converti codurile caracterelor Unicode in
octeti.
Crearea (deschiderea) unui flux de caractere de iesire catre un fisier se realizeaza cu ajutorul
constructorului clasei FileWriter , care are forma:
FileWriter(String <sir>)
unde:
– <sir> – reprezinta numele, si eventual calea, fisierului; la specificarea caii fisierului trebuie sa se
foloseasca doua caractere backslash pentru a nu se confunda cu o secventa escape .
Trebuie sa se aiba o grija deosebita atunci cand se specifica numele fisier ului in care se scrie. Daca se
foloseste numele unui fisier deja existent, odata cu inceperea scrierii datelor, acesta va fi sters definitiv.
Constructorul cu doi parametrii are forma:
FileWriter(String <sir>, boolean <adauga>)
unde:
– <sir> – reprezinta n umele, si eventual calea, fisierului; la specificarea caii fisierului trebuie sa se
foloseasca doua caractere backslash pentru a nu se confunda cu o secventa escape .
– <adauga> – poate avea valoare true, caz in care se face adaugarea datelor la sfarsitul fisierului, sau
poate avea valoarea false , caz in care nu se face adaugarea de date la sfarsitul fisierului ci suprascrierea
datele existente; daca fisierul nu poate fi deschis, atunci este lansata exceptia FileNotFoundException .
Clasa FileWriter are trei metode ce pot fi folosite pentru a scrie date intr -un flux:
write (char <c>) – scrie in flux un caracter specificat in parametrul <c>;
write (char [] <c>, int <poz_ini>, int <lungime>)) – scrie in flux caractere din tabloul specificat <c>,
incepand de la po zitia <poz_ini> si avand numarul de caractere dat de <lungime>;
write (String <str>, int <poz_ini>, int <lungime>) – scrie in flux caractere din sirul specificat <str>,
incepand de la pozitia <poz_ini> si avand numarul de caractere dat de <lungime>.
Constructorul cu doi parametrii are forma:
FileWriter(String <sir>, boolean <adauga>)
unde:
– <sir> – reprezinta numele, si eventual calea, fisierului; la specificarea caii fisierului trebuie sa se
foloseasca doua caractere backslash pentru a nu se confund a cu o secventa escape .
– <adauga> – poate avea valoare true, caz in care se face adaugarea datelor la sfarsitul fisierului, sau
poate avea valoarea false , caz in care nu se face adaugarea de date la sfarsitul fisierului ci suprascrierea
datele existente; daca fisierul nu poate fi deschis, atunci este lansata exceptia FileNotFoundException .

Clasa FileWriter are trei metode ce pot fi folosite pentru a scrie date intr -un flux:
write (char <c>) – scrie in flux un caracter specificat in parametrul <c>;
write (char [] <c>, int <poz_ini>, int <lungime>)) – scrie in flux caractere din tabloul specificat <c>,
incepand de la pozitia <poz_ini> si avand numarul de caractere dat de <lungime>;
write (String <str>, int <poz_ini>, int <lungime>) – scrie in flux caractere d in sirul specificat <str>,
incepand de la pozitia <poz_ini> si avand numarul de caractere dat de <lungime>.
Metoda close() inchide fluxul de iesire respectiv.
B.2 Fluxuri filtrate de caractere de iesire cu o zona tampon (“buffer”)
Fluxurile de caractere cu o zona tampon (“buffer”) permit utilizarea unei zone tampon pentru cresterea
eficientei operatiilor de scriere. Fluxurile de caractere de iesire cu tampon folosesc clasa BufferedWriter .
Crearea (deschiderea) unui flux de caractere cu tampon se realizeaza cu ajutorul constructorilor clasei
BufferedWriter .
Constructorii clasei BufferedWriter au una din formele:
a)
BufferedWriter(Writer <in>) unde:
– <in> – reprezinta fluxul originar de tip Writer .
Nota: Zona tampon are o lungime care este aleasa implicit (automat).
b)
BufferedWriter(Writer <in>, int <lg_buffer>) unde:
– <in> – reprezinta fluxul originar de tip Writer ;
– <lg_buffer> – reprezinta lungimea zonei tampon a fluxului de iesire.
Clasa BufferedWriter poseda aceleasi trei metode de scriere care au fost prezentate la clasa FileWriter .
O metoda folositoare este newLine() , care scrie in fisier caracterul (sau caracterele) ce specifica sfarsitul
liniei pe platforma folosita pentru executia programului.
Metoda close() este apel ata pentru a inchide fluxul de caractere de iesire si pentru a asigura ca toate
datele memorate in zona tampon au fost trimise catre destinatia fluxului.
Urmatorul program (ScrieFisierText.java) citeste date de la tastatura si scrie intr -un flux de caracte re cu
tampon, catre o destinatie care este un fisier cu numele “scrie_linii.dat”.
import java.io.*;
public class ScrieFisierText {
public static void main (String [] args) {

String linie;
try {
BufferedWriter fisier = new BufferedWriter(
new FileWriter("scrie_linii.dat"));
BufferedReader in = new BufferedReader(
new InputStreamReader(System.in));
System.out.println("Introduceti o linie de text iar la sfarsit tastati <Enter> ");
do {
linie = in.readLine();
fisier.write(linie, 0, linie.length());
fisier.newLine();
} while (linie.length() != 0);
fisier.close();
}
catch(IOException e) {
System.out.println("Eroare: " + e.getMe ssage());
}
}
}
Fluxuri de intrare/iesire care perimt accesul direct la date (fluxuri cu acces direct sau “random”)
Clasa RandomAccessFile ofera posibilitatea de a lucra cu fisiere in acces direct (random).
Clasa RandomAccessFile deriva direct d in superclasa Object nefiind subclasa a claselor InputStream sau
OutputStream .
Accesul la datele din fluxul este la nivel de octet.
Intr-un flux de date cu acces direct sunt permise atat scrieri, cat si citiri. Fisierul, nou sau existent, poate
fi deschis fie pentru citire, fie pentru citire si scriere.
Accesul direct la date este asigurat prin gestionarea unui indicator care identifica pozitia incepand de la
care se face o citire sau o scriere; dupa o astfel de operatie, indicatorul avanseaza cu numarul d e octeti
cititi sau scrisi.

Este asigurata atat posibilitatea de a afla pozitia indicatorului (reprezentand numarul de octeti din fisier
aflati la stanga indicatorului), cat si posibilitatea de a da indicatorului o anumita valoare care sa il
pozitioneze, astfel, la locul in care se doreste sa aiba loc urmatoarea citire sau scriere.
De asemenea, clasa RandomAccessFile ofera posibilitatea de a determina lungimea fisierului. Aceasta
lungime nu este definitiva: o operatie de scriere care face ca indicatorul sa depaseasca sfarsitul curent al
fisierului are ca efect modificarea lungimii acestuia; in schimb o pozitionare a indicatorului dincolo de
sfarsitul fisierului neurmata de o scriere in fisier nu schimba lungimea fisierului.
Incercarea de a citi dincolo de s farsitul fisierului va determina semnalarea exceptiei EOFException .
Crearea (deschiderea) unui flux cu acces direct (random) se realizeaza cu ajutorul constructorului clasei
RandomAccesFile , care are forma:
RandomAccessFile(String <sir>, String <mod>)
unde:
– <sir> – reprezinta numele, si eventual calea, fisierului; la specificarea caii fisierului trebuie sa se
foloseasca doua caractere backslash pentru a nu se confunda cu o secventa escape ; daca fisierul nu
exista el este creat;
– <mod> – specifica doua valori: “r” – fisierul poate fi folosit numai pentru citire;
“rw” – fisierul poate fi folosit atat pentru citire cat si pentru scriere.
Dupa deschiderea fluxului cu acces direct (random) se pot folosi metodele acestui flux pentru realizarea
diverselor operatii de intrare sau de iesire. Descriem cateva dintre ele.
Metoda getFilePointer () returneaza pozitia curenta a indicatorului, in bytes, de la care va avea loc
urmatoarea citire sau scriere in flux. Returneaza un tip de data long
Metoda seek() pozitioneaza indicatorul la pozitia data de parametrul <poz> pornind de la inceputul
fisierului; de la aceasta pozitie se va putea realiza o noua citire sau scriere din/in fisier. Forma acestei
metode este:
seek(long <poz>)
Metoda length () returneaza lungimea curenta a fisierului.
Metoda close() inchide fluxul de date cu acces direct, eliberand resursele sistemului.
Metoda read() citeste un octet din fluxul de intrare; rezultatul intors este un intreg din intervalul 0 – 255.
Daca s -a detecta t sfarsitul de fisier, rezultatul intors este -1.
Metoda read cu trei parametrii are forma:
read (byte [] <b>, int <poz_ini>, int <lungime>)
unde:
– <b> – un tablou de octeti in care se vor memora datele citite;

– <poz_ini> – pozitia elementului din cadrul tabloului unde se va stoca primul octet de date;
– <lungime> – numarul de octeti care se vor citi din fluxul de intrare repetand metoda read fara
parametri.
Metoda returneaza un intreg care reprezinta numarul de octeti cititi sau -1 daca, de la inceput, f luxul de
intrare este la sfarsitul sau.
Deoarece clasa RandomAccessFile implementeaza interfetele DataInput si DataOutput, metodele de
citire si de scriere pentru datele de tipuri primitive sunt aceleasi cu cele de la clasele DataInputStream si
DataOutputS tream :
– readBoolean (); writeBoolean (boolean <v>);
– readChar (); writeChar (char <v>);
– readDouble (); writeDouble (double <v>);
– readFloat (); writeFloat (float <v>);
– readInt (); writeInt (int <v>);
– readLong (); writeLong (long <v>);
– readShort (); writeShort (short <v>);
Fiecare dintre metodele de citire/scriere prezentate incearca sa citeasca/sa scrie un numar de octeti
egal cu lungimea pe care sunt reprezentate tipurile primitive respective indicate in numele metodei.
Metoda readLine () citeste din fluxul de intrare o linie de text. Metoda returneaza un obiect de tip String
care contine linia de text citita din flux , fara a include si caracterul (sau caracterele) care reprezinta
sfarsitul de linie. Daca se ajunge la sfarsitul fluxului, valoarea sirului returnat va fi null.
Metoda write cu un parametru scrie un octet in fluxul de iesire. Aceasta metoda are forma:
write(int <b>)
unde: <b> – variabila care contine octetul de scris in fluxul de iesire.
Metoda write cu trei parametrii are for ma:
write (byte [] <b>, int <poz_ini>, int <lungime>)
unde:
– <b> – specifica un tablou de octeti care va fi scris in fluxul de iesire;
– <poz_ini> – pozitia elementului din cadrul tabloului de la care se incepe scrierea in fluxul de iesire;
– <lungime> – numarul de octeti care se vor scrie in fluxul de iesire.
Urmatorul program (ScrieFisierRandom.java) scrie intr -un fisier de tip Random si apoi citeste din fisierul
deja creat si afiseaza continutul acestuia.
import java.io.*;

public class ScrieFisierRandom {
public static void main (String [] args) {
String numeAutor;
String titluCarte;
int nrEx;
String linie;
char [] caractere = new char[20];
try {
RandomAccessFile fisier = new RandomAccessFile("carte.dat", "rw");
BufferedRe ader in = new BufferedReader(
new InputStreamReader(System.in));
do {
System.out.println("Nume autor ");
linie = in.readLine();
if (linie.length() > 20)
numeAutor = linie.substring(0, 20);
else
numeAutor = linie;
System.out.println("Titlul cartii");
linie = in.readLine();
if (linie.length() > 20)
titluCarte = linie.substring(0, 20);
else
titluCarte = linie;
System.out.println("Numar de exemp lare:");
linie = in.readLine();
for (int i = 0; i <= 19; i++)
caractere[i] = ' ' ;
if (linie.length() > 0)

{
nrEx = Integer.parseInt(linie);
char [] buffer = numeAutor.toCharArray();
for (int i = 0; i <= buffer.len gth-1; i++)
caractere[i]=buffer[i];
for (int i = 0; i <= 19; i++)
fisier.writeChar(caractere[i]);
for (int i = 0; i <= 19; i++)
caractere[i] = ' ' ;
buffer = titluCarte.toCharArray();
for (int i = 0; i <= buffer.length -1; i++)
caractere[i]=buffer[i];
for (int i = 0; i <= 19; i++)
fisier.writeChar(caractere[i]);
fisier.writeInt(nrEx); }
} while (linie.length() != 0);
System.out.println(fisier.length());
System.out.println();
fisier.seek(0);
while( fisier.getFilePointer() <= fisier.length() -1)
{
System.out.print("Nume autor: ");
for (int i = 0; i <= 19; i++)
System.out.print(fisier.readChar());
System.out.println();
System.ou t.print("Titlu carte: ");
for (int i = 0; i <= 19; i++)
System.out.print(fisier.readChar());
System.out.println();

System.out.print("Numar exemplare: ");
System.out.println(fisier.readInt());
System.out.println();
}
fisier.close();
}
catch(IOException e) {
System.out.println("Eroare: " + e.getMessage());}
catch(NumberFormatException nfe) {
System.out.println("Nu ati introdus un numar intreg");}
}
}
Clasa File
Clasa File permite specificarea numelor de fisiere si directoare intr -un mod independent de sistemul de
operare de pe calculatorul gazda, precum si realizarea in program a unor operatii asupra fisierelor si
directoarelor (creare, stergere, renumire etc.).
Pentr u separarea informatiilor ce identifica o cale, sistemele Windows si Unix folosesc, respectiv
caracterele “ \” si “/”. Intr -o insiruire de cai, cele doua sisteme folosesc respectiv caracterele “;” si “:”.
Pentru a permite independenta de platforma, clasa File contine, pentru cele doua tipuri de separatori,
constantele: File.separator si File.pathSeparator , care primesc automat pe fiecare sistem de operare
reprezentarea corespunzatoare.
Nota : Un obiect de tip File ce specifica un nume de fisier poate fi folosit ca parametru pentru crearea de
fluxuri de tipurile FileInputStream , FileOutputStream , FileReader si FileWriter .
Pentru a crea un obiect de tip File se pot folosi urmatorii constructori :
a)
File(String <cale >) – specifica un director sau un fisier;
b)
File(String <cale>, String <nume_fisier>) – specifica o cale de directori si un nume de fisier;
c)
File(File <director>, String <nume_fisier>) – specifica un nume de director de tip File si un nume de fisier.
Vom descrie cateva metode mai des folosite din clasa File.

Metoda exist () returneaza o valoare de tip boolean care arata daca fisierul exista sub numele si in
directorul specificate la crearea obiectului File.
Metoda length () returneaza o valoare de tip l ong ce reprezinta dimensiunea in octeti a fisierului.
Metoda renameTo (File <nume_nou>) redenumeste fisierul sub numele dat in parametrul <nume_nou>
si returneaza o valoare de tip boolean care indica daca operatia s -a finalizat cu succes sau nu.
Metoda dele te() sterge un fisier sau un director si returneaza o valoare de tip boolean care indica
succesul operatiei.
Metoda mkdir () se foloseste pentru a crea un director specificat de obiectul File care a fost creat in
prealabil. Metoda returneaza o valoare de t ip boolean care indica daca operatia s -a finalizat cu succes
sau nu.
Metoda setReadOnly () se foloseste pentru a permite numai citirea fisierului sau directorului specificat
de obiectul File. Metoda returneaza o valoare de tip boolean care indica daca operatia s -a finalizat cu
succes sau nu.
Metoda canRead () se foloseste pentru a testa daca un fisier specificat de obiectul File poate fi citit.
Returneaza valoarea true daca fisierul exista si poate fi citit sau false daca nu.
Metoda canWrite () se foloseste pentru a testa daca un fisier specificat de obiectul File poate fi
modificat. Returneaza valoarea true daca fisierul exista si se poate scrie in el sau false daca nu.
Metoda list() se foloseste pentru a stoca numele tuturor fisierelor si directoarelor existente intr -un
director specificat de obiectul File. Metoda returneaza un tablou de siruri de caractere in care sunt
stocate numele fisierelor si directoarelor continute intr -un director specificat de obiectul File. Daca
obiectul de tip File nu este un director atunci se returneaza valoarea null.
Fiecare dintre aceste metode va semnala o exceptie SecurityException daca programul nu are
permisiunile necesare pentru executarea operatiilor respective. Deci se folosesc blocuri try … catch sau
clauze throws pentru a trata aceste exceptii.
Programul urmator (DemoLucruFisiere.java) converteste textul dintr -un fisier in litere mari. Fisierul cu
numele citit de la tastatura este verificat daca exista pe disc si apoi este citit caracter cu caracter . Dupa
conversia caracterului in litera mare, el este scris intr -un fisier temporar folosind un flux de iesire cu
tampon. In loc de siruri de caractere pentru numele fisierelor, s -au folosit obiecte File, facand posibila
stergerea fisierului din care s -au citit caracterele si redenumirea fisierului temporar creat in care toate
caracterele sunt litere mari.
import java.io.*;
public class DemoLucruFisiere {
public static void main(String [] args) {
try {
BufferedReader consola = new BufferedReader(

new InputStreamReader(System.in));
System.out.println("Introduceti numele unui fisier: ");
ConversieLitere litMari = new ConversieLitere(consola.readLine());
litMari.conversie();
}
catch(IOException e) {
System.out.println("Eroare: " + e.getMessage());
}
}
}
class ConversieLitere {
String numeSursa;
ConversieLitere(String nume) {
numeSursa = nume;
}
void conversie() {
try {
File sursa = new File(numeSursa);
boolean exista = sursa.exists();
File temp = new File( numeSursa + ".tmp");
BufferedReader in = new BufferedReader(new
FileReader(sursa));
BufferedWriter out = new BufferedWriter(new
FileWriter(temp));
boolean eof = false;
int carCitit = 0;
do
{
carCitit = in.read();

if (carCitit != -1)
{
char carScris =
Character.toUpperCase((char)carCitit);
out.write(carScris);}
else
eof = true;
} while (!eof);
in.close();
out.close();
boolean sters = sursa.delete();
if(sters)
temp.renameTo(sursa);
}
catch(IOException e) {
System.out.println("Eroare: " + e.getMessage());
}
catch(SecurityException se) {
System.out.println("Eroare: " + se.getMessage());
}
}
}
Nota: Metoda toUpperCase() apartine clasei Character si realizeaza conversia unui caracter din litere
mici in litere mari.
Clasa StringTokenizer folosita pentru analizarea lexicala (a cuvintelor) dintr -un flux de intrare
Clasa StringTokenizer este inclusa in p achetul java.util si permite separarea elementelor lexicale
(“tokens”) distincte din cadrul unui sir de caractere.

Separarea in elemente lexicale (“tokenization”) inseamna impartirea, printr -un caracter delimitator, a
sirului initial intr -un numar de elem ente lexicale distincte. Implicit, Java foloseste ca delimitatori ai
elementelor lexicale caracterul tab, caracterul spatiu si caracterul de linie noua (“newline”). Obiectele de
tip StringTokenizer pot fi construite pentru a accepta si alti delimitatori de elemente lexicale.
Metodele -constructor ale clasei StringTokenizer, mai des folosite, au forma:
a)
StringTokenizer(String <str>)
unde:
– <str> – specifica sirul de caractere supus separarii in elemente lexicale;
b)
StringTokenizer(String <str>, String <d elimitator>)
unde:
– <str> – specifica sirul de caractere supus separarii in elemente lexicale;
– <delimitator> – specifica o lista de caractere de delimitare; de exemplu, un parametru <delimitator> de
felul “,:” indica faptul ca delimitatorii sunt virgula si doua puncte
Constructorul prezentat la pct. b) este folosit pentru a schimba delimitatorul implicit de elemente
lexicale.
Vom descrie cateva metode ale clasei StringTokenizer .
Metoda nextToken () este folosita pentru a extrage fiecare element lexical dintr -un sir de caractere
utilizand delimitatorii impliciti Java sau delimitatorii precizati explicit la crearea obiectului de tip
StringTokenizer . Metoda returneaza un sir de caractere care reprezint a elementul lexical extras.
Metoda nextToken poate fi folosita si cu un parametru de tip String care are ca efect schimbarea
delimitatorului folosit pentru separarea elementelor lexicale din sirul curent dupa ce obiectul de tip
StringTokenizer a fost crea t. In acest caz metoda are forma:
String nextToken(String <delimitator_nou>) unde:
– <delimitator_nou> – specifica noul delimitator dupa care se va face extragerea unui element lexical de
la pozitia curenta in sirul curent supus separarii pana la intanlire a delimitatorului precizat in parametrul
metodei.
Metoda returneaza un sir de caractere care reprezinta elementul lexical extras pe baza noului
delimitator.
Aceasta metoda genereaza o exceptie NoSuchElementException daca nu mai exista nici un element
lexical in sirul curent supus separarii.

Metoda hasMoreTokens () este folosita pentru a afla daca sirul curent supus separarii contine mai multe
elemente lexicale (cuvinte). Metoda returneaza valoarea true daca sirul curent supus separarii contine
mai multe ele mente lexicale si false daca nu.
Urmatoarea secventa de cod ilustreaza folosirea metodei nextToken cu un parametru:
StringTokenizer st = new StringTokenizer(“Nume si Prenume:Ionescu Florin”, “:”);
System.out.println(“Primul element – “ + st.nextToken());
while (st.hasMoreTokens()) {
System.out.println(“Urmatorul element – “ + st.nextToken(“ “));}
In acest caz, programul va afisa urmatorul rezultat:
Primul element – Nume si Prenume
Urmatorul element – Ionescu
Urmatorul element – Florin
Metoda countTokens () este folosita pentru a specifica numarul de elemente lexicale pe care le contine
sirul curent supus separarii. Metoda returneaza un intreg care reprezinta numarul de elemente lexicale
pe care le contine sirul curent.
Urmatorul program (TestTokenizer.java ) ilustreaza modul de folosire a unui obiect de tip StringTokenizer
pentru a separa un sir de numere, citite de la tastatura pe aceeasi linie, folosid ca delimitator caracterul
spatiu. Dupa citire, sirul de numere este stocat intr -un tablou de numere intre gi.
Programul foloseste doua metode ale clasei CitesteDate din pachetul intrareiesire si anume:
citesteString () si citesteSeparaSir ().
Metoda citesteString () citeste de la tastatura un sir de numere pe o singura linie.
Metoda citesteSeparaSir () separa sirul de numere citit in elemente lexicale folosind ca delimitator
caracterul spatiu si converteste aceste elemente intr -un tablou de numere intregi.
import intrareiesire.*;
class TestTokenizer
{
public static void main(String[] args)
{
System.out.println("Introduceti un sir de numere pe aceeasi linie:");
int [] tablouInt = CitesteDate.citesteSeparaSir();
System.out.println ("Tabloul de numere citit este: ");
for (int i = 0; i < tablouInt.length; i++)

System.out.println(tablouInt[i] + " ");
}
}
package intrareiesire;
import java.io.*;
import java.util.StringTokenizer;
/* citeste un sir de caractere il separa in elemente lexicale, folosind delimitatorul spatiu
* si creaza un tablu de numere de tipul int */
public class CitesteDate {
public static String citesteString() {
BufferedReader br = new BufferedReader(
new InputStreamReader(System.in));
try {
return br.readLine();
}
catch(IOException ioe) {
return null;
}
}
public static int citesteNrInt() {
try {
return Integer.parseInt(citesteString());
}
catch(NumberFormatException nfe) {
System.out.println("Nu este numar intreg. Se stocheaza valoarea 0.");
return 0;
}
}
public static int [] citesteSeparaSir() {

String sir = citesteString();
StringTokenizer st = new StringTokenizer(sir);
int[] tablou = new int[st.countTokens()];
for (int i = 0; i < tablou.length; ++i)
{
try {
tablou[i] = Integer.parseInt(st.nextToken());
}
catch(NumberFormatException nfe) {
System.out.pr intln("Nu este numar intreg. Se stocheaza
valoarea 0.");
tablou[i] = 0;
}
}
return tablou;
}
}
Despre fire de executie in Java
Programarea calculatoarelor “traditionala” presupune existenta unui procesor; instructiunile unicului
prog ram sunt executate secvential de catre unicul procesor existent. Putem numi acest tip de
programare ca fiind programare neconcurenta .
Calculatoarele moderne realizeaza, insa, atat prin resurse software cat si prin hardware, desfasurarea
concomitenta a mai multor actiuni.
Un proces este un program de sine statator, care dispune de propriul sau spatiu de adrese. Un sistem de
operare multitasking cu un singur procesor este capabil sa execute mai multe procese (programe) in
acelasi timp, oferindu -le periodic un anumit numar de cicluri procesor, lasand astfel impresia ca fiecare
proces se executa independent, in paralel cu altul.
Un fir de executie (“thread”) reprezinta o secventa de instructiuni din cadrul procesului (programului
executabil). Firele de executie (“threads”) permit unui program sa execute mai multe parti (secvente de
instructiuni) din el insusi in acelasi timp. Deci, un singur proces poate sa contina mai multe fire care se
executa in mod concurent si interactioneaza (coopereaza) intre ele in timp. Putem numi acest tip de
programare ca fiind programare concurenta .

Un exemplu tipic de utilizare a firelor de executie il reprezinta un browser de Web care permite
descarcarea unui numar de fisiere (fiecare operatie de descarcare reprezentand un fir de ex ecutie) timp
in care, se poate sa se realizeze navigarea prin alte pagini (pe un alt fir de executie).
Un alt exemplu poate fi o aplicatie de procesare de texte. Aplicatia poate utiliza un fir de executie pentru
a procesa intrarile de la tastatura ale util izatorului, al doilea fir de executie verifica ortografia
documentului si al treilea fir de executie salveaza periodic documentul utilizatorului intr -un fisier pe disc.
Firele de executie sunt asemanatoare cu procesele , in sensul ca pot fi executate indepe ndent si
simultan, dar difera prin faptul ca nu implica un consum de resurse atat de mare ca acestea.
Daca pe sistemul gazda se afla mai multe procesoare atunci firele de executie din cadrul aplicatiei pot sa
se execute pe procesoare diferite, realizand astfel un paralelism real.
Specificatiile limbajului Java definesc firele de executie ca facand parte din bibliotecile Java standard
(pachetele java.lang.* ).
Chiar daca aplicatia Java nu creaza fire de executie, in fapt, exista automat doua astfel de fire : cel
curent (firul de executie principal – metoda main() a aplicatiei Java) si cel folosit de colectorul de
gunoaie .
Observatie: Desi firele de executie dau impresia ca doua sau mai multe secvente de cod se executa in
acelasi timp, in realitate, calculato rul poate sa execute numai unul dintre fire la un moment dat. Pentru
a crea iluzia ca firele sunt executate simultan, Java comuta rapid controlul de la un fir la altul – fiecare fir
executandu -se pentru scurt timp inainte de a trece controlul la un alt fir .
Crearea firelor de executie in Java
In Java se folosesc doua variante pentru a crea fire de executie:
– se foloseste clasa Thread din pachetul java.lang ;
– se implementeaza interfata Runnable .
Derivarea din clasa Thread este cea mai simpla modalitate de a crea un fir de executie.
Cea mai importanta metoda a clasei Thread este run(). Prin redefinirea acestei metode se precizeaza
instructiunile care trebuie executate de firul de executie. Practic, metoda run() furnizeaza codul care va
fi executat in paralel cu codul celorlalte fire de executie din cadrul programului.
Metoda start () predefinita in clasa Thread lanseaza executia propriu -zisa a firului de executie si apeleaza
automat metoda run().
Nota: Daca nu se apeleaza m etoda start () firul de executie nu va fi pornit niciodata.
Observatie: Desi firele de executie dau impresia ca doua sau mai multe secvente de cod se executa in
acelasi timp, in realitate, calculatorul poate sa execute numai unul dintre fire la un moment da t. Pentru
a crea iluzia ca firele sunt executate simultan, Java comuta rapid controlul de la un fir la altul – fiecare fir
executandu -se pentru scurt timp inainte de a trece controlul la un alt fir.
Crearea firelor de executie in Java

In Java se folosesc doua variante pentru a crea fire de executie:
– se foloseste clasa Thread din pachetul java.lang ;
– se implementeaza interfata Runnable .
Derivarea din clasa Thread este cea mai simpla modalitate de a crea un fir de executie.
Cea mai importanta metoda a clasei Thread este run(). Prin redefinirea acestei metode se precizeaza
instructiunile care trebuie executate de firul de executie. Practic, metoda run() furnizeaza codul care va
fi executat in paralel cu codul celorlalte fire de executie din cadrul progr amului.
Metoda start () predefinita in clasa Thread lanseaza executia propriu -zisa a firului de executie si apeleaza
automat metoda run().
Nota: Daca nu se apeleaza metoda start () firul de executie nu va fi pornit niciodata.
Deci, crearea unui fir de execu tie se realizeaza in 2 pasi astfel:
1. Se defineste o clasa (a firului de executie) care deriveaza din clasa Thread in care se
redefineste metoda run();
2. Se creaza obiectul de tipul clasei definite la pct. 1, cu ajutorul unui constructor adecvat si se
apeleaza metoda start () pentru a lansa (porni) firul de executie care apeleaza automat si metoda run();
pasul 2 se realizeaza in metoda main () a aplicatiei Java.
Urmatorul program (TestThread.java) creaza 3 fire de executie, fiecare fir avand asociat un numar unic
stocat in variabila de instanta numarFir , generat cu ajutorul variabilei statice contorFir (variabila de
clasa). In metoda run() se scade valoarea unui contor numit contorCiclu la fiecare executie a ciclului
while , pana cand valoarea contorului ajunge la 0, moment in care metoda run() se incheie si firul de
executie se termina.
public class TestThread extends Thread
{
private static int contorFir = 0;
private int numarFir ;
public TestThread() //constructorul clasei
{
numarFir = ++contorFir ;
System.out.println("Creez firul nr. " + numarFir);
public void run() //contine instructiunile executate de fir
{
int contorCiclu = 5;

while(true)
{
System.out.println("Fir nr. " + numarFir + "(" +
contorCiclu + ")");
if(–contorCiclu == 0)
{
return;
}
}
}
public static void main(String[] args)
{
for(int i = 0; i < 3; i++)
{
new TestThread().start(); // lanseaza firul de executie
}
System.out.println("Firele de executie au fost pornite.");
}
}
Iesirea afisata de program, care difera de la o executie la alta, este:
Creez firul nr. 1
Creez firul nr. 2
Creez firul nr. 3
Fir nr. 1(5)
Fir nr. 2(5)
Fir nr. 1(4)
Fir nr. 2(4)
Fir nr. 1(3)
Fir nr. 2(3)

Fir nr. 1(2)
Fir nr. 2(2)
Fir nr. 1(1)
Fir nr. 2(1)
Firele de executie au fost pornite.
Fir nr. 3(5)
Fir nr. 3(4)
Fir nr. 3(3)
Fir nr. 3(2)
Fir nr. 3(1)
Se observa ca firele d e executie nu au fost executate in ordinea in care au fost create.
Observatie: Ordinea in care procesorul ruleaza firele de executie este nedeterminata, cu exceptia
situatiei in care se foloseste metoda setPriority () pentru a modifica prioritatea de execu tie a unui fir.
Implementarea interfetei Runnable reprezinta o modalitate mai eficienta de creare a unui fir de
executie.
Toate clasele care implementeaza interfata Runnable trebuie sa implementeze metoda run() a acestei
interfete.
Noul fir este lansat in executie tot cu ajutorul clasei Thread , care ofera un constructor avand ca
parametru o instanta a unei clase care implementeaza interfata Runnable .
Aceasta modalitate de creare a unui fir de executie trebuie aleasa atunci cand clasa pe care o cream nu
se poate deriva din clasa Thread , pentru ca extinde alta clasa.
Deci, crearea unui fir de executie folosind interfata Runnable se realizeaza in 3 pasi astfel:
1. Se defineste o clasa (a firului de executie) care implementeaza interfata Runnable in care se
defineste metoda run();
2. Se creaza obiectul de tipul clasei definite la pct. 1, cu ajutorul unui constructor adecvat; acest
obiect creat este si de tip Runnable ;
3. Obiectul creat la pasul 2 este folosit ca parametru la constructia obiectul ui de tip Thread ,
adica a firului de executie; apoi se apeleaza metoda start () a acestui nou obiect pentru a lansa (porni)
firul de executie care apeleaza automat si metoda run() a obiectului creat la pasul 2 care este si de tip
Runnable ; pasul 3 se realiz eaza in metoda main () a aplicatiei Java.
Programul urmator (TestRunnable.java) reprezinta varianta Runnable a programului TestThread.java
prezentat deja. Diferentele sunt evidentiate mai ingrosat.
public class TestRunnable implements Runnable {

private static int contorFir = 0;
private int numarFir ;
public TestRunnable()
{
numarFir = ++contorFir ;
System.out.println("Creez firul nr. " + numarFir); }
public void run()
{
int contorCiclu = 5;
while(true)
{
System.out.println("Fir nr. " + numarFir + "(" +
contorCiclu + ")");
if(–contorCiclu == 0)
{
return;
}
}
}
public static void main(String[] args)
{
for(int i = 0; i < 3; i++)
{
new Thread(new TestRunnable()).start();
}
System.out.println("Firele de executie au fost pornite.");
}
}
Schimbarea prioritatii firelor de executie

Java creaza iluzia ca mai multe fire de executie ruleaza in acelasi timp, prin rapida comutare a
controlului procesorului intre fire. In functie de scopul aplicatiei, se poate schimba prioritatea de
procesare a unui anumit fir care este data implicit de Java. In acest fel se poate determina care fir de
executie urmeaza sa se execute.
Prioritatea firelor de executie furnizeaza o modalitate d e a acorda unui fir un avantaj fata de alte fire
care isi disputa timpul de procesare.
In Java, prioritatea unui fir de executie poate lua valori de la 1 la 10, unde 1 reprezinta cea mai joasa
prioritate, iar 10 reprezinta prioritatea cea mai inalta.
De a semenea, Java defineste trei constante care pot fi utilizate pentru selectarea prioritatii firelor:
MIN_PRIORITY , care este egala cu 1;
NOM_PRIORITY , care este egala cu 5;
MAX_PRIORITY , care este egala cu 10.
Un fir de executie mosteneste de la firul pa rinte o prioritate implicita care este, de obicei,
NOM_PRIORITY.
Daca exista mai multe fire cu prioritate maxima, acestea sunt planificate dupa un algoritm round -robin.
Firele de prioritate mai mica intra in executie doar atunci cand toate firele de priori tate mare sunt
inactive.
Pentru a schimba prioritatea unui fir de executie se foloseste metoda setPriority () a clasei Thread .
Pentru a afla prioritatea unui fir de executie se foloseste metoda getPriority () a clasei Thread .
Programul urmator (TestPriority. java) arata modul in care se poate stabili prioritatea unui fir de
executie. Programul creaza doua fire de executie minFir si maxFir si atribuie acestor obiecte prioritatea
1si respectiv prioritatea 10. Programul porneste apoi fiecare fir care executa o bu cla for afisand repetat
numele firului respectiv urmat de numarul iteratiei ciclului for.
class UnFir extends Thread {
public UnFir(String nume) {
super(nume);
}
public void run() {
for(int i=0; i < 8; i++)
{
System.out.println( getName() + " " + i); }
}
}

public class TestPriority {
public static void main(String[] args)
{
UnFir minFir = new UnFir("Fir Min");
UnFir maxFir = new UnFir("Fir Max");
minFir.setPriority(Thread.MIN_PRIORITY);
maxFir.setPriority(Thread.MAX_PRIORITY);
minFir.start();
maxFir.start();
System.out.println("Firele de executie au fost pornite.");
}
}
Nota:
1. Constructorul folosit pentru clasa UnFir este definit pe baza constructorului clasei Thread cu un
parametru care are forma:
public Thread (String <nume_fir>) in care parametrul specifica numele firului de executie care se creaza.
2. Metoda getName () este mostenita de la clasa Thread si returneaza un sir de caractere care specifica
numele firului de executie curent.
Dupa executia programului pe ecranul calculatorului sunt afisate:
Fir Max 0
Fir Max 1
Fir Max 2
Fir Max 3
Fir Max 4
Fir Max 5
Fir Max 6
Fir Max 7
Firele de executie au fost pornite.
Fir Min 0

Fir Min 1
Fir Min 2
Fir Min 3
Fir Min 4
Fir Min 5
Fir Min 6
Fir Min 7
Se observa ca firul cu prioritate mai inalta monopolizeaza iesirea la consola.

Curs 11
Cuvinte importante:
– starile unui fir de executie: “fir nou creat”, “fir in executie”, “fir intrerupt”, “fir mort”;
– intreruperea unui fir de executie folosind metoda sleep ();
– asteptarea terminarii unui fir de executie folosind metoda join();
– despre programarea concurenta;
– sincronizarea partajarii datelor intre firele de executie: inconsistenta la concurenta; sectiune
critica; modificatorul synchronized , instructiunea synchronized ; monitor;
– coordonarea firelor de executie prin asteptare: metodele wait (), notify () si notifyAll ();
– starea de blocare circulara (deadlock);
– verificarea starii unui fir de exe cutie folosind metoda isAlive ().
Starile unui fir de executie
Un fir de executie se poate afla in Java in mai multe stari, in functie de ce se intampla cu el la un
moment dat.
In timpul executiei aplicatiei Java, un obiect de tip Thread (fir de executie) poate fi in una din
urmatoarele patru stari:
– “fir nou creat” (“new”);
– “fir in executie” (“runnable”);
– “fir intrerupt” (“not runnable”);
– “fir mort” (“dead”).

Atunci cand este creat folosind operatorul new , dar inainte de apelul metodei start (), firul se gaseste in
starea “fir nou creat” (“runnable”). In aceasta stare, se pot apela, pentru firul de executie, doar
metodele start () si stop ().
Metoda start () lanseaza (“porneste”) firul in executie prin apelul metodei run().
Metoda stop () “omoara” firul de executie inca inainte de a fi “pornit”.
Orice alta metoda apelata in aceasta stare provoaca terminarea firului de executie prin generarea unei
exceptii de tipul IllegalThreadStateException .
In starea “fir in executie” (“runnable”) un fir executa c odul din metoda sa run(). Metoda run() este
partea principala a unui fir. Pentru a trece firul de la starea “fir nou creat” la starea “fir in executie” este
necesar sa apelam metoda start ().
Cand un fir de executie este inactiv, el se afla in starea “fir intrerupt” . Aceasta este o stare temporara.
Un fir devine inactiv daca se apeleaza metodele sleep () sau wait (). De asemenea, firul intra in starea “fir
intrerupt” si daca asteapta terminarea unei operatii de intrare/iesire de lunga durata, caz in care firu l va
intra din nou in starea “fir in executie” doar dupa terminarea acelei operatii.
Pe timpul in care firul de executie se afla in starea “fir intrerupt”, acesta nu este planificat deloc la
controlul unitatii centrale, acesta fiind dat celorlalte fire de executie din aplicatie.
Starea finala a unui fir de executie este starea “fir mort” . Aceasta stare este pastrata pana la momentul
in care obiectul este eliminat din memorie de mecanismul de colectare a gunoaielor.
Un fir intara in starea “fir mort” atunci cand metoda run() a firului de executie se incheie normal.
Intreruprea unui fir de executie folosind metoda sleep ()
Metoda sleep (), inclusa in clasa Thread , se foloseste atunci cand se doreste ca firul de executie sa faca o
pauza scurta intr -un interval de timp. Suspendarea executarii unui fir cu metoda sleep () reprezinta o
modalitate de partajare a timpului de procesare .
Metoda sleep () are forma:
public static void sleep (<nr_milisecunde) unde:
– <nr_milisecunde> – specifica numarul de milisecunde pentru care se doreste intreruperea executiei
firului.
Dupa trecerea intervalului specificat firul de executie va fi pornit din nou.
Metoda sleep () semnaleaza o exceptie de tipul InterruptedException care trebuie interceptata de
metoda care a apelat -o printr -un bloc try … catch .
Programul urmator (TestSleep.java) ilustreaza modul de folosire a metodei sleep () pentru a intrerupe pe
o perioada de 500 de milisecunde (o jumatate de secunda) firul de executie cu prioritate maxima.
Programul creaza doua fire de executi e minFir si maxFir si atribuie acestor obiecte prioritatea 1si
respectiv prioritatea 10. Programul porneste apoi fiecare fir care executa o bucla afisand repetat numele
firului respectiv.

class UnFirNou extends Thread {
public UnFirNou(String nume) {
super(nume); }
public void run() {
for(int i=0; i < 8; i++) {
System.out.println(getName() + " " + i);
try {
sleep(500); }
catch(InterruptedException ie) {
System.out.println("Se porneste jumatate de secunda mai tarziu"); }
}
}
}
public class TestSleep {
public static void main(String[] args) {
UnFirNou minFir = new UnFirNou("Fir Min");
UnFirNou maxFir = new UnFirNou("Fir Max");
minFir.setPriority(Thread.MIN_PRIORITY);
maxFir.setPriority(Thread.MAX_PRIORITY);
minFir .start();
maxFir.start();
System.out.println("Firele de executie au fost pornite.");
}
}
Dupa executia programului la consola se afiseaza:
Fir Max 0
Firele de executie au fost pornite.
Fir Min 0
Fir Max 1

Fir Min 1
Fir Max 2
Fir Min 2
Fir Max 3
Fir Min 3
Fir Max 4
Fir Min 4
Fir Max 5
Fir Min 5
Fir Max 6
Fir Min 6
Fir Max 7
Fir Min 7
Se obseva ca datorita intreruperii firului cu prioritate maxima, firul de executie cu prioritate minima se
poate executa in timpul intreruperii celui cu prioritate maxima.
Asteptarea terminarii unui fir de executie folosind metoda join()
Metoda join() este folosita in cazul in care un fir de executie porneste unul sau mai multe fire de
executie iar acest fir trebuie sa astepte terminarea activitatilor firelor pe care le-a lansat inainte de a
continua executia propriilor actiuni. In lipsa acestei metode, firul, care a lansat unul sau mai multe fire,
isi continua activitatea in paralel cu firele pe care le -a pornit.
Metoda join(), inclusa in clasa Thread (), are forma:
public final void join()
Metoda face ca firul de executie care a lansat la randul sau un fir de executie sa astepte terminarea
acestuia (fara precizarea duratei de timp) inainte de a trece la urmatoarea actiune prevazuta in
activitatea lui (codul lui).
Metoda join() semnaleaza o exceptie de tipul InterruptedException care trebuie interceptata de metoda
care a apelat -o printr -un bloc try … catch .
Programul urmator (TestJoin.java) ilustreaza modul de folosire a metodei join(). Firul principal (metoda
main ()) porneste trei fire de executie si asteapta terminarea executiei fiecarui fir pentru a executa
ultima instructiune, care afiseaza la consola un mesaj. Acest program este o varianta a programului
TestThread.java descris in lectia 10.
class UnFirExec extends Thread {

private static int contorFir = 0;
private int numarFir ;
public UnFirExec() {
numarFir = ++contorFir ;
System.out.println("Creez firul nr. " + numarFir);
}
public void run() {
int contorCiclu = 5;
while(true)
{
System.out.println("Fir nr. " + numarFir + "(" +
contorCiclu + ")");
if(–contorCiclu == 0)
{ return; }
}
}
}
public class TestJoin {
public static void main(String[] args) {
UnFirExec [] ob = new UnFirExec [3];
System.out.println("Se pornesc firele de executie");
for (int i=0; i<3; i++)
{
ob[i] = new UnFirExec();
ob[i].start();
try {
ob[i].join();}
catch(InterruptedException ie) {

System.out.println("Firul de executie principal asteapta
terminarea"); }
}
System.out.println("Firele de executie s -au pornit.");
}
}
Dupa executia programului la consola se afiseaza urmatoarele:
Se pornesc firele de executie
Creez firul nr. 1
Fir nr. 1(5)
Fir nr. 1(4)
Fir nr. 1(3)
Fir nr. 1(2)
Fir nr. 1(1)
Creez firul nr. 2
Fir nr. 2(5)
Fir nr. 2(4)
Fir nr. 2(3)
Fir nr. 2(2)
Fir nr. 2(1)
Creez firul nr. 3
Fir nr. 3(5)
Fir nr. 3(4)
Fir nr. 3(3)
Fir nr. 3(2)
Fir nr. 3(1)
Firele de executie s -au pornit.
Daca nu s -ar fi folosit metoda join() pe ntru a permite mai intai terminarea executiei fiecarui fir lansat
din firul principal si apoi continuarea executiei acestuia atunci rezultatul afisat la consola ar fi fost
urmatorul:

Se pornesc firele de executie
Creez firul nr. 1
Creez firul nr. 2
Cree z firul nr. 3
Firele de executie s -au pornit.
Fir nr. 1(5)
Fir nr. 1(4)
Fir nr. 1(3)
Fir nr. 1(2)
Fir nr. 1(1)
Fir nr. 2(5)
Fir nr. 2(4)
Fir nr. 2(3)
Fir nr. 2(2)
Fir nr. 2(1)
Fir nr. 3(5)
Fir nr. 3(4)
Fir nr. 3(3)
Fir nr. 3(2)
Fir nr. 3(1)
Despre programarea concurenta
Aproape intotdeauna, executarea concurenta a mai multor fire de executie cere o anumita sincronizare
si coordonare intre ele, deci sunt necesare anumite mecanisme care sa asigure sincronizarea si
comunicarea intre fire.
Spec ificarea sincronizarii si coordonarii intre firele de executie constituie obiectul programarii
concurente .
In cele mai des folosite cazuri, programarea concurenta se aplica atunci cand avem la dispozitie un
singur procesor, care “aloca” firelor de executi e intervale de timp de lucru aleatoare. Mai general,
putem considera ca este folosit modelul aleator , care consta din repetarea ciclica, de catre un procesor
fizic, a urmatoarelor actiuni :
– alege aleator unul dintre firele de executie;

– executa, un in terval de timp aleator , instructiuni ale firului de executie respectiv.
Exemplele prezentate in lectia 10 demonstreaza cele mentionate mai sus.
Trebuie subliniat ca programarea concurenta rezerva o serie de surprize informaticianului obisnuit cu
programare a secventiala. Prezentam in continuare cateva dintre ele si modul lor de rezolvare in Java.
Sincronizarea partajarii datelor intre firele de executie.
In cazul in care doua fire de executie au acces partajat la aceeasi variabila (adica ambele o pot consu lta
sau modifica) pot aparea rezultate ciudate daca aplicatia nu se ingrijeste de sincronizarea accesului
firelor la aceea variabila.
Iata un exemplu care ilustreaza cele mentionate mai sus. Sa presupunem ca un sot si o sotie au fiecare o
agenda de cheltu ieli. Chiar daca fiecare este atent sa actualizeze propria sa agenda, daca nu se consulta
intre ei, cheltuielile lor pot depasi veniturile. Pentru a elimina problema, este necesar ca ei sa aiba o
singura agenda de cheltuieli si ambii sa aiba acces la agend a pe rand. Astfel, ei nu vor depasi suma din
cont pentru ca ambi au grija sa tina la zi agenda pe rand.
Programul urmator(TestNesincronizare.java) ilustreaza lipsa de sincronizare intre doua fire de executie
concurente. Programul lanseaza doua fire de exec utie care actualizeaza un cont bancar pe baza sumei
de bani extrase, care este generata aleator. Fiecare fir de executie actualizeaza, pentru 10 extrageri din
contul bancar, variabila sumaCont (suma de bani din contul bancar) si variabila cheltuieli (totalul sumei
de bani extrase) in metoda de clasa extrageDinCont ().
class ContNesincronizat {
private static int sumaCont = 1000;
private static int cheltuieli = 0;
public static void extrageDinCont(int vol) {
if (vol <= sumaCont)
{
System.out.println("Suma extrasa din cont: " + vol);
sumaCont -= vol;
cheltuieli += vol;
System.out.print("Suma in cont: " + sumaCont);
System.out.println(", Total cheltuieli: " + cheltuieli);
}
else
Syste m.out. println("Suma ceruta este respinsa: " + vol);
}

}
Deoarece fiecare din cele doua fire au acces concurent la metoda extrageDinCont (), ordinea actualizarii,
de catre cele doua fire de executie, a celor doua variabile mentionate in instructiunile:
sumaCont -= vol;
cheltuieli += vol;
nu poate fi prevazuta de programator (este aleatorie).
Sistemul de operare (sau masina virtuala Java) detine controlul complet asupra planificarii firelor de
executie. In consecinta, nu se stie dinainte ce fir se va execu ta la un moment dat sau cat timp va fi
executat un anumit fir de executie .
Astfel, valoarea fiecareia din variabilele sumaCont si cheltuieli poate fi modificata de un fir, inainte ca
aceasta sa fi fost modificata de celalat fir si astfel in final sa rezul te valori eronate.
Codul complet al aplicatiei Java TestNesincronizare.java, care evidentiaza problemele care pot aparea la
partajarea accesului la aceeasi variabila, este prezentat in continuare.
class ContNesincronizat {
private static int sumaCont = 10 00;
private static int cheltuieli = 0;
public static void extrageDinCont(int vol) {
if (vol <= sumaCont)
{
System.out.println("Suma extrasa din cont: " + vol);
sumaCont -= vol;
cheltuieli += vol;
System.out.print("Suma in cont: " + sumaCont);
System.out.println(", Total cheltuieli: " + cheltuieli);
}
else
System.out. println("Suma ceruta este respinsa: " + vol);
}
}
class FirExecNesincronizat extends Thread {

public voi d run() {
for(int i=0; i<10; i++)
{
ContNesincronizat.extrageDinCont((int) (Math.random() * 500));
}
}
}
public class TestNesincronizare {
public static void main(String [] args) {
new FirExecNesincronizat().start();
new FirExecNesincronizat ().start();
}
}
Dupa executia aplicatiei un posibil rezultat afisat la consola este:
Suma extrasa din cont: 110
Suma in cont: 890, Total cheltuieli: 110
Suma extrasa din cont: 138
Suma extrasa din cont: 340
Suma in cont: 550, Total cheltuieli: 450
Suma extrasa din cont: 412
Suma in cont: 138, Total cheltuieli: 862
Suma extrasa din cont: 138
Suma in cont: 0, Total cheltuieli: 1000
Suma ceruta este respinsa: 135
Suma ceruta este respinsa: 280
Suma ceruta este respinsa: 298
Suma ceruta este respinsa: 70
Sum a ceruta este respinsa: 169
Suma ceruta este respinsa: 211

Suma ceruta este respinsa: 343
Suma in cont: -138, Total cheltuieli: 1138
Suma ceruta este respinsa: 223
Suma ceruta este respinsa: 284
Suma ceruta este respinsa: 168
Suma ceruta este respinsa: 113
Suma ceruta este respinsa: 309
Suma ceruta este respinsa: 397
Suma ceruta este respinsa: 461
Suma ceruta este respinsa: 488
Se observa ca la un moment dat un fir de executie a actualizat variabila sumaCont inainte de a se face
actualizarea acestei variabi le de catre celalat fir care s -a lansat inaintea lui.
Problema pusa in evidenta poarta denumirea de inconsistenta la concurenta (“race condition”).
Vom numi sectiune critica o secventa de instructiuni a caror executare trebuie sa se supuna urmatoarei
regu li: in momentul in care un fir F incepe executarea primei instructiuni din secventa, nici un alt fir nu
poate sa execute instructiuni din aceeasi secventa inainte de terminarea executarii ultimei instructiuni
din secventa de catre firul F . In aceste condit ii spunem ca are loc o excludere reciproca (cel mult un fir se
poate afla intr -o sectiune critica).
Excluderea reciproca poate rezolva problema inconsistentei la concurenta a datelor partajate de mai
multe fire.
Pentru a realiza excluderea reciproca, se folosesc doua facilitati oferite de limbajul Java:
– sincronizarea folosind metode declarate cu modificatorul synchronized ;
– sincronizarea folosind instructiunea synchronized .
Sincronizarea folosind metode declarate cu modificatorul synchronized
Pentru a sincroniza partajarea datelor, se creaza o metoda de acces la variabilele partajate si se
foloseste modificatorul synchronized in antetul metodei respective. Java va restrictiona accesul la
metoda sincronizata pe un anumit obiect Ob, in asa fel in cat un singur fir sa poata accesa metoda la un
moment dat pe acel obiect Ob. Pentru celelalte fire accesul la metoda obiectului Ob este blocat. In
momentul in care un fir termina de executat o metoda sincronizata pe obiectul Ob, atunci unul din firele
de e xecutie blocate va fi deblocat si va incepe efectiv invocarea metodei dorite.
In Java se foloseste urmatoarea terminologie :
– obiectul Ob avand ca tip clasa C se numeste monitor ;

– monitorul este liber daca nu este in curs de executie nici o metoda sincronizata a sa; in caz
contrar, daca o metoda sincronizata a sa este in curs de executie, se spune ca monitorul este ocupat ;
– daca un fir de executie invoca, prin intermediul monitorului Ob, o metoda sin cronizata a clasei
C si monitorul este ocupat, firul va fi blocat in multimea (de fire blocate) de asteptare asociata
monitorului ;
– daca un fir este in curs de a executa , prin intermediul obiectului Ob, o metoda sincronizata a
clasei C, spunem ca el detine controlul (exclusiv) asupra monitorului ;
– cand firul termina de executat metoda sincronizata , el pierde controlul asupra monitorului ;
daca multimea asociata monitorului este nevida, se alege “la intamplare” (in functie de implementarea
concreta a plan ificarii procesorului) un fir din aceasta multime si acest fir trece la executarea metodei
sincronizate pe care a incercat mai inainte sa o invoce; acum monitorul este din nou ocupat si noul fir
este cel care detine controlul asupra monitorului.
Programul urmator (TestSincronizare.java) ilustreaza modul in care s -a rezolvat “inconsistenta la
concurenta” pentru exemplul prezentat in programul “TestNesincronizare.java” folosind o metoda de
acces la date, sincronizata (metoda extrageDinCont ).
class ContSincro nizat {
private static int sumaCont = 1000;
private static int cheltuieli = 0;
public static synchronized void extrageDinCont(int vol) {
if (vol <= sumaCont)
{
System.out.println("Suma extrasa din cont: " + vol);
sumaCont -= vol;
cheltuieli += vol;
System.out.print("Suma in cont: " + sumaCont);
System.out.println(", Total cheltuieli: " + cheltuieli);
}
else
System.out. println("Suma ceruta este respinsa: " + vol);
}
}
class FirEx ecSincronizat extends Thread {

public void run() {
for(int i=0; i<10; i++)
{
ContSincronizat.extrageDinCont((int) (Math.random() * 500)) ;
}
}
}
public class TestSincronizare {
public static void main(String [] args) {
new FirExecSincronizat().start();
new FirExecSincronizat().start();
} }
Sincronizarea folosind instructiunea synchronized
Sincronizarea cu ajutorul blocurilor synchronized este o alta tehnica folosita pentru asigurarea
consistentei la concurenta pentru mai multe fire de executie. Cu ajutorul blocurilor synchronized se
realizeaza serializarea (secventializarea) accesului la o anumita secventa de cod din cadrul unei metode,
a mai multor fire de executie.
Aceasta tehica se aplica mai ales atunci cand avem in a plicatie metode complexe, care realizeaza multe
calcule, si doar o mica portiune din ele este susceptibila de inconsistenta la concurenta. Folosind blocuri
synchronized creste viteza de executie a aplicatiei intrucat metodele sincronizate sunt mai lente.
Pe de alta parte, metodele sincronizate nu pot fi folosite in orice situatie. De exemplu, tablourile Java nu
dispun de metode, cu atat mai putin de metode sincronizate. Exista totusi multe cazuri in care se
doreste ca accesul la elementele unui tablou sa f ie sincronizat pentru doua sau mai multe fire.
Instructiunea synchronized are urmatoarea sintaxa :
synchronized (<nume_obiect>)
{
<instructiue>;

}
unde:
– <nume_obiect> – specifica o variabila referinta care este numele unui obiect sau unui tablou J ava.

Programul urmator (TestBlocSinc.java) este o varianata a programului prezentat ca exemplu de folosire
a metodelor sincronizate (TestSincronizare.java). In aceasta varianta de aplicatie, clasa ContSincronizat si
metoda sincronizata aferenta extrageDin Cont () a fost scoasa din aplicatie, iar blocul de instructiuni al
acestei metode a fost introdus in metoda run() (a clasei FireExecSinc ) sub forma unui bloc sincronizat
(folosind instructiunea synchronized )
class FirExecSinc extends Thread {
private static Integer sumaCont = new Integer(1000);
private static int cheltuieli = 0;
static {
System.out.println("Suma initiala in cont: " + sumaCont);
}
public void run() {
int vol;
for(int i=0; i<10; i++)
{
vol = (int) (Math.random() * 500);
synchronized(sumaCont)
{
if (vol <= sumaCont.intValue())
{
System.out.println("Suma extrasa din cont: " + vol);
sumaCont = new Integer(sumaCont.intValue() -vol);
cheltuieli + = vol;
System.out.print("Suma in cont: " + sumaCont.intValue());
System.out.println(", Total cheltuieli: " + cheltuieli);
}
else
System.out. println("Suma ceruta este respinsa: " + vol);
}
}}}

public class TestBlocSinc {
public static void main(String [] args) {
new FirExecSinc().start();
new FirExecSinc().start();
}
}
Dupa executia programului la consola sunt afisate urmatoarele rezultate:
Suma initiala in cont: 1000
Suma extrasa din cont: 59
Suma in cont: 941, Total cheltuieli: 59
Suma extrasa din cont: 147
Suma in cont: 794, Total cheltuieli: 206
Suma extrasa din cont: 357
Suma in cont: 437, Total cheltuieli: 563
Suma extrasa din cont: 337
Suma in cont: 100, Total cheltuieli: 900
Suma extrasa din cont: 95
Suma in cont: 5, Total cheltuieli: 995
Suma ceruta este respinsa: 75
Suma ceruta este respinsa: 116
Suma ceruta este respinsa: 464
Suma ceruta este respinsa: 491
Suma ceruta este respinsa: 11
Suma ceruta este respi nsa: 433
Suma ceruta este respinsa: 47
Suma ceruta este respinsa: 31
Suma ceruta este respinsa: 405
Suma ceruta este respinsa: 328
Suma ceruta este respinsa: 434

Suma ceruta este respinsa: 100
Suma ceruta este respinsa: 152
Suma ceruta este respinsa: 237
Suma ceruta este respinsa: 314
Coordonarea firelor de executie prin asteptare. Metodele wait() si notify()
Firele de executie din cadrul unei aplicatii Java sunt adeseori interdependente; un fir de executie poate
sa depinda de un alt fir de executie care tr ebuie sa incheie o anumita operatie sau sa satisfaca o cerere.
Exista foarte multe situatii in care este util sa coordonam doua sau mai multe fire de executie.
Cazul clasic de coordonare a doua fire de executie este problema “producator/consumator”, in c are
producatorul si consumatorul partajeaza date comune, unul producand date care sunt consumate de
celalalt.
De exempu, sa presupunem ca am ajuns in fata ferestrei unui restaurant fast -food si cerem o comanda.
Daca comanda nu este gata, trebuie sa astept am. In plus, daca au fost facute deja cinci comenzi,
vanzatorul nu poate da comanda facuta primului sosit ci trebuie sa astepte sosirea clientului care are
comanda pregatita. De asemenea, si noi trebuie sa asteptam sosirea clientului care are comanda
prega tita. In acest caz, consumatorul (adica noi) si producatorul (adica vanzatorul) se asteapta unul pe
celalalt pana la venirea clientului pentru care este pregatita comanda.
Sa presupunem ca intr -o aplicatie Java exista un fir de executie care trebuie sa cre eze (produca) date
stocate in anumite variabile si un al doilea fir care trebuie sa le prelucreze (consume) . Firele trebuie sa
utilizeze o regula similara cu cea descrisa mai sus. Firul consumator asteapta (wait) producerea unui
eveniment (crearea de date) iar firul producator notifica (notify) producerea acelui eveniment.
Cuvintele wait si notify sunt folosite in Java ca nume de metode care se apeleaza pentru a coordona
firele de executie. Acestea sunt metode publice ale clasei radacina Object .
Metodele d e coordonare a firelor de executie
Metodele folosite au urmatoarele forme:
final void wait ()
final void wait (long <t>)
final void notify ()
final void notifyAll ()
unde : <t> – timpul de asteptare exprimat in milisecunde.
Toate aceste metode trebuie sa fie apelate din interiorul unei metode sincronizate sau a unui bloc
sincronizat.

Firele de executie sunt de obicei coordonate folosind conceptul de conditie sau variabila conditionala . O
conditie reprezinta o stare sau un eveniment fara de care firul n u poate continua executia. In Java, acest
model este exprimat in general sub forma:
while(! <conditia_de_continuare_executie>)
{
wait();
}
Efectul folosirii acestui model de coordonare este urmatorul:
– La inceput, se verifica daca variabila conditi onala este adevarata. Daca da, nu este necesar sa se
astepte. In cazul in care conditia nu este inca adevarata, se apeleaza metoda wait() .
– Cand asteptarea ( wait() ) se incheie (fie pentru ca firul a fost notificat cu metoda notify() sau
notifyAll() de catr e un alt fir, fie pentru ca a expirat timpul de asteptare precizat in parametrul
<t>) se verifica din nou conditia pentru a ne asigura ca a devenit adevarata. Trebuie precizat ca,
daca suntem siguri ca variabila conditionala a devenit adevarata, putem inlo cui ciclul while cu un
simplu if.
Apelul metodei wait() pe un obiect opreste temporar (suspenda) firul de executie curent pana cand un
alt fir apeleaza metoda notify () pe acelasi obiect. Metoda notify () informeaza firul, care asteapta, ca s -a
produs un ev eniment care ar putea schimba conditia de asteptare.
Metoda wait () are si o varianta cu un parametru, interpretat ca perioada de expirare a asteptarii
(timeout) masurata in milisecunde. Aceasta varianata este folosita cand nu dorim sa asteptam la infinit
producerea unui anumit eveniment.
Metoda notifyAll () difera de notify () prin aceea ca “trezeste” toate eventualele fire din multimea de
asteptare asociata monitorului (obiectului) care a invocat metoda notifyAll ().
Metodele wait (), notify () si notifyAll () pot fi apelate doar daca firul de executie curent detine controlul
asupra monitorului (obiectului) prin care sunt apelate.
Pentru a nu se crea confuzie, trebuie de precizat ca metoda wait () elibereaza temporar monitorul dupa
ce a fost apelata si obtine din nou controlul asupra monitorului inainte de a se incheia apelul ei. Astfel,
metoda wait () permite si altor fire de executie sa detina controlul asupra aceluiasi monitor si sa apeleze
metoda notify () sau notifyAll ().
Toate metodele de coordonar e a firelor de executie genereaza exceptia IllegalMonitorStateException ,
daca firul curent nu detine controlul asupra monitorului reprezentat de obiectul curent.
De asemenea, toate metodele de coordonare genereaza exceptia InterruptedException . Aceasta
exceptie se genereaza atunci cand se apeleaza metoda interrupt() a clasei Thread .

Limbajul Java ofera posibilitatea de a intrerupe asteptarea de orice natura ( wait , sleep , join) a unui fir de
executie prin generarea unei exceptii de tipul InterruptedExcept ion intr-un alt fir de executie, folosind
metoda interrupt() . Aceasta metoda este utilizata pentru “a trezi” firele de executie aflate in asteptare
in cadrul metodelor wait() , sleep() etc.
Urmatorul exemplu ( TestWaitNotify .java) prezinta un fir producato r si un fir consumator utilizand
metodele wait () si notify (). Aplicatia simuleaza o unitate in care se produce o cantitate de marfa care
apoi este cumparata de catre un consumator.
Daca cantitatea de marfa exista in unitate este diferita de zero, atunci p roducatorul asteapta
cumpararea ei de catre un consumator. Daca nu exista, atunci producatorul fabrica o anumita cantitate
de marfa.
Pe de alta parte, daca cantitatea de marfa ceruta nu exista in unitate (este egala cu zero) atunci
consumatorul asteapta c a ea sa fie produsa. Daca exista, atunci ea este cumparata de consumator.
Pentru rezolvarea acestei probleme in aplicatia TestWaitNotify.java s -au definit doua clase:
– clasa ConsumatorProducator – clasa centrala care ofera doua metode consuma () si produce ()
pentru a consuma marfa produsa (simulata prin atribuirea valorii variabilei marfa pentru variabila temp
si a valorii 0 pentru variabila marfa ) si respectiv pentru a produce marfa (simulata prin atribuirea valorii
variabilei cantitate pentru variabila marfa ); in cadrul acestor doua metode s -au folosit metodele wait ()
cu o conditie de asteptare si notify ();
– clasa FirConsProd – clasa care implementeaza cele doua fire de executie Consumator si
respectiv Producator in functie de parametrii oferiti constructorului clasei.
public class TestWaitNotify {
public static void main(String [] args) {
ConsumatorProducator unConsProd = new ConsumatorProducator();
new FirConsProd(unConsProd, "Consumator"). start();
System.out.println("Firul Consumator lansat");
new FirConsProd(unConsProd, "Producator").start();
System.out.println("Firul Producator lansat");
} }
class ConsumatorProducator {
private int marfa = 0;
public syn chronized void consuma() {
int temp;
while(marfa == 0)

{
System.out.println("Consumator in asteptare");
try {
wait();
}
catch(InterruptedException ie) {}
}
temp = marfa;
marfa = 0;
System.out.println("Marfa consumata " + temp);
notify();
}
public synchronized void produc e(int cantitate) {
while(marfa !=0)
{
System.out.println("Producator in asteptare");
try {
wait();
}
catch (InterruptedException ie) {}
}
marfa = cantitate;
notify();
System.out.println("Marfa produsa " + marfa);
}
}
class FirConsProd exten ds Thread {
private boolean producator = false;
private ConsumatorProducator consProd;

public FirConsProd(ConsumatorProducator cp, String tip ) {
consProd = cp;
if(tip.equals("Producator"))
producator = true;
}
public void run() {
for(int i = 0; i < 10; i++)
{
if(producator)
consProd.produc e((int)(Math.random() * 10) + 1);
else
consProd.consuma();
}
} }
Dupa executia programului un posibil rezultat afisat la consola este:
Firul Consumator lansat
Consumator in asteptare
Firul Producator lansat
Marfa produsa 8
Producator in asteptare
Marfa consumata 8
Consumator in asteptare
Marfa produsa 10
Producator in asteptare
Marfa consumata 10
Marfa produsa 10
Producator in asteptare
Marfa consumata 10
Consumator in asteptare

Marfa produsa 7
Producator in asteptare
Marfa consumata 7
Consumator in asteptare
Marfa produsa 8
Producator in asteptare
Marfa consumata 8
Consumator in asteptare
Marfa produsa 4
Producator in asteptare
Marfa consumata 4
Consumator in asteptare
Marfa produsa 7
Producator in asteptare
Marfa consumata 7
Consumator in asteptare
Marfa produsa 9
Marfa consumata 9
Marfa produsa 4
Marfa consumata 4
Marfa produsa 3
Marfa consumata 3
Starea de blocare circulara (deadlock)
Blocarea circulara, numita uneori si “imbratisare mortala” este unul dintre evenimentele cele mai grave
care pot sa apara intr -un mediu multi -fir. De aceea programatorii trebuie sa fie aten ti pentru a -l evita.
O blocare circulara este o situatie in care doua sau mai multe fire de executie sunt blocate in asteptarea
unei resurse comune si nu pot continua executia. In aceasta situatie doua sau mai multe fire de executie
asteapta indeplinirea unei conditii iar aceasta nu este niciodata satisfacuta.

Pentru a preveni starea de blocare circulara este indicat sa serializam (sa secventializam sau sa
sincronizam) nu numai resursele, dar si procesul de procurare a acestor resurse. Aceasta va impiedica
asteptarea de catre mai multe fire a unei resurse comune.
Verificarea starii unui fir de executie
La inceputul acestei lectii au fost descrise cele patru stari ale unui fir de executie.
Pentru a verifica starea unui fir in cadrul aplicatiei Java, se utilizeaza metoda isAlive () a clasei Thread .
Daca firul este in starea “fir in executie” ( runnable ) sau “fir intrerupt” ( not runnable ), metoda isAlive ()
returneaza valoarea true, iar daca firu l este in starea “fir nou creat” ( new ) sau “fir mort” ( dead ), metoda
isAlive () returneaza valoarea false .
Urmatorul program (TestStareFir.java) ilustreaza modul de folosire a metodei isAlive():
class UnFirDeTest extends Thread{
public void run() {
System.out.println("Intru in metoda run()");
for (int i = 0; i < 10; i++)
{
System.out.println("Ma pregatesc sa dorm");
try {
sleep(500);
}
catch (InterruptedException ie) { }
}
}
}
public class TestStareFir {
public static void main(String [] args) {
UnFirDeTest fir = new UnFirDeTest();
System.out.println("Starea firului este: " + fir.isAlive() + " adica new");
fir.start();
System.out.println("Firul este lansat in executie");
System.out.println("Starea firului este: " + fir.isAlive() + " adica runnable");

}
}
Dupa executia programului un posibil rezultat afisat la consola este:
Starea firului este: false a dica new
Intru in metoda run()
Ma pregatesc sa dorm
Firul este lansat in executie
Starea firului este: true adica runnable
Ma pregatesc sa dorm
Ma pregatesc sa dorm
Ma pregatesc sa dorm
Ma pregatesc sa dorm
Ma pregatesc sa dorm
Ma pregatesc sa dorm
Ma pregatesc sa dorm
Ma pregatesc sa dorm
Ma pregatesc sa dorm

Curs 12
Cuvinte importante:
-pachete Java folosite pentru crearea unei interfete grafice utilizator: AWT, Swing;
-folosirea mediului de dezvoltare IDE – NetBeans pentru proiectarea interfetei utilizator:
instrumente NetBeans, crearea ferestrei aplicatiei; moduri de pozitionare a componentelor grafice in
fereastra aplicatiei; componente grafice AWT si Swing;
– tratarea evenimentelor: tipuri de evenimente; clase Java specifice tipurilor de even imente;
tipuri de interceptori de evenimente (listener); inregistrarea unui obiect a clasei interceptoare ca
administrator al unui eveniment; folosirea claselor abstracte <tip_eveniment>Adapter si a claselor
anonime pentru tratarea evenimentelor; utilizare a IDE – NetBeans pentru tratarea evenimentelor .

Pachete Java folosite pentru crearea unei interfete grafice utilizator
Interfata grafica a unei aplicatii Java (GUI) este folosita pentru a permite , intr -o forma “prietenosa”,
interactiunea dintre utilizator si obiectele grafice de pe ecran . Un obiect grafic “asteapta” sa fie
executata o actiune asupra sa (clic de mouse, apasarea unei taste etc), pentru “a raspunde” cu
executarea unui anumit cod. De fapt, se asteapta declansarea unui eveniment (clic de mouse pe obiect,
apasarea unei taste intr -o cutie de text etc) pentru ca aplicatia “sa raspunda” intr -un mod prevazut de
programator.
Limbajul Java pune la dispozitia programatorilor o mare varietate de facilitati de elaborare si prelucrare
a interfetelor grafi ce utilizator.
In prezent, Java ofera doua tehnologii de creare a unei interfete grafice utilizator:
– AWT (Abstract Windowing Toolkit) – este API -ul initial pus la dispozitie incepand cu primele
versiuni de Java; toate componentele AWT fac parte din pachetul java.awt ;
– Swing – este parte a proiectului JFC (Java Foundation Classes) (creat in urma colaborarii dintre
Sun Netscape si IBM); Swing foloseste aceeasi infrastructura de clase ca si AWT extinzand
functionalitatea acestuia; pachetul “swing” a fost integrat incepand cu ve rsiunea 2 a Java; toate
componentele Swing fac parte din pachetul javax.swing .
Nota : Este de preferat ca interfetele -utilizator Java sa fie create folosind tehnologia Swing , deoarece,
aceasta include mai multe facilitati; i nsa nu se poate renunta complet l a tehnologia AWT deoarece aici
exista clase esentiale, folosite si in tehnologia Swing.
Crearea unei aplicatii Java cu interfata grafic a se desfasoara in doua etape :
A. Realizarea design -ului interfetei grafice, care inseamna:
– crearea unei suprafete de afisare (cum ar fi o fereastra) pe care vor fi asezate obiectele grafice
(componente le) care servesc la comunicarea cu utilizatorul (butoane, casete pentru editarea textelor,
liste, etc);
– crearea si asezarea componentelor pe suprafata de afisare la pozitiile corespunzatoare .
B. Realizarea functionalitatii interfetei grafice, care inseamna:
– definirea unor metode de tratare a diferitelor tipuri de evenimente, metode care sunt apelate
cand utilizatorul interactioneaza cu obiectele grafice (componente le) ale interfetei;
– ”ascultarea” (interceptarea sau listener) diferitelor tipuri de evenimente, generate in
momentul interactiunii obiectelor grafice cu utilizatorul , si executarea actiunilor corespunzatoare, asa
cum au fost ele definite in metodele de tratare.
Realizarea design -ului interfetei utilizator. Folosirea mediului de dezvoltare IDE – NetBeans pentru
proiectarea interfetei utilizator
IDE-NetBeans este un mediu de dezvoltare pentru aplicatii informatice Java.

IDE-NetBeans este format dintr -o suita de instrumente care sprijina programatorul in realizarea unei
aplicatii informatice Java.
Instrumentele principale ale mediului de dezvoltare NetBeans , folosite pentru proiectarea interfetei
utilizator sunt urmatoarele:
– Proiectorul interfetei grafice (fereastra Design) reprezinta zona principala de lucru, in care se
proiecteaza ferestrele de interfata -utilizator si obiectele grafice (componente AWT si Swing, meniuri)
care sunt plasate in aceste ferestre.
– Fereastra de instrumente grafice (fereastra Palette) contine reprezantari grafice ale
componentelor AWT si Swing.
– Fereastra de proprietati (fereastra Properties) contine trei categorii de informatii despre o
componenta grafica, selectata la un moment dat, categorii evidentiate prin trei etichete pozitionate in
antetul ferestrei:
a) eticheta “Properties” – descrie caracteristici referitoare la aspectul componentei (culoare,
dimensiune, texte afisate pe componenta respectiva, culoare etc);
b) eticheta “Events” – descrie metodel e pentru tratarea evenimentelor a caror sursa este
componenta selectata;
c) eticheta “Code” – se foloseste pentru a insera cod propriu in metoda initComponent()
generata automat de NetBeans sau in orice alta parte a programului unde NetBeans genereaza aut omat
cod; de asemenea se foloseste si pentru a modifica secvente de cod generate automat cu NetBeans
pentru componenta selectata;
– Fereastra de cod (fereastra Source) contine codul Java al aplicatiei informatice; in aceasta
fereastra sunt zone de cod car e sunt generate automat de NetBeans (si ele nu pot fi modificate decat cu
ajutorul ferestrei Properties) si sunt zone de cod in care programatorul poate insera, modifica sau sterge
instructiunii proprii;
– Fereastra de navigare printre componentele grafic e ale interfetei (fereastra Inspector) permite
vizualizarea tuturor componentelor grafice ale interfetei utilizator; de asemenea permite si selectia
componentei respective in fereastra Design; in aceasta fereastra sunt afisate si componentele non –
vizuale;
– Fereastra de navigare in structura proiectului permite vizualizarea tuturor pachetelor,
fisierelor, bibliotecilor etc ce formeaza aplicatia, intr -o structura arborescenta. Navigarea prin aceasta
structura se realizeaza la fel ca in Windows Explorer, iar deschiderea fisierelor are loc prin dublu -clic pe
numele lor. Aceasta fereastra permite gestionarea rapida a componentelor aplicatiei (modificare,
adaugare sau stergere).
Crearea ferestrei de lansare a aplicatiei informatice
Pentru crearea ferestrei de lansare a aplicatiei informatice se procedeaza astfel:
1. Se creaza un proiect, prin metoda cunoscuta deja;
2. Se alege optiune New din meniul File si pe ecran apare fereastra “New File”.

In aceasta fereastra se extinde (cu clic pe semnul “+”) elementul “ Java GUI Forms” din caseta
“Categories”, si se alege elementul “AWT Forms” daca se doreste proiectarea unei interfete utilizator
folosind tehnologia AWT (crearea unei ferestre de tip Frame).
Daca se doreste proiectarea unei interfete utilizator folosind t ehnologia Swing (crearea unei ferestre de
tip JFrame) nu este necesar sa se extinda elementul “AWT Forms”.
Apoi, in caseta “File Types” se alege elementul “Frame Form” pentru fereastra AWT sau “JFrame Form”
pentru fereastra Swing.
3. Stabilirea numelui fer estrei de tip Frame in varianta AWT sau JFrame in varianta Swing si a locului
acesteia in cadrul proiectului.
De fapt, NetBeans creaza un nou fisier cu extensia .java care contine codul initial pentru o clasa, cu
numele precizat in caseta “Class Name”, c are extinde clasa Frame (ATW) sau JFrame (Swing).

Pasul 2 – alegerea tipului de fereastra AWT sau Swing pentru interfata -utilizator

Pasul 3 – stabilirea numelui ferestre de tip Frame sau JFrame si a locului acesteia in cadrul proiectului

Pasul 3 – stabilirea numelui ferestre de tip Frame sau JFrame si a locului acesteia in cadrul proiectului
Dupa terminarea procedurii de creare a ferestrei aplicatiei ecranul de lucru arata ca in figura de mai jos:

Dupa crearea ferestrei aplicatiei informatice mediul NetBeans ne permite sa lucram in doua moduri:
– modul de lucru “Source” – folosit pentru a edita (inserare de, modificare de, stergere de) cod;
– modul de lucru “Design” – folosit pentru a insera, modifica sau sterge componente grafice
elementare, in fereastra aplicatiei, precum si pentru a modifica proprietati sau a trata evenimente
specifice fiecarei componente a ferestrei.
Vom detalia cateva aspecte legate de modul de lucru “Design”
Stabilirea modului de pozitionare a componentelor grafice pe s uprafata de afisare (fereastra
aplicatiei) folosind modul de lucru “Design”
Mediul NetBeans permite mai multe moduri de pozitionare si adaugare a componentelor grafice in
fereastra aplicatiei. Dupa crearea ferestrei aplicatiei mediul NetBeans stabileste sc hita de asezare si
adaugare, care este tipul BorderLayout putin utilizat. Descrierea acestei schite se va face in cursul
urmator.
Pentru modificarea schitei de asezare a componentelor grafice in fereastra aplicatiei se procedeaza
astfel:
– se intra in fereastra Inspector si se alege componenta “Frame” sau “JFrame”
– se executa clic cu butonul drept al mouse -ului si din meniul contextual, care apare, se alege
optiunea Set Layout apoi, se alege tipul de schita dorit, cum ar fi: Free Design, A bsoluteLayout,
BoxLayout, CardLayout, FlowLayout, GridLayout, GridBagLayout, NullLayout. Este de preferat sa
se aleaga Free Design care este cel mai usor de folosit si permite programatorului sa aseze
componentele in mod liber cum doreste el.
Folosirea com ponentelor grafice din fereastra Palette a mediului NetBeans

In folosirea componentelor grafice din fereastra Palette trebuie sa se aiba in vedere tehnologia folosita
pentru crearea ferestrei aplicatiei. Daca fereastra aplicatiei a fost creata cu AWT, atu nci se vor adauga in
aceasta numai componente AWT iar daca fereastra aplicatiei a fost creata cu Swing, atunci se vor
adauga numai componente Swing.
Swing foloseste aceeasi infrastructura de clase ca si AWT, ceea ce permite folosirea combinata a
componente lor Swing si AWT in aceeasi interfata utilizator. Totusi, in unele cazuri este posibil ca aceste
doua tipuri de componente sa nu fie reprezentate corect in cadrul containerului. Pentru evitarea
problemelor, cel mai bine este sa folosim exclusiv un singur s istem de componente grafice.
Componentele AWT din fereastra Palette sunt reprezentate in figura de mai jos:

Componentele Swing din fereastra Palette sunt reprezentate in figura de mai jos:

Realizarea functionalitatii interfetei grafice. Tratarea evenimentelor
Cand se lucreaza cu o interfata grafica, o actiune a utilizatorului asupra unei componente grafice
declanseaza (genereaza) un eveniment .
Exemple de evenimente sunt: apasarea unui buton, modificarea textului intr -un control de editare,
inch iderea sau redimensionarea unei ferestre, etc.
In Java, un eveniment este un obiect (instanata) al unei clase cu un nume de forma:
<tip>Event , in care <tip> reprezinta tipul evenimentului.
In Java, o componenta care genereaza un eveniment se mai numeste si sursa evenimentului (event
source).
In Java, interceptarea unui eveniment generat de o componenta a interfetei grafice se realizeaza prin
intermediul unui obiect (interceptor sau care trateaza evenimentul) al unei clase interceptoare (l istener)
care implementeaza o interfata cu un nume de forma <tip_eveniment>Listener sau extinde o clasa
abstracta cu un nume de forma <tip_eveniment>Adapter .

Realizarea functionalitatii interfetei grafice. Tratarea evenimentelor
Cand se lucreaza cu o in terfata grafica, o actiune a utilizatorului asupra unei componente grafice
declanseaza (genereaza) un eveniment .
Exemple de evenimente sunt: apasarea unui buton, modificarea textului intr -un control de editare,
inchiderea sau redimensionarea unei ferestre , etc.
In Java, un eveniment este un obiect (instanata) al unei clase cu un nume de forma:
<tip>Event , in care <tip> reprezinta tipul evenimentului.
In Java, o componenta care genereaza un eveniment se mai numeste si sursa evenimentului (event
source).
In Java, interceptarea unui eveniment generat de o componenta a interfetei grafice se realizeaza prin
intermediul unui obiect (interceptor sau care trateaza evenimentul) al unei clase interceptoare (listener)
care implementeaza o interfata cu un nume de fo rma <tip_eveniment>Listener sau extinde o clasa
abstracta cu un nume de forma <tip_eveniment>Adapter .

Tipuri de evenimente
Un eveniment este un obiect (instanta) al unei clase <tip>Event din urmatoarea ierarhie de clase Java:

Principalele tipuri de evenimente definite cu ajutorul claselor <tip>Event sunt descrise in urmatorul
tabel:
Clase Java specifice tipurilor de evenimente
Utilizator
(actiune)
Component
a
(genereaza
Interceptor de tip
Listener
(intercepteaza si
trateaza un
Object
EventObject (din pachetul java.util )
AWTEvent (din pachetul java.awt )
<tip>Event (din
pachetul
java.awt.event )
<tip>Event (din
pachetul
java.awt.event )

Clase specifice tipurilor
de evenimente Tipurile de evenimente apar in situatii ca:
ActionEvent Actiuni asupra unei componente elementare (buton, etc)
AdjustmentEvent Actiuni asupra unei componente de tip Scrollbar
ConponentEvent Deplasari, redimensionari, ascunderi (componenta devine invizibila)
ContainerEvent Adaugare, stergere de componente pe container
FocusEvent Obtinerea/pierderea controlului asupra tastaturii
ItemEvent Selectia sau deselectia de componente (liste, casute de optiuni etc)
KeyEvent Apasarea sau eliberarea unei taste
MouseEvent Actiuni de mouse: clic, apasare, eliberare, iesire/intrare in
componenta
MouseMotionEvent Miscare mouse, tarare (drag) mouse
TextEvent Modificarea textului din componenta
WindowEvent Inchidere sau minimizare/maximizare ferestre
Tipuri de interceptori de evenimente (listener)
O clasa interceptoare de evenimente (listener) poate fi orice clasa care specifica in declaratia sa ca
doreste sa intercepteze (sa trateze) evenimente de un anumit tip.
Pentru a deveni o clasa interceptoare a unui eveniment de un anumit tip, cl asa respectiva trebuie sa
implementeze (cuvantul -cheie implements ) o interfata specifica pentru tratarea tipului de eveniment
(interfata care este un tip de interceptor) si care are un nume de forma <tip_eveniment>Listener .
De exemplu, pentru interceptare a evenimentelor de tip MouseEvent , clasa respectiva trebuie sa
implementeze interfata MouseListener etc.
Interfetele <tip_eveniment>Listener se gasesc in pachetul java.awt.Event si sunt derivate din
superinterfata EventListener care face parte din pachetu l java.util .
Fiecare interfata <tip_eveniment>Listener declara una sau mai multe metode care vor trebui sa fie
implementate in clasa interceptoare si care vor fi apelate automat la aparitia unui eveniment.
De exemplu:

class TrateazaButoane implements Mo useListener {
public void mouseClincked(MouseEvent me) {
// Metoda interfetei MouseListener

}}
class TrateazaCaseteText implements TextListener {
public void textValueChanged(TextEvent te) {
// Metoda interfetei TextListener

}
}
Metodele din interfetele <tip_eveniment>Listener sunt declarate sub forma:
public void nume_metoda (<tip>Event e)
unde:
– nume_metoda – corespunde unui “subeveniment” al evenimentului identificat prin <tip>.
– De exemplu, un eveniment de tipul MouseEvent , car e corespunde generic actionarii cu
butoanele mouse -ului asupra unei componente, are ca “subevenimente” : clicul (apasarea si
eliberarea), apasarea si eliberarea unui buton al mouse -ului, precum si intrarea si iesirea din
componenta. Pentru fiecare “subeven iment” este prevazuta o metoda in interfata
MouseListener , de forma:
– void mouseClincked (MouseEvent e)
– void mousePressed (MouseEvent e)
– void mouseReleased (MouseEvent e)
– void mouseEntered (MouseEvent e)
– void mouseExited (MouseEvent e)
– Intrucat o clasa poate im plementa oricate interfete, ea va putea sa intercepteze (sa trateze)
evenimente de mai multe tipuri:
– class Interceptor implements MouseListener, TextListener {
– public void mouseClincked(MouseEvent me) {

– //Metoda interfetei MouseListener
– …
– }
– public void textValueChanged(TextEvent te) {
– //Metoda interfetei TextListener
– …
– }}
Urmatorul tabel prezinta principalele tipuri de interceptori (interfetele specifice tratarii tipului de
eveniment) si sursele evenimentelor (clasele din pachetul java.awt care definesc componente AWT Java
adica componentele vizuale):
Tip de interceptor asociat
unui tip de eveniment Sursa evenimentelor (clase care definesc componente AWT)
ActionListener List (caseta cu lista), Button (buton de comanda), TextField
(camp de text), MenuItem (optiuni de meniu)
AdjustmentListener Scrollbar (bara de defilare)
ComponentListener Component (orice componenta a interfetei grafice)
ContainerListener Container (o componenta care contine alte componente)
FocusListener Component
ItemListener Checkbox (caseta de validare), List, Choice (caseta
combinata), CheckboxMenuItem(caseta de validare a unei
optiuni de meniu)
KeyListener Component
MouseListener si
MouseMotionListener Component
TextListener TextField, TextArea (arie de text)
WindowListener Window

Orice instanta a unei clase care intercepteaza (trateaza) un eveniment de un anumit tip trebuie sa
implementeze obligatoriu toate metodele interfetei corespunzatoare <tip_eveniment>Listener.
Tabelul de mai jos prezinta, pentru fiecare interfata <tip_eveniment>Listener , metodele puse la
dispozitie si care trebuie implementate de clasa interceptoare de evenimente.
Interfata implementata de clasa interceptoare
(care trateaza tipul de eveniment) Metodele interfetei
ActionListener actionPerformed(ActionEvent e)
AdjustmentListener adjustmentValueChanged(AdjustmentEvent e)
ComponentListener componentHidden(ComponentEvent e)
componentMoved(ComponentEvent e)
componentResized(ComponentEvent e)
componentShown(ComponentEvent e)
ContainerListener componentAdded(ContainerEvent e)
componentRemoved(ContainerEvent e)
FocusListener focusGained(FocusEvent e)
focusLost(FocusEvent e)
ItemListener itemStateChanged(ItemEvent e)

Interfata implementata de clasa
interceptoare (care trateaza tipul de
eveniment) Metodele interfetei
KeyListener keyPressed(KeyEvent e )
keyReleased(KeyEvent e)
keyTyped(KeyEvent e)

MouseListener mouseClicked(MouseEvent e)
mouseEntered(MouseEvent e)
mouseExited(MouseEvent e)
mousePressed(MouseEvent e)
mouseReleased(MouseEvent e)
MouseMotionListener mouseDragged(MouseEvent e)
mouseMoved(MouseEvent e)
TextListener textValueChanged(TextEvent e)
WindowListener windowActivated(WindowEvent e)
windowClosed(WindowEvent e)
windowClosing(WindowEvent e)
windowDeactivated(WindowEvent e)
windowDeiconified(WindowEvent e)
windowIconified(WindowEvent e)
windowOpened(WindowEvent e)

Inregistrarea unui obiect a clasei interceptoare ca administrator al unui eveniment
Pentru ca evenimentele unei componente Java sa fie interceptate (tratate) de catre o instanta a unei
clase interceptoare de evenimente, acesta instanta trebuie inregistrat a ca administrator al interceptarii
(tratarii) evenimentelor asociate componentei respective.
Inregistrarea unei instante a clasei interceptoare de evenimente ca administrator al interceptarii
(tratarii) evenimentelor unei componente Java se face prin inv ocarea metodelor din clasa Component de
tipul add<tip_eveniment>Listener() . Forma generala pentru aceste metode este:
public void add<tip_eveniment>Listener (<tip_eveniment>Listener <a>)
unde:
– <tip_eveniment>Listener – specifica tipul de interceptor (inter fata specifica tratarii tipului de
eveniment);

– <a> – specifica o instanta a unei clase interceptoare care implementeaza interfata
<tip_eveniment>Listener ; aceasta instanta este considerata administratorul tratarii
evenimentelor unei componente.
– De exemplu :
– cmdBtn. addMouseListener (new TrateazaButoane());
– Stabileste ca obiectul creat newTrateazaButoane() este inregistrat ca administrator al tratarii
evenimentelor de mouse ale butonului de comanda cmdBtn .
– Cu alte cuvinte, metodele de tipul add<tip_eveniment >Listener() asociaza sursa evenimenului
(componenta Java) cu administratorul evenimentului (instanta care trateaza evenimentul)
– Un administrator de evenimente poate fi asociat mai multor tipuri de evenimente, deoarece
clasa interceptoare din care provine a dministratorul poate implementa mai multe interfete
<tip_eveniment>Listener . Putem da exemplul obiectului de tip Frame, care poate implementa
oricate interfete <tip_eveniment>Listener, deoarece acesta poate trata diverse tipuri de
evenimente care se produc asupra componentelor elementare (butoane, casete de text etc)
asezate in fereastra.
– De asemenea, unei componente Java ii putem asocia mai multi administratori de evenimente.
– Mai mentionam ca pentru fiecare metoda add<tip_eveniment>Listener() exista si o m etoda de
tip remove<tip_eveniment>Listener() , prin care un administrator de evenimente inceteaza de a
mai fi asociat unei componente.
– In concluzie, tratarea evenimentelor in Java se desfasoara astfel:
– 1. Componentele Java genereaza evenimente cand ceva ”interesant” se intampla;
– 2. Sursele evenimentelor (componentele Java) permit oricarei clase sa ”intercepteze”
evenimentele sale prin metode de tip add<tip_eveniment>Listener() ;
– 3. O clasa care “intercepteaza” evenimente trebuie sa implementeze interfete specifice fiecarui
tip de eveniment – acestea descriu metode ce vor fi apelate automat la aparitia evenimentelor.
– Asadar, pentru a scrie cod care sa se execute in momentul in care utilizatorul interactioneaza cu
o componenta grafica trebuie sa parcurgem urmatorii pasi:
– 1. sa definim o clasa care sa implementeze interfete specifice <tip_eveniment>Listener si care sa
”intercepteze” evenimentele produse de acea componenta; in cadrul acestei clase trebuie sa
implementam (sa scriem) metodele specifice pentru tratarea evenimentelor;

– 2. sa cream o instanta a clasei definite la pasul 1 si sa comunicam componentei -sursa ca
respectiva instanta ii intercepteaza (trateaza) evenimentele pe care le genereaza, cu alte
cuvinte, sa inregistram acea instanta drept adminis trator al evenimentelor produse de
componenta respectiva (folosind metode de tip add<tip_eveniment>Listener() ).
– Folosirea claselor abstracte <tip_eveniment>Adapter si a claselor anonime pentru tratarea
evenimentelor
– Stim deja ca, o clasa care trateaza ev enimente de un anumit tip trebuie sa implementeze
interfata corespunzatoare acelui tip. Aceasta inseamna ca trebuie sa implementeze obligatoriu
toate metodele definite de acea interfata, chiar daca nu specifica nici un cod pentru unele dintre
ele. Sunt ins a situatii cand acest lucru poate deveni neplacut, mai ales atunci cand nu ne
intereseaza decat o singura metoda a interfetei pentru ca dorim sa tratam un singur
“subeveniment”.
– Un exemplu, in acest sens, este urmatorul: o fereastra (de tip Frame ) care nu are specificat cod
pentru tratarea “subevenimentului” sau de inchidere nu poate fi inchisa cu butonul marcat cu ’x’
din coltul dreapta sus si nici cu combinatia de taste Alt+F4. Pentru a realiza acest lucru trebuie
interceptat (tratat) evenimentul de inch idere a ferestrei in metoda windowClosing() si apelata
metoda de inchidere System.exit() pentru terminarea programului, in cazul cand ne referim la
fereastra principala a aplicatiei. Aceasta inseamna ca trebuie sa implementam interfata
WindowListener care are nu mai putin de sapte metode.
– Pentru a evita scrierea inutila a acestor metode, exista o serie de clase care implementeaza
interfetele <tip_eveniment>Listener fara a specifica nici un cod pentru metodele lor. Aceste
clase au un nume de forma: <tip_ev eniment>Adapter.
– Clasele <tip_eveniment>Adapter sunt clase abstracte care implementeaza fiecare o anumita
interfata <tip_eveniment>Listener fara a specifica cod la nici o metoda a interfetei.
– Scopul unei astfel de clase este ca la crearea unui intercepto r de evenimente, in loc sa
implementam o anumita interfata, si implicit toate metodele sale, sa extindem clasa
<tip_eveniment>Adapter corespunzatoare interfetei respective (daca aceasta clasa exista) si sa
suprascriem doar metodele care ne intereseaza (cel e in care vrem sa scriem o anumita secventa
de cod).
– De exemplu, adaptorul interfetei WindowListener este clasa abstracta WindowAdapter. Definim
o clasa interceptoare care extinde clasa WindowAdapter si suprascriem in ea metoda
windowClosing() .
– Avantajul acestei modalitati de tratare a evenimentelor este reducerea codului programului,
acesta devenind mult mai lizibil.

– Dezavantajul major al acestei modalitati este ca, daca se doreste interceptarea mai multor tipuri
de evenimente, atunci trebuie definite cl ase interceptoare care sa extinda clase
<tip_eveniment>Adapter pentru fiecare tip de eveniment. Acest fapt se datoreaza restrictiei de
mostenire a claselor, care spune ca o clasa nu poate extinde decat o singura clasa. Vom vedea
insa ca acest dezavantaj po ate fi eliminat prin folosirea unei clase anonime.
– In tabelul de mai jos sunt date toate clasele <tip_eveniment>Adapter (adaptori) asociate
interfetelor <tip_eveniment>Listener .
– Se oberva ca o interfata <tip_eveniment>Listener are un adaptor de tipul
<tip_eveniment>Adapter . Interfetele care nu au un adaptor sunt cele care definesc o singura
metoda si prin urmare crearea unei clase adaptor nu isi are rostul.
Interfata <tip_eveniment>Listener Adaptorul <tip_eveniment>Adapter
ActionListener Nu are
AdjustmentListener Nu are
ComponentListener ComponentAdapter
ContainerListener ContainerAdapter
FocusListener FocusAdapter
ItemListener Nu are
KeyListener KeyAdapter
MouseListener si MouseMotionListener MouseAdapter si MouseMotionAdapter
TextListener Nu are
WindowListener WindowAdapter

Folosirea claselor interne anonime pentru tratarea evenimentelor
O clasa interna este o clasa definita in interiorul altei clase.
O clasa anonima este o clasa interna fara nume folosita pentru crearea unui singur obiect de un anumit
tip.

Clasele anonime sunt preferate de programatori atunci cand se doreste sa se defineasca clase simple,
derivate din clasa Thread , din clase de tip Adapter , din interfete de tip Listener, care au o singura
metoda sau derivate din alte clase avand o singura metoda. Codul clasei anonime apare exact in locul in
care este folosit, usurand astfel intelegerea programului.
De exemplu, urmatoarea secventa de cod creaza o instanta a unei clase fara nume care extinde clasa
WindowAdaper si pentru care este suprascrisa metoda windowClosing ():
addWindowListener (new java.awt.event. WindowAdapter () {
public void windowClosing (java.awt.event.WindowEvent evt ) {
System.exit(0);
}
});
Un exemplu tipic de folosire a claselor anonime este instantierea adaptorilor direct in corpul unei clase
(de tip Frame ) care contine componente ale caror evenimente trebuie tratate.
Utilizarea IDE NetBeans pentru tratarea evenimentelor Java
Mediul de dezvoltare NetBeans faciliteaza lucu cu evenimente permitand generarea automata de cod
pentru definirea claselor interceptoare de evenimente si pentru definirea metodelor de tratare a
acestora. De asemenea, se genereaza cod si pentru a asocia o componenta -sursa la administratorul de
evenimente dorit.
Pentru a trata evenimentele unei componente (obiect vizual) in mod automat se procedeaza astfel:
1. se intra in modul de lucru “Design” (proiectare interfata grafica);
2. se alege din fereastra de proprietati (“Properties”) tab -ul “Event” al componentei dorite care este
sursa evenimentului; astfel, sunt vizualizate toate metodele -eveniment atasate componentei respective;
3. se selecteaza apoi metoda -eveniment dorita; pe ecran apare fereastra “Handlers” a metodei –
eveniment in care se alege butonul “Add” pentru a da un nume unei metode definita de programator
care sa trateze evenimentul respectiv; dupa terminarea acestei operatiuni IDE NetBeans face com utarea
in modul de lucru “Source” (editare cod sursa);
4. In modul de lucru “Source” IDE NetBeans creaza automat antetul metodei a carui nume a fost stabilit
la pasul 3; imediat dupa antetul metodei, programatorul poate introduce cod care sa trateze un
eveniment.
Daca se doreste stergerea unei metode -eveniment asociata cu o componenta din interfata, se
procedeaza la fel, numai ca la pasul 3 se foloseste butonul “Remove” din fereastra “Handlers”. Automat,
se va sterge si codul metodei -eveniment respective.
Figura de mai jos ilustreaza cum se poate declara o metoda pentru tratarea unui tip de eveniment al
unei componente din interfata utilizator (a unui buton de comanda).

Urmatorul program (TestEvenimente.java) creaza o interfata grafica folosind compone nta Frame in care
sunt plasate componente elementare de tip Label , Button si TextField . Programul citeste de la tastatura
un sir de 10 numere si calculeaza media numerelor citite. Media este apoi afisata in caseta de text din
interfata grafica.
Mediul de programare folosit pentru crearea acestei interfete utilizator a fost IDE NetBeans. Variabila de
tip Label are numele label1 (dat implicit de NetBeans) variabila de tip Button are numele cmdMedie iar
variabila de tip TextField are numele txtMedie . Interfat a utilizator a aplicatiei in faza de proiectare este
ilustrata in figura de mai jos

Listingul acestui program este prezentat in continuare.
public class TestEvenimente extends java.awt.Frame {
/** Creates new form TestEvenimente */
public TestEvenimente() {
initComponents() ;
}

/** This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
// <editor -fold defaultstate="collapsed" desc=" Generated Code ">
private void initComponents() {
cmdMedie = new java.awt.Button();
label1 = new java.awt.Label();
txtMedi e = new java.awt.TextField();
setLocationRelativeTo(null);
setTitle("Calcul medie");
addWindowListener(new java.awt.event.WindowAdapter() {
public void windowClosing(java.awt.event.WindowEvent evt) {
exitForm(evt);
}
});
cmdMedie.setLabel("calcul medie aritmetica");
cmdMedie.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseClicked(java.awt.event.MouseEvent evt) {
clicDeMo useMedie(evt);
}
});
label1.setText("media este");
org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(layout.createSequentialGroup()
.add(76, 76, 76)

.add(label1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE,
org.jdesktop.layo ut.GroupLayout.DEFAULT_SIZE,
org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
.add(41, 41, 41)
.add(txtMedie, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 96,
org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
.addContainerG ap(133, Short.MAX_VALUE))
.add(org.jdesktop.layout.GroupLayout.TRAILING, layout.createSequentialGroup()
.addContainerGap(147, Short.MAX_VALUE)
.add(cmdMedie, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE,
org.j desktop.layout.GroupLayout.DEFAULT_SIZE,
org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
.add(122, 122, 122))
);
layout.setVerticalGroup(
layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(layout.createSequentialGroup()
.add(35, 35, 35)
.add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING)
.add(label1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE,
org.jdesktop.layout.GroupLayout.DEFAULT_SIZE,
org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
.add(txtMedie, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE,
org.jdesktop.layout.GroupLayout.DEFAULT_SIZE,
org.jdesktop.layout.GroupLayout.P REFERRED_SIZE))
.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, 185,
Short.MAX_VALUE)
. /** Exit the Application */
private void exitForm(java.awt.event.WindowEvent evt) {

System.exit(0);
}

public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new TestEvenimente().setVisible(true);
}
});
}
// Variables declaration – do not modify
private java.awt.Button cmdMedie;
private java.awt.Label label1;
private java.awt.TextField txtMedie;
// End of variables declaration
}
add(cmdMedie, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE,
org.jdesktop.layout.GroupLayout.DEFAULT_SIZE,
org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
.add(36, 36, 36))
);
pack();
}// </editor -fold>
private void clicDeMouseMedie(java.awt.event.MouseEvent evt) {
int[] a = new int[10];
int suma;
float medie;
suma = 0;
medie = 0;

for(int i = 0; i < 10; i++)
{
String raspuns = javax.swing.JOptionPane.showInputDialog(this, "Introduceti un
numar", "Introducere de date", javax.swing.JOptionPane.INFORMATION_MESSAGE);
a[i] = Integer.parseInt(raspuns);
suma += a[i];
}
medie = suma/10;
txtMedie.setText(new Float(medie).toString());
}
Vom face cateva comentarii asupra programului prezentat mai sus:
1. IDE NetBeans genereaza automat metoda cu numele initComponents() folosita de constructorul clasei
TestEvenimente pentru initializarea componentelor interfetei utilizator; codul din aceasta metoda nu se
poate modifica in modul de lucru “Source” ci numai in modul de lucru “Design” prin folosirea fereastrei
de proprietati (“Properties”).
2. Sunt incluse in m etoda initComponent() urmatoarele metode de tratare a evenimentelor:
– metoda -eveniment mouseClicked() a clasei interceptoare MouseAdapter , folosita pentru
butonul de comanda cmdMedie ; metoda este redefinita in interiorul unei clase anonime;
– metoda -evenime nt windowClosing() a clasei WindowAdapter , folosita pentru inchiderea
ferestrei aplicatiei; metoda este redefinita in interiorul unei clase anonime.
3. Metoda clicDeMouseMedie() este apelata din metoda mouseClicked() si descrie codul care trebuie
executat atunci cand se face clic de mouse pe butonul cmdMedie . Antetul acestei metode nu se poate
modifica decat in modul de lucru “Design” folosind procedura descrisa la tratarea evenimentelor cu
ajutorul IDE NetBeans. Corpul metodei poate fi modificat de program ator in modul de lucru “Source”.
4. Metoda exitForm ()este apelata din metoda windowClosing () si descrie codul care trebuie executat
atunci cand se apasa pe butonul “x” din coltul din dreapta sus al ferestrei aplicatiei. Acest cod a fost
generat automat la crearea fisierului “TestEvenimente.java”, dar el poate fi modificat de programator in
modu l de lucru “Source”.
Mediul de dezvoltare NetBeans genereaza codul:
System.exit(0);
Metoda System.exit(0) realizeaza inchiderea masinii virtuale Java si deci a aplicatiei Java.

5. Metoda main () a aplicatiei a fost generata automat la crearea fisierului “TestEvenimente.java”. Codul
din aceasta metoda poate fi modificat sau completat cu alte instructiuni. Metoda
java.awt.EventQueue.invokeLater () apelata in metoda main () pune in executie firulul care face vizibila
fereastra aplicatiei, dupa ce s -au procesat toate celelalte evenimente trimise in coada de evenimente. Se
observa ca si aceasta metoda are ca parametru o instanta a unei clase anonime de tip Runnable . Metoda
care face vizibila fereastra aplicatiei este setVisible ().
6. In cod mai sunt folosite meto de ca:
– setText () pentru componenta txtMedie , care stabileste textul afisat in caseta de text;
– setLabel () pentru componenta cmdMedie , care stabileste textul afisat pe butonul cmdMedie ;
– SetTitle () pentru componenta de tip Frame, reprezentand fereastra ap licatiei, care specifica
titlul ferestrei.
Despre aceste metode, vom discuta mai pe larg in lectia urmatoare.
7. In metoda clicDeMouseMedie () este folosita clasa JOptionPane (din pachetul javax.swing ) pentru a
crea o caseta de dialog standard (sub forma unei mici ferestre) prin care se face citirea de la tastatura a
datelor de intrare. Pentru afisarea pe ecran a ferestrei de introducere a datelor s -a folosit metoda
showInputDialog () a clasei JOptionPa ne.
Despre crearea unor casete de dialog care sa realizeze introducerea datelor de la tastatura sau afisarea
unor mesaje scurte pe baza clasei JOptionPane , vom discuta mai pe larg in lectia urmatoare.
8. In metoda initComponents () s-a generat automat cod pentru pozitionarea componentelor vizuale pe
suprafata de afisare a ferestrei.
Deoarece in faza de proiectare a ferestrei aplicatiei, s -a ales, ca mod de asezare a componentelor, schita
(layout) “Free Design” (optiunea Set Layou t -> Free Design din mediul NetBeans) s -a generat automat
cod Java pentru:
– crearea administratorului de pozitionare (folosind operatorul new si clasa corespunzatoare
org.jdesktop.layout.GroupLayout );
– stabilirea administratorului de pozitionare pentru ferea stra aplicatiei (folosind metoda
setLayout ());
– adaugarea componentelor in fereastra aplicatiei (folosind metoda add()).
Despre toate acestea mai pe larg in lectia 13.

Curs 13
Cuvinte importante:

– realizarea unei interfete grafice folosind AWT: ierarh ii de clase AWT; clasa Component , clasa
Container , clasa Window , clasa Frame , clasa Panel ;
– notiuni de baza despre pozitionarea componentelor interfetei utilizator: administratori de
pozitionare;
– componente AWT elementare: clasa Label , clasa Button , clasa TexField , clasa TextArea ;
– realizarea unei interfete grafice folosind tehnologia Swing: avantaje Swing; containere radacina
(clasa JFrame , clasa JDialog , clasa JWidow) ; clasa abstracta JComponent ; containere intermediare (clasa
JPanel ).
Realizare a unei interfete utilizator grafice folosind AWT
O componenta este un obiect grafic care poate fi adaugat pe suprafata de afisare a unei aplicatii Java.
Utilizatorul poate interactiona cu aplicatia prin intermediul acestor componente.
Pentru realizarea une i interfete -utilizator grafice pachetul java.awt dispune de urmatoarea ierarhie de
clase :

Clasa abstracta Component , aflata in radacina arborelui claselor din AWT, defineste interfata general
valabila pentru toate componentele grafice. Obiectele de t ip Component se numesc componente
grafice .
Un container (obiect de tip Container ) este o componenta care poate contine alte componente AWT.
Exemple de containere sunt: ferestre independente (obiecte de tip Frame ), casete de dialog (obiecte de
tip Dialog ), fereastra Applet etc.
Clasa Container este superclasa tuturor suprafetelor de afisate Java (ferestre independente, Applet -uri
etc).
O fereastra AWT (obiect de tip Window ) este o suprafata de afisare dreptunghiulara fara margini si fara
bara de meniuri.
Un cadru (obiect de tip Frame ) este o fereastra AWT cu margini, titlu si bara de meniuri.
Window
Dialog
Object
Component (clasa abstracta)
Container
Frame
ScrollPane
Panel
Applet
Button
Label
TextComponent

TextArea
TextField

O fereastra de dialog (obiect de tip Dialog ) extinde o fereastra AWT prin adaugarea de margini si a unui
titlu; ea este folosita in principal pentru a prelua informat ii de la utilizator.
O fereastra de defilare (obiect de tip ScrollPane ) implementeaza un cadru de defilare pe orizontala si pe
verticala pentru o componenta inclusa in container.
Un panou (obiect de tip Panel ) este folosit pentru a grupa mai multe componente elementare (butoane,
casete de text etichete etc).
Un applet (obiect de tip Applet ) extinde un panou AWT si este folosit ca suprafata de afisare a
componentelor elementare ale unei aplicatii Internet de tip Applet, executate prin intermediul unu i
browser compatibil Java (ca de exemplu Internet Explorer sau Netscape).
Vom descrie succint componentele prezentate in ierarhia de clase AWT.
Clasa Component este o clasa abstracta care deriva din clasa Object si face parte din pachetul java.awt .
Dintre metodele acestei clase mentionam:
– void setVisible (boolean <b>) afiseaza si activeaza componenta daca parametrul <b> are
valoarea true sau face componenta invizibila daca parametrul <b> este false ;
– boolean isEnabled() testeaza daca componenta curent a este disponibila;
– void setEnabled (boolean <b>) face disponibila componenta daca parametrul <b> are valoarea
true sau face componenta indisponibila daca parametrul <b> este false ;
– void requestFocus () este o metoda prin care componenta curenta primeste focus -ul (controlul
asupra tastaturii) cu conditia ca ea sa fie vizibila;
– boolean hasFocus () testeaza daca componenta curenta are focusul;
– Component getParent () returneaza componenta -parinte;
– void setBackground (Color <c>) stabileste culoa rea fundalului componentei conform cu
parametrul <c>;
– void setForeground (Color <c>) stabileste culoarea de scriere sau de desenare pe componenta
conform cu parametru <c>;
Nota: Sa observam ca parametrul pentru metodele setBackground() si setForeground() este un obiect
de tip Color . Clasa Color contine anumite constante care indica culoarea si mai multe metode prin care
se poate stabili o culoare. Exemple de constante de culoare sunt: black, red, white, yellow etc. De
asemenea, clasa contine constructorul Color(float <r>, float <g>, float <b>) prin care se poate forma o
culoare in sistemul RGB.
– setFont (Font <font>) stabileste font -ul cu care se scrie, stilul sau si marimea.
Nota: Se observa ca parametrul metodei setFont() este un obiect de tip Font . Clasa Font are un
constructor de forma: Font(String <nume>, int <stil>, int <marime>) , in care: parametrul <nume>
specifica numele font -ului, parametrul <stil> specifica stilul (valorile uzuale sunt: Font.ITALIC , Font.Bold ,
Font.PLAIN ), parametrul <marime> s pecifica marimea font -ului.

– void setName (string <nume>) este o metoda prin intermediul careia se poate atasa un nume
pentru o componenta indiferent de tipul ei; acest nume poate fi folosit cand trebuie sa detectam o
anumita componenta din container.
– String getName () returneaza numele componentei dat prin setName ().
Clasa Container face parte din pachetul java.awt .
Constructorul clasei este de forma:
Container ()
Dintre metodele acestei clase mentionam:
– void setLayout (LayoutManager <tip_pozitionare >) stabileste modul de pozitionare al
componentelor interfetei in container, corespunzator parametrului <tip_pozitionare> (adica stabileste
gestionarul de pozitionare a componentelor in container). Vom reveni la modalitatile de dispunere a
componentelor in terfetei grafice mai tarziu in aceasta lectie;
– Component add(Component <comp>) insereaza componenta <comp> in container;
– Component add(Component <comp>, Object <constrangeri>) insereaza componenta <comp>
in container si stabileste constrangeri pentr u pozitionare in functie de gestionarul de pozitionare (Layout
Manager) ales pentru container;
– void remove (Component <comp>) elimina componenta <comp> din container;
– void removeAll () elimina toate componentele din container;
– Component getComponen tCount () returneaza numarul de componente din container;
– Component[] getComponents () returneaza un tablou cu toate componentele din container;
– void validate () forteaza containerul sa reaseze toate componentele sale; aceasta metoda
trebuie apelata explicit atunci cand adaugam sau eliminam componente pe suprafata de afisare dupa ce
aceasta a devenit vizibila in timpul executiei programului.
Clasa Window face parte din pachetul java.awt si nu este utilizata, de regula direct pentru construirea
ferestr elor. Sunt utilizate clasele derivate, cum ar fi Dialog (pentru ferestre de dialog) sau Frame (pentru
fereastra unei aplicatii).
Ferestrele formeaza o ierarhie. Fiecare fereastra are o fereastra -parinte si poseda (sau nu) mai multe
subferestre.
Cele mai im portante metode publice ale clasei Window sunt:
– void dispose () elibereaza resursele native ale ecranului folosite de fereastra si produce
disparitia acesteia de pe ecran;
– Window[] getOwnedWindows () returneaza un vector cu subferestrele ferestrei cure nte;
– Window getOwner () returneaza parintele ferestrei curente;

– boolean isActive () returneaza valoarea true daca fereastra este activa si valoarea false daca
fereastra este inactiva;
– void pack () face ca fereastra si componentele sale sa se potrivea sca la dimensiuni optime.
Clasa Frame face parte din pachetul java.awt si corespunde ferestrelor aplicatiei.
Dintre constructorii clasei mentionam:
– Frame () creaza o fereastra cu margini, titlu si bara de meniuri dar care nu are precizat nici un
text in titlu;
– Frame (String <titlu>) creaza o fereastra cu margini, titlu si bara de meniuri care are inscris in
titlu textul dat de parametrul <titlu>.
Dintre metodele publice mai importante ale clasei Frame mentionam:
– void setTitle (String <titlu>) stabile ste textul care apare in titlul ferestrei;
– void setMenuBar (MenuBar <baraMeniu> stabileste meniul de tip bara al aplicatiei;
– void pack () este mostenita de la clasa Window ; metoda redimensioneaza fereastra la cea mai
mica dimensiune posibila, tinand co nt de dimensiunile curente ale componentelor sale, de modul de
asezare a componentelor sale si de insertiile de margini sau intre componente stabilite; trebuie apelata
dupa adaugarea tuturor componentelor pe suprafata ferestrei.
Clasa Dialog face parte din pachetul java.awt si permite lucrul cu ferestre de dialog. Acestea nu pot fi
maximizate sau minimizate. Clasa Dialog poseda urmatorii constructori:
Dialog (Dialog <proprietar>);
Dialog (Dialog <proprietar>, String <titlu>);
Dialog (Dialog <proprietar>, String <titlu>, boolean <modal>);
Dialog (Frame <proprietar>);
Dialog (Frame <proprietar>, String <titlu>);
Dialog (Frame <proprietar>, String <titlu>, boolean <modal>);
unde:
– <proprietar> – specifica fereastra -parinte (fereastra care contine comanda care a lansat
fereastra de dialog);
– <titlu> – specifica titlul ferestrei;
– <modal> – specifica valoarea true daca fereastra este modala si valoarea false daca fereastra
este nemodala.
– Nota:

– O fereastra de dialog este modala daca dupa afisarea ei nu se mai poate actiona asupra ferestrei
(parinte) din care aceasta a fost lansata. O fereastra este nemodala daca permite activarea
ferestrei (parinte) fara ca fereastra de dialog sa se inchida.
– Clasa Dialog este derivata din clasa Window si deci mosteneste met odele acestei clase. In plus
mentionam doua metode care se refera la tipul ferestrei (modala sau nemodala):
– – boolean isModal () testeaza daca fereastra de dialog este modala sau nu;
– – void setModal (boolean <modal>) seteaza tipul modal daca parametrul <mo dal>
primeste valoarea true.
– Clasa Panel face parte din pachetul java.awt si este folosita pentru gruparea unui numar de
componente elementare (butoane, casete de text etichete etc).
– Clasa Panel poseda urmatorii constructori:
– – Panel() ; creaza un panel ca re foloseste gestionarul de pozitionare implicit pentru
asezarea componentelor in panel;
– – Panel (LayoutManager <tip_pozitionare>) ; creaza un panel care foloseste un gestionar
de pozitionare a componentelor specificat in parametrul <tip_pozitionare>.
– Notiuni de baza despre pozitionarea componentelor interfetei utilizator
– Pentru a avea mai mult control asupra aspectului interfetei, programatorul care lucreaza cu
AWT poate folosi administratorii (gestionari) de pozitionare (layout managers). Un administrat or
de pozitionare determina modul cum vor fi aranjate (pozitionate) componentele adaugate intr –
un container.
– Un administrator de pozitionare este un obiect al unei clase care implementeaza interfata
LayoutManager .
– Pentru stabilirea unui administrator de po zitionare, clasa Container pune la disopzitie metoda
setLayout(LayoutManager <tip_pozitionare>) .
– Orice container are un gestionar de pozitionare. Java pune la dispozitie urmatoarele clasele din
pachetul java.awt pentru gestionarea pozitionarii:

Pentru a crea un administrator de pozitionare pentru un container, se creaza o instanta a clasei
administratorului folosind o instructiune de genul:
GridLayout glo = new GridLayout();
Dupa crearea administratorului de pozitionare, acesta va fi declarat dre pt administrator de pozitionare
pentru container folosind metoda setLayout() a acestuia:
setLayout(glo);
Nota: Administratorul de pozitionare trebuie stabilit inainte de a adauga (folosind metoda add())
componentele in container.
Vom descrie succint cateva dintre clasele administratorilor de pozitionare mai des folositi.
Pozitionarea secventiala a componentelor – clasa FlowLayout
FlowLayout este cea mai simpla clasa de administrare a pozitionarii componentelor. Ea aranjeaza
componentele intr -o manier a asemanatoare dispunerii cuvintelor intr -o pagina – de la stanga la dreapta
pana la capatul randului, apoi in continuare pe randul urmator. Acesta este gestionarul de pozitionare
implicit pentru obiecte de tip Panel si Applet.
Pozitionarea tabelara a com ponentelor – clasa GridLayout
Administratorul de pozitionare tabelara ( GridLayout ) aranjeaza componentele intr -un tabel format din
randuri si coloane. Componentele sunt asezate incepand cu celula aflata cel mai in stanga pe primul
rand al tabelului si con tinuand spre dreapta. Dupa completarea tuturor celulelor de pe primul rand se
continua cu cel de -al doilea rand, de la stanga la dreapta, si asa mai departe. In figura de mai jos se
prezinta aranjamentul GridLayout pentru cinci etichete Label, folosind med iul NetBeans.
LayoutManager
(interfata)
GridLayout
FlowLayout
LayoutManager2 (interfata)
Object (clasa
radacina Java)
CardLayout
BorderLayout
GridBagLayout

Listingul programului care realizeaza interfata -utilizator proiectata, folosind gestionarul de
pozitionare GridLayout (PozitionareGridLayout.java) se prezinta in continuare. Pentru proiectarea
interfetei -utilizator s -a folosit mediul de dezvoltare NetBeans 5.0.
public class PozitionareGridLayout extends java.awt.Frame {
public PozitionareGridLayout() {
initComponents();
}
// <editor -fold defaultstate="collapsed" desc=" Generated Code ">
private void initComponen ts() {
label1 = new java.awt.Label();
label2 = new java.awt.Label();
label3 = new java.awt.Label();
label4 = new java.awt.Label();
label5 = new java.awt.Label();
setLayout(new java.awt.GridLayout(3, 3, 10, 10 ));
setTitle("Pozitionare de tip GridLayout");
addWindowListener(new java.awt.event.WindowAdapter() {
public void windowClosing(java.awt.event.WindowEvent evt) {
exitForm(evt);
}

});
label1.setBackground(new java.awt.Color(255, 255, 153));
label1.setText("testez");
add(label1);
label2.setBackground(new java.awt.Color(255, 255, 153));
label2.setText("diverse");
add(label2);
label3. setBackground(new java.awt.Color(255, 255, 153));
label3.setText("tipuri");
add(label3);
label4.setBackground(new java.awt.Color(255, 255, 153));
label4.setText("de aranjamente");
add(label4);
label5.setBackground(new java.awt.Color(255, 255, 153));
label5.setText("pe suprafata ferestrei");
add(label5);
pack();
}// </editor -fold>
/** Exit the Application */
private void exitForm(java.awt.event.WindowEv ent evt) {
System.exit(0);
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new PozitionareGri dLayout().setVisible(true);
}
});
}

// Variables declaration – do not modify
private java.awt.Label label1;
private java.awt.Label label2;
private java.awt.Label label3;
private java.awt.Label lab el4;
private java.awt.Label label5;
// End of variables declaration
}
La executia programului pe ecran se afiseaza fereastra de tip Frame de mai jos:

Pozitionare marginala – clasa BorderLayout
Pozitionarea marginala ( BorderLayout ) imparte un container in cinci sectiuni: nord, sud, est, vest si
centru. Acest aranjament are ca rezultat o componenta centrala de dimensiuni mari, inconjurata de
patru componente de dimensiuni mai mici. Acesta este gestionarul de pozitionare implicit pen tru
obiecte de tip Frame si pentru obiecte de tip Dialog .
Pozitionare tabelara neproportionata – GridBagLayout
Pozitionarea tabelara neproportionata ( GridBagLayout ) reprezinta o extensie a dispunerii tabelare. O
pozitionare tabelara neproportionata difera de o dispunere tabelara simpla prin urmatoarele:
– o componenta poate ocupa mai multe celule ale tabelului;
– proportiile intre diferitele randuri sau coloane nu trebuie sa fie aceleasi;
– componentele dispuse in cadrul celulelor pot fi aranjate in dif erite moduri.
Dispunerea in stiva – CardLayout
Dispunerea in stiva ( CardLayout ) difera de celelalte pozitionari deoarece ascunde vederii unele
componente (de tip container sau componenta elementara). Clasa CardLayout permite afisarea unei
singure compone nte (de tip container sau componenta elementara) din grup la un moment dat. Fiecare
container sau componenta elementara din stiva este denumit cartela (card ).

De obicei, dispunerea in stiva foloseste panoul pentru fiecare cartela. Mai intai se introduc
componentele dorite in fiecare dinte panourile din stiva, iar pentru fiecare panou se poate stabili
gestionarul de pozitionare dorit. Apoi panourile (cartele) se introduc in containerul pentru care s -a
stabilit o dispunere in stiva.
Dispunerea componentelor fara utilizarea unui gestionar de pozitionare – NullLayout
Pentru a plasa componentele fara a utiliza un gestionar predefinit vom apela metoda setLayout () cu
parametrul null:
setLayout(null);
In dispunerea componentelor fara un gestionar de pozitionare, c omponentele trebuie dimensionate si
pozitionate, altfel nu sunt vizibile.
Pentru dimensionarea si plasarea componentelor putem utiliza metoda:
void setBounds (int <x>, int <y>, int <latime>, int <inaltime>);
unde:
– <x>, <y> – specifica coordonatele pozitie i componentei in container;
– <latime>, <inaltime> – specifica dimensiunile componentei.
In figura de mai jos se prezinta aranjamentul NullLayout pentru cinci etichete Label, folosind mediul
NetBeans.

Se stie faptul ca programele scrise in Java trebuie sa ruleze independent de rezolutia monitorului. In
dispunerea componentelor fara gestionar de pozitionare este necesar cu atat mai mult sa se aiba grija
de aceasta cerinta.
O clasa care face posibila independenta de platforma pe care se executa aplicatia e ste clasa abstracta
ToolKit care face parte din pachetul java.awt .
Cele mai importante metode ale clasei ToolKit sunt:
– static Toolkit getDefaultToolkit () returneaza un obiect Toolkit , care contine date despre
setarile curente ale sistemului de operare n ativ;
– Dimension getScreenSize () returneaza o referinta catre un obiect de tip Dimension care
contine lungimea (width) si inaltimea (height) in pixeli a ecranului.
Nota : In mediul de dezvoltare NetBeans metodele prezentate sunt generate automat pentru o aplicatie
Java, daca in fereatra Properties , la tab -ul Code , se seteaza elementul Form Size Policy cu valoarea
“Generate Resize Code ”. Implicit acest element este setat cu valoarea “ Generate pack() ” care permite
generarea automata a metodei pack () a contai nerului in care se afla componentele.
Listingul programului care realizeaza interfata -utilizator proiectata (PozitionareNullLayout.java) fara
folosirea unui gestionar de pozitionare se prezinta in continuare. Pentru proiectarea interfetei -utilizator
s-a folosit mediul de dezvoltare NetBeans 5.0.
public class PozitionareNullLayout extends java.awt.Frame {
public PozitionareNullLayout() {
initComponents() ;}
// <editor -fold defaultstate="collapsed" desc=" Generated Code ">
private void initComponents() {
label1 = new java.awt.Label();
label2 = new java.awt.Label();
label3 = new java.awt.Label();
label4 = new java.awt.Label();
label5 = new java.awt.Label();
setLayout(null);
setTitle("Pozitionare de tip NullLayout");
addWindowListener(new java.awt.event.WindowAdapter() {
public void windowClosing(java.awt.event.WindowEvent evt) {
exitForm(evt);}});

label1.setBackground(new j ava.awt.Color(255, 255, 153));
label1.setText("testez");
add(label1);
label1.setBounds(30, 60, 50, 30);
label2.setBackground(new java.awt.Color(255, 255, 153));
label2.setText("diverse");
add(label2);
label2.setBounds(80, 60, 50, 30);
label3.setBackground(new java.awt.Color(255, 255, 153));
label3.setText("tipuri");
add(label3);
label3.setBounds(130, 60, 40, 30);
label4.setBackground(new java.awt.Color(255, 255, 153));
label4.setText("de aranjamente");
add(label4);
label4.setBounds(170, 60, 110, 30);
label5.setBackground(new java.awt.Color(255, 255, 153));
label5.setText("pe suprafata ferestrei");
add(label5);
label5.setBounds(30, 90, 175, 30);
java.awt.Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
setBounds((screenSize.width -368)/2, (screenSize.height -223)/2, 368, 223);
}// </editor -fold>
/** Exit the Application */
private void exitForm(java.awt.event.WindowEvent evt) {
System.exit(0);
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {

public void run() {
new PozitionareNullLayout().setVisible(true);
}
});
}
// Variables declaration – do not modify
private java.awt.Label label1;
private java.awt.Label label2;
private ja va.awt.Label label3;
private java.awt.Label label4;
private java.awt.Label label5;
// End of variables declaration
}
La executia programului pe ecran se afiseaza fereastra de tip Frame de mai jos:

Pozitionarea Free Design a componentelor, utilizata in mediul NetBeans – clasa
org.jdesktop.layout.GroupLayout
Administratorul de pozitionare Free Design aranjeaza fiecare componenta fata de marginile de sus, de
jos si din stanga a containerului (ferestre i), precum si fata de componentele alaturate. Acest tip de
gestionar de pozitionare este inclus in mediul de dezvoltare NetBeans si este destul de usor de folosit
neavand constrangeri de asezare a componentelor proiectate.
In lectia 12 s -a prezentat codul -sursa pentru o aplicatie Java care calculeaza media aritmetica a 10
numere naturale. Interfata -utilizator a fost proiectata folosind gestionarul de pozitionare Free Design .
Componente AWT elementare
Componentele elementare (numite si controale grafice) permit interactiunea cu utilizatorul si realizarea
(prin modul lor de asezare si aspectul lor) unei interfete “prietenoase” in dialogul cu acesta.
Componentele elementare pot fi adaugate containerelor. Fie C un container si comp o componenta
elementara. Ad augarea lui comp in C se realizeaza astfel:

– se creaza componenta comp folosind operatorul new ;
– se apeleaza metoda add(), declarata in clasa Container , pentru componenta comp :
C.add(comp);
Nota: Mediul de dezvoltare NetBeans permite generarea automata a codului -sursa pentru adaugarea
unei componente la un container.
Atunci cand se adauga o componenta intr -un container, nu se specifica coordonatele x, y ale locului
unde va fi plasata aceasta (cu exceptia dispunerii fara administrator de pozitionare). De aranjamentul
componentelor se ocupa administratorul de dispunere (layout manager) care apartine containerului
respectiv.
Vom descrie cateva componente elementare AWT mai des folosite: etichete ( Label), butoane ( Button ),
campuri de text ( TextField ) si zone de text ( TextArea ).
Etichete
Etichetele sunt create folosind clasa Label . Etichetele sunt texte care pot fi afisate pe suprafata de
afisare dar nu pot fi modificate de utilizator
Clasa Label are urmatorii constructori:
– Label () creaza o eticheta cu text vid;
– Label (String <text>) creaza o eticheta cu textul, specificat in parametrul <text>, aliniat la
stanga.
Dintre metodele clasei Label , mai des folosite sunt:
– void setText (String <text>) scrie un text, specificat in parametrul <text>, pe eticheta;
– String getText () returneaza textul asociat etichetei;
– void setAlignment (int i) seteaza aliniere textului in eticheta (precizand pentru argument una
din constantele clasei). Alinierea impli cita este la stanga.
Butoane
Butoanele sunt create folosind clasa Button . Butoanele sunt folosite intr -o interfata pentru a declansa o
anumita actiune.
Clasa Button are urmatorii constructori:
– Button () creaza un buton care nu contine nici un text pentru explicarea functiei sale;
– Button (String <eticheta>) creaza un buton pe care este afisat sirul de text, specificat in
parametrul <eticheta>.
Dintre metodele clasei Button , mai des folosite sunt:
– void setText (String <eticheta>) scrie sirul de te xt, specificat in parametrul <eticheta>, pe buton;

– String getText () returneaza eticheta inscrisa pe buton;
Campuri si arii de text
Campurile si ariile de text sunt create folosind clasele TextField si TextArea . Textele sunt folosite intr -o
interfata pentru a crea zone in care textul poate fi modificat de utilizator. Aceste doua clase au ca
superclasa TextComponent .
Clasa TextField are mai multi constructori dintre care mentionam:
– TextField () creaza un camp d e text care nu contine nici un text;
– TextField (String <text>) creaza un camp de text completat cu sirul de text, specificat in
parametrul <text>.
Dintre metodele clasei TextField , mai des folosite sunt:
– void setText (String <text>) scrie sirul de text , specificat in parametrul <text>, in camp;
– String getText () returneaza textul continut de camp;
– void setEditable (boolean <b>) determina daca acel camp de text poate fi modificat. Un
parametru cu valoarea false impiedica editarea campului, iar valoar ea true o permite (aceasta este
prestabilita).
– boolean isEditable () returneaza o valoare de tip boolean prin care se indica daca acel camp poate fi
editat ( true) sau nu ( false );
– int getCaretPosition () returneaza pozitia cursorului in cadrul textului;
– void setCaretPosition () muta cursorul la pozitia specificata;
– String getSelectionText () returneaza textul selectat.
Obiectele de tip TextArea se deosebesc de obiectele TextField prin aceea ca ele contin mai multe linii de
text. Zonele de text poseda bare de defilare orizontale si verticale, care permit utilizatorului sa parcurga
intregul text continut in componenta.
Clasa TextArea are mai multi constructori dintre care mentionam:
– TextArea () creaza o arie de text care nu contine nici un text, cu in altimea si latimea
nespecificate;
– TextArea (String <text>) creaza o arie de text completata cu sirul de text, specificat in
parametrul <text>, cu inaltimea si latimea nespecificate;
Dintre metodele clasei TextArea , mai des folosite sunt:
– void setText (String <text>), String getText (), void setEditable (boolean <b>), boolean
isEditable () au aceeasi semnificatie ca cele prezentate la clasa TextField ;
– void append (String <text>) adauga textul specificat, in parametrul metodei, la sfarsitul textului
din co mponenta;

– void insert (String <text>, int <pozitie>) insereaza textul, specificat in parametrul <text>, la
pozitia indicata de parametrul <pozitie>;
– void replaceRange (String <text>, int <inceput>, int <sfarsit>) inlocuieste textul cuprins intre
pozit ile specificate de parametrii <inceput> si <sfarsit> cu textul indicat in parametrul <text>;
– int getRows () intoarce numarul de randuri ale componentei;
– void setRows (int <m>) stabileste numarul de linii ale ariei de text conform cu parametrul <m>;
– int getColumns () intoarce numarul de coloane ale componentei;
– void setColumns (int <n>) stabileste numarul de coloane ale ariei de text conform cu
parametrul <n>.
Realizarea unei interfete grafice folosind Swing
Tehnologia Swing face parte din proiect numit JFC (Java Foundation Classes) care pune la dispozitie ,
dezvoltatorilor de aplicatii Java o serie intreaga de facilitati pentru scrierea de aplicatii cu o interfata
grafica mult imbunatatita functional si estetic fata de vechiu l model AWT.
Avantaje Swing
Swing permite unei aplicatii Java sa -si modifice aspectul si comportarea (“look -and- feel”) sub actiunea
unui program sau chiar a utilizatorului. Astfel, Swing permite crearea unei aplicatii Java cu o interfata –
utilizator care foloseste stilul sistemului d e operare nativ – cum ar fi Windows sau Solaris – sau un stil
propriu Java, care a fost denumit “Metal”.
Componentele Swing sunt implementate in intregime in Java. Aceasta are ca rezultat o mai buna
compatibilitate cu platforme diferite decat in cazul fol osirii componentelor AWT. Toate componentele
Swing fac parte din pachetul javax.swing .
Toate componentele grafice Swing sunt construite conform specificatiei JavaBeans, ceea ce inseamna ca
sunt, de fapt, componente JavaBeans.
Proiectarea ferestrelor aplic atiei cu Swing

Modul de folosire a unei componente Swing nu este diferit de cel al folosirii componentelor AWT. Toate
componentele Swing sunt subclase ale clasei JComponent cu exceptia componentelor de tip JFrame ,
JWindow, JDialog si JApplet .

Pentru a fi afi sate pe ecran , componentele grafice , ale unei aplicatii care foloseste o interfata Swing,
trebuie plasate pe o suprafata de afisare , numita “ container radacina” . “Containerul radacina” este
reprezentat de una din clasele JFrame , JWindow, JDialog sau JApplet .
Observatii :
1. Modul in care componentele unui container vor fi desenate la momentul vizualizarii acestuia depinde
de gestionarul de pozitionare care este asociat containerului. Este important sa intelegem modul in care
lucreaza gestionarii de po zitionare, pentru a nu avea surprize la momentul desenarii containerului.
2. Dupa cum am precizat deja, panourile reprezentand “containere intermediare” li se asociaza
gestionarul FlowLayout , iar ferestrelor reprezentand “containere radacina” li se asocia za gestionarul
BorderLayout . Se poate opta pentru varianta ca mai multe componente sa fie grupate separat in
containere intermediare (de exemplu de tip JPanel ), astfel avand posibilitatea de a le gestiona impreuna
pozitionarea, separat de toate celelalte c omponente.
A. Containere radacina
Toate containerele radacina implementeaza interfata RootPaneContainer si deci au aceeasi organizare
interna.
Diferenta dintre aceste containere si celelalte componente Swing este ca ele mostenesc direct clasele
corespon dente lor din AWT:
– JFrame mosteneste clasa Frame ;
– JDialog mosteneste clasa Dialog;
– JWindow mosteneste clasa Window;
– JApplet mosteneste clasa Applet.
Object (din pachetul java.lang )
Component (clasa abstracta, din pachetul java.awt )
Container (din pachetul java.awt )
JComponent (clasa abstracta, din pachetul javax.swing )

Swing ofera independenta fata de sistemul de operare de pe masina gazda (in sensul look -and-feel-ului
componentelor care ramane identic pentru toate sistemele) tocmai prin modul in care aceste containere
sunt construite, continutul lor fiind gestionat de o componenta panou care este instanta a clasei
JRootPane .
Clasa JFrame
Clasa JFrame este derivata din clasa Frame si poate fi folosita intr -un mod asemanator, totusi, cu multe
deosebiri.
Orice aplicatie Java cu interfata Swing contine cel putin un “conta iner radacina” reprezentat de fereastra
principala a programului, instanta a clasei JFrame .
Orice fereastra JFrame contine un atribut de tip protected cu numele rootPane , care este o instanta a
clasei JRootPane , ce serveste drept container pentru alte cat eva componente -panou. Nu putem adauga
componente direct unei ferestre JFrame , ci unuia dintre panourile continute in rootPane .
Ierarhia implicita pentru panourile asociate la constructia unei ferestre JFrame este descrisa in
continuare.

Panoul contentPane este cel pe care se adauga si se aranjeaza toate componentele (grafice, elementare
sau intermedare) ferestrei JFrame .
Metoda getContentPane () (metoda a clasei JFrame ) este folosita pentru obtinerea unei referinte la
atributul contentPane asoci at ferestrei .
Aceasta metoda este folosita pentru adaugarea de componente la panoul contentPane (si implicit la
fereastra) in felul urmator:
fereastraMeaJframe.getContentPane().add(componentaMea); .
De asemenea, aceasta metoda este folosita pentru a seta gestionarul de pozitionare pentru o fereastra
in felul urmator:
JFrame
rootPane(un JRootPane)
layeredPane
(un panou
JLayeredPane)
contentPane
(implicit un JPanel)
glassPane
(implicit un
JPanel)
menuBar
(implicit un JMenuBar
null)

fereastraMeaJframe.getContentPane().setLayout(new FlowLayout)); .
Componenta glassPane este un panou JPanel neopac care sta deasupra tuturor componentelor din
JRootPane , actionand ca un ecran de protectie pentru fereastra. Acest lucru permite desenarea
deasupra tuturor componentelor din fereastra curenta, precum si interceptarea sau intreruperea
evenimentelor generate de mouse.
Componenta layeredPane se afla sub glassPane . Reprezinta un c ontainer care ofera o a treia dimensiune
pentru a pozitiona componentele, si anume adancimea. Este un container avand un numar nelimitat de
straturi (layers) pe care componentele pot fi asezate. Apare in acest fel suprapunerea componentelor
continute, aces t lucru putand fi foarte util. De exemplu, dorim ca un meniu pop-up sa apara deasupra
celorlalte componente continute de fereastra.
Clasa JLayeredPane ofera 6 obiecte de tip Integer , constante, reprezentand cele mai utilizate straturi.
Dintre acestea menti onam stratul FRAME_CONTENT_LAYER care este locul in care panoul -radacina,
asociat unei ferestre JFrame, adauga panoul contentPane si optional bara de meniuri.
Bara de meniuri nu exista implicit, dar poate fi setata folosind metoda setMenuBar () din clasa JFrame in
felul urmator:
JMenuBar meniulMeu = new JMenuBar();
setMenuBar(meniulMeu);
Astfel, bara de meniuri este pozitionata in partea de sus a stratului.
Spre deosebire de Frame , un obiect JFrame are un comportament implicit la inchiderea ferestrei , care
consta in ascunderea ferestrei atunci cand utilizatorul apasa butonul de inchidere (din coltul dreapta
sus). Acest comportament poate fi modificat prin apelarea metodei setDefaultCloseOperation ()
(metoda a clasei JFrame ) care primeste ca parametru diverse constante ce se gasesc in clasa
WindowConstants .
Constantele folosite ca parametru pentru metoda setDefaultCloseOperation () sunt:
– DO_NOTHING_ON_CLOSE ( definita in WindowConstants ) – nu se intampla nimic, ci numai
solicita programului sa trateze, in metoda windowClosing (), evenimentele interceptate cu un
interceptor de tip WindowListener ;
– HIDE_ON_CLOSE (defin ita in WindowConstants ) – ascunde automat fereastra dupa invocarea si
interceptarea unui obiect de tip WindowListener, ea pudand fi revizualizata la un moment
ulterior;
-EXIT_ON_CLOSE (defin ita in WindowConstants ) – termina aplicatia folosind metoda System.exit (),
descrisa in lectia 12.
– DISPOSE_ON_CLOSE (defin ita in WindowCons tants ) – distruge fereastra si continutul ei.
Valoarea implicita a parametrului metodei este: HIDE_ON_CLOSE .

Nota: Daca se foloseste mediul de programare NetBeans, codul pentru apelul metodelor
getContentPane si setDefaultCloseOperation se genereaza automa t in metoda initComponents () a
constructorului ferestrei de tip JFrame .
Dintre constructorii clasei JFrame mentionam:
– JFrame () creaza o fereastra care are gestionarul de pozitionare implicit BorderLayout () dar nu
are titlu;
– JFrame (String <titlu> ) creaza o fereastracare are gestionarul de pozitionare implicit
BorderLayout () si un titlu precizat in parametrul <titlu>.
Clasa JWindow
Componenta JWindow este asemanatoare cu JFrame , cu exceptia faptului ca nu are bara de titlu, nu i se
pot modifica di mensiunile, nu se poate minimiza sau maximiza si nu poate fi inchisa.
JWindow poate fi folosita pentru a vizualiza un mesaj temporar sau diverse imagini grafice.
Clasa JDialog
Aceasta clasa este folosita pentru a crea o fereastra de dialog care are o stru ctura si un comportament
identice cu JFrame . Putem crea o fereastra JDialog modala sau nemodala, dependenta sau nu de un alt
container.
B. Clasa JComponent
Clasa JComponent este o clasa abstracta din care deriveaza toate componentele Swing cu exceptia
com ponentelor de tip container -radacina.
Vom prezenta cateva dintre metodele acestei clase, mai des utilizate.
Fiecare componenta grafica are asociate trei proprietati pentru dimensionare, descrise in tabelul care
urmeaza impreuna cu metodele prin care acestea pot fi accesate.
Proprietate Metoda de acces Explicatii
preferredSize getPreferredSize()
setPreferredSize() Dimensiunea preferata a unei
componente. Este folosita de cei mai
multi gestionari de pozitionare pentru
a dimensiona implicit compon entele.
Dimensiunea preferata a unei
componente este determinata de
“look -and-feel-ul” componentei si de
font -urile pe care componenta le
foloseste

minimumSize getMinimumSize()
setMinimumSize() Folosita de gestionarii de pozitionare
ca limita in micsorarea dimensionilor
componentelor.
maximumSize getMaximumSize()
setMaximumSize() Folosita de gestionarii de pozitionare
ca limita in maximizarea
dimensionilor componentelor.
Metodele prefixate cu set, prezentate in tabelul precedent, primesc ca intrare o instanta a clasei
java.awt.Dimension. De exemplu, pentru a fixa dimensiunile unei componente elementare oarecare la o
latime de 200 pixeli si la o inaltime de 100 pixeli, se foloseste urmatoarea secventa de cod:
Dimension dim = new Dimension(200 ,100);
comp.setPreferredSize(dim);
Pentru ca o componenta sa fie desenata intr -adevar cu dimensiunile specificate in prealabil, trebuie sa
ne asiguram ca aceasta are un gestionar de pozitionare care respecta setarile facute pentru dimensiuni.
Spre exemplu, FlowLayout si GridBagLayout respecta dimensiunile preferate ale componentelor. In
schimb BorderLayout si GridLayout nu respecta dimensiunile preferate.
Nota : a) Daca se doreste redimensionarea unei componente care este deja vizibila, ea trebuie
redesenata dupa setarea noilor dimensiuni.
b) Pentru a aduce componentele la dimensiunile lor preferate (preferred size) se va apela metoda
pack () pentru container inainte de a apela setVisible () pentru container.
Metoda setToolTipText () seteaza un sir de caractere care va fi afisat atunci cand cursorul mouse -ului
stationeaza deasupra componentei. Sirul are rolul unui mesaj lamuritor despre functia respectivei
componente.
Formatul metodei este:
void setToolTipText (String <text_ajutator>)
Metoda getBorder () returneaza tipul de chenar (border) ales pentru componenta curenta sau valoarea
null daca chenarul nu a fost setat.
Formatul metodei este:
Border getBorder ()
Metoda setBorder () stabileste un chenar pentru componenta curenta.
Formatul metodei este:
void setBorder (Border <chenar>)
Metoda setEnabled () face ca o componenta sa fie disponibila sau nu.
Formatul metodei este:

void setEnabled (boolean <v>)
in care parametrul <v> are valorile true sau false .
C. Containere intermediare
Containerele intermediare sunt panouri si sunt instante ale claselor: JPanel , JScrollPane , JSplitPane ,
JTabbedPane care mostenesc superclasa JComponent .
Vom descrie succint clasele JPanel si JScrollPane des folosite in proiectarea unei interfete -utilizator .
Clasa JPanel
Aceasta clasa reprezinta containerul intermediar pentru orice interfata grafica si este folosit de cele mai
multe ori pentru a grupa si aranja mai multe componente ale unui alt container care le contine. Un
exemplu in acest sens este panoul contentPane de tip JPanel care reprezinta continutul unei ferestre
JFrame .
Dintre constructorii clasei JPanel mentionam:
– JPanel () creaza un panou care are gestionarul de pozitionare FlowLayout ();
– JPanel (LayoutManager <tip_de_pozitionare>) creaza un panou care are gestionarul de
pozitionare dat de parametrul <tip_de_pozitionare>.
Precizam ca principalele metode ale clasei JPanel care permit adaugarea, accesul si stergerea
componentelor dintr -un container, adaugarea de gestionari de positionare, setare a chenarelor, sunt
mosteniri din superclasele derivate.
Clasa JScrollPane
Clasa JScrollPane este folosita pentru a da posibilitatea derularii (scroll) unei alte componente in cazul in
care ea nu incape in intregime intr -o zona cu dimensiuni fixe. Compon enta JScrollPane ofera o
“perspectiva ” (numita “ viewport ”) asupra unei surse de date care poate fi, de exemplu, o imagine, un
document text, un tabel, o lista etc. Aceasta sursa de date reprezinta componenta din a carei suprafata
se va vizualiza doar o anu mita portiune la un moment dat, cu posibilitatea de derulare.
Pentru a realiza derularea, JScrollPane pune la dispozitie doua bare de derulare si un container
JWiewport , care reprezinta zona prin care se vizualizeaza componenta -continut, ce poarta denumirea de
“vedere ” (“view ”).
Dintre constructorii clasei JScrollPane mentionam:
– JScrollPane () creaza un panou de derulare cu cele doua bare de derulare (orizontala si
verticala) fara a fi precizata componenta (numita “view”) care va fi adaugata in p anou pentru a se
permite derularea ei;
– JScrollPane (Component <vedere>) creaza un panou de derulare cu cele doua bare de derulare
(orizontala si verticala) in care este adaugata si componeta “view” ce va putea fi derulata in containerul
JScrollPane .
Dintre metodele clasei mai des folosite mentionam:

void setViewportView (Component <vedere>) a clasei JScrollPane stabileste componenta “view”
precizata in parametrul <vedere> care va fi supusa mecanismului de “scroll” atunci cand ea nu se poate
vizualiza in intregime; aceasta metoda se foloseste daca nu s -a creat un JScrollPane care sa aiba, deja,
inclusa componenta “view”;
void setHorizontalScrollBarPolicy (int <politica_derularii>) stabileste politica de aparitie a barei
orizontale de defilare atunci cand s e vizualizeaza componenta “view”; se poate folosi, ca parametru, o
constanta a clasei JScrollPane , care indica faptul ca aceasta bara de defilare va aparea intodeauna
pentru componenta “view;
void setVertical ScrollBarPolicy () stabileste politica de apari tie a barei verticale de defilare atunci
cand se vizualizeaza componenta “view”; se poate folosi, ca parametru ,o constanta a clasei JScrollPane ,
care indica faptul ca aceasta bara de defilare va aparea intodeauna pentru componenta “view;
Nota : In mediul d e dezvoltare NetBeans se pot folosi proprietatile horizontalScrollBarPolicy sau
vertical ScrollBarPolicy din fereastra Properties pentru obiectul JScrollPane creat. Odata setata
proprietatea, codul de apel al metodelor este generat automat in metoda initCom ponents ().
De exemplu, obiectele de tip JTextArea nu se afiseaza pe fereastra in mod direct, ci prin intermediul unui
obiect de tip JScrollPane . In secventa de cod ce urmeaza se prezinta modul de creare a unui obiect
JScrollPane1 si cum se adauga in el un obiect “view” JTextArea1 .
jScrollPane1 = new JScrollPane();
jScrollPane1.setHorizontalScrollBarPolicy
(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS );
jScrollPane1.setVerticalScrollBarPolicy
(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
jTextArea1.setColumns(20);
jTextArea1.setRows(5);
jScrollPane1.setViewportView(jTextArea1);

Curs 14

Cuvinte importante:
-componente elementare: JLabel, JButton, JCheckBox, JRadioButton, JGroupButton, JTex tField,
JTextArea, JComboBox, JList, JTable; constructori si metode pentru componentele elementare;
– meniuri: clasele JMenuBar, JMenu si JMenuItem; constructori si metode pentru meniuri;
– Casete de dialog standard(predefinite) pentru afisare de mesaje si introducere de date de la
tastatura: clasa JOptionPane si metoda Show folosita.

Componente elementare Swing. Utilizarea mediului IDE NetBeans pentru proiectarea si realizarea
functionalitatii componentelor Swing
Deoarece clasa JComponent extinde clasa Container , ea mosteneste functionalitatea generala a
containerelor si componentelor AWT, furnizand o serie intreaga de noi facilitati.
Dintre facilitatile oferite de clasa JComponent mentionam:
– Asocierea de “ ToolTips ” (informatii ajutatoare dependente de context). Folosind metoda
setToolTip () poate fi atasat unei componente un text cu explicatii legate de componenta
respectiva. Cand utilizatorul trece cu mouse -ul deasupra componentei va fi afisat, pentru o
perioada de timp, textul ajutator specificat.
– Stabilirea de c henare . Orice componenta Swing poate avea unul sau mai multe chenare. Specificarea
unui chenar se realizeaza cu metoda setBorder ().
– Extinderea s uport ului pentru pozitionarea si dimensionare a componentel or. Folosind metodele
setPreferredSize (), setMinimumSize (), setMaximumSize (), setAlignmentX (), setAlignmentY () pot fi
controlati parametrii folositi de gestionarii de pozitionare pentru asezarea si dimensionarea automata a
componentelor in cadrul unui cont ainer. In lectia 13 s -au prezentat pe larg aceste proprietati.
– Stabilirea de secvente de taste de accelerare. O secventa de taste de accelerare (key accelerator),
denumita si secventa de prescurtare (keyboard mnemonic), reprezinta o grupare de taste care poate fi
folosita pentru a controla comportamentul unei componente a interfetei utilizator. Aceste taste permit
folosirea unei aplicatii fara ajutorul mouse -ului.
Toate componentele elementare AWT se regasesc si in Swing. In majoritatea cazurilor, co nstructorii
componentelor Swing sunt similari constructorilor AWT. Toate clasele corespunzatoare componentelor
elementare din AWT au acelasi nume in Swing, dar precedat de litera “J”, cum ar fi: JButton , JTextField ,
JLabel , JTextArea etc.
Clasa JLabel
Componentele de acest tip se utilizeaza pentru a afisa texte si imagini, cu rol lamuritor pentru alte
componente.
Dintre constructorii clasei mentionam:
– JLabel () creaza o eticheta care nu are afisat nici text nici imagine;
– JLabel (String <s>) creaza o e ticheta care afiseaza sirul <s>;
– JLabel (Icon <image>) creaza o eticheta care afiseaza un obiect <image>.
Sirul de caractere afisat sau imaginea afisata pe eticheta pot fi adaugati folosind si metodele:
void setText (String <s>)
sau
void setIcon (Icon <image>).

Nota: Crearea unui obiect de tip Icon se realizeaza folosind constructorul
ImageIcon (“<nume_fisier_imagine>”) in felul urmator:
Icon imagine = new ImageIcon (“imagineamea.gif”);
Alinierea continutului unei etichete se poate stabili cu una dintre metodele:
void setHorizontalAlignment (int <aliniament>)
sau
void setVerticalAlignment (int <aliniament>)
in care alinierea este una dintre constantele definite in interfata SwingConstants.
Implicit, textele sunt aliniate la dreapta si imaginile sunt cent rate. Vertical, textul sau imaginea sunt
aliniate centrat.
Clasa JButton
Cu ajutorul acestei clase se creaza butoane de comanda. La apasarea butonului se genereaza un
eveniment care trebuie tratat de programator.
Dintre constructorii clasei mentionam:
– JButton () creaza un buton fara text sau fara imagine asociata;
– JButton (String <text>) creaza un buton pe care este afisat un text;
– JButton (Icon <imagine>) creaza un buton pe care este afisata o imagine.
Clasa JButton este derivata din clasa abstracta AbstractButton si mosteneste toate metodele acestei
clase.
Dintre metodele mai des folosite mentionam:
void setText (String <s>) si void setIcon (Icon <image>) afiseaza un text sau o imagine pe buton.
Aceste metode au fos t descrise la clasa JLabel ;
void setEnabled (boolean <b>) face ca butonul sa fie disponibil (parametrul <b> are valoarea
true) sau indisponibil (parametrul <b> are valoarea false ).
Unui buton i se poate asocia o litera (aceasta va deveni subliniata) in tex tul pe care il are afisat care sa
fie folosita pentru declansarea actiunii produse de buton fara folosirea mouse -ului. Metoda folosita
pentru acest lucru este:
void setMnemonic (char <litera>)
in care <litera > reprezinta litera din textul afisat pe buton care in combinatie cu tasta ALT (pe platforma
Windows) determina declansarea actiunii.
Apelul metodei poate fi de genul:
setMnemonic(‘I’);

Metoda void doClick () executa “clic” de mouse prin programare (automat), fara folosirea mouse -ului.
Clasa JCheckBox
Cu ajutorul acestei clase se creaza butoane a caror stare poate fi setata intre bifat sau nebifat. Daca se
apasa cu mouse -ul un buton de tip JCheckBox acesta va deveni selectat.
Dintre constructorii clasei mentionam:
– JCheckBox () creaza un buton fara text sau fara imagine asociata si neselectat (nebifat);
JCheckBox (String <text>) creaza un buton careia i se asociaza text in partea dreapta si este neselectat
(nebifat);
– JCheckBox (String <text>, boolean <selectat>) creaza un buton careia i se asociaza text in partea
dreapta si este bifat (valoarea true pentru <selectat>) sau nebifat (valoarea false pentru <selectat>);
– JCheckBox (Icon <imagine>) creaza un buton careia i se asociaza o imagine in partea dreapta si
este neselectat;
– JCheckBox (Icon <imagine>, boolean <selectat> ) creaza un buton careia i se asociaza o imagine
in partea dreapta si este bifat (valoarea true pentru <selectat>) sau nebifat (valoarea false pentru
<selectat>).
Dintre metodele mai des folosite mentionam:
boolean isSelected () returneaza starea butonului, adica valoarea true daca butonul este selectat
(bifat) sau valoarea false daca butonul este neselectat (nebifat);
void setSelected (boolean <selectat>) stabileste starea butonului, adica selectat (bifat) daca
parametrul <selectat> are valoarea true sau neselectat (nebifat) daca parametrul <selectat> are valoarea
false .
Observatie: In cazul unui buton JCheckBox se foloseste un interceptor de evenimente de tip ItemListener
pentru a testa daca butonul este sau nu selectat.
Clasa JRadioButton
Obiectele de tip JRadioButton sunt asemanatoare cu cele de tip JCheckBox , negrupate au acelasi
comportament, numai ca arata ca niste butoane radio.
Butoanele pot fi grupate, adica pot fi toate tratate ca un intreg. Avantajul crearii unui grup de butoane
este acela ca se poate selecta numai un singur buton din grup la un moment dat.
Pentru a grupa butoanele se foloseste un obiect al clasei ButtonGroup .
Constructorul clasei ButtonGroup este:
ButtonGroup()
Cele mai importante m etode ale clasei ButtonGroup sunt:
void add(AbstractButton <b>) adauga un buton grupului, unde:

– parametru <b> specifica obiecte de tip AbstractButton , care este superclasa pentru JRadioButton ,
JCheckBox , JButton .
Enumeration getElements () returneaza u n pointer la grupul de butoane;
int getButtonCount () returneaza numarul de butoane din grup.
De exempu, daca dorim sa cream un grup de trei butoane -radio intr -o fereastra de tip JFrame se
procedeaza astfel:
// cream grupul de butoane si cele trei butoane -radio
buttonGroup1 = new javax.swing.ButtonGroup();
jRadioButton1 = new javax.swing.JRadioButton();
jRadioButton2 = new javax.swing.JRadioButton();
jRadioButton3 = new javax.swing.JRadioButton();
//adaugam cele trei butoane -radio la grupul de butoane
buttonGroup1.add(jRadioButton1);
buttonGroup1.add(jRadioButton2);
buttonGroup1.add(jRadioButton3);
In mediul de dezvoltare NetBeans secventa de cod de mai sus este generata au tomat in metoda
initComponents () astfel:
1. Se creaza obiectul buttonGroup1, care este o componenta non -vizuala si de aceea atunci cand
este creata este plasata in tab -ul Other Components din instrumentul Inspector si nu in fereastra
aplicatiei de tip JFrame (analizati fereastra Inspector );
2. Se creaza butoanele -radio care se doresc a fi incluse in buttonGroup1 ;
3. In fereastra Properties la tab -ul Properties , pentru ficare buton -radio se seteaza proprietatea
buttonGroup cu valoarea buttonGroup1.
Compon ente text
Clasa abstracta JTextComponent sta la baza tuturor componentelor text din Swing si este localizata in
pachetul javax.swing.text . Toate componentele text se regasesc in pachetul javax.swing . Vom prezenta
doua dintre acestea : JTextField si JTextAr ea.
1. Clasa JTextField
Aceasta clasa este utilizata pentru introducerea de la tastatura a unor siruri de caractere. Dintre
constructorii clasei mentionam:
– JTextField (String <sir>) creaza o caseta de text care afiseaza implicit sirul de caractere <sir> ;

– JTextField (String <sir>, int <nr>) creaza o caseta de text care afiseaza implicit sirul de caractere
<sir> si care are o latime suficienta pentru a afisa simultan un numar de <nr> caractere.
Dintre metodele cele mai des utilizate mentionam:
String getText () returneaza sirul de caractere din cutia de text;
void setText ( String <sir>) umple cutia de text cu sirul de caractere <sir>.
2. Clasa JTextArea
Aceasta clasa este folosita pentru crearea de cutii de text care permit utilizatorului sa introduca text pe
mai multe linii. Se poate utiliza un singur font de o singura marime ( plain text ).
Obiectele de tip JTextArea nu se afiseaza pe fereastra in mod direct, ci prin intermediul altor obiecte de
tip JScrollPane .
Prezentam trei dintre constructorii clase i:
– JTextArea() creaza o zona de text fara un text afisat;
– JTextArea(String <sir>) creaza o zona de text care afiseaza implicit sirul de caractere <sir>;
– JTextArea(String <sir>, <nr_linii>, <nr_coloane>) creaza o zona de text care afiseaza implicit
sirul de caractere <sir> si are un numar de linii <nr_linii> si un numar de coloane <nr_coloane>.
Dintre metodele mai des utilizate ale clasei JTextArea mentionam:
– void append (String <sir>) adauga la sfarsitul sirului din componenta un alt sir <sir>;
– void insert (String <sir>, int <pozitie>) insereaza, in textul zonei de text, un sir de caractere <sir>
incepand de la pozitia <pozitie>;
– String getText () si void setText (String <sir>) au fost deja prezentate la clasa JTextField ;
-String getSelectedTe xt() returneaza sirul de caractere selectat;
– void setLineWrap (boolean <v>) imparte textul pe mai multe linii in cazul in care acesta nu
incape pe latimea componentei; daca valoarea parametrului este true, afiseaza textul pe o singura linie,
daca parametrul are valoarea false .
Clasa JComboBox
Aceasta componenta combina o caseta de text (care poate fi sau nu editabila) cu o lista expandabila la
cerere din care utilizatorul poate sa selecteze o singura optiune la un moment dat.
Aceasta componenta are atasat un model de date care reprezinta structura de date atasata pentru
continutul ei. Java pune la dispozitie pentru componenta JComboBox un model de date implicit oferit de
clasa DefaultComboBoxModel care implementeaza interfata ComboBoxModel si interfata
MutableComboBoxModel , ce fac posibile operatiile de adaugare, stergere si modificare in mod dinamic a
continutului componentei JComboBox .

Modelul de date atasat componentei JComboBox poate fi construit si explicit ca instanta de tip
ComboBoxModel .
Dintre constructorii clasei JComboBox mentionam:
– JComboBox () construieste un obiect J ComboBox cu un model de date implicit oferit de Java,
care nu contine, initial, nici un element in lista; elementele vor f i adaugate ulterior prin apelul metodei
addItem () in cadrul programului;
-JComboBox (ComboBoxModel <model>) construieste un obiect J ComboBox cu un model de
date explicit, dat de parametrul <model>, creat de programator si folosit pentru incarcarea continut ului
listei.
Mediul IDE NetBeans da posibilitatea setarii modelului de date pentru componenta vizuala JComboBox ,
ceea ce inseamna o facilitate deosebita. Pentru a seta modelul de date se foloseste fereastra Properties ,
tab-ul Properties , din care se select eaza proprietatea model . Dupa executia unui click pe butonul din
dreapta acestei proprietati care are afisat pe el trei puncte (…), apare fereastra pentru setarea modelului
componentei JComboBox :

Elementele listei se creaza implicit, atunci cand se creaza lista (prin tragere cu mouse -ul a obiectului de
tip JComboBox din fereastra Palette ). Ele se pot sterge complet (ca in fereastra de mai sus) si atunci
elementele listei se vor adauga dinamic prin program asa cum se va vedea in continuare.
O alta varianta este sa modificam textul afisat pe fiecare element al listei si, eventual sa adaugam, in
fereastra de mai sus, elemente la lista de tip JComboBox creata si astfel se va genera automat codul –
sursa de apel al metodei setModel (), in metoda initComponent () din clasa de tip JFrame a aplicatiei.
Acasta lista este insa o lista fixa.
Dintre metodele folosite mai des in lucru cu JComboBox prezentam:
void addItem (Object <element>) adauga listei un element ( optiune); parametrul <element>
poate fi o referinta catre orice obiect, inclusiv catre tipul des utilizat String ;
Object getSelectedItem () returneaza sirul de caractere corespunzator optiunii selectate (trebuie
realizata conversia explicita de tip daca s e doreste sa se obtina un obiect de tip String );

void setSelectedItem (Object <element>) seteaza optiunea data in parametrul <element> ca
element selectat, care apare in cutia de text a JComboBox ;
int getItemCount () returneaza numarul de elemente din list a;
int getSelectedIndex () returneaza indexul optiunii selectate;
Object getItemAt (int <index>) returneaza obiectul retinut de elementul de indice dat de
parametrul <index> (trebuie realizata conversia explicita de tip daca se doreste sa se obtina un ob iect de
tip String );
ComboBoxModel getModel () returneaza modelul de date folosit;
void setModel (<model>) stabileste modelul creat de programator care va fi folosit pentru
reprezentarea continutului listei;
void setMaximumRowCount (int <nr_linii>) stabile ste numarul maxim de linii care vor fi afisate
din lista;
O componenta JComboBox poate genera doua tipuri de evenimente si anume: ItemEvents si
ActionEvents .
Secventa de cod urmatoare arata cum se poate crea un obiect JComboBox plecand de la modelul de
date implicit. Obiectul JComboBox creat nu contine initial nici un element. Elementele din lista sunt
create dinamic in timpul executiei programului, dar toata lista are o dimensiune fixa si elementele listei
sunt specificate in program. De asemenea, se prezi nta si secventa de cod care realizeaza selectia unui
element din lista.
Crearea si initializarea obiectului jComboBox1 :
private javax.swing.JComboBox jComboBox1;
jComboBox1 = new javax.swing.JComboBox();
jComboBox1.setMaximumRowCount(10);
jComboBox1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
selectareCombo(evt);
}
});
Umplerea obiectului JComboBox1 cu o lista fixa de e lemente:
jComboBox1.addItem("Matematica");
jComboBox1.addItem("Informatica");
jComboBox1.addItem("Engleza");

jComboBox1.addItem("Alte materii");
jComboBox1.setVisible(true);
validate();
pack();
Select area unui element din lista obiectului jComboBox1 implementand o metoda actionPerformed a
interfetei ActionListener pentru lista:
private void selectareCombo(java.awt.event.ActionEvent evt) {
jLabel2.setText("Element selectat din JComboBox");
jLabel1.setText((String)jComboBox1.getSelectedItem());
pack();
validate();
}
Observatie : Orice eveniment care este atasat unei componente elementare poate fi tratat prin
intermediul unui interceptor, folosind interfata NetBeans care genereaza automat cod pentru crearea
interceptorului de evenimente, iar programatorul nu are de facut decat sa introduca codul asociat
tratarii evenimentului selectat. Selectarea metodei prin care se trateaza evenimentul se face in fereastra
Properties , la tab -ul Events .
Secventa de cod urmatoare arata cum se poate crea un obiect JComboBox plecand de la modelul de
date implicit. Obiectul JComboBox creat nu contine initial nici un element. Elementele din lista sunt
create dinamic in timpul executiei programului, dar toata lista are o dimensiune variabila si elementele
listei sunt specificate de utilizatorul aplicatiei de la tastatura.
Umplerea obie ctului JComboBox1 cu o lista variabila de elemente introduse de la tastatura de catre
utilizator:
String [] siruri = new ItemLista("JCOMBO").umpleLista();
if (siruri != null){
for (int i=0;i<siruri.length;i++)
jComboBox1.add Item(siruri[i]);
jComboBox1.setVisible(true);
validate();
pack();}
Clasa ItemLista in care este definita metoda umpleLista () a fost creata de programator si este descrisa in
continuare:

class ItemLista {
int nr;
String[] sir;
String tipLista;
public ItemLista(String tipLista) {
this.tipLista = tipLista;
}
public String[] umpleLista (){
String raspuns = javax.swing.JOptionPane.showInputDialog(null, "Introduceti nr de item -uri pentru "
+ tipLista, "Introducere de date", javax.swing.JOptionPane.INFORMATION_MESSAGE);
try {
if (raspuns != ""){
nr = Integer.parseInt(raspuns);
sir = new String[nr];
for (int i=0;i<nr;i++)
sir[i] =javax.swing.JOptionPane.showInputDialog(null, "Introduceti item -uri pentru " + tipLista,
"Introducere de date" + tipLista, javax.swing.JOptionPane.INFORMATION_MESSAGE);
return sir;}
else {
javax.swing.JOptionPane.showMessageDialog(null, "Nu ati introdus numarul de item -uri",
"Erori", javax.swing.JOptionPane.ERROR_MESSAGE);
return null;}
}
catch(Exception e){
javax.swing.JOptionPane.showMessageDialog( null, "Nu ati introdus numarul de item -uri", "Erori",
javax.swing.JOptionPane.ERROR_MESSAGE);
return null;
}
}
}

Observatie : Clasa JOptionPane folosita, in clasa ItemLista , pentru citirea datelor de la tastatura si
afisarea unor mesaje de informare va fi prezentata mai tarziu in acesta lectie.
Clasa JList
Este folosita pentru crearea unei liste care permite utilizatorului sa aleaga un element (optiune) din
cadrul ei. Obiectele de tip JList nu se afiseaza pe fereastra in mod direct, ci prin intermediul altor obiecte
de tip JScrollPane .
Continutul unei liste este gestionat printr -un model de date care este o instanta de tip ListModel . Este
de subliniat ca JList ofera acces la continutul liste i doar prin intermediul modelului de date asociat.
Java pune la dispozitie pentru componenta JList un model de date implicit oferit de clasa
AbstractListModel care implementeaza interfata ListModel , permitand programatorului sa aleaga
structura de date in care sa pastreze continutul listei.
Modelul de date atasat componentei JList poate fi construit si explicit ca instanta de tip ListModel .
Dintre constructorii clasei JList mentionam:
– JList () construieste un obiect J List fara un model de date atasat cont inutului listei; stabilirea
modelului se face ulterior prin apelul metodei setModel ();
– JList (ListModel <model>) construieste un obiect J List cu un model de date explicit, dat de
parametrul <model>, creat de programator si folosit pentru incarcarea cont inutului listei.
Mediul IDE NetBeans da posibilitatea setarii modelului de date pentru componenta vizuala JList, ceea ce
inseamna o facilitate deosebita. Pentru a seta modelul de date se foloseste fereastra Properties , tab -ul
Properties , din care se select eaza proprietatea model . Dupa executia unui click pe butonul din dreapta
acestei proprietati care are afisat pe el trei puncte (…), apare fereastra pentru setarea modelului
componentei JList:
Elementele listei se creaza implicit, atunci cand se creaza lista (prin tragere cu mouse -ul a obiectului de
tip JList din fereastra Palette ). Ele se pot sterge complet (ca in fereastra de mai sus) si atunci trebuie
setat modelul de date prin program asa cu m se va vedea in continuare.

O alta varianta este sa modificam textul afisat pe fiecare element al listei si, eventual sa adaugam, in
fereastra de mai sus, elemente la lista de tip JLIst creata si astfel se va genera automat codul -sursa de
apel al metode i setModel (), in metoda initComponent () din clasa de tip JFrame a aplicatiei. Acasta lista
este insa o lista fixa.

Dintre metodele folosite mai des in lucru cu JList prezentam:
Object getSelectedValue () returneaza primul element selectat din lista JList sau null daca nu s -a
selectat nici un element (trebuie realizata conversia explicita de tip daca se doreste sa se obtina un
obiect de tip String );
void setSelectedValue (Object <element>, boolean <stare_derulare>) seteaza optiunea data in
parametrul <eleme nt> ca element selectat al listei Jlist, si daca parametru <stare_derulare> are valoarea
true se realizeaza si derularea listei pentru a se vizualiza obiectul selectat;
int getSelectedIndex () returneaza indexul elementului selectat; returneaza valoarea –1 daca nu
este selectat nici un element in lista;
void setSelectedIndex (int <index>) selecteaza elementul avand indicele <index>;
ListModel getModel () returneaza modelul de date atasat listei de elemente afisate prin JList;
void setModel (ListModel <mode l>) seteaza modelul de date atasat listei de elemente afisate
prin JList .
Evenimentul pe care il poate genera o componenta JList este ListSelectionEvent , care se gaseste in
pachetul javax.swing.event si care este generat atunci cand se selecteaza unul dintre elementele listei.
Secventa de cod urmatoare arata cum se poate crea un obiect JList care initial nu are un model de date
asociat si nu contine elemente in lista. Modelul de date este setat in pro gram iar elementele din lista
sunt create dinamic in timpul executiei programului. Toata lista are o dimensiune fixa stabilita prin
modelul de date iar elementele listei sunt specificate in program. De asemenea, se prezinta si secventa
de cod care realizea za selectia unui element din lista de tip JList.
Crearea si initializarea obiectului jList1 :
private javax.swing.JScrollPane jScrollPane3;
private javax.swing.JList jList1;
jScrollPane3 = new javax.swing.JScrollPane();
jList1 = new javax.swing.JList();
jScrollPane3.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AL
WAYS);

jScrollPane3.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS
);
jList1.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));
jList1.addListSelectionListener(new javax.swing.event.ListSelectionListener() {
public void valueChanged(javax.swing.event.ListSelectionE vent evt) {
selectareList(evt);

}
});
jScrollPane3.setViewportView(jList1);
Observatie : Secventa de cod prezentata arata ca obiectul jList1 nu se afiseaza pe fereastra in mod direct,
ci prin intermediul obiectulu i jScrollPane3 .
Stabilirea modelului de date si umplerea obiectului JList1 cu o lista fixa de elemente:
jList1.setModel(new javax.swing.AbstractListModel() {
String [] strings = {"Matematica", "Informatica", "Engleza", "Alte materii"};
public int getSize() { return strings.length; }
public Object getElementAt(int i) { return strings[i]; }
});
jList1.setVisible(true);
jScrollPane3.setVisible(true);
validate();
pack();
Selectarea unui element din lista obiectului jList1 implementand o metoda valueChanged a interfetei
ListSelectionListener pentru lista:
private void selectareList(javax.swing.event.ListSelectionEvent evt) {
jLabel2.s etText("Element selectat din JList");
jLabel1.setText((String)jList1.getSelectedValue());
pack();
validate();
}
Secventa de cod urmatoare arata cum se poate crea un obiect JList care initial nu are un model de date
asociat si n u contine elemente in lista. Modelul de date este setat in program, iar elementele din lista
sunt create dinamic in timpul executiei programului. Lista poate avea o dimensiune variabila specificata
de utilizator de la tastatura, iar elementele listei sunt specificate, de asemenea de utilizatorul aplicatiei
de la tastatura.
Setarea modelului de date atasat obiectului JList1 cu o lista variabila de elemente introduse de la
tastatura de catre utilizator:
jList1.setModel(new javax.swing.AbstractListModel() {

String [] strings = new ItemLista("JLIST").umpleLista();
public int getSize() { if (strings != null) return strings.length; else return 0;}
public Object getElementAt(int i) { if (strings != null) return strings[i]; else return null; }
});
if (jList1.getModel().getSize() != 0)
{
jList1.setVisible(true);
jScrollPane3.setVisible(true);
validate();
pack();
}
Clasa ItemLista in care este definita metoda umpleLis ta() a fost deja prezentata la componenta
JComboBox .
Interfata -utilizator a aplicatiei Java care realizeaza umplerea dinamica a doua liste de tip JComboBox si
JList , cu dimensiuni variabile introduse de la tastatura, in care sunt incluse si secventele de cod aratate
este:

Listingul complet al aplicatiei se prezinta in continuare:
public class TestareComponente2 extends javax.swing.JFrame {
public TestareComponente2() {
initComponents();
}
private void initComponents() {

jButton1 = new javax.swing.JButton();
jScrollPane3 = new javax.swing.JScrollPane();
jList1 = new javax.swing.JList();
jComboBox1 = new javax.swing.JComboBox();
setTitle("Exercitiu -JComboBox si JListBox variabile");
jButton1.setText("umple lista combo si lista List");
jButton1.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseClicked(java.awt.event.MouseEvent evt) {
adaugaItem(evt);
}
});
jScrollPane3.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AL
WAYS);
jScrollPane3.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS
);
jScrollPane3.setVisible(fa lse);
jList1.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));
jList1.setVisible(false);
jScrollPane3.setViewportView(jList1);
jComboBox1.setMaximumRowCount(10);
jComboBox1.setVisible(false);
org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
// pozitionarea componentelor vizuale in fereastra si adaugarea l or in fereastra de tip
// JFrame cu numele TestareComponente2
// codul corespunzator nu mai este prezentat, el este generat automat de
// NetBeans si nu se mai prezinta aici
java.awt.Dimension screenSize = java.awt.Toolkit.getDefault Toolkit().getScreenSize();
setBounds((screenSize.width -320)/2, (screenSize.height -299)/2, 320, 299);
}

private void adaugaItem(java.awt.event.MouseEvent evt) {
adaugaDateLaComboLaLis t();
}
public void adaugaDateLaComboLaList() {
String [] siruri = new ItemLista("JCOMBO").umpleLista();
if (siruri != null){
for (int i=0;i<siruri.length;i++)
jComboBox1.addItem (siruri[i]);
jComboBox1.setVisible(true);
validate();
pack();}
jList1.setModel(new javax.swing.AbstractListModel() {
String [] strings = new ItemLista("JLIST").umpleLista();
public int getSize() { if (strings != null) return strings.length; else return 0;}
public Object getElementAt(int i) { if (strings != null) return strings[i]; else return null; }
});
if (jList1.getModel().getSize() ! = 0)
{
jList1.setVisible(true);
jScrollPane3.setVisible(true);
validate();
pack();
}
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new TestareComponente2().setVisible(true);
}

});}

private javax.swing.JButton jButton1;
private javax.swing.JComboBox jComboBox1;
private javax.swing.JL ist jList1;
private javax.swing.JScrollPane jScrollPane3;
}
// clasa ItemLista a fost descrisa in textul lectiei si nu se mai prezinta aici
Clasa JTable
Cu ajutorul clasei JTable se creaza tabele. Obiectele de tip JTable nu se afiseaz a pe fereastra in mod
direct, ci prin intermediul altor obiecte de tip JScrollPane .
Datorita complexitatii acestei componente, JTable are un pachet dedicat si anume javax.swing.table .
Este de subliniat ca JTable ofera acces la datele continute in tabel doar prin intermediul modelului de
date asociat.
Continutul unui tabel este gestionat de trei modele de date care sunt instante ce implementeza trei
interfete: TableModel , TableColumnModel si ListSelectionModel .
TableModel reprezinta interfata principala care trebuie implementata de o clasa care va gestiona
modelul de date asociat unui tabel.
Swing ofera doua clase care reprezinta implementari implicite ale acestei interfete si care pot fi folosite
pentru crearea modelului de date si anume: AbstractTableM odel si DefaultTableModel .
AbstractTableModel ofera libertatea in alegerea structurii de date care sta la baza modelului.
DefaultTableModel foloseste o structura de date de tip Vector de elemente de tip Vector (Vector este o
clasa de obiecte cu structura de date de tip lista care se afla in pachetul java.util ) si este folosit de
mediul NetBeans pentru crearea modelului de date atasat unui tabel.
Modelul de date atasat componentei JTable poate fi construit si explicit ca instanta de tip TableModel .
Dintre constructorii clasei JTable mentionam:
– JTable () construieste un tabel care este initializat cu modelul de date implicit pentru tabel,
model implicit pentru coloane si modelul implicit pentru selectie;
– JTable (int <nr_linii>, <nr_coloane>) construieste un tabel cu dimensiunile <nr_linii> si
<nr_coloane> avand celule goale si drept model de date DefaultTableModel ;
– JTable (Object [][] <linii_de _date>, Object[] <nume_coloane>) construieste un tabel pentru
vizualiza rea unei matrice data prin parametrul <linii_de_date> si avand numele coloanelor date prin
parametrul <nume_coloane>;

– JTable (TabelModel <model>) construieste un tabel avand modelul de date precizat in
parametrul <model>.
Am precizat ca interfata TableM odel sta la baza modelelor de date pentru tabele. De asemenea, clasa
DefaultTableModel este folosita, implicit, pentru crearea modelului de date al unui tabel, daca folosim
mediul IDE NetBeans.
Vom discuta in continuare despre modele de date asociate tabe lelor create pe baza clasei
DefaultTableModel.
Dupa cum am mentionat mediul IDE NetBeans da posibilitatea setarii modelului de date pentru
componenta vizuala JTable , ceea ce inseamna o facilitate deosebita. Pentru a seta modelul de date se
foloseste ferea stra Properties , tab -ul Properties , din care se selecteaza proprietatea model . Dupa
executia unui click pe butonul din dreapta acestei proprietati care are afisat pe el trei puncte (…), apare
fereastra pentru setarea modelului componentei JTable :

Modelul tabelului se poate crea implicit, atunci cand se creaza tabelul (prin tragere cu mouse -ul a
obiectului de tip JTable din fereastra Palette ). Liniile pot fi setate la zero (ca in fereastra de mai sus) si
atunci numarul lor se stabileste dinamic pri n program asa cum se va vedea in continuare. Dar oricum se
genereaza automat cod -sursa de apel al metodei setModel (), in metoda initComponent () din clasa de
tip JFrame a aplicatiei.
O alta varianta este ca, in fereastra de mai sus, sa stabilim un numar de linii si coloane dorite pentru
tabel, sa stabilim numele coloanelor tabelului si astfel se va genera automat codul -sursa de apel al
metodei setModel (), in metoda initComponent () din clasa de tip JFrame a aplicatiei. Acasta lista este
insa o lista fixa.
Dintre metodele folosite mai des in lucru cu instante de modele de date ale clasei DefaultTableModel
prezentam:
void setColumnIdentifiers (Object [] <nume_noi_coloane>) seteaza numele c oloanelor tabelului;
boolean isCellEditable (int <index_linie>, int <index_coloana>) returneaza numai valoarea true
indiferent de parametrii dati, ceea ce inseamna ca toate celulele tabelului pot fi editate; daca se doreste
sa se inhibe editatrea celulelo r, metoda trebuie suprascrisa; suprascrierea metodei este realizata
automat de mediul NetBeans la crearea tabelului daca se doreste acest lucru;

void setRowCount (int <nr_linii>) seteaza numarul de linii ale tabelului dat de parametrul
<nr_linii>;
void setColumnCount (int <nr_coloane>) seteaza numarul de coloane ale tabelului dat de
parametrul <nr_coloane>;
Dintre metodele folosite mai des in lucru cu obiecte de tip JTable mentionam:
TableModel getModel () returneaza modelul de date asociat cu obiectul JTable;
Object getValueAt (int <nr_linie>, int <nr_coloana>) returneaza o referinta la obiectul memorat
de celula respectiva; trebuie realizata conversia explicita de tip daca se doreste sa se obtina un obiect de
tip String si apoi trebuie aplicata o metoda d e conversie la tipul de data dorit;
void setValueAt (Object <valoare>, int <nr_linie>, int <nr_coloana>) seteaza referinta la obiectul
<valoare> pentru linia data de <nr_linie> si coloana data de <nr_coloana>;
Secventa de cod urmatoare arata cum se poate c rea un obiect JTable care initial are un model de date
asociat cu doua coloane si zero linii. Modelul de date nu permite editarea celulelor din tabel. Modelul
de date este apoi modificat in program astfel: se schiba numele coloanelor tabelului si se setea za
dinamic numarul de linii ale tabelului in timpul executiei programului.
Crearea si initializarea obiectului jTable1 si setarea modelului de date asociat:
jScrollPane1 = new javax.swing.JScrollPane();
jTable1 = new javax.swing.JTable();
jScrollPane1.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AL
WAYS);
jScrollPane1.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS
);
jTable1.setModel(new javax.swing.table.Defau ltTableModel (
new Object [][] { }, new String [] { "Title 1", "Title 2"})
{
boolean[] canEdit = new boolean [] {
false, false
};
public boolean isCellEditable(int rowIndex, int columnIndex) {
return canEdit [columnIndex];
}
});

jScrollPane1.setViewportView(jTable1);
Observatie : Secventa de cod prezentata arata ca obiectul jTable1 nu se afiseaza pe fereastra in mod
direct, ci prin interm ediul obiectului jScrollPane1 .
Setarea prin cod -sursa a numarului de linii ale tabelului si umplerea celulelor tabelului cu valori rezultate
din calculul unei functii matematice:
private void calculFunctie(java.awt.event.MouseEvent evt) {
try {
javax.swing.table.TableModel model = jTable1.getModel();
javax.swing.table.DefaultTableModel modelImp = (javax.swing.table.DefaultTableModel)model;
modelImp.setColumnIdentifiers(new String [] {"x","f(x)"});
int n = (int)((Float.parseFloat(jTextField2.getText()) –
Float.parseFloat(jTextField1.getText()))/Float.parseFloat(jTextField3.getText())+ 1);
float pas = Float.parseFloat(jTextField3.getText());
float X1 = Float.parseFloat(jTextFiel d1.getText());
float X2 = Float.parseFloat(jTextField2.getText());
modelImp.setRowCount(n);
int i= 0;
int j =0 ;
for (float X = X1; X <= X2; X+=pas)
{
double F = Math.pow(X,2)+ 1;
j = 0;
jTable1.setValueAt(new Float(X),i,j);
j = 1;
jTable1.setValueAt(new Float(F),i,j);
i++;
}
}
catch(Exception e) {

javax.swing.JOptionPane.showMessageDialog(this, "Nu ati introdus un numar", "Erori",
javax.swing.JOptionPane.ERROR_MESSAGE);
}
jTable1.setVisible(true);
jScrollPane1.setVisible(true);
validate();
pack();
}
Interfata -utilizator a aplicatiei Java care realizeaza calculul valorilor unei functii matematice simple (x2 +
1) pentru care x apartine intr -un interval dat de la tastatura si in care sunt incluse si secventele de cod
aratate este:

Daca se dor este crearea unui tabel care sa contina un numar fix de linii si de coloane care nu se modifica
in timpul executiei programului, atunci se poate apela la mediul NetBeans, prin setarea proprietatii
model din fereastra Properties cu numarul de linii si de co loane dorite. De precizat este ca celulele
tabelului creat sunt implicit editabile. Dupa stetarea modelului tabelului mediul NetBeans genereaza
automat cod -sursa pentru crearea, initializarea si apelul metodei setModel () ca mai jos:
jScrollPane1 = new java x.swing.JScrollPane();
jTable1 = new javax.swing.JTable();
jTable1.setModel(new javax.swing.table.DefaultTableModel(
new Object [][] {

{null, null, null, null},
{null, null, null, null},
{null, null, null, null}
},
new String [] {
"A", "B", "C", "D"
}
));
jScrollPane1.setViewportView(jTable1);
Codul -sursa pentru extragerea (citirea) valorilor din celulele t abelului creat si stocarea lor intr -o matrice
A de tip MatriceOperatii se arata in continuare:
MatriceOperatii A = new MatriceOperatii(3,4);
for (int i=0;i<3;i++)
for(int j=0;j<4;j++)
A.setElement(i,j, Integer.parseInt((( String)(jTable1.getValueAt(i,j)))));
Metoda setElement () este o metoda a clasei MatriceOperatii care deriveaza din clasa Matrice . Pentru
intelegere se prezinta codul -sursa si pentru aceste doua clase:
public class Matrice {
int n, m;
int [][] elem ente;
public Matrice(int lin, int col){
n = lin;
m = col;
elemente = new int [n][m];
}
public void afisare(){
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
System.out.println(" "+elemente[ i][j]);

}
}
class MatriceOperatii extends Matrice {
public MatriceOperatii(int l, int c){
super(l,c);
}
public MatriceOperatii produs(MatriceOperatii y) {
int np = n;
int mp = y.m;
MatriceOperatii z = new MatriceOperatii(np,mp);
for (int i=0;i<np;i++)
{
for(int j=0;j<mp;j++)
{
z.elemente[i][j]=0;
for(int k=0;k<m;k++)
{
z.elemente[i][j]=z.elemente[i][j]+elemente[i][k]*y.elemente[k][j];
}
}
}
return z;
}
public MatriceOperatii suma(MatriceOperatii y){
int np = n;
int mp = m;
MatriceOperatii z = new Matr iceOperatii(np,mp);
for (int i=0;i<np;i++)
for(int j=0;j<mp;j++)

z.elemente[i][j]= elemente[i][j]+y.elemente[i][j];
return z;
}
public void setElement(int i, int j, int valoare){
elemente[i][j] = valoare;
}
public int getElement(int i, int j){
return elemente[i][j];
}
}
Clasele JMenuBar, JMenu si JMenuItem
In Java meniurile se construiesc prin utilizarea obiectelor din clasele:
1) JMenuBar folosita pentru a obtine bare de meniuri aflate in partea de sus a ferestrei;
2) JMenu folosita pentru a crea optiuni in bara de meniuri; aceste optiuni pot contine la randul lor
alte optiuni;
3) JMenuItem folosita pentru a crea optiuni in meniurile de tip JMen u continute in bara de meniuri
Are rolul unui buton, adica optiunea selectata conduce la o anumita actiune.
Clasa JMenuBar
Are constructorul:
JMenuBar() construieste o bara de meniuri in partea de sus a ferestrei.
Metoda cea mai importanta a acestei cla se este
JMenu add(Jmenu <meniu>) adauga la bara de meniuri componente de tip JMenu .
Clasa JMenu
Are mai muti constructori printre care mentionam:
– JMenu() construieste un meniu fara a afisa un text pe el;
– JMenu(String <text>) construieste un meni u care are afisat un text.
Dintre metode mai importante sunt:
JMenuItem add(JMenuItem <optiune>) adauga o componenta de tip JMenuItem ;

Component add(Component <c>) adauga o alta componenta (de un tip derivat din tipul
Component ).
Clasa JMenuItem
Are mai muti constructori printre care mentionam:
– JMenuItem() construieste o optiune care nu afiseaza nimic;
– JMenuItem(String <text>) construieste o optiune care afiseaza sirul <text>;
– JMenuItem(String <s>, Icon <ic>) construieste o optiune care afiseaza un text si o mica
imagine.
Secvența următoare de cod arată cum se construiește o bară de meniuri cu un meniu și două opțiuni
pentru acest meniu. Mai jos se prezinta si fereastra care contine bara de meniuri construita.

private javax.swing.JMenu jMenu1;
private javax.swing.JMenuBar jMenuBar1;
private javax.swing.JSeparator jSeparator1;
private javax.swing.JMenuItem meniu11;
private javax.swing.JMenuItem meniu12;
jMenuBar1 = new javax .swing.JMenuBar();
jMenu1 = new javax.swing.JMenu();
meniu11 = new javax.swing.JMenuItem();
jSeparator1 = new javax.swing.JSeparator();
meniu12 = new javax.swing.JMenuItem();
jMenu1.setText("Exemple de componente grafice");
meniu11.setAcce lerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_F,
java.awt.event.InputEvent.CTRL_MASK));
meniu11.setText("Exercitiu -JComboBox si JListBox fixe");

meniu11.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
comboListFixe(evt);
}
});
jMenu1.add(meniu11);
jMenu1.add(jSeparator1);
meniu12.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.a wt.event.KeyEvent.VK_V,
java.awt.event.InputEvent.CTRL_MASK));
meniu12.setText("Exercitiu – JComboBox si JListBox variabile");
meniu12.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt. event.ActionEvent evt) {
comboListVariabile(evt);
}
});
jMenu1.add(meniu12);
jMenuBar1.add(jMenu1) ;
setJMenuBar(jMenuBar1 );
private void comboListVariabile (java.awt.event.ActionEvent evt) {
new TestareComponente2().setVisible(true);
}
private void comboListFixe (java.awt.event.ActionEvent evt) {
new TestareComponente1().setVisible(true);
}
Observatie: Codul prezentat este generat automat de mediul NetBeans atunci cand se proiecteaza bara
de meniuri in fereastra de proiectare (Design) a aplicatiei Java.
Pentru a atasa bara de meniuri unei ferestre de tip JFrame se foloseste o metoda a acestei clase si
anume:
void setJMenuBar (JMenuBar <b>).

In multe aplicatii, anumite optiuni din meniuri sunt inzestrate cu acceleratori (shortcut -uri de meniu)
prin care o anumita comanda se poat e obtine fie din meniu, fie dintr -o combinatie de taste. Si in Java se
pot crea acceleratori.
Principala metoda folosite pentru a seta un accelerator la o optiune de meniu este:
void setAccelerator (KeyStroke <tasta>) ataseaza un accelerator la un obiect de tip JMenuItem ;
Pentru a obtine parametrul <tasta> de tip KeyStroke care poate fi o combinatie de taste se foloseste
metoda getKeyStroke (int <cod_tasta>, int <modificator>) unde: <cod_tasta> reprezinta o constanta a
clasei KeyEvent , iar <modificator> este o constanta a clasei ActionEvent .
Pentru setarea unui accelerator se poate folosi mediul NetBeans, care pune la dispozitie proprietatea
accelerator ce poate fi setata in fereastra Properties pentru fiecare optiune de meniu de tip JMenuItem .
Casete de dialog standard(predefinite) pentru afisare de mesaje si introducere de date de la tastatura
Clasa JOptionPane ofera mai multe metode care pot fi folosite pentru a crea casete de dialog standard:
mici ferestre in care se afiseaza un scurt mesaj sau se int roduc date de la tastatura.
Casetele de dialog standard sunt de patru tipuri:
– ConfirmDialog – o caseta de dialog care pune o intrebare si contine trei butoane: Yes, No, Cancel;
– InputDialog – o caseta de dialog care asteapta introducerea unui text;
– MessageDialog – o caseta de dialog care afiseaza un mesaj;
– OptionDialog – o caseta de dialog care cuprinde toate celelalte trei tipuri.
Pentru crearea uneia din cele patru tipuri de casete de dialog se foloseste metoda show<tip_caseta> () in
care <tip_ca seta> specifica unul din tipurile de casete prezentate mai sus. Toate aceste metode sunt
statice si se afla in clasa JOptionPane .
Crearea casetelor de dialog de confirmare
Crearea casetelor de dialog de confirmare se realizeaza cu metoda:
showConfirmDialog (<componenta_parinte>, <mesaj_afisat>, <titlu_casetei>, <buton_afisat>,
<pictograma_afisata>)
unde:
– <componenta_parinte> – specifica containerul care va fi considerat parintele casetei de dialog;
aceasta informatie este folosita pentru a determina unde se va afisa pe ecran fereastra de
dialog; daca se foloseste valoarea null pentru acest argument sau containerul nu este un obiect
JFrame , caseta de dialog va fi afisata in centrul ecranului.
– <mesaj_afisat> – specifica sirul de text care va fi afisat in caseta;
– <titlul_casetei> – specifica un sir de text care va fi afisat pe bara de titlu;

– <buton_afisat> – specifica ce butoane vor fi afisate in caseta, pe baza constantelor:
YES_NO_CANCEL_OPTION sau YES_NO_OPTION;
– <pictograma_afisata> – specifica tipul pictogramei afisata in caseta care determina tipul casetei
de dialog, pe baza constantelor: ERROR_MESSAGE, INFORMATION_MESSAGE, PLAIN_MESSAGE,
QUESTION_MESSAGE.
Metoda returneaza un intreg care reprezinta una din cele trei valori posibile: YES _OPTION, NO_OPTION,
CANCEL_OPTION.
De exemplu:
int raspuns = JOptionPane.showConfirmDialog(null, “Pot sa adaug o inregistrare in fisierul dvs.”);
Crearea casetelor de dialog de intrare
Crearea casetelor de dialog de intrare se realizeaza cu metoda:
showIn putDialog (<componenta_parinte>, <mesaj_afisat>, <titlu_casetei>, <pictograma_afisata>)
Metoda returneaza un sir de caractere care reprezinta raspunsul utilizatorului.
De exemplu:
String raspuns = JOptionPane.showInputDialog(this, "Introduceti un numar", "Introducere de date",
JOptionPane.INFORMATION_MESSAGE);
Iata cum arata o caseta InputDialog :
Crearea casetelor de dialog pentru afisarea mesajelor
Crearea casetelor de dialog pentru mesaje se realizeaza cu metoda:
showMessageDialog (<componenta_parinte >, <mesaj_afisat>, <titlu_casetei>, <pictograma_afisata>)
Metoda este de tip void deci nu returneaza nimic.
De exemplu:
JOptionPane.showMessageDialog(null, "Nu ati introdus numarul de item -uri", "Erori",
JOptionPane.ERROR_MESSAGE);
Afiseaza, in caseta de dialog cu titlul “”Erori”, mesajul "Nu ati introdus numarul de item -uri” . Iata cum
arata aceasta caseta:

Similar Posts