Sunteți pe pagina 1din 169

Introducere

Scurt istoric
Ce este Java?
Despre aceast carte
Convenii utilizate n aceast carte
Sugestii i reclamaii
Alte surse de informaii
Mulumiri

Scurt istoric
Limbajul Java mpreun cu mediul su de dezvoltare i execuie au
fost proiectate pentru a rezolva o parte dintre problemele actuale ale
programrii. Proiectul Java a pornit cu scopul declarat de a dezvolta
un software performant pentru aparatele electronice de larg
consum. Aceste echipamente se definesc ca: mici, portabile,
distribuite i lucrnd n timp real. De la aceste aparate, ne-am
obinuit s cerem fiabilitate i uurin n exploatare.
Limbajul luat iniial n considerare a fost C++. Din pcate, atunci
cnd s-a ncercat crearea unui mediu de execuie care s respecte
toate aceste condiii s-a observat c o serie de trsturi ale C++ sunt
incompatibile cu necesitile declarate. n principal, problema vine
din faptul c C++ este prea complicat, folosete mult prea multe
convenii i are nc prea multe elemente de definiie lsate la
latitudinea celor care scriu compilatoare pentru o platform sau
alta.
n aceste condiii, firma Sun a pornit proiectarea unui nou limbaj de
programare asemntor cu C++ dar mult mai flexibil, mai simplu i
mai portabil. Aa s-a nscut Java. Printele noului limbaj a fost
James Gostling care v este poate cunoscut ca autor al
editorului emacs i al sistemului de ferestre grafice NeWS. Proiectul
a nceput nc din 1990 dar Sun a fcut public specificaia noului
limbaj abia n 1995 la SunWorld n San Francisco.
Numele iniial al limbajului a fost Oak, numele unui copac care
crete n faa biroului lui James Gostling. Ulterior, s-a descoperit c
numele fusese deja folosit n trecut pentru un alt limbaj de
programare aa c a fost abandonat i nlocuit cu Java, spre deliciul
programatorilor care iubesc cafenelele i aromele exotice.

Ce este Java?
n primul rnd, Java ncearc s rmn un limbaj simplu de folosit
chiar i de ctre programatorii neprofesioniti, programatori care
doresc s se concentreze asupra aplicaiilor n principal i abia apoi
asupra tehnicilor de implementare a acestora. Aceast trstur
poate fi considerat ca o reacie direct la complexitatea
considerabil a limbajului C++.
Au fost ndeprtate din Java aspectele cele mai derutante din C++
precum suprancrcarea operatorilor i motenirea multipl. A fost
introdus un colector automat de gunoaie care s rezolve problema
dealocrii memoriei n mod uniform, fr intervenia
programatorului. Colectorul de gunoaie nu este o trstur nou,
dar implementarea acestuia n Java este fcut inteligent i eficient
folosind un fir separat de execuie, pentru c Java are ncorporate
faciliti de execuie pe mai multe fire de execuie. Astfel, colectarea
gunoaielor se face de obicei n timp ce un alt fir ateapt o operaie
de intrare-ieire sau pe un semafor.
Limbajul Java este independent de arhitectura calculatorului pe
care lucreaz i foarte portabil. n loc s genereze cod nativ pentru o
platform sau alta, compilatorul Java genereaz o secven de
instruciuni ale unei maini virtuale Java. Execuia aplicaiilor Java
este interpretat. Singura parte din mediul de execuie Java care
trebuie portat de pe o arhitectur pe alta este mediul de execuie
cuprinznd interpretorul i o parte din bibliotecile standard care
depind de sistem. n acest fel, aplicaii Java compilate pe o
arhitectur SPARC de exemplu, pot fi rulate fr recompilare pe un
sistem bazat pe procesoare Intel.
Una dintre principalele probleme ale limbajelor interpretate este
viteza de execuie, considerabil sczut fa de cea a limbajelor
compilate. Dac nu v mulumete viteza de execuie a unei astfel
de aplicaii, putei cere mediului de execuie Java s genereze
automat, plecnd de la codul mainii virtuale, codul specific mainii
pe care lucrai, obinndu-se astfel un executabil nativ care poate
rula la vitez maxim. De obicei ns, n Java se compileaz doar
acele pri ale programului mari consumatoare de timp, restul
rmnnd interpretate pentru a nu se pierde flexibilitatea. Mediul
de execuie nsui este scris n C respectnd standardele POSIX,
ceea ce l face extrem de portabil.

Interpretorul Java este gndit s lucreze pe maini mici, precum ar fi


procesoarele cu care sunt dotate aparatele casnice. Interpretorul
plus bibliotecile standard cu legare dinamic nu depesc 300
Koctei. Chiar mpreun cu interfaa grafic totul rmne mult sub
1 Moctet, exact ca-n vremurile bune.
Limbajul Java este orientat obiect. Cu el se pot crea clase de obiecte
i instane ale acestora, se pot ncapsula informaiile, se pot moteni
variabilele i metodele de la o clas la alta, etc. Singura trstur
specific limbajelor orientate obiect care lipsete este motenirea
multipl, dar pentru a suplini aceast lips, Java ofer o facilitate
mai simpl, numit interfa, care permite definirea unui anumit
comportament pentru o clas de obiecte, altul dect cel definit de
clasa de baz. n Java orice element este un obiect, n afar de
datele primare. Din Java lipsesc funciile i variabilele globale. Ne
rmn desigur metodele i variabilele statice ale claselor.
Java este distribuit, avnd implementate biblioteci pentru lucrul n
reea care ne ofer TCP/IP, URL i ncrcarea resurselor din reea.
Aplicaiile Java pot accesa foarte uor reeaua, folosindu-se de
apelurile ctre un set standard de clase.
Java este robust. n Java legarea funciilor se face n timpul
execuiei i informaiile de compilare sunt disponibile pn n
momentul rulrii aplicaiei. Acest mod de lucru face ca sistemul s
poat determina n orice moment neconcordana dintre tipul referit
la compilare i cel referit n timpul execuiei evitndu-se astfel
posibile intruziuni ruvoitoare n sistem prin intermediul unor
referine falsificate. n acelai timp, Java detecteaz referinele nule
dac acestea sunt folosite n operaii de acces. Indicii n tablourile
Java sunt verificai permanent n timpul execuiei i tablourile nu se
pot parcurge prin intermediul unor pointeri aa cum se ntmpl n
C/C++. De altfel, pointerii lipsesc complet din limbajul Java,
mpreun cu ntreaga lor aritmetic, eliminndu-se astfel una din
principalele surse de erori. n plus, eliberarea memoriei ocupate de
obiecte i tablouri se face automat, prin mecanismul de colectare de
gunoaie, evitndu-se astfel ncercrile de eliberare multipl a unei
zone de memorie.
Java este un limbaj cu securitate ridicat. El verific la fiecare
ncrcare codul prin mecanisme de CRC i prin verificarea
operaiilor disponibile pentru fiecare set de obiecte. Robusteea este
i ea o trstur de securitate. La un al doilea nivel, Java are
incorporate faciliti de protecie a obiectelor din sistem la scriere
3

i/sau citire. Variabilele protejate ntr-un obiect Java nu pot fi


accesate fr a avea drepturile necesare, verificarea fiind fcut n
timpul execuiei. n plus, mediul de execuie Java poate fi configurat
pentru a proteja reeaua local, fiierele i celelalte resurse ale
calculatorului pe care ruleaz o aplicaie Java.
Limbajul Java are inclus suportul nativ pentru aplicaii care
lucreaz cumai multe fire de execuie, inclusiv primitive de
sincronizare ntre firele de execuie. Acest suport este independent
de sistemul de operare, dar poate fi conectat, pentru o performan
mai bun, la facilitile sistemului dac acestea exist.
Java este dinamic. Bibliotecile de clase n Java pot fi reutilizate cu
foarte mare uurin. Cunoscuta problem a fragilitii superclasei
este rezolvat mai bine dect n C++. Acolo, dac o superclas este
modificat, trebuie recompilate toate subclasele acesteia pentru c
obiectele au o alt structur n memorie. n Java aceast problem
este rezolvat prin legarea trzie variabilelor, doar la execuie.
Regsirea variabilelor se face prin nume i nu printr-un
deplasament fix. Dac superclasa nu a ters o parte dintre vechile
variabile i metode, ea va putea fi refolosit fr s fie necesar
recompilarea subclaselor acesteia. Se elimin astfel necesitatea
actualizrii aplicaiilor, generat de apariia unei noi versiuni de
bibliotec aa cum se ntmpl, de exemplu, cu MFC-ul Microsoft (i
toate celelalte ierarhii C++).

Despre aceast carte


Aceast carte a fost scris pentru a veni n sprijinul acelora care
doresc s programeze n limbajul Java. Spre deosebire de
majoritatea crilor existente la ora actual pe piaa internaional,
nu prea multe de altfel, cartea de fa se focalizeaz asupra
facilitilor pe care le ofer noul limbaj, lsnd pe planul al doilea
descrierea bibliotecilor standard, impresionante de altfel, definite de
ctre Sun i colaboratorii acestuia. Alegerea a fost fcut din
convingerea c bibliotecile vin i trec, se dezvolt, n timp ce
limbajul rmne.
Cartea se adreseaz n acelai timp nceptorilor i programatorilor
profesioniti. nceptorii vor gsi n prima parte noiuni
fundamentale necesare oricrui programator. Profesionitii, n
schimb, vor gsi o referin complet a limbajului Java.

Prima parte a crii i introduce cititorul pas cu pas n


fundamentele funcionrii i programrii calculatoarelor tratnd la
un nivel accesibil noiuni precum memoria i procesorul, datele i
instruciunile, clasele de obiecte mpreun cu trsturile
fundamentale ale programrii orientate obiect.
Partea a doua a crii prezint limbajul Java n detaliu mpreun cu
o serie de exemple simple. Aceast parte este conceput pentru a fi
n acelai timp o introducere n sintaxa Java pentru cei care au
programat deja i o introducere n constrngerile sintactice i
semantica unui limbaj de programare pentru nceptori.
Partea a treia a crii prezint cteva dintre aspectele fundamentale
ale programrii n Java precum aplicaiile, apleturile, pachetele de
clase, firele de execuie i tratarea excepiilor. Aceast parte este
conceput de sine stttoare i poate servi ca exemplu de
programare n Java. Fiecare seciune din aceast parte conine
exemple extinse de aplicaii scrise n Java, comentate n surs i n
afara acesteia.
Cititorul nceptor n ale programrii trebuie s parcurg cartea de
la nceput pn la sfrit pentru a putea intra treptat n tainele
programrii n general i ale limbajului Java.
Pentru cititorii avansai, prima parte nu constituie un interes major
i poate fi srit fr implicaii majore n nelegerea materialului
din prile urmtoare. Aceti cititori pot s treac direct la partea a
treia pentru a urmri exemplele i abia dup aceea s revin la
partea a doua pentru informaii detaliate asupra sintaxei i
facilitilor Java. Partea a doua poate fi folosit i pe post de
referin.
O singur excepie: ultima seciune din prima parte introduce
noiunea de interfa, puin cunoscut programatorilor n alte
limbaje dect Java. Este util ca aceast seciune s fie consultat de
ctre toi cititorii, indiferent de nivelul de pregtire n care se afl.

Convenii utilizate n aceast carte


Pentru descrierea sintacticii limbajului Java, am apelat la
urmtoarele convenii obinuite de reprezentare a regulilor
gramaticale:

Cuvintele rezervate ale limbajului Java sunt scrise n caractere


ngroate, ca: while, do, final.
Cuvintele care in locul construciilor reale ale programului
sunt scrise cu caractere oblice, ca n:
if(Condiie) Instruciune1 else Instruciune2

Condiie, Instruciune1 i Instruciune2, care apar n descriere,


trebuiesc nlocuite cu condiiile adevrate, respectiv cu
instruciunile adevrate care trebuiesc executate n funcie de
condiie. De exemplu, o construcie real, care respect
descrierea de mai sus ar putea fi:
if( i < j )
min = i;
else
min = j;

O list de termeni separai prin caractere |, se poate nlocui cu


oricare dintre termenii listei.
De exemplu:
public | private | protected

nseamn c n locul acestui termen poate s apar oricare


dintre cuvintele rezervate specificate n
list, public, private sau protected.

Un termen pus ntre paranteze ptrate este opional. De


exemplu, n descrierea:
Tip NumeVariabil [Iniializator] ;
Partea de Iniializator poate s lipseasc.

Dac, dup un termen apare caracterul *, acesta reprezint


faptul c termenul se poate repeta de un numr arbitrar de
ori, eventual niciodat. De exemplu, n:
class NumeClas ClauzImplements*
caracterul * reprezint faptul c termenul notat
prinClauzImplements se poate repeta de un numr
arbitrar de ori, eventual niciodat.

Pe marginea din stnga a paginii, vei ntlni o serie de


simboluri grafice, cu specificaie precis, care v vor
permite s navigai mai uor n interiorul crii. Iat
semnificaia acestora:
Semnul din stnga reprezint faptul c n paragraful marcat
introducedefiniia unui nou termen. Termenul nou introdus este
reprezentat n interiorul semnului i este scris cu caractere oblice n
textul paragrafului. n cazul de fa cuvntul nou introdus este
cuvntul definiia. Atunci cnd gsii o trimitere la un paragraf
pentru explicaii, cutai acest semn pe margine pentru a gsi mai
repede definiia noiunii dorite.
Semnul din stnga reprezint o trimitere napoi ctre o noiune deja
prezentat n partea de fundamente. Aceast trimitere conine
deasupra simbolului grafic numele noiunii pe care trebuie s l
cutai ntr-un simbol de definiie, i sub simbolul grafic numrul
paragrafului unde se afl definiia. Cititorul nceptor ca i cel
avansat poate urma aceste trimiteri pentru a-i mprospta
cunotinele sau pentru a se familiariza cu cuvintele sau expresiile
folosite pentru a desemna noiuni greu traductibile.
Semnul din stnga reprezint o referire n avans a unei noiuni care
va fi introdus mai trziu. Acest semn este destul de rar n
interiorul crii, dar este totui nevoie de el pentru a face referire la
anumite faciliti care i gsesc cel mai bine locul n paragraful n
care apare semnul. Putei sri fr probleme aceste precizri la
prima citire a capitolului i s le luai n seam doar atunci cnd
folosii cartea pe post de referin pentru limbajul Java.
Semnul din stnga reprezint referirea unei noiuni care nu este
descris n carte. Acest semn apare atunci cnd se face o referin
la una din clasele standard ale mediului Java. Putei gsi informaii
exacte despre clasa respectiv la adresa www.javasoft.com, sau
putei ncrca din Internet o documentaie complet prin ftp de la
adresa ftp.javasoft.com, directorul/docs.
Semnul din stnga reprezint o trimitere ctre alt carte, n care
noiunile din paragraf sunt prezentate mai pe larg. Am folosit acest
semn doar de dou ori, pentru a trimite ctre o carte disponibil la
aceeai editur cu cartea prezent, despre HTML, scris de Dumitru
Rdoiu. O putei gsi pe prima poziie n bibliografie.

Sugestii i reclamaii
7

Posibilele erori care s-au strecurat n aceast carte cad n sarcina


exclusiv a autorului ei care i cere pe aceast cale scuze n avans.
Orice astfel de eroare sau neclaritate cu privire la coninutul crii
poate fi comunicat direct autorului pe
adresa erotariu@agora.ro sau:
Eugen Rotariu
Computer Press Agora
Str. Tudor Vladimirescu, Nr. 63/1, Cod. 4300, Trgu Mure
Romnia
n Internet, putei s contactai editura Computer Press Agora la
adresa www.agora.ro. Pe server exist o pagin separat dedicat
acestei cri. Putei verifica periodic aceast pagin pentru
eventuale corecturi, exemple suplimentare sau adugiri la
coninutul crii.

Alte surse de informaii


Subiectul Java este departe de a fi ncheiat n aceast carte aa c,
dac reacia dumneavoastr este pozitiv, voi ncerca s construiesc
o a doua carte dedicat claselor standard Java, mediilor de
dezvoltare, din ce n ce mai numeroase, ierarhiilor de baz de date,
obiecte distribuite i aa mai departe care i-au fcut apariia de la
Sun sau din alt parte n ultimul timp. Nu ezitai s-mi dai de tire
dac vei considera util o asemenea continuare.
Pn atunci ns, putei consulta crile listate n seciunea de
bibliografie de la sfritul acestei cri. Numai cri n limba englez
n acest domeniu deocamdat, dar m atept ca situaia s se
schimbe dramatic n perioada imediat urmtoare. Noi cri de Java
dedicate cititorilor romni nu vor ntrzia s apar.
Internet-ul este de asemenea o surs interminabil de informaii,
situri Java exist i vor continua s apar n ntreaga lume. Adresa
de baz este probabil www.javasoft.com, adres care v pune n
legtur direct cu firma care a creat i ntreine n continuare
dezvoltarea Java. n plus, putei consulta revista electronic
JavaWorld de la adresawww.javaworld.com care conine
ntotdeauna informaii fierbini, cursuri, apleturi i legturi ctre
alte adrese unde v putei mbogi cunotinele despre Java.
Pentru documentaii, exemple i nouti n lumea Java putei
consulta i www.gamelan.com sau www.blackdown.org.

Pentru cei care doresc s dezvolte apleturi pe care s le insereze n


propriile pagini HTML, recomand n plus citirea crii lui Dumitru
Rdoiu, HTML - Publicaii Web, editat de asemenea la Computer
Press Agora.
n fine, nu ncetai s cumprai revistele PC Report i Byte
Romnia ale aceleiai edituri, pentru c ele vor conine ca de obicei
informaii de ultim or, cursuri i reportaje de la cele mai noi
evenimente din lumea calculatoarelor.

Capitolul I
Arhitectura calculatoarelor
1.1 Modelul Von Neumann de arhitectur a calculatoarelor
1.2 Organizarea memoriei interne
1.3 Reprezentarea informaiilor n memoria intern
1.4 Modelul funcional al calculatoarelor

1.1 Modelul Von Neumann de arhitectur a


calculatoarelor
Descrierea care urmeaz este o descriere a modelului Von Neumann
de construcie a calculatoarelor. Se pot aduce destule critici acestui
model care domin sever nc de la nceputurile mainilor de calcul
electronic, dar el continu s fie singurul model funcional.
Modelul Von Neumann definete calculatorul ca pe un ansamblu
format dintr-o unitate central i o memorie intern. Unitatea
central sauprocesorul este responsabil cu administrarea i
prelucrarea informaiilor n timp ce memoria intern servete la
depozitarea acestora. n terminologia calculatoarelor, depozitarea
informaiilor n memoria intern a calculatorului se
numete memorare.
Acest ansamblu unitate central plus memorie intern comunic cu
exteriorul prin intermediul unor dispozitive periferice. Dispozitivele
periferice pot fi de intrare sau de ieire n funcie de direcia n care
se mic datele. Dac datele sunt furnizate de dispozitivul periferic
i transferate spre unitatea central, atunci dispozitivul este de
intrare precum sunt tastatura sau mausul. Dac datele sunt
generate de unitatea central i transmise spre dispozitivul periferic
atunci dispozitivul este de ieire precum sunt ecranul sau
imprimanta. Exist i dispozitive mixte de intrare/ieire precum
sunt discurile pentru memorarea extern a informaiilor.
Tastatura calculatorului reprezint un set de butoane (taste)
inscripionate care ne permite transmiterea ctre unitatea central a
unor litere, cifre, semne de punctuaie, simboluri grafice sau
comenzi funcionale. Mausulreprezint un dispozitiv simplu, mobil,
care ne permite indicarea unor regiuni ale ecranului cu ajutorul
unui cursor.

10

n plus, mausul ne permite activarea regiunilor respective cu


ajutorul celor 1-2-3 butoane ale sale.
Ecranul este un dispozitiv cu ajutorul cruia calculatorul comunic
informaii spre exterior. Aceste informaii apar sub form de litere,
cifre, semne de punctuaie, simboluri grafice sau desene oarecare
ntr-o varietate mai mare sau mai mic de culori. Informaia de pe
ecran se pierde odat cu redesenarea acestuia. Pentru transferul
acestor informaii pe hrtie i ndosarierea lor s-au creat alte
dispozitive periferice, numite imprimante.
Memoria intern pierde informaiile odat cu oprirea alimentrii
calculatorului. Pentru a salva informaiile utile, precum i
programele de prelucrare ale acestora este nevoie de dispozitive de
memorare permanente. Din aceast categorie fac
parte discurile calculatorului. Exist mai multe modele de discuri
precum discurile fixe, discurile flexibile sau compact-discurile,
fiecare dintre acestea avnd caracteristici, viteze de acces i
capaciti de memorare diferite. Informaiile salvate pe discuri pot fi
ncrcate din nou n memoria intern la o pornire ulterioar a
calculatorului. V vei ntreba desigur de ce este nevoie de dou
tipuri distincte de memorie: pentru c discurile au viteze de acces
mult prea mici pentru a putea fi folosite direct de ctre unitatea
central.

Figura 1.1 Modelul constructiv al calculatoarelor Von Neuman.

11

Dei modelul constructiv de baz al calculatoarelor nu a evoluat


prea mult, componenta tehnologic a acestora s-a aflat ntr-o
permanent evoluie. Transformarea vizeaz la ora actual viteza de
lucru i setul de instruciuni ale unitii centrale, capacitatea i
viteza de stocare a memoriei interne precum i tipurile i calitatea
dispozitivelor periferice.

1.2 Organizarea memoriei interne


Memoria calculatoarelor actuale este, din punct de vedere logic, o
niruire de cifre binare, 0 sau 1. Alegerea bazei 2 de numeraie are
n principal raiuni constructive: este mult mai uor i mult mai
fiabil s reprezini un principiu binar ca absena/prezena sau
plus/minus dect unul nuanat. O cifr binar este numit, n
termeni de calculatoare, bit.
Biii sunt grupai, opt cte opt, n uniti de memorare
numite octei.
Iari, alegerea cifrei opt are raiuni istorice: era nevoie de o putere
a lui doi care s fie ct mai mare, pentru a putea permite transferuri
rapide ntre diversele componente ale calculatorului (unitate
central, memorie, dispozitive periferice), dar totodat suficient de
mic pentru ca realizarea dispozitivelor implicate, cu tehnologia
existent, s fie posibil. Cifra opt avea n plus avantajul c
permitea reprezentarea tuturor caracterelor tipribile necesare la
ora respectiv precum: literele, cifrele sau semnele de punctuaie.
ntr-un octet se pot reprezenta pn la 256 (28) astfel de caractere.
n prezent octetul este depit datorit necesitii de reprezentare a
caracterelor tuturor limbilor scrise din lume.
Pentru a accesa o informaie n memorie este nevoie de un mod de a
referi poziia acesteia. Din acest motiv, octeii memoriei au fost
numerotai unul cte unul ncepnd de la 0 pn la numrul
maxim de octei n memorie. Numrul de ordine al unui octet l vom
numi pentru moment adres. Noiunea de adres i-a extins
semnificaia n ultimul timp dar, pentru nelegerea acestui capitol,
explicaia de mai sus este suficient.
Zona fizic de memorie rezervat unei anumite informaii se
numetelocaia informaiei respective n memorie. n unele dintre
locaiile din memorie putem pstra chiar adresa unor alte locaii din
memorie. Informaia memorat n aceste locaii se
numete referin. Cu alte cuvinte, o referin este o informaie
12

memorat ntr-o locaie de memorie care ne trimite spre (se refer


la) o alt locaie de memorie. O locaie de memorie se poate ntinde
pe mai mult dect un octet.

1.3 Reprezentarea informaiilor n memoria intern


Dup cum ai putut observa din cele prezentate pn acum, n
memoria calculatorului nu se pot nscrie dect numere naturale.
Mai precis, fiecare octet de memorie poate memora un numr de la
0 la 28-1, adic 255. Orice alt informaie pe care dorim s o
reprezentm n memoria calculatorului trebuie redus la unul sau
mai multe numere naturale mici.
Aceast trstur a modelului actual de memorare introduce un pas
suplimentar de abstractizare n procesul de proiectare de aplicaii, i
anume pasul n care se construiete un model de reprezentare n
memorie a datelor, necesar aplicaiei.
S presupunem, de exemplu, c o aplicaie necesit reprezentarea
n memoria calculatorului a unui set de culori. Pentru memorarea
acestor culori este nevoie de o convenie care s stabileasc o
coresponden biunivoc ntre setul de culori i setul de numere
naturale folosite la reprezentarea acestora. Corespondena este
biunivoc pentru c ea trebuie s ofere posibilitatea de a regsi n
mod unic o culoare plecnd de la un numr i, n acelai timp, s
ofere o reprezentare unic, sub form de numr, pentru fiecare
culoare. De exemplu, putem pune n coresponden culoarea neagr
cu numrul 0, culoarea roie cu numrul 1, culoarea albastr cu
numrul 2 i aa mai departe. Ori de cte ori vom memora 2 vom
memora albastru i ori de cte ori vom dori s memorm rou, vom
memora 1.
Ca rezultat al folosirii acestei abstractizri, datele aplicaiei devin
dependente de convenia de reprezentare utilizat. Presupunnd c
o aplicaie construiete n memorie o imagine grafic folosindu-se de
o anumit coresponden dintre culori i numere, oricare alt
aplicaie care vrea s utilizeze imaginea respectiv trebuie s
foloseasc aceeai convenie.
O cale similar de rezolvare vom ntlni i la reprezentarea
caracterelor.Caracterele sunt denumirea ntr-un singur cuvnt a
literelor, cifrelor, semnelor de punctuaie sau simbolurilor grafice
reprezentate n memorie. Este nevoie de o convenie prin care

13

atam fiecrui caracter cte un numr natural memorabil ntr-un


octet.
n cazul reprezentrii caracterelor, exist chiar un standard
internaional care definete numerele, reprezentabile pe un octet,
corespunztoare fiecrui caracter n parte, numit standardul ASCII.
Alte standarde, cum ar fi standardul Unicode, reprezint caracterele
pe doi octei, ceea ce le d posibilitatea s ia n considerare o gam
mult mai larg de caractere.
Caracter Reprezentare pe un octet (ASCII)
A-Z
65-90
a-z
97-122
0-9
48-57
,
195,227
,
206,238
,
194,226
,
170,186
,
222,254
Tabelul 1.1 Un fragment din codurile ASCII i Unicode de reprezentare a caracterelor grafice n
memoria calculatoarelor.

Desigur, este greu s inem minte codul numeric asociat fiecrui


caracter sau fiecrei culori. Este nevoie de pai suplimentari de
codificare, care s pun informaia n legtur cu simboluri mai
uor de inut minte dect numerele. De exemplu, este mult mai
uor pentru noi s inem minte cuvinte sau imagini. Dar s nu
uitm niciodat c, pentru calculator, cel mai uor este s
memoreze i s lucreze cu numere.

1.4 Modelul funcional al calculatoarelor


Fiecare calculator definete un numr de operaii care pot fi
executate de unitatea sa central. Aceste operaii sunt n principal
destinate memorrii sau recuperrii informaiilor din memoria
intern, calculelor aritmetice sau logice i controlului dispozitivelor
periferice. n plus, exist un numr de instruciuni pentru controlul
ordinii n care sunt executate operaiile.
O instruciune este o operaie elementar executabil de ctre
unitatea central a unui calculator. O secven de mai multe
instruciuni executate una dup cealalt o vom numi program.

14

Instruciunile care compun un program trebuiesc i ele reprezentate


n memorie, la fel ca orice alt informaie, din cauza faptului c
unitatea central nu are posibilitatea s-i pstreze programele n
interior. Pentru memorarea acestor instruciuni este nevoie de o
nou convenie de reprezentare care s asocieze un numr sau o
secven de numere naturale fiecrei instruciuni a unitii centrale.
Execuia unui program de ctre calculator presupune ncrcarea
instruciunilor n memoria intern i execuia acestora una cte una
n unitatea central. Unitatea central citete din memorie cte o
instruciune, o execut, dup care trece la urmtoarea instruciune.
Pentru pstrarea secvenei, unitatea central memoreaz n
permanen o referin ctre urmtoarea instruciune ntr-o locaie
intern numitindicator de instruciuni.
Modelul de execuie liniar a instruciunilor, n ordinea n care
acestea sunt aezate n memorie, este departe de a fi acceptabil.
Pentru a fi util, un program trebuie s poat s ia decizii de
schimbare a instruciunii urmtoare n funcie de informaiile pe
care le prelucreaz. Aceste decizii pot nsemna uneori comutarea
execuiei de la o secven de instruciuni la alta. Alteori, este
necesar s putem executa o secven de instruciuni n mod repetat
pn cnd este ndeplinit o anumit condiie exprimabil cu
ajutorul informaiilor din memorie. Numrul de repetri ale
secvenei de instruciuni nu poate fi hotrt dect n momentul
execuiei. Aceste ramificri ale execuiei se pot simula destul de
uor prin schimbarea valorii referinei memorate n indicatorul de
instruciuni.

15

Capitolul II
Limbaje de programare
2.1 Comunicaia om-main
2.2 Tipuri de numere reprezentabile n calculator
2.3 Valori de adevr
2.4 iruri de caractere
2.5 Tipuri primitive de valori ale unui limbaj de programare
2.6 Tablouri de elemente
2.7 Expresii de calcul
2.8 Variabile
2.9 Instruciuni

2.1 Comunicaia om-main


Pentru a executa un program de calculator este necesar s putem
comunica cu unitatea central pentru a-i furniza instruciunile
necesare. Cel mai simplu mod de a le comunica este nscrierea
codului instruciunilor direct n memoria calculatorului de unde pot
fi citite de ctre unitatea central. Aceast cale este ns extrem de
anevoioas pentru programator pentru c el trebuie s nvee s se
exprime coerent ntr-un limbaj ale crui componente de baz sunt
coduri numerice.
O alternativ mai bun este folosirea unui limbaj de comunicaie
format dintr-un numr foarte mic de cuvinte i caractere speciale
mpreun cu un set de convenii care s ajute la descrierea
numerelor i a operaiilor care trebuiesc executate cu aceste
numere. Limbajul trebuie s fie att de simplu nct calculatorul s
poat traduce singur, prin intermediul unui program
numit compilator, frazele acestui limbaj n instruciuni ale unitii
centrale. Ori de cte ori vom imagina un nou limbaj de comunicaie
cu calculatorul va trebui s crem un nou program compilator care
s traduc acest limbaj n instruciuni ale unitii centrale, numite
uneori iinstruciuni main.
n realitate folosirea termenului de limbaj de comunicaie nu este
extrem de fericit pentru c de obicei noi doar instruim calculatorul
ce are de fcut i cum trebuie s fac acel lucru, fr s-i dm vreo
ans acestuia s comenteze sarcinile primite. n continuare vom
numi aceste limbaje simplificate limbaje de programare pentru a le

16

deosebi de limbajele pe care le folosim pentru a comunica cu ali


oameni i pe care le vom numi limbaje naturale.
Limbajele de programare trebuie s ne ofere o cale de descriere a
modulului n care dorim s reprezentm informaiile cu care
lucreaz programul, o cale de a specifica operaiile care trebuiesc
executate cu aceste informaii i o cale de a controla ordinea n care
sunt executate aceste operaii.
n plus, limbajele de programare trebuie s respecte urmtorul
principiu fundamental: rezultatul execuiei unei comenzi dintr-un
limbaj de programare trebuie s fie complet determinat. Asta
nseamn c n limbajele de programare nu este permis nici o
form de ambiguitate a exprimrii.
Informaiile reprezentate n memoria calculatorului i prelucrate de
ctre un program scris ntr-un limbaj de programare se numesc
date. Tipurile de date care se pot descrie direct cu un anumit limbaj
de programare se numesc tipurile de date elementare ale limbajului.
Operaiile elementare posibil de exprimat ntr-un limbaj de
programare se numesc instruciuni ale limbajului.
Limbajele de programare au evoluat foarte mult de la nceputurile
calculatoarelor. Tendina general este aceea de apropiere treptat
de limbajele naturale i de modul n care acestea descriu i
utilizeaz informaiile. Abstraciile exprimabile cu ajutorul
limbajelor de programare sunt din ce n ce mai multe i cuprind o
gam din ce n ce mai larg a noiunilor fundamentale cu care
opereaz mintea uman.
Un alt aspect n care se reflect evoluia limbajelor de programare
este reprezentat de creterea profunzimii i calitii controlului pe
care compilatoarele l fac n momentul traducerii din limbaj de
programare n limbaj main, astfel nct ansa de a grei la
descrierea programului s fie ct mai mic.
Cu toate c limbajele de programare au fcut pai eseniali n
ultimul timp, ele au rmas totui foarte departe de limbajele
naturale. Pentru a programa un calculator, trebuie s poi gndi i
s poi descrie problemele ntr-unul dintre limbajele pe care acesta
le nelege. Din acest motiv, scrierea programelor continu s
rmn o activitate rezervat unui grup de iniiai, chiar dac acest
grup este n continu cretere.

17

2.2 Tipuri de numere reprezentabile n calculator


Dei toate informaiile reprezentabile direct n memoria
calculatorului sunt doar numere naturale, constructorii
calculatoarelor de astzi au diversificat tipurile acestora prin
stabilirea unor convenii de reprezentare pentru numerele negative,
reale i pentru caractere. Aceste convenii folosesc numerele
naturale pentru reprezentarea celorlalte tipuri de numere. Uneori,
reprezentrile ocup mai mult de un octet n memoria
calculatorului, dimensiunile obinuite fiind 1, 2, 4 sau 8 octei. Sau,
echivalent, 8, 16, 32 sau 64 de bii.
Numerele naturale sunt ntotdeauna pozitive. Pentru reprezentarea
unuinumr ntreg cu semn pot fi folosite dou numere naturale.
Primul dintre acestea, avnd doar dou valori posibile, reprezint
semnul numrului i se poate reprezenta folosind o singur cifr
binar. Dac valoarea acestei cifre binare este 0, numrul final este
pozitiv, iar dac valoarea cifrei este 1, numrul final este negativ. Al
doilea numr natural folosit n reprezentarea numerelor ntregi cu
semn conine valoarea absolut a numrului final. Aceast
convenie, dei are dezavantajul c ofer dou reprezentri pentru
numrul zero, un zero pozitiv i altul negativ, este foarte aproape de
reprezentarea numerelor cu semn folosit de calculatoarele
moderne.
n realitate, convenia care se folosete pentru reprezentarea
numerelor ntregi cu semn este aa numita reprezentare n
complement fa de doi. Aceasta reprezint numerele negative prin
complementarea valorii lor absolute bit cu bit i apoi adunarea
valorii 1 la numrul rezultat. Complementarea valorii unui bit se
face nlocuind valoarea 1 cu 0 i valoarea 0 cu 1. Dac avem de
exemplu numrul 1, reprezentat pe un octet ca un ir de opt cifre
binare 00000001, complementarea bitcu bit a acestui numr este
numrul reprezentat pe un octet prin11111110.
Pentru a reprezenta valoarea -1 nu ne mai rmne altceva de fcut
dect s adunm la numrul rezultat n urma complementrii un 1
i reprezentarea final a numrului ntreg negativ -1 pe un octet
este 11111111.
n aceast reprezentare, numrul 00000000 binar reprezint
numrul 0 iar numrul 10000000, care mai nainte reprezenta
numrul 0 negativ, acum reprezint numrul -128. ntr-adevr,
numrul 128 se poate reprezenta n binar prin 10000000.
18

Complementat, acest numr devine 01111111 i dup adunarea cu


1, 10000000. Observai c numerele 128 i -128 au aceeai
reprezentare. Convenia este aceea c se pstreaz reprezentarea
pentru -128 i se elimin cea pentru 128. Alegerea este datorat
faptului c toate numerele pozitive au n primul bit valoarea 0 i
toate cele negative valoarea -1. Prin transformarea lui 10000000 n 128 se pstreaz aceast regul.
Folosind reprezentarea n complement fa de doi, numerele ntregi
reprezentabile pe un octet sunt n intervalul -128 pn la 127, adic
-27pn la 27 -1. n general, dac avem o configuraie de n cifre
binare, folosind reprezentarea n complement fa de doi putem
reprezenta numerele ntregi din intervalul nchis -2n-1 pn la 2n-1-1.
n practic, se folosesc numere ntregi cu semn reprezentate pe 1
octet, 2 octei, 4 octei i 8 octei, respectiv 8, 16, 32 i 64 de bii.
Dac dorim s reprezentm un numr real n memoria
calculatorului, o putem face memornd cteva cifre semnificative ale
acestuia plus o informaie legat de ordinul su de mrime. n acest
fel, dei pierdem precizia numrului, putem reprezenta valori foarte
aproape de zero sau foarte departe de aceast valoare.
Soluia de reprezentare este aceea de a pstra dou numere cu
semn care reprezint cifrele semnificative ale numrului real
respectiv un exponentcare d ordinul de mrime. Cifrele
reprezentative ale numrului se numesc mpreun mantis.
Numrul reprezentat n final este 0.mantisaEexponent. E are valoarea
256 spre deosebire de exponentul 10 pe care l folosim n uzual.
Dac valoarea exponentului estefoarte mare i pozitiv, numrul
real reprezentat este foarte departe de 0, nspre plus sau nspre
minus. Dac exponentul este foarte mare n valoare absoluti
negativ, numrul real reprezentat este foarte aproape de zero.
n plus, pentru a ne asigura de biunivocitatea corespondenei, avem
nevoie de o convenie care s stabileasc faptul c virgula este
plasat imediat n faa cifrelor semnificative i c n faa acesteia se
gsete o singur cifr 0. Numerele care respect aceast convenie
se numesc numere normalizate.
Aceast mutare a virgulei imediat n faa cifrelor semnificative poate
s presupun modificarea exponentului care pstreaz ordinul de
mrime al numrului. Numerele fracionare se numesc n limbajul
calculatoarelornumere n virgul mobil sau numere flotante tocmai
din cauza acestei eventuale ajustri a poziiei virgulei.
19

Cu aceast convenie nu se poate reprezenta orice numr real, dar


se poate obine o acoperire destul de bun a unui interval al axei
numerelor reale cu valori. Atunci cnd ncercm s reprezentm n
memoria calculatorului un numr real, cutm de fapt cel mai
apropiat numr real reprezentabil n calculator i aproximm
numrul iniial cu acesta din urm. Ca rezultat, putem efectua
calcule complexe cu o precizie rezonabil.
Descrierea conveniei exacte de reprezentare a numerelor reale n
calculator depete cadrul acestei prezentri. Unele dintre detalii
pot fi diferite de cele prezentate aici, dar principiul este exact acesta.
Convenia de reprezentare a numerelor reale este standardizat de
IEEE n specificaia 754.
Desigur, n unele probleme, lipsa de precizie poate s altereze
rezultatul final, mai ales c, uneori, erorile se cumuleaz. Exist de
altfel o teorie complex, analiza numeric, conceput pentru a
studia cile prin care putem ine sub control aceste erori de precizie.
Putem crete precizia de reprezentare a numerelor reale prin
mrirea spaiului rezervat mantisei. n acest fel mrim numrul de
cifre semnificative pe care l pstrm. n general, unitile centrale
actuale lucreaz cu dou precizii: numerele flotante simple,
reprezentate pe 4 octei i numerele flotante duble, reprezentate pe 8
octei.

2.3 Valori de adevr


Uneori, avem nevoie s memorm n calculator valori de adevr.
Exist doar dou valori de adevr posibile: adevrat i fals. Uneori,
aceste valori de adevr se mai numesc i valori booleene. Dei
pentru memorarea acestor valori este suficient o singur cifr
binar, n practic aceste valori sunt reprezentate pe un ntreg octet
pentru c operaiile la nivel de bit sunt de obicei prea lente. Valorile
booleene se pot combina ntre ele prin operaii logice: i , sau ,
"negaie .

2.4 iruri de caractere


Dup cum spuneam mai nainte, dei orice informaie reprezentat
n calculator este n final un numr, mintea uman este obinuit
s lucreze cu cuvinte i imagini mai mult dect cu numere. De
aceea, calculatorul trebuie s aib posibilitatea s simuleze
memorarea informaiilor de acest fel.
20

n ceea ce privete cuvintele, ele pot fi reprezentate n memoria


calculatorului prin caracterele care le formeaz. niruirea acestor
caractere n memorie duce la noiunea de ir de caractere. Pe lng
caracterele propriu-zise care construiesc cuvntul, un ir de
caractere trebuie s poat memora i numrul total de caractere din
ir, cu alte cuvinte lungimea sa.
n realitate, un ir de caractere nu conine doar un singur cuvnt ci
este o niruire oarecare de caractere printre care pot exista i
caractere spaiu. De exemplu, urmtoarele secvene sunt iruri de
caractere: "Acesta este un ir de caractere", "Eugen", "ABCD 0123",
"HGkduI;.!".
Fiecare limbaj de programare trebuie s ofere o convenie de
reprezentare a irurilor de caractere n calculator precum i o
convenie de scriere a acestora n program. De obicei, cea de-a doua
convenie este aceea c irul de caractere trebuie nchis ntre
apostroafe sau ghilimele. n paragraful anterior de exemplu, am
folosit ghilimele pentru delimitarea irurilor de caractere.
Convenia de reprezentare n memorie difer de la un limbaj de
programare la altul prin modul n care este memorat lungimea
irului, precum i prin convenia de reprezentare n memorie a
caracterelor: ASCII, Unicode sau alta.
mpreun cu fiecare tip de dat, limbajele de programare trebuie s
defineasc i operaiile ce se pot executa cu datele de tipul respectiv.
Pentru irurile de caractere, principala operaie este concatenarea.
Prin concatenarea a dou iruri de caractere se obine un ir de
caractere care conine caracterele celor dou iruri puse n
prelungire. De exemplu, prin concatenarea irurilor de caractere
"unu" i ", doi", rezult irul de caractere: "unu, doi".

2.5 Tipuri primitive de valori ale unui limbaj de


programare
Vom numi tipuri primitive de valori ale unui limbaj acele tipuri de
valori care se pot reprezenta direct ntr-un anumit limbaj de
programare. Pentru ca informaia reprezentabil s fie independent
de calculatorul pe care ruleaz programele, un limbaj de programare
trebuie s-i defineasc propriile sale tipuri primitive, eventual
diferite de cele ale unitii centrale, tipuri care s generalizeze
tipurile primitive ale tuturor unitilor centrale.
21

Pentru fiecare dintre aceste tipuri primitive de valori, limbajul


trebuie s defineasc dimensiunea locaiei de memorie ocupate,
convenia de reprezentare i mulimea valorilor care pot fi
reprezentate n aceast locaie. n plus, limbajul trebuie s
defineasc operaiile care se pot executa cu aceste tipuri i
comportarea acestor operaii pe seturi de valori diferite.
Tipurile primitive ale unui limbaj sunt de obicei: numere de diverse
tipuri, caractere, iruri de caractere, valori de adevr i valori de tip
referin. Totui, acest set de tipuri primitive, denumirea exact a
tipurilor i operaiile care se pot executa cu ele variaz mult de la
un limbaj de programare la altul.

2.6 Tablouri de elemente


Tipurile primitive mpreun cu referinele, adic tipurile de date
elementare, indivizibile ale unui limbaj, sunt insuficiente pentru
necesitile unei aplicaii reale. De obicei este nevoie de organizri
de date mai complicate n care avem structuri de date create prin
asocierea mai multor tipuri de date elementare. Aceste structuri de
organizare a informaiilor pot conine date de acelai tip sau date de
tipuri diferite.
n cazul n care dorim s reprezentm o structur coninnd date de
acelai tip, va trebui s folosim o structur clasic de reprezentare a
datelor numit tablou de elemente. Practic, un tablou de elemente
este o alturare de locaii de memorie de acelai fel. Alturarea este
continu n sensul c zona de memorie alocat tabloului nu are
guri. De exemplu, putem gndi ntreaga memorie intern a
calculatorului ca fiind un tablou de cifre binare sau ca un tablou de
octei.
Informaiile de acelai fel reprezentate ntr-un tablou se pot prelucra
n mod unitar. Referirea la un element din tablou se face prin
precizarea locaiei de nceput a tabloului n memorie i a numrului
de ordine al elementului pe care dorim s-l referim. Numrul de
ordine al unui element se numete indexul elementului. De aceea,
tablourile se numesc uneori i structuri de date indexate.
S presupunem c, la adresa 1234 n memorie, deci ncepnd cu
octetul numrul 1234, avem un tablou de 200 de elemente de tip
ntregi cu semn reprezentai pe 4 octei. Pentru a accesa elementul
numrul 123 din tablou, trebuie s i aflm adresa n memorie.
Pentru aceasta, trebuie s calculm deplasamentul acestui element
22

fa de nceputul tabloului, cu alte cuvinte, la ci octei distan


fa de nceputul tabloului se gsete elementul numrul 123.
Pentru calcului deplasamentului, este nevoie s tim cu ce index
ncepe numerotarea elementelor din tablou. De obicei aceasta
ncepe cu 0 sau cu 1, primul element fiind elementul 0 sau
elementul 1. S presupunem, n cazul nostru, c numerotarea ar
ncepe cu 0. n acest caz, elementul cu indexul 123 este de fapt al
124-lea element din tablou, deci mai are nc 123 de elemente
naintea lui. n aceste condiii, pentru a afla adresa elementului dat,
este suficient s adugm la adresa de nceput a tabloului,
deplasamentul calculat ca numrul de elemente din fa nmulit cu
dimensiunea unui element din tablou. Adresa final este 1234 +
123 * 4 = 1726.
Pentru a putea lucra cu elementele unui tablou este deci suficient
s memorm adresa de nceput a tabloului i indexul elementelor pe
care dorim s le accesm. Alternativa ar fi fost s memorm adresa
locaiei fiecrui element din tablou.
Unul dintre marile avantaje ale utilizrii tablourilor este acela c
elementele dintr-un tablou se pot prelucra n mod repetitiv,
apelndu-se aceeai operaie pentru un subset al elementelor din
tablou. Astfel, ntr-un program putem formula instruciuni de
forma: pentru elementele tablouluiT ncepnd de la al treilea pn la
al N-lea, s se execute operaia O. Numrul N poate fi calculat
dinamic n timpul execuiei programului, n funcie de necesiti.
Elementele unui tablou pot fi de tip primitiv, referin sau pot fi
tipuri compuse, inclusiv alte tablouri.

2.7 Expresii de calcul


Sarcina principal a calculatoarelor este aceea de a efectua calcule.
Pentru a putea efectua aceste calcule, calculatorul trebuie s
primeasc o descriere a operaiilor de calcul pe care le are de
executat. Calculele simple sunt descrise cel mai bine prin expresii
de calcul.
Expresiile sunt formate dintr-o serie de valori care intr n calcul,
numiteoperanzi i din simboluri care specific operaiile care
trebuiesc efectuate cu aceste valori, numite operatori. Operatorii
reprezint operaii de adunare, nmulire, mprire, concatenare a
irurilor de caractere, etc.
23

Operanzii unor expresii pot fi valori elementare precum numerele,


irurile de caractere sau pot fi referiri ctre locaii de memorie n
care sunt memorate aceste valori. Tot operanzi pot fi i valorile unor
funcii predefinite precum sinus, cosinus sau valoarea absolut a
unui numr. Calculul complex al valorii acestor funcii pentru
argumentele de intrare este astfel ascuns sub un nume uor de
recunoscut.

Figura 2.1 Un exemplu de expresie i componentele acesteia

2.8 Variabile
Uneori, atunci cnd calculele sunt complexe, avem nevoie s
pstrm rezultate pariale ale acestor calcule n locaii temporare de
memorie. Alteori, chiar datele iniiale ale problemei trebuie
memorate pentru o folosire ulterioar. Aceste locaii de memorie
folosite ca depozit de valori le vom numi variabile. Variabilele pot
juca rol de operanzi n expresii.
Pentru a regsi valoarea memorat ntr-o anumit variabil, este
suficient s memorm poziia locaiei variabilei n memorie i tipul
de dat memorat la aceast locaie, numit i tipul variabilei.
Cunoaterea tipului variabilei este esenial la memorarea i
regsirea datelor. La locaia variabilei gsim ntotdeauna o
configuraie de cifre binare. Interpretarea acestor cifre binare se
poate face numai cunoscnd convenia de reprezentare care s-a
folosit la memorarea acelor cifre binare. Mai mult, tipul de variabil
ne i spune ci octei de memorie ocup locaia respectiv.
Pentru a putea referi variabilele n interiorul unui program, trebuie
s atribuim cte un nume pentru fiecare dintre acestea i s
rezervm locaiile de memorie destinate lor. Aceast rezervare a
locaiilor se poate face fie la pornirea programului fie pe parcurs.
24

Putem mpri variabilele n funcie de perioada lor de existen n


variabile statice, care exist pe tot parcursul programului
i variabile locale care se creeaz doar n seciunea de program n
care este nevoie de ele pentru a fi distruse imediat ce se prsete
seciunea respectiv. Variabilele statice pstreaz de obicei
informaii eseniale pentru execuia programului precum numele
celui care a pornit programul, data de pornire, ora de pornire sau
numrul p . Variabilele locale pstreaz valori care au sens doar n
contextul unei anumite seciuni din program. De exemplu,
variabilele care sunt utilizate la calculul sinusului dintr-un numr,
sunt inutile i trebuiesc eliberate imediat ce calculul a fost terminat.
n continuare, doar valoarea final a sinusului este important.
n plus, exist variabile care se creeaz doar la cererea explicit a
programului i nu sunt eliberate dect atunci cnd programul nu
mai are nevoie de ele. Aceste variabile se numesc variabile dinamice.
De exemplu, se creeaz o variabil dinamic atunci cnd utilizatorul
programului introduce un nou nume ntr-o list de persoane.
Crearea i tergerea acestui nume nu are legtur cu faza n care se
afl rularea programului ci are legtur cu dorina celui care
utilizeaz programul de a mai aduga sau terge un nume n lista
persoanelor cu care lucreaz, pentru a le trimite, de exemplu,
felicitri de anul nou.

2.9 Instruciuni
Operaiile care trebuiesc executate de un anumit program sunt
exprimate n limbajele de programare cu ajutorul unor instruciuni.
Spre deosebire de limbajele naturale, exist doar cteva tipuri
standard de instruciuni care pot fi combinate ntre ele pentru a
obine funcionalitatea programelor. Sintaxa de scriere a acestor
tipuri de instruciuni este foarte rigid. Motivul acestei rigiditi este
faptul c un compilator recunoate un anumit tip de instruciune
dup sintaxa ei i nu dup sensul pe care l are ca n cazul
limbajelor naturale.
Tipurile elementare de instruciuni nu s-au schimbat de-a lungul
timpului pentru c ele sunt coninute n nsui modelul de
funcionare al calculatoarelor Von Neumann.
n primul rnd, avem instruciuni de atribuire. Aceste instruciuni
presupun existena unei locaii de memorie creia dorim s-i
atribuim o anumit valoare. Atribuirea poate s par o operaie
foarte simpl dar realitatea este cu totul alta. n primul rnd,
25

valoarea respectiv poate fi rezultatul evalurii (calculului) unei


expresii complicate care trebuie executat nainte de a fi memorat
n locaia de memorie dorit.
Apoi, nsi poziia locaiei n memorie ar putea fi rezultatul unui
calcul n urma cruia s rezulte o anumit adres. De exemplu, am
putea dori s atribuim o valoare unui element din interiorul unui
tablou. ntr-o astfel de situaie, locaia de memorie este calculat
prin adunarea unui deplasament la adresa de nceput a tabloului.
n fine, locaia de memorie i valoarea pe care dorim s i-o atribuim
ar putea avea tipuri diferite. n acest caz, operaia de atribuire
presupune i transformarea, dac este posibil, a valorii ntr-o nou
valoare de acelai tip cu locaia de memorie. n plus, aceast
transformare trebuie efectuat n aa fel nct s nu se piard
semnificaia valorii originale. De exemplu, dac valoarea original
era -1 ntreg iar locaia de memorie este de tip flotant, valoarea
obinut dup transformare trebuie s fie -1.0.
Transformarea valorilor de la un tip la altul se numete n termeni
informatici conversie. Conversiile pot aprea i n alte situaii dect
instruciunile de atribuire, de exemplu la transmiterea parametrilor
unei funcii, n calculul unei expresii.
Forma general a unei instruciuni de atribuire este:
Locaie = Valoare
Locaia poate fi o adres cu tip, un nume de variabil sau o expresie
n urma creia s rezulte o adres cu tip. Printr-o adres cu tip
nelegem o adres de memorie pentru care a fost specificat tipul
valorilor care pot fi memorate n interior. O adres simpl, fr tip,
nu poate intra ntr-o atribuire pentru c nu putem ti care este
convenia de reprezentare care trebuie folosit la memorarea valorii.
Al doilea tip de instruciune elementar este instruciunea
condiional. Aceast instruciune permite o prim form de
ramificare a ordinii n care se execut instruciunile. Ramificarea
depinde de o condiie care poate fi testat pe setul de date cu care
lucreaz aplicaia. n funcie de valoarea de adevr care rezult n
urma evalurii condiiei se poate executa o instruciune sau alta.
Modelul de exprimare a unei expresii condiionale este urmtorul:
Dac condiia este adevrat
26

execut instruciunea 1
altfel
execut instruciunea 2.
Cele dou ramuri de execuie sunt disjuncte n sensul c dac este
executat instruciunea de pe o ramur atunci cu siguran
instruciunea de pe cealalt ramur nu va fi executat. Dup
execuia uneia sau a celeilalte instruciuni ramurile se reunific i
execuia i continu drumul cu instruciunea care urmeaz dup
instruciunea condiional.

Figura 2.2 Schema de funcionare a unei instruciuni condiionale

Condiia care hotrte care din cele dou instruciuni va fi


executat este de obicei un test de egalitate ntre dou valori sau un
test de ordonare n care o valoare este testat dac este mai mic
sau nu dect o alt valoare. Condiiile pot fi compuse prin conectori
logici de tipul i , sau sau non , rezultnd n final condiii de
forma: dac variabila numit Temperatur este mai mic dect 0 i
mai mare dect -10, atunci
Instruciunile condiionale au i o variant n care, n funcie de o
valoare ntreag alege o instruciune dintr-un set de instruciuni i
apoi o execut. Aceast form este n realitate derivat din
instruciunea condiional clasic, ea putnd fi exprimat prin:
Dac Variabila este egal cu Valoarea 1 atunci
execut instruciunea 1
27

altfel, dac Variabila este egal cu Valoarea 2 atunci


execut instruciunea 2
altfel, dac Variabila

altfel
execut instruciunea implicit.
Un al treilea tip de instruciuni elementare sunt instruciunile de
ciclaresau repetitive sau buclele. Acestea specific faptul c o
instruciune trebuie executat n mod repetat. Controlul ciclurilor
de instruciuni se poate face pe diverse criterii. De exemplu se poate
executa o instruciune de un numr fix de ori sau se poate executa
instruciunea pn cnd o condiie devine adevrat sau fals.
Condiia de terminare a buclei poate fi testat la nceputul buclei
sau la sfritul acesteia. Dac condiia este testat de fiecare dat
nainte de execuia instruciunii, funcionarea ciclului se poate
descrie prin:
Atta timp ct Condiia este adevrat
execut Instruciunea
Acest tip de instruciuni de ciclare poat numele de cicluri while,
cuvntulwhile nsemnnd n limba englez "atta timp ct . n
cazul ciclurilor while, exist posibilitatea ca instruciunea din
interiorul ciclului s nu se execute niciodat, dac condiia este de
la nceput fals.

Figura 2.3 Schema de funcionare a unui ciclu while

Dac condiia este testat de fiecare dat dup execuia


instruciunii, funcionarea ciclului se poate descrie prin:
28

Execut Instruciunea
atta timp ct Condiia este adevrat.
Acest tip de instruciuni de ciclare poart numele de cicluri do-while,
cuvntul do nsemnnd n limba englez "execut . n cazul
ciclurilor do-while instruciunea din interiorul ciclului este garantat
c se execut cel puin o dat, chiar dac valoare condiiei de
terminare a buclei este de la nceput fals.

Figura 2.4 Schema de funcionare a unui ciclu do-while

Dup cum ai observat, probabil, dac instruciunea din interiorul


buclei nu afecteaz n nici un fel valoarea de adevr a condiiei de
terminare a buclei, exist ansa ca bucla s nu se termine
niciodat.
Al patrulea tip de instruciuni sunt apelurile de proceduri.
O procedur este o secven de instruciuni de sine stttoare i
parametrizat. Un apel de procedur este o instruciune prin care
form programul s execute pe loc instruciunile unei anumite
proceduri. Dup execuia procedurii, se continu cu execuia
instruciunii de dup apelul de procedur.
Procedurile sunt utile atunci cnd, n zone diferite ale programului,
dorim s executm aceeai secven de instruciuni. n aceste
situaii, putem s scriem secvena de instruciuni o singur dat i
s-o apelm apoi oriunde din interiorul programului.
De exemplu, ori de cte ori vom dori s tergem toate semnele de pe
ecranul calculatorului, putem apela la o procedur, pentru a nu fi
nevoii s scriem de fiecare dat secvena de instruciuni care duce
la tergerea ecranului. Procedura n sine, o vom scrie o singur dat
i i vom da un nume prin care o vom putea apela ulterior ori de
cte ori avem nevoie.
29

Uneori secvena de instruciuni dintr-o procedur depinde de


niteparametri adic de un set de valori care sunt precizate doar n
momentul apelului procedurii. n aceste cazuri, procedura se poate
comporta n mod diferit n funcie de valorile de apel ale acestor
parametri. n funcie de tipul declarat al unor parametri i de tipul
real al valorilor care sunt trimise ca parametri ntr-un apel de
procedur, se poate ntmpla ca nainte de apelul propriu-zis s fie
necesar o conversie de tip.
De exemplu, n cazul procedurii care calculeaz valoarea sinusului
unui numr, parametrul de intrare este nsui numrul pentru care
trebuie calculat sinusul. Rezultatul acestui calcul va fi diferit, n
funcie de valoarea la apel a parametrului. n mod normal,
parametrul va fi un numr flotant iar dac la apel vom transmite ca
parametru o valoare ntreag, ea va fi convertit spre o valoare
flotant.
n urma apelului unei proceduri poate rezulta o valoare pe care o
vom numi valoare de retur a procedurii. De exemplu, n urma
apelului procedurii de calcul a sinusului unui numr, rezult o
valoare flotant care este valoarea calculat a sinusului. Acest tip de
proceduri, care ntorc valori de retur se mai numesc i funcii.
Funciile definesc ntotdeauna un tip al valorii de retur pe care o
ntorc. n acest fel, apelurile de funcii pot fi implicate i n formarea
unor expresii de calcul sub form de operanzi, expresia cunoscnd
tipul de valoare care trebuie ateptat ca valoare a apelului unei
anumite funcii.
Analogia cu funciile pe care le-ai studiat la matematic este
evident dar nu total. n cazul funciilor scrise ntr-un limbaj de
programare, dou apeluri consecutive ale aceleiai funcii cu
aceleai valori ca parametri se pot comporta diferit datorit
dependenei de condiii exterioare sistemului format din funcie i
parametrii de apel. n plus, se poate ntmpla ca modul de
comportare al funciei i valoarea de retur s nu fie definite pentru
anumite valori de apel ale parametrilor. Dei scrierea acestui tip de
funcii este nerecomandabil, n practic ntlnim astfel de funcii la
tot pasul.

30

Capitolul III
Reprezentarea informaiilor cu obiecte
3.1 Obiecte
3.2 ncapsularea informaiilor n interiorul obiectelor
3.3 Clase de obiecte
3.4 Derivarea claselor de obiecte
3.5 Interfee spre obiecte

3.1 Obiecte
Informaiile pe care le reprezentm n memoria calculatorului sunt
rareori att de simple precum culorile sau literele. n general, dorim
s reprezentm informaii complexe, care s descrie obiectele fizice
care ne nconjoar sau noiunile cu care operm zilnic, n interiorul
crora culoarea sau o secven de litere reprezint doar o mic
parte. Aceste obiecte fizice sau noiuni din lumea real trebuiesc
reprezentate n memoria calculatorului n aa fel nct informaiile
specifice lor s fie pstrate la un loc i s se poat prelucra ca un
tot unitar. S nu uitm ns c, la nivelul cel mai de jos, informaia
ataat acestor obiecte continu s fie tratat de ctre compilator ca
un ir de numere naturale, singurele informaii reprezentabile direct
n memoria calculatoarelor actuale.
Pentru a reprezenta n memoria intern obiecte fizice sau noiuni,
este nevoie s izolm ntregul set de proprieti specifice acestora i
s l reprezentm prin numere. Aceste numere vor ocupa n
memorie o zon compact pe care, printr-un abuz de limbaj, o vom
numi, ntr-o prim aproximare, obiect. Va trebui ns s avei
ntotdeauna o imagine clar a deosebirii fundamentale dintre un
obiect fizic sau o noiune i reprezentarea acestora n memoria
calculatorului.
De exemplu, n memoria calculatorului este foarte simplu s crem
un nou obiect, identic cu altul deja existent, prin simpla duplicare a
zonei de memorie folosite de obiectul pe care dorim s-l dedublm.
n realitate ns, este mult mai greu s obinem o copie identic a
unui obiect fizic, fie el o simpl foaie de hrtie sau o bancnot de
10000 de lei.
S revenim ns la numerele naturale. Din moment ce ele sunt
singurele entiti reprezentabile n memoria calculatorului, este
firesc ca acesta s fie echipat cu un set bogat de operaii predefinite
31

de prelucrare a numerelor. Din pcate, atunci cnd facem


corespondena dintre numere i litere de exemplu, nu ne putem
atepta la un set la fel de bogat de operaii predefinite care s
lucreze cu litere. Dar, innd cont de faptul c n cele din urm
lucrm tot cu numere, putem construi propriile noastre operaii
specifice literelor, combinnd n mod corespunztor operaiile
numerice predefinite.
De exemplu, pentru a obine dintr-o liter majuscul, s spunem
A , corespondenta ei minuscul a , este suficient s adunm un
deplasament numeric corespunztor, presupunnd c literele mari
i cele mici sunt numerotate n ordine alfabetic i imediat una
dup cealalt n convenia de reprezentare folosit. n setul ASCII
deplasamentul este 32, reprezentarea lui A fiind 65 iar
reprezentarea lui a fiind 97. Acest deplasament se pstreaz
pentru toate literele din alfabetul englez i romn, la cel din urm
existnd totui o excepie n cazul literei .
Putem s extindem cerinele noastre mai departe, spunnd c,
atunci cnd analizm un obiect fizic sau o noiune pentru a le
reprezenta n calculator, trebuie s analizm nu numai proprietile
acestora dar i modul n care acestea pot fi utilizate i care sunt
operaiile care pot fi executate asupra lor sau cu ajutorul lor. Acest
set de operaii va trebui ulterior s-l redefinim n contextul mulimii
de numere care formeaz proprietile obiectului din memoria
calculatorului, i s l descompunem n operaii numerice
preexistente. n plus, trebuie s analizm modul n care
reacioneaz obiectul atunci cnd este supus efectului unor aciuni
exterioare. Uneori, setul de operaii specifice unui obiect mpreun
cu modul n care acesta reacioneaz la stimuli exteriori se
numete comportamentul obiectului.
De exemplu, dac dorim s construim un obiect care reprezint o
minge de form sferic n spaiu, este necesar s definim trei
numere care s reprezinte coordonatele x, y i z relativ la un sistem
de axe dat, precum i o valoare pentru raza sferei. Aceste valori
numerice vor face parte din setul de proprieti ale obiectului minge.
Dac mai trziu vom dori s construim o operaie care s reprezinte
mutarea n spaiu a obiectului minge, este suficient s ne folosim de
operaiile cu numere pentru a modifica valorile coordonatelor x, y i
z.
Desigur, obiectul minge este insuficient descris prin aceste
coordonate i, pentru a simula n calculator obiectul real este nevoie
32

de multe proprieti suplimentare precum i de multe operaii n


plus. Dar, dac problema pe care o avem de rezolvat nu necesit
aceste proprieti i operaii, este preferabil s nu le definim n
obiectul folosit pentru reprezentare. Rezultatul direct al acestui mod
de abordare este acela c vom putea defini acelai obiect real n mai
multe feluri pentru a-l reprezenta n memoria intern. Modul de
definire depinde de problema de rezolvat i de programatorul care a
gndit reprezentarea. De altfel, aceste diferene de percepie ale
unui obiect real exist i ntre diveri observatori umani.
Din punctul de vedere al programrii, un obiect este o reprezentare
n memoria calculatorului a proprietilor i comportamentului unei
noiuni sau ale unui obiect real.

Figura 3.1 Modelul de reprezentare al unui obiect n memorie. Stratul exterior reprezint doar
operaiile care ofer calea de a interaciona cu proprietile obiectului i nu are corespondent
direct n zona de memorie ocupat de obiect.

3.2 ncapsularea informaiilor n interiorul obiectelor


Exist situaii n care accesul din exterior la proprietile unui
obiect poate s pun probleme acestuia. Ce s-ar ntmpla de
exemplu dac s-ar putea accesa direct valorile care definesc
funcionalitatea corpului uman? Desigur, exist cazuri n care acest
lucru ar fi mbucurtor. N-ar mai fi nevoie s acionm indirect
asupra concentraiilor de enzime n corp ci am putea s modificm
aceste valori n mod direct. Dar, n acelai timp, am putea provoca
mari necazuri n cazul n care am modifica aceste valori n afara
pragului suportabil de ctre organism. Din aceste motive, este
preferabil s lsm modificarea acestor parametri n sarcina
exclusiv a unor operaii definite de ctre obiect, operaii care vor
verifica noile valori nainte de a le schimba n interiorul obiectului.
33

n lipsa acestui filtru, putem s stricm coerena valorilor memorate


n interiorul unui obiect, fcndu-l inutilizabil.
Din acest punct de vedere, putem privi obiectul ca pe un set de
valori care formeaz miezul obiectului i un set de operaii care
mbrac aceste valori, protejndu-le. Vom spune c proprietile
obiectului sunt ncapsulate n interiorul acestora. Mai mult, obiectul
ncapsuleaz i modul de funcionare a operaiilor lui specifice, din
exterior neputndu-se observa dect modul de apelare a acestor
operaii i rezultatele apelurilor. Cu alte cuvinte,procesul de
ncapsulare este procesul de ascundere a detaliilor neimportante
sau sensibile de construcie a obiectului.
Dar nu numai proprietile unui obiect trebuiesc protejate ci i
operaiile definite de ctre acesta. Unele dintre operaiile definite
pentru un obiect, cum ar fi de exemplu procesul respirator al
omului, sunt periculos de lsat la dispoziia oricui. Este preferabil
s putem controla foarte exact cine ce operaii poate apela pentru
un anumit obiect. n acest mod, din punctul de vedere al unui
observator strin, omul este perceput ca un obiect mult mai simplu
dect este n realitate, pentru c acel observator nu poate vedea
dect acele valori i nu poate apela dect acele operaii care sunt
fcute publice.
Desigur, n practic este nevoie de o oarecare rafinare a gradului de
protejare a fiecrei operaii sau proprieti n aa fel nct nsui
accesul observatorilor exteriori s poat fi nuanat n funcie de
gradul de similitudine i apropiere al observatorului fa de obiectul
accesat. Rafinarea trebuie s mearg pn la a putea specifica
pentru fiecare proprietate i operaie n parte care sunt observatorii
care au acces i care nu.
Aceast protejare i ncapsulare a proprietilor i operaiilor ce se
pot executa cu ajutorul unui obiect are i o alt consecin i
anume aceea c utilizatorul obiectului respectiv este independent de
detaliile constructive ale obiectului respectiv. Structura intern a
obiectului poate fi astfel schimbat i perfecionat n timp fr ca
funcionalitatea de baz s fie afectat.

3.3 Clase de obiecte


n lumea real se pot identifica uor familii de obiecte. Este greu s
descriem ntr-un limbaj de programare fiecare minge din lume dar,
pentru a putea folosi orice minge din lume, este suficient s
34

descriem o singur dat care sunt proprietile unei mingi n


general, precum i operaiile care pot fi executate cu aceasta.
Aceasta nu nseamn c toate obiectele minge din lume sunt
identice. Diferena dintre ele se afl reprezentat n primul rnd n
valorile proprietilor lor care sunt mrimi numerice variabile, adic
difer de la un obiect de acelai fel la altul. De exemplu, n fiecare
obiect minge vom avea un numr natural care reprezint culoarea
mingii. Acest numr poate s difere de la o minge la alta exact aa
cum, n realitate, culoarea difer de la o minge la alta. La fel
coordonatele poziiei mingii la un moment dat sau raza mingii
precum i materialul din care este confecionat au valori care
variaz de la o minge la alta.
Cu alte cuvinte, fiecare minge din lume are acelai set de
proprieti, dar valorile acestora pot s difere de la o minge la alta.
Modelul de reprezentare n memorie a unui obiect este ntotdeauna
acelai, dar valorile memorate n locaiile corespunztoare
proprietilor sunt n general diferite.
n ceea ce privete operaiile, acestea sunt ntotdeauna aceleai dar
rezultatul aplicrii lor poate s difere n funcie de valorile
proprietilor obiectului asupra cruia au fost aplicate. De exemplu,
atunci cnd aruncm o minge spre pmnt ea va ricoa din acesta
ridicndu-se din nou n aer. nlimea la care se va ridica ns, este
dependent de dimensiunile i materialul din care a fost
confecionat mingea. Cu alte cuvinte, noua poziie n spaiu se va
calcula printr-o operaie care va ine cont de valorile memorate n
interiorul obiectului. Se poate ntmpla chiar ca operaia s
hotrasc faptul c mingea va strpunge podeaua n loc s fie
respins de ctre aceasta.
S mai observm c operaiile nu depind numai de proprietile
obiectului ci i de unele valori exterioare acestuia. Atunci cnd
aruncm o minge spre pmnt, nlimea la care va ricoa aceasta
depinde i de viteza cu care a fost aruncat mingea. Aceast vitez
este un parametru al operaiei de aruncare. Nu are nici un rost s
transmitem ca parametrii ai unei operaii valorile proprietilor unui
obiect pentru c acestea sunt ntotdeauna disponibile operaiei. Nici
o operaie nu se poate aplica asupra unui obiect fr s tim exact
care este obiectul respectiv i ce proprieti are acesta. Este absurd
s ne gndim la ce nlime se va ridica o minge n general, fr s
facem presupuneri asupra valorilor proprietilor acesteia. S mai
observm ns c, dac toate mingile ar avea aceleai valori pentru
proprietile implicate n operaia descris mai sus, am putea s
35

calculm nlimea de ricoeu n general, fr s fim dependeni de


o anumit minge.
n concluzie, putem spune c obiectele cu care lucrm fac parte
ntotdeauna dintr-o familie mai mare de obiecte cu proprieti i
comportament similar. Aceste familii de obiecte le vom numi n
continuareclase de obiecte sau concepte n timp ce obiectele
aparinnd unei anumite clase le vom numi instane ale clasei de
obiecte respective. Putem vorbi despre clasa de obiecte minge i
despre instanele acesteia, mulimea tuturor obiectelor minge care
exist n lume. Fiecare instan a clasei minge are un loc bine
precizat n spaiu i n timp, un material i o culoare. Aceste
proprieti difer de la o instan la alta, dar fiecare instan a
aceleiai clase va avea ntotdeauna aceleai proprieti i aceleai
operaii vor putea fi aplicate asupra ei. n continuare vom
numi variabile aceste proprieti ale unei clase de obiecte i vom
numi metode operaiile definite pentru o anumit clas de obiecte.
Pentru a clarifica, s mai relum nc o dat: O clas de obiecte este
o descriere a proprietilor i operaiilor specifice unui nou tip de
obiecte reprezentabile n memorie. O instan a unei clase de
obiecte este un obiect de memorie care respect descrierea clasei. O
variabil a unei clase de obiecte este o proprietate a clasei respective
care poate lua valori diferite n instane diferite ale clasei. O metod
a unei clase este descrierea unei operaii specifice clasei respective.
S mai precizm faptul c, spre deosebire de variabilele unei clase,
metodele acesteia sunt memorate o singur dat pentru toate
obiectele. Comportarea diferit a acestora este dat de faptul c ele
depind de valorile variabilelor.
O categorie aparte a claselor de obiecte este categoria acelor clase
care reprezint concepte care nu se pot instania n mod direct,
adic nu putem construi instane ale clasei respective, de obicei
pentru c nu avem destule informaii pentru a le putea construi. De
exemplu, conceptul de om nu se poate instania n mod direct
pentru c nu putem construi un om despre care nu tim exact dac
este brbat sau femeie. Putem n schimb instania conceptul de
brbat i conceptul de femeie care sunt nite subconcepte ale
conceptului om.
Clasele abstracte, neinstaniabile, servesc n general pentru
definirea unor proprieti sau operaii comune ale mai multor clase
i pentru a putea generaliza operaiile referitoare la acestea. Putem,
36

de exemplu s definim n cadrul clasei de obiecte om modul n care


acesta se alimenteaz ca fiind independent de apartenena la
conceptul de brbat sau femeie. Aceast definiie va fi valabil la
amndou subconceptele definite mai sus. n schimb, nu putem
dect cel mult s precizm faptul c un om trebuie s aib un
comportament social. Descrierea exact a acestui comportament
trebuie fcut n cadrul conceptului de brbat i a celui de femeie.
Oricum, este interesant faptul c, indiferent care ar fi clasa
acestuia, putem s ne bazm pe faptul c acesta va avea definit un
comportament social, specific clasei lui.
Cele dou metode despre care am vorbit mai sus, definite la nivelul
unui superconcept, sunt profund diferite din punctul de vedere al
subconceptelor acestuia. n timp ce metoda de alimentaie este
definit exact i amndou subconceptele pot s o foloseasc fr
probleme, metoda de comportament social este doar o metod
abstract, care trebuie s existe, dar despre care nu se tie exact
cum trebuie definit.
Fiecare dintre subconcepte trebuie s-i defineasc propriul su
comportament social pentru a putea deveni instaniabil. Dac o
clas de obiecte are cel puin o metod abstract, ea devine n
ntregime o clas abstract i nu poate fi instaniat, adic nu
putem crea instane ale unei clase de obiecte abstracte.
Altfel spus, o clas abstract de obiecte este o clas pentru care nu
s-au precizat suficient de clar toate metodele astfel nct s poat fi
folosit n mod direct.

3.4 Derivarea claselor de obiecte


O alt proprietate interesant a claselor de obiecte este aceea de
ierarhizare. Practic, ori de cte ori definim o nou clas de obiecte
care s reprezinte un anumit concept, specificm clasa de obiecte
care reprezint conceptul original din care provine noul concept
mpreun cu diferenele pe care le aduce noul concept derivat fa
de cel original. Aceast operaie de definire a unei noi clase de
obiecte pe baza uneia deja existente o vom numiderivare. Conceptul
mai general se va numi superconcept iar conceptul derivat din
acesta se va numi subconcept. n acelai mod, clasa original se va
numi superclas a noii clase n timp ce noua clas de obiecte se va
numisubclas a clasei derivate.

37

Uneori, n loc de derivare se folosete termenul de extindere.


Termenul vine de la faptul c o subclas i extinde superclasa cu
noi variabile i metode.
n spiritul acestei ierarhizri, putem presupune c toate clasele de
obiecte sunt derivate dintr-o clas iniial, s-i spunem clasa de
obiecte generice, n care putem defini proprietile i operaiile
comune tuturor obiectelor precum ar fi testul de egalitate dintre
dou instane, duplicarea instanelor sau aflarea clasei de care
aparine o anumit instan.
Ierarhizarea se poate extinde pe mai multe nivele, sub form
arborescent, n fiecare punct nodal al structurii arborescente
rezultate aflndu-se clase de obiecte. Desigur, clasele de obiecte de
pe orice nivel pot avea instane proprii, cu condiia s nu fie clase
abstracte, imposibil de instaniat.

Figura 3.2 O ierarhie de clase de obiecte n care clasele sunt reprezentate n cmpuri eliptice
iar instanele acestora n cmpuri dreptunghiulare. Clasele abstracte de obiecte au elipsa
dublat.

Desigur, este foarte dificil s construim o ierarhie de clase de obiecte


complet, care s conin clase de obiecte corespunztoare fiecrui
concept cunoscut. Din fericire, pentru o problem dat, conceptele
implicate n rezolvarea ei sunt relativ puine i pot fi uor izolate,
simplificate i definite. Restrngerea la minimum a arborelui de
concepte necesar rezolvrii unei anumite probleme fr a se afecta
generalitatea soluiei este un talent pe care fiecare programator
trebuie s i-l descopere i s i-l cultive cu atenie. De alegerea
acestor concepte depinde eficiena i flexibilitatea aplicaiei.
O clas de obiecte derivat dintr-o alt clas pstreaz toate
proprietile i operaiile acesteia din urm aducnd n plus
38

proprieti i operaii noi. De exemplu, dac la nivelul clasei de


obiecte om am definit forma biped a acestuia i capacitatea de a
vorbi i de a nelege, toate acestea vor fi motenite i de ctre
clasele derivate din clasa om, i anume clasa brbailor i cea a
femeilor. Fiecare dintre aceste clase de obiecte derivate i vor defini
propriile lor proprieti i operaii pentru a descrie diferena dintre
ele i clasa original.
Unele dintre proprietile i operaiile definite n superclas pot fi
redefinite n subclasele de obiecte derivate. Vechile proprieti i
operaii sunt disponibile n continuare, doar c pentru a le putea
accesa va trebui s fie specificat explicit superclasa care deine
copia redefinit. Operaia de redefinire a unor operaii sau variabile
din interiorul unei clase n timpul procesului de derivare o vom
numi rescriere.
Aceast redefinire ne d de fapt o mare flexibilitate n construcia
ierarhiei unei probleme date pentru c nici o proprietate sau
operaie definit ntr-un punct al ierarhiei nu este impus definitiv
pentru conceptele derivate din acest punct direct sau nu.
Revenind pentru un moment la protejarea informaiilor interne ale
unui obiect s precizm faptul c gradul de similitudine de care
vorbeam mai sus este mrit n cazul n care vorbim de dou clase
derivate una din cealalt. Cu alte cuvinte, o subclas a unei clase
are acces de obicei la mult mai multe informaii memorate n
superclasa sa dect o alt clas de obiecte oarecare. Acest lucru
este firesc innd cont de faptul c, uneori, o subclas este nevoit
s redefineasc o parte din funcionalitatea superclasei sale.

3.5 Interfee spre obiecte


Un obiect este o entitate complex pe care o putem privi din diverse
puncte de vedere. Omul de exemplu poate fi privit ca un mamifer
care nate pui vii sau poate fi privit ca o fiin gnditoare care
nv s programeze calculatoare sau poate fi privit ca un simplu
obiect spaio-temporal care are propria lui form i poziie n funcie
de timp.
Aceast observaie ne spune c trebuie s dm definiii despre ce
nseamn cu adevrat faptul c un obiect poate fi privit ca un
mamifer sau ca o fiina gnditoare sau ca un obiect spaio-temporal.
Aceste definiii, pe care le vom numi n continuare interfee, sunt
aplicabile nu numai clasei de obiecte om dar i la alte clase de
39

obiecte derivate sau nu din acesta, superclase sau nu ale acesteia.


Putem s gsim o mulime de clase de obiecte ale cror instane pot
fi privite ca obiecte spaio-temporale dar care s nu aib mare lucru
n comun cu omul. Practic, atunci cnd construim o interfa,
definim un set minim de operaii care trebuie s aparin obiectelor
care respect aceast interfa. Orice clas de obiecte care declar
c respect aceast interfa va trebui s defineasc toate operaiile.
Operaiile ns, sunt definite pe ci specifice fiecrei clase de obiecte
n parte. De exemplu, orice obiect spaial trebuie s defineasc o
operaie de modificare a poziiei n care se afl. Dar aceast operaie
este diferit la un om, care poate s-i schimbe singur poziia, fa
de o minge care trebuie ajutat din exterior pentru a putea fi
mutat. Totui, dac tim cu siguran c un obiect este o instan
a unui clase de obiecte care respect interfaa spatio-temporal,
putem linitii s executm asupra acestuia o operaie de schimbare
a poziiei, fr s trebuiasc s cunoatem amnunte despre modul
n care va fi executat aceast operaie. Tot ceea ce trebuie s tim
este faptul c operaia este definit pentru obiectul respectiv.
n concluzie, o interfa este un set de operaii care trebuiesc
definite de o clas de obiecte pentru a se nscrie ntr-o anumit
categorie. Vom spune despre o clas care definete toate operaiile
unei interfee c implementeaz interfaa respectiv.
Cu alte cuvinte, putem privi interfeele ca pe nite reguli de
comportament impuse claselor de obiecte. n clipa n care o clas
implementeaz o anumit interfa, obiectele din clasa respectiv
pot fi privite n exclusivitate din acest punct de vedere. Interfeele
pot fi privite ca nite filtre prin care putem privi un anumit obiect,
filtre care nu las la vedere dect proprietile specifice interfeei,
chiar dac obiectul n vizor este mult mai complicat n realitate.
Interfeele creaz o alt mprire a obiectelor cu care lucrm. n
afar de mprirea normal pe clase, putem s mprim obiectele
i dup interfeele pe care le implementeaz. i, la fel cu situaia n
care definim o operaie doar pentru obiectele unei anumite clase,
putem defini i operaii care lucreaz doar cu obiecte care
implementeaz o anumit interfa, indiferent de clasa din care
acestea fac parte.

40

Capitolul IV
Structura lexical Java
4.1 Setul de caractere
4.2 Uniti lexicale
4.2.1 Cuvinte cheie
4.2.2 Identificatori
4.2.3 Literali
4.2.3.1
4.2.3.2
4.2.3.3
4.2.3.4
4.2.3.5

Literali ntregi
Literali flotani
Literali booleeni
Literali caracter
Literali ir de caractere

4.2.4 Separatori
4.2.5 Operatori
4.3 Comentarii

4.1 Setul de caractere


Limbajului Java lucreaz n mod nativ folosind setul de caractere
Unicode. Acesta este un standard internaional care nlocuiete
vechiul set de caractere ASCII. Motivul acestei nlocuiri a fost
necesitatea de a reprezenta mai mult de 256 de caractere. Setul de
caractere Unicode, fiind reprezentat pe 16 bii are posibiliti mult
mai mari.
Vechiul standard ASCII este ns un subset al setului Unicode, ceea
ce nseamn c vom regsi caracterele ASCII cu exact aceleai
coduri ca i mai nainte n noul standard.
Java folosete setul Unicode n timpul rulrii aplicaiilor ca i n
timpul compilrii acestora. Folosirea Unicode n timpul execuiei nu
nseamn nimic altceva dect faptul c o variabil Java de tip
caracter este reprezentat pe 16 bii iar un ir de caractere va ocupa
fizic n memorie de doua ori mai muli octei dect numrul
caracterelor care formeaz irul.
n ceea ce privete folosirea Unicode n timpul compilrii,
compilatorul Java accept la intrare fiiere surs care pot conine
41

orice caractere Unicode. Se poate lucra i cu fiiere ASCII obinuite


n care putem introduce caractere Unicode folosind secvene escape.
Fiierele surs sunt fiiere care conin declaraii i instruciuni
Java. Aceste fiiere trec prin trei pai distinci la citirea lor de ctre
compilator:
1. irul de caractere Unicode sau ASCII, memorat n fiierul
surs, este transformat ntr-un ir de caractere Unicode.
Caracterele Unicode pot fi introduse i ca secvene escape
folosind doar caractere ASCII.
2. irul de caractere Unicode este transformat ntr-un ir de
caractere n care sunt evideniate separat caracterele de
intrare fa de caracterele de sfrit de linie.
3. irul de caractere de intrare i de sfrit de linie este
transformat ntr-un ir de cuvinte ale limbajului Java.
n primul pas al citirii fiierului surs, sunt generate secvene
escape.Secvenele escape sunt secvene de caractere ASCII care
ncep cu caracterul backslash \. Pentru secvenele escape Unicode,
al doilea caracter din secven trebuie s fie u sau U. Orice alt
caracter care urmeaz dup backslash va fi considerat ca fiind
caracter nativ Unicode i lsat nealterat. Dac al doilea caracter din
secvena escape este u, urmtoarele patru caractere ASCII sunt
tratate ca i cifre hexazecimale (n baza 16) care formeaz mpreun
doi octei de memorie care reprezint un caracter Unicode.
Se pot folosi la intrare i fiiere ASCII normale, pentru c ASCII este
un subset al Unicode. De exemplu, putem scrie:
int f\u0660 = 3;

Numele variabilei are dou caractere i al doilea caracter este o cifr


arabic-indic.
Exemple de secvene Unicode:
\uaa08 \U0045 \uu6abe

n al doilea pas al citirii fiierului surs, sunt recunoscute ca i


caractere de sfrit de linie caracterele ASCII CR i ASCII LF. n
acelai timp, secvena de caractere ASCII CR-ASCII LF este tratat
ca un singur sfrit de linie i nu dou. n acest mod, Java suport
n comun standardele de terminare a liniilor folosite de diferite
sisteme de operare: MacOS, Unix i DOS.

42

Este important s separm caracterele de sfrit de linie de restul


caracterelor de intrare pentru a ti unde se termin comentariile de
o singur linie (care ncep cu secvena //) precum i pentru a
raporta odat cu erorile de compilare i linia din fiierul surs n
care au aprut acestea.
n pasul al treilea al citirii fiierului surs, sunt izolate elementele
de intrare ale limbajului Java, i anume: spaii, comentarii i uniti
lexicale.
Spaiile pot fi caracterele ASCII SP (spaiu), FF (avans de pagin)
sau HT (tab orizontal) precum i orice caracter terminator de linie.
Comentariile le vom discuta n paragraful 4.3.

4.2 Uniti lexicale


Unitile lexicale sunt elementele de baz cu care se construiete
semantica programelor Java. n irul de cuvinte de intrare, unitile
lexicale sunt separate ntre ele prin comentarii i spaii. Unitile
lexicale n limbajul Java pot fi:

Cuvinte cheie
Identificatori
Literali
Separatori
Operatori

4.2.1 Cuvinte cheie


Cuvintele cheie sunt secvene de caractere ASCII rezervate de limbaj
pentru uzul propriu. Cu ajutorul lor, Java i definete unitile
sintactice de baz. Nici un program nu poate s utilizeze aceste
secvene altfel dect n modul n care sunt definite de limbaj.
Singura excepie este aceea c nu exist nici o restricionare a
apariiei cuvintelor cheie n iruri de caractere sau comentarii.
Cuvintele cheie ale limbajului Java sunt:
abstract
boolean
break
byte
case
cast
catch
char
class

for
future
generic
goto
if
implements
import
inner
instanceof

public
rest
return
short
static
super
switch
synchronized
this

43

const
continue
default
do
double
else
extends
final
finally
float

intinterface
long
native
new
null
operator
outer
package
private
protected

throw
throws
transient
try
var
void
volatile
while
byvalue

Dintre acestea, cele ngroate sunt efectiv folosite, iar restul sunt
rezervate pentru viitoare extensii ale limbajului.
4.2.2 Identificatori
Identificatorii Java sunt secvene nelimitate de litere i cifre Unicode,
ncepnd cu o liter. Identificatorii nu au voie s fie identici cu
cuvintele rezervate.
Cifrele Unicode sunt definite n urmtoarele intervale:
Reprezentare Unicode Caracter ASCII
\u0030-\u0039

0-9

Explicaie
cifre ISO-LATIN-1

\u0660-\u0669

cifre Arabic-Indic

\u06f0-\u06f9

cifre Eastern Arabic-Indic

\u0966-\u096f

cifre Devanagari

\u09e6-\u09ef

cifre Bengali

\u0a66-\ u0a6f

cifre Gurmukhi

\u0ae6-\u0aef

cifre Gujarati

\u0b66-\u0b6f

cifre Oriya

\u0be7-\u0bef

cifre Tamil

\u0c66-\u0c6f

cifre Telugu

\u0ce6-\u0cef

cifre Kannada

\u0d66-\u0d6f

cifre Malayalam

\u0e50-\u0e59

cifre Thai

\u0ed0-\u0ed9

cifre Lao

\u1040-\u1049

cifre Tibetan
Tabelul 4.1 Cifrele Unicode.

44

Un caracter Unicode este o liter dac este n urmtoarele intervale


i nu este cifr:
Reprezentare
Unicode

Caracter
ASCII

Explicaie

\u0024

semnul dolar (din motive istorice)

\u0041-\u005a

A-Z

litere majuscule Latin

\u005f

underscore (din motive istorice)

\u0061-\u007a

a-z

litere minuscule Latin

\u00c0-\u00d6

diferite litere Latin cu diacritice

\u00d8-\u00f6

diferite litere Latin cu diacritice

\u00f8-\u00ff

diferite litere Latin cu diacritice

\u0100-\u1fff

alte alfabete i simboluri non-CJK

\u3040-\u318f

Hiragana, Katakana, Bopomofo, i


Hangul

\u3300-\u337f

cuvinte ptratice CJK

\u3400-\u3d2d

simboluri Hangul coreene

\u4e00-\u9fff

Han (Chinez, Japonez, Corean)

\uf900-\ufaff

compatibilitate Han
Tabelul 4.2 Literele Unicode.

4.2.3 Literali
Un literal este modalitatea de baz de exprimare n fiierul surs a
valorilor pe care le pot lua tipurile primitive i tipul ir de caractere.
Cu ajutorul literalilor putem introduce valori constante n variabilele
de tip primitiv sau n variabilele de tip ir de caractere.
n limbajul Java exist urmtoarele tipuri de literali:

literali
literali
literali
literali
literali

ntregi
flotani
booleeni
caracter
ir de caractere

4.2.3.1 Literali ntregi

45

Literalii ntregi pot fi reprezentai n baza 10, 16 sau 8. Toate


caracterele care se folosesc pentru scrierea literalilor ntregi fac
parte din subsetul ASCII al setului Unicode.
Literalii ntregi pot fi ntregi normali sau lungi. Literalii lungi se
recunosc prin faptul c se termin cu sufixul l sau L. Un literal
ntreg este reprezentat pe 32 de bii iar unul lung pe 64 de bii.
Un literal ntreg n baza 10 ncepe cu o cifr de la 1 la 9 i se
continu cu un ir de cifre de la 0 la 9. Un literal ntreg n baza 10
nu poate s nceap cu cifra 0, pentru c acesta este semnul folosit
pentru a semnaliza literalii scrii n baza 8.
Exemple de literali ntregi n baza 10:
12356L234871234567890l

Exemplul al doilea i al patrulea sunt literali ntregi lungi.


Pentru a exprima un literal ntreg n baza 16 trebuie s definim
cifrele de la 10 la 15. Convenia va fi urmtoarea:
10 - a, A13 - d, D
11 - b, B14 - e, E
12 - c, C15 - f, F

n plus, pentru c un literal ntreg n baza 16 poate ncepe cu o


liter, vom aduga prefixul 0x sau 0X. Dac nu am aduga acest
sufix, compilatorul ar considera c este vorba despre un
identificator.
Exemple de literali ntregi n baza 16:
0xa340X1230x2c45L0xde123abccdL

Ultimele dou exemple sunt literali ntregi lungi.


n fine, pentru a reprezenta un literal ntreg n baza 8, l vom
preceda cu cifra 0. Restul cifrelor pot fi oricare ntre 0 i 7. Cifrele 8
i 9 nu sunt admise n literalii ntregi n baza 8.
Exemple de literali ntregi n baza 8:
0234500123001234567712345677L

Valoarea maxim a unui literal ntreg normal este de 2147483647


(231-1), scris n baza 10. n baza 16, cel mai mare literal pozitiv se
46

scrie ca0x7fffffff iar n baza 8 ca 017777777777. Toate trei


scrierile reprezint de fapt aceeai valoare, doar c aceasta este
exprimat n baze diferite.
Cea mai mic valoare a unui literal ntreg normal este -2147483648
(-231), respectiv 0x80000000 i 020000000000.
Valorile 0xffffffff i037777777777 reprezint amndou valoarea
-1.
Specificarea n surs a unui literal ntreg normal care depete
aceste limite reprezint o eroare de compilare. Cu alte cuvinte, dac
folosim n surs numrul: 21474836470 de exemplu, fr s punem
sufixul de numr lung dup el, compilatorul va genera o eroare la
analiza sursei.
Valoarea maxim a unui literal ntreg lung este, n baza
10,9223372036854775807L (263-1). n octal, asta
nseamn0777777777777777777777L iar n baza
16 0x7fffffffffffffffL. n mod asemntor, valoarea minim a
unui literal ntreg lung este -9223372036854775808L (-263-1), n
octal aceast valoare este0400000000000000000000L iar n baza 16
este 0x8000000000000000L.
La fel ca i la literalii ntregi normali, depirea acestor limite este o
eroare de compilare.
4.2.3.2 Literali flotani
Literalii flotani reprezint numere reale. Ei sunt formai dintr-o
parte ntreag, o parte fracionar, un exponent i un sufix de tip.
Exponentul, dac exist, este introdus de litera e sau E urmat
opional de un semn al exponentului.
Este obligatoriu s existe mcar o cifr fie n partea ntreag fie n
partea zecimal i punctul zecimal sau litera e pentru exponent.
Sufixul care indic tipul flotantului poate fi f sau F n cazul n care
avem o valoare flotant normal i d sau D dac avem o valoare
flotant dubl. Dac nu este specificat nici un sufix, valoarea este
implicit dubl.
Valoarea maxim a unui literal flotant normal
este 3.40282347e+38f iar valoarea cea mai mic reprezentabil
este 1.40239846e-45f, ambele reprezentate pe 32 de bii.
47

Valoarea maxim reprezentabil a unui literal flotant dublu este


de1.79769313486231570e+308 iar valoarea cea mai mic
reprezentabil este4.94065645841246544e-324, ambele
reprezentate pe 64 de bii.
La fel ca i la literalii ntregi, este o eroare s avem exprimat n
surs un literal mai mare dect valoarea maxim reprezentabil sau
mai mic dect cea mai mic valoare reprezentabil.
Exemple de literali flotani:
1.0e45f-3.456f0..01e-3

Primele dou exemple reprezint literali flotani normali, iar celelalte


literali flotani dubli.
4.2.3.3 Literali booleeni
Literalii booleeni nu pot fi dect true sau false, primul
reprezentnd valoarea boolean de adevr iar cellalt valoarea
boolean de fals. True ifalse nu sunt cuvinte rezervate ale
limbajului Java, dar nu vei putea folosi aceste cuvinte ca
identificatori.
4.2.3.4 Literali caracter
Un literal de tip caracter este utilizat pentru a exprima caracterele
codului Unicode. Reprezentarea se face fie folosind o liter, fie o
secven escape. Secvenele escape ne permit reprezentarea
caracterelor care nu au reprezentare grafic i reprezentarea unor
caractere speciale precum backslash i nsi caracterul apostrof.
Caracterele care au reprezentare grafic pot fi reprezentate ntre
apostrofe, ca n exemplele:
'a' '' ','

Pentru restul caracterelor Unicode trebuie s folosim secvene


escape. Dintre acestea, cteva sunt predefinite n Java, i anume:
Secven escape

Caracterul reprezentat

'\b'

caracterul backspace BS \u0008

'\t'

caracterul tab orizontal HT \u0009

'\n'

caracterul linefeed LF \u000a


48

'\f'

caracterul formfeed FF \u000c

'\r'

caracterul carriage return CR \u000d

'\"'

caracterul ghilimele \u0022

'\''

caracterul apostrof \u0027

'\\'

caracterul backslash \u005c

Tabelul 4.3 Secvene escape predefinite n Java.

n form general, o secven escape se scrie sub una din formele:


'\o' '\oo''\too'

unde o este o cifr octal iar t este o cifr octal ntre 0 i 3.


Nu este corect s folosii ca valori pentru literale caracter
secvena'\u000d' (caracterul ASCII CR), sau altele care reprezint
caractere speciale, pentru c acestea fiind secvene escape Unicode
sunt transformate foarte devreme n timpul procesrii sursei n
caractere CR i sunt interpretate ca terminatori de linie.
Exemple de secvene escape:
'\n''\u23a''\34'

dac dup caracterul backslash urmeaz altceva


dect: b, t, n, f, r, ",', \, 0, 1, 2, 3, 4, 5, 6, 7 se va semnala
o eroare de compilare.
n acest moment secvenele escape Unicode au fost deja nlocuite cu
caractere Unicode native. Dac u apare dup \, se semnaleaz o
eroare de compilare.
4.2.3.5 Literali ir de caractere
Un literal ir de caractere este format din zero sau mai multe
caractere ntre ghilimele. Caracterele care formeaz irul de
caractere pot fi caractere grafice sau secvene escape ca cele definite
la literalii caracter.
Dac un literal ir de caractere conine n interior un caracter
terminator de linie va fi semnalat o eroare de compilare. Cu alte
cuvinte, nu putem avea n surs ceva de forma:
"Acesta este

49

greit!

chiar dac aparent exprimarea ar reprezenta un ir format din


caracterele A, c, e, s, t, a, spaiu, e, s, t, e, linie nou, g, r, e, , i, t, !.
Dac dorim s introducem astfel de caractere terminatoare de linie
ntr-un ir va trebui s folosim secvene escape ca n:
Acesta este\ngreit

Dac irul de caractere este prea lung, putem s-l spargem n


buci mai mici pe care s le concatenm cu operatorul +.
Fiecare ir de caractere este n fapt o instan a clasei de
obiecte Stringdeclarat standard n pachetul java.lang.
Exemple de iruri de caractere:
"""\"""ir de caractere""unu" + "doi"

Primul ir de caractere din exemplu nu conine nici un caracter i


se numete irul vid. Ultimul exemplu este format din dou iruri
distincte concatenate.
4.2.4 Separatori
Un separator este un caracter care indic sfritul unei uniti
lexicale i nceputul alteia. Separatorii sunt necesari atunci cnd
uniti lexicale diferite sunt scrise fr spaii ntre ele. Acestea se
pot totui separa dac unele dintre ele conin caractere separatori.
n Java separatorii sunt urmtorii:
( ) { } [ ] ; , .

Exemple de separare:
a[i]sin(56)

n primul exemplu nu avem o singur unitate lexical ci patru: a, [,


i, ]. Separatorii [ i ] ne dau aceast informaie. n al doilea exemplu,
unitile lexicale sunt tot 4 sin, (, 56, ).
Atenie, separatorii particip n acelai timp i la construcia
sintaxei limbajului. Ei nu sunt identici cu spaiile dei, ca i
acestea, separ uniti lexicale diferite.
4.2.5 Operatori
50

Operatorii reprezint simboluri grafice pentru operaiile elementare


definite de limbajul Java. Despre operatori vom discuta mai mult
atunci cnd vom prezenta expresiile. Deocamdat, iat lista tuturor
operatorilor limbajului Java:
=><!~?:
==<=>=!=&&||++-+-*/&|^%<<>> >>>
+=-=*=/=&=|=^=%=<<=>>=>>>=

S mai precizm deocamdat c toi operatorii joac i rol de


separatori. Cu alte cuvinte, din secvena de caractere:
vasile+gheorghe

putem extrage trei uniti lexicale, vasile, + i gheorghe.

4.3 Comentarii
Un comentariu este o secven de caractere existent n fiierul
surs dar care servete doar pentru explicarea sau documentarea
sursei i nu afecteaz n nici un fel semantica programelor.
n Java exist trei feluri de comentarii:

Comentarii pe mai multe linii, nchise ntre /* i */. Toate


caracterele dintre cele dou secvene sunt ignorate.
Comentarii pe mai multe linii care in de documentaie,
nchise ntre /** i */. Textul dintre cele dou secvene este
automat mutat n documentaia aplicaiei de ctre generatorul
automat de documentaie.
Comentarii pe o singur linie care ncep cu //. Toate
caracterele care urmeaz acestei secvene pn la primul
caracter sfrit de linie sunt ignorate.

n Java, nu putem s scriem comentarii n interiorul altor


comentarii. La fel, nu putem introduce comentarii n interiorul
literalilor caracter sau ir de caractere. Secvenele /* i */ pot s
apar pe o linie dup secvena // dar i pierd semnificaia. La fel se
ntmpl cu secvena // n comentarii care ncep cu /* sau /**.
Ca urmare, urmtoarea secven de caractere formeaz un singur
comentariu:
/* acest comentariu /* // /* se termin abia aici: */

51

Capitolul V
5.1 Variabile
5.1.1 Declaraii de variabile
5.1.1.1 Tipul unei variabile
5.1.1.2 Numele variabilelor
5.1.1.3 Iniializarea variabilelor
5.1.2 Tipuri primitive
5.1.2.1 Tipul boolean
5.1.2.2 Tipul caracter
5.1.2.3 Tipuri ntregi
5.1.2.3.1 Tipul octet
5.1.2.3.2 Tipul ntreg scurt
5.1.2.3.3 Tipul ntreg
5.1.2.3.4 Tipul ntreg lung
5.1.2.4 Tipuri flotante
5.1.2.4.1 Tipul flotant
5.1.2.4.2 Tipul flotant dublu
5.1.2.4.3 Reali speciali definii de IEEE
5.1.3 Tipuri referin
5.1.3.1 Tipul referin ctre o clas
5.1.3.2 Tipul referin ctre o interfa
5.1.3.3 Tipul referin ctre un tablou
5.1.4 Clasa de memorare
5.1.4.1 Variabile locale
5.1.4.2 Variabile statice
5.1.4.3 Variabile dinamice
5.1.5 Tablouri de variabile
5.1.5.1 Declaraia variabilelor de tip tablou
5.1.5.2 Iniializarea tablourilor.
5.1.5.3 Lungimea tablourilor
52

5.1.5.4 Referirea elementelor din tablou


5.1.5.5 Alocarea i eliberarea tablourilor
5.1.6 Conversii
5.1.6.1
5.1.6.2
5.1.6.3
5.1.6.4
5.1.6.5
5.1.6.6

Conversii de extindere a valorii


Conversii de trunchiere a valorii
Conversii pe tipuri referin
Conversii la operaia de atribuire
Conversii explicite
Conversii de promovare aritmetic

5.1.1 Declaraii de variabile


O variabil n limbajul Java este o locaie de memorie care poate
pstra o valoare de un anumit tip. n ciuda denumirii, exist
variabile care i pot modifica valoarea i variabile care nu i-o pot
modifica, numite n Javavariabile finale. Orice variabil trebuie s
fie declarat pentru a putea fi folosit. Aceast declaraie trebuie s
conin un tip de valori care pot fi memorate n locaia rezervat
variabilei i un nume pentru variabila declarat. n funcie de locul
n sursa programului n care a fost declarat
variabila, aceasta primete o clas de memorare local sau static.
Aceast clas de memorare definete intervalul de existen al
variabilei n timpul execuiei.
n forma cea mai simpl, declaraia unei variabile arat n felul
urmtor:
Tip NumeVariabil [, NumeVariabil]*;

5.1.1.1 Tipul unei variabile


Tipul unei variabile poate fi fie unul dintre tipurile primitive definite
de limbajul Java fie o referin. Creatorii limbajului Java au avut
grij s
defineasc foarte exact care sunt caracteristicile fiecrui tip primitiv
n parte i care este setul de valori care se poate memora n
variabilele care au tipuri primitive. n plus, a fost exact definit i
modalitatea de reprezentare a acestor tipuri primitive n memorie. n
acest fel, variabilele Java devin independente de platforma hardware
i software pe care lucreaz.
53

n acelai spirit, Java definete o valoare implicit pentru fiecare tip


de dat, n cazul n care aceasta nu a primit nici o valoare de la
utilizator. n acest fel, tim ntotdeauna care este valoarea cu care o
variabil intr n calcul. Este o practic bun ns aceea ca
programele s nu depind niciodat de aceste iniializri
implicite.
5.1.1.2 Numele variabilelor
Numele variabilei poate fi orice identificator Java. Convenia
nescris de formare a numelor variabilelor este aceea c orice
variabil care nu este final are un nume care ncepe cu liter
minuscul n timp ce
variabilele finale au nume care conin numai majuscule. Dac
numele unei variabile care nu este final conine mai multe cuvinte,
cuvintele ncepnd cu cel de-al doilea se scriu cu litere minuscule
dar cu prima liter majuscul. Exemple de nume de variabile care
nu sunt finale ar putea fi:
culoarea numrulDePai urmtorulElement

Variabilele finale ar putea avea nume precum:


PORTOCALIUVERDEALBASTRUDESCHIS

5.1.1.3 Iniializarea variabilelor


Limbajul Java permite iniializarea valorilor variabilelor chiar n
momentul declarrii acestora. Sintaxa este urmtoarea:
Tip NumeVariabil = ValoareIniial;

Desigur, valoarea iniial trebuie s fie de acelai tip cu tipul


variabilei sau s poat fi convertit ntr-o valoare de acest tip.
Dei limbajul Java ne asigur c toate variabilele au o valoare
iniial bine precizat, este preferabil s executm aceast
iniializare n mod explicit pentru fiecare declaraie. n acest fel
mrim claritatea propriului cod.
Regula ar fi deci urmtoarea: nici o declaraie fr iniializare.
5.1.2 Tipuri primitive
5.1.2.1 Tipul boolean
54

Tipul boolean este folosit pentru memorarea unei valori de adevr.


Pentru acest scop, sunt suficiente doar dou valori: adevrat i fals.
n Java aceste dou valori le vom nota prin literalii true i
respectiv false.
Aceste valori pot fi reprezentate n memorie folosindu-ne de o
singur cifr binar, adic pe un bit.
Valorile booleene sunt foarte importante n limbajul Java pentru c
ele sunt valorile care se folosesc n condiiile care controleaz
instruciunile repetitive sau cele condiionale. Pentru a exprima o
condiie este suficient s scriem o expresie al crui rezultat este o
valoare boolean, adevrat sau fals.
Valorile de tip boolean nu se pot transforma n valori de alt tip n
mod nativ. La fel, nu exist transformare nativ dinspre celelalte
valori nspre tipul boolean. Cu alte cuvinte, avnd o variabil de tip
boolean nu putem memora n interiorul acesteia o valoare ntreag
pentru c limbajul Java nu face pentru noi nici un fel de
presupunere legat de ce nseamn o anumit valoare ntreag din
punctul de vedere al valorii de adevr. La fel, dac avem o variabil
ntreag, nu i putem atribui o valoare de tip boolean.
Orice variabil boolean nou creat primete automat valoarea
implicitfalse. Putem modifica aceast comportare specificnd n
mod explicit o valoare iniial true dup modelul pe care l vom
descrie mai trziu.
Pentru a declara o variabil de tip boolean, n Java vom folosi
cuvntul rezervat boolean ca n exemplele de mai jos:
boolean terminat;
boolean areDreptate;

Rndurile de mai sus reprezint declaraia a dou variabile de tip


boolean numite terminatrespectiv areDreptate. Cele dou variabile au,
dup declaraie, valoarea false. Adic nu e terminat dar nici n-are
dreptate.
5.1.2.2 Tipul caracter
Orice limbaj de programare ne ofer ntr-un fel sau altul
posibilitatea de a lucra cu caractere grafice care s reprezinte litere,
cifre, semne de punctuaie, etc. n cazul limbajului Java acest lucru
se poate face folosind tipul primitiv numit tip caracter.
55

O variabil de tip caracter poate avea ca valoare coduri Unicode


reprezentate pe 16 bii, adic doi octei. Codurile reprezentabile
astfel sunt foarte multe, putnd acoperi caracterele de baz din
toate limbile scrise existente.
n Java putem combina mai multe caractere pentru a forma cuvinte
sau iruri de caractere mai lungi. Totui, trebuie s precizm c
aceste iruri de caractere nu trebuiesc confundate cu tablourile de
caractere pentru c ele conin n plus informaii legate de lungimea
irului.
Codul nu este altceva dect o coresponden ntre numere i
caractere fapt care permite conversii ntre variabile ntregi i
caractere n ambele sensuri. O parte din aceste transformri pot s
altereze valoarea original din cauza dimensiunilor diferite ale
zonelor n care sunt memorate cele dou tipuri de valori.
Convertirea caracterelor n numere i invers poate s fie util la
prelucrarea n bloc a caracterelor, cum ar fi trecerea tuturor literelor
minuscule n majuscule i invers.
Atunci cnd declarm un caracter fr s specificm o valoare
iniial, el va primi automat ca valoare implicit caracterul nullal
codului Unicode, \u0000?.
Pentru a declara o variabil de tip caracter folosim cuvntul
rezervat charca n exemplele urmtoare:
char primaLiter;
char prima, ultima;

n cele dou linii de cod am declarat trei variabile de tip caracter


care au fost automat iniializate cu caracterul null. n continuare,
vom folosi interschimbabil denumirea de tip caracter cu denumirea
de tip char, care are avantajul c este mai aproape de declaraiile
Java.
5.1.2.3 Tipuri ntregi
5.1.2.3.1 Tipul octet

ntre tipurile ntregi, acest tip ocup un singur octet de memorie,


adic opt cifre binare. ntr-o variabil de tip octet sunt reprezentate
ntotdeauna valori cu semn, ca de altfel n toate variabilele de tip
ntreg definite n limbajul Java. Aceast convenie simplific schema
de tipuri primitive care, n cazul altor limbaje include separat tipuri
ntregi cu semn i fr.
56

Fiind vorba de numere cu semn, este nevoie de o convenie de


reprezentare a semnului. Convenia folosit de Java este
reprezentarea n complement fa de doi. Aceast reprezentare este
de altfel folosit de majoritatea limbajelor actuale i permite
memorarea, pe 8 bii a 256 de numere ncepnd de la -128 pn
la 127. Dac avei nevoie de numere mai mari n valoare absolut,
apelai la alte tipuri ntregi.
Valoarea implicit pentru o variabil neiniializat de tip octet este
valoarea 0 reprezentat pe un octet.
Iat i cteva exemple de declaraii care folosesc cuvntul Java
rezervatbyte:
byte octet;
byte eleviPeClasa;

n continuare vom folosi interschimbabil denumirea de tip octet cu


cea de tip byte.
5.1.2.3.2 Tipul ntreg scurt

Tipul ntreg scurt este similar cu tipul octet dar valorile sunt
reprezentate pe doi octei, adic 16 bii. La fel ca i la tipul octet,
valorile
sunt ntotdeauna cu semn i se folosete reprezentarea n
complement fa de doi. Valorile de ntregi scuri reprezentabile sunt
de la -32768 la 32767 iar valoarea implicit este 0 reprezentat pe doi
octei.
Pentru declararea variabilelor de tip ntreg scurt n Java se folosete
cuvntul rezervat short, ca n exemplele urmtoare:
short i, j;
short valoareNuPreaMare;

n continuare vom folosi interschimbabil denumirea de tip ntreg


scurt i cea de tip short.
5.1.2.3.3 Tipul ntreg

Singura diferen dintre tipul ntreg i tipurile precedente este


faptul c valorile sunt reprezentate pe patru octei adic 32 bii.
Valorile reprezentabile sunt de la -2147483648 la 2147483647 valoarea
implicit fiind 0. Cuvntul rezervat este int ca n:
57

int salariu;

n continuare vom folosi interschimbabil denumirea de tip ntreg i


cea de tip int.
5.1.2.3.4 Tipul ntreg lung

n fine, pentru cei care vor s reprezinte numerele ntregi cu semn


pe 8 octei, 64 de bii, exist tipul ntreg lung. Valorile
reprezentabile sunt de la -9223372036854775808 la 9223372036854775807 iar
valoarea implicit este 0L.
Pentru cei care nu au calculatoare care lucreaz pe 64 de bii este
bine de precizat faptul c folosirea acestui tip duce la operaii lente
pentru c nu exist operaii native ale procesorului care s lucreze
cu numere aa de mari.
Declaraia se face cu cuvntul rezervat long. n continuare vom folosi
interschimbabil denumirea de tip ntreg lung cu cea de tip long.
5.1.2.4 Tipuri flotante
Acest tip este folosit pentru reprezentarea numerelor reale sub
form de exponent i cifre semnificative. Reprezentarea se face pe
patru octei, 32 bii, aa cum specific standardul IEEE 754.
5.1.2.4.1 Tipul flotant

Valorile finite reprezentabile ntr-o variabil de tip flotant sunt de


forma:
sm2e

unde s este semnul +1 sau -1, m este partea care specific cifrele
reprezentative ale numrului, numit i mantis, un ntreg pozitiv
mai mic dect 224 iar e este un exponent ntreg ntre -149 i 104.
Valoarea implicit pentru variabilele flotante este 0.0f. Pentru
declararea unui numr flotant, Java definete cuvntul
rezervat float. Declaraiile se fac ca n exemplele urmtoare:
float procent;
float noi, ei;

n continuare vom folosi interschimbabil denumirea de tip flotant i


cea de tip float.

58

5.1.2.4.2 Tipul flotant dublu

Dac valorile reprezentabile n variabile flotante nu sunt destul de


precise sau destul de mari, putei folosi tipul flotant dublu care
folosete opt octei pentru reprezentare, urmnd acelai standard
IEEE 754
Valorile finite reprezentabile cu flotani dubli sunt de forma:
sm2e

unde s este semnul +1 sau -1, m este mantisa, un ntreg pozitiv mai
mic dect 253 iar e este un exponent ntreg ntre -1045 i 1000.
Valoarea implicit n acest caz este 0.0d.
Pentru a declara flotani dubli, Java definete cuvntul
rezervat double ca n:
double distanaPnLaLun;

n continuare vom folosi interschimbabil denumirea de tip flotant


dublu i cea de tip double.
n afar de valorile definite pn acum, standardul IEEE definete
cteva valori speciale reprezentabile pe un flotant sau un flotant
dublu.
5.1.2.4.3 Reali speciali definii de IEEE

Prima dintre acestea este NaN (Not a Number), valoare care se


obine atunci cnd efectum o operaie a crei rezultat nu este
definit, de exemplu 0.0 / 0.0.
n plus, standardul IEEE definete dou valori pe care le putem
folosi pe post de infinit pozitiv i negativ. i aceste valori pot rezulta
n urma unor calcule.
Aceste valori sunt definite sub form de constante i n ierarhia
standard Java, mai precis n clasa java.lang.Float i respectiv n
java.lang.Double. Numele constantelor este POSITIVE_INFINITY,
NEGATIVE_INFINITY, NaN.
n plus, pentru tipurile ntregi i ntregi lungi i pentru tipurile
flotante exist definite clase n ierarhia standard Java care se
numesc respectiv java.lang.Integer, java.lang.Long, java.lang.Float i
java.lang.Double. n fiecare dintre aceste clase numerice sunt
59

definite dou constante care reprezint valorile minime i maxime


care se pot reprezenta n tipurile respective. Aceste dou constante
se numesc n mod uniform MIN_VALUE i MAX_VALUE.
5.1.3 Tipuri referin
Tipurile referin sunt folosite pentru a referi un obiect din
interiorul unui alt obiect. n acest mod putem nlnui informaiile
aflate n memorie.
Tipurile referin au, la fel ca i toate celelalte tipuri o valoare
implicit care este atribuit automat oricrei variabile de tip
referin care nu a fost iniializat. Aceast valoare implicit este
definit de ctre limbajul Java prin cuvntul rezervat null.
Putei nelege semnificaia referinei nule ca o referin care nu
trimite nicieri, a crei destinaie nu a fost nc fixat.
Simpla declaraie a unei referine nu duce automat la rezervarea
spaiului de memorie pentru obiectul referit. Singura rezervare care
se face este aceea a spaiului necesar memorrii referinei n sine.
Rezervarea obiectului trebuie fcut explicit n program printr-o
expresie de alocare care folosete cuvntul rezervat new.
O variabil de tip referin nu trebuie s trimit pe tot timpul
existenei sale ctre acelai obiect n memorie. Cu alte cuvinte,
variabila i poate schimba locaia referit n timpul execuiei.
5.1.3.1 Tipul referin ctre o clas
Tipul referin ctre o clas este un tip referin care trimite ctre o
instan a unei clasei de obiecte. Clasa instanei referite poate fi
oricare clas valid definit de limbaj sau de utilizator.
Clasa de obiecte care pot fi referite de o anumit variabil de tip
referin la clas trebuie declarat explicit. De exemplu, pentru a
declara o referin ctre o instan a clasei Minge, trebuie s folosim
urmtoarea sintax:
Minge mingeaMea;

Din acest moment, variabila referin de clas


numit mingeaMea va putea pstra doar referine ctre obiecte de
tip Minge sau ctre obiecte aparinnd unor clase derivate din
clasa Minge. De exemplu, dac avem o alt clas, derivat din Minge,
60

numit MingeDeBaschet, putem memora n referinamingeaMea i o


trimitere ctre o instan a clasei MingeDeBaschet.
n mod general ns, nu se pot pstra n
variabila mingeaMea referine ctre alte clase de obiecte. Dac se
ncerc acest lucru, eroarea va fi semnalat chiar n momentul
compilrii, atunci cnd sursa programului este examinat pentru a
fi transformat n instruciuni ale mainii virtuale Java.
S mai observm c o referin ctre clasa de obiecte Object,
rdcina ierarhiei de clase Java, poate pstra i o referin ctre un
tablou. Mai multe lmuriri asupra acestei afirmaii mai trziu.
5.1.3.2 Tipul referin ctre o interfa
Tipul referin ctre o interfa permite pstrarea unor referine
ctre obiecte care respect o anumit interfa. Clasa obiectelor
referite poate fi oricare, atta timp ct clasa respectiv
implementeaz interfaa cerut.
Declaraia se face cu urmtoarea sintax:
ObiectSpaioTemporal mingeaLuiVasile;

n care tipul este chiar numele interfeei cerute. Dac clasa de


obiecte Mingedeclar c implementeaz aceast interfa, atunci
variabila referinmingeaLuiVasile poate lua ca valoare referina
ctre o instan a claseiMinge sau a clasei MingeDeBaschet.
Prin intermediul unei variabile referin ctre o interfa nu se poate
apela dect la funcionalitatea cerut n interfaa respectiv, chiar
dac obiectele reale ofer i alte faciliti, ele aparinnd unor clase
mai bogate n metode.
5.1.3.3 Tipul referin ctre un tablou
Tipul referin ctre un tablou este un tip referin care poate pstra
o trimitere ctre locaia din memorie a unui tablou de elemente.
Prin intermediul acestei referine putem accesa elementele tabloului
furniznd indexul elementului dorit.
Tablourile de elemente nu exist n general ci ele sunt tablouri
formate din elemente de un tip bine precizat. Din aceast cauz,
atunci cnd declarm o referin ctre un tablou, trebuie s
precizm i de ce tip sunt elementele din tabloul respectiv.
61

La declaraia referinei ctre tablou nu trebuie s precizm i


numrul de elemente din tablou.
Iat cum se declar o referin ctre un tablou de ntregi lungi:
long numere[];

Numele variabilei este numere. Un alt exemplu de declaraie de


referin ctre un tablou:
Minge echipament[];

Declaraia de mai sus construiete o referin ctre un tablou care


pstreaz elemente de tip referin ctre o instan a clasei Minge.
Numele variabilei referin este echipament. Parantezele drepte de
dup numele variabilei specific faptul c este vorba despre un
tablou.
Mai multe despre tablouri ntr-un paragraf urmtor.
5.1.4 Clasa de memorare
Fiecare variabil trebuie s aib o anumit clas de memorare.
Aceast clas ne permite s aflm care este intervalul de existen i
vizibilitatea unei variabile n contextul execuiei unui program.
Este important s nelegem exact aceast noiune pentru c altfel
vom ncerca s referim variabile nainte ca acestea s fi fost create
sau dup ce au fost distruse sau s referim variabile care nu sunt
vizibile din zona de program n care le apelm. Soluia simpl de
existen a tuturor variabilelor pe tot timpul execuiei este desigur
afar din discuie att din punct de vedere al eficienei ct i a
eleganei i stabilitii codului.
5.1.4.1 Variabile locale
Aceste variabile nu au importan prea mare n contextul ntregii
aplicaii, ele servind la rezolvarea unor probleme locale. Variabilele
locale sunt declarate, rezervate n memorie i utilizate doar n
interiorul unor blocuri de instruciuni, fiind distruse automat la
ieirea din aceste blocuri. Aceste variabile sunt vizibile doar n
interiorul blocului n care au fost create i n subblocurile
acestuia.
5.1.4.2 Variabile statice
62

Variabilele statice sunt n general legate de funcionalitatea


anumitor clase de obiecte ale cror instane folosesc n comun
aceste variabile. Variabilele statice sunt create atunci cnd codul
specific clasei n care au fost declarate este ncrcat n memorie i
nu sunt distruse dect atunci cnd acest cod este eliminat din
memorie.
Valorile memorate n variabile statice au importan mult mai mare
n aplicaie dect cele locale, ele pstrnd informaii care nu trebuie
s se piard la dispariia unei instane a clasei. De exemplu,
variabila n care este memorat numrul de picioare al obiectelor din
clasa Om nu trebuie s fie distrus la dispariia unei instane din
aceast clas. Aceasta din cauz c i celelalte instane ale clasei
folosesc aceeai valoare. i chiar dac la un moment dat nu mai
exist nici o instan a acestei clase, numrul de picioare ale unui
Om trebuie s fie accesibil n continuare pentru interogare de ctre
celelalte clase.
Variabilele statice nu se pot declara dect ca variabile ale unor clase
i conin n declaraie cuvntul rezervat static. Din cauza faptului c
ele aparin clasei i nu unei anumite instane a clasei, variabilele
statice se mai numesc uneori i variabile de clas.
5.1.4.3 Variabile dinamice
Un alt tip de variabile sunt variabilele a cror perioad de existen
este stabilit de ctre programator. Aceste variabile pot fi alocate la
cerere, dinamic, n orice moment al execuiei programului. Ele vor fi
distruse doar atunci cnd nu mai sunt referite de nicieri.
La alocarea unei variabile dinamice, este obligatoriu s pstrm o
referin ctre ea ntr-o variabil de tip referin. Altfel, nu vom
putea accesa n viitor variabila dinamic. n momentul n care nici o
referin nu mai trimite ctre variabila dinamic, de exemplu pentru
c referina a fost o variabil local i blocul n care a fost declarat
i-a terminat execuia, variabila dinamic este distrus automat de
ctre sistem printr-un mecanism numit colector de gunoaie.
Colectorul de gunoaie poate porni din iniiativa sistemului sau din
iniiativa programatorului la momente bine precizate ale execuiei.
Pentru a rezerva spaiu pentru o variabil dinamic este nevoie s
apelm la o expresie de alocare care folosete cuvntul rezervat new.
Aceast expresie aloc spaiul necesar pentru un anumit tip de
63

valoare. De exemplu, pentru a rezerva spaiul necesar unui obiect


de tip Minge, putem apela la sintaxa:
Minge mingeaMea = new Minge();

iar pentru a rezerva spaiul necesar unui tablou de referine ctre


obiecte de tip Minge putem folosi declaraia:
Minge echipament[] = new Minge[5];

Am alocat astfel spaiu pentru un tablou care conine 5 referine


ctre obiecte de tip Minge. Pentru alocarea tablourilor coninnd
tipuri primitive se folosete aceeai sintax. De exemplu,
urmtoarea linie de program aloc spaiul necesar unui tablou cu
10 ntregi, crend n acelai timp i o variabil referin spre acest
tablou, numit numere:
int numere[] = new int[10];

5.1.5 Tablouri de variabile


Tablourile servesc, dup cum spuneam, la memorarea secvenelor
de elemente de acelai tip. Tablourile unidimensionale au
semnificaia vectorilor de elemente. Se poate ntmpla s lucrm i
cu tablouri de referine ctre tablouri, n acest caz modelul fiind
acela al unei matrici bidimensionale. n fine, putem extinde definiia
i pentru mai mult de dou dimensiuni.
5.1.5.1 Declaraia variabilelor de tip tablou
Pentru a declara variabile de tip tablou, trebuie s specificm tipul
elementelor care vor umple tabloul i un nume pentru variabila
referin care va pstra trimiterea ctre zona de memorie n care
sunt memorate elementele tabloului.
Dei putem declara variabile referin ctre tablou i separat, de
obicei declaraia este fcut n acelai timp cu alocarea spaiului ca
n exemplele din paragraful anterior.
Sintaxa Java permite plasarea parantezelor drepte care specific
tipul tablou nainte sau dup numele variabilei. Astfel, urmtoarele
dou declaraii sunt echivalente:
int[] numere;
int numere[];

64

Dac dorii s folosii tablouri cu dou dimensiuni ca matricile,


putei s declarai un tablou de referine ctre tablouri cu una
dintre urmtoarele trei sintaxe echivalente:
float[][] matrice;
float[] matrice[];
float matrice[][];

De precizat c i n cazul dimensiunilor multiple, declaraiile de mai


sus nu fac nimic altceva dect s rezerve loc pentru o referin i s
precizeze numrul de dimensiuni. Alocarea spaiului pentru
elementele tabloului trebuie fcut explicit.
Despre rezervarea spaiului pentru tablourile cu o singur
dimensiune am vorbit deja. Pentru tablourile cu mai multe
dimensiuni, rezervarea spaiului se poate face cu urmtoarea
sintax:
byte [][]octeti = new byte[23][5];

n expresia de alocare sunt specificate n clar numrul elementelor


pentru fiecare dimensiune a tabloului.
5.1.5.2 Iniializarea tablourilor.
Limbajul Java permite i o sintax pentru iniializarea elementelor
unui tablou. ntr-un astfel de caz este rezervat automat i spaiul de
memorie necesar memorrii valorilor iniiale. Sintaxa folosit n
astfel de cazuri este urmtoarea:
char []caractere = { a, b, c, d };

Acest prim exemplu aloc spaiu pentru patru elemente de tip


caracter i iniializeaz aceste elemente cu valorile dintre acolade.
Dup aceea, creeaz variabila de tip referin numit caractere i o
iniializeaz cu referina la zona de memorie care pstreaz cele
patru valori.
Iniializarea funcioneaz i la tablouri cu mai multe dimensiuni ca
n exemplele urmtoare:
int [][]numere = {
{ 1, 3, 4, 5 },
{ 2, 4, 5 },
{ 1, 2, 3, 4, 5 }
};
double [][][]reali = {
{ { 0.0, -1.0 }, { 4.5 } },
{ { 2.5, 3.0 } }

65

};

Dup cum observai numrul iniializatorilor nu trebuie s fie


acelai pentru fiecare element.
5.1.5.3 Lungimea tablourilor
Tablourile Java sunt alocate dinamic, ceea ce nseamn c ele i
pot schimba dimensiunile pe parcursul execuiei. Pentru a afla
numrul de elemente dintr-un tablou, putem apela la urmtoarea
sintax:
float []tablou = new float[25];
int dimensiune = tablou.length;
// dimensiune primete valoarea 25

sau
float [][]multiTablou = new float[3][4];
int dimensiune1 = multiTablou[2].length;
// dimensiune1 primete valoarea 4
int dimensiune2 = multiTablou.length;
// dimensiune2 primete valoarea 3 ^

5.1.5.4 Referirea elementelor din tablou


Elementele unui tablou se pot referi prin numele referinei tabloului
i indexul elementului pe care dorim s-l referim. n Java, primul
element din tablou este elementul cu numrul 0, al doilea este
elementul numrul 1 i aa mai departe.
Sintaxa de referire folosete parantezele ptrate [ i ]. ntre ele
trebuie specificat indexul elementului pe care dorim s-l referim.
Indexul nu trebuie s fie constant, el putnd fi o expresie de
complexitate oarecare.
Iat cteva exemple:
int []tablou = new int[10];
tablou[3] = 1;
// al patrulea element primete valoarea 1
float [][]reali = new float[3][4];
reali[2][3] = 1.0f;
// al patrulea element din al treilea tablou
// primete valoarea 1

n cazul tablourilor cu mai multe dimensiuni, avem n realitate


tablouri de referine la tablouri. Asta nseamn c dac considerm
urmtoarea declaraie:
66

char [][]caractere = new char [5][];

Figura 5.1 Elementele tabloului sunt de tip referin, iniializate implicit la valoarea null.

Variabila referin numit caractere conine deocamdat un tablou


de 5 referine la tablouri de caractere. Cele cinci referine sunt
iniializate cunull. Putem iniializa aceste tablouri prin atribuiri de
expresii de alocare:
caractere[0] = new char [3];
caractere[4] = new char [5];

Figura 5.2 Noile tablouri sunt referite din interiorul tabloului original. Elementele noilor
tablouri sunt caractere.

La fel, putem scrie:


char []tablouDeCaractere = caractere[0];

Figura 5.3 Variabilele de tip referin caractere[0] i tablouDeCaractere trimit spre acelai
tablou rezervat n memorie.

Variabila tablouDeCaractere trimite ctre acelai tablou de caractere


ca i cel referit de primul element al tabloului referit de
variabila caractere.
S mai precizm c referirea unui element de tablou printr-un index
mai mare sau egal cu lungimea tabloului duce la oprirea execuiei
programului cu un mesaj de eroare de execuie corespunztor.
67

5.1.5.5 Alocarea i eliberarea tablourilor


Despre alocarea tablourilor am spus deja destul de multe. n cazul
n care nu avem iniializatori, variabilele sunt iniializate cu valorile
implicite definite de limbaj pentru tipul corespunztor. Aceasta
nseamn c, pentru tablourile cu mai multe dimensiuni, referinele
sunt iniializate cu null.
Pentru eliberarea memoriei ocupate de un tablou, este suficient s
tiem toate referinele ctre tablou. Sistemul va sesiza automat c
tabloul nu mai este referit i mecanismul colector de gunoaie va
elibera zona. Pentru a tia o referin ctre un tablou dm o alt
valoare variabilei care refer tabloul. Valoarea poate fi null sau o
referin ctre un alt tablou.
De exemplu:
float []reali = new float[10];
?
reali = null; // eliberarea tabloului
sau
reali = new float[15]; // eliberarea n alt fel
sau
{
float []reali = new float[10];
?
}// eliberare automat, variabila reali a fost
// distrus la ieirea din blocul n care a
// fost declarat, iar tabloul de 10 flotani
// nu mai este referit ^

5.1.6 Conversii
Operaiile definite n limbajul Java au un tip bine precizat de
argumente. Din pcate, exist situaii n care nu putem transmite la
apelul acestora exact tipul pe care compilatorul Java l ateapt. n
asemenea situaii, compilatorul are dou alternative: fie respinge
orice operaie cu argumente greite, fie ncearc s converteasc
argumentele ctre tipurile necesare. Desigur, n cazul n care
conversia nu este posibil, singura alternativ rmne prima.
n multe situaii ns, conversia este posibil. S lum de exemplu
tipurile ntregi. Putem s convertim ntotdeauna un ntreg scurt la
un ntreg. Valoarea rezultat va fi exact aceeai. Conversia invers
ns, poate pune probleme dac valoarea memorat n ntreg
depete capacitatea de memorare a unui ntreg scurt.

68

n afar de conversiile implicite, pe care compilatorul le hotrte de


unul singur, exist i conversii explicite, pe care programatorul le
poate fora la nevoie. Aceste conversii efectueaz de obicei operaii
n care exist pericolul s se piard o parte din informaii.
Compilatorul nu poate hotr de unul singur n aceste situaii.
Conversiile implicite pot fi un pericol pentru stabilitatea aplicaiei
dac pot s duc la pierderi de informaii fr avertizarea
programatorului. Aceste erori sunt de obicei extrem de greu de
depistat.
n fiecare limbaj care lucreaz cu tipuri fixe pentru datele sale exist
conversii imposibile, conversii periculoase i conversii sigure.
Conversiile imposibile sunt conversiile pe care limbajul nu le
permite pentru c nu tie cum s le execute sau pentru c operaia
este prea periculoas. De exemplu, Java refuz s converteasc un
tip primitiv ctre un tip referin. Dei s-ar putea imagina o astfel de
conversie bazat pe faptul c o adres este n cele din urm un
numr natural, acest tip de conversii
sunt extrem de periculoase, chiar i atunci cnd programatorul cere
explicit aceast conversie.
5.1.6.1 Conversii de extindere a valorii
n aceste conversii valoarea se reprezint ntr-o zon mai mare fr
s se piard nici un fel de informaii. Iat conversiile de extindere pe
tipuri primitive:
la short, int, long, float sau double
la int, long, float sau double
char la int, long, float sau double
int la long, float sau double
long la float sau double
float la double

byte

short

S mai precizm totui c, ntr-o parte din aceste cazuri, putem


pierde din precizie. Aceast situaie apare de exemplu la conversia
unui long ntr-unfloat, caz n care se pierd o parte din cifrele
semnificative pstrndu-se ns ordinul de mrime. De altfel
aceast observaie este evident dac inem cont de faptul c
un long este reprezentat pe 64 de bii n timp ce unfloat este
reprezentat doar pe 32 de bii.

69

Precizia se pierde chiar i n cazul


conversiei long la double sau int la floatpentru c, dei dimensiunea
zonei alocat pentru cele dou tipuri este aceeai, numerele flotante
au nevoie de o parte din aceast zon pentru a reprezenta
exponentul.
n aceste situaii, se va produce o rotunjire a numerelor
reprezentate.
5.1.6.2 Conversii de trunchiere a valorii
Conveniile de trunchiere a valorii pot produce pierderi de informaie
pentru c ele convertesc tipuri mai bogate n informaii ctre tipuri
mai srace. Conversiile de trunchiere pe tipurile elementare sunt
urmtoarele:

la char
short la byte sau char
char la byte sau short
int la byte, short sau char
long la byte, short char, sau int
float la byte, short, char, int sau long
double la byte, short, char, int, long sau
byte

float.

n cazul conversiilor de trunchiere la numerele cu semn, este posibil


s se schimbe semnul pentru c, n timpul conversiei, se
ndeprteaz pur i simplu octeii care nu mai ncap i poate
rmne primul bit diferit de vechiul prim bit. Copierea se face
ncepnd cu octeii mai puin semnificativi iar trunchierea se face la
octeii cei mai semnificativi.
Prin octeii cei mai semnificativi ne referim la octeii n care sunt
reprezentate cifrele cele mai semnificative. Cifrele cele mai
semnificativesunt cifrele care dau ordinul de mrime al numrului.
De exemplu, la numrul 123456, cifrele cele mai semnificative sunt
primele, adic: 1, 2, etc. La acelai numr, cifrele cele mai puin
semnificative sunt ultimele, adic: 6, 5, etc.
5.1.6.3 Conversii pe tipuri referin
Conversiile tipurilor referin nu pun probleme pentru modul n
care trebuie executat operaia din cauz c, referina fiind o
adres, n timpul conversiei nu trebuie afectat n nici un fel
aceast adres. n schimb, se pun probleme legate de corectitudinea
logic a conversiei. De exemplu, dac avem o referin la un obiect
70

care nu este tablou, este absurd s ncercm s convertim aceast


referin la o referin de tablou.
Limbajul Java definete extrem de strict conversiile posibile n cazul
tipurilor referin pentru a salva programatorul de eventualele
necazuri care pot apare n timpul execuiei. Iat conversiile posibile:

O referin ctre un obiect aparinnd unei clase C poate fi


convertit la o referin ctre un obiect aparinnd clasei S doar
n cazul n careC este chiar S sau C este derivat direct sau
indirect din S.
O referin ctre un obiect aparinnd unei clase C poate fi
convertit ctre o referin de interfa I numai dac
clasa C implementeaz interfaa I.
O referin ctre un tablou poate fi convertit la o referin
ctre o clas numai dac clasa respectiv este clasa Object.
O referin ctre un tablou de elemente ale crui elemente
sunt de tipul T1 poate fi convertit la o referin ctre un
tablou de elemente de tip T2 numai dac T1 i T2 reprezint
acelai tip primitiv sau T2este un tip referin i T1 poate fi
convertit ctre T2.

5.1.6.4 Conversii la operaia de atribuire


Conversiile pe care limbajul Java le execut implicit la atribuire
sunt foarte puine. Mai exact, sunt executate doar acele conversii
care nu necesit validare n timpul execuiei i care nu pot pierde
informaii n cazul tipurilor primitive.
n cazul valorilor aparinnd tipurilor primitive, urmtorul tabel
arat conversiile posibile. Pe coloane avem tipul de valoare care se
atribuie iar pe linii avem tipurile de variabile la care se atribuie:
boolean char byte short int long float double
boolean

Da

Nu

Nu

Nu

Nu Nu

Nu

Nu

char

Nu

Da

Da

Da

Nu Nu

Nu

Nu

byte

Nu

Da

Da

Nu

Nu Nu

Nu

Nu

short

Nu

Da

Da

Da

Nu Nu

Nu

Nu

int

Nu

Da

Da

Da

Da Nu

Nu

Nu

long

Nu

Da

Da

Da

Da

Da

Nu

Nu

float

Nu

Da

Da

Da

Da

Da

Da

Nu
71

double

Nu

Da

Da

Da

Da

Da

Da

Da

Tabloul 5.1 Conversiile posibile ntr-o operaie de atribuire cu tipuri primitive. Coloanele
reprezint tipurile care se atribuie iar liniile reprezint tipul de variabil ctre care se face
atribuirea.

Dup cum observai, tipul boolean nu poate fi atribuit la o variabil


de alt tip.
Valorile de tip primitiv nu pot fi atribuite variabilelor de tip referin.
La fel, valorile de tip referin nu pot fi memorate n variabile de tip
primitiv. n ceea ce privete tipurile referin ntre ele, urmtorul
tabel definete situaiile n care conversiile sunt posibile la
atribuirea unei valori de tipul Tla o variabil de tipul S:
T este o clas
care nu este
final

T este o clas
care este final

T este o
interfa

T = B[] este un
tablou cu
elemente de
tipul B

S este o
clas care
nu este
final

T trebuie s fie T trebuie s fie


subclas a lui
o subclas a
S
lui S

eroare la
compilare

S trebuie s fie
Object

S este o
clas care
este final

T trebuie s fie T trebuie s fie


aceeai clas
aceeai clas
ca i S
ca i S

eroare la
compilare

eroare la
compilare

S este o
interfa

T trebuie s
implementeze
interfaa S

T trebuie s
implementeze
interfaa S

T trebuie s
fie o
subinterfa
a lui S

eroare la
compilare

S = A[] este
un tablou
cu
elemente
de tipul A

eroare la
compilare

eroare la
compilare

eroare la
compilare

A sau B sunt
acelai tip
primitiv sau A
este un tip
referin i B
poate fi
atribuit lui A

Tabloul 5.2 Conversiile posibile la atribuirea unei valori de tipul T la o variabil de tipul S.

5.1.6.5 Conversii explicite


Conversiile de tip cast, sau casturile, sunt apelate de ctre
programator n mod explicit. Sintaxa pentru construcia unui cast
72

este scrierea tipului ctre care dorim s convertim n paranteze n


faa valorii pe care dorim s o convertim. Forma general este:
( Tip ) Valoare
Conversiile posibile n acest caz sunt mai multe dect conversiile
implicite la atribuire pentru c n acest caz programatorul este
prevenit de eventuale pierderi de date el trebuind s apeleze
conversia explicit.
Dar, continu s existe conversii care nu se pot apela nici mcar n
mod explicit, dup cum am explicat nainte.
n cazul conversiilor de tip cast, orice valoare numeric poate fi
convertit la orice valoare numeric.
n continuare, valorile de tip boolean nu pot fi convertite la nici un
alt tip.
Nu exist conversii ntre valorile de tip referin i valorile de tip
primitiv.
n cazul conversiilor dintr-un tip referin ntr-altul putem separa
dou cazuri. Dac compilatorul poate decide n timpul compilrii
dac conversia este corect sau nu, o va decide. n cazul n care
compilatorul nu poate decide pe loc, se va efectua o verificare a
conversiei n timpul execuiei. Dac conversia se dovedete greit,
va apare o eroare de execuie i programul va fi ntrerupt.
Iat un exemplu de situaie n care compilatorul nu poate decide
dac conversia este posibil sau nu:
Minge mingeaMea;
?
MingeDeBaschet mingeaMeaDeBaschet;
// MingeDeBaschet este o clas
// derivat din clasa Minge
mingeaMeaDeBaschet=(MingeDeBaschet)mingeaMea;

n acest caz, compilatorul nu poate fi sigur dac referina memorat


n variabila mingeaMea este de tip MingeDeBaschet sau nu pentru c
variabilei de tip Minge i se pot atribui i referine ctre instane de
tip Minge n general, care nu respect ntru totul definiia
clasei MingeDeBaschet sau chiar referin ctre alte tipuri de minge
derivate din clasa Minge, de exempluMingeDePolo care implementeaz
proprieti i operaii diferite fa de clasaMingeDeBaschet.
73

Iat i un exemplu de conversie care poate fi decis n timpul


compilrii:
Minge mingeaMea;
MingeDeBaschet mingeaMeaDeBaschet;
?
mingeaMea = ( Minge ) mingeaMeaDeBaschet;

n urmtorul exemplu ns, se poate decide n timpul compilrii


imposibilitatea conversiei:
MingeDeBaschet mingeaMeaDeBaschet;
MingeDePolo mingeaMeaDePolo;
?
mingeaMeaDePolo = ( MingeDePolo ) mingeaMeaDeBaschet;

n fine, tabelul urmtor arat conversiile de tip cast a cror


corectitudine poate fi stabilit n timpul compilrii. Conversia
ncearc s transforme printr-un cast o referin de tip T ntr-o
referin de tip S.
T este o
clas care
nu este
final

T este o clas
care este final

T este o
interfa

T = B[] este un
tablou cu
elemente de
tipul B

S este o
clas care
nu este
final

T trebuie s T trebuie s fie


fie subclas
o subclas a
a lui S
lui S

Totdeauna
corect la
compilare

S trebuie s fie
Object

S este o
clas care
este final

S trebuie s T trebuie s fie


fie subclas aceeai clas
a lui T
ca i S

S trebuie s
implementeze
interfaa T

eroare la
compilare

T trebuie s
implementeze
interfaa S

Totdeauna
corect la
compilare

eroare la
compilare

eroare la
compilare

eroare la
compilare

A sau B sunt
acelai tip
primitiv sau A
este un tip
referin i B
poate fi
convertit cu un
cast la A

S este o
interfa

Totdeauna
corect la
compilare

S = A[] este T trebuie s


un tablou
fie Object
cu
elemente
de tipul A

Tabloul 5.3 Cazurile posibile la convertirea unei referine de tip T ntr-o referin de tip S.

5.1.6.6 Conversii de promovare aritmetic


74

Promovarea aritmetic se aplic n cazul unor formule n care


operanzii pe care se aplic un operator sunt de tipuri diferite. n
aceste cazuri,
compilatorul ncearc s promoveze unul sau chiar amndoi
operanzii la acelai tip pentru a putea fi executat operaia.
Exist dou tipuri de promovare, promovare aritmetic unar i
binar.
n cazul promovrii aritmetice unare, exist un singur operand care
n cazul c este byte sau short este transformat la int altfel rmne
nemodificat.
La promovarea aritmetic binar se aplic urmtorul algoritm:
1. Dac un operand este double, cellalt este convertit la double.
2. Altfel, dac un operand este de tip float, cellalt operand este
convertit la float.
3. Altfel, dac un operand este de tip long, cellalt este convertit
la long
4. Altfel, amndoi operanzii sunt convertii la int.
De exemplu, n urmtoarea operaie amndoi operanzii vor fi
convertii lafloat prin promovare aritmetic binar:
float f;
double i = f + 3;

Dup efectuarea operaiei, valoarea obinut va fi convertit implicit


ladouble.
n urmtorul exemplu, se produce o promovare unar la int de la
short.
short s, r;
?
int min = ( r < -s ) ? r : s;

n expresia condiional, operandul -s se traduce de fapt prin


aplicarea operatorului unar - la variabila s care este de tip short. n
acest caz, se va produce automat promovarea aritmetic unar de
la short la int, apoi se va continua evaluarea expresiei.

75

Capitolul V
5.2 Expresii
5.2.1 Valoarea i tipul unei expresii
5.2.2 Ordinea de evaluare
5.2.3 Operatori
5.2.3.1 Operatori unari
5.2.3.1.1 Operatorii de preincrementare i postincrementare
5.2.3.1.2 Operatorul + unar
5.2.3.1.3 Operatorul - unar
5.2.3.1.4 Operatorul de complementare
5.2.3.1.5 Operatorul de negare logic
5.2.3.1.6 Casturi
5.2.3.2 Operatori binari
5.2.3.2.1 Operatori multiplicativi: *, /, %
5.2.3.2.2 Operatori aditivi: +, -, concatenare pentru iruri de
caractere
5.2.3.2.3 Operatori de iftare: >>, <<, >>>
5.2.3.2.4 Operatori relaionali: <, >, <=, >=, instanceof
5.2.3.2.5 Operatori de egalitate: ==, !=
5.2.3.2.6 Operatori la nivel de bit: &, |, ^
5.2.3.2.7 Operatori logici: &&, ||
5.2.3.3 Operatorul condiional ?:
5.2.3.4 Operaii ntregi
5.2.3.5 Operaii flotante
5.2.3.6 Apeluri de metode
5.2.1 Valoarea i tipul unei expresii
Fiecare expresie a limbajului Java are un rezultat i un tip.
Rezultatul poate fi:

o valoare
o variabil
nimic

76

n cazul n care valoarea unei expresii are ca rezultat o variabil,


expresia poate apare n stnga unei operaii de atribuire. De
exemplu expresia:
tablou[i]

este o expresie care are ca rezultat o variabil i anume locaia


elementului cu indexul i din tabloul de elemente numit tablou.
O expresie nu produce nimic doar n cazul n care este un apel de
metod i acest apel nu produce nici un rezultat (este declarat de
tip void).
Fiecare expresie are n timpul compilrii un tip cunoscut. Acest tip
poate fi o valoare primitiv sau o referin. n cazul expresiilor care
au tip referin, valoarea expresiei poate s fie i referina
neiniializat, null.
5.2.2 Ordinea de evaluare
n Java operanzii sunt evaluai ntotdeauna de la stnga spre
dreapta. Acest lucru nu trebuie s ne ndemne s scriem cod care
s depind de ordinea de evaluare pentru c, n unele situaii, codul
rezultat este greu de citit. Regula este introdus doar pentru a
asigura generarea uniform a codului binar, independent de
compilatorul folosit.
Evaluarea de la stnga la dreapta implic urmtoarele aspecte:

n cazul unui operator binar, operandul din stnga este


ntotdeauna complet evaluat atunci cnd se trece la evaluarea
operandului din dreapta. De exemplu, n expresia:

( i++ ) + i

dac i avea valoarea iniial 2, toat expresia va avea


valoarea 5pentru c valoarea celui de-al doilea i este luat dup ce
s-a executat incrementarea i++.

n cazul unei referine de tablou, expresia care numete


tabloul este complet evaluat nainte de a se trece la evaluarea
expresiei care d indexul. De exemplu, n expresia:

( a = b )[i]

77

indexul va fi aplicat dup ce s-a executat atribuirea valorii


referin bla variabila referin de tablou a. Cu alte cuvinte,
rezultatul va fi al i-lea element din tabloul b.
n cazul apelului unei metode, expresia care numete obiectul
este complet evaluat atunci cnd se trece la evaluarea
expresiilor care servesc drept argumente.
n cazul unui apel de metod, dac exist mai mult dect un
parametru, la evaluarea parametrului numrul i, toi
parametrii de la1 la i-1 sunt deja evaluai complet.
n cazul unei expresii de alocare, dac avem mai multe
dimensiuni exprimate n paranteze drepte, dimensiunile sunt
de asemenea evaluate de la stnga la dreapta. De exemplu, n
expresia:

new int[i++][i]

tabloul rezultat nu va fi o matrice ptratic ci, dac i avea


valoarea 3, de dimensiune 3 x 4.

5.2.3 Operatori
5.2.3.1 Operatori unari
Operatorii unari se aplic ntotdeauna unui singur operand. Aceti
operatori sunt, n general exprimai naintea operatorului asupra
cruia se aplic. Exist ns i dou excepii, operatorii de
incrementare i decrementare care pot apare i nainte i dup
operator, cu semnificaii diferite.
Operatorii unari sunt urmtorii:

preincrement
-- predecrement
++ postincrement
-- postdecrement
+ unar
- unar
~ complementare
! negaie logic
cast
++

5.2.3.1.1 Operatorii de preincrementare i postincrementare

Operatorii ++ preincrement i postincrement au acelai rezultat final,


i anume incrementeaz variabila asupra creia acioneaz cu 1.
78

Operandul asupra cruia sunt apelai trebuie s fie o variabil de


tip aritmetic. Nu are sens s apelm un operand de incrementare
asupra unei valori (de exemplu valoarea unei expresii sau un
literal), pentru c aceasta nu are o locaie de memorie fix n care s
memorm valoarea dup incrementare.
n cazul operatorului prefix, valoarea rezultat a acestei expresii este
valoarea variabilei dup incrementare n timp ce, la operatorul
postfix, valoarea rezultat a expresiei este valoarea de dinainte de
incrementare. De exemplu, dup execuia urmtoarei secvene de
instruciuni:
int i = 5;
int j = i++;

valoarea lui j este 5, n timp ce, dup execuia urmtoarei secvene


de instruciuni:
int i = 5;
int j = ++i;

valoarea lui j va fi 6. n ambele cazuri, valoarea final a lui i va fi 6.


n cazul operatorilor -? predecrement i postdecrement, sunt
valabile aceleai consideraii ca mai sus, cu diferena c valoarea
variabilei asupra creia se aplic operandul va fi decrementat cu 1.
De exemplu, urmtoarele instruciuni:
int i = 5;
int j = i--;

fac ca j s aib valoarea final

iar urmtoarele instruciuni:

int i = 5;
int j = --i;

fac ca j s aib valoarea final 4. n ambele cazuri, valoarea final a


lui ieste 4.
Operatorii de incrementare i de decrementare se pot aplica i pe
variabile de tip flotant. n asemenea cazuri, se convertete valoarea
1 la tipul variabilei incrementate sau decrementate, dup care
valoarea rezultat este adunat respectiv sczut din vechea valoare
a variabilei. De exemplu, urmtoarele instruciuni:
double f = 5.6;
double g = ++f;

79

au ca rezultat final valoarea

6.6

pentru f i pentru g.

5.2.3.1.2 Operatorul + unar

Operatorul + unar se aplic asupra oricrei valori primitive


aritmetice. Valoarea rmne neschimbat.
5.2.3.1.3 Operatorul - unar

Operatorul - unar se aplic asupra oricrei valori primitive


aritmetice. Rezultatul aplicrii acestui operand este negarea
aritmetic a valorii. n cazul valorilor ntregi, acest lucru este
echivalent cu scderea din 0 a valorii originale. De exemplu,
instruciunile:
int i = 5;
int j = -i;

i dau lui j valoarea -5 . n cazul valorilor speciale definite de


standardul IEEE pentru reprezentarea numerelor flotante, se aplic
urmtoarele reguli:

Dac operandul este NaN rezultatul negrii aritmetice este tot


NaN pentru c NaN nu are semn.
Dac operandul este unul dintre infinii, rezultatul este
infinitul opus ca semn.
Dac operandul este zero de un anumit semn, rezultatul este
zero de semn diferit. ^

5.2.3.1.4 Operatorul de complementare

Operatorul de complementare ~ se aplic asupra valorilor primitive


de tip ntreg. Rezultatul aplicrii operandului este complementarea
bit cu bit a valorii originale. De exemplu, dac operandul era de tip
byte avnd valoarea, n binar, 00110001, rezultatul va fi 11001110. n
realitate, nainte de complementare se face i extinderea valorii la
un ntreg, deci rezultatul va fi de fapt: 11111111 11111111 11111111
11001110.
5.2.3.1.5 Operatorul de negare logic

Operatorul de negare logic ! se aplic n exclusivitate valorilor de


tip boolean. n cazul n care valoarea iniial a operandului
este truerezultatul va fi false i invers.
5.2.3.1.6 Casturi

80

Casturile sunt expresii de conversie dintr-un tip ntr-altul, aa cum


deja am artat la paragraful destinat conversiilor. Rezultatul unui
cast este valoarea operandului convertit la noul tip de valoare
exprimat de cast. De exemplu, la instruciunile:
double f = 5.6;
int i = ( int )f;
double g = -5.6;
int j = ( int )g;

valoarea variabilei f este convertit la o valoare ntreag, anume 5, i


noua valoare este atribuit variabilei i. La fel, j primete valoarea -5.
S mai precizm c nu toate casturile sunt valide n Java. De
exemplu, nu putem converti o valoare ntreag ntr-o valoare de tip
referin.
5.2.3.2 Operatori binari
Operatorii binari au ntotdeauna doi operanzi. Operatorii binari
sunt urmtorii:

Operatori
Operatori
caractere
Operatori
Operatori
Operatori
Operatori
Operatori

multiplicativi: *, /, %
aditivi: +, -, + (concatenare) pentru iruri de
de iftare: >>, <<, >>>
relaionali: <, >, <=, >=,
de egalitate: ==, !=
la nivel de bit: &, |, ^
logici: &&, ||

instanceof

5.2.3.2.1 Operatori multiplicativi: *, /, %

Operatorii multiplicativi reprezint respectiv operaiile de nmulire


(*), mprire (/) i restul mpririi (%). Prioritatea acestor operaii
este mai mare relativ la operaiile aditive, deci aceti operatori se vor
executa mai nti. Exemple:
10 * 5 == 50
10.3 * 5.0 == 51.5
10 / 2.5 == 4.0// mprire real
3 / 2 == 1// mprire ntreag
7 % 2 == 1// restul mpririi ntregi
123.5 % 4 == 3.5 // 4 * 30 + 3.5
123.5 % 4.5 == 2.0 // 4.5 * 27 + 2.0

81

Dup cum observai, operanzii sunt convertii mai nti la tipul cel
mai puternic, prin promovare aritmetic, i apoi se execut operaia.
Rezultatul este de acelai tip cu tipul cel mai puternic.
n cazul operatorului pentru restul mpririi, dac lucrm cu
numere flotante, rezultatul se calculeaz n felul urmtor: se
calculeaz de cte ori este cuprins cel de-al doilea operand n primul
(un numr ntreg de ori) dup care rezultatul este diferena care mai
rmne, ntotdeauna mai mic strict dect al doilea operand.
5.2.3.2.2 Operatori aditivi: +, -, concatenare pentru iruri de caractere

Operatorii aditivi reprezint operaiile de adunare (+), scdere (-) i


concatenare (+) de iruri. Observaiile despre conversia tipurilor
fcute la operatorii multiplicativi rmn valabile. Exemple:
2 + 3 == 5
2.34 + 3 == 5.34
34.5 - 23.1 == 11.4
"Acesta este" + " un sir" == "Acesta este un sir"
"Sirul: " + 1 == "Sirul: 1"
"Sirul: " + 3.4444 == "Sirul: 3.4444"
"Sirul: " + null = "Sirul: null"
"Sirul: " + true = "Sirul: true"
Object obiect = new Object();
"Sirul: " + obiect == "java.lang.Object@1393800"

La concatenarea irurilor de caractere, lungimea irului rezultat


este suma lungimii irurilor care intr n operaie. Caracterele din
irul rezultat sunt caracterele din primul ir, urmate de cele dintr-al
doilea ir n ordine.
Dac cel de-al doilea operand nu este de tip String ci este de tip
referin, se va apela metoda sa toString, i apoi se va folosi n
operaie rezultatul. Metoda toString este definit n clasa Object i
este motenit de toate celelalte clase.
Dac cel de-al doilea operand este un tip primitiv, acesta este
convertit la un ir rezonabil de caractere care s reprezinte valoarea
operandului.
5.2.3.2.3 Operatori de iftare: >>, <<, >>>

Operatorii de iftare se pot aplica doar pe valori primitive ntregi. Ei


reprezint respectiv operaiile de iftare cu semn stnga (<<) i
dreapta (>>) i operaia de iftare fr semn spre dreapta (>>>).

82

iftrile cu semn lucreaz la nivel de cifre binare. Cifrele binare din


locaia de memorie implicat sunt mutate cu mai multe poziii spre
stnga sau spre dreapta. Poziia binar care reprezint semnul
rmne neschimbat. Numrul de poziii cu care se efectueaz
mutarea este dat de al doilea operand. Locaia de memorie n care
se execut operaia este locaia n care este memorat primul
operand.
iftarea cu semn la stnga reprezint o operaie identic cu
nmulirea cu 2 de n ori, unde n este al doilea operand. iftarea cu
semn la dreapta reprezint mprirea ntreag. n acest caz, semnul
este copiat n mod repetat n locurile rmase goale. Iat cteva
exemple:
255 << 3 ==
// 00000000
255 >> 5 ==
// 00000000

2040
11111111 -> 00000111 11111000
7
11111111 -> 00000000 00000111

iftarea fr semn la dreapta, mut cifrele binare din operand


completnd spaiul rmas cu zerouri:
0xffffffff
0xffffffff
0xffffffff
0xffffffff
0xffffffff

>>>
>>>
>>>
>>>
>>>

-1 == 0x00000001
-2 == 0x00000003
-3 == 0x00000007
3 == 0x1fffffff
5 == 0x07ffffff ^

5.2.3.2.4 Operatori relaionali: <, >, <=, >=, instanceof

Operatorii relaionali ntorc valori booleene de adevrat sau fals. Ei


reprezint testele de mai mic (<), mai mare (>), mai mic sau egal (<=),
mai mare sau egal (>=) i testul care ne spune dac un anumit obiect
este sau nu instan a unei anumite clase (instanceof). Iat cteva
exemple:
1 < 345 == true
1 <= 0 == false
Object o = new Object();
String s = new String();
o instanceof Obiect == true
s instanceof String == true
o instanceof String == false
s instanceof Object == true

S mai observm c

String

este derivat din

Object.

5.2.3.2.5 Operatori de egalitate: ==, !=

83

Aceti operatori testeaz egalitatea sau inegalitatea dintre dou


valori. Ei reprezint testul de egalitate (==) i de inegalitate (!=).
Rezultatul aplicrii acestor operatori este o valoare boolean.
Exemple:
( 1 == 1.0 ) == true
( 2 != 2 ) == false
Object o = new Object();
String s1 = "vasile";
String s2 = s1;
String s4 = "e";
String s3 = "vasil" + s4;
( o == s1 ) == false
( s1 == s2 ) == true // acelai obiect referit
( s3 == s1 ) == false // acelai ir de caractere
// dar obiecte diferite

S observm c egalitatea a dou obiecte de tip String reprezint


egalitatea a dou referine de obiecte i nu egalitatea coninutului
irului de caractere. Dou referine sunt egale dac refer exact
acelai obiect, nu dac obiectele pe care le refer sunt egale ntre
ele. Egalitatea coninutului a dou iruri de caractere se testeaz
folosind metoda equals, definit n clasa String.
5.2.3.2.6 Operatori la nivel de bit: &, |, ^

Operatorii la nivel de bit reprezint operaiile logice obinuite, dac


considerm c 1 ar reprezenta adevrul i 0 falsul. Operatorii la
nivel de bit, consider cei doi operanzi ca pe dou iruri de cifre
binare i fac operaiile pentru fiecare dintre perechile de cifre binare
corespunztoare n parte. Rezultatul este un nou ir de cifre binare.
De exemplu, operaia de i(&) logic are urmtorul tabel de adevr:
1
1
0
0

&
&
&
&

1
0
1
0

==
==
==
==

1
0
0
0

Dac apelm operatorul

&

pe numerele reprezentate binar:

00101111
01110110

rezultatul este:
00100110

Primul numr reprezint cifra

47,

al doilea

118

iar rezultatul

38,

deci:

47 & 118 == 38

84

n mod asemntor, tabela de adevr pentru operaia


logic sau (|) este:
1
1
0
0

|
|
|
|

1
0
1
0

==
==
==
==

1
1
1
0

iar tabela de adevr pentru operaia logic de sau exclusiv (^) este:
1
1
0
0

^
^
^
^

1
0
1
0

==
==
==
==

0
1
1
0

Iat i alte exemple:


1245 ^ 2345 == 3572
128 & 255 == 128
127 & 6 == 6
128 | 255 == 255
127 | 6 == 127
32 ^ 64 == 96 ^
5.2.3.2.7 Operatori logici: &&, ||

Operatorii logici se pot aplica doar asupra unor operanzi de tip


boolean. Rezultatul aplicrii lor este tot boolean i reprezint
operaia logic de i (&&) sau operaia logic de sau (||) ntre cele
dou valori booleene. Iat toate posibilitile de combinare:
true && true == true
true && false == false
false && true == false
false && false == false
true || true == true
true || false == true
false || true == true
false || false == false

n cazul operatorului && este evaluat mai nti operandul din stnga.
Dac acesta este fals, operandul din dreapta nu mai este evaluat,
pentru c oricum rezultatul este fals. Acest lucru ne permite s
testm condiiile absolut necesare pentru corectitudinea unor
operaii i s nu executm operaia dect dac aceste condiii sunt
ndeplinite.
De exemplu, dac avem o referin i dorim s citim o valoare de
variabil din obiectul referit, trebuie s ne asigurm c referina
este diferit de null. n acest caz, putem scrie:
String s = "sir de caractere";

85

if( s != null && s.length < 5 ) ?

n cazul n care s este


fi executat.

null,

a doua operaie nu are sens i nici nu va

n mod similar, la operatorul ||, se evalueaz mai nti primul


operand. Dac acesta este adevrat, nu se mai evalueaz i cel de-al
doilea operand pentru c rezultatul este oricum adevrat. Faptul se
poate folosi n mod similar ca mai sus:
if( s == null || s.length == 0 ) ?

n cazul n care s este


evaluarea.

null,

nu se merge mai departe cu

5.2.3.3 Operatorul condiional ?:


Este singurul operator definit de limbajul Java care accept trei
operanzi. Operatorul primete o expresie condiional boolean pe
care o evalueaz i alte dou expresii care vor fi rezultatul aplicrii
operandului. Care dintre cele dou expresii este rezultatul adevrat
depinde de valoarea rezultat a expresiei booleene. Forma general a
operatorului este:
ExpresieCondiional ? Expresie1 : Expresie2
Dac valoarea expresiei condiionale este true, valoarea operaiei
este valoarea expresiei 1. Altfel, valoarea operaiei este valoarea
expresiei 2.
Cele dou expresii trebuie s fie amndou aritmetice sau
amndou booleene sau amndou de tip referin.
Iat i un exemplu:
int i = 5;
int j = 4;
double f = ( i < j ) ? 100.5 : 100.4;

Parantezele nu sunt obligatorii.


Dup execuia instruciunilor de mai sus, valoarea lui f este
Iar dup:

100.4.

int a[] = { 1, 2, 3, 4, 5 };
int b[] = { 10, 20, 30 };
int k = ( ( a.length < b.length ) ? a : b )[0];

86

valoarea lui k va deveni

10.

5.2.3.4 Operaii ntregi


Dac amndoi operanzii unei operator sunt ntregi atunci ntreaga
operaie este ntreag.
Dac unul dintre operanzi este ntreg lung, operaia se va face cu
precizia de 64 de bii. Operanzii sunt eventual convertii. Rezultatul
este un ntreg lung sau o valoare boolean dac operatorul este un
operator condiional.
Dac nici unul dintre operanzi nu e ntreg lung, operaia se face
ntotdeauna pe 32 de bii, chiar dac cei doi operanzi sunt ntregi
scuri sau octei. Rezultatul este ntreg sau boolean.
Dac valoarea obinut este mai mare sau mai mic dect se poate
reprezenta pe tipul rezultat, nu este semnalat nici o eroare de
execuie, dar rezultatul este trunchiat.
5.2.3.5 Operaii flotante
Dac un operand al unei operaii este flotant, atunci ntreaga
operaie este flotant. Dac unul dintre operanzi este flotant dublu,
operaia este pe flotani dubli. Rezultatul este un flotant dublu sau
boolean.
n caz de operaii eronate nu se genereaz erori. n loc de aceasta se
obine rezultatul NaN. Dac ntr-o operaie particip un NaN
rezultatul este de obicei NaN.
n cazul testelor de egalitate, expresia
NaN == NaN

are ntotdeauna rezultatul fals pentru c un NaN nu este egal cu


nimic. La fel, expresia:
NaN != NaN

este ntotdeauna adevrat.


n plus, ntotdeauna expresia:
-0.0 == +0.0

87

este adevrat, unde +0.0 este zeroul pozitiv iar -0.0 este zeroul
negativ. Cele dou valori sunt definite n standardul IEEE 754.
n alte operaii ns, zero pozitiv difer de zero negativ. De exemplu
1.0 / 0.0 este infinit pozitiv iar 1.0 / -0.0 este infinit negativ.
5.2.3.6 Apeluri de metode
La apelul unei metode, valorile ntregi nu sunt automat extinse la
ntreg sau la ntreg lung ca la operaii. Asta nseamn c, dac un
operand este transmis ca ntreg scurt de exemplu, el rmne ntreg
scurt i n interiorul metodei apelate.

88

Capitolul V
5.3 Instruciuni
5.3.1 Blocuri de instruciuni
5.3.1.1 Declaraii de variabile locale
5.3.2 Tipuri de instruciuni
5.3.2.1 Instruciuni de atribuire
5.3.2.1.1 Atribuire cu operaie
5.3.2.1.2 Atribuiri implicite
5.3.2.2 Instruciuni etichetate
5.3.2.3 Instruciuni condiionale
5.3.2.3.1 Instruciunea if
5.3.2.3.2 Instruciunea switch
5.3.2.4 Instruciuni de ciclare
5.3.2.4.1 Instruciunea while
5.3.2.4.2 Instruciunea do
5.3.2.4.3 Instruciunea for
5.3.2.5 Instruciuni de salt
5.3.2.5.1 Instruciunea break
5.3.2.5.2 Instruciunea continue
5.3.2.5.3 Instruciunea return
5.3.2.5.4 Instruciunea throw
5.3.2.6 Instruciuni de protecie
5.3.2.6.1 Instruciunea try
5.3.2.6.2 Instruciunea synchronized
5.3.2.7 Instruciunea vid
5.3.1 Blocuri de instruciuni
Un bloc de instruciuni este o secven, eventual vid, de
instruciuni i declaraii de variabile locale. Aceste instruciuni se
89

execut n ordinea n care apar n interiorul blocului. Sintactic,


blocurile de instruciuni sunt delimitate n surs de
caracterele { i }.
n limbajul Java, regula general este aceea c oriunde putem pune
o instruciune putem pune i un bloc de instruciuni, cu cteva
excepii pe
care le vom sesiza la momentul potrivit, specificnd n acest fel c
instruciunile din interiorul blocului trebuiesc privite n mod unitar
i tratate ca o singur instruciune.
5.3.1.1 Declaraii de variabile locale
O declaraie de variabil local introduce o nou variabil care
poate fi folosit doar n interiorul blocului n care a fost definit.
Declaraia trebuie s conin un nume i un tip. n plus, ntr-o
declaraie putem specifica o valoare iniial n cazul n care valoarea
implicit a tipului variabilei, definit standard de limbajul Java, nu
ne satisface.
Numele variabilei este un identificator Java. Acest nume trebuie s
fie diferit de numele celorlalte variabile locale definite n blocul
respectiv i de eventualii parametri ai metodei n interiorul creia
este declarat blocul.
De exemplu, este o eroare de compilare s declarm cea de-a doua
variabilx n blocul:
{
int x = 3;

{
int x = 5;

}
}

Compilatorul va semnala faptul c deja exist o variabil cu acest


nume n interiorul metodei. Eroarea de compilare apare indiferent
dac cele dou variabile sunt de acelai tip sau nu.
Nu acelai lucru se ntmpl ns dac variabilele sunt declarate n
dou blocuri de instruciuni complet disjuncte, care nu se includ
unul pe cellalt. De exemplu, declaraiile urmtoare sunt perfect
valide:

90

{
{
int x = 3;

{
int x = 5;

}
}

Practic, fiecare bloc de instruciuni definete un domeniu de


existen a variabilelor locale declarate n interior. Dac un bloc are
subblocuri declarate n interiorul lui, variabilele din aceste
subblocuri trebuie s fie distincte ca nume fa de variabilele din
superbloc. Aceste domenii se pot reprezenta grafic ca n figura
urmtoare:

Figura 5.4 Reprezentarea grafic a domeniilor de existen a variabilelor incluse unul ntr-altul.

Figura reprezint situaia din primul exemplu. Observai c


domeniul blocului interior este complet inclus n domeniul blocului
exterior. Din aceast cauz, x apare ca fiind definit de dou ori. n
cel de-al doilea exemplu, reprezentarea grafic este urmtoarea:

91

Figura 5.5 Reprezentarea grafic a domeniilor de existen a variabilelor disjuncte.

n acest caz, domeniile n care sunt definite cele dou variabile sunt
complet disjuncte i compilatorul nu va avea nici o dificultate n a
identifica la fiecare referire a unei variabile cu numele x despre care
variabil este vorba. S mai observm c, n cel de-al doilea
exemplu, referirea variabilelor x n blocul mare, n afara celor dou
subblocuri este o eroare de compilare.
n cazul n care blocul mare este blocul de implementare al unei
metode i metoda respectiv are parametri, aceti parametri sunt
luai n considerare la fel ca nite declaraii de variabile care apar
chiar la nceputul blocului. Acest lucru face ca numele parametrilor
s nu poat fi folosit n nici o declaraie de variabil local din
blocul de implementare sau subblocuri ale acestuia.
n realitate, o variabil local poate fi referit n interiorul unui bloc
abia dup declaraia ei. Cu alte cuvinte, domeniul de existen al
unei variabile locale ncepe din punctul de declaraie i continu
pn la terminarea blocului.
Astfel, urmtoarea secven de instruciuni:
{
x = 4;
int x = 3;
}

va determina o eroare de compilare, cu specificaia c variabila x nu


a fost nc definit n momentul primei atribuiri.
Acest mod de lucru cu variabilele face corect urmtoarea secven
de instruciuni:
{
{
int x = 4;
}
int x = 3;
}

pentru c, n momentul declaraiei din interiorul subblocului,


variabila xdin exterior nu este nc definit. La ieirea din subbloc,
prima declaraie i termin domeniul, aa c se poate defini fr
probleme o nou variabil cu acelai nume.
5.3.2 Tipuri de instruciuni

92

5.3.2.1 Instruciuni de atribuire


O atribuire este o setare de valoare ntr-o locaie de memorie. Forma
general a unei astfel de instruciuni este:
Locaie = valoare ;
Specificarea locaiei se poate face n mai multe feluri. Cel mai
simplu este s specificm un nume de variabil local. Alte
alternative sunt acelea de a specifica un element dintr-un tablou de
elemente sau o variabil care nu este declarat final din interiorul
unei clase sau numele unui parametru al unei metode.
Valoarea care trebuie atribuit poate fi un literal sau rezultatul
evalurii unei expresii.
Instruciunea de atribuire are ca rezultat chiar valoarea atribuit.
Din aceast cauz, la partea de valoare a unei operaii de atribuire
putem avea chiar o alt operaie de atribuire ca n exemplul
urmtor:
int x = 5;
int y = 6;
x = ( y = y / 2 );

Valoarea final a lui x va fi identic cu valoarea lui y i va fi egal


cu 3. Parantezele de mai sus sunt puse doar pentru claritatea
codului, pentru a nelege exact care este ordinea n care se execut
atribuirile. n realitate, ele pot s lipseasc pentru c, n mod
implicit, Java va executa nti atribuirea din dreapta. Deci, ultima
linie se poate rescrie ca:
x = y = y / 2;

De altfel, gruparea invers nici nu are sens:


( x = y ) = y / 2;

Aceast instruciune va genera o eroare de compilare pentru c,


dup executarea atribuirii din paranteze, rezultatul este
valoarea 6 iar unei valori nu i se poate atribui o alt valoare.
n momentul atribuirii, dac valoarea din partea dreapt a operaiei
nu este de acelai tip cu locaia din partea stng, compilatorul va
ncerca conversia valorii la tipul locaiei n modul pe care l-am
discutat n paragraful referitor la conversii. Aceast conversie
trebuie s fie posibil, altfel compilatorul va semnala o eroare.
93

Pentru anumite conversii, eroarea s-ar putea s nu poat fi


depistat dect n timpul execuiei. n aceste cazuri, compilatorul
nu va semnala eroare dar va fi semnalat o eroare n timpul
execuiei i rularea programului va fi abandonat.
5.3.2.1.1 Atribuire cu operaie

Se ntmpl deseori ca valoarea care se atribuie unei locaii s


depind de vechea valoare care era memorat n locaia respectiv.
De exemplu, n instruciunea:
int x = 3;
x = x * 4;

vechea valoare a lui x este nmulit cu 4 i rezultatul nmulirii este


memorat napoi n locaia destinat lui x. ntr-o astfel de
instruciune, calculul adresei locaiei lui x este efectuat de dou ori,
o dat pentru a lua vechea valoare i nc o dat pentru a memora
noua valoare. n realitate, acest calcul nu ar trebui executat de dou
ori pentru c locaia variabilei xnu se schimb n timpul
instruciunii.
Pentru a ajuta compilatorul la generarea unui cod eficient, care s
calculeze locaia lui x o singur dat, n limbajul Java au fost
introduse instruciuni mixte de calcul combinat cu atribuire. n
cazul nostru, noua form de scriere, mai eficient, este:
int x = 3;
x *= 4;

Eficiena acestei exprimri este cu att mai mare cu ct calculul


locaiei este mai complicat. De exemplu, n secvena urmtoare:
int x = 3, y = 5;
double valori[] = new double[10];
valori[( x + y ) / 2] += 3.5;

calculul locaiei de unde se va lua o valoare la care se va


aduna 3.5 i unde se va memora napoi rezultatul acestei operaii
este efectuat o singur dat. n acest exemplu, calcului locaiei
presupune execuia expresiei:
( x + y ) / 2

i indexarea tabloului numit valori cu valoarea rezultat. Valoarea


din partea dreapt poate fi o expresie arbitrar de complicat, ca n:
valori[x] += 7.0 * ( y * 5 );

94

Iat toi operatorii care pot fi mixai cu o atribuire:


*=, /=, %=, +=, -=, <<=, >>=, >>>=,

&=, |=, ^= ^

5.3.2.1.2 Atribuiri implicite

S mai observm c, n cazul folosirii operatorilor de incrementare


i decrementare se face i o atribuire implicit pentru c pe lng
valoarea rezultat n urma operaiei, se modific i valoarea
memorat la locaia pe care se aplic operatorul. La fel ca i la
operaiile mixte de atribuire, calculul locaiei asupra creia se aplic
operatorul se efectueaz o singur dat.
5.3.2.2 Instruciuni etichetate
Unele dintre instruciunile din interiorul unui bloc de instruciuni
trebuie referite din alt parte a programului pentru a se putea
direciona execuia spre aceste instruciuni. Pentru referirea acestor
instruciuni, este necesar ca ele s aib o etichet asociat. O
etichet este deci un nume dat unei instruciuni din program prin
care instruciunea respectiv poate fi referit din alte pri ale
programului.
Eticheta cea mai simpl este un simplu identificator urmat de
caracterul :i de instruciunea pe care dorim s o etichetm:
Etichet: Instruciune
ca n exemplul urmtor:
int a = 5;
Eticheta: a = 3;

Pentru instruciunea switch, descris mai jos, sunt definite dou


moduri diferite de etichetare. Acestea au forma:
case

Valoare: Instruciune

default:

Instruciune

Exemple pentru folosirea acestor forme sunt date la definirea


instruciunii.
5.3.2.3 Instruciuni condiionale

95

Instruciunile condiionale sunt instruciuni care selecteaz pentru


execuie o instruciune dintr-un set de instruciuni n funcie de o
anumit condiie.
5.3.2.3.1 Instruciunea if

Instruciunea if primete o expresie a crei valoare este obligatoriu


de tipul boolean. Evaluarea acestei expresii poate duce la doar dou
valori: adevrat sau fals. n funcie de valoarea rezultat din aceast
evaluare, se execut unul din dou seturi de instruciuni distincte,
specificate de instruciunea if.
Sintaxa acestei instruciuni este urmtoarea:
if(

Expresie ) Instruciune1 [else Instruciune2]

Dup evaluarea expresiei booleene, dac valoarea rezultat este


se execut instruciunea 1.

true,

Restul instruciunii este opional, cu alte cuvinte partea care ncepe


cu cuvntul rezervat else poate s lipseasc. n cazul n care aceast
parte nu lipsete, dac rezultatul evalurii expresiei este false se va
executa instruciunea 2.
Indiferent de instruciunea care a fost executat n interiorul
unui if, dup terminarea acesteia execuia continu cu
instruciunea de dup instruciunea if, n afar de cazul n care
instruciunile executate conin n interior o instruciune de salt.
S mai observm c este posibil ca ntr-o instruciune if s nu se
execute nici o instruciune n afar de evaluarea expresiei n cazul
n care expresia este fals iar partea else din
instruciunea if lipsete. Expresia boolean va fi ntotdeauna
evaluat.
Iat un exemplu de instruciune

if

n care partea

else

lipsete:

int x = 3;
if( x == 3 )
x *= 7;

i iat un exemplu n care sunt prezente ambele pri:


int x = 5;
if( x % 2 == 0 )
x = 100;
else
x = 1000;

96

Instruciunea 1 nu poate lipsi niciodat. Dac totui pe ramura de


adevr a instruciunii condiionale nu dorim s executm nimic,
putem folosi o instruciune vid, dup cum este artat puin mai
departe.
n cazul n care dorim s executm mai multe instruciuni pe una
dintre ramurile instruciunii if, putem s n locuim instruciunea 1
sau 2 sau pe amndou cu blocuri de instruciuni, ca n exemplul
urmtor:
int x = 5;
if( x == 0 ) {
x = 3;
y = x * 5;
} else {
x = 5;
y = x * 7;
}

Expresia boolean poate s fie i o expresie compus de forma:


int
int
if(
x =

x = 3;
y = 5;
y != 0 && x / y == 2 )
4;

n acest caz, aa cum deja s-a specificat la descrierea


operatorului &&, evaluarea expresiei nu este terminat n toate
situaiile. n exemplul nostru, dac y este egal cu 0, evaluarea
expresiei este oprit i rezultatul este fals. Aceast comportare este
corect pentru c, dac un termen al unei operaii logice de
conjuncie este fals, atunci ntreaga conjuncie este fals.
n plus, acest mod de execuie ne permite s evitm unele operaii
cu rezultat incert, n cazul nostru o mprire prin 0. Pentru mai
multe informaii relative la operatorii && i || citii seciunea
destinat operatorilor.
5.3.2.3.2 Instruciunea switch

Instruciunea switch ne permite saltul la o anumit instruciune


etichetat n funcie de valoarea unei expresii. Putem s specificm
cte o etichet pentru fiecare valoare particular a expresiei pe care
dorim s o difereniem. n plus, putem specifica o etichet la care s
se fac saltul implicit, dac expresia nu ia nici una dintre valorile
particulare specificate.
Sintaxa instruciunii este:
97

switch(

Expresie ) {

[case ValoareParticular: Instruciuni;]*


[default: InstruciuniImplicite;]
}
Execuia unei instruciuni switch ncepe ntotdeauna prin evaluarea
expresiei dintre parantezele rotunde. Aceast expresie trebuie s
aib tipul caracter, octet, ntreg scurt sau ntreg. Dup evaluarea
expresiei se trece la compararea valorii rezultate cu valorile
particulare specificate n etichetelecase din interiorul blocului de
instruciuni. Dac una dintre valorile particulare este egal cu
valoarea expresiei, se execut instruciunile ncepnd de la
eticheta case corespunztoare acelei valori n jos, pn la captul
blocului. Dac nici una dintre valorile particulare specificate nu este
egal cu valoarea expresiei, se execut instruciunile care ncep cu
eticheta default, dac aceasta exist.
Iat un exemplu de instruciune

switch:

int x = 4;

int y = 0;
switch( x + 1 ) {
case 3:
x += 2;
y++;
case 5:
x = 11;
y++;
default:
x = 4;
y += 3;
}

Dac valoarea lui x n timpul evalurii expresiei este 2 atunci


expresia va avea valoarea 3 i instruciunile vor fi executate una
dup alta ncepnd cu cea etichetat cu case 3. n ordine, x va
deveni 4, y va deveni 1, x va deveni11, y va deveni 2, x va
deveni 4 i y va deveni 5.
Dac valoarea lui x n timpul evalurii expresiei este 4 atunci
expresia va avea valoarea 5 i instruciunile vor fi executate pornind
de la cea etichetat cu case 5. n ordine, x va deveni 11, y va
deveni 1, x va deveni 4 iy va deveni 4.

98

n fine, dac valoarea lui x n timpul evalurii expresiei este diferit


de 2 i4, se vor executa instruciunile ncepnd cu cea etichetat
cu default. n ordine, x va deveni 4 i y va deveni 3.
Eticheta default poate lipsi, caz n care, dac nici una dintre valorile
particulare nu este egal cu valoarea expresiei, nu se va executa nici
o instruciune din bloc.
n cele mai multe cazuri, aceast comportare a
instruciunii switch nu ne convine, din cauza faptului c
instruciunile de dup cea etichetat cu case5 se vor executa i dac
valoarea este 3. La fel, instruciunile de dup cea etichetat
cu default se execut ntotdeauna. Pentru a schimba aceast
comportare trebuie s folosim una dintre instruciunile de salt care
s opreasc execuia instruciunilor din bloc nainte de ntlnirea
unei noi instruciuni etichetate.
Putem de exemplu folosi instruciunea de salt break care va opri
execuia instruciunilor din blocul switch. De exemplu:
char c = '\t';

String mesaj = "nimic";


switch( c ) {
case '\t':
mesaj = "tab";
break;
case '\n':
mesaj = "linie noua";
break;
case '\r':
mesaj = "retur";
default:
mesaj = mesaj + " de";
mesaj = mesaj + " car";
}

n acest caz, dac c este egal cu caracterul tab, la terminarea


instruciuniiswitch, mesaj va avea valoarea "tab". n cazul n
care c are valoarea CR,mesaj va deveni mai nti "retur" apoi "retur
de" i apoi "retur de car". Lipsa lui break dup instruciunea
mesaj = "retur";

face ca n continuare s fie executate i instruciunile de dup cea


etichetat cu default.
5.3.2.4 Instruciuni de ciclare

99

Instruciunile de ciclare (sau ciclurile, sau buclele) sunt necesare


atunci cnd dorim s executm de mai multe ori aceeai
instruciune sau acelai bloc de instruciuni. Necesitatea acestui
lucru este evident dac ne gndim c programele trebuie s poat
reprezenta aciuni de forma: execut 10 ntoarceri, execut 7
genoflexiuni, execut flotri pn ai obosit, etc.
Desigur, sintaxa instruciunilor care se execut trebuie s fie
aceeai, pentru c ele vor fi n realitate scrise n Java o singur
dat. Totui, instruciunile nu sunt neaprat aceleai. De exemplu,
dac executm n mod repetat instruciunea:
int tablou[] = new int[10];
int i = 0;
tablou[i++] = 0;

n realitate se va memora valoarea 0 n locaii diferite pentru c


variabila care particip la calculul locaiei i modific la fiecare
iteraie valoarea. La primul pas, se va face 0 primul element din
tablou i n acelai timp i va primi valoarea 1. La al doilea pas, se va
face 0 al doilea element din tablou ii va primi valoarea 2, i aa mai
departe.
Lucrurile par i mai clare dac ne gndim c instruciunea
executat n mod repetat poate fi o instruciune if. n acest caz, n
funcie de expresia condiional din if se poate executa o ramur
sau alta a instruciunii.
De exemplu instruciunea din bucl poate fi:
int i = 0;
if( i++ % 2 == 0 )

else

n acest caz, i este cnd par cnd impar i se execut alternativ cele
dou ramuri din if. Desigur, comportarea descris este valabil
dac valoarea luii nu este modificat n interiorul uneia dintre
ramuri.
5.3.2.4.1 Instruciunea while

Aceast instruciune de buclare se folosete atunci cnd vrem s


executm o instruciune atta timp ct o anumit expresie
condiional rmne adevrat. Expresia condiional se evalueaz

100

i testeaz nainte de execuia instruciunii, astfel c, dac expresia


era de la nceput fals, instruciunea nu se mai executa niciodat.
Sintaxa acestei instruciuni este:
while(

Test ) Corp

Test este o expresie boolean iar Corp este o instruciune normal,


eventual vid. Dac avem nevoie s repetm mai multe instruciuni,
putem nlocui corpul buclei cu un bloc de instruciuni.
Iat i un exemplu:
int i = 0;
int tablou[] = new int[20];
while( i < 10 )
tablou[i++] = 1;

Bucla while de mai sus se execut de 10 ori primele 10 elemente din


tablou fiind iniializate cu 1. n treact fie spus, celelalte rmn la
valoarea 0 care este valoarea implicit pentru ntregi. Dup cei 10
pai iterativi, i devine 10i testul devine fals (10 < 10).
n exemplul urmtor, corpul nu se execut nici mcar o dat:
int i = 3;
while( i < 3 )
i++;

Putem s crem un ciclu infinit (care nu se termin niciodat) prin:


while( true )
;

ntreruperea execuiei unui ciclu infinit se poate face introducnd n


corpul ciclului o instruciune de salt.
5.3.2.4.2 Instruciunea do

Buclele do se folosesc atunci cnd testul de terminare a buclei


trebuie fcut dup execuia corpului buclei. Sintaxa de descriere a
instruciuni do este:
do

Corp

while(

Test ) ;

Test este o expresie boolean iar Corp este o instruciune sau un


bloc de instruciuni. Execuia acestei instruciuni nseamn
execuia corpului n mod repetat atta timp ct expresia Test are
101

valoarea adevrat. Testul se evalueaz dup execuia corpului, deci


corpul se execut cel puin o dat.
De exemplu, n instruciunea:
int i = 3;
do
i++;
while( false );

valoarea final a lui i este 4, pentru c instruciunea i++ care


formeaz corpul buclei se execut o dat chiar dac testul este
ntotdeauna fals.
n instruciunea:
int i = 1;
do {
tablou[i] = 0;
i += 2;
} while( i < 5 );

sunt setate pe 0 elementele 1 i 3 din tablou. Dup a doua


iteraie, i devine5 i testul eueaz cauznd terminarea iteraiei.
5.3.2.4.3 Instruciunea for

Instruciunea for se folosete atunci cnd putem identifica foarte


clar o parte de iniializare a buclei, testul de terminare a buclei, o
parte de reluare a buclei i un corp pentru bucl. n acest caz,
putem folosi sintaxa:
for(

Iniializare Test ; Reluare ) Corp

Corp i Iniializare sunt instruciuni normale. Test este o expresie


boolean iar Reluare este o instruciune creia i lipsete
caracterul ; final.
Execuia unei bucle for ncepe cu execuia instruciunii de
iniializare. Aceast instruciune stabilete de obicei nite valori
pentru variabilele care controleaz bucla. Putem chiar declara aici
noi variabile. Aceste variabile exist doar n interiorul corpului
buclei i n instruciunile de test i reluare ale buclei.
n partea de iniializare nu putem scrie dect o singur instruciune
fie ea declaraie sau instruciune normal. n acest caz
instruciunea nu se poate nlocui cu un bloc de instruciuni. Putem
ns s declarm dou variabile cu o sintax de forma:
102

int i = 0, j = 1;

Dup execuia prii de iniializare se pornete bucla propriu-zis.


Aceasta const din trei instruciuni diferite executate n mod
repetat. Cele trei instruciuni sunt testul, corpul buclei i
instruciunea de reluare. Testul trebuie s fie o expresie boolean.
Dac aceasta este evaluat la valoarea adevrat, bucla continu cu
execuia corpului, a instruciunii de reluare i din nou a testului. n
clipa n care testul are valoarea fals, bucla este oprit fr s mai fie
executat corpul sau reluarea.
Iat un exemplu:
int x = 0;
for( int i = 3; i < 30; i += 10 )
x += i;

n aceast bucl se execut mai nti crearea variabilei i i


iniializarea acesteia cu 3. Dup aceea se testeaz variabila i dac
are o valoare mai mic dect 30. Testul are rezultat adevrat (i este 0
< 30) i se trece la execuia corpului unde x primete valoarea 3 (0 +
3). n continuare se execut partea de reluare n care i este crescut
cu 10, devenind 13. Se termin astfel primul pas al buclei i aceasta
este reluat ncepnd cu testul care este n continuare adevrat (13
< 30). Se execut corpul, xdevenind 16 (3 + 13), i reluarea,
unde x devine 23 (13 + 10). Se reia bucla de la test care este n
continuare adevrat (23 < 30). Se execut corpul
unde x devine 39 (16 + 23) i reluarea unde i devine 33 (23 + 10). Se
reia testul care n acest caz devine fals (33 < 30) i se prsete
bucla, continundu-se execuia cu prima instruciune de dup
bucl.
Dup ieirea din bucl, variabila i nu mai exist, deci nu se mai
poate folosi i nu putem vorbi despre valoarea cu care iese din
bucl, iar variabila xrmne cu valoarea 39.
Pentru a putea declara variabila i n instruciunea de iniializare a
buclei for este necesar ca n blocurile superioare instruciunii for s
nu existe o alt variabil i, s nu existe un parametru numit i i nici
o etichet cu acest nume.
Dac dorim un corp care s conin mai multe instruciuni, putem
folosi un bloc. Nu putem face acelai lucru n partea de iniializare
sau n partea de reluare.

103

Oricare dintre prile buclei for n afar de iniializare poate s


lipseasc. Dac aceste pri lipsesc, se consider c ele sunt
reprezentate de instruciunea vid. Dac nu dorim iniializare
trebuie totui s specificm implicit instruciunea vid. Putem de
exemplu s scriem o bucl infinit prin:
int x;
for( ;; )
x = 0;

Putem specifica funcionarea instruciunii for folosindu-ne de o


instruciune while n felul urmtor:
Iniializare
while(

Test ) {

Corp
Reluare ;
}
n fine, schema urmtoare reprezint funcionarea unei bucle

for:

Figura 5.6 Schema de funcionare a buclei for.

5.3.2.5 Instruciuni de salt


Instruciunile de salt provoac ntreruperea forat a unei bucle, a
unui bloc de instruciuni sau ieirea dintr-o metod. Instruciunile
de salt sunt destul de periculoase pentru c perturb curgerea
uniform a programului ceea ce poate duce la o citire i nelegere
eronat a codului rezultat.
104

5.3.2.5.1 Instruciunea break

Instruciunea break produce ntreruperea unei bucle sau a unui


blocswitch. Controlul este dat instruciunii care urmeaz imediat
dup bucla ntrerupt sau dup blocul instruciunii switch.
De exemplu n secvena:
int i = 1, j = 3;
int tablou[] = new int[10];
while( i < 10 ) {
tablou[i++] = 0;
if( i == j )
break;
}
i += 2;

sunt setate pe 0 elementele 1 i 2 ale tabloului. Dup a doua


iteraie idevine 3 i testul i == j are valoarea adevrat, producnduse execuia instruciunii break.
Instruciunea break cauzeaz ieirea forat din bucl, chiar dac
testul buclei i < 10 este n continuare valid. La terminarea tuturor
instruciunilor de mai sus, i are valoarea 5.
n exemplul urmtor:
int i, j = 3;
int tablou[] = new tablou[10];
do {
tablou[i] = 0;
if( i++ >= j )
break;
} while( i < 10 );

sunt setate pe 0 elementele 0, 1, 2 i 3 din tablou. Dac v ntrebai


la ce mai folosete testul buclei, atunci s spunem c este o msur
suplimentar de siguran. Dac cumva j intr cu o valoare greit,
testul ne asigur n continuare c nu vom ncerca s setm un
element care nu exist al tabloului. De fapt, pericolul exist nc,
dac valoarea iniial a luii este greit, deci testul ar trebui mutat
la nceput i bucla transformat ntr-un while, ca cel de mai sus.
n cazul buclelor for, s mai precizm faptul c la o ieire forat nu
se mai execut instruciunea de reluare.
Instruciunea
n:
break

break

poate avea ca argument opional o etichet, ca

Identificator;
105

n acest caz, identificatorul trebuie s fie eticheta unei instruciuni


care s includ instruciunea break. Prin faptul c instruciunea
include instruciunea break, nelegem c instruciunea break apare
n corpul instruciunii care o include sau n corpul unei instruciuni
care se gsete n interiorul corpului instruciunii care include
instruciunea break. Controlul revine instruciunii de dup
instruciunea etichetat cu identificatorul specificat.
De exemplu, n instruciunile:
int i, j;
asta: while( i < 3 ) {
do {
i = j + 1;
if( i == 3 )
break asta;
} while( j++ < 3 );
}
j = 10;

instruciunea break termin bucla do i bucla while controlul fiind dat


instruciunii de dup while, i anume atribuirea:
j = 10;
5.3.2.5.2 Instruciunea continue

Instruciunea continue permite reluarea unei bucle fr a mai


termina execuia corpului acesteia. Reluarea se face ca i cum
corpul buclei tocmai a fost terminat de executat. Bucla nu este
prsit.
De exemplu, n instruciunea:
int i;
while( i < 10 ) {
i++;
continue;
i++;
}

corpul buclei se execut de 10 ori, pentru c a doua incrementare a


lui i nu se execut niciodat. Execuia ncepe cu testul i apoi
urmeaz cu prima incrementare. Dup aceasta se execut
instruciunea continue care duce la reluarea buclei, pornind de la
test i urmnd cu incrementarea i din nou instruciunea continue.
n exemplul urmtor:
int i;

106

do {
i++;
continue;
i++;
} while( i < 10 );

corpul se execut de 10 ori la fel ca i mai sus.


Instruciunea continue duce la evitarea celei de-a doua incrementri,
dar nu i la evitarea testului de sfrit de bucl.
n sfrit, n exemplul urmtor:
for( int i = 0; i < 10; i++ ) {
continue;
i++;
}

corpul se execut tot de 10 ori, ceea ce nseamn c reluarea buclei


duce la execuia instruciunii de reluare a buclei for i apoi a
testului. Doar ceea ce este n interiorul corpului este evitat.
Instruciunea continue poate avea, la fel ca i instruciunea break, un
identificator opional care specific eticheta buclei care trebuie
continuat. Dac exist mai multe bucle imbricate una n cealalt
buclele interioare celei referite de etichet sunt abandonate.
De exemplu, n secvena:
asta: for( int i, j = 1; i < 10; i++ ) {
while( j < 5 ) {
j++;
if( j % 2 == 0 )
continue asta;
}
}

instruciunea continue provoac abandonarea buclei


buclei for cu partea de reluare i apoi testul.

while

i reluarea

5.3.2.5.3 Instruciunea return

Instruciunea return provoac prsirea corpului unei metode. n


cazul n care return este urmat de o expresie, valoarea expresiei
este folosit ca valoare de retur a metodei. Aceast valoare poate fi
eventual convertit ctre tipul de valoare de retur declarat al
metodei, dac acest lucru este posibil. Dac nu este posibil, va fi
semnalat o eroare de compilare.

107

Este o eroare de compilare specificarea unei valori de retur ntr-o


instruciune return din interiorul unei metode care este
declarat void, cu alte cuvinte care nu ntoarce nici o valoare.
Instruciunea return fr valoare de retur poate fi folosit i pentru a
prsi execuia unui iniializator static.
Exemple de instruciuni return vei gsi n seciunea care trateaz
metodele unei clase de obiecte.
5.3.2.5.4 Instruciunea throw

Instruciunea throw este folosit pentru a semnaliza o excepie de


execuie. Aceast instruciune trebuie s aib un argument i
acesta trebuie s fie un tip obiect, de obicei dintr-o subclas a clasei
de obiecte Exception.
La execuia instruciunii throw, fluxul normal de execuie este
prsit i se termin toate instruciunile n curs pn la prima
instruciune try care specific ntr-o clauz catch un argument
formal de acelai tip cu obiectul aruncat sau o superclas a
acestuia.
5.3.2.6 Instruciuni de protecie
Aceste instruciuni sunt necesare pentru tratarea erorilor i a
excepiilor precum i pentru sincronizarea unor secvene de cod
care nu pot rula n paralel.
5.3.2.6.1 Instruciunea try

Instruciunea try iniiaz un context de tratare a excepiilor. n orice


punct ulterior iniializrii acestui context i nainte de terminarea
acestuia, o excepie semnalat prin execuia unei
instruciuni throw va returna controlul la nivelul instruciunii try,
abandonndu-se n totalitate restul instruciunilor din corpul
acestuia.
La semnalarea unei excepii aceasta poate fi prins de o
clauz catch i, n funcie de tipul obiectului aruncat, se pot executa
unele instruciuni care repun programul ntr-o stare stabil. De
obicei, o excepie este generat atunci cnd s-a produs o eroare
major i continuarea instruciunilor din contextul curent nu mai
are sens.

108

n finalul instruciunii, se poate specifica i un bloc de instruciuni


care se execut imediat dup blocul try i blocurile catch indiferent
cum s-a terminat execuia acestora. Pentru specificarea acestor
instruciuni, trebuie folosit o clauz finally.
Iat sintaxa unei instruciuni
try

try:

Bloc1 [catch( Argument ) Bloc2]*[finally Bloc3]

Dac, undeva n interiorul blocului 1 sau n metodele apelate din


interiorul acestuia, pe oricte nivele, este apelat o
instruciune throw, execuia blocului i a metodelor n curs este
abandonat i se revine n instruciunea try. n continuare, obiectul
aruncat de throw este comparat cu argumentele specificate n
clauzele catch. Dac unul dintre aceste argumente este instan a
aceleiai clase sau a unei superclase a clasei obiectului aruncat, se
execut blocul de instruciuni corespunztor clauzeicatch respective.
Dac nici una dintre clauzele catch nu se potrivete, obiectul este
aruncat mai departe. Dac excepia nu este nicieri prins n
program, acesta se termin cu o eroare de execuie.
Indiferent dac a aprut o excepie sau nu, indiferent dac s-a
executat blocul unei clauze catch sau nu, n finalul execuiei
instruciunii try se execut blocul specificat n clauza finally, dac
aceasta exist.
Clauza finally se execut chiar i dac n interiorul blocului 1 s-a
executat o instruciune throw care a aruncat un obiect care nu poate
fi prins de clauzele catch ale acestei instruciuni try. n astfel de
situaii, execuia instruciunii throw se oprete temporar, se execut
blocul finally i apoi se arunc mai departe excepia.
Exemple de utilizare a instruciunii

try

gsii n paragraful 9.2

5.3.2.6.2 Instruciunea synchronized

Instruciunea synchronized introduce o secven de instruciuni


critic. O secven critic de instruciuni trebuie executat n aa fel
nct nici o alt parte a programului s nu poat afecta obiectul cu
care lucreaz secvena dat. Secvenele critice apar de obicei atunci
cnd mai multe pri ale programului ncearc s acceseze n
acelai timp aceleai resurse.
Gndii-v, de exemplu, ce s-ar ntmpla dac mai multe pri ale
programului ar ncerca s incrementeze n acelai timp valoarea
109

unei variabile. Una dintre ele ar citi vechea valoare a variabilei, s


spunem 5, ar incrementa-o la 6 i, cnd s o scrie napoi, s
presupunem c ar fi ntrerupt de o alt parte a programului care ar
incrementa-o la 6. La revenirea n prima parte, aceasta ar termina
prima incrementare prin scrierea valorii 6 napoi n variabil.
Valoarea final a variabilei ar fi 6 n loc s fie 7 aa cum ne-am
atepta dac cele dou incrementri s-ar face pe rnd.
Spunem c cele dou regiuni n care se face incrementarea aceleiai
variabile sunt regiuni critice. nainte ca una dintre ele s se execute,
ar trebui s ne asigurm c cealalt regiune critic nu ruleaz deja.
Cea mai simpl cale de a face acest lucru este s punem o condiie
de blocare chiar pe variabila incrementat. Ori de cte ori o regiune
critic va ncerca s lucreze, va verifica dac variabila noastr este
liber sau nu.
Instruciunea synchronized i blocheaz obiectul pe care l primete
ca parametru i apoi execut secvena critic. La sfritul acesteia
obiectul este deblocat napoi. Dac instruciunea nu poate bloca
imediat obiectul pentru c acesta este blocat de o alt instruciune,
ateapt pn cnd obiectul este deblocat.
Mai mult despre aceast instruciune precum i exemple de utilizare
vei gsi n partea a treia, capitolul 9. Pn atunci, iat sintaxa
general a acestei instruciuni:
synchronized

( Expresie ) Instruciune

Expresia trebuie s aib ca valoare o referin ctre un obiect sau


un tablou care va servi drept dispozitiv de blocare. Instruciunea
poate fi o instruciune simpl sau un bloc de instruciuni.
5.3.2.7 Instruciunea vid
Instruciunea vid este o instruciune care nu execut nimic. Ea este
folosit uneori, atunci cnd este obligatoriu s avem o instruciune,
dar nu dorim s executm nimic n acea instruciune. De exemplu,
n cazul unei instruciuni if, este obligatoriu s avem o instruciune
pe ramura de adevr. Dac ns nu dorim s executm nimic acolo,
putem folosi un bloc vid sau o instruciune vid.
Sintaxa pentru o instruciune vid este urmtoarea:
;

110

Iat i un exemplu:
int x = 3;
if( x == 5 ) ; else x = 5;

Caracterul ; care apare dup condiia din if reprezint o


instruciune vid care specific faptul c, n cazul n care x are
valoarea 5 nu trebuie s se execute nimic.

111

Capitolul VI
Obiecte Java
6.1 Declaraia unei noi clase de obiecte
Pasul 1: Stabilirea conceptului reprezentat de clasa de obiecte
Pasul 2: Stabilirea numelui clasei de obiecte
Pasul 3: Stabilirea superclasei
Pasul 4: Stabilirea interfeelor pe care le respect clasa
Pasul 5: Stabilirea modificatorilor clasei
Pasul 6: Scrierea corpului declaraiei
Stop: Forma general a unei declaraii de clas
6.2 Variabilele unei clase
6.2.1
6.2.2
6.2.3
6.2.4
6.2.5

Modificatori
Protecie
Accesarea unei variabile
Vizibilitate
Variabile predefinite: this i super

6.3 Metodele unei clase


6.3.1 Declararea metodelor
6.3.1.1 Numele i parametrii metodelor
6.3.1.2 Modificatori de metode
6.3.1.2.1 Metode statice
6.3.1.2.2 Metode abstracte
6.3.1.2.3 Metode finale
6.3.1.2.4 Metode native
6.3.1.2.5 Metode sincronizate
6.3.1.3 Protejarea metodelor
6.3.2
6.3.3
6.3.4
6.3.5

Clauze throws
Apelul metodelor
Valoarea de retur a unei metode
Vizibilitate

6.4 Iniializatori statici


6.5 Constructori i finalizatori
112

6.5.1 constructori
6.5.2 Finalizatori
6.5.3 Crearea instanelor
6.6 Derivarea claselor
6.7 Interfee
n primul rnd s observm c, atunci cnd scriem programe n
Java nu facem altceva dect s definim noi i noi clase de obiecte.
Dintre acestea, unele vor reprezenta nsi aplicaia noastr n timp
ce altele vor fi necesare pentru rezolvarea problemei la care lucrm.
Ulterior, atunci cnd dorim s lansm aplicaia n execuie nu va
trebui dect s instaniem un obiect reprezentnd aplicaia n sine
i s apelm o metod de pornire definit de ctre aplicaie, metod
care de obicei are un nume i un set de parametri bine fixate.
Totui, numele acestei metode depinde de contextul n care este
lansat aplicaia noastr.
Aceast abordare a construciei unei aplicaii ne spune printre altele
c vom putea lansa oricte instane ale aplicaiei noastre dorim,
pentru c fiecare dintre acestea va reprezenta un obiect n memorie
avnd propriile lui valori pentru variabile. Execuia instanelor
diferite ale aplicaiei va urma desigur ci diferite n funcie de
interaciunea fiecreia cu un utilizator, eventual acelai, i n
funcie de unii parametri pe care i putem defini n momentul crerii
fiecrei instane.

6.1 Declaraia unei noi clase de obiecte


Pasul 1: Stabilirea conceptului reprezentat de clasa de obiecte
S vedem ce trebuie s definim atunci cnd dorim s crem o nou
clas de obiecte. n primul rnd trebuie s stabilim care este
conceptul care este reprezentat de ctre noua clas de obiecte i s
definim informaiile memorate n obiect i modul de utilizare a
acestuia. Acest pas este cel mai important din tot procesul de
definire al unei noi clase de obiecte. Este necesar s ncercai s
respectai dou reguli oarecum antagonice. Una dintre ele spune c
nu trebuiesc create mai multe clase de obiecte dect este nevoie,
pentru a nu face dificil nelegerea modului de lucru al aplicaiei la
care lucrai. Cea de-a doua regul spune c nu este bine s mixai
ntr-un singur obiect funcionaliti care nu au nimic n comun,
crend astfel clase care corespund la dou concepte diferite.

113

Medierea celor dou reguli nu este ntotdeauna foarte uoar.


Oricum, v va fi mai uor dac pstrai n minte faptul c fiecare
clas pe care o definii trebuie s corespund unui concept real bine
definit, necesar la rezolvarea problemei la care lucrai. i mai
pstrai n minte i faptul c este inutil s lucrai cu concepte foarte
generale atunci cnd aplicaia dumneavoastr nu are nevoie dect
de o particularizare a acestora. Riscai s pierdei controlul
dezvoltrii acestor clase de obiecte prea generale i s ngreunai
dezvoltarea aplicaiei.
Pasul 2: Stabilirea numelui clasei de obiecte
Dup ce ai stabilit exact ce dorii de la noua clas de obiecte,
suntei n msur s gsii un nume pentru noua clas, nume care
trebuie s urmeze regulile de construcie ale identificatorilor
limbajului Java definite n capitolul anterior.
Stabilirea unui nume potrivit pentru o nou clas nu este
ntotdeauna un lucru foarte uor. Problema este c acest nume nu
trebuie s fie exagerat de lung dar trebuie s exprime suficient de
bine destinaia clasei. Regulile de denumire ale claselor sunt
rezultatul experienei fiecruia sau al unor convenii de numire
stabilite anterior. De obicei, numele de clase este bine s nceap cu
o liter majuscul. Dac numele clasei conine n interior mai multe
cuvinte, aceste cuvinte trebuie de asemenea ncepute cu liter
majuscul. Restul caracterelor vor fi litere minuscule.
De exemplu, dac dorim s definim o clas de obiecte care
implementeaz conceptul de motor Otto vom folosi un nume
ca MotorOtto pentru noua clas ce trebuie creat. La fel, vom defini
clasa MotorDiesel sau MotorCuReacie. Dac ns avem nevoie s definim
o clas separat pentru un motor Otto cu cilindri n V i carburator,
denumirea clasei caMotorOttoCuCilindrinViCarburator nu este poate
cea mai bun soluie. Poate c n acest caz este preferabil o
prescurtare de forma MotorOttoVC. Desigur, acestea sunt doar cteva
remarci la adresa acestei probleme i este n continuare necesar ca
n timp s v creai propria convenie de denumire a claselor pe care
le creai.
Pasul 3: Stabilirea superclasei
n cazul n care ai definit deja o parte din funcionalitatea de care
avei nevoie ntr-o alt superclas, putei s derivai noua clas de
obiecte din clasa deja existent. Dac nu exist o astfel de clas,
114

noua clas va fi automat derivat din clasa de obiecte predefinit


numit Object. n Java, clasa Object este superclas direct sau
indirect pentru orice alt clas de obiecte definit de utilizator.
Alegerea superclasei din care derivai noua clas de obiecte este
foarte important pentru c v ajut s refolosii codul deja
existent. Totui, nu alegei cu uurin superclasa unui obiect
pentru c astfel putei ncrca obiectele cu o funcionalitate inutil,
existent n superclas. Dac nu exist o clas care s v ofere doar
funcionalitatea de care avei nevoie, este preferabil s derivai noua
clas direct din clasa Object i s apelai indirect funcionalitatea pe
care o dorii.
Pasul 4: Stabilirea interfeelor pe care le respect clasa
Stabilirea acestor interfee are dublu scop. n primul rnd ele
instruiesc compilatorul s verifice dac noua clas respect cu
adevrat toate interfeele pe care le-a declarat, cu alte cuvinte
definete toate metodele declarate n aceste interfee. A doua
finalitate este aceea de a permite compilatorului s foloseasc
instanele noii clase oriunde aplicaia declar c este nevoie de un
obiect care implementeaz interfeele declarate.
O clas poate s implementeze mai multe interfee sau niciuna.
Pasul 5: Stabilirea modificatorilor clasei
n unele cazuri trebuie s oferim compilatorului informaii
suplimentare relative la modul n care vom folosi clasa nou creat
pentru ca acesta s poat executa verificri suplimentare asupra
descrierii clasei. n acest scop, putem defini o clas ca fiind
abstract, final sau public folosindu-ne de o serie de cuvinte
rezervate numite modificatori. Modificatorii pentru tipurile de clase
de mai sus sunt respectiv: abstract, final i public.
n cazul n care declarm o clas de obiecte ca fiind abstract,
compilatorul va interzice instanierea acestei clase. Dac o clas
este declarat final, compilatorul va avea grij s nu putem deriva
noi subclase din aceast clas. n cazul n care declarm n acelai
timp o clas de obiecte ca fiind abstract i final, eroarea va fi
semnalat nc din timpul compilrii pentru c cei doi modificatori
se exclud.
Pentru ca o clas s poat fi folosit i n exteriorul contextului n
care a fost declarat ea trebuie s fie declarat public. Mai mult
115

despre acest aspect n paragraful referitor la structura programelor.


Pn atunci, s spunem c orice clas de obiecte care va fi
instaniat ca o aplicaie trebuie declarat public.
Pasul 6: Scrierea corpului declaraiei
n sfrit, dup ce toi ceilali pai au fost efectuai, putem trece la
scrierea corpului declaraiei de clas. n principal, aici vom descrie
variabilele clasei mpreun cu metodele care lucreaz cu acestea.
Tot aici putem preciza i gradele de protejare pentru fiecare dintre
elementele declaraiei. Uneori numim variabilele i metodele unei
clase la un loc ca fiind cmpurile clasei. Subcapitolele urmtoare
vor descrie n amnunt corpul unei declaraii.
Stop: Forma general a unei declaraii de clas
Sintaxa exact de declarare a unei clase arat n felul urmtor:
{

abstract

extends

implements

final

public

}*

class

NumeClas

NumeSuperclas ]
NumeInterfa [ , NumeInterfa ]* ]

{ [ CmpClas ]* }

6.2 Variabilele unei clase


n interiorul claselor se pot declara variabile. Aceste variabile sunt
specifice clasei respective. Fiecare dintre ele trebuie s aib un tip,
un nume i poate avea iniializatori. n afar de aceste elemente, pe
care le-am prezentat deja n seciunea n care am prezentat
variabilele, variabilele definite n interiorul unei clase pot avea
definii o serie de modificatori care altereaz comportarea variabilei
n interiorul clasei, i o specificaie de protecie care definete cine
are dreptul s acceseze variabila respectiv.
6.2.1 Modificatori
Modificatorii sunt cuvinte rezervate Java care precizeaz sensul unei
declaraii. Iat lista acestora:
static
final
transient
volatile

116

Dintre acetia, transient nu este utilizat n versiunea curent a


limbajului Java. Pe viitor va fi folosit pentru a specifica variabile
care nu conin informaii care trebuie s rmn persistente la
terminarea programului.
Modificatorul volatile specific faptul c variabila respectiv poate fi
modificat asincron cu rularea aplicaiei. n aceste cazuri,
compilatorul trebuie s-i ia msuri suplimentare n cazul generrii
i optimizrii codului care se adreseaz acestei variabile.
Modificatorul final este folosit pentru a specifica o variabil a crei
valoare nu poate fi modificat. Variabila respectiv trebuie s
primeasc o valoare de iniializare chiar n momentul declaraiei.
Altfel, ea nu va mai putea fi iniializat n viitor. Orice ncercare
ulterioar de a seta valori la aceast variabil va fi semnalat ca
eroare de compilare.
Modificatorul static este folosit pentru a specifica faptul c variabila
are o singur valoare comun tuturor instanelor clasei n care este
declarat. Modificarea valorii acestei variabile din interiorul unui
obiect face ca modificarea s fie vizibil din celelalte obiecte.
Variabilele statice sunt iniializate la ncrcarea codului specific
unei clase i exist chiar i dac nu exist nici o instan a clasei
respective. Din aceast cauz, ele pot fi folosite de metodele
statice.
6.2.2 Protecie
n Java exist patru grade de protecie pentru o variabil
aparinnd unei clase:

privat
protejat
public
prietenoas

O variabil public este accesibil oriunde este accesibil numele


clasei. Cuvntul rezervat este public.
O variabil protejat este accesibil n orice clas din pachetul
creia i aparine clasa n care este declarat. n acelai timp,
variabila este accesibil n toate subclasele clasei date, chiar dac
ele aparin altor pachete. Cuvntul rezervat este protected.

117

O variabil privat este accesibil doar n interiorul clasei n care a


fost declarat. Cuvntul rezervat este private.
O variabil care nu are nici o declaraie relativ la gradul de
protecie este automat o variabil prietenoas. O variabil
prietenoas este accesibil n pachetul din care face parte clasa n
interiorul creia a fost declarat, la fel ca i o variabil protejat.
Dar, spre deosebire de variabilele protejate, o variabil prietenoas
nu este accesibil n subclasele clasei date dac aceste sunt
declarate ca aparinnd unui alt pachet. Nu exist un cuvnt
rezervat pentru specificarea explicit a variabilelor prietenoase.
O variabil nu poate avea declarate mai multe grade de protecie n
acelai timp. O astfel de declaraie este semnalat ca eroare de
compilare.
6.2.3 Accesarea unei variabile
Accesarea unei variabile declarate n interiorul unei clasei se face
folosindu-ne de o expresie de forma:
ReferinInstan.NumeVariabil
Referina ctre o instan trebuie s fie referin ctre clasa care
conine variabila. Referina poate fi valoarea unei expresii mai
complicate, ca de exemplu un element dintr-un tablou de referine.
n cazul n care avem o variabil static, aceasta poate fi accesat i
fr s deinem o referin ctre o instan a clasei. Sintaxa este, n
acest caz:
NumeClas.NumeVariabil
6.2.4 Vizibilitate
O variabil poate fi ascuns de declaraia unei alte variabile cu
acelai nume. De exemplu, dac ntr-o clas avem declarat o
variabil cu numeleunu i ntr-o subclas a acesteia avem declarat
o variabil cu acelai nume, atunci variabila din superclas este
ascuns de cea din clas. Totui, variabila din superclas exist
nc i poate fi accesat n mod explicit. Expresia de referire este, n
acest caz:
NumeSuperClas.NumeVariabil

118

sau
super.NumeVariabil

n cazul n care superclasa este imediat.


La fel, o variabil a unei clase poate fi ascuns de o declaraie de
variabil dintr-un bloc de instruciuni. Orice referin la ea va trebui
fcut n mod explicit. Expresia de referire este, n acest caz:
this.NumeVariabil

6.2.5 Variabile predefinite: this i super


n interiorul fiecrei metode non-statice dintr-o clas exist
predefinite dou variabile cu semnificaie special. Cele dou
variabile sunt de tip referin i au aceeai valoare i anume o
referin ctre obiectul curent. Diferena dintre ele este tipul.
Prima dintre acestea este variabila this care are tipul referin ctre
clasa n interiorul creia apare metoda. A doua este variabila super al
crei tip este o referin ctre superclasa imediat a clasei n care
apare metoda. n interiorul obiectelor din clasa Object nu se poate
folosi referina superpentru c nu exist nici o superclas a clasei de
obiecte Object.
n cazul n care super este folosit la apelul unui constructor sau al
unei metode, ea acioneaz ca un cast ctre superclasa imediat.

6.3 Metodele unei clase


Fiecare clas i poate defini propriile sale metode pe lng metodele
pe care le motenete de la superclasa sa. Aceste metode definesc
operaiile care pot fi executate cu obiectul respectiv. n cazul n care
una dintre metodele motenite nu are o implementare
corespunztoare n superclas, clasa i poate redefini metoda dup
cum dorete.
n plus, o clas i poate defini metode de construcie a obiectelor i
metode de eliberare a acestora. Metodele de construcie sunt apelate
ori de cte ori este alocat un nou obiect din clasa respectiv. Putem
declara mai multe metode de construcie, ele diferind prin
parametrii din care trebuie construit obiectul.

119

Metodele de eliberare a obiectului sunt cele care elibereaz resursele


ocupate de obiect n momentul n care acesta este distrus de ctre
mecanismul automat de colectare de gunoaie. Fiecare clas are o
singur metod de eliberare, numit i finalizator. Apelarea acestei
metode se face de ctre sistem i nu exist nici o cale de control al
momentului n care se produce acest apel.
6.3.1 Declararea metodelor
Pentru a declara o metod, este necesar s declarm numele
acesteia, tipul de valoare pe care o ntoarce, parametrii metodei
precum i un bloc n care s descriem instruciunile care trebuiesc
executate atunci cnd metoda este apelat. n plus, orice metod
are un numr de modificatori care descriu proprietile metodei i
modul de lucru al acesteia.
Declararea precum i implementarea metodelor se face ntotdeauna
n interiorul declaraiei de clas. Nu exist nici o cale prin care s
putem scrie o parte dintre metodele unei clase ntr-un fiier separat
care s fac referin apoi la declaraia clasei.
n form general, declaraia unei metode arat n felul urmtor:
[Modificator]* TipRezultat Declaraie [ClauzeThrows]*CorpulMetodei
Modificatorii precum i clauzele

throws

pot s lipseasc.

6.3.1.1 Numele i parametrii metodelor


Recunoaterea unei anumite metode se face dup numele i tipul
parametrilor si. Pot exista metode cu acelai nume dar avnd
parametri diferii. Acest fenomen poart numele
de suprancrcarea numelui unei metode.
Numele metodei este un identificator Java. Avem toat libertatea n
a alege numele pe care l dorim pentru metodele noastre, dar n
general este preferabil s alegem nume care sugereaz utilizarea
metodei.
Numele unei metode ncepe de obicei cu liter mic. Dac acesta
este format din mai multe cuvinte, litera de nceput a fiecrui
cuvnt va fi majuscul. n acest mod numele unei metode este
foarte uor de citit i de depistat n surs.

120

Parametrii metodei sunt n realitate nite variabile care sunt


iniializate n momentul apelului cu valori care controleaz modul
ulterior de execuie. Aceste variabile exist pe toat perioada
execuiei metodei. Se pot scrie metode care s nu aib nici un
parametru.
Fiind o variabil, fiecare parametru are un tip i un nume. Numele
trebuie s fie un identificator Java. Dei avem libertatea s alegem
orice nume dorim, din nou este preferabil s alegem nume care s
sugereze scopul la care va fi utilizat parametrul respectiv.
Tipul unui parametru este oricare dintre tipurile valide n Java.
Acestea poate fi fie un tip primitiv, fie un tip referin ctre obiect,
interfa sau tablou.
n momentul apelului unei metode, compilatorul ncearc s
gseasc o metod n interiorul clasei care s aib acelai nume cu
cel apelat i acelai numr de parametri ca i apelul. Mai mult,
tipurile parametrilor de apel trebuie s corespund cu tipurile
parametrilor declarai ai metodei gsite sau s poat fi convertii la
acetia.
Dac o astfel de metod este gsit n declaraia clasei sau n
superclasele acesteia, parametrii de apel sunt convertii ctre
tipurile declarate i se genereaz apelul ctre metoda respectiv.
Este o eroare de compilare s declarm dou metode cu acelai
nume, acelai numr de parametri i acelai tip pentru parametrii
corespunztori. ntr-o asemenea situaie, compilatorul n-ar mai ti
care metod trebuie apelat la un moment dat.
De asemenea, este o eroare de compilare s existe dou metode care
se potrivesc la acelai apel. Acest lucru se ntmpl cnd nici una
dintre metodele existente nu se potrivete exact i cnd exist dou
metode cu acelai nume i acelai numr de parametri i, n plus,
parametrii de apel se pot converti ctre parametrii declarai ai
ambelor metode.
Rezolvarea unei astfel de probleme se face prin conversia explicit
(cast) de ctre programator a valorilor de apel spre tipurile exacte
ale parametrilor metodei pe care dorim s o apelm n realitate.
n fine, forma general de declaraie a numelui i parametrilor unei
metode este:
121

NumeMetod( [TipParametru NumeParametru]


[,TipParametru NumeParametru]* )
6.3.1.2 Modificatori de metode
Modificatorii sunt cuvinte cheie ale limbajului Java care specific
proprieti suplimentare pentru o metod. Iat lista complet a
acestora n cazul metodelor:

- pentru metodele statice


abstract - pentru metodele abstracte
final - pentru metodele finale
native - pentru metodele native
synchronized - pentru metodele sincronizate
static

6.3.1.2.1 Metode statice

n mod normal, o metod a unei clase se poate apela numai printr-o


instan a clasei respective sau printr-o instan a unei subclase.
Acest lucru se datoreaz faptului c metoda face apel la o serie de
variabile ale clasei care sunt memorate n interiorul instanei i care
au valori diferite n instane diferite. Astfel de metode se
numesc metode ale instanelor clasei.
Dup cum tim deja, exist i un alt tip de variabile, i anume
variabilele de clas sau variabilele statice care sunt comune tuturor
instanelor clasei respective i exist pe toat perioada de timp n
care clasa este ncrcat n memorie. Aceste variabile pot fi accesate
fr s avem nevoie de o instan a clasei respective.
n mod similar exist i metode statice. Aceste metode nu au nevoie
de o instan a clasei sau a unei subclase pentru a putea fi apelate
pentru c ele nu au voie s foloseasc variabile care sunt memorate
n interiorul instanelor. n schimb, aceste metode pot s foloseasc
variabilele statice declarate n interiorul clasei.
Orice metod static este implicit i final.
6.3.1.2.2 Metode abstracte

Metodele abstracte sunt metode care nu au corp de implementare.


Ele sunt declarate numai pentru a fora subclasele care vor s aib
instane s implementeze metodele respective.

122

Metodele abstracte trebuie declarate numai n interiorul claselor


care au fost declarate abstracte. Altfel compilatorul va semnala o
eroare de compilare. Orice subclas a claselor abstracte care nu este
declarat abstract trebuie s ofere o implementare a acestor
metode, altfel va fi generat o eroare de compilare.
Prin acest mecanism ne asigurm c toate instanele care pot fi
convertite ctre clasa care conine definiia unei metode abstracte
au implementat metoda respectiv dar, n acelai timp, nu este
nevoie s implementm n nici un fel metoda chiar n clasa care o
declar pentru c nu tim pe moment cum va fi implementat.
O metod static nu poate fi declarat i abstract pentru c o
metod static este implicit final i nu poate fi rescris.
6.3.1.2.3 Metode finale

O metod final este o metod care nu poate fi rescris n subclasele


clasei n care a fost declarat. O metod este rescris ntr-o
subclas dac aceasta implementeaz o metod cu acelai nume i
acelai numr i tip de parametri ca i metoda din superclas.
Declararea metodelor finale este util n primul rnd compilatorului
care poate genera metodele respective direct n codul rezultat fiind
sigur c metoda nu va avea nici o alt implementare n subclase.
6.3.1.2.4 Metode native

Metodele native sunt metode care sunt implementate pe o cale


specific unei anumite platforme. De obicei aceste metode sunt
implementate n C sau n limbaj de asamblare. Metoda propriu-zis
nu poate avea corp de implementare pentru c implementarea nu
este fcut n Java.
n rest, metodele native sunt exact ca orice alt metod Java. Ele
pot fi motenite, pot fi statice sau nu, pot fi finale sau nu, pot s
rescrie o metod din superclas i pot fi la rndul lor rescrise n
subclase.
6.3.1.2.5 Metode sincronizate

O metod sincronizat este o metod care conine cod critic pentru


un anumit obiect sau clas i nu poate fi rulat n paralel cu nici o
alt metod critic sau cu o instruciune synchronized referitoare la
acelai obiect sau clas.
123

nainte de execuia metodei, obiectul sau clasa respectiv sunt


blocate. La terminarea metodei, acestea sunt deblocate.
Dac metoda este static atunci este blocat o ntreag clas, clasa
din care face parte metoda. Altfel, este blocat doar instana n
contextul creia este apelat metoda.
6.3.1.3 Protejarea metodelor
Accesul la metodele unei clase este protejat n acelai fel ca i
accesul la variabilele clasei. n Java exist patru grade de protecie
pentru o metod aparinnd unei clase:

privat
protejat
public
prietenoas

O metod declarat public este accesibil oriunde este accesibil


numele clasei. Cuvntul rezervat este public.
O metod declarat protejat este accesibil n orice clas din
pachetul creia i aparine clasa n care este declarat. n acelai
timp, metoda este accesibil n toate subclasele clasei date, chiar
dac ele aparin altor pachete. Cuvntul rezervat este protected.
O metod declarat privat este accesibil doar n interiorul clasei
n care a fost declarat. Cuvntul rezervat este private.
O metod care nu are nici o declaraie relativ la gradul de protecie
este automat o metod prietenoas. O metod prietenoas este
accesibil n pachetul din care face parte clasa n interiorul creia a
fost declarat la fel ca i o metod protejat. Dar, spre deosebire de
metodele protejate, o metod prietenoas nu este accesibil n
subclasele clasei date dac aceste sunt declarate ca aparinnd
unui alt pachet. Nu exist un cuvnt rezervat pentru specificarea
explicit a metodelor prietenoase.
O metod nu poate avea declarate mai multe grade de protecie n
acelai timp. O astfel de declaraie este semnalat ca eroare de
compilare.
6.3.2 Clauze throws

124

Dac o metod poate arunca o excepie, adic s apeleze


instruciuneathrow, ea trebuie s declare tipul acestor excepii ntr-o
clauz throws. Sintaxa acesteia este:
throws

NumeTip [, NumeTip]*

Numele de tipuri specificate n clauza throws trebuie s fie accesibile


i s fie asignabile la tipul de clas Throwable. Dac o metod conine
o clauzthrows, este o eroare de compilare ca metoda s arunce un
obiect care nu este asignabil la compilare la tipurile de
clase Error, RunTimeException sau la tipurile de clase specificate n
clauza throws.
Dac o metod nu are o clauz throws, este o eroare de compilare ca
aceasta s poat arunca o excepie normal din interiorul corpului
ei.
6.3.3 Apelul metodelor
Pentru a apela o metod a unei clase este necesar s dispunem de o
cale de acces la metoda respectiv. n plus, trebuie s dispunem de
drepturile necesare apelului metodei.
Sintaxa efectiv de acces este urmtoarea:
CaleDeAcces.Metod( Parametri )
n cazul n care metoda este static, pentru a specifica o cale de
acces este suficient s furnizm numele clasei n care a fost
declarat metoda. Accesul la numele clasei se poate obine fie
importnd clasa sau ntreg pachetul din care face parte clasa fie
specificnd n clar numele clasei i drumul de acces ctre aceasta.
De exemplu, pentru a accesa metoda random definit static n
clasa Mathaparinnd pachetului java.lang putem scrie:
double aleator = Math.random();

sau, alternativ:
double aleator = java.lang.Math.random();

n cazul claselor definite n pachetul java.lang nu este necesar nici


un import pentru c acestea sunt implicit importate de ctre
compilator.
125

Cea de-a doua cale de acces este existena unei instane a clasei
respective. Prin aceast instan putem accesa metodele care nu
sunt declarate statice, numite uneori i metode ale instanelor
clasei. Aceste metode au nevoie de o instan a clasei pentru a
putea lucra, pentru c folosesc variabile non-statice ale clasei sau
apeleaz alte metode non-statice. Metodele primesc acest obiect ca
pe un parametru ascuns.
De exemplu, avnd o instan a clasei Object sau a unei subclase a
acesteia, putem obine o reprezentare sub form de ir de caractere
prin:
Object obiect = new Object();
String sir = obiect.toString();

n cazul n care apelm o metod a clasei din care face parte i


metoda apelant putem s renunm la calea de acces n cazul
metodelor statice, scriind doar numele metodei i parametrii. Pentru
metodele specifice instanelor, putem renuna la calea de acces, dar
n acest caz metoda acceseaz aceeai instan ca i metoda
apelant. n cazul n care metoda apelant este static, specificarea
unei instane este obligatorie n cazul metodelor de instan.
Parametrii de apel servesc mpreun cu numele la identificarea
metodei pe care dorim s o apelm. nainte de a fi transmii, acetia
sunt convertii ctre tipurile declarate de parametri ai metodei,
dup cum este descris mai sus.
Specificarea parametrilor de apel se face separndu-i prin virgul.
Dup ultimul parametru nu se mai pune virgul. Dac metoda nu
are nici un parametru, parantezele rotunde sunt n continuare
necesare. Exemple de apel de metode cu parametri:
String numar = String.valueOf( 12 );
// 12 -> String
double valoare = Math.abs( 12.54 );
// valoare absolut
String prima = numar.substring( 0, 1 );
// prima litera ^

6.3.4 Valoarea de retur a unei metode


O metod trebuie s-i declare tipul valorii pe care o ntoarce. n
cazul n care metoda dorete s specifice explicit c nu ntoarce nici
o valoare, ea trebuie s declare ca tip de retur tipul void ca n
exemplul:
126

void a() { }

n caz general, o metod ntoarce o valoare primitiv sau un tip


referin. Putem declara acest tip ca n:
Thread cautaFirulCurent() { }
long abs( int valoare ) { }

Pentru a returna o valoare ca rezultat al execuiei unei metode,


trebuie s folosim instruciunea return, aa cum s-a artat n
seciunea dedicat instruciunilor. Instruciunea return trebuie s
conin o expresie a crei valoare s poat fi convertit la tipul
declarat al valorii de retur a metodei.
De exemplu:
long abs( int valoare ) {
return Math.abs( valoare );
}

Metoda static abs din clasa Math care primete un parametru ntreg
returneaz tot un ntreg. n exemplul nostru,
instruciunea return este corect pentru c exist o cale de conversie
de la ntreg la ntreg lung, conversie care este apelat automat de
compilator nainte de ieirea din metod.
n schimb, n exemplul urmtor:
int abs( long valoare ) {
return Math.abs( valoare );
}

compilatorul va genera o eroare de compilare pentru c metoda


static absdin clasa Math care primete ca parametru un ntreg lung
ntoarce tot un ntreg lung, iar un ntreg lung nu poate fi convertit
sigur la un ntreg normal pentru c exist riscul deteriorrii valorii,
la fel ca la atribuire.
Rezolvarea trebuie s conin un cast explicit:
int abs( long valoare ) {
return ( int )Math.abs( valoare );
}

n cazul n care o metod este declarat void, putem s ne ntoarcem


din ea folosind instruciunea return fr nici o expresie. De exemplu:
void metoda() {

127

if( )
return;

Specificarea unei expresii n acest caz duce la o eroare de compilare.


La fel i n cazul n care folosim instruciunea return fr nici o
expresie n interiorul unei metode care nu este declarat void.
6.3.5 Vizibilitate
O metod este vizibil dac este declarat n clasa prin care este
apelat sau ntr-una din superclasele acesteia. De exemplu, dac
avem urmtoarea declaraie:
class A {

void a() { }
}
class B extends A {
void b() {
a();
c();

}
void c() { .. }

Apelul metodei a n interiorul metodei b din clasa B este permis


pentru c metoda a este declarat n interiorul clasei A care este
superclas pentru clasa B. Apelul metodei c n aceeai metod b este
permis pentru c metodac este declarat n aceeai clas ca i
metoda a.
Uneori, o subclas rescrie o metod dintr-o superclas a sa. n acest
caz, apelul metodei respective n interiorul subclasei duce automat
la apelul metodei din subclas. Dac totui dorim s apelm metoda
aa cum a fost ea definit n superclas, putem prefixa apelul cu
numele superclasei. De exemplu:
class A {

void a() { }
}
class B extends A {
void a() { .. }
void c() {
a();// metoda a din clasa B
A.a();// metoda a din clasa A

128

Desigur, pentru a "vedea" o metod i a o putea apela, este nevoie


s avem drepturile necesare.

6.4 Iniializatori statici


La ncrcarea unei clase sunt automat iniializate toate variabilele
statice declarate n interiorul clasei. n plus, sunt apelai toi
iniializatorii statici ai clasei.
Un iniializator static are urmtoarea sintax:
static

BlocDeInstruciuni

Blocul de instruciuni este executat automat la ncrcarea clasei. De


exemplu, putem defini un iniializator static n felul urmtor:
class A {
static double a;
static int b;
static {
a = Math.random();
// numr dublu ntre 0.0 i 1.0
b = ( int )( a * 500 );
// numr ntreg ntre 0 i 500
}

Declaraiile de variabile statice i iniializatorii statici sunt executate


n ordinea n care apar n clas. De exemplu, dac avem urmtoarea
declaraie de clas:
class A {
static int i = 11;
static {
i += 100;
i %= 55;
}
static int j = i + 1;
}

valoarea final a lui i va fi


fi 2.

( ( 11 + 100 ) % 55 ) iar valoarea lui j va

6.5 Constructori i finalizatori


6.5.1 constructori

129

La crearea unei noi instane a unei clase sistemul aloc automat


memoria necesar instanei i o iniializeaz cu valorile iniiale
specificate sau implicite. Dac dorim s facem iniializri
suplimentare n interiorul acestei memorii sau n alt parte putem
descrie metode speciale numiteconstructori ai clasei.
Putem avea mai muli constructori pentru aceeai clas, acetia
diferind doar prin parametrii pe care i primesc. Numele tuturor
constructorilor este acelai i este identic cu numele clasei.
Declaraia unui constructor este asemntoare cu declaraia unei
metode oarecare, cu diferena c nu putem specifica o valoare de
retur i nu putem specifica nici un fel de modificatori. Dac dorim
s returnm dintr-un constructor, trebuie s folosim
instruciunea return fr nici o expresie. Putem ns s specificm
gradul de protecie al unui constructor ca fiind public, privat,
protejat sau prietenos.
Constructorii pot avea clauze

throws.

Dac o clas nu are constructori, compilatorul va crea automat


unconstructor implicit care nu ia nici un parametru i care
iniializeaz toate variabilele clasei i apeleaz constructorul
superclasei fr argumente prinsuper(). Dac superclasa nu are un
constructor care ia zero argumente, se va genera o eroare de
compilare.
Dac o clas are cel puin un constructor, constructorul implicit nu
mai este creat de ctre compilator.
Cnd construim corpul unui constructor avem posibilitatea de a
apela, pe prima linie a blocului de instruciuni care reprezint
corpul constructorului, un constructor explicit. Constructorul explicit
poate avea dou forme:
this(

[Parametri] );

super(

[Parametri] );

Cu aceast sintax apelm unul dintre constructorii superclasei sau


unul dintre ceilali constructori din aceeai clas. Aceste linii nu pot
aprea dect pe prima poziie n corpul constructorului. Dac nu
apar acolo, compilatorul consider implicit c prima instruciune
din corpul constructorului este:
130

super();

i n acest caz se va genera o eroare de compilare dac nu exist un


constructor n superclas care s lucreze fr nici un parametru.
Dup apelul explicit al unui constructor din superclas cu
sintaxa super( ) este executat n mod implicit iniializarea tuturor
variabilelor de instan (non-statice) care au iniializatori explicii.
Dup apelul unui constructor din aceeai clas cu sintaxa this( )
nu exist nici o alt aciune implicit, deci nu vor fi iniializate nici
un fel de variabile. Aceasta datorit faptului c iniializarea s-a
produs deja n constructorul apelat.
Iat i un exemplu:
class A extends B {
String valoare;
A( String val ) {
// aici exist apel implicit
// al lui super(), adic B()
valoare = val;
}
A( int val ) {
this( String.valueOf( val ) );// alt constructor
}
} ^

6.5.2 Finalizatori
n Java nu este nevoie s apelm n mod explicit distrugerea unei
instane atunci cnd nu mai este nevoie de ea. Sistemul ofer un
mecanism de colectare a gunoaielor care recunoate situaia n care
o instan de obiect sau un tablou nu mai sunt referite de nimeni i
le distruge n mod automat.
Acest mecanism de colectare a gunoaielor ruleaz pe un fir de
execuie separat, de prioritate mic. Nu avem nici o posibilitate s
aflm exact care este momentul n care va fi distrus o instan.
Totui, putem specifica o funcie care s fie apelat automat n
momentul n care colectorul de gunoaie ncearc s distrug
obiectul.
Aceast funcie are nume, numr de parametri i tip de valoare de
retur fixe:
void

finalize()

131

Dup apelul metodei de finalizare (numit i finalizator), instana nu


este nc distrus pn la o nou verificare din partea colectorului
de gunoaie. Aceast comportare este necesar pentru c instana
poate fi revitalizat prin crearea unei referine ctre ea n interiorul
finalizatorului.
Totui, finalizatorul nu este apelat dect o singur dat. Dac
obiectul revitalizat redevine candidat la colectorul de gunoaie,
acesta este distrus fr a i se mai apela finalizatorul. Cu alte
cuvinte, un obiect nu poate fi revitalizat dect o singur dat.
Dac n timpul finalizrii apare o excepie, ea este ignorat i
finalizatorul nu va mai fi apelat din nou.
6.5.3 Crearea instanelor
O instan este creat folosind o expresie de alocare care folosete
cuvntul rezervat new. Iat care sunt paii care sunt executai la
apelul acestei expresii:

Se creeaz o nou instan de tipul specificat. Toate variabilele


instanei sunt iniializate pe valorile lor implicite.
Se apeleaz constructorul corespunztor n funcie de
parametrii care sunt transmii n expresia de alocare. Dac
instana este creat prin apelul metodei newInstance, se apeleaz
constructorul care nu ia nici un argument.
Dup creare, expresia de alocare returneaz o referin ctre
instana nou creat.

Exemple de creare:
A o1 = new A();
B o2 = new B();
class C extends B {
String valoare;
C( String val ) {
// aici exist apel implicit
// al lui super(), adic B()
valoare = val;
}
C( int val ) {
this( String.valueOf( val ) );
}
}
C o3 = new C( "Vasile" );
C o4 = new C( 13 );

132

O alt cale de creare a unui obiect este apelul


metodei newInstancedeclarate n clasa Class. Iat paii de creare n
acest caz:

Se creeaz o nou instan de acelai tip cu tipul clasei pentru


care a fost apelat metoda newInstance. Toate variabilele
instanei sunt iniializate pe valorile lor implicite.
Este apelat constructorul obiectului care nu ia nici un
argument.
Dup creare referina ctre obiectul nou creat este returnat
ca

valoare a metodei newInstance. Tipul acestei referine va


fi Object n timpul compilrii i tipul clasei reale n timpul
execuiei.

6.6 Derivarea claselor


O clas poate fi derivat dintr-alta prin folosirea n declaraia clasei
derivate a clauzei extends. Clasa din care se deriv noua clas
se numete superclas imediat a clasei derivate. Toate clasele care
sunt superclase ale superclasei imediate ale unei clase
sunt superclase i pentru clasa dat. Clasa nou derivat se
numete subclas a clasei din care este derivat.
Sintaxa general este:
class

SubClas

extends

SuperClas

O clas poate fi derivat dintr-o singur alt clas, cu alte cuvinte o


clas poate avea o singur superclas imediat.
Clasa derivat motenete toate variabilele i metodele superclasei
sale. Totui, ea nu poate accesa dect acele variabile i metode care
nu sunt declarate private.
Putem rescrie o metod a superclasei declarnd o metod n noua
clas avnd acelai nume i aceiai parametri. La fel, putem declara
o variabil care are acelai nume cu o variabil din superclas. n
acest caz, noul nume ascunde vechea variabil, substituindu-i-se.
Putem n continuare s ne referim la variabila ascuns din
superclas specificnd numele superclasei sau folosindu-ne de
variabila super.
Exemplu:
133

class A {
int a = 1;
void unu() {
System.out.println( a );
}
}
class B extends A {
double a = Math.PI;
void unu() {
System.out.println( a );
}
void doi() {
System.out.println( A.a );
}
void trei() {
unu();
super.unu();
}
}

Dac apelm metoda unu din clasa A, aceasta va afia la consol


numrul 1. Acest apel se va face cu instruciunea:
( new A() ).unu();

Dac apelm metoda unu din clasa B, aceasta va afia la consol


numrulPI. Apelul l putem face de exemplu cu instruciunea:
B obiect = new B();
obiect.unu();

Observai c n metoda unu din clasa B, variabila referit este


variabila adin clasa B. Variabila a din clasa A este ascuns. Putem
ns s o referim prin sintaxa A.a ca n metoda doi din clasa B.
n interiorul clasei B, apelul metodei unu fr nici o alt specificaie
duce automat la apelul metodei unu definite n interiorul clasei B.
Metoda unu din clasa B rescrie metoda unu din clasa A. Vechea
metod este accesibil pentru a o referi n mod explicit ca n
metoda trei din clasa B. Apelul acestei metode va afia mai nti
numrul PI i apoi numrul 1.
Dac avem declarat o variabil de tip referin ctre o instan a
clasei A, aceast variabil poate s conin n timpul execuiei i o
referin ctre o instan a clasei B. Invers, afirmaia nu este
valabil.
n clipa n care apelm metoda unu pentru o variabil referin ctre
clasaA, sistemul va apela metoda unu a clasei A sau B n funcie de
adevratul tip al referinei din timpul execuiei. Cu alte cuvinte,
urmtoarea secven de instruciuni:
134

A tablou[] = new A[2];


tablou[0] = new A();
tablou[1] = new B();
for( int i = 0; i < 2; i++ ) {
tablou[i].unu();
}

va afia dou numere diferite, mai nti 1 i apoi PI. Aceasta din
cauz c cel de-al doilea element din tablou este, n timpul
execuiei, de tip referin la o instan a clasei B chiar dac la
compilare este de tipul referin la o instan a clasei A.
Acest mecanism se numete legare trzie, i nseamn c metoda
care va fi efectiv apelat este stabilit doar n timpul execuiei i nu
la compilare.
Dac nu declarm nici o superclas n definiia unei clase, atunci se
consider automat c noua clas deriv direct din clasa Object,
motenind toate metodele i variabilele acesteia.

6.7 Interfee
O interfa este n esen o declaraie de tip ce const dintr-un set
de metode i constante pentru care nu s-a specificat nici o
implementare. Programele Java folosesc interfeele pentru a suplini
lipsa motenirii multiple, adic a claselor de obiecte care deriv din
dou sau mai multe alte clase.
Sintaxa de declaraie a unei interfee este urmtoarea:
Modificatori

interface

NumeInterf [

extends

[Interfa][, Interfa]*]

Corp
Modificatorii unei interfee pot fi doar cuvintele
rezervate public i abstract. O interfa care este public poate fi
accesat i de ctre alte pachete dect cel care o definete. n plus,
fiecare interfa este n mod implicit abstract.
Modificatorul abstract este permis dar nu obligatoriu.
Numele interfeelor trebuie s fie identificatori Java. Conveniile de
numire a interfeelor le urmeaz n general pe cele de numire a
claselor de obiecte.
Interfeele, la fel ca i clasele de obiecte, pot avea subinterfee.
Subinterfeele motenesc toate constantele i declaraiile de metode
135

ale interfeei din care deriv i pot defini n plus noi elemente.
Pentru a defini o subinterfa, folosim o clauz extends. Aceste clauze
specific superinterfaa unei interfee. O interfa poate avea mai
multe superinterfee care se declar separate prin virgul dup
cuvntul rezervatextends. Circularitatea definiiei subinterfeelor nu
este permis.
n cazul interfeelor nu exist o rdcin comun a arborelui de
derivare aa cum exist pentru arborele de clase, clasa Object.
n corpul unei declaraii de interfa pot s apar declaraii de
variabile i declaraii de metode. Variabilele sunt implicit statice i
finale. Din cauza faptului c variabilele sunt finale, este obligatoriu
s fie specificat o valoare iniial pentru aceste variabile. n plus,
aceast valoare iniial trebuie s fie constant (s nu depind de
alte variabile).
Dac interfaa este declarat public, toate variabilele din corpul
su sunt implicit declarate publice.
n ceea ce privete metodele declarate n interiorul corpului unei
interfee, acestea sunt implicit declarate abstracte. n plus, dac
interfaa este declarat public, metodele din interior sunt implicit
declarate publice.
Iat un exemplu de declaraii de interfee:
public interface ObiectSpatial {
final int CUB = 0;
final int SFERA = 1;
double greutate();
double volum();
double raza();
int tip();
}
public interface ObiectSpatioTemporal extends ObiectSpatial {
void centrulDeGreutate( long moment,
double coordonate[] );
long momentInitial();
long momentFinal();
}

Cele dou interfee definesc comportamentul unui obiect spaial


respectiv al unui obiect spaio-temporal. Un obiect spaial are o
greutate, un volum i o raz a sferei minime n care se poate nscrie.
n plus, putem defini tipul unui obiect folosindu-ne de o serie de
valori constante predefinite precum ar fi SFERA sau CUB.

136

Un obiect spaio-temporal este un obiect spaial care are n plus o


poziie pe axa timpului. Pentru un astfel de obiect, n afar de
proprietile deja descrise pentru obiectele spaiale, trebuie s avem
n plus un moment iniial, de apariie, pe axa timpului i un
moment final. Obiectul nostru nu exist n afara acestui interval de
timp. n plus, pentru un astfel de obiect putem afla poziia centrului
su de greutate n fiecare moment aflat n intervalul de existen.
Pentru a putea lucra cu obiecte spaiale i spaio-temporale este
nevoie s definim diverse clase care s implementeze aceste
interfee. Acest lucru se face specificnd clauza implements n
declaraia de clas. O clas poate implementa mai multe interfee.
Dac o clas declar c implementeaz o anumit interfa, ea este
obligatoriu s implementeze toate metodele declarate n interfaa
respectiv.
De exemplu, putem spune c o minge este un obiect spaial de tip
sfer. n plus, mingea are o poziie n funcie de timp i un interval
de existen. Cu alte cuvinte, mingea este chiar un obiect spaiotemporal. Desigur, n afar de proprietile spaio-temporale mingea
mai are i alte proprieti precum culoarea, proprietarul sau preul
de cumprare.
Iat cum ar putea arta definiia clasei de obiecte de tip minge:
import java.awt.Color;
class Minge extends Jucarie implements ObiectSpatioTemporal
int culoare = Color.red;
double pret = 10000.0;
double raza = 0.25;
long nastere;
long moarte;
// metodele din ObiectSpatial
double greutate() {
return raza * 0.5;
}
double raza() {
return raza;
}
double volum() {
return ( 4.0 / 3.0 ) * Math.PI * raza * raza * raza;
}
int tip() {
return SFERA;
}
// metodele din interfaa ObiectSpatioTemporal
boolean centrulDeGreutate( long moment,
double coordonate[] ) {
if( moment < nastere || moment > moarte ) {
return false;
}

137

coordonate[0] = x;
coordonate[1] = y;
coordonate[2] = z;
return true;
}
long momentInitial() {
return nastere;
}
long momentFinal() {
return moarte;
}
int ceCuloare() {
return culoare;
}
double cePret() {
return pret;
}
}

Observai c noua clas Minge implementeaz toate metodele definite


n interfaa ObiectSpatioTemporal i, pentru c aceasta extinde
interfaaObiectSpatial, i metodele definite n cea din urm. n plus,
clasa i definete propriile metode i variabile.
S presupunem n continuare c avem i o alt clas, Rezervor, care
este tot un obiect spaio-temporal, dar de form cubic. Declaraia
acestei clase ar arta ca:
class Rezervor extends Constructii implements ObiectSpatioTemporal {

Desigur, toate metodele din interfeele de mai sus trebuiesc


implementate, plus alte metode specifice.
S mai observm c cele dou obiecte deriv din clase diferite:
Mingea din Jucrii iar Rezervorul din Construcii. Dac am putea
deriva o clas din dou alte clase, am putea
deriva Minge din Jucarie i ObiectSpatioTemporaliar Rezervor din Constructie
i ObiectSpaioTemporal. ntr-o astfel de situaie, nu ar mai fi necesar
ca ObiectSpaioTemporal s fie o interfa, ci ar fi suficient ca acesta s
fie o alt clas.
Din pcate, n Java, o clas nu poate deriva dect dintr-o singur
alt clas, aa c este obligatoriu n astfel de situaii s folosim
interfeele. DacObiectSpaioTemporal ar fi putut fi o clas, am fi avut
avantajul c puteam implementa acolo metodele cu funcionare
identic din cele dou clase discutate, acestea fiind automat

138

motenite fr a mai fi nevoie de definirea lor de dou ori n fiecare


clas n parte.
Putem crea n continuare metode care s lucreze cu obiecte spaiotemporale, de exemplu o metod care s afle distana unui corp
spaio-temporal fa de un punct dat la momentul su iniial. O
astfel de metod se poate scrie o singur dat, i poate lucra cu
toate clasele care implementeaz interfaa noastr. De exemplu:

double distanta( double punct[], ObiectSpatioTemporal obiect ) {


double coordonate[] = new double[3];
obiect.centrulDeGreutate( obiect.momentInitial(),
coordonate );
double x = coordonate[0] - punct[0];
double y = coordonate[1] - punct[1];
double z = coordonate[2] - punct[2];
return Math.sqrt( x * x + y * y + z * z );
}

Putem apela metoda att cu un obiect din clasa Minge ct i cu un


obiect din clasa Rezervor. Compilatorul nu se va plnge pentru c el
tie c ambele clase implementeaz interfaa ObiectSpaioTemporal, aa
c metodele apelate n interiorul calculului distanei
(momentInitial i centruDeGreutate) sunt cu siguran implementate
n ambele clase. Deci, putem scrie:
Minge minge;
Rezervor rezervor;
double punct[] = { 10.0, 45.0, 23.0 };
distana( punct, minge );
distana( punct, rezervor );

Desigur, n mod normal ar fi trebuit s proiectm i un constructor


sau mai muli care s iniializeze obiectele noastre cu valori
rezonabile. Aceti constructori ar fi stat cu siguran n definiia
claselor i nu n definiia interfeelor. Nu avem aici nici o cale de a
fora definirea unui anumit constructor cu ajutorul interfeei.

139

Capitolul VII
Modele de programare
Un nou limbaj de programare nu are anse s se impun fr s
ofere, pe lng sintaxa propriu-zis un set de biblioteci sau o
ierarhie de clase coerent i ct mai general. Atunci cnd limbajul
C a fost prezentat pentru prima dat, mpreun cu el a fost
prezentat i biblioteca standard de intrare ieire. Primul program C
pe care l-am nvat coninea deja apelul:
printf( "hello, world!" );

Limbajul Java nu numai c nu face excepie de la aceast regul


dar chiar o extinde cu ambiia de a oferi totul. Interfaa Java pentru
programarea aplicaiilor (API) ofer o ierarhie de clase care include
funcionalitate pentru lucrul cu mai multe fire de execuie, lucrul n
reea, crearea interfeelor utilizator complexe, grafic, etc.
Acest capitol va prezenta o parte a acestei ierarhii mpreun cu
cteva tehnici uzuale de scriere a aplicaiilor Java.
Exist mai multe moduri de a aborda scrierea unui program. Unul
dintre acestea este scrierea unui program care are iniiativa pe toat
perioada rulrii. Acest tip de programe execut n permanen o
secven de cod, fie i numai o bucl de ateptare a crei condiie
depinde de elemente exterioare precum ar fi o apsare de tast sau
sosirea unui pachet de date din reea.
Alternativa este aceea de a scrie programe care intr n execuie
doar atunci cnd sunt generate anumite evenimente n sistem. n
clipa n care apar aceste evenimente, programul le analizeaz i
execut o secven de cod specific evenimentului respectiv. Dup
execuia codului, programul se oprete din nou pn la apariia
unui nou eveniment.
Aceste dou alternative diferite de a aborda scrierea unui program
i au rdcinile n moduri diferite de lucru ale sistemelor de operare
i n moduri diferite de a gndi interfaa cu utilizatorul.
Java implementeaz ambele stiluri de programe discutate mai sus.
n primul caz, avem o clas de pornire care conine o funcie public
principal i care va fi lansat n execuie la apelarea programului.

140

n acest caz programul i controleaz complet execuia ulterioar.


n termenii limbajului Java, aceasta este o aplicaie.
n al doilea caz, codul ruleaz n interiorul unui navigator Internet.
Clasa de pornire trebuie s aib implementate metode de rspuns la
anumite evenimente pe care le genereaz navigatorul, precum ar fi
iniializare, pornire, oprire, desenare, etc. Acest al doilea tip de
programe Java le vom numi apleturi.
Distincia dintre cele dou moduri de organizare a codului este
destul de vag, din cauz c cele dou moduri de lucru se pot
amesteca n
realitate, un obiect aplet putnd fi n acelai timp lansat ca aplicaie
independent i invers. Totul depinde de metodele care au fost
definite n interiorul clasei de pornire a programului.

7.1 Aplicaii Java


Cea mai simpl aplicaie Java este declaraia unei clase de pornire
coninnd o singur metod, main , ca n exemplul urmtor:
public class HelloWorld {
public static void main( String args[] ) {
System.out.println( "Hello, world!" );
}
}

Acest exemplu definete o funcie principal care afieaz un simplu


mesaj pe consola aplicaiei. Afiarea este lsat n sarcina
clasei java.lang.Systemcare conine n interior implementarea ieirii i
intrrii standard precum i a ieirii standard de eroare sub forma
unor referine ctre obiecte de tipInputStream pentru in (intrarea
standard) respectiv PrintStream pentru out ierr (ieirea standard i
ieirea standard de eroare).
Numele metodei main este obligatoriu, la fel i parametrul acesteia.
Atunci cnd lansm interpretorul Java mpreun cu numele unei
clase care reprezint clasa de pornire, interpretorul caut n
interiorul acestei clase definiia unei metode numite main . Aceast
metod trebuie s fie obligatoriu public i static. n acelai timp,
metoda main trebuie s nu ntoarc nici un rezultat i s accepte un
singur parametru de tip tablou de iruri de caractere.
Dac interpretorul gsete aceast metod n interiorul clasei
apelate, el lanseaz n execuie metoda main . Atenie,
141

metoda main fiind de tip static, nu poate apela dect variabile statice.
De obicei ns, metoda main nu face nimic altceva dect s-i
prelucreze parametrul dup care s creeze o serie de obiecte care
vor controla execuia ulterioar a aplicaiei.
Singurul parametru al metodei main este un tablou care conine
argumentele aflate pe linia de comand n momentul apelului. Nu
este necesar transmiterea numrului de argumente care au fost
gsite pe linia de comand pentru c tablourile Java conin n
interior informaii relative la numrul de elemente. Acest numr de
elemente se poate obine prin accesarea variabilei length din
interiorul tabloului ca n exemplul urmtor care listeaz parametrii
de pe linia de comand la lansarea unei clase:
public class Arguments {
public static void main( String args[] ) {
for( int i = 0; i < args.length; i++ ) {
System.out.println( args[i] );
}
}
}
Iat un exemplu de rulare a acestei aplicaii:
>java Arguments unu doi trei
unu
doi
trei
> ^

7.2 Apleturi Java


Apleturile Java ruleaz ntr-un document HTML. n acest document,
fiecare aplet are rezervat o fereastr dreptunghiular prin care
comunic cu utilizatorul. Dreptunghiul de ncadrare al ferestrei este
definit ntr-un tag HTML numit APPLET. Aceast fereastr este n
exclusivitate la dispoziia apletului care este responsabil de
desenarea ei i de tratarea eventualelor evenimente care se refer la
ea.
Noul tag HTML este recunoscut deocamdat doar de anumite
navigatoare WWW precum HotJava i Netscape 2.0. Este foarte
probabil
ca n viitor majoritatea navigatoarelor s ofere compatibilitate Java.
mpreun cu definirea interfeei dintre apleturi i navigator, Sun a
definit i o sintax specific noului tag HTML care permite
poziionarea i dimensionarea ferestrei apletului n document
142

precum i specificarea unor parametri care s poat altera modul de


lucru al apletului.
Iat un prim exemplu de aplet:
import java.awt.Graphics;
public class HelloWorldApplet extends java.applet.Applet {
public void init() {
resize( 150,25 );
}
public void paint( Graphics g ) {
g.drawString( "Hello world!", 50, 25 );
}
}

n mod minimal, apletul nostru nu definete dect dou metode i


anume una de iniializare, necesar pentru organizarea mediului n
care ruleaz apletul i una de desenare a spaiului destinat
apletului n interiorul documentului HTML. Metoda de iniializare
nu face n acest caz dect s redimensioneze spaiul alocat n mod
corespunztor necesitilor sale n timp ce metoda de desenare
afieaz n acest spaiu un mesaj de salut.
Pentru a vedea rezultatele rulrii acestui aplet trebuie s construim
un document minimal HTML, care poate s arate n felul urmtor:
<HTML>
<HEAD>
<TITLE> Hello World Applet </TITLE>
</HEAD>
<BODY>
Iata iesirea programului:
<APPLET CODE="HelloWorldApplet.class" WIDTH=150
</APPLET>
</BODY>
</HTML>

HEIGHT=25>

Spre deosebire de o aplicaie normal Java, apleturile nu pot primi


parametri pe linia de comand pentru c nu exist linie de
comand. Din acest motiv, trebuie s introducem parametrii
apletului n fiierul HTML. De exemplu am putea introduce, imediat
dup linia de declaraie a apletului o linie de forma:
<PARAM NAME=mesaj VALUE="Salutare, lume!">

i s modificm codul apletului dup cum urmeaz:


import java.awt.Graphics;
public class HelloWorldApplet extends java.applet.Applet {
private String sir;

143

public void init() {


sir=getParameter( "mesaj" );
if( sir == null ) {
sir = "Hello, World!";
}
resize( 150,25 );
}
public void paint( Graphics g ) {
g.drawString( sir, 50, 25 );
}
}

n acest mod putem s controlm la lansare iniializarea apletului.


n definiia clasei Applet exist i dou funcii care permit
navigatorului regsirea unui minim de informaii despre aplet.
Aceste informaii reprezint descrierea apletului i a parametrilor
acestuia. Funciile care trebuiesc definite n noua clas derivat
din Applet sunt getAppletInfo igetParameterInfo . De exemplu, putem
introduce n clasa HelloWorldAppletdou noi funcii:
public String getAppletInfo() {
return "Applet scris de Eugen Rotariu";
}
public String [][] getParameterInfo() {
String info[][] = {
{ "Parametru", "String", "Textul de afisat" }
};
return info;
}

Execuia unui aplet este marcat de cteva evenimente importante


generate de ctre navigator. Atunci cnd navigatorul ntlnete o
etichet APPLET, pornete n primul rnd ncrcarea codului
necesar rulrii apletului. Pn cnd acest cod nu a ajuns pe
calculatorul client, apletul nu poate fi pornit.
Dup ncrcarea codului, apletul este apelat pentru iniializare.
Acesta este momentul n care apletul i pregtete parametrii i
obine de la sistem resursele necesare rulrii. Dup ce iniializarea a
fost terminat, navigatorul trimite ctre aplet o comand de pornire.
Aceasta este comanda care pune efectiv apletul n funciune
deschiznd interaciunea cu utilizatorul.
Un aplet ruleaz atta timp ct navigatorul este activ. La
schimbarea paginii curente, apleturile din vechea pagin nu sunt
distruse, dar primesc o comand de oprire temporar (pe care de
altfel pot s o ignore). La rencrcarea paginii, o alt comand de
pornire este lansat spre aplet i acest ciclu se poate relua. n
sfrit, la oprirea navigatorului, apletul primete o comand de

144

oprire definitiv, caz n care el trebuie s elibereze toate resursele pe


care le blocheaz.
Orice aplet Java reprezint, din punctul de vedere al limbajului un
nou tip de obiect, derivat din obiectul standard Applet . Atunci cnd
navigatorul lanseaz un nou aplet el nu face altceva dect s
instanieze un nou obiect din aceast clas. Subrutinele care
trateaz evenimentele descrise anterior trebuiesc definite ca metode
n interiorul acestui nou tip de obiecte.
n continuare, ntre dou evenimente de pornire i respectiv de
oprire temporar a apletului navigatorul transmite ctre aplet
evenimente specifice oricrei interfee grafice cum ar fi evenimentul
care provoac redesenarea spaiului destinat apletului, evenimente
legate de apsarea unor taste sau a unor butoane ale mausului, etc.
Ca rspuns la aceste evenimente, apletul trebuie s reacioneze
schimbnd coninutul ferestrei, lansnd mesaje sonore, etc. Iat i
un exemplu de aplet care ne arat fazele prin care trece un aplet n
timpul existenei sale:
import java.applet.Applet;
import java.awt.*;
public class EventTutor extends Applet {
public void init() {
// metoda de iniializare
// este apelat la construcia noii instane de aplet
System.out.println("init");
}
public void paint(Graphics g) {
// metoda de desenare
// este apelat ori de cte ori este necesar
// redesenarea ferestrei apletului
System.out.println("paint");
}
public void start() {
// metoda de lansare in execuie
// este apelat la pornire
//sau la rentoarcerea n pagina apletului
System.out.println("start");
}
public void stop() {
// metoda de oprire temporar a execuiei
System.out.println( "stop" );
}
public void destroy() {
// metoda de oprire definitiv
System.out.println("destroy");
}
public void update(Graphics g) {

145

// metoda de actualizare a ferestrei apletului


// este apelata atunci cnd nu este necesar redesenarea
// ntregii ferestre. n mod implicit,
// metoda apeleaz metoda paint.
System.out.println("update");
}
public boolean mouseUp(Event e, int x, int y) {
// S-a ridicat butonul mausului n fereastra apletului.
System.out.println("mouseUp");
return false;
}
public boolean mouseDown(Event e, int x, int y) {
// S-a apsat butonul mausului n fereastra apletului
System.out.println("mouseDown");
return false;
}
public boolean mouseDrag(Event e, int x, int y) {
// S-a micat mausul n fereastra apletului
// cu butonul apsat
System.out.println("mouseDrag");
return false;
}
public boolean mouseMove(Event e, int x, int y) {
// S-a micat mausul n fereastra apletului
System.out.println("mouseMove");
return false;
}
public boolean mouseEnter(Event e, int x, int y) {
// Mausul a ptruns n fereastra apletului
System.out.println("mouseEnter");
return false;
}
public boolean mouseExit(Event e, int x, int y) {
// mausul a ieit din fereastra apletului
System.out.println("mouseExit");
return false;
}
public void gotFocus() {
// Fereastra apletului a devenit fereastra activ
System.out.println("gotFocus");
}
public void lostFocus() {
// Fereastra apletului nu mai este fereastra activa
System.out.println("lostFocus");
}
public boolean keyDown(Event e, int x) {
// S-a apsat o tasta i aceasta
// este destinata apletului
System.out.println("keyDown");
return true;
}
}

146

Putei rula apletul de mai sus pentru a vedea care este ordinea n
care sunt apelate aceste metode de ctre navigator. Apletul de mai
sus produce ieiri la consol (o fereastr text) i nu n fereastra
apletului. Dac nu vedei consola, ncercai s cutai prin
meniurile navigatorului opiunea de afiare a consolei Java.
Netscape de exemplu are o astfel de opiune n meniul OptionsShow Java console.
Din cele spuse pn acum se poate deduce c apleturile Java nu au
o via proprie, ele fiind doar apelate din cnd n cnd de navigator.
Ceea ce nu este ntocmai adevrat pentru c biblioteca standard de
clase Java ofer suport pentru aplicaii care folosesc mai multe fire
de execuie. Apleturile pot astfel crea fire de execuie care s lucreze
independent fa de navigator.

7.3 Tagul APPLET


Iat descrierea DTD tagului pe care Sun l-a definit pentru
introducerea unui aplet ntr-un document HTML.
<!ELEMENT APPLET - - (PARAM*, (%text;)*)>
<!ATTLIST APPLET
CODEBASE CDATA #IMPLIED-- code base -CODE CDATA #REQUIRED-- code file -NAME CDATA #IMPLIED-- applet name -WIDTH NUMBER #REQUIRED
HEIGHT NUMBER #REQUIRED
ALIGN (left|right|top|texttop|middle|absmiddle|
baseline|bottom|absbottom)
baseline
VSPACE NUMBER #IMPLIED
HSPACE NUMBER #IMPLIED
>
<!ELEMENT PARAM - 0 EMPTY>
<!ATTLIST PARAM
NAME NAME #REQUIRED-- The name of the parameter -VALUE CDATA #IMPLIED-- The value of the parameter
>

--

Atributele obligatorii ale acestei definiii sunt numele fiierului n


care este memorat codul i dimensiunea spaiului rezervat
apletului. Minimal, tag APPLET arat n felul urmtor:
<APPLET CODE="HelloWorldApplet.class" WIDTH=200
Text care apare dac navigatorul nu tie Java
</APPLET>

HEIGHT=150>

Atributele opionale ale tagului descriu locaia de baz a codului


apletului, modul de aliniere n pagin, spaierea i eventualii
parametrii care pot fi transmii apletului din interiorul
documentului HTML.
147

Dac codul clasei este n acelai director cu documentul HTML este


suficient s fie specificat atributul CODE cu numele fiierului unde
este acesta memorat. Dac este nevoie de un director diferit, trebuie
completat i atributul CODEBASE n care se menioneaz
directorul. De exemplu, dac fiierele .class sunt ntr-un subdirector
numit /clase al directorului care conine documentul HTML, atunci
exemplul de mai sus devine:
<APPLET CODE="HelloWorldApplet.class" CODEBASE="clase"
WIDTH=200 HEIGHT=150>
Text care apare dac navigatorul nu tie Java
</APPLET>

Atributul ALIGN specific modul n care fereastra destinat


apletului va fi aliniat n pagin. Valorile sale posibile sunt: LEFT,
RIGHT, TOP, TEXTTOP, MIDDLE, ABSMIDDLE, BASELINE,
BOTTOM i ABSBOTTOM. Valoarea implicit este BASELINE.

LEFT, RIGHT - alinierea va fi n stnga, respectiv dreapta,


textului din linie.
TOP - alinierea se va face cu elementul cel mai nalt din linie,
fie el un alt aplet, o imagine sau textul nsui.
TEXTTOP - alinierea se face cu cea mai nalt poziie ocupat
de textul liniei.
ABSMIDDLE - mijlocul apletului va fi aliniat cu mijlocul
elementului cel mai mare din linie.
MIDDLE - mijlocul apletului se va alinia cu mijlocul liniei de
baz a textului.
BASELINE, BOTTOM - baza apletului se va alinia cu linia de
baz a textului.
ABSBOTTOM - baza apletului va fi aliniat cu elementul cel
mai de jos din linie.

Atributele VSPACE i HSPACE specific, n pixeli, spaiul care


desparte apletul de textul care l nconjoar.
Pentru a transmite parametrii unui aplet, putei folosi tagul PARAM
aa cum am artat mai sus.

148

Capitolul VII
Structura programelor

8.1
8.2
8.3
8.4

Pachete de clase
Importul claselor
Fiiere surs
Compilare i execuie

8.1 Pachete de clase


Clasele Java sunt organizate pe pachete. Aceste pachete pot avea
nume ierarhice. Numele de pachete au forma urmtoare:
[NumePachet.]* NumeComponentPachet
Numele de pachete i de componente ale acestora sunt identificatori
Java. De obicei, aceste nume urmeaz structura de directoare n
care sunt memorate clasele compilate. Rdcina arborelui de
directoare n care
sunt memorate clasele este indicat de o variabil sistem
CLASSPATH. n DOS aceasta se seteaz n felul urmtor:
set CLASSPATH=.;c:\java\lib

n Unix se poate seta cu comanda:


CLASSPATH=.:/usr/local/lib/java ; export CLASSPATH

dac lucrai cu bash . Din aceast rdcin, fiecare pachet are


propriul director. n director exist codul binar pentru componentele
pachetului respectiv. Dac pachetul conine subpachete, atunci
acestea sunt memorate ntr-un subdirector n interiorul directorului
pachetului.
Creatorii Java recomand folosirea unei reguli unice de numire a
pachetelor, astfel nct s nu apar conflicte. Convenia
recomandat de ei este aceea de a folosi numele domeniului Internet
aparinnd productorului claselor. Astfel, numele de pachete ar
putea arta ca n:
COM.Microsoft.OLE
COM.Apple.quicktime.v2

149

i aa mai departe.

8.2 Importul claselor


Desigur, este nevoie ca o clas s poat folosi obiecte aparinnd
unei alte clase. Pentru aceasta, definiia clasei respective trebuie s
importe codul binar al celeilalte clase pentru a ti care sunt
variabilele i metodele clasei respective.
Importul se face cu o instruciune special:
import

numeClas ;

unde numele clasei include i pachetul din care aceasta face parte.
De exemplu:
import java.awt.Graphics;
import java.applet.Applet;

Se poate importa i un pachet ntreg, adic toate clasele aparinnd


acelui pachet, printr-o instruciune de forma:
import

numePachet.*;

De exemplu:
import java.awt.*;

8.3 Fiiere surs


Codul surs Java trebuie introdus cu un editor ntr-un fiier text pe
care l vom numi n continuare fiier surs. Un fiier surs poate s
conin declaraia mai multor clase i interfee, dar doar una dintre
acestea poate fi declarat public. Utilizarea celorlalte clase este
limitat la fiierul respectiv. Mai mult, nu putem avea n acelai
timp o interfa public i o clas public declarate n acelai fiier
surs.
Dac dorim s nregistrm codul clasei ntr-un anumit pachet,
putem s includem la nceputul fiierului surs o declaraie de
forma:
package

numePachet;

150

dac aceast declaraie lipsete, clasa va fi plasat n pachetul


implicit, care nu are nume.
Structura general a unui fiier surs este urmtoarea:
[ DeclaraiePachet ][ InstruciuneImport ]*[ DeclaraieDeTip ]*
unde declaraia de tip poate fi o declaraie de clas sau de
interfa.

8.4 Compilare i execuie


Fiierele surs Java au obligatoriu extensia .java . Numele lor este
identic cu numele clasei sau interfeei publice declarate n interior.
n urma compilrii rezult fiiere cu nume identice cu numele
claselor dar cu extensia .class indiferent dac este vorba de o clas
sau o interfa. Fiierul .class este generat n directorul local i nu
direct la locaia pachetului.
Compilarea se face cu o comand de forma:
javac FiierSurs .java

Comanda aceasta, ca i celelalte descrise n acest paragraf este


specific mediului de dezvoltare Java pus la dispoziie de Sun,
numit JDK (Java Development Kit). n viitor este probabil s apar
multe alte medii de dezvoltare care vor avea propriile lor
compilatoare i interpretoare i, posibil, propriile linii de comand.
La compilare, variabila sistem CLASSPATH trebuie s fie deja setat
pentru c nsui compilatorul Java actual este scris n Java.
Pentru lansarea n execuie a unei aplicaii Java, trebuie s
introducei comanda:
java NumeClas

unde numele clasei este numele aplicaiei care conine metoda


Interpretorul va cuta un fiier cu numele NumeClas.class i va
ncerca s instanieze clasa respectiv.

main

Pentru lansarea unui aplet vei avea nevoie de un document HTML


care conine tagul APPLET i ca parametru al acesteia
name=NumeClas.class

151

La lansarea unui aplet, clasele care sunt apelate de clasa principal


sunt mai nti cutate pe sistemul pe care ruleaz navigatorul. Dac
nu sunt acolo, ele vor fi transferate n reea. Asta nseamn c
transferul de cod este relativ mic, trebuie transferat doar codul
specific aplicaiei.

152

Capitolul IX
Fire de execuie i sincronizare

9.1
9.2
9.3
9.4
9.5
9.6
9.7
9.8

Crearea firelor de execuie


Strile unui fir de execuie
Prioritatea firelor de execuie
Grupuri de fire de execuie
Enumerarea firelor de execuie
Sincronizare
Un exemplu
Un exemplu Runnable

O aplicaie Java ruleaz n interiorul unui proces al sistemului de


operare. Acestproces const din segmente de cod i segmente de
date mapate ntr-un spaiu virtual de adresare. Fiecare proces
deine un numr de resurse alocate de ctre sistemul de operare,
cum ar fi fiiere deschise, regiuni de memorie alocate dinamic, sau
fire de execuie. Toate aceste resurse deinute de ctre un proces
sunt eliberate la terminarea procesului de ctre sistemul de operare.
Un fir de execuie este unitatea de execuie a unui proces. Fiecare fir
de execuie are asociate o secven de instruciuni, un set de
regiitri CPU i o stiv. Atenie, un proces nu execut nici un fel de
instruciuni. El este de fapt un spaiu de adresare comun pentru
unul sau mai multe fire de execuie. Execuia instruciunilor cade n
responsabilitatea firelor de execuie. n cele ce urmeaz vom
prescurta uneori denumirea firelor de execuie, numindu-le pur i
simplu fire.
n cazul aplicaiilor Java interpretate, procesul deine n principal
codul interpretorului iar codul binar Java este tratat ca o zon de
date de ctre interpretor. Dar, chiar i n aceast situaie, o aplicaie
Java poate avea mai multe fire de execuie, create de ctre
interpretor i care execut, seturi distincte de instruciuni binare
Java.
Fiecare dintre aceste fire de execuie poate rula n paralel pe un
procesor separat dac maina pe care ruleaz aplicaia este o
main cu mai multe procesoare. Pe mainile monoprocesor,
senzaia de execuie n paralel a firelor de execuie este creat prin
rotirea acestora pe rnd la controlul unitii centrale, cte o cuant
de timp fiecare. Algoritmul de rotire al firelor de execuie este de tip
round-robin.
153

Mediul de execuie Java execut propriul su control asupra firelor


de execuie. Algoritmul pentru planificarea firelor de execuie,
prioritile i strile n care se pot afla acestea sunt specifice
aplicaiilor Java i implementate identic pe toate platformele pe care
a fost portat mediul de execuie Java. Totui, acest mediu tie s
profite de resursele sistemului pe care lucreaz. Dac sistemul
gazd lucreaz cu mai multe procesoare, Java va folosi toate aceste
procesoare pentru a-i planifica firele de execuie. Dac sistemul
ofer multitasking preemptiv, multitaskingul Java va fi de asemenea
preemptiv, etc.
n cazul mainilor multiprocesor, mediul de execuie Java i
sistemul de operare sunt responsabile cu repartizarea firelor de
execuie pe un procesor sau altul. Pentru programator, acest
mecanism este complet transparent, neexistnd nici o diferen
ntre scrierea unei aplicaii cu mai multe fire pentru o main cu un
singur procesor sau cu mai multe. Desigur, exist ns diferene n
cazul scrierii aplicaiilor pe mai multe fire de execuie fa de acelea
cu un singur fir de execuie, diferene care provin n principal din
cauza necesitii de sincronizare ntre firele de execuie aparinnd
aceluiai proces.
Sincronizarea firelor de execuie nseamn c acestea se ateapt
unul pe cellalt pentru completarea anumitor operaii care nu se
pot executa n paralel sau care trebuie executate ntr-o anumit
ordine. Java ofer i n acest caz mecanismele sale proprii de
sincronizare, extrem de uor de utilizat i nglobate n chiar sintaxa
de baz a limbajului.
La lansarea n execuie a unei aplicaii Java este creat automat i
un prim fir de execuie, numit firul principal. Acesta poate ulterior
s creeze alte fire de execuie care la rndul lor pot crea alte fire, i
aa mai departe. Firele de execuie dintr-o aplicaie Java pot fi
grupate n grupuri pentru a fi manipulate n comun.
n afar de firele normale de execuie, Java ofer i fire de execuie
cu prioritate mic care lucreaz n fundalul aplicaiei atunci cnd
nici un alt fir de execuie nu poate fi rulat. Aceste fire de fundal se
numesc demoni i execut operaii costisitoare n timp i
independente de celelalte fire de execuie. De exemplu, n Java
colectorul de gunoaie lucreaz pe un fir de execuie separat, cu
proprieti de demon. n acelai fel poate fi gndit un fir de execuie
care execut operaii de ncrcare a unor imagini din reea.

154

O aplicaie Java se termin atunci cnd se termin toate firele de


execuie din interiorul ei sau cnd nu mai exist dect fire demon.
Terminarea firului principal de execuie nu duce la terminarea
automat a aplicaiei.

9.1 Crearea firelor de execuie


Exist dou ci de definire de noi fire de execuie: derivarea din
clasa Thread a noi clase i implementarea ntr-o clas a
interfeei Runnable .
n primul caz, noua clas motenete toate metodele i variabilele
clasei Threadcare implementeaz n mod standard, n Java,
funcionalitatea de lucru cu fire de execuie. Singurul lucru pe care
trebuie s-l fac noua clas este s reimplementeze metoda run care
este apelat automat de ctre mediul de execuie la lansarea unui
nou fir. n plus, noua clas ar putea avea nevoie s implementeze
un constructor care s permit atribuirea unei denumiri firului de
execuie.
Dac firul are un nume, acesta poate fi obinut cu
metoda getName care returneaz un obiect de tip String .
Iat un exemplu de definire a unui nou tip de fir de execuie:
class FirNou extends Thread {
public FirNou( String nume ) {
// apeleaz constructorul din Thread
super( nume );
}
public void run() {
while( true ) { // fr sfrit
System.out.println( getName() +
" Tastati ^C" );
}
}
}

Dac vom crea un nou obiect de tip FirNou i l lansm n execuie


acesta va afia la infinit mesajul "Tastai ^C". ntreruperea execuiei
se poate face ntr-adevr prin tastarea caracterului ^C, caz n care
ntreaga aplicaie este terminat. Atta timp ns ct noul obiect nu
va fi ntrerupt din exterior, aplicaia va continua s se execute
pentru c mai exist nc fire de execuie active i indiferent de
faptul c firul de execuie principal s-a terminat sau nu.
Iat i un exemplu de aplicaie care folosete aceast clas:
155

public TestFirNou {
public static void main( String[] ) {
new FirNou( "Primul" ).start();
}
}

Metoda start , predefinit n obiectul Thread lanseaz execuia


propriu-zis a firului. Desigur exist i ci de a opri execuia la
nesfrit a firului creat fie prin apelul metodei stop , prezentat mai
jos, fie prin rescrierea funciei run n aa fel nct execuia sa s se
termine dup un interval finit de timp.
A doua cale de definiie a unui fir de execuie este implementarea
interfeeiRunnable ntr-o anumit clas de obiecte. Aceast cale este
cea care trebuie aleas atunci cnd clasa pe care o crem nu se
poate deriva din clasa Thread pentru c este important s fie derivat
din alt clas. Desigur, motenirea multipl ar rezolva aceast
problem, dar Java nu are motenire multipl.
Aceast nou cale se poate folosi n modul urmtor:
class Oclasa {

}
class FirNou extends Oclasa implements Runnable {
public void run() {
for( int i = 0; i < 100; i++ ) {
System.out.println( "pasul " + i );
}
}

}
public class TestFirNou {
public static void main( String argumente[] ) {
new Thread( new FirNou() ).start();
// Obiectele sunt create i folosite imediat
// La terminarea instruciunii, ele sunt automat
// eliberate nefiind referite de nimic
}
}

Dup cum observai, clasa Thread are i un constructor care


primete ca argument o instan a unei clase care implementeaz
interfaa Runnable . n acest caz, la lansarea n execuie a noului fir,
cu metoda start , se apeleaz metoda run din acest obiect i nu din
instana a clasei Thread .
Atunci cnd dorim s crem un aplet care s ruleze pe un fir de
execuie separat fa de pagina de navigator n care ruleaz pentru
a putea executa operaii n fereastra apletului i n acelai timp s
putem folosi n continuare navigatorul, suntem obligai s alegem
156

cea de-a doua cale de implementare. Aceasta pentru c apletul


nostru trebuie s fie derivat din clasa standard Applet . Singura
alternativ care ne rmne este aceea de a implementa n aplet
interfaa Runnable.

9.2 Strile unui fir de execuie


Un fir de execuie se poate afla n Java n mai multe stri, n funcie
de ce se ntmpl cu el la un moment dat.
Atunci cnd este creat, dar nainte de apelul metodei start, firul se
gsete ntr-o stare pe care o vom numi Fir Nou Creat . n aceast
stare, singurele metode care se pot apela pentru firul de execuie
sunt metodele start i stop . Metoda startlanseaz firul n execuie
prin apelul metodei run . Metoda stop omoar firul de execuie nc
nainte de a fi lansat. Orice alt metod apelat n aceast stare
provoac terminarea firului de execuie prin generarea unei excepii
de tipIllegalThreadStateException .
Dac apelm metoda start pentru un Fir Nou Creat firul de execuie
va trece n starea Ruleaz . n aceast stare, instruciunile din corpul
metodei run se execut una dup alta. Execuia poate fi oprit
temporar prin apelul metodei sleep care primete ca argument un
numr de milisecunde care reprezint intervalul de timp n care
firul trebuie s fie oprit. Dup trecerea intervalului, firul de execuie
va porni din nou.
n timpul n care se scurge intervalul specificat de sleep , obiectul nu
poate fi repornit prin metode obinuite. Singura cale de a iei din
aceast stare este aceea de a apela metoda interrupt . Aceast
metod arunc o excepie de tipInterruptedException care nu este
prins de sleep dar care trebuie prins obligatoriu de metoda care a
apelat metoda sleep . De aceea, modul standard n care se apeleaz
metoda sleep este urmtorul:

try {
sleep( 1000 ); // o secund
} catch( InterruptedException ) {

Dac dorim oprirea firului de execuie pe timp nedefinit, putem


apela metodasuspend . Aceasta trece firul de execuie ntr-o nou
stare, numit Nu Ruleaz . Aceeai stare este folosit i pentru oprirea
157

temporar cu sleep . n cazul apeluluisuspend ns, execuia nu va


putea fi reluat dect printr-un apel al metodei resume. Dup acest
apel, firul va intra din nou n starea Ruleaz .
Pe timpul n care firul de execuie se gsete n starea Nu Ruleaz ,
acesta nu este planificat niciodat la controlul unitii centrale,
aceasta fiind cedat celorlalte fire de execuie din aplicaie.
Firul de execuie poate intra n starea Nu Ruleaz i din alte motive.
De exemplu se poate ntmpla ca firul s atepte pentru terminarea
unei operaii de intrare/ieire de lung durat caz n care firul va
intra din nou n starea Ruleazdoar dup terminarea operaiei.
O alt cale de a ajunge n starea Nu Ruleaz este aceea de a apela o
metod sau o secven de instruciuni sincronizat dup un obiect.
n acest caz, dac obiectul este deja blocat, firul de execuie va fi
oprit pn n clipa n care obiectul cu pricina apeleaz
metoda notify sau notifyAll .
n fine, atunci cnd metoda run i-a terminat execuia, obiectul intr
n starea Mort. Aceast stare este pstrat pn n clipa n care
obiectul
este eliminat din memorie de mecanismul de colectare a gunoaielor.
O alt posibilitate de a intra n starea Mort este aceea de a apela
metoda stop .
Atunci cnd se apeleaz metoda stop , aceasta arunc cu o
instruciune throw o eroare numit ThreadDeath . Aceasta poate fi
prins de ctre cod pentru a efectua curenia necesar. Codul
necesar este urmtorul:

try {
firDeExecutie.start();

} catch( ThreadDeath td ) {
// curenie
throw td; // se arunc obiectul mai departe
// pentru a servi la distrugerea
// firului de execuie
}

Desigur, firul de execuie poate fi terminat i pe alte ci, caz n care


metoda stopnu este apelat i eroarea ThreadDeath nu este aruncat.
n aceste situaii este preferabil s ne folosim de o clauz finally ca
n:
158


try {
firDeExecutie.start();

} finally {
..// curenie
}

n fine, dac nu se mai poate face nimic pentru c firul de execuie


nu mai rspunde la comenzi, putei apela la calea disperat a
metodei destroy . Din pcate, metoda destroy termin firul de execuie
fr a proceda la curirile necesare n memorie.
Atunci cnd un fir de execuie este oprit cu comanda stop , mai este
nevoie de un timp pn cnd sistemul efectueaz toate operaiile
necesare opririi. Din aceast cauz, este preferabil s ateptm n
mod explicit terminarea firului prin apelul metodei join :
firDeExecutie.stop()
try {
firDeExecutie.join();
} catch( InterruptedException e ) {

Excepia de ntrerupere trebuie prins obligatoriu. Dac nu apelm


metoda joinpentru a atepta terminarea i metoda stop este de
exemplu apelat pe ultima linie a funciei main , exist ansa ca
sistemul s cread c firul auxiliar de execuie este nc n via i
aplicaia Java s nu se mai termine rmnnd ntr-o stare de
ateptare. O putei desigur termina tastnd ^C.

9.3 Prioritatea firelor de execuie


Fiecare fir de execuie are o prioritate cuprins ntre valorile
MIN_PRIORITY i MAX_PRIORITY. Aceste dou variabile finale sunt
declarate n clasa Thread . n mod normal ns, un fir de execuie are
prioritatea NORM_PRIORITY, de asemenea definit n clasa Thread .
Mediul de execuie Java planific firele de execuie la controlul
unitii centrale n funcie de prioritatea lor. Dac exist mai multe
fire cu prioritate maxim, acestea sunt planificate dup un algoritm
round-robin. Firele de prioritate mai mic intr n calcul doar atunci
cnd toate firele de prioritate mare sunt n starea Nu Ruleaz.
Prioritatea unui fir de execuie se poate interoga cu
metoda getPriority care ntoarce un numr ntreg care reprezint
prioritatea curent a firului de execuie. Pentru a seta prioritatea, se
159

folosete metoda setPriority care primete ca parametru un numr


ntreg care reprezint prioritatea dorit.
Schimbarea prioritii unui fir de execuie este o treab periculoas
dac metoda cu prioritate mare nu se termin foarte repede sau
dac nu are opriri dese. n caz contrar, celelalte metode nu vor mai
putea primi controlul unitii centrale.
Exist ns situaii n care putem schimba aceast prioritate fr
pericol, de exemplu cnd avem un fir de execuie care nu face
altceva dect s citeasc caractere de la utilizator i s le memoreze
ntr-o zon temporar. n acest caz, firul de execuie este n cea mai
mare parte a timpului n starea Nu Ruleaz din cauz c ateapt
terminarea unei operaii de intrare/ieire. n clipa n care
utilizatorul tasteaz un caracter, firul va iei din starea de ateptare
i va fi primul planificat la execuie din cauza prioritii sale
ridicate. n acest fel utilizatorul are senzaia c aplicaia rspunde
foarte repede la comenzile sale.
n alte situaii, avem de executat o sarcin cu prioritate mic. n
aceste cazuri, putem seta pentru firul de execuie care execut
aceste sarcini o prioritate redus.
Alternativ, putem defini firul respectiv de execuie ca un demon.
Dezavantajul n aceast situaie este faptul c aplicaia va fi
terminat atunci cnd exist doar demoni n lucru i exist
posibilitatea pierderii de date. Pentru a declara un fir de execuie ca
demon, putem apela metoda setDaemon. Aceast metod primete ca
parametru o valoare boolean care dac este true firul este fcut
demon i dac nu este adus napoi la starea normal. Putem testa
faptul c un fir de execuie este demon sau nu cu
metoda isDemon .

9.4 Grupuri de fire de execuie


Uneori avem nevoie s acionm asupra mai multor fire de execuie
deodat, pentru a le suspenda, reporni sau modifica prioritatea n
bloc. Din acest motiv, este util s putem grupa firele de execuie pe
grupuri. Aceast funcionalitate este oferit n Java de ctre o clas
numit ThreadGroup .
La pornirea unei aplicaii Java, se creeaz automat un prim grup de
fire de execuie, numit grupul principal, main . Firul principal de
execuie
160

face parte din acest grup. n continuare, ori de cte ori crem un
nou fir de execuie, acesta va face parte din acelai grup de fire de
execuie ca i firul de execuie din interiorul cruia a fost creat, n
afar de cazurile n care n constructorul firului specificm explicit
altceva.
ntr-un grup de fire de execuie putem defini nu numai fire dar i
alte grupuri de execuie. Se creeaz astfel o arborescen a crei
rdcin este grupul principal de fire de execuie.
Pentru a specifica pentru un fir un nou grup de fire de execuie,
putem apela constructorii obinuii dar introducnd un prim
parametru suplimentar de tipThreadGroup . De exemplu, putem folosi
urmtorul cod:
ThreadGroup tg = new ThreadGroup( "Noul grup" );
Thread t = new Thread( tg, "Firul de executie" );

Acest nou fir de execuie va face parte dintr-un alt grup de fire dect
firul principal. Putem afla grupul de fire de execuie din care face
parte un anumit fir apelnd metoda getThreadGroup , ca n secvena:
Thread t = new Thread( "Firul de Executie" );
ThreadGroup tg = t.getThreadGroup();

Operaiile definite pentru un grup de fire de execuie sunt


clasificabile n operaii care acioneaz la nivelul grupului, cum ar fi
aflarea numelui, setarea unei prioriti maxime, etc., i operaii care
acioneaz asupra fiecrui fir de execuie din grup, cum ar
fi stop , suspend sau resume . Unele dintre aceste operaii necesit
aprobarea controloarelor de securitate acest lucru fcndu-se
printr-o metod numit checkAccess . De exemplu, nu putei seta
prioritatea unui fir de execuie dect dac avei drepturile de acces
necesare.

9.5 Enumerarea firelor de execuie


Pentru a enumera firele de execuie active la un moment dat, putem
folosi metodaenumerate definit n clasa Thread precum i n
clasa ThreadGroup . Aceast metod primete ca parametru o referin
ctre un tablou de referine la obiecte de tipThread pe care l umple
cu referine ctre fiecare fir activ n grupul specificat.
Pentru a afla cte fire active sunt n grupul respectiv la un moment
dat, putem apela metoda activeCount din clasa ThreadGroup . De
exemplu:
161

public listeazaFire {
ThreadGroup grup = Thread.currentThread().getThreadGroup();
int numarFire = grup.activeCount();
Thread fire[] = new Thread[numarFire];
grup.enumerate( fire );
for( int i = 0; i < numar; i++ ) {
System.out.println( fire[i].toString() );
}
}

Metoda enumerate ntoarce numrul de fire memorate n tablou, care


este identic cu numrul de fire active.

9.6 Sincronizare
n unele situaii se poate ntmpla ca mai multe fire de execuie s
vrea s acceseze aceeai variabil. n astfel de situaii, se pot
produce ncurcturi dac n timpul unuia dintre accese un alt fir de
execuie modific valoarea variabilei.
Limbajul Java ofer n mod nativ suport pentru protejarea acestor
variabile. Suportul este construit de fapt cu granulaie mai mare
dect o singur variabil, protecia fcndu-se la nivelul obiectelor.
Putem defini metode, n cadrul claselor, care sunt sincronizate.
Pe o instan de clas, la un moment dat, poate lucra o singur
metod sincronizat. Dac un alt fir de execuie ncearc s apeleze
aceeai metod pe aceeai instan sau o alt metod a clasei de
asemenea declarat sincronizat, acest al doilea apel va trebui s
atepte nainte de execuie eliberarea instanei de ctre cealalt
metod.
n afar de sincronizarea metodelor, se pot sincroniza i doar
blocuri de instruciuni. Aceste sincronizri se fac tot n legtur cu
o anumit instan a unei clase. Aceste blocuri de instruciuni
sincronizate se pot executa doar cnd instana este liber. Se poate
ntmpla ca cele dou tipuri de sincronizri s se amestece, n
sensul c obiectul poate fi blocat de un bloc de instruciuni i toate
metodele sincronizate s atepte, sau invers.
Declararea unui bloc de instruciuni sincronizate se face prin:
synchronize

( Instan ) {

Instruciuni
}
162

iar declararea unei metode sincronizate se face prin folosirea


modificatoruluisynchronize la implementarea metodei.

9.7 Un exemplu
Exemplul urmtor implementeaz soluia urmtoarei probleme:
ntr-o ar foarte ndeprtat triau trei nelepi filozofi. Aceti trei
nelepi i pierdeau o mare parte din energie certndu-se ntre ei
pentru a afla care este cel mai nelept. Pentru a trana problema o
dat pentru totdeauna, cei trei nelepi au pornit la drum ctre un
al patrulea nelept pe care cu toii l recunoteau c ar fi mai bun
dect ei.
Cnd au ajuns la acesta, cei trei i-au cerut s le spun care dintre
ei este cel mai nelept. Acesta, a scos cinci plrii, trei negre i
dou albe, i li le-a artat explicndu-le c i va lega la ochi i le va
pune n cap cte o plrie, cele dou rmase ascunzndu-le. Dup
aceea, le va dezlega ochii, i fiecare dintre ei va vedea culoarea
plriei celorlali dar nu i-o va putea vedea pe a sa. Cel care i va
da primul seama ce culoare are propria plrie, acela va fi cel mai
nelept.
Dup explicaie, neleptul i-a legat la ochi, le-a pus la fiecare cte o
plrie neagr i le-a ascuns pe celelalte dou. Problema este aceea
de a descoperi care a fost raionamentul celui care a ghicit primul
c plria lui este neagr.
Programul urmtor rezolv problema dat n felul urmtor: Fiecare
nelept privete plriile celorlali doi. Dac ambele sunt albe,
problema este rezolvat, a lui nu poate fi dect neagr. Dac vede o
plrie alb i una neagr, atunci el va trebui s atepte puin s
vad ce spune cel cu plria neagr. Dac acesta nu gsete soluia,
nseamn c el nu vede dou plrii albe, altfel ar fi gsit imediat
rspunsul. Dup un scurt timp de ateptare, neleptul poate s fie
sigur c plria lui este neagr.
n fine, dac ambele plrii pe care le vede sunt negre, va trebui s
atepte un timp ceva mai lung pentru a vedea dac unul dintre
concurenii si nu ghicete plria. Dac dup scurgerea timpului
nici unul nu spune nimic, nseamn c nici unul nu vede o plrie
alb i una neagr. nseamn c propria plrie este neagr.
Desigur, raionamentul pleac de la ideea c ne putem baza pe
faptul c toi nelepii gndesc i pot rezolva probleme uoare. Cel
163

care ctig a gndit doar un pic mai repede. Putem simula viteza
de gndiri cu un interval aleator de ateptare pn la luarea
deciziilor. n realitate, intervalul nu este aleator ci dictat de viteza de
gndire a fiecrui nelept.
Cei trei nelepi sunt implementai identic sub form de fire de
execuie. Nu ctig la fiecare rulare acelai din cauza caracterului
aleator al implementrii. neleptul cel mare este firul de execuie
principal care controleaz activitatea celorlalte fire i le servete cu
date, culoarea plriilor, doar n msura n care aceste date trebuie
s fie accesibile. Adic nu se poate cere propria culoare de plrie.
Culoarea iniial a plriilor se poate rescrie din linia de comand.
import java.awt.Color;
// clasa Filozof implementeaz comportamentul
// unui concurent
class Filozof extends Thread {
// prerea concurentului despre culoarea
// plriei sale. Null dac nc nu i-a
// format o prere.
Color parere = null;
Filozof( String nume ) {
super( nume );
}
public void run() {
// concurentii firului curent
Filozof concurenti[] = new Filozof[2];
// temporar
Thread fire[] = new Thread[10];
int numarFire = enumerate( fire );
for( int i = 0, j = 0; i < numarFire &&
j < 2; i++ ) {
if( fire[i] instanceof Filozof &&
fire[i] != this ) {
concurenti[j++] = (Filozof)fire[i];
}
}
while( true ) {
Color primaCuloare = Concurs.culoare( this,
concurenti[0] );
Color adouaCuloare =
Concurs.culoare( this, concurenti[1] );
if( primaCuloare == Color.white &&
adouaCuloare == Color.white ) {
synchronized( this ) {
parere = Color.black;
}
} else if( primaCuloare == Color.white ){
try{
sleep( 500 );
} catch( InterruptedException e ){
};
if( Concurs.culoare( this, concurenti[1]) != concurenti[1].aGhicit()) {
synchronized( this ) {
parere = Color.black;
};

164

}
} else if( adouaCuloare == Color.white ) {
try{
sleep( (int)( Math.random()*500));
} catch( InterruptedException e ) {
};
if( Concurs.culoare(this, concurenti[0] ) != concurenti[0].aGhicit()) {
synchronized( this ) {
parere = Color.black;
};
}
} else {
try {
sleep( (int)( Math.random()*500)+500 );
} catch( InterruptedException e ) {
};
if( Concurs.culoare(this, concurenti[0]) != concurenti[0].aGhicit() &&
Concurs.culoare( this,
concurenti[1] ) !=
concurenti[1].aGhicit() ) {
synchronized( this ) {
parere = Color.black;
};
}
}
}
}
public synchronized Color aGhicit() {
return parere;
}
}
public class Concurs {
private static Color palarii[] = {
Color.black, Color.black, Color.black
};
private static Filozof filozofi[] = new Filozof[3];
public static void main( String args[] ) {
for( int i = 0; i < args.length && i <
3; i++ ) {
if( args[i].equalsIgnoreCase( "alb" ) ) {
palarii[i] = Color.white;
} else if(args[i].equalsIgnoreCase("negru")) {
palarii[i] = Color.black;
}
}
for( int i = 0; i < 3; i++ ) {
filozofi[i] = new Filozof( "Filozoful " +
( i + 1 ) );
}
for( int i = 0; i < 3; i++ ) {
filozofi[i].start();
}
System.out.println( "Concurenti:" );
for( int i = 0; i < 3; i++ ) {
System.out.println( "\t" +
filozofi[i].getName() + " "
+ (( palarii[i] == Color.white ) ?
"alb":"negru" ) );
}
gata:
while( true ) {
for( int i = 0; i < 3; i++ ) {

165

if( filozofi[i].aGhicit()==palarii[i] ) {
System.out.println(
filozofi[i].getName() +
" a ghicit." );
break gata;
}
}
}
for( int i = 0; i < 3; i++ ) {
filozofi[i].stop();
try {
filozofi[i].join();
} catch( InterruptedException e ) {};
}
}
public static Color culoare( Filozof filozof,
Filozof concurent ) {
if( filozof != concurent ) {
for( int i = 0; i < 3; i++ ) {
if( filozofi[i] == concurent ) {
return palarii[i];
}
}
}
return null;
}
} ^

9.8 Un exemplu Runnable


Exemplul urmtor implementeaz problema celor 8 dame, i anume:
gsete toate posibilitile de a aeza pe o tabl de ah 8 regine n
aa fel nct acestea s nu se bat ntre ele. Reginele se bat pe linie,
coloan sau n diagonal.
Soluia de fa extinde problema la o tabl de NxN csue i la N
regine. Parametrul N este citit din tagul HTML asociat apletului.
import java.awt.*;
import java.applet.Applet;
public
class QueensRunner extends Applet implements Runnable {
int n;
int regine[];
int linie;
Image queenImage;
Thread myThread;
public void start() {
if( myThread == null ) {
myThread = new Thread( this, "Queens" );
myThread.start();
}
}
public void stop() {
myThread.stop();
myThread = null;
}

166

public void run() {


while( myThread != null ) {
nextSolution();
repaint();
try {
myThread.sleep( 1000 );
} catch ( InterruptedException e ){
}
}
}
boolean isGood() {
for( int i = 0; i < linie; i++ ) {
if( regine[linie] == regine[i] ||
Math.abs( regine[i] regine[linie] ) == Math.abs( i - linie ) ) {
return false;
}
}
return true;
}
void nextSolution() {
while( true ) {
if( linie < 0 ) {
linie = 0;
}
regine[linie]++;
if( regine[linie] > n ) {
regine[linie] = 0;
linie--;
} else {
if( isGood() ) {
linie++;
if( linie >= n ) {
break;
}
}
}
}
}
public void init() {
String param = getParameter( "Dimension" );
if( param == null ) {
n = 4;
} else {
try {
n = Integer.parseInt( param );
} catch( NumberFormatException e ) {
n = 4;
}
if( n < 4 ) {
n = 4;
}
}
regine = new int[n + 1];
for( int i = 0; i < n; i++ ) {
regine[i] = 0;
}
linie = 0;
queenImage = getImage(getCodeBase(), "queen.gif"

);

167

}
public void paint( Graphics g ) {
Dimension d = size();
g.setColor( Color.red );
int xoff = d.width / n;
int yoff = d.height / n;
for( int i = 1; i < n; i++ ) {
g.drawLine( xoff * i, 0, xoff * i, d.height );
g.drawLine( 0, yoff * i, d.width, yoff * i );
}
for( int i = 0; i < n; i++ ) {
for( int j = 0; j < n; j++ ) {
if( regine[i] - 1 == j ) {
g.drawImage(queenImage,
i*xoff + 1, j*yoff + 1, this);
}
}
}
}
public String getAppletInfo() {
return "Queens by E. Rotariu";
}
} ^

168

Bibliografie
1. Dumitru Rdoiu,
HTML - Publicaii Web, Computer Press Agora SRL
2. James Gostling, Henry McGilton,
The Java Language Environment, A white paper, Sun
Microsystems, Inc.
3. David Flanagan,
Java in a Nutshell: A Desktop Quick Reference for Java
Programmers,
O'Reilly & Associates, Inc.
4. Ed Anuff,
The Java Sourcebook , Wiley Computer Publishing
5. Mike Daconta,
Java for C/C++ Programmers, Wiley Computer Publishing
6. Arthur van Hoff, Sami Shaio, Orca Starbuck,
Hooked on Java, Addison-Wesley Publishing Company
7. Laura Lemay, Charles L. Perkins,
Teach your self Java in 21 days, Sams.net Publishing
8. *** - The Java Language Specification, Sun Microsystems,
Inc.

169

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