Sunteți pe pagina 1din 523

Severin BUMBARU

PROGRAMAREA ORIENTAT PE OBIECTE N LIMBAJUL JAVA

Editura Fundaiei Universitare "Dunrea de Jos" - Galai, 2002

Severin Bumbaru Severin Bumbaru Programarea orientat pe obiecte n limbajul Java Editura Fundaiei Universitare "Dunrea de Jos" din Galai - 2002 ISBN 973-8352-53-3 Referent tiinific: prof.dr.ing. Cornelia NOVAC

Programarea orientata pe obiecte n limbajul Java

CUPRINSUL
0. Introducere 1. Scurt prezentare a platformei Java i a programrii orientate pe obiecte 2. iruri. Elemente lexicale ale limbajului Java. Variabile i tipuri de date primitive 3. Expresii. Instruciuni simple i instruciuni structurate. Tratarea excepiilor n limbajul Java 4. Tipul referin. Utilizarea claselor din pachetul java.lang. Tablouri. Utilizarea parametrilor din linia de comnad 5. Declararea claselor 6. Caracteristicile obiectelor i claselor i reflectarea lor n declararea claselor. Interfete. Clase imbricate 7. Interfee utilizator grafice i programarea orientat pe evenimente 8. Componentele grafice din JFC/Swing 9. Utilizarea ferestrelor de dialog. Desenarea 10. Introducere n HTML. Crearea i utilizarea de appleturi 11. Fluxuri de intrare/ieire i fiiere 12. Fire de execuie Index de clase i interfee Bibliografie Anex : Fiierele surs ale claselor date ca exemple
4 7 27 66 99 137 163 198 240 267 291 306 333 363 458 460

Severin Bumbaru

Introducere
Obiectivele cursului Cum este structurat acest curs Recomandri privind modul de lucru 4 5 5

Obiectivele cursului
Cursul "Programare orientat pe obiecte n limbajul Java" se adreseaz studenilor profilelor "Ingineria sistemelor i calculatoarelor" i "Electronic" de la Universitatea "Dunrea de Jos" din Galai i i propune urmtoarele obiective:

nsuirea conceptelor de baz ale programrii orientate pe obiecte; nsuirea limbajului de programare Java; formarea deprinderilor privind realizarea de aplicaii i miniaplicaii n limbajul Java; iniiere n utilizarea bibliotecilor de clase Java; nsuirea proiectrii interfeei grafice utilizator i a programrii orientate pe evenimente; iniiere n utilizarea fluxurilor de date i fiierelor n limbajul Java; iniiere n programarea concurent (realizarea de programe cu mai multe fire de execuie).

Cursul poate fi folosit i de toi cei care doresc s se iniieze n utilizarea limbajului Java i n programarea orientat pe obiecte.

Programarea orientata pe obiecte n limbajul Java

Cum este structurat cursul


Cursul este structurat ca un ciclu de 12 lecii, care cuprind att prezentarea conceptelor care trebuie nsuite de studeni, ct i indicaii asupra lucrrilor practice i exemple de ntrebri pentru verificarea cunotinelor. Cursul se prezint n format electronic (hipertext), fiind alctuit dintr-un ansamblu de pagini legate ntre ele. Din punct de vedere al obligativitii citirii i nsuirii cunotinelor coninute, aceste pagini sunt situate pe patru niveluri, care difera ntre ele prin culoarea fundalului (background):

Nivelul 0: Informaii cu caracter organizatoric. Trebuie citite i respectate, dar nu constituie subiect de examinare. Nivelul 1: Concepte de baz cu caracter obligatoriu. Fr cunoaterea lor nu poaste fi promovat aceast disciplin. Nivelul 2: Concepte necesare pentru o bun cunoatere a programrii orientate pe obiecte i a limbajului Java. Constituie subiecte de verificare i sunt luate n consideraie la stabilirea notei. Nivelul 3: Documentaie necesar pentru elaborarea aplicaiilor i miniaplicaiilor n limbajul Java: descrierea unor clase si interfete, prezentarea pachetelor s.a. Nu se cere memorarea acestei documentaii, dar la sustinerea programelor elaborate trebuie sa cunoateti semnificaia tuturor componentelor utilizate. Nivelul 4: Informaii suplimetare, utile pentru o bun ntelegere i nsuire a disciplinei, dar care nu constituie subiecte de examinare. Cursul conine, de asemenea, un index de clase si interfee, n care se dau legturi ctre pagini care prezint unele clase i interfee din bibliotecile platformei Java (Java API) utile n realizarea aplicaiilor.

Recomandri privind modul de lucru


Cercetrile n domeniul psihologiei educaionale au dus la concluzia c nvarea este eficient atunci cnd studentul contribuie activ, analiznd critic materialele studiate, experimentnd i susinndu-i opiniile n faa altora. n consecin, pentru o bun nsuire a acestei discipline, v recomandm:

s lucrai n echip; fiecare membru al echipei, dup ce i-a nsuit conceptele de baz ale unei lecii: o propune i realizeaz experimente pentru clarificarea acestor concepte; o discut cu colegii cele constatate n urma experimentelor efectuate;

Severin Bumbaru

membrii echipei i mpart ntre ei temele de aplicaii i miniaplicaii primite la laborator, concep i realizeaz aceste aplicaii (miniaplicaii); la elaborarea aplicaiilor i miniaplicaiilor, folosii att acest curs, ct i alte surse de documentare, n special documentaia original; dac, n timpul realizarii aplicaiei, ntmpinai dificulti, consultati-v cu colegii sau cu cadrul didactic ndrumtor. Facei aceasta numai dac suntei convins c nu putei rezolva singur; dup realizarea aplicaiei, explicai colegilor de echip cum ai realizat-o i ce dificulti ai avut; dei accentul se pune pe experimentare, atragem atenia c obiectivul principal al cursului este nsuirea conceptelor care sunt puse n eviden n fiecare lecie. Numai c aceast nsuire de concepte se realizeaz nu doar prim simpla citire a materialului documentar, ci prin experimentare, dezvoltare de aplicaii i schimb de opinii.

Programarea orientata pe obiecte n limbajul Java

Scurt prezentare a platformei Java i a programrii orientate pe obiecte


O prima cunotin cu limbajul i platforma Java Scurt istoric al limbajului i platformei Java Introducere n programarea orientat pe obiecte Prezentarea principalelor tipuri de produse software care se pot scrie n limbajul Java ablonul unei aplicaii simple n limbajul Java Aplicarea acestui ablon la realizarea unei aplicaii simple, n care se afieaz un text pe ecran; Editarea, compilarea i execuia aplicaiilor Java ntrebri 7 17 18 19 20 21 21 26

O prim cunotin cu limbajul i platforma Java


n informatic, Java este

un limbaj de programare, ale crui caliti i-au permis rspndirea rapid, fiind n prezent unul din limbajele cele mai larg folosite. Limbajul este simplu, orientat pe obiecte, robust, sigur, portabil, interpretat, neutru fa de arhitectur, concurent, dinamic si distribuit; un mediu de execuie pentru aplicaiile Java, numit n prezent n englez "Java 2 Runtime Environment", care conine maina virtual Java i un nucleu al bibliotecilor de clase Java; o platform pentru dezvoltarea de aplicaii n care se folosete limbajul Java, care se numete n prezent n englez "Java 2 Platform" i conine: o compilatorul Java (Java Compiler); o maina virtual Java (Java Virtual Machine); o bibliotecile de clase Java (Java Class Libraries); o vizualizatorul de appleturi Java (Java AppletViewer); o depanatorul Java (Java Debbuger) i alte instrumente de dezvoltare; o documentaia; o tehnologie software puternic i modern, care corespunde cerinelor lucrului n reele de calculatoare.

Exist, desigur, i alte semnificaii ale cuvntului Java, care ns nu au legatur direct cu informatica.

Limbajul Java
Java este un limbaj de programare de utilizare larg, care are urmtoarele proprieti:

Severin Bumbaru

este simplu: dei sintaxa se aseamn cu cea a limbajelor C/C++, au fost eliminate acele aspecte care constituiau surse de erori sau produceau confuzii; este orientat pe obiecte: n limbajul Java nu este posibil s se scrie aplicaii care nu respect normele programrii orientate pe obiecte; este robust: programele scrise n Java sunt foarte fiabile, deoarece sunt prevzute numeroase verificri att la compilare, ct i n timpul executrii; este sigur: fiind destinat lucrului n reele de calculatoare, la realizarea sistemului Java s-a avut n vedere necesitatea ca programele s nu poat aduce daune calculatoarelor pe care ruleaz, cum ar fi accesul neautorizat la informaie sau chiar distrugerea acesteia; este portabil, adic programul poate fi mutat de pe un calculator pe altul, de alt tip hardware i/sau cu alt sistem de operare; este compilat i interpretat: programul surs, scris n limbajul Java, este translatat de ctre compilatorul Java ntr-un program intermediar sub form de cod de octei (engleza: bytecode). n timpul execuiei, acest cod de octei este interpretat de ctre maina virtual Java, care conine un interpretor; este neutru fa de arhitectur: codul de octei generat de compilatorul Java nu depinde de arhitectura echipamentului pe care acesta va fi executat, deoarece el nu este executat direct de ctre procesorul hardware al acestui echipament, ci este interpretat de ctre maina virtual Java; permite programarea concurent: n limbajul Java se pot scrie programe cu mai multe fire de execuie (engleza: multithreading), care pot fi executate simultan i sincronizate; este dinamic, deoarece legarea ntre ele a claselor i obiectelor nu se face static (la compilare), ci dinamic (n momentul execuiei); este distribuit, adic permite realizarea de programe utilizabile n reele heterogene (care conin calculatoare de tipuri diferite);

n enumerarea de mai sus, care nu este nicidecum complet apar, probabil, i unii termeni care v sunt, deocamdata, neclari sau necunoscui. Unii din aceti termeni vor fi clarificai chiar n acest capitol, alii - n capitolele urmtoare. Atenie! Dei sintaxa limbajului Java se aseamn cu cea a limbajelor C sau C++, Java nu este C. Pe parcursul leciilor urmtoare vom atrage atenia programatorilor de C/C++ asupra principalelor deosebiri dintre Java i aceste limbaje.

Simplificri fcute n Java fa de C/C++


Dei sintaxa limbajului Java a fost inspirat de cea a limbajelor C i C++, autorii limbajului Java au eliminat acele aspecte care produceau dificulti programatorilor, constituind surse de erori i confuzii. Dintre acestea menionm:

reducerea numrului de tipuri de date primitive prin eliminarea tipurilor fr semn (unsigned); introducerea tipului de date boolean, astfel nct datele logice s nu se mai confunde cu cele ntregi; irurile de caractere nu mai sunt tablouri, ci obiecte ale clasei String; tablourile sunt ele nsele obiecte; n timpul execuiei se verific dac indicele se ncadreaz n dimensiunea tabloului i se genereaz o excepie n caz contrar; 8

Programarea orientata pe obiecte n limbajul Java


s-au eliminat pointerii i operaiile cu pointeri, meninndu-se numai tipul referin din C++; s-a renunat la suprancrcarea operatorilor; limbajul este strict tipizat, adic se verific att la compilare, ct i n timpul execuiei (n operaiile de atribuire i de calcul i la transferul de parametri ctre subprograme), corectitudinea tipurilor de date utilizate i se semnaleaz excepiile; s-a renunat la motenirea multipl (care exist n C++), meninndu-se numai motenirea simpl. Ca urmare, toate clasele formeaz o ierarhie unic, avand ca radacin clasa Object; distrugerea obiectelor care nu mai sunt necesare se face automat, de ctre un "colector de reziduuri" (n englez: garbage collector), deci nu mai trebuie fcut prin program.

Neutralitatea arhitectural
n mod ideal, un program sub forma de cod de octei (bytecode) ar trebui s poat fi executat pe orice tip de calculator, indiferent de arhitectura acestuia, tipul procesorului, capacitatea de memorie etc, deci s fie independent de platform. n realitate, calculatorul trebuie s aib o memorie disponibil suficient de mare pentru a conine cel puin maina virtual Java (JVM). Apare deci o contradicie: pentru a executa programe mari, JVM trebuie s aiba o memorie mare, deci i calculatorul gazd trebuie s aib o memorie mare. Pe de alt parte, pentru a putea executa programe Java pe calculatoare de capacitate foarte mic (cum sunt cele ncorporate n diverse aparate electrocasnice, aparate de automatizare etc) este necesar o JVM cu memorie mic. Un program destinat unui calculator mic poate fi executat i pe unul cu memorie mare, dar nu i invers. Aceasta a condus la necesitatea de a avea mai multe "medii de execuie Java", n funcie de dimensiunile i destinaia calculatorului pe care se instaleaz, iar ntre caracteristicile programelor Java nu se mai mentioneaza "independena de platform" ci "neutralitatea fa de arhitectur". Neutralitatea fa de arhitectur nseamn, de fapt, c arhitectura mainii virtuale Java, care este ea nsi un calculator abstract (organizarea memoriei, conveniile de reprezentare a datelor n memorie, setul de instruciuni al procesorului etc) nu depinde de arhitectura calculatorului pe care aceasta se instaleaza. ntrucat codul de octei obinut din compilarea programului Java nu se execut nemijlocit pe calculatorul gazd, ci pe maina virtual Java, el poate fi acelai pe orice calculator pe care este instalata o astfel de main, deci este neutru fa de arhitectura calculatorului gazda. Este nsa necesar s precizm c maina virtual Java nsi este un produs software, care este instalat i funcioneaz direct pe calculatorul gazd, deci respect conveniile arhitecturale ale acestuia. n consecin, pe fiecare tip de calculator trebuie instalat o main virtual Java corespunztoare. Se poate, deci, vorbi de neutralitatea fa de arhitectura a programelor Java, dar nu i a mainii virtuale Java.

Severin Bumbaru

Calculatoare abstracte. Modelul von Neuman


Conceptul de calculator abstract
Sistemele de calcul reale sunt extrem de complicate, astfel c cel care dorete s le cunoasc n detaliu are nevoie de cunotine aprofundate n domenile tehnice crora le aparin echipamentele care le compun (electronica, electrotehnica, mecanica etc.). Din fericire, asemenea cunostine nu sunt absolut necesare pentru a programa un calculator, dei uneori pot fi utile. n realitate, programatorul nu scrie programul pentru calculatorul real, ci pentru un calculator abstract, dat sub forma unui model care elimina detaliile, pstrnd numai acele elemente care sunt necesare pentru limbajul de programare folosit. Asa dar, la stabilirea schemei calculatorului abstract, trebuie s se in seama att de calculatorul real pe care l modeleaz, ct i de limbajul de programare folosit. Este deci posibil ca, pentru acelai calculator concret, s existe mai multe modele abstracte, folosite pentru diferite limbaje. Este ns, de asemenea, posibil ca pentru mai multe calculatoare concrete s se foloseasc acelai calculator abstract, diferena ntre ele manifestandu-se prin acele detalii, care se pierd la abstractizare. n general, un calculator abstract are un set de instruciuni, un set de regitri i un model de memorie.

Modelul de memorie
Memoria calculatorului abstract este o succesiune de locaii de memorie. Fiecare locaie de memorie este privit ca o "caset" care conine un numar fix de cifre binare (bii). Numrul de ordine al locaiei (care arat poziia acesteia n cadrul memoriei) se numeste adres. n consecin, memoria calculatorului este adresabil. Locaia este cea mai mic zon de memorie care poate fi citit sau nregistrat. La orice operaie de citire/scriere se transfer un numar ntreg de locaii. n principiu, modelele de memorie pot s difere ntre ele prin numrul de bii coninut n locaia de memorie (prin "lungimea" locaiei). Totui, la majoritatea calculatoarelor actuale, locaia de memorie conine opt bii i se numete octet (engl.: byte). Iat un exemplu de model de memorie organizat pe octei:

10

Programarea orientata pe obiecte n limbajul Java

n acest model, n coloana din stnga apar adresele locaiilor. Le-am scris n sistemul de numeratie zecimal, pentru a fi mai uor de urmrit. De obicei ns, ele se exprim n sistemul binar, sau n cel hexazecimal. Numrul de locaii este ns n realitate, desigur, mult mai mare, exprimandu-se de regul n megaoctei. n coloana din dreapta au fost reprezentate locaiile de memorie, coninnd fiecare exact opt cifre binare. Coninutul a fost aici ales, desigur, arbitrar.

Capacitatea de memorie
Capacitatea memoriei calculatorului se poate exprima n bii. Totui, ntruct majoritatea calculatoarelor moderne au memoria organizat pe octei, se obisnuiete s se foloseasc drept unitate de masur octetul sau multiplii acestuia. Reamintim c nu trebuie sa confundam un bit cu un octet (engl.: byte). Primul este unitatea binara, exprimndu-se prin cifrele binare 0 si 1. Numele este o prescurtare de la denumirea din englez a unitii binare: binary unit, de la care s-au luat nceputul i sfritul. Un octet (byte) este ns un numr format din 8 cifre binare, deci din 8 bii. Multiplii octetului sunt kilooctetul, megaoctetul, gigaoctetul si teraoctetul. Avnd n vedere c sistemul de numeraie folosit n memoria intern a calculatorului este cel binar, pentru multipli nu s-au folosit puterile lui 10, ca n sistemul zecimal, ci puterile lui 2 cele mai apropiate de acestea: 1 kilooctet (engl. kilobyte) = 1024 octei = 210 octei, prescurtat K sau Ko sau KB ; 1 megaoctet (engl. megabyte) = 1024 kilooctei = 1'048'576 octei, prescurtat M sau Mo sau MB ; 1 gigaoctet (engl.: gigabyte) = 1024 megaoctei = 1'073'741'824 octei, prescurtat G sau Go sau GB ; 1 teraoctet (engl: terabyte) = 1024 gigaoctei =1'099'511'627'776 octei, prescurtat T sau To sau TB ;

Procesorul abstract
Procesorul abstract este caracterizat printr-un set de regitri i un set de instruciuni. Regitrii procesorului sunt, la fel ca locaiile de memorie, dispozitive n care se memoreaz numere binare de lungime fix, specific procesorului respectiv. Aceasta este, n general un multiplu de 8, deci ntr-un registru pot fi "ncrcai" un numr ntreg de octei.

11

Severin Bumbaru Instruciunile sunt codificate intern tot prin numere binare, formate din cel puin dou pri: un cod al operaiei i adresa operandului (uneori adresele operanzilor). Exemple de operaii: - ncrcarea, adic transferul unui operand din memorie ntr-un registru; instruciunea conine codul operaiei de ncarcare, adresa din memorie a operandului i numrul registrului n care se ncarc; - memorarea, adic inregistrarea la o anumit adres din memorie a coninutului unui registru; se dau: codul operaiei, numrul registrului de origine i adresa din memorie a destinaiei; - operaii de calcul (aritmetice sau logice), care se efectueaza fie ntre operanzii din registre, fie ntre un operand dintr-un registru i unul din memorie. n instruciune se dau codul operaiei i numerele registrelor ntre care se face aceasta, sau numrul unui registru i o adres din memorie. Rezultatul operaiei rmane, de regul, ntr-un registru; - instruciuni de salt, prin care se modific fluxul normal (secvenial) al executrii instruciunilor. n mod normal, dup ce s-a executat o instruciune din program, se trece la cea imediat urmtoare, n ordinea n care acestea sunt situate n memorie. Instruciunea de salt indic trecerea la executarea unei instruciuni situat la o alt adres din memorie. Fiecare instruciune este nregistrat n memorie pe o lungime unul sau mai multi octei.

Maina von Neumann


Matematicianul american de origine maghiar John von Neumann a publicat n anul 1945 prima descriere a unui calculator cu program memorat, care ar fi putut fi construit. Aceast descriere a avut o influen foarte mare asupra evoluiei ulterioare a calculatoarelor i este cunoscut sub numele "maina von Neumann". Maina von Neumann este format din: - o unitate aritmetic i logic; - o unitate de control; - o unitate de intrare/ieire; - o unitate de memorie. Unitatea aritmetic i logic i unitatea de control formeaz mpreun procesorul (unitatea central) de la calculatoarele actuale.

12

Programarea orientata pe obiecte n limbajul Java Maina von Neuman lucreaz numai cu numere ntregi. Unitatea aritmetic i logic efectueaz operaiile de calcul (adunare, scdere, nmulire, mprire ntreag, valoare absoluta). Ea conine doi regitri, dintre care unul se numeste registru acumulator. Orice operaie se face folosind regitrii unitii centrale: - ncrcarea este transferul unui operand din memorie n unul din registri; - memorarea este transferul continutului registrului acumulator la o anumit adres din memorie; - operaiile de calcul (adunare, scdere, nmulire, mprire) se fac ntre numerele din cei doi regitri, iar rezultatul rmne n registrul acumulator; - operaiile de intrare/ieire se fac ntre registrul acumulator i unitatea de intrare/ieire. Dac, de exemplu, dorim s se efectueze calculul c=a+b, aceasta nseamn c se vor executa urmtoarele instructiuni: ncarc n registrul A operandul situat n memorie la adresa a; ncarc n registrul R operandul situat n memorie la adresa b; adun operanzii din cei doi regitri (rezultatul rmne n registrul acumulator A); memoreaz coninutul registrului A la adresa c din memorie. Bineneles, aceste instruciuni vor fi reprezentate n cod binar, adica att operaiile, ct i adresele din memorie vor fi exprimate prin numere n sistemul de numeraie cu baza 2. Caracteristica principal a mainii von Neuman este ca funcionarea ei este un proces secvenial: la un moment dat se execut o singur instruciune, iar executarea unei instruciuni poate s nceap numai dup ce s-a ncheiat executarea celei precedente. n toate operaiile particip unitatea central i regitrii acesteia. Primele generaii de calculatoare construite au respectat destul de fidel modelul mainii von Neuman. Chiar dac, ulterior, evoluia calculatoarelor i a sistemelor de operare a suferit abateri de la acest model (s-a introdus accesul direct la memorie al unitilor de intrare/ieire, au aparut calculatoare cu mai multe procesoare, care funcioneaz n paralel, etc.), limbajele de programare au continuat, n majoritatea lor, s fie fcute pentru calculatoare abstracte de tip von Neumann. Exemple bine cunoscute de astfel de limbaje sunt Fortran, Cobol, Basic, Pascal, C, C++ .a. Limbajul Java face parte din categoria limbajelor pentru procese concurente, n sensul c el permite s existe n paralel mai multe fire de executie, ale cror operaii pot, n principiu, s se realizeze pe procesoare diferite. Este unul din motivele pentru care acest limbaj nu mai are la baz maina von Neumann, ci pentru el a fost conceput un alt calculator abstract, numit maina virtual Java.

Mediul de execuie Java


Mediul de execuie Java, numit n englez Java Runtime Environment, conine maina virtual Java i un nucleu de clase Java. Acest mediu trebuie instalat pe orice calculator, pe care se dorete s se execute programe Java. Maina virtual Java (englez: JVM - Java Virtual Machine) este, n general, implementat software sub forma unui produs program adecvat calculatorului pe care acesta se instaleaz.

13

Severin Bumbaru Ideea de baz a limbajului i tehnologiei Java, este ca - pe baza acestora - s se poat creea produse software neutre fa de arhitectura sistemului de calcul, deci care s poat fi executate pe orice echipament, de la produse de uz casnic comandate numeric (televizoare, telefoane, maini de splat, frigidere, etc) pan la supercalculatoare. Ea se exprim prin sloganul "Write Once, Run Anywhere" (scrie o singur dat i ruleaz oriunde), care arat c un program, dup ce a fost scris i compilat, poate fi executat (rulat) pe orice calculator. Pentru realizarea acestui obiectiv, s-a decis ca n tehnologia Java portabilitatea programelor sa se realizeze la nivel de cod de octei (bytecode), adic sub forma de cod binar destinat unui calculator abstract, numit maina virtual Java. n acest scop:

s-a ntocmit o descriere riguroas numit specificaia mainii virtuale Java, (The Java Virtual Machine Specification), n care se prezint n detaliu arhitectura i funcionarea acestei maini; pe fiecare calculator, pe care se execut programe Java, trebuie sa existe o implementare (o realizare concret sub forma de produs software sau hardware) a mainii virtuale Java, care execut efectiv programul dat sub forma de cod de octei.

Nucleul de clase: Limbajul Java este orientat pe obiecte. Orice program este un ansamblu de clase i de obiecte, care sunt instanieri ale claselor. n mediul de execuie Java este inclus i o bibliotec de clase predefinite. Este vorba, n special, de acele clase care asigur comunicarea dintre programul Java i sistemul de operare al calculatorului gazd. Dei interfaa acestor clase cu programul Java nu depinde de tipul calculatorului gazd, implementarea lor este dependenta de platform, la fel ca i cea a mainii virtuale Java.

Implementarea mainii virtuale Java


De regul, arhitectura i setul de instruciuni al calculatorului, pe care se execut un program Java, difer de cele ale mainii virtuale Java. n consecin, codul de octei generat de compilatorul Java nu poate fi executat nemijlocit de procesorul (procesoarele) calculatorului pe care acesta se execut. Dac este realizat software (aa cum se ntampl n majoritatea cazurilor), maina virtual Java este ea nsi un produs program, care este scris i compilat special pentru tipul de calculator pe care se instaleaz, deci folosete setul de instruciuni nativ al acestuia. Acest produs program trebuie s respecte specificaia mainii virtuale Java, dar realizarea concret depinde de tipul de calculator pe care se instaleaz. Mai mult, pentru acelai calculator pot fi realizate mai multe maini virtuale Java, care toate respecta specificaia, dar difer ntre ele prin modul de realizare. n principiu, componenta principal a mainii virtuale Java este un interpretor, adic un program care parcurge instruciunile coninute n codul de octei Java din memoria mainii virtuale Java i le convertete n instruciuni native, care pot fi executate de procesorul calculatorului gazd. Aceast conversie necesit un anumit timp, din care cauz durata de execuie a unui program interpretat este intotdeauna mai mare dect a unuia compilat direct n codul nativ. Din aceast cauz, principala deficien care se semnala la primele implementri ale mainii virtuale Java era c durata de execuie a programelor era sensibil mai mare dect a celor scrise in limbaje "tradiionale" compilate, cum ar fi C, C++, Pascal, Fortran etc.

14

Programarea orientata pe obiecte n limbajul Java Implementrile moderne ale mainii virtuale Java se caracterizeaz prin mrirea sensibil a vitezei de executie, care se apropie deja de cea a programelor compilate. Aceasta se realizeaz, n special, prin introducerea unei compilri "just in time": codul de octei este compilat, n momentul execuiei, in cod nativ pentru calculatorul gazd i abia apoi este executat. Desigur c cea mai eficient reducere a duratei de execuie se produce atunci cnd maina virtual Java este implementata hardware, astfel nct codul de octeti Java (bztecode) este cod nativ al acestei maini. n acest caz, durata de execuie a programului este aceeai cu cea a unui program compilat tradiional.

Platforma Java 2
Un mare avantaj al programatorilor in limbajul Java este c au la dispoziie un set puternic de instrumente de dezvoltare a programelor: compilator, depanator, bibliotec de clase, documentaie etc. La nceput, acesta s-a numit "setul de dezvoltare Java" (n engleza: JDK Java Development Kit). Au existat mai multe versiuni succesive: JDK 1.0, JDK 1.1, JDK 1.2 aparute, respetiv, in anii 1996, 1997 si 1998. O component important pentru programatori a setului de dezvoltare Java este "Interfaa pentru programarea de aplicaii" (API - Application Programming Interface). Aceasta este acea parte din documentaie, n care se d specificaia claselor, adic descrierea riguroas a modului n care clas respectiv este vazut de ctre programul de aplicaie. Trecerea de la JDK 1.0 la JDK 1.1 a reprezentat o revizuire de concepie, n special n ce privete API, astfel c numeroase clase existente n JDK 1.0 au devenit depreciate n JDK 1.1, fiind nlocuite cu clase noi. La trecerea de la JDK 1.1 la JDK 1.2 nu a mai aprut o astfel de situaie, dar numrul de clase a fost sensibil mrit. n consecin, nu se mai recomanda folosirea n programele Java a JDK 1.0. n anul 1998 s-a introdus denumirea de "Platforma Java 2", care se refer la ntregul complex de specificaii, resurse software i documentaie puse la dispoziie programatorilor i utilizatorilor de Java. Ca urmare, JDK 1.2 a fost redenumit "Java 2 Platform SDK, SE v1.2" (SDK - Software Development Kit, SE - Standard Edition, v - version). In prezent, se utilizeaz deja "Java 2 Platform SDK, SE v1.4". Platforma Java 2 se ofer n prezent de firma Sun Microsystems n trei variante:

Java 2 Platform, Standard Edition (J2SE) - pentru dezvoltarea aplicaiilor i miniaplicaiilor obinuite (de pe staiile de lucru); Java 2 Platform, Enterprise Edition (J2EE) - pentru dezvoltarea de aplicaii pentru serverele de ntreprindere; Java 2 Platform, MicroEdition (J2ME) - pentru utilizarea pe calculatoare de capacitate foarte mic, ncorporate n echipamente electrice sau electronice.

n cursul nostru vom folosi J2SE, iar din documentaia oferit de firma Sun vom folosi n special documentaia API pentru aceast platform.

15

Severin Bumbaru

Tehnologia Java
Datorit caracteristicilor sale, Java nu mai poate fi considerat doar un limbaj de programare asociat cu o platform de dezvoltare de aplicaii, ci a devenit o veritabil tehnologie software. Cnd s-a trecut de la programarea procedural la programarea orientat pe obiecte, s-a artat c aceasta poate fi comparat cu trecerea de la fabricaia artizanal la cea industrial: programul nu mai trebuie creat "de la zero", ci poate fi conceput ca un ansamblu de componente (obiecte) "prefabricate". Programatorii se pot mpri n dou categorii: cei care creeaza clasele de obiecte i le ofer "pe piaa" i cei care, din aceste componente, creaz aplicaii (produse software finite) oferite utilizatorilor. Limbajele orientate pe obiecte existente anterior (C++, Object Pascal, etc) nu au reuit, totui, s stea la baza unei astfel de "industrializri". Cauza principal este c, fiind limbaje compilate, nu puteau sta la baza producerii unor componente utilizabile pe orice platform hardware i sub orice sistem de operare i - deci - nu puteau fi folosite fara dificulti ntr-o reea de calculatoare eterogen. Dei a aprut recent, rspndirea foarte rapid a platformei Java se datorete tocmai faptului c apariia ei a corespuns cu dezvoltarea ampl a reelelor de calculatoare, n special a Internet-ului. Un numr foarte mare de firme productoare de software i numeroi programatori individuali din intreaga lume s-au angajat n dezvoltarea de clase, componente i aplicaii programate n Java. Numrul de clase din Java SDK crete continuu, fiind utilizabile n domenii din ce n ce mai variate: prelucrri de date numerice, prelucrri de texte, interfaa grafic cu utilizatorul, lucrul cu fiiere, comunicatii n reele, legtura cu baze de date, securitatea datelor, calcul distribuit, etc. n afar de clasele din SDK (puse la dispoziie de firma Sun Microsystems), programatorii pot folosi un numar mare de clase i componente Java ("Java beans") oferite de alte firme, multe din ele disponibile liber pe Internet. Ca urmare, se poate spune c baza tehnologic a programrii n Java crete exponenial. Limbajul Java n sine este simplu i uor de nvat. Fora tehnologiei Java const nu n limbajul folosit, ci n numrul din ce n ce mai mare de clase reutilizabile, pe care programatorii le au la dispoziie, i n faptul c programele realizate pot fi utilizabile practic oriunde, fr a fi necesar sa fie refcute cnd se trece de la un tip de calculator la altul. Aceasta presupune ns, ca n orice alta tehnologie, i necesitatea unei standardizri, a introducerii unor norme pe care s le respecte ntreaga comunitate a programatorilor. Acest rol il ndeplinesc acum specificatiile: specificatia limbajului Java, specificatia mainii virtuale Java, Java API, etc. ntreinerea i dezvoltarea acestor specificaii este facut, deocamdat, de firma Sun Microsystems. Nu este exclus ca, cu timpul, acest rol sa fie conferit unui organism de standardizare internaional, pentru a nu se creea avantaje unui anumit productor de software. Dintre resursele cele mai importante puse la dispoziia programatorilor de tehnologia Java, menionm:

Java API - specificaia claselor interfeei de programare de aplicaii Java i bibliotecile care implementeaz aceste clase;

16

Programarea orientata pe obiecte n limbajul Java

JFC (Java Foundation Classes) - biblioteca de clase pentru realizarea unor interfee grafice cu utilizatorul independente de sistemul de operare utilizat. ncepnd cu Platforma Java 2 este inclus n Java API; Java Beans - o arhitectur de componente reutilizabile, neutre fa de tipul calculatorului i sistemul de operare, care pot fi utilizate n medii de programare vizuale. Se ofera i instrumente de dezvoltare pentru astfel de componente: BDK (Beans Development Kit) pentru dezvoltarea de componente, Java Plug-in (pentru legtura cu Active-X de la Microsoft), JAF (JavaBeans Activation Framework) pentru identificarea, localizarea componentelor i altele; JDBC (Java Data Base Connectivity) - componente pentru legtura cu baze de date; JINI - tehnologie bazat pe Java, pentru asigurarea conectivitii echipamentelor n reele de calculatoare; tehnologia agenilor software - produse software care se pot deplasa de la un calculator la altul ntr-o reea i pot ndeplini n mod autonom pe calculatorul de destinaie sarcinile pentru care au fost trimise. Platforma Java este foarte convenabil pentru crearea i utilizarea agenilor n reele eterogene. Exemple sunt tehnologia agleilor oferita de firma IBM, cadrul de dezvoltare a agentilor Java Java Agents Framework (JAF) de la Universitatea din Massachutess, etc. i multe altele.

Exist, de asemenea, numeroase medii de programare pentru Java, oferite de diverse firme, cum sunt:

Forte for Java - un mediu de programare vizual, realizat si oferit gratuit pentru utilizri necomerciale de firma Sun MicroSystems. WebGain VisualCafe - un mediu de programare vizual, realizat de firma WebGain; Borland JBuilder - un mediu de programare vizual, realizat de firma Borland; VisualAge for Java - un mediu de programare vizual realizat de firma IBM; Visual J# .NET - un mediu de dezvoltare vizual al firmei Microsoft i altele.

n acest curs, ne vom rezuma la nsuirea limbajului Java i a unor componente din Java API, folosind numai Java 2 SDK, Standard Edition.

Scurt istoric al platformei Java


n anul 1990, un grup de programatori de la firma Sun Microsystems, ntre care i James Gosling, lucrau la proiectul "Green", al crui obiectiv era realizarea de software pentru aparate electrocasnice cu comanda numeric (maini de splat, frigidere, cuptoare cu microunde, telefoane, televizoare etc.). S-a ncercat, pentru nceput, s se foloseasc pentru programare limbajul C++, dar s-a constatat rapid c acesta nu corespundea scopului urmrit, deoarece programele obinute erau prea mari i nu erau portabile la nivel de cod binar. S-a ajuns astfel la concluzia c este necesar un nou limbaj de programare, care s fie simplu, uor de nvat i de utilizat, iar programul binar obinut prin compilare s poat fi rulat pe calculatoare de capacitate mic i cu arhitecturi diferite. Acest nou limbaj a fost numit Oak (n romaneste "nuc"; se spune c atunci cnd a trebuit sa-i dea un nume, Gosling s-a uitat pe fereastr i a vzut un nuc n faa ei), prima lui variant fiind gata la mijlocul lui 1991.

17

Severin Bumbaru Desi s-a realizat o cantitate mare de software, s-a constatat c, n vremea respectiv, orientarea ctre aparatura electrocasnic ("de consum"), nu corespundea nc cerinelor pieei. Dup o serie de alte ncercri, s-a ajuns la concluzia c cea mai buna utilizare a noului limbaj este realizarea de software pentru reelele de calculatoare. ntrucat denumirea "Oak" nu a putut fi nregistrat oficial, n timpul unei discuii "la o ceac de cafea", autorii au decis sa-i dea limbajului numele Java, care a fost i nregistrat ca marc comerciala (TM - Trade Mark). Iat dece acest nume apare frecvent scris sub forma JavaTM. Prima utilizare comercial a acestui limbaj a fost includerea unui interpretor Java n navigatorul (browserul) de Web al firmei Netscape. Introducerea de appleturi (miniaplicaii) Java n paginile de Web a permis ca acestea sa devina interactive, deci s capete o component dinamic. In continuare, folosirea limbajului i apoi a tehnologiei Java a cptat o dezvoltare exponenial. Iat cteva date: - ianuarie 1996 - lansarea JDK 1.0; - decembrie 1996 - lansarea JDK 1.1, versiunea beta; - februarie 1997 - lansarea versiunii finale a JDK 1.1; - martie 1998 - se lanseaz JFC (Java Foundation Classes); - decembrie 1998 - se lanseaz "Java 2 Platform"; - iunie 1999 - se anunta trei ediii ale platformei Java 2: J2SE, J2EE si J2ME. - mai 2000 - se lanseaz platforma J2SE v 1.3. - februarie 2002 - este lansat platforma J2SE v 1.4

Introducere n programarea orientat pe obiecte


Programarea orientat pe obiecte (POO) este o form de programare, n care programatorii definesc clase de obiecte, iar programul conine un ansamblu de clase i obiecte, care comunic ntre ele prin mesaje. Clasa este o extensie a conceptului de tip de date i conine o structur de date, mpreun cu metodele (functiile) care se aplica acestor date. Obiectul este o instantiere (o instanta) a clasei. In acelasi program se pot folosi mai multe obiecte apartinand aceleeasi clase, sau unor clase diferite. Fiecare obiect se caracterizeaza prin stare si comportament. Starea obiectului depinde de datele pe care acesta le contine, in timp ce comportamentul este dat de metodele clasei respective. In general, comunicarea prin mesaje consta in invocarea de metode. Daca obiectul a invoca o metoda a obiectului b, aceasta poate avea ca efect modificarea starii obiectului b (adica modificarea unor date continute in structura de date a lui b) si/sau poate primi o valoare intoarsa de metoda respectiva. Se considera ca, prin invocarea metodei, obiectul a a transmis un mesaj obiectului b, ceeace a provocat din partea acestuia un anumit raspuns (deci b a manifestat o anumita comportare).

18

Programarea orientata pe obiecte n limbajul Java Exemplu Sa consideram clasa poligoanelor regulate. Structura de date contine doua variabile: numarul de laturi (care este o variabila de tip intreg) si lungimea unei laturi (care este o variabila de tip real). Metodele pot fi, de exemplu, mici programe (functii) prin care se calculeaza aria, perimetrul, apotema, raza cercului circumscris etc. Pot exista si metode prin care se modifica numarul de laturi sau lungimea laturii, deci se modifica starea poligonului. Clasa are un nume (de ex. PoligonRegulat). Pot exista, evident, mai multe instante (obiecte) ale acestei clase, care toate sunt poligoane regulate, dar difera intre ele prin numarul de laturi si/sau prin lungimea laturii. Fie p un PoligonRegulat cu 4 laturi de lungime 3.5. Invocarea metodei p.arie() are ca efect calcularea functiei arie()pentru obiectul p, deci se va obtine ca raspuns valoarea 12.25. Prin invocarea acestei metode, s-a transmis obiectului p mesajul ca se cere calcularea ariei, iar comportamentul acestui obiect a constat in punerea in executie a metodei invocate si intoarcerea valorii calculate a ariei. Valoarea intoarsa depinde, evident, de starea in care se gaseste p in momentul invocarii metodei, adica de numarul de laturi si de lungimea laturii. Atat variabilele, cat si metodele pot fi statice sau nestatice. Variabilele statice (ale clasei) apartin clasei, adica au aceeasi valoare pentru toate obiectele clasei respective. Variabilele de instanta (nestatice) apartin obiectului (instantei), deci au valori diferite de la un obiect la altul.

De exemplu, daca clasa Pasare contine variabila numarAripi, aceasta variabila va avea valoarea 2 pentru toate pasarile, deci pentru toate instantele clasei respective, fiind o variabila statica sau a clasei. In schimb, variabila varsta va avea valori diferite pentru fiecare pasare, deci este o variabila a instantei (nestatica). Metodele statice (ale clasei) pot folosi numai variabilele statice ale clasei respective, in timp ce metodele nestatice pot folosi atat variabilele statice, cat si pe cele ale instantei. Din punct de vedere al modului de acces, datele si metodele unei clase pot fi publice sau private. Cele publice sunt accesibile din orice alta clasa, in timp ce cele private sunt accesibile numai din clasa careia ii apartin.

Tipuri de produse software scrise n Java


Limbajul Java este folosit cel mai frecvent pentru a scrie urmatoarele trei tipuri de programe: aplicaie - este un produs software care se instaleaz pe un anumit calculator i funcioneaz direct sub controlul sistemului de operare, avnd acces la toate resursele calculatorului respectiv. Una din clasele aplicaiei trebuie sa conin metoda principal, cu care ncepe execuia aplicatiei. Aceast metod se numete main i are forma:

19

Severin Bumbaru
public static void main(String args[]) { // corpul metodei }

applet (miniaplicaie) - este un program care se transmite sub form de cod de octei (bytecode) prin reeaua de calculatoare i este executat n cadrul unui navigator (browser) de Web, fr a avea acces la fiierele sau sistemul de intrare/ieire al calculatorului pe care se execut; servlet - un program care se execut pe un server dein reea.

Un ablon de aplicaie simpl n limbajul Java


n prima parte a acestui curs, n aplicaiile fcute la curs i la laborator vom utiliza urmtorul ablon:
class <nume_clasa> { public static void main(String args[]) { // corpul metodei main } }

Prile scrise cu negru (inclusiv parantezele i acoladele) le vom considera obligatorii, iar cele scrise cursiv cu rou sunt la latitudinea programatorului.
<nume_clasa> - este numele clasei, fiind ales de ctre programator cu respectarea urmtoarelor condiii: - numele clasei trebuie s nceap cu o liter i este format numai din litere, cifre i eventual - liniua de subliniere; - prin convenie (dei aceasta nu este o regul de sintax), numele de clas ncepe ntotdeauna cu o majuscul; - n cazul numelor compuse din mai multe cuvinte, fiecare cuvnt ncepe cu majuscul; - lungimea numelui nu este limitat, dar nu este recomandabil sa fie prea mare. // corpul metodei main -

este o succesiune de instruciuni i comentarii care respect

sintaxa limbajului Java.

Prile componente ale acestui ablon pot fi explicate pe baza cunotintelor pe care le avem deja despre programarea orientat pe obiecte i despre limbajele de programare. - descrierea (definirea) unei clase ncepe prin cuvantul class, urmat de numele clasei; - corpul clasei este cuprins ntre acolade { ... } - n cazul nostru, corpul clasei conine o singura metod; - metoda are forma unei funcii, care se numete main i are un singur argument numit args. Vom vedea ulterior c acesta este un tablou de obiecte din clasa String, adic un tablou de iruri de caractere. Tot atunci vom vedea c acest argument servete pentru preluarea parametrilor din linia de comand;

20

Programarea orientata pe obiecte n limbajul Java - metoda main (metoda principal) este public, adic poate fi utilizat de obiecte din alta clas (n cazul nostru, ea este apelat de maina virtual Java la punerea n execuie a aplicaiei); -metoda main este static, deci apartine clasei i nu instanelor acestei clase; - privit ca o funcie, metoda main trebuie, n principiu, s ntoarc o valoare. n acest caz, metoda nu ntoarce o valoare, deci tipul valorii ntoarse este void (loc gol, lips).

Exemplu de aplicaie simpl


Dm aici un exemplu de aplicaie simpl scris n limbajul Java. Aplicaia este o clas Java, care conine metoda main. Exemplul 1 Considerm urmtorul program:

class PrimaAplicatie { public static void main(String args[]) { System.out.println("Prima noastra aplicatie a reusit!"); } }

Remarcm urmatoarele:

programul respect ablonul de aplicaie simpl adoptat de noi; numele clasei este PrimaAplicatie; corpul clasei este constituit dintr-o singur instruciune, prin care este invocat metoda println a obiectului out din clasa System.

Dei nu cunoatem nc modul n care se definesc i se utilizeaz clasele i obiectele n limbajul Java, menionam aici c instruciunea de forma
System.out.println(<sir_de_caractere>);

are ca efect afiarea pe ecran a irului primit ca argument. n limbajul Java, instruciunile simple se termin cu caracterul ; (punct i virgul). Efectul executrii acestei aplicaii este c se afieaz pe ecran textul Prima noastra
aplicatie a reusit!

Editarea, compilarea i executarea aplicaiilor Java


Fiecare aplicaie Java parcurge urmtoarele etape: editarea programului surs, compilarea i eliminarea erorilor sintactice, testarea i eliminarea erorilor de concepie, executarea. n acest scop, pe calculatorul pe care lucrai trebuie sa existe un set de dezvoltare Java, preferabil Java 2 Platform SDK, Standard Edition. Pentru a dezvolta aplicaii Java:

21

Severin Bumbaru

dac lucrati sub Windows, vei folosi o fereastr MS-DOS (Command Prompt); dac lucrai sub Linux sau Unix, vei folosi o fereastr de X-Terminal. Sub Linux v recomandm sa folosii KDE, sub care s selectai din bara de scule pictograma "Terminal Emulation", sau din meniul Applications sa alegeti optiunea "X Terminal".

Editarea fisierului surs


Pentru nceput, vom considera c aplicaia este constituit dintr-o singur clas, care respect ablonul indicat anterior. Programul surs pentru aceast clas va fi editat sub forma unui fiier separat, care are acelai nume cu clasa i are extensia .java. De exemplu, clasa PrimaAplicatie va fi editat sub forma unui fiier de text cu numele PrimaAplicatie.java. Este preferabil s punei acest fiier ntr-un subdirector separat. De exemplu puteti crea un subdirector numit javaLab, n care s creai un alt subdirector numit sapt1, n care sa punei fiierul PrimaAplicatie.java. Pentru crearea fiierului se va folosi un editor de text simplu, care genereaz numai text neformatat, de exemplu "Notepad" daca lucrai sub Windows sau sub Linux cu WinLinux99, respectiv "Text Editor" sau "Advanced Editor", daca lucrai sub Linux cu KDE.

Compilarea i eliminarea erorilor semnalate de compilator


Translatarea programului surs n program sub forma de cod de octei (bytecode) se face cu ajutorul compilatorului Java, numit javac. n acest scop, va deplasai n subdirectorul n care se gsete programul surs pe care dorii s-l compilai i dai comanda
javac <fisier_sursa>

De exemplu, pentru a compila fiierul care conine clasa PrimaAplicatie mergeti n subdirectorul n care se gseste fiierul respectiv i dai comanda
javac PrimaAplicatie.java

Dup ce ai dat aceast comand, vei obine unul din urmtoarele rezultate: 1. Pe ecran apare din nou promptul sistemului de operare, fr a se afia un mesaj de eroare. n acest caz, compilarea a decurs normal, iar dac dai comanda dir vei constata ca n subdirectorul curent a aprut un nou fiier, care poart numele clasei i extensia class. Acesta este fiierul care conine bytecode-ul clasei compilate. 2. Obinei un mesaj de eroare, care indic fie c exist erori n program, care au fost sesizate de compilator, fie c exist erori n linia de comand prin care ai cerut compilarea. n ambele cazuri, este necesar s eliminai erorile i s reluai compilarea. Exemplu de utilizare corect Sa considerm ca am creat corect fiierul surs PrimaAplicatie.java, dup care dm comanda
javac PrimaAplicatie.java

Constatm c pe ecran nu apare nici un mesaj de eroare, ci apare din nou promptul sistemului de operare. Dac dm acum comanda
dir

Constatm, de asemenea, c n lista de fiiere care se afieaz apar:


PrimaAplicatie.class PrimaAplicatie.java Dintre acestea, PrimaAplicatie.java

este fiierul surs editat de noi, n timp ce

22

Programarea orientata pe obiecte n limbajul Java


PrimaAplicatie.class

este fiierul de cod de octeti rezultat n urma compilrii.

Exemplul 1 de eroare Considerm c, dup ce ai creat fiierul surs PrimaAplicatie.java, dai comanda
jamac PrimaAplicatie.java

n care numele compilatorului este introdus greit (jamac n loc de javac). Ca efect, vei obtine un mesaj prin care se arat c cuvantul jamac nu este o comand corect (nu este numele unei comenzi interne a sistemului de operare sau numele unui program executabil), de exemplu:
jamac: command not found

Exemplul 2 de eroare S considerm acum c numele fiierului surs este introdus greit, de exemplu:
javac PimaAplicatie.java

n acest caz, mesajul de eroare este


can't read: PimaAplicatie.java

adic "nu pot citi: PimaAplicatie.java", ceeace nseamn c un astfel de fiier nu exist n directorul curent. Exemplul 3 de eroare S urmrim ce se ntmpl dac introducem comanda
javac PrimaAplicatie

n care numele fiierului este corect, dar lipeste extensia. n acest caz, obtinei urmtorul mesaj:
PrimaAplicatie is an invalid option or argument. usage: javac <options> <source files>

urmat de o lista de opiuni. Aceasta nseamn c nu s-a respectat sintaxa comenzii, care cere ca comanda javac s fie urmat (eventual) de una sau mai multe opiuni din lista dat, dup care trebuie s apar numele fiierului (fiierelor) surs care trebuie compilate. Aceste nume de fiiere trebuie sa conin obligatoriu extensia java. Exemplul 4 de eroare S considerm acum c fiierul surs editat de noi conine erori. Un exemplu este fiierul PrimaAplicatie1.java, care are urmtorul coninut:
class PrimaAplicatie1 { void main(String args[]) { System.ont.println("Prima noastra aplicatie a reusit!"); } }

Compilnd acest fiier obinem urmtorul mesaj de eroare:


PrimaAplicatie1.java:3: No variable ont defined in class Java.lang.System System.ont.pintln("Prima noastra aplicatie a reusit!"); ^ Acest mesaj se interpreteaz astfel: n fiierul PrimaAplicatie1.java, linia 3, n locul marcat mai jos prin ^, apare variabila ont, care nu exist n clasa System din pachetul (biblioteca) java.lang. ntr-adevar, eroarea const n faptul c apare ont n loc de out. Observm c a fost reprodusa

linia din program n care apare eroarea i s-a marcat prin ^ locul apariiei erorii. Dac dm comanda dir, constatam c n directorul curent nu a aprut clasa PrimaAplicatie1.class. Fcnd corecia n fiier i compilnd din nou, constatm c nu mai apare nici un mesaj de eroare, deci compilatorul nu a mai sesizat nici o eroare i a creat fiierul care conine codul de octei corespunztor. Remarcm c, totui, programul nu este corect, deoarece - conform ablonului dat anterior,

23

Severin Bumbaru prima linie din metoda main trebuia s aib forma
public static void main(String args[]){

Compilatorul nu a sesizat aceast eroare deoarece, n principiu, clasa poate sa conina i o metoda main de forma celei date n acest fisier. Vom vedea, ns, c eroarea apare la executarea programului. Exerciiu ncercai s facei i alte modificri n programul surs i s constatai ce erori apar la compilare. De exemplu:

scrieti incorect cuvintele public, static, main, string, System. println; omitei unele dintre acolade sau paranteze; punei acolade sau paranteze n plus.

Putei introduce intenionat i mai multe din erorile de mai sus simultan. Compilai fiierul astfel modificat i interpretati mesajele de eroare obinute.

Executarea aplicaiei
Dac n directorul curent exist fiierul <nume_aplicaie>.class, executarea acestei aplicaii se solicit prin comanda
java <nume_aplicaie>

Remarcm c se d ca parametru numai numele clasei, fr extensia class. Efectul acestei comenzi este, fie executarea aplicatiei, fie aparitia unui mesaj de eroare de execuie. Prin comanda java se pune n execuie interpretorul mainii virtuale Java. Acest interpretor verific dac n directorul curent exist fiierul <nume_aplicaie>.class. Daca acesta exist, ncarc n memorie codul de octei pe care l conine i pune n execuie metoda public static void main(). Dac fiierul nu exist, sau dac el nu conine o astfel de metod, se semnaleaz printr-un mesaj de eroare. Exemplul 1 Considerm c a reuit compilarea fiierului corect PrimaAplicatie.java i s-a obinut astfel fiierul PrimaAplicatie.class, dup care se d comanda
java PrimaAplicatie

Ca rezultat, pe ecran apare textul


Prima noastra aplicatie a reusit!

Exemplul 2 S dm acum comanda


java PimaApicatie

n care numele clasei este dat greit. Ca rezultat, obinem mesajul de eroare
Exception in thread "main" java.lang.NoClassDefFoundError: PimaApicatie

Acest mesaj arat c nu s-a gsit definiia clasei PimaAplicatie (Eroarea constatat se deduce din numele acesteia: NoClassDefFoundError provine de la "no class definition found error", adica nu a fost gsit definiia clasei PimaApicatie. Exemplul 3 S considerm acum c am eliminat erorile de compilare din fiierul PrimaAplicatie1.java i am obinut fiierul PrimaAplicatie1.class, dar c metoda main a rmas fr modificatorii public static. Am artat c lipsa acestor modificatori nu d eroare de compilare. Dnd acum comanda
java PrimaAplicatie1

se obine mesajul de eroare

24

Programarea orientata pe obiecte n limbajul Java


Exception in thread "main" java.lang.NoSuchMethodError: main

"No such method" se traduce prin "nu exista o astfel de metoda". Urmeaza dou puncte i numele metodei care nu exist: main. Noi tim c, n realitate, n clasa PrimaAplicatie1 exista o metod numita main, numai c nu este cea pe care o caut interpretorul java pentru a pune aplicaia in execuie: acesta caut metoda
public static void main(String args[])

care, n aceast clas, nu exist.

ntrebri
Nivel 1
1. Ce este Java? 2. Ce caliti are limbajul de programare Java? 3. Ce conine mediul de execuie Java? 4. Ce conine platforma Java? 5. Ce este programarea orientat pe obiecte? 6. Ce este clasa? 7. Ce este obiectul i ce legatur exist ntre clas i obiect? 8. Prin ce se determin starea obiectului? 9. Prin ce se definete comportamentul obiectului? 10. Ce deosebire exist ntre variabilele statice i cele nestatice? 11. Ce deosebire exist ntre metodele statice i cele nestatice? 12. Ce deosebire exist ntre datele sau metodele publice i cele private? 13. Care sunt principalele tipuri de produse software care pot fi scrise n limbajul Java? 14. Ce deosebire exist ntre applet i aplicatie? 15. Ce deosebire exista ntre applet i servlet? 16. Care este metoda care trebuie s existe n mod obligatoriu n orice aplicaie? 17. Ce este un fiier surs Java i cum se stabilete numele lui? 18. Ce fel de editor se folosete pentru crearea fiierului surs? 19. Prin ce comand se cere compilarea unui fiier surs Java? 20. Ce se obine n cazul n care compilarea a decurs corect? 21. Ce se obine dac compilarea nu a reuit? 22. Prin ce comand se cere executarea unei aplicaii?

Nivel 2
1. 2. 3. 4. 5. 6. 7. 8. Dece limbajul Java este mai simplu dect C/C++? Limbajul Java este compilat sau interpretat? Ce fel de cod genereaz compilatorul Java? Ce se nelege prin portabilitatea programelor? Dece limbajul Java este neutru fa de arhitectur? Dece limbajul Java permite programarea concurent? Ce este maina virtual Java? Ce deosebire este ntre specificaia mainii virtuale Java i implementarea acesteia?

25

Severin Bumbaru 9. Ce sunt JDK 1.0, JDK 1.1 i JDK 1.2? 10. Ce este SDK si ce legatura exist ntre JDK i SDK? 11. Ce este API? 12. Ce platforme de dezvoltare pentru Java se folosesc n prezent? 13. Ce este un navigator de Web? 14. Ce este un browser? 15. Ce este WWW? 16. Ce navigatoare de Web cunoateti? 17. Dai ablonul unei aplicaii simple i explicati prile componente. 18. Ce se ntmpl dac n comanda javac numele fiierului surs este introdus greit? 19. Ce se ntmpl dac n comanda javac numele fiierului surs este introdus fr extensia java? 20. Cum sunt semnalate de compilator erorile care apar n program? 21. Ce se ntmpl dac n faa metodei main se omit modificatorii public static?

26

Programarea orientata pe obiecte n limbajul Java

iruri. Elementele lexicale ale limbajului Java. Variabile i tipuri de date primitive
Comentarii n fiierul surs iruri; concatenarea irurilor; Metode pentru afiarea pe ecran a irurilor; Uniti lexicale ale limbajului Java identificatori cuvinte cheie i cuvinte rezervate literali separatori i operatori spaii i comentarii Variabile; Declararea i iniializarea variabilelor; variabile finale; Tipuri de date primitive i declaraii de tip tipul boolean tipuri numerice tipuri de date ntregi tipuri de date n virgul mobil tipul char ntrebri 27 28 29 30 30 31 32 32 34 34 35 36 39 41 45 57 61 63

Comentarii n fiierul surs


Comentariile sunt texte care pot fi introduse n programul surs, dar nu sunt luate n consideraie de compilator i deci nu au efect n timpul executrii programului. Comentariile sunt utile pentru o mai buna nelegere a programului de ctre om. n programele Java, se pot folosi trei feluri de comentarii: a/ comentarii care se pot extinde pe una sau mai multe linii i au forma
/* <comentariu> */

b/ comentarii de sfarsit de linie, care incep cu simbolul // si continua pana la sfarsitul liniei respective, deci au forma
// <comentariu>

c/ comentarii care sunt destinate reproducerii n documentaia clasei i au forma


/** <comentariu>*/

deci se deosebesc formal de cele de la punctul a numai prin faptul ca incep cu simbolul /**. Primele dou forme de comentariu exist i n limbajul C++, n timp ce ultima este specific numai limbajului Java.

27

Severin Bumbaru Exemplu Dm aici ca exemplu fiierul Comentarii.java, care are la baz fiierul PrimaAplicatie.java, dar acesta fost completat cu comentarii.
/** Aplicatie in care se exemplifica folosirea celor trei tipuri de comentarii permise in limbajul Java */ class Comentarii { // aici incepe definitia clasei Comentarii /* metoda main este metoda principala a clasei, cu care incepe executarea programului */ public static void main(String args[]) { /* Urmeaza instructiunea prin care se invoca metoda println pentru afisarea unui text */ System.out.println("Prima noastra aplicatie a reusit!"); } } // sfarsitul metodei main

// sfarsitul clasei Comentarii

Dac vom compila i pune n executie aceast aplicaie, vom constata c efectul este acelai ca n cazul clasei PrimaAplicaie, deoarece comentariile introduse n fiierul surs nu au efect n timpul execuiei programului. OBSERVAIE: Comentariile sunt absolut necesare pentru nelegerea programului. n acelai timp, abuzul de comentarii poate s fac urmarirea acestuia dificil. Este, deci, recomandabil s se introduc n program toate comentariile necesare pentru o bun nelegere a acestuia, dar nu mai mult. La aprecierea programelor scrise de Dvs. se va lua ntotdeauna n consideraie prezena i calitatea comentariilor.

iruri
irul se reprezint n program printr-o succesiune de caractere cuprins ntre ghilimele. Iat cteva exemple de iruri:
"sir de caractere" "ABCDefgh" "1A23bc7" "*+_/?" ""

Ultimul exemplu este un ir vid (care nu conine nici un caracter).

Concatenarea irurilor
Asupra irurilor se poate aplica operaia de concatenare, reprezentata prin operatorul +. Expresia ir1+ir2, n care operatorul + este plasat ntre dou iruri, are ca rezultat un nou ir, care conine cele dou iruri-operanzi puse unul dup altul. De exemplu, expresia
"abcde"+"fgh"

d ca rezultat irul "abcdefgh".

28

Programarea orientata pe obiecte n limbajul Java Operaia de concatenare este asociativ, dar nu este comutativ. De exemplu, expresiile urmtoare sunt echivalente, ca urmare a asociativitii:
"ABC"+"DEF"+"GH" ("ABC"+"DEF")+"GH" "ABC"+("DEF"+"GH") "ABCDEFGH"

n schimb, expresia "uvw"+"ab" este echivalent cu "uvwab", n timp ce expresia "ab"+"uvw" este echivalent cu "abuvw", deci concatenarea nu este comutativ.

Metode pentru afiarea pe ecran a irurilor


n capitolul precedent, am folosit deja pentru afiarea irurilor de caractere metoda
System.out.println(<ir>)

la care vom aduga acum i metoda n este un ir de caractere, care se afieaza pe ecran. Deosebirea dintre ele const n faptul c, dup afiarea irului, metoda println transmite i comanda de trecere la linie nou, n timp ce metoda printnu transmite o astfel de comand. n consecin, n cazul afirii cu println, urmtoarea afiare se va face de la nceput de linie nou, iar la afiarea cu print afiarea urmtoare se va face n continuare, pe aceeai linie. Numele metodei println provine de la print line, care se traduce prin "tiprete o linie". Metodele println siprint aparin obiectului out din clasa System. n limbajul Java, clasa System conine metodele prin care se comunic cu sistemul de operare al calculatorului, iar obiectul out al acestei clase reprezint dispozitivul de ieire standard al sistemului, care este de obicei unitatea de afiare de la consol (ecranul). Metoda println actioneaz la fel ca metoda print, cu deosebirea c adaug la sfritul irului afiat caracterul de control \n care constituie comanda de trecere la linie nou (New Line). Exemplu Considerm urmatoarea aplicaie, coninut n fiierul AfisareSiruri.java:
/* Exersarea metodelor print si println */ class AfisareSiruri { public static void main(String args[]) { System.out.println("sirul 1"); System.out.println("sirul 2"); // se afiseaza sub sirul 1 System.out.println("AB"+"CDE"); // se afiseaza ABCDE System.out.println("ab"+"cd"+"ef"); // se afiseaza abcdef System.out.println(("ab"+"cd")+"ef"); // asociativitate System.out.println("ab"+("cd"+"ef")); /* Urmatoarele trei instructiuni afiseaza in continuare, pe o singura linie. */ System.out.print("pqrst"); // nu se trece la linie noua System.out.print("UVW"); // se afiseaza in continuare System.out.print("xyz\n"); // echivalent cu println("xyz") /* Trecerea la linia urmatoare se face datorita prezentei System.out.print(<ir>) ambele metode, argumentul <ir>

29

Severin Bumbaru

caracterului \n in sirul "xyz\n" */ System.out.println("ultima linie afisata"); } }

Compilnd i executnd acest program, putem constata c:


dup executarea fiecrei metode println se trece pe ecran la o linie noua; expresiile "ab"+"cd"+"ef", ("ab"+"cd")+"ef" si"ab"+("cd"+"ef") dau rezultate identice. print("xyz\n") are acelasi efect cu println("xyz").

Unitile lexicale ale limbajului Java


Unitile lexicale, numite i lexeme (engl. token, lexeme) sunt construciile elementare ale limbajului ("atomii" acestuia). Acestea sunt simboluri, formate din unul sau mai multe caractere, care au o anumit semnificaie n limbaj. Dup rolul ndeplinit, unitile lexicale sunt: identificatori, cuvinte cheie, cuvinte rezervate, literali, separatori,operatori, comentarii i spaii. De exemplu, n programul din fiierul AfisareSiruri.java distingem urmatoarele uniti lexicale: - cuvinte cheie: class, public, static, void; - identificatori: AfisareSiruri, main, String, args, System, out, print, println; - literali: "sirul 1", "sirul 2", "AB", "CDE", "ab", "cd", "ef", ; - separatori: { } ( ) [ ] , ; - operator: +; - comentarii: /* Exersarea metodelor print si println */
// se afiseaza sub sirul 1

Vom analiza acum separat fiecare din aceste categorii de uniti lexicale.

Identificatori
Numele date programelor sau componentelor acestora (clase, variabile, metode etc.) se numesc identificatori. Identificatorii se aleg de ctre programator, respectnd anumite reguli. n limbajul Java, identificatorii sunt iruri formate din litere, cifre i caractere de subliniere ('_'), care ncep cu o liter. Lungimea identificatorului nu prezint importan, ns acesta nu poate conine spaii libere sau alte caractere, dect cele menionate aici.

Exemple de identificatori valabili:

30

Programarea orientata pe obiecte n limbajul Java

PrimaClasa aplha viteza v15XB7 pretDeVanzare pret_de_vanzare

Este clar acum c i exemplele date anterior ( Afisari, main, String, args, System, out, print, println) sunt, de asemenea, identificatori. Se obinuiete ca numele de clase s nceap cu liter majuscul. De asemenea, se obisnuiete ca separarea ntre cuvinte, n cadrul identificatorilor compui din mai multe cuvinte ale limbajului natural, s se fac incepnd fiecare cuvant nou cu liter majuscul, dar se poate face i prin caracterul de subliniere '_'. Acestea nu sunt ns reguli sintactice, ci doar convenii neobligatorii. Programatorul poate adopta orice identificatori care respect regulile i conveniile de mai sus i care nu sunt cuvinte cheie sau cuvinte rezervate. Desigur ns c folosirea unor identificatori care au semnificaie pentru om, cum ar fi viteza sau PretDeVanzare este preferabil celor fr semnificaie, cum ar fi v15XB7, deoarece uureaz nelegerea i urmrirea programului. Amintim nsa c, pentru calculator, identificatorii nu au nici o alta semnificaie, deci, din acest punct de vedere, toate exemplele de identificatori date aici sunt la fel de bune.

Cuvinte cheie
n orice limbaj de programare, exist un set de cuvinte, numite cuvinte cheie, care sunt considerate simboluri sintactice i nu pot fi folosite n program ca identificatori. n limbajul Java, exist urmtoarele cuvinte cheie:
abstract boolean break byte case catch char class const continue default do double else extends final finally float for goto if implements import instanceof int strictfp super switch synchronized this throw throws transient try void volatile while

interface
long native new package private protected public return short static

Dintre acestea, const i goto nu sunt folosite n prezent, dar ele au fost introduse n tabela cuvintelor cheie n vederea unei eventuale utilizri viitoare. Observm acum c toate exemplele de cuvinte cheie date la nceputul acestei seciuni (class, public, static, void) sunt prezente n tabela de mai sus.

31

Severin Bumbaru

Cuvinte rezervate
Se consider cuvinte rezervate acele cuvinte, care nu pot fi folosite ca identificatori, avnd semnificaii speciale. Cuvintele cheie sunt i ele considerate n majoritatea limbajelor, inclusiv Java, drept cuvinte rezervate. n afar de acestea, n limbajul Java exist urmatoarele cuvinte rezervate: true, false, null. Primele dou sunt valorile logice adevrat i fals, iar al treilea are semnificaia de referin nul. De fapt, aceste cuvinte rezervate sunt forme speciale de literali.

Literali
Literalii sunt reprezentrile n fiierele surs ale valorilor constante. Exemple de literali: - caractere: 'a', 'A', '+', '$', '5'; - iruri de caractere: "sir de caractere", "abc$79.28#^z"; - numere ntregi: 14726, -25413; - numere reale: 12.7389, -0.05673, 2.3075E12, -1.4237E-5; - valori logice: true, false; - referina nul: null. Am subliniat faptul c literalul este forma sub care o anumita valoare este reprezentat n fiierul surs, deci n programul scris n limbaj de nivel superior (n cazul nostru n limbajul Java). Vom arta ulterior c forma de reprezentare a acelorai valori n memoria intern a calculatorului (forma intern) este diferit de cea extern. Vom reveni asupra regulilor de scriere a literalilor cnd vom prezenta tipurile de date din limbajul Java.

Separatori
Separatorul este un caracter care delimiteaz formele sintactice sau le separ ntre ele. n limbajul Java se folosesc urmtorii separatori:
{ } ( ) [ ] ; , .

Spaiul liber i operatorii indeplinesc, de asemenea, rolul de separatori. Aproape toi aceti separatori au fost deja folosii n exemplele date n acest capitol.

Operatori
Operatorii sunt simboluri ale unor operaii. Am folosit deja simbolul + ca operator de concatenare (deci simbol al operaiei de concatenare). Operatorul poate fi format din unul sau mai multe caractere. Entitatea asupra creia se aplic operatorul se numete operand. Dup numrul de operanzi, operatorii pot fi unari, binari sau ternari.

Dup numrul de operanzi deosebim: operatori unari, care se aplic unui singur operand, de ex. operatorul - n expresia -x; utilizarea operatorului unar se face, de regula, sub forma "prefix" operator operand, n care operatorul se pune n faa operandului; uneori ns se foloseste i forma "postfix"
operand operator

n care operatorul se pune dup operand;

32

Programarea orientata pe obiecte n limbajul Java operatori binari, care se aplic asupra a doi operanzi, operatorul fiind situat ntre acetia; de ex. operatorul de concatenare + n expresia "acesta este " + "un exemplu" sau operatorul de adunare a dou numere + n expresia 17+28.Operatorii binari se folosesc sub forma "infix"
operand1 operator operand2

n care operatorul este situat ntre cei doi operanzi; operatori ternari, care se aplic asupra a trei operanzi; n limbajul Java exist un singur operator ternar ( ? :) folosit n expresiile condiionale. Operatorul ternar se scrie sub forma
operand1 ? operand2 : operand3

n care operand1 are o valoare logic (true sau false), iar ceilalti doi operanzi sunt expresii aritmetice sau logice (dar de acelai tip). Din exemplele de mai sus, observm c semnificaia unui operator poate s depind de context, ca n cazul operatorului +, care a fost folosit att pentru operaia de concatenare a irurilor, ct i pentru cea de adunare a numerelor. Din punct de vedere matematic, operatorii sunt funcii cu unul, dou sau trei argumente (argumentele fiind operanzii). De exemplu, expresia a+b, n care + este un operator binar, iar a i b sunt operanzi, este o funcie de argumente a si b, care are ca valoare suma valorilor celor dou argumente. Dup efectul operatorului asupra operanzilor, operatorii pot fi fr efect lateral, care lasa valorile operanzilor nemodificate, i cu efect lateral, care modific valorile operanzilor. Astfel, operatorul + din exemplul anterior, este un operator fr efect lateral. n schimb, n expresia ++a operatorul de incrementare ++ are efect lateral deoarece, n urma efectuarii operaiei, valoarea operandului a crete cu o unitate.

Dm aici o list a operatorilor folosii n limbajul Java. Operatori unari:


+ () ++ [] -{} new ! ~

Operatori binari
+ == & && << = . <= | || >> += * >= ^ / != %

>>> -= *= /= instanceof

&=

|=

^=

~=

<<=

>>=

>>>=

Operator ternar
?:

Remarcm c operatorii + i - pot fi att unari ( ca n expresiile +a sau -a), ct i binari (ca

33

Severin Bumbaru n expresiile a+bsaua-b). Semnificaiile operatorilor vor fi artate cnd se vor prezenta tipurile de date i expresiile.

Comentarii
Dup cum s-a aratat deja, n fiierele surs pot fi introduse comentarii, care au rolul de a da omului,care citete programul respectiv, anumite explicaii necesare pentru o mai buna nelegere a acestuia. Din punct de vedere sintactic, ntregul comentariu este privit ca o singur unitate lexical, care este ignorat de ctre compilator, deci nu are efect asupra codului de octei generat de acesta.

Spaii
ntre unitile lexicale ale programului pot fi introduse orict de multe spaii libere, fr ca acestea s aib influen asupra sintaxei sau semanticii programului. Mai multe spaii libere succesive sunt tratate de compilator ca i cnd ar fi un singur spaiu.

Variabile
In matematic, variabila este un simbol dat unei valori, care aparine unei mulimi de valori ce constituie domeniul de definiie al variabilei respective. n programare, variabila este un nume cruia i se asociaz o valoare. Numele variabilei este un identificator, iar valoarea variabilei trebuie s aparin unui anumit tip de date. Asupra valorilor variabilelor pot fi efectuate prin program anumite operaii.

Exemplul 1 In expresia x=a+2, x i a sunt variabile. Operaiile efectuate sunt urmtoarele: se adun valoarea variabilei a cu valoarea 2 (dat aici sub form de literal), iar rezultatul se atribuie ca valoare variabilei x; n consecin, valoarea variabilei a ramne nemodificat, n schimb variabila x primete o nou valoare. Operatorul = nu exprima aici relaia de egalitate, ci operaia de atribuire a unei valori unei variabile. Exemplul 2 Expresia System.out.println(a) are ca efect afiarea pe ecran a valorii variabilei a.

Valoarea variabilei trebuie s fie reprezentat n memoria calculatorului la o anumit adres i s ocupe acolo un anumit spaiu (un anumit numr de bii). n consecin, numim variabil o zon de memorie care poarta un nume i care conine o anumit valoare, apartinnd unui tip de date. Programatorul care folosete un limbaj de nivel nalt, cum este i limbajul Java, nu trebuie s cunoasc adresa de memorie, la care este plasat valoarea variabilei, i nici reprezentarea

34

Programarea orientata pe obiecte n limbajul Java intern a acesteia, fiind suficient s-i cunoasca numele i tipul. Alocarea de spaiu n memorie pentru fiecare variabil se face, dup caz, de ctre compilator sau interpretor. n schimb, numele i tipul variabilei trebuie declarate de ctre programator. Remarcm c n matematic operaiile cu variabile se fac, de cele mai multe ori, la nivel abstract, asupra simbolurilor variabilelor i nu asupra valorilor acestora. De exemplu, n identitatea a+a=2.a nu are importana ce valoare are variabila a, egalitatea fiind ntotdeauna adevarat. n programare se are n vedere faptul c, att timp ct ea exista n memorie, variabila are ntotdeauna o valoare (deoarece zona de memorie aferent nu poate fi vid), iar operaiile se fac asupra valorilor variabilelor i nu asupra numelor acestora.

Declararea i iniializarea variabilelor


n limbajul Java, orice variabil trebuie declarat nainte de a fi utilizat. Prin declararea variabilei se nelege precizarea, pentru compilator, a tipului i numelui acesteia. Iniializarea variabilei se face atunci, cnd acesteia i se d pentru prima dat o valoare i deci i se aloc spaiu n memorie. Dac, la declararea variabilei, aceasta nu este i iniializat n mod explicit, atunci ea este iniializata cu o valoare implicit, care va fi specificat la descrierea fiecrui tip. Iat un exemplu de declaraie de variabil:
int alpha, beta=3702, k;

Aceasta este o instruciune din program, prin care se specific urmtoarele:


alpha, beta i k sunt numele unor variabile de tipul int; variabilei beta i se d valoarea iniiala 3702; variabilelor alpha si k li se dau valori iniiale implicite corespunztoare int (n cazul de fa valoarea 0).

tipului

Din exemplul de mai sus, se observ c declaraia de tip are urmatoarea form:
tip variabila_1, ..., variabila_n;

n care:
tip - numele tipului de date cruia i aparin variabilele declarate; variabila_i - specificarea numelui unei variabile, urmat opional variabilei respective precedat de simbolul =.

de valoarea

Remarcam c:

declaraia de tip este o instructiune care se termin obligatoriu prin simbolul ; (punct i virgul); este posibil ca, ntr-o singur declaraie, s apar mai multe variabile; n acest caz,

35

Severin Bumbaru specificaiile variabilelor respective sunt separate prin virgule; indicarea valorii variabilei este opional.

n declaraia de tip, valoarea iniial a variabilei poate fi dat sub forma unui literal sau a unei expresii. n ultimul caz, este necesar ca expresia s fie calculabil, deci toate variabilele pe care le conine s aiba deja valori date anterior. Prin convenie, n limbajul Java numele de variabile ncep ntotdeauna cu liter mic. Este permis ns ca, n interiorul numelui, sa existe i litere mari. Aceasta se ntampl atunci cnd numele variabilei este format din mai multe cuvinte ale limbii naturale, de exemplu vitezaMedie. Ulterior, la descrierea fiecrui tip de date, vom da i exemple de declarare a variabilelor de tipul respectiv.

Variabile finale
n limbajul Java, se numesc variabile finale acele "variabile", ale cror valori nu pot fi modificate prin program. Acestea sunt deci, de fapt, nite constante cu nume. Ele se aseamn cu variabilele propriu-zise prin faptul c sunt tot perechi nume - valoare, numai c valoarea lor se d o singur dat, sub forma de iniializare n declaraia de tip sau sub forma de atribuire, dup care nu mai poate fi modificat. Se obinuiete ca numele de variabile finale s fie scrise n ntregime cu majuscule. Declaraia de tip este la fel cu cea pentru variabile obinuite, dar are in fa modificatorul final, care este un cuvnt cheie.

De exemplu, declaraia
final int ALPHA=17, BETA=-1453;

servete pentru a specific faptul c ALPHA i BETA suntvariabile finale de tip int, ale caror valori sunt, respectiv, 17 si -1453 i nu mai pot fi ulterior modificate (deci ALPHA i BETA sunt, de fapt, nite constante).

Tipuri de date primitive


Tipul de date este unul din conceptele fundamentale ale programrii calculatoarelor. Tipul de date este o mulime de valori, asociat cu o mulime de operaii care se pot face asupra valorilor respective. n limbajul Java, tipurile de date se mpart n dou categorii: tipuriprimitive i tipuri referin.

36

Programarea orientata pe obiecte n limbajul Java Tipurile de date primitive sunt predefinite n limbaj. Aceasta nseamn c numele, mulimea de valori, mulimea de operaii i tipul rezultatului operaiilor pentu fiecare tip primitiv sunt impuse prin limbaj i, deci, nu trebuie definite i nu pot fi modificate de programator. Tipurile de date primitive n limbajul Java se clasific astfel:

tipul boolean; tipurile numerice o tipuri intregi: byte, short, int, long; o tipuri reale: float si double; o tipul char

Pentru fiecare tip de date vom arta reprezentarea extern, reprezentarea intern, operaiile i operatorii corespunztori. Prin reprezentare extern, nelegem regulile dup care se scriu valorile datelor respective n programe, n documente sau pe ecranul calculatorului. Reprezentarea extern a valorii ntr-un program se numete literal. Prin reprezentare intern, nelegem forma sub care datele respective apar n memoria mainii virtuale Java. O proprietate foarte important a reprezentrii interne a datelor este c aceasta, fiind destinat mainii virtuale Java, nu depinde de calculatorul concret pe care se va executa programul. Vom ncepe studiul cu tipul de date boolean, apoi vom studia tipurile numerice propriu-zise (intregi i reale), dup care vom studia tipul char, ca un tip numeric special.

Operaii i operatori
Pentru fiecare tip primitiv de date vom arta, de asemenea, operaiile specifice i operatorii corespunztori. Pentru nceput, vom prezenta aici operaia de atribuire i operatorii relaionali == i != care se aplic tuturor tipurilor de date. Celelalte operaii i operatorii corespunztori se vor fi prezenta odat cu tipurile de date crora li se aplic.

Operaia de atribuire
Prin operaia de atribuire se d (se atribuie) unei variabile o nou valoare, care o nlocuiete pe cea deja existent. Operatorul de atribuire este = (semnul egal, care ns aici se citete "se atribuie") este un operator binar cu efect lateral. Expresia a=b, n care a este o variabila, iar b este un operand care poate fi un literal, o variabil sau o expresie, are semnificaia "se atribuie variabilei a valoarea operandului b". Atribuirea este posibil numai daca valoarea operandului b este de acelasi tip cu variabila a, sau dac se poate converti implicit la acest tip. Atribuirea este o operaie cu efect lateral, deoarece produce modificarea valorii operandului situat n partea stnga a operatorului de atribuire. Exemplu Fie x o variabil de tip int. Expresia x=-17 se citeste "se atribuie lui x valoarea -17". Efectul operaiei de atribuire este, n acest caz, c valoarea anterioar a variabilei x se nlocuiete n memorie prin noua valoare. n partea dreapt a operatorului de atribuire putea fi nu numai un literal, ca n cazul nostru, ci orice alt expresie cu valoare de tip int.

37

Severin Bumbaru

Operatorii

==

!=

Pentru toate tipurile de date se pot aplica operatorii relaionali == si !=. Acetia sunt operatori binari fr efect lateral. La aplicarea unui astfel de operator, rezultatul operaiei este valoarea boolean true (adevrat) sau false (fals). Operatorul == (se citete "este egal cu") exprim relaia de egalitate. Expresia a==b, unde a i b sunt doi operanzi care pot fi literali, variabile sau expresii, are valoarea logic (booleana) true dac valoarile celor doi operanzi sunt egale, sau are valoarea logic false, dac egalitatea nu este satisfacut. Cei doi operanzi trebuie sa fie comparabili, deci fie ambii de tip boolean, fie ambii numerici.

Atragem atenia asupra deosebirilor eseniale dintre operatorul de atribuire = si operatorul de egalitate ==. a/ Operatorul de atribuire = impune ca operandul din partea stang sa fie o variabil, n timp ce n cazul operatorului de egalitate == ambii operanzi pot fi expresii. b/ Operatorul de atribuire = are efect lateral, care const n modificarea valorii variabilei din partea stang, n timp ce operatorul == nu are efect lateral, deci valorile ambilor operanzi rmn neschimbate; c/ Valoarea expresiei de atribuire a=b este identic cu valoarea atribuita variabilei a i are deci tipul acesteia, n timp ce valoarea expresiei a==b este ntotdeauna de tip boolean, indiferent de tipul operanzilor. Operatorul != (se citete "este diferit de") exprim relaia de inegalitate a celor doi operanzi. Expresia a!=b, unde a i b sunt doi operanzi care pot fi literali, variabile sau expresii, are valoarea logic (boolean) false dac valoarile celor doi operanzi sunt diferite, sau are valoarea logic true, dac operanzii au valori egale.

Declaraii de tip
Declararaiile de tip sunt instruciuni prin care se specific tipul, numele i, dac este necesar, valoarea iniial a variabilelor folosite n program. n limbajul Java, declaraiile de tip au forma:
tip variabila1, variabila2, ..., variabilaN;

n care:
tip - tipul variabilelor care se declar; variabila- numele variabilei sau, daca este necesar, numele i valoarea iniial date forma nume_variabil = valoare_iniial nume_variabila este un identificator; n limbajul Java se obinuiete ca numele de

sub

variabile s nceap cu liter mic, dei aceasta nu este o regul de sintax; valoare_initiala este o valoare de acelai tip cu variabila, care se d variabilei la iniializare (n momentul cnd i se aloc spaiu n memorie). Aceast valoare poate fi dat sub forma unui literal sau a unei expresii calculabile (n care toate variabilele au valori atribuite anterior). Remarcm c specificaiile variabilelor se separ ntre ele prin virgule, iar la sfritul declaraiei se pune simbolul ; (punct i virgul) care, n limbajul Java, este terminatorul de

38

Programarea orientata pe obiecte n limbajul Java instructiune.

Limbajul Java este strict tipizat, deci orice variabil trebuie s fie declarat nainte de a fi folosit. n plus, compilatorul Java verific dac, n momentul primei ei utilizri ntr-o expresie, variabila are deja o valoare. Exemplu Prin instruciunea
int alpha, beta=-723, gamma=beta+7; se declar c variabilele alpha, beta i gamma sunt de tip int. Variabila alpha nu este iniializat, beta primete valoarea iniial -723, iar gamma primete ca valoare rezultatul calculrii expresiei beta+7. Aceast expresie este calculabil, ntruct beta are deja o

valoare.

Tipul boolean
Mulimea de valori a acestui tip este {true, false}. Ea conine cele dou valori admise de logica boolean: true nseamnadevrat, iar false nseamn fals. Asupra datelor din acest tip pot fi aplicate operaiile de atribuire, de comparaie (== si !=) i operaiile algebrei booleene (operaiile logice).

Operatorii booleeni
Operatorul de negaie este un operator unar fr efect lateral i se reprezint prin simbolul ! (semnul exclamrii). Expresia !a, n care a este un operand boolean, se citete non-a i se interpreteaz ca negaia lui a: daca a are valoarea true, atunci !a are valoarea false i invers. Operatorii logici binari sunt operatori fr efect lateral, prin care se realizeaz operaiile logice I, SAU i SAU-EXCLUSIV. - Operatorii & si && realizeaza operatia logica I. Expresiile a&b i a&&b ,n care a i b sunt operanzi de tip boolean, are valoarea true(adevrat) dac i numai dac att a ct i b au valoarea true. n celelalte cazuri expresia are valoarea false. - Operatorii | si || realizeaz operaia logic SAU. Expresiile a|b i a||b , n care a i b sunt operanzi de tip boolean, are valoarea false dac i numai dac ambii operanzi au valoarea false. n celelalte cazuri expresia are valoarea true. - Operatorul ^ realizeaz operatia logic SAU-EXCLUSIV. Expresia a^b , n care a i b sunt operanzi de tip boolean, are valoarea true dac i numai dac cei doi operanzi au valori diferite (unul este adevrat, iar cellalt fals). Dac cei doi operanzi au valori identice, valoarea expresiei este false.

Deosebirile ntre operatorii & i &&, respectiv ntre | i || sunt urmtoarele: - n cazul operatorilor & i | se evalueaz n mod obligatoriu ambii operanzi; - n cazul operatorului &&, numit I-condiional, evaluarea celui de al doilea operand se face numai dac primul operand are valoarea true; altfel, se consider c operaia d valoarea false, fr a se mai evalua valoarea celui de al doilea operand;

39

Severin Bumbaru - n cazul operatorului ||, numit SAU-condiional, evaluarea celui de al doilea operand se face numai dac primul operand are valoarea false; altfel, se consider ca operaia d valoarea true, fr a se mai evalua valoarea celui de al doilea operand. Vom reveni asupra acestor deosebiri cnd vom arta cum sunt tratate n Java expresiile logice mai complicate. Aciunea operatorilor logici este prezentat sintetic n tabela de mai jos, n care a i b sunt doi operanzi logici.
a true true false false b true false false false a&b true false false false a&&b true false false false a|b true true false false a||b true true true false a^b false true true false

n programul din fiierul TipBoolean.java se testeaz unele din aceste operaii booleene.

/* Testarea declararii variabilelor booleene si a efectului operatiilor logice */ class TipBoolean { public static void main(String args[]) { boolean alpha=true, beta=false, p, q, r,s; p=!alpha; q=alpha&&beta; r=alpha||beta; s=alpha^beta; System.out.println(" alpha="+alpha+" beta="+beta+" p="+p+ " q="+q+" r="+r+" s="+s); System.out.println("alpha&&beta="+(alpha&&beta)+ "alpha||beta="+(alpha||beta)); System.out.println("alpha==beta: "+(alpha==beta)); System.out.println("alpha!=beta: "+(alpha!=beta)); } }

Executnd acest program se obine urmtorul rezultat afiat pe ecran:

alpha=true beta=false p=false q=false r=true s=true alpha&&beta=false alpha||beta=true alpha==beta: false alpha!=beta: true

Se observ cu uurin c rezultatele sunt corecte.

40

Programarea orientata pe obiecte n limbajul Java Pentru programatorii de C/C++ n limbajele C/C++ nu exist tipul de date boolean, astfel c n locul acestuia se folosesc datele ntregi. n consecin, n aceste limbaje, operatorii & si | nu sunt considerai operatori booleeni ci operatori logici pe bii. n Java nu este permis s se utilizeze expresii aritmetice n locul unor expresii logice (booleene), aa cum se ntmpl n C/C++.

Tipuri numerice
Sub aspect conceptual, datele care aparin acestor tipuri sunt numere, asupra crora pot fi aplicate operaiile aritmetice (adunare, scdere, nmulire, mprire) i operaiile de comparaie aritmetic (mai mic, mai mare, egal, diferit de). Din punct de vedere matematic, aceste date pot fi numere ntregi sau reale. Existena mai multor tipuri n cadrul fiecreia din aceste dou categorii se datorete particularitilor de reprezentare a datelor n memorie. Tipurile de date numerice n Java sunt urmtoarele:

tipuri ntregi: byte, short, int, long; tipuri reale (n virgul mobil): float i double; tipul char

Inainte de a trece la studierea fiecrui tip de date n parte, vom prezenta unele operaii care se aplic tuturor tipurilor de date numerice: atribuirea, conversia de tip, operatiile arimetice i comparaia. Exemple pentru aplicarea acestor operaii se vor da la studierea diferitelor tipuri concrete de date numerice.

Operaia de atribuire
Operaia de atribuire se poate aplica tuturor tipurilor de date, deci i celor numerice. n expresia
variabil = expresie

daca variabila din partea stng aparine unuia din tipurile numerice, atunci valoarea expresiei din partea dreapt trebuie sa fie, de asemenea, numeric i s aib un tip compatibil cu cel al variabilei din partea stng. Prin tip compatibil nelegem fie acelai tip cu cel al variabilei din stnga, fie un tip numeric care poate fi convertit implicit la acesta. Dac tipul operandului din dreapta este numeric, dar nu se convertete implicit la cel din stnga, se poate folosi conversia de tip explicit prin operatorul cast. n acest caz, ns, exist pericolul ca valoarea s se altereze prin conversie.

Conversia de tip
Dac este necesar, datele pot fi convertite dintr-un tip n altul. Dup caz, conversia se poate face implicit, sau poate fi cerut explicit prin program.

41

Severin Bumbaru n limbajul Java, conversia de tip implicit se face atunci cnd prin conversie nu se pierde informaie. De exemplu, dac n expresia a=b variabila a este de tip int, iar b este de tip short sau byte, valoarea variabilei b va fi automat convertit la tipul int nainte de atribuire.

n tabela de mai jos sunt indicate cu X toate conversiile de tip care se pot realiza inplicit. n coloana din stnga este tipul datei care este supusa conversiei, iar n capul tabelei (pe prima linie) tipul ctre care se face conversia. byte byte short char int long float short X int X X X long X X X X float X X X X X double X X X X X X

De exemplu, tipul int se poate converti implicit n oricare din tipurile long, float sau double, dar nu i n tipurile byte sau short. Conversia de tip explicit se face prin operatorul unar numit cast, care are forma (tip), adic este format din numele tipului ctre care se face conversia, cuprins ntre paranteze. Acesta este un operator fr efect lateral, deci care nu modific valoarea operandului. De exemplu, expresia (byte)a se va folosi pentru a converti valoarea operandului a la tipul byte. Aceasta nseamn c valoarea variabilei a rmne neschimbat, ns valoarea expresiei (byte)a se obine din cea a lui a prin convertirea ei la tipul byte. Utilizarea operatorului cast se justific atunci cnd, n situaia respectiv, conversia implicit nu este posibil. Nu este ns greit dac folosim acest operator chiar i cnd conversia respectiv se poate face i implicit.

Utilizarea operatorului cast arat faptul c programatorul dorete s se faca o anumit conversie, chiar dac prin aceasta se poate pierde informaie. Asupra efectelor pe care care le are conversia explicit vom reveni la prezentarea diferitelor tipuri de date numerice.

Operaiile aritmetice
Operaiile aritmetice sunt cele care se aplic unor operanzi numerici, avnd ca rezultate tot numere. Dup numrul de operanzi, ele pot fi unare sau binare. Unele operaii aritmetice unare au i efect lateral. Tipul rezultatului operaiilor aritmetice depinde de tipul operanzilor i va fi discutat la fiecare din tipurile numerice n parte.

42

Programarea orientata pe obiecte n limbajul Java n exemplele de expresii din aceast seciune, vom considera c a i b sunt doi operanzi numerici. n limbajul Java exist urmtorii operatori aritmetici: Operatori unari fr efect lateral:

Operator
+ -

Exemplu de expresie
+a -a

Valoarea expresiei aceeai cu valoarea operandului valoarea operandului cu semn schimbat

Operatori unari cu efect lateral Operatorii de incrementare ++ i decrementare -- au ca operanzi variabile numerice. Operatorul de incrementare ++ are ca efect lateral creterea cu o unitate a valorii variabileioperand, iar operatorul de decrementare -- are ca efect lateral micorarea cu o unitate a acestei valori. Acest efect are loc indiferent dac operatorul este plasat naintea operandului sau dup acesta. n schimb, poziia operatorului fa de operand are importan la stabilirea valorii expresiei rspective. Daca operatorul este plasat n fata operandului, operaia de incrementare sau decremantare are loc nainte de a se stabili valoarea expresiei; dac, ns, operatorul este plasat dupa operand, valoarea expresiei se stabilete nainte de a se face incrementarea sau decrementarea. Efectul operaiilor este prezentat n tabelul de mai jos.

Operator Expresie Operatie


++ ++ --++a a++ --a a--

Valoarea expresiei Efect lateral


a+1 a a-1 a

preincrementare postincrementare predecrementare postdecrementare

valoarea variabilei a creste cu 1 valoarea variabilei a creste cu 1 valoarea variabilei a scade cu 1 valoarea variabilei a scade cu 1

Operatori binari Operatorii binari nu au efect lateral - deci nu modific valorile operanzilor - i sunt dai n tabela de mai jos.

Operator Expresie Operatie Valoarea expresiei


+ * / % a+b a-b a*b a/b a%b

adunare scadere

suma valorilor operanzilor diferenta valorilor operanzilor

inmultire produsul valorilor operanzilor impartire catul (rezultatul impartirii) primului operand la al doilea modulo restul impartirii intregi a primului operand la al doilea

43

Severin Bumbaru Prin mprire ntreag nelegem mprirea fcut astfel, nct ctul sa fie un numr ntreg (fr extragerea prii fracionare (situate dupa virgul).

Operaii de atribuire compus


Urmnd tradiia limbajului C, n limbajul Java exist i operatori de atribuire compus, n care operaia de atribuire este combinat cu una din operaiile aritmetice. Operatorii de atribuire compus sunt urmtorii: +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=, >>>=. Se observ c fiecare din aceti operatori are forma op= n care op este un operator aritmetic binar. Expresia n
variabila op= operand care op este un operator aritmetic binar, este variabila = variabila op operand

echivalent cu expresia

i se evalueaz astfel: - se calculeaz mai nti valoarea expresiei (variabila op operand)n care variabila intr cu valoarea sa anterioar; - valoarea astfel calculat se atribuie ca noua valoare a variabilei din partea stnga. Aceasta noua valoare este, totodat, i valoare a expresiei. Constatm astfel c operatorii de atribuire compus au efect lateral, la fel cu cei de atribuire.

Exemplu Fie x=3.72 si y=0.19 dou variabile de tip double. Expresia x+=y se calculeaza, la fel ca expresia x=x+y, n modul urmtor: - se calculeaz valoarea expresiei x+y, care este 3.91; - se atribuie variabilei x valoarea 3.91 (efectul lateral); - valoarea astfel atribuit (3.91) este considerat i drept valoare a expresiei x+=y.

Comparaia
Comparaiile sunt operaii binare fr efect lateral, n care se compar dou numere, obinndu-se ca rezultat o valoare de tip boolean. Operatorii prin care se efectueaz comparaia a dou numere se numesc operatori relaionali i sunt dai n tabela de mai jos. Operator
< <= > >= == !=

Semnificatie mai mic dect mai mic dect sau egal cu mai mare dect mai mare dect sau egal cu este egal cu este diferit de

Operatorii relaionali se aplic tuturor tipurilor de date numerice, inclusiv celor de tip char. Se permite ca cei doi operanzi sa fie de tipuri diferite, de exemplu s se compare o valoare de tip byte cu una de tip double sau cu una de tip char.

44

Programarea orientata pe obiecte n limbajul Java S consideram, de exemplu, expresia a<b, unde a i b sunt operanzi de tipuri ntregi. Dac valoarea operandului a este mai mic dect cea a operandului b, atunci valoarea acestei expresii este true (adevrat). Dac ns valoarea lui a nu este mai mic dect cea a lui b, ca rezultat se obine valoarea false (fals). Menionm c valorile logice true i false sunt cele dou valori ale tipului de date boolean

Tipuri de date ntregi


Tipurile de date ntregi sunt byte, short, int, long i char. Conceptual, datele care aparin tipurilor byte, short, int i long sunt numere ntregi, n timp ce tipul char conine caractere (litere, cifre, semne de punctuaie etc). ntruct caracterele se codific n memoria calculatorului prin numere ntregi fr semn, n limbajul Java asupra lor se pot aplica toate operaiile pentru numere ntregi. Totusi, datorit particularitilor pe care le prezint, noi vom trata tipul char separat.

Mulimile de valori ale tipurilor ntregi


Tipurile de date ntregi propriu-zise sunt date n tabela de mai jos. Tipul Lungimea byte short int long 1 octet (8 bii) 2 octei (16 bii) 4 octei (32 bii) 8 octei (64 bii) Intervalul de valori [-128, 127] [-32768, 32767] [-2147483648, 2147683647] [-9223372036854775808, 9223372036854775807]

Se observ, deci, c deosebirea dintre diferitele tipuri de date ntregi const n lungimea reprezentrii lor interne, care condiioneaz i mulimea de valori a tipului respectiv. Este evident c mulimea de valori a fiecruia din aceste tipuri este numai o submulime a mulimii numerelor ntregi.

Reprezentarea intern a datelor de tip byte, short, int si long se face sub forma de numere ntregi cu semn, n sistemul de numeraie binar. Primul bit al reprezentrii interne este interpretat drept semn (0 pentru + si 1 pentru -). Numerele ntregi pozitive se reprezint, deci, prin numere binare care ncep cu cifra 0. Numerele ntregi negative se reprezint prin complementul la doi al modulului lor. Avand n vedere c cu n cifre n baza 2 se pot reprezenta 2n valori, se obin domeniile de valori indicate n tabelul de mai sus. De exemplu, pentru tipul byte exist 28=256 valori. Limitele domeniilor de valori pentru fiecare tip ntreg se pot exprima n binar n funcie de numrul de bii astfel: - tipul byte: -27 ... 27-1; - tipul short: -215 ... 215-1; - tipul int: -231 ... 231-1; - tipul long: -264 ... 264-1.

45

Severin Bumbaru

Sa lum ca exemplu numerele de tip byte, care se reprezint intern pe o lungime de 8 bii. Cel mai mic numar pozitiv este, n acest caz, 00000000 (deci 0 extins pe toi cei 8 bii), iar cel mai mare numar pozitiv este01111111, care este n sistemul zecimal 27-1, adica 127. Pentru reprezentarea numerelor negative se foloeste complementul la 2, care se obtine astfel: se ia modulul numrului respectiv (n binar) i se inverseaza toti biii (din 0 n 1 i invers), dup care se adun 1 la valoarea astfel obinut. De exemplu, numarul -108 se va reprezenta astfel: se ia modulul acestuia, 108, care se reprezinta n binar pe 8 bii sub forma 01101100. nversnd biii se obtine 10010011. Adunnd 1 (n binar) la acest numr se obine 10010100 care este reprezentarea intern a numarului negativ -108 i are primul bit 1. Remarcam c numarul -1 se reprezinta intern pe 8 bii prin 11111111, iar numrul -128 prin 10000000.

Literali de tip ntreg


Literalii de tip ntreg servesc pentru reprezentarea n program a valorilor numerice de tip ntreg i pot fi clasificai astfel:

dup tipul de date: literali de tip int i de tip long dup sistemul de numeraie: literali zecimali, octali sau hexazecimali.

Nu exist in limbajul Java literali de tip byte sau short. Literalii de tip long se deosebesc de cei de tip int prin faptul ca se termin prin litera L sau l. Se prefera litera majuscula L, deoarece litera mic l se poate confunda cu cifra 1. n sistemul zecimal, literalii ntregi sunt iruri de cifre zecimale care pot fi precedate de semn i nu conin n interiorul lor separatori, cum sunt punctul, virgula sau apostroful (care se folosesc de noi n scrierea uzual a numerelor) i nu incep cu cifra 0.

Exemple corecte de literali ntregi n sistemul zecimal: - de tip int: 0 -5 276315 -176426 - de tip long: 0L -5L 3567286542987L Exemple de literali ntregi scrii greit: 27.653.816 (conine puncte); 5,187 (conine virgula); 3'876'293 (conine apostrofuri); 069354 -084931 (ncep cu cifra 0). n sistemul octal, literalii ntregi sunt numere cu sau fr semn, scrise n sistemul de numeraie octal (cu baza opt) i care ncep cu cifra 0. Amintim c cifrele sistemului octal sunt 0, 1, 2, 3, 4, 5, 6, 7.

46

Programarea orientata pe obiecte n limbajul Java Exemple de literali coreci n sistemul octal:
016724 -04507

n sistemul hexazecimal, literalii ntregi sunt numere cu sau fr semn, scrise n sistemul de numeraie hexazecimal (cu baza 16) i care ncep cu prefixul 0x. Amintim c cifrele sistemului hexazecimal sunt: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F. n locul majusculelor se pot folosi i minusculele corespunztoare.

Exemple de literali coreci n sistemul hexazecimal: 0x37B2E

-0x2ab7f3

Sistemele octal i hexazecimal prezint avantajul c au ca baze puteri ale lui 2. Din aceast cauz, conversia din aceste sisteme de numeraie n binar pentru numerele pozitive se face simplu: fiecare cifra octal se reprezint n binar prin trei bii, iar fiecare cifr fexazecimal prin patru bii. De exemplu, numrul octal 15132 (corespunztor literalului 015132) se va reprezenta n binar prin 001101001011010, iar numrul hexazecimal 6ac3 (corespunzator literalului 0x6ac3) se convertete n binar prin 0110101011000011. La conversia invers, din binar n octal, se grupeaz cifrele numarului binar cte trei de la dreapta la stnga, dup care se nlocuiete fiecare grup de trei bii prin valoarea corespunztoare n octal. n mod corespunztor, la conversia din binar n hexazecimal, se grupeaz biii cte patru de la dreapta la stnga i se nlocuiete fiecare grup prin cifra hexazecimal corespunztoare. De exemplu, numrul binar 0110110010110011 corespunde numerelor 066263 n octal i 6cb3 in hexazecimal.

Operaii i operatori pentru date de tip ntreg


Asupra datelor de tip ntreg se pot aplica operaii de atribuire, de conversie de tip, operaii aritmetice, de comparaie, operaii de deplasare binar, operaii logice pe bii i operaii de atribuire compus. Primele trei au fost discutate anterior i vom indica aici numai unele particulariti ale aplicrii lor n cazul datelor de tipuri ntregi.

Conversia de tip i atribuirea


Diferitele tipuri de date ntregi difer ntre ele prin lungimea reprezentrii lor interne. La convertirea unui tip mai scurt n unul mai lung (de exemplu a unui byte sau short n int) valoarea numrului rmne neschimbat. Din aceast cauz, aceast conversie se poate face implicit. n schimb, la conversia de la o lungime mai mare la una mai mic, se rein numai octeii situai n partea dreapt a numrului, eliminndu-se octeii din stnga care depesc noua lungime. Prin aceasta este posibil s se modifice valoarea numrului i chiar semnul lui. Din aceast cauz, la efectuarea unor astfel de conversii, programatorul trebuie s-i asume raspunderea folosind operatorul cast. Exemplu S considerm urmatoarea aplicaie din fiierul CastInt.java.
/* Verificarea actiunii operatorului (cast) in cazul numerelor intregi */ class CastInt {

47

Severin Bumbaru

public static void main(String args[]) { /* Declararea si initializarea variabilelor */ byte b1=73, b2=-107, b3, b4, b5; int i1=91, i2=-103, i3=22195, i4, i5; /* Atribuiri cu conversie implicita de la byte la int */ i4=b1; i5=b2; /* Atribuiri care necesita conversie explicita de la int la byte */ b3=(byte)i1; b4=(byte)i2; b5=(byte)i3; /* Afisarea rezultatelor */ System.out.println("i4="+i4+" i5="+i5+"\nb3="+b3+" b4="+b4+ " b5="+b5); } }

Compilnd i rulnd pe calculator aceast aplicaie obinem urmtorul rezultat afiat pe ecran:
i4=73 i5=-107 b3=91 b4=-103 b5=-77

Analiznd aceste rezultate, constatm c: - valorile variabilelor i3 i i4 au fost atribuite corect, deoarece conversia s-a fcut de la lungimea de un octet la cea de 4 octei, astfel c nu s-au alterat valorile; - valorile variabilelor b3 i b4 au fost atribuite corect, dei conversia s-a fcut prin (cast) de la lungimea de 4 octei la cea de 1 octet. Explicaia este c valorile atribuite se ncadrau n intervalul de valori permise pentru tipul byte; - n cazul variabilei b5 s-a atribuit valoarea -77, dei n instruciunea b5=(byte)i3 variabila i3 are valoarea 22195. Prin conversie s-au modificat deci att valoarea, ct i semnul, deoarece 22195 nu se ncadreaz n mulimea de valori a tipului byte.

Pentru cei interesai, putem urmri cum s-au facut efectiv aceste conversii, lund n consideraie reprezentrile interne. a/ Atribuirea i4=b1 unde b1 are valoarea 73. b1 se reprezinta intern prin octetul 01001001. Cnd se face conversia de la byte la int se extinde aceasta reprezentare externa prin adaugarea la stnga a trei octei nuli. Se obine astfel numrul de tip int 00000000000000000000000001001001 care este valoarea 73 pe 4 octei. b/ Atribuirea i5=b2 unde b2 are valoarea negativ -107. b2 se reprezint intern prin octetul 10010101 (folosind codul complementar pentru numere negative). Intruct primul bit este 1, cnd se face conversia de la byte la int se adaug la stnga trei octei completai n ntregime cu cifra 1, obinndu-se reprezentarea intern 11111111111111111111111110010101. n acest fel s-a conservat semnul, obinndu-se tot numrul -107, dar reprezentat pe 4 octei.

48

Programarea orientata pe obiecte n limbajul Java

c/ Atribuirea b3=(byte)i1 unde i1 are valoarea 91. Reprezentarea intern a lui i1 este 00000000000000000000000001011011 i se extinde pe 4 octei. Prin conversia de la int la byte se elimin cei trei octei din stnga, obinndu-se reprezentarea pe un octet 01011011. ntruct s-au eliminat numai zerouri din stnga, valoarea a rmas neschimbat. d/ Atribuirea b4=(byte)i2 unde i2 are valoarea negativ -103. Reprezentarea intern a lui i2 este 11111111111111111111111110011001 fiind complementul lui 103 extins pe 4 octei. Prin conversie la tipul byte se elimin cei trei octei din stnga, obinndu-se 10011001 care este tot numrul -103, dar reprezentat pe un singur octet. e/ Atribuirea b5=(byte)i3, unde i3 are valoarea 22195. Reprezentarea intern a lui i3 pe patru octeti este 00000000000000000101011010110011. Prin conversie la tipul byte se elimina cei trei octei din stnga, reinndu-se octetul 10110011 care se atribuie ca valoare a lui b5. Deoarece ncepe cu bitul 1, aceasta se interpreteaza ca valoarea negativ -77. Constatm astfel c prin conversie s-au modificat att valoarea, ct i semnul. Aceasta s-a ntmplat ntruct valoarea de la care a pornit conversia nu se ncadra n mulimea de valori a tipului byte, iar la eliminarea celor trei octei din partea stang s-au pierdut cifre semnificative.

Operaii aritmetice cu numere ntregi


Asupra datelor de tip ntreg se pot aplica toi operatorii aritmetici prezentai anterior. Vom prezenta aici numai unele particulariti ale operaiilor aritmetice cu numere ntregi i vom da exemple. Tipul rezultatului operaiilor aritmetice cu numere ntregi se stabileste astfel: a/ n cazul operaiilor de incrementare (++) i decrementare (--) tipul rezultatului este acelai cu tipul operandului; b/ pentru toate celelalte operaii, dac cel puin unul din operanzi este de tip long, atunci rezultatul este de tip long; altfel, rezultatul este de tip int. Remarcm, deci, c singurele operaii aritmetice care pot da rezultat de tip byte sau short sunt cele de incrementare sau decrementare. mparirea ntreag O consecin a modului de stabilire a rezultatului operaiilor aritmetice este c, atunci cnd se face o operaie de mprire (/) ntre dou numere ntregi, rezultatul este un numar ntreg (de tip int sau long, dup caz). La mprire se calculeaz, deci, numai partea ntreag a ctului. Excepia de mprire la zero Este posibil ca, n operatia de mparire ntreag, al doilea operand (mpritorul) s fie egal cu zero. n acest caz, maina virtual Java genereaz o excepie de mprire la zero, care face parte din clasa ArithmeticException. n programul de mai jos, din fiierul ImpartireZero.java, se testeaz o astfel de situaie.

49

Severin Bumbaru

/* Testarea exceptiei de impartire la zero */ class ImpartireZero { public static void main(String args[]) { int a=5, b=0, c=0; System.out.println(a/b); } }

Se observ c n expresia a/b opeandul b are valoarea zero. La executarea acestui program se afieaza pe ecran urmtorul mesaj:

Exception in thread "main" java.lang.ArithmeticException: / by zero at ImpartireZero.main(ImpartireZero.java:6)

Acest mesaj se interpreteaz astfel: s-a produs o excepie din clasa ArithmeticException n firul de execuie "main"; excepia const n mprire (/) la zero i a aprut n metoda main a clasei ImpartireZero, fiind localizat n fiierul surs ImpartireZero.java linia 6. Se poate constata cu uurin c, ntr-adevar, operaia care a produs excepia se gsete n locul indicat. nlocuind n acest fiier operaia a/b prin c/b (astfel nct ambii operanzi sunt nuli) caonstatm c, dac repetm compilarea i execuia, obinem aceeai excepie. Aa dar, la depistarea excepiei de mprire la zero, maina virtual Java testeaz numai mpritorul, nu i dempritul. Depirea binar La efectuarea unor operaii cu numere ntregi este posibil ca rezultatul s fie un numar binar mai lung dect spaiul alocat n memorie pentru tipul de date respectiv. De exemplu, dac se nmulesc dou numere de tip int (reprezentate pe 32 bii fiecare), rezultatul poate fi un numar mai lung de 32 bii, deci a crui valoare nu se mai ncadreaz n mulimea de date a tipului int. O astfel de situaie se numete depire binar. n limbajul Java, apariia depirii binare nu este considerat o excepie, ci calculul continu, dar se rein numai octeii din dreapta ai rezultatului, ati ct corespund reprezentrii interne a tipului de date respectiv (4 octei pentru int i 8 octei pentru long). n consecina se pierd octeii cei mai semnificativi i are loc, deci, modificarea valorii i chiar a semnului rezultatului, la fel ca n cazul conversiei de la un tip cu lungime mai mare la unul cu lungime mai mic. Exemplu n urmtoarea aplicaie din fiierul Intregi.java se fac unele teste privind operaiile cu numere ntregi.

class Intregi { public static void main(String args[]) { byte b1=73, b2=-109, b3, b4, b5; short s1=9000, s2=-11000, s3; int i1=900000, i2=-1100000, i3, i4, i5; long m1=10000000000L, m2=-200000000000L, m3, m4; b3=(byte)(-b2);

50

Programarea orientata pe obiecte n limbajul Java

b4=(byte)(b1+b2); b5=++b1; s3=(short)(s2/s1); s4=(short)(s2%s1); // restul impartirii s2/s1 i3=i1+i2; i4=i1*i2; i5=(int)(m2/i1); m3=m2-m1; m4=m2*m1; System.out.println("b3="+b3+" b4="+b4+" b5="+b5); System.out.println("s3="+s3+" s4="+s4); System.out.println("i3="+i3+" i4="+i4+" i5="+i5); System.out.println("m3="+m3+" m4="+m4); System.out.println("b5*b2="+(b5*b2)+ "s1*s2="+(s1*s2)); } }

Remarcm c la calcularea valorilor variabilelor b3, b4 i s3 a fost necesar s se foloseasc conversia explicit (cast), deoarece valorile expresiilor din paranteze din partea dreapt a operandului de atribuire sunt de tip int, n timp ce variabilele din partea stnga sunt de tip byte sau short. n mod similar s-a folosit castul la calcularea lui i5, deoarece expresia m2/m1 este de tipul long. Se poate constata cu usurin, suprimnd din program operatorii cast din expresiile respective, c dac nu se folosesc aceti operatori sunt semnalate erori de compilare. n schimb, nu a fost necesar s se recurg la cast la calcularea valorii lui b5, deoarece expresia ++b este de tip byte. Executnd acest program, se obin pe ecran urmtoarele rezultate:

b3=109 b4=-36 b5=74 s3=-1 s4=-2000 i3=-200000 i4=2137445376 i5=-222222 m3=-210000000000 m4=-7751640039368425472 b5*b2=-8066 s1*s2=-99000000

Din aceste rezultate constatm c: - s-a obinut s3=-1 si nu s3=-1.222222... deoarece n expresia s2/s1 ambii operanzi sunt de tipuri ntregi, deci rezultatul este ntreg (mprire ntreag). Din acelai motiv s-a obinut i5=-222222 si nu -222222.222222....; - la calcularea lui i4 nu s-a obinut valoarea corect -990000000000, ci valoarea 2137445376. Cauza este c valoarea depete marginea superioar a valorilor de tip int, deci s-a produs o depire binar i s-au trunchiat octeii cei mai semnificativi. Tot o depire binar s-a produs i la calcularea lui m4 (de data aceasta pentru tipul long); - valorile produselor b5*b2 i s1*s2 au fost calculate i afisate corect, dei ele depesc limitele mulimilor de valori de tip byte, respectiv de tip short. Aceasta s-a produs deoarece expresiile respective sunt de tip int.

Comparaia
Operatorii de comparaie pot fi aplicai pentru orice fel de operanzi numerici. Ca exemplu, n fiierul ComparInt.java se da un program, n care se compar diferite numere ntregi i se

51

Severin Bumbaru afieaz rezultatele.


/* Testarea operatorilor de comparatie in cazul tipurilor de date intregi */ class ComparInt { public static void main(String args[]) { byte b1=48, b2=-17; short s1=2765, s2=-12970; int i1=762983, i2=48, i3=-12970; long m1=876432906528L, m2=48; System.out.println(b1==b2); System.out.println(b1==i2); System.out.println(s1!=i2); System.out.println(i2!=m2); System.out.println(m2>i2); System.out.println(m2>=i2); System.out.println(s2<i3); System.out.println(i3<=s2); } }

Executnd acest program se obin pe ecran urmtoarele rezultate sub forma de valori booleene:

false true true talse true talse true

52

Programarea orientata pe obiecte n limbajul Java

Avnd n vedere c true nseamn adevrat, iar false nseamn fals, se poate constata cu uurinta c aceste rezultate sunt corecte. Remarcm, de asemenea, c rezultatul comparaiei depinde numai de valorile numerelor comparate, nu i de tipul acestora. Operaii de deplasare binar
Urmnd "tradiia" limbajului C, limbajul Java conine i operatori de deplasare binar. Acetia sunt operatori binari (cu doi operanzi) fr efect lateral. Tipul rezultatului operaiei se stabilete la fel ca n cazul operaiilor aritmetice cu numere ntregi. Valoarea rezultat se stabilete astfel: se ia reprezentarea intern a primului operand i se deplaseaz la stnga sau la dreapta cu un numar de poziii binare egal cu cel de al doilea operand. Operatorii de deplasare i efectele lor sunt prezentate n tabela de mai jos, n care a i s sunt operanzi care aparin unor tipuri ntregi.

Operator Expresie Efect


<< >> >>> a<<s a>>s a>>>s

deplasare la stnga cu s poziii binare deplasare la dreapta cu s poziii binare, cu conservarea semnului deplasare la dreapta fr semn, cu s poziii binare

Deplasarea la stnga cu s poziii este echivalenta cu nmulirea numrului cu 2s. Dac s este suficient de mare, poate avea loc o depire binar, la fel ca n cazul nmulirii aritmetice (cu operatorul *). Deplasarea la dreapta cu s poziii cu operatorul >> este echivalenta cu mprirea ntreag la 2s. Deplasarea biilor la dreapta cu s pozitii cu operatorul >>> are asupra numerelor pozitive acelai efect ca cel al operatorului >>. n schimb, n cazul operanzilor negativi, n cazul operatorului >>> nu se mai conserv semnul, iar modulul numrului se modific. Aceasta se ntmpl, ntruct pe poziiile eliberate din partea stng se nsereaz bitul 0. Exemplu n fiierul Deplasari.java se d un exemplu de aplicaie, n care se testeaz aciunea operatorilor de deplasare binar.

/* Testarea operatiilor de deplasare binara */ class Deplasari { public static void main(String args[]) { byte b1=15, b2; int i1=1024, i2=-1024; b2=(byte)(b1<<3); System.out.println("b1="+b1+" b2="+b2); System.out.println("i1<<4="+(i1<<4)+" i1>>4="+(i1>>4)+ " i1>>>4="+(i1>>>4));

53

Severin Bumbaru

System.out.println("i2<<4="+(i2<<4)+" i2>>4="+(i2>>4)+ " i2>>>4="+(i2>>>4)); } }

Rezultatele afiate la executarea acestui program sunt urmtoarele:

b1=15 b2=120 i1<<4=16384 i1>>4=64 i1>>>4=64 i2<<4=-16384 i2>>4=-64 i2>>>4=268435392

Avnd n vedere c 23=8 i 24=16, rezultatele obinute pot fi verificate cu uurin. Constatm ca singura deosebire dintre efectele operatorilor >> i >>> apare cnd primul operand este negativ.

Operatorul >>> nu exist n limbajul C, el fiind introdus numai n Java. Pentru a inelege mai bine efectul operatorilor de deplasare, s urmrim ce se ntmpl n exemplul de mai sus la nivelul reprezentrii interne a datelor (n binar). Avnd n vedere c 1024=210, reprezentrile interne ale operanzilor i1 i i2 sunt urmtoarele:
i1=00000000000000000000010000000000 i2=11111111111111111111110000000000

Dup aplicarea operatorului << (deplasare binar la stnga cu inserare de zerouri pe spaiile libere din dreapta) obinem: - pentru operaia i1<<4: 00000000000000000100000000000000 - pentru operaia i2<<4: 11111111111111111100000000000000 ceeace reprezint n zecimal numerele 214=16384 si, respectiv, -214=-16384. Dup aplicarea operatorului >> (deplasare la dreapta cu conservarea semnului) se obine: - pentru operaia i1>>4: 00000000000000000000000001000000 - pentru operaia i2>>4: 11111111111111111111111111000000 ceeace reprezint n sistemul zecimal numerele 26=64 i, respectiv, -26=-64. Remarcm c n cazul operandului negativ i2, la deplasarea la dreapta s-a nserat pe poziiile libere bitul 1 pentru a se conserva semnul. Dup aplicarea operatorului >>> (deplasare la dreapta fr conservarea semnului) se obine: - pentru operaia i1>>>4: 00000000000000000000000001000000 - pentru operaia i2>>>4: 00001111111111111111111111000000 Pentru operandul pozitiv i1 s-a obinut un rezultat identic cu cel precedent. n schimb, n cazul operandului negativ i2, pe poziiile eliberate din partea stng s-a nserat bitul 0, ceeace a dus la schimbarea semnului i a valorii rezultatului fa de cazul deplsarii cu conservarea semnului.

Operaii logice pe bii


Tot urmnd "tradiia" limbajelor C/C++, n limbajul Java se pot utiliza pentru tipurile de date

54

Programarea orientata pe obiecte n limbajul Java ntregi i operatorii logici pe bii ~, &, | si ^. Acetia sunt operatori fr efect lateral. Operaiile logice se fac la nivel de bit, adic ntre fiecare bit al operandului din stnga i bitul corespunztor al operandului din dreapta, considerndu-se ca 0 este echivalent cu false, iar 1 este echivalent cu true. Operatorul unar ~ exprim negaia logic, deci nlocuirea lui 0 cu 1 i invers. Operatorii binari &, | si ^ acioneaz la fel ca n cazul tipului boolean, numai c se aplic la nivel de bit. Aciunea operatorilor este dat n tabela de mai jos, n care a i b sunt cei doi operanzi, iar ai si bisunt biii de pe pozitia i a acestor operanzi. n tabel se d efectul fiecrei operaii asupra bitului i al rezultatului.

ai 0 0 1 1

bi 0 1 0 1

~a 1 1 0 0

a&b 0 0 0 1

a|b 0 1 1 1

a^b 0 1 1 0

Exemplu n fiierul LogicaBiti.java este dat un exemplu de program, n care se testeaz operaiile logice pe bii. Pentru a se verifica manual mai uor, am considerat c opraiile se fac asupra datelor de tip byte. Este bine s avem ns in vedere c rezultatele operaiilor sunt de tip int. Aceasta se poate constata cu usurina dac ncercm s eliminm castul din instruciunea n care se calculeaz b3.

/* Testarea operatiilor logice pe biti */ class LogicaBiti { public static void main(String args[]) { byte b1=17, b2=-95, b3; b3=(byte)(b1&b2); // este necesara conversie de la int la byte System.out.println("~b1="+(~b1)+" b1&b2="+b3+" b1|b2="+(b1|b2)+ " b1^b2="+(b1^b2)); } }

Rezultatele afiate la executarea acestui program sunt urmtoarele:

~b1=-18 b1&b2=1 b1|b2=-79 b1^b2=-80

Iat i cum decurg operaiile din exemplul de mai sus la nivel de bit:
b1: 00010001 b2: 10100001 ~b1: 11101110

echivalent cu 17 echivalent cu -95 echivalent cu -18

55

Severin Bumbaru

echivalent cu 1 echivalent cu -79 echibalent cu -80 Bineneles c toate aceste rezultate ar trebui exprimate pe 32 bii, prin prelungire la stnga cu cate 18 cifre de 0 sau de 1 dup caz, astfel nct s se conserve semnul.

b1&b2: 00000001 b1|b2: 10110001 b1^b2: 10110000

Aplicarea operatorilor de atribuire compus


Pentru operanzii de tipuri ntregi se pot aplica toi operatorii de atribuire compus +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=, >>=. Exemplu n programul din fiierul AtribComp.java se testeaz unele operaii de atribuire compus. Iat acest program:
/* Testarea operatorilor de atribuire compusa */ class AtribComp { public static void main(String args[]) { int m=176, b=-15, c=16, d=-28; System.out.println(m+" "+(m+=b)+" "+m); System.out.println((m/=d)+" "+m); System.out.println(b+" "+(b<<=2)+" "+b); System.out.println(c+" "+(c|=b)+" "+c); } }

La executarea programului se obin pe ecran urmtoarele rezultate:

176 161 161 -5 -5 -15 -60 -60 16 -44 -44

Prima linie afiat conine: - valoarea variabilei m nainte de evaluarea expresiei m+=b; - valoarea expresiei m+=b; ea este egal cu m+b adic cu 176-15; - valoarea variabilei m dup calcularea acestei expresii. Recomandm sa explicai n mod similar i celelalte linii afiate.

56

Programarea orientata pe obiecte n limbajul Java

Tipuri de date n virgul mobil


Mulimile de valori pentru tipurile de date n virgul mobil
Conceptual, datele care aparin acestor tipuri sunt numere reale. n limbajul Java exist dou tipuri de date reale (numite i tipuri de date flotante sau n virgul mobil): Tipul
float double

Lungimea

Intervalul de valori

4 octeti (32 biti) [-3.402347e+38f, ... 3.402347e38f] 8 octeti (64 biti) [-1.7976931348623157e+308, ... 1.7976931348623157e308]

Reprezentarea intern a datelor n virgul mobil adoptat pentru maina virtual Java corespunde standardului ANSI/IEEE 754-1985. Reprezentarea extern a numerelor n virgul mobil se poate face n urmtoarele moduri: a/ ca numere reale fr exponent, n care partea ntreag este separat de cea fracionara prin punct; b/ ca numere reale cu exponent, n care un numr ntreg sau unul real fr exponent, numit mantisa sau coeficient, este urmat de un exponent zecimal, format din litera e sau E urmata de un numar intreg. Semnificaia este c mantisa se nmultete cu 10 ridicat la o putere egal cu exponentul. O caracteristic important a numerelor n virgul mobil este precizia. Se numete precizie numrul maxim de cifre semnificative pe care l poate avea mantisa pentru tipul de date respectiv. Aceasta depinde de numrul de bii alocai mantisei n reprezentarea intern. n cazul limbajului Java, datele de tip float pot avea cel mult 7 cifre semnificative, iar cele de tip double cel mult 16 cifre semnificative. n reprezentarea extern a numrului se pot folosi i mai multe cifre, dar cele care depesc lungimea admis nu vor fi luate n consideraie la conversia din forma extern n cea intern.

Cifrele semnificative sunt cifrele mantisei numrului, care ncep de la prima cifr diferit de zero i se termin cu ultima cifra diferita de zero. De exemplu, numrul 000102.3015000 are 7 cifre semnificative (cele subliniate), deoarece zerourile de la nceput i de la sfrit nu influeneaz valoarea numrului. Acelai numr poate avea diferite reprezentri externe, de exemplu: 102.3015, 10.23015E1, 1.023015E2, 0.1023015E3, 0.01023015E4 etc. Pentru toate aceste numere, reprezentarea intern va fi aceeai. Menionm c numerele de mai sus, dei au numai 7 cifre semnificative, vor fi reprezentate intern ca numere de tip double, deci pe 8 octei fiecare. Pentru a fi reprezentate intern ca date de tip float (pe 4 octeti) trebuie scrise cu litera f sau F la sfrit, de exemplu 102.3015f. n afar de valorile numerice, pentru datele n virgul mobil sunt prevzute i urmtoarele valori speciale:

57

Severin Bumbaru corespunde valorii plus infinit; corespunde valorii minus infinit; reprezint ceva care nu este numr (Nota Number). n consecin, n cazul datelor de tipuri reale, dac a este un numar real pozitiv, operaia a/0.0 d ca rezultat Infinity, iar operaia a/(-0.0) da rezultatul -Infinity. Operaia 0.0/0.0 d rezultatul NaN. Atenie: valorile Infinity, -Infinity i NaN sunt formele externe sub care acestea se afieaz pe ecran, se tipresc la imprimant sau se scriu ntr-un fiier de text. Fiecreia dintre ele i corespunde o reprezentare intern, sub forma unui ir de 4 sau 8 octei, corespunztor tipului float sau double. Aceste reprezentri interne respect regula, conform creia, dac sunt interpretate ca numere n virgul mobil, ndeplinesc urmtoarele condiii: Infinity este mai mare decat orice valoare de tipul respectiv; -Infinity este mai mic dect orice valoare de tipul respectiv. n acest fel, valorile menionate pstreaz consistena operaiilor de comparaie.
Infinity -Infinity NaN -

Literalii n virgul mobil


Literalii n virgul mobil sunt reprezentrile valorilor reale n programele Java. La scrierea literalilor se respect formele externe de numere reale fr exponent sau cu exponent prezentate mai sus, cu precizarea ca literalii de tip float se termina cu litera f sau F, n timp ce literalii de tip double nu au un astfel de sufix. Exemple de literali n virgul mobil a/ literali de tip float fr exponent: 123.7f, -1876.53f; b/ literali de tip float cu exponent: 7.28765e12f (echivalent cu 7.28765x1012) -8 5.0754286e-8f (echivalent cu 5.075428x10 ) 3 -3.9104e3f (echivalent cu -3.9104x10 ) c/ literali de tip double fr exponent: 154236789.20973, -3401.76398653; d/ literali de tip double cu exponent:
2935.87628091e-12 -1.20937543872E23 12e23 (echivalent cu

12.0x1023)

Att la tipul float, ct i la tipul double, valoarea 0.0 are semn: poate exista att +0.0 ct i -0.0. Un 0 fr semn este echivalent cu +0.0. Pentru tipul float, aceste valori sunt scrise sub forma +0.0f i -0.0f.

Valorile speciale Infinity, -Infinity i NaN nu sunt literali, ci doar forme externe de afiare a valorilor interne corespunztoare. n consecin, ele nu pot fi folosite n programele surs. De exemplu, daca x este o variabil n virgul mobil, nu putem face atribuirea x=Infinity.

Operaii i operatori pentru date n virgul mobil


Asupra datelor n virgul mobil se pot aplica operaii de atribuire, de conversie de tip, operaii aritmetice i de comparaie, atribuirea compus. Acestea au fost deja prezentate,

58

Programarea orientata pe obiecte n limbajul Java astfel c vom indica aici numai unele particulariti ale aplicrii lor n cazul datelor n virgul mobil.

Conversia de tip i atribuirea


S-a artat deja ca orice dat numeric de tip ntreg se poate converti implicit n oricare din tipurile n virgul mobil. De asemenea, are loc conversie implicit de la float la double. n consecin, folosirea conversiei explicite (cast) este necesar atunci cnd se trece de la double la float, sau de la un tip n virgul mobil la unul ntreg. Conversia din double n float nu conduce niciodata la alterarea valorii, ci numai la pierderea de precizie. Aceasta se produce, ntrucat se trece de la o mantis de 52 de bii la una de 24 bii , deci de la cca 17 cifre semnificative la numai cca 7 cifre semnificative n sistemul zecimal. n schimb, conversia explicit de la date n virgul mobil la oricare din datele de tip ntreg poate duce la denaturarea valorii i a semnului numrului, la fel ca n cazul tipurilor intregi. Aceasta se ntmpl atunci cnd valoarea care trebuie convertit nu se ncadreaz n mulimea de valori specific tipului n care se face conversia. Unei variabile n virgul mobil i se pot atribui orice valori de tipuri numerice.

Operaii aritmetice cu numere reale


Asupra datelor n virgul mobil se pot aplica toi operatorii aritmetici prezentai anterior, inclusiv operatorii de incrementare (++), decrementare (--) i restul mpririi ntregi (%). Vom prezenta aici numai unele particulariti ale operaiilor aritmetice n virgul mobil i vom da exemple. O particularitate important a operaiilor aritmetice n virgul mobil n limbajul Java este c mprirea la zero nu mai este considerat o exceptie, ci este o operaie permis. Rezultatul mpririi la zero depinde de valoarea dempritului i de semnele celor doi operanzi. Rezultatul mpririi 0/0 este NaN (Not a Number, deci o valoare nedefinit). Dac dempritul este diferit de zero, rezultatul mpririi este Infinity cu un semn care se stabilete dup semnele celor doi operanzi: + (plus) dac au acelai semn, sau - (minus)dac semnele operanzilor sunt diferite. Amintim c la numerele n virgul mobil n Java i valoarea zero are semn, deci exist +0.0 si -0.0. Exemplu n programul din fiierul VirgulaMobila.java, pe care l reproducem mai jos, se testeaz diferite operaii aritmetice n virgul mobil, inclusiv cele care au ca rezultate valori speciale.

/* Testarea operatiilor aritmetice cu numere in virgula mobila */ class VirgulaMobila { public static void main(String args[]) { double a=12.7865, b=-158.07, c=0.0, d=-0.0, inf1, inf2, n; float p=3476.15f, q=0.00237621f, r=0.0f, s=-0.0f; System.out.println("a/b="+(a/b)+" b/a="+(b/a)+" b%a="+(b%a)); System.out.println("a/c="+(a/c)+" b/c="+(b/c)); System.out.println("a/d="+(a/d)+" b/d="+(b/d));

59

Severin Bumbaru
System.out.println("c/d="+(c/d)+" d/c="+(d/c)); System.out.println("p/q="+(p/q)+" q/p="+(q/p)+" p%q="+(p%q)); System.out.println("p/r="+(p/r)+" p/s="+(p/s)); System.out.println("a/q="+(a/q)+" p/b="+(p/b)); inf1=a/c; inf2=a/d; n=c/d; System.out.println("a/inf1="+(a/inf1)+" a/inf2="+(a/inf2)); System.out.println("inf1/inf2="+(inf1/inf2)+" inf2/inf1="+ (inf2/inf1)); System.out.println("a*inf1="+(a*inf1)+" c*inf1="+(c*inf1)); } }

La executarea acestui program se afieaz urmtorul rezultat:

a/b=-0.08089137723793256 b/a=-12.362257068001407 b%a=-4.631999999999991 a/c=Infinity b/c=-Infinity a/d=-Infinity b/d=Infinity c/d=NaN d/c=NaN p/q=1462896.8 q/p=6.835752E-7 p%q=0.001879394 p/r=Infinity p/s=-Infinity a/q=5381.048097062204 p/b=-21.991205809728285 a/inf1=0.0 a/inf2=-0.0 inf1/inf2=NaN inf2/inf1=NaN a*inf1=Infinity c*inf1=NaN

Din aceste rezultate constatm c: - operaiile cu infinii i nedeterminri respect regulile cunoscute din matematic (mprirea la zero d rezultat infinit, iar 0/0, infinit impartit la infinit i zero nmulit cu infinit sunt nedeterminri); - dac cel puin un operand este n dubl precizie (double), rezultatul este n dubl precizie; dac ambii operanzi sunt n simpl precizie (float), rezultatul este float; - se verific egalitatea [b/a]*a+(b%a)=b, in care [b/a] este partea intreag a ctului b/a, iar b%a este restul mpririi ntregi a lui b la a; de exemplu, (-12)*12.7865-4.632=158.07.

Comparaia
Pentru datele in virgula mobil se aplic aceiai operatori de comparatie (relaionali) ca i pentru numerele ntregi.

Atribuirea compus
n cazul tipurilor de date reale se aplic urmtorii operatori de atribuire compus:+=, -=, *=, /=, %=.

60

Programarea orientata pe obiecte n limbajul Java

Tipul char Tipul de date char


Datele de tip char sunt caractere, adic simboluri tipografice elementare: litere, cifre, semne de punctuaie, simboluri matematice, etc. n limbajul Java, reprezentarea intern a caracterelor se face pe 2 octei (16 bii), n sistemul Unicode. In acest sistem, caracterele sunt codificate n memoria intern prin numere ntregi pozitive n intervalul [0, 65535]. n fluxurile de date de intrare/ieire i n fiiere, caracterele pot fi reprezentate i n alte coduri. Codul cel mai frecvent folosit n aceste scopuri este ASCII, n care reprezentarea caracterelor se face pe un singur octet, deci prin numere ntregi fr semn n intervalul [0, 255]. Remarcm ca datele de tip char sunt singurul tip de date ntregi fr semn din limbajul Java, mulimea de valori a acestui tip de date fiind intervalul de numere naturale [0, 65535]. Reprezentarea extern a caracterelor se face n una din urmtoarele forme: a/ punnd caracterul respectiv ntre apostrofuri: 'a', 'B', '+', '(', '3', etc; b/ folosind o secven escape, n care apare codul numeric hexazecimal al caracterului respectiv, n Unicode, de ex: '\u006c' sau '\uffff'; ntr-o astfel de secven, codul numeric al caracterului (format din patru cifre hexazecimale) este precedat de \u; c/ folosind o secventa escape pentru caracterele speciale din urmatorul tabel:

Caracterul
'\b' '\t' '\n' '\f' '\r' '\"' '\'' '\\'

Reprezentarea in Unicode
'\u0008'

Semnificatia deplasare la stnga cu o poziie (backspace) tabulare orizontal (horizontal tab) trecere la linie nou (line feed, NL) salt la pagina nou (form feed) ntoarcerea carului (carriage return, CR) ghilimele (double quote) apostrof (single quote) bar invers (backslash)

'\u0009'
'\u000a' '\u000c' '\u000d' '\u0022' '\u0027' '\u005c'

Datele de tip char pot fi folosite n operaii numerice, n care caz ele sunt interpretate drept numere intregi fr semn, conform cu reprezentarea lor intern prin numere binare. Din acest motiv, n limbajul Java datele de tip char sunt incluse n categoria celor de tipuri ntregi.

n programele Java, secvenele escape pot fi folosite pentru a reprezenta caracterele n orice loc din textul sursa. Peste tot unde ntlnete n textul surs caracterul \ (bara invers, backslash), compilatorul consider c urmeaza o secven escape, pe care o nlocuiete cu caracterele Unicode corespunztoare. Exemplul 1 irul de caractere "abc\"def" conine secventa escape \", care se va inlocui cu codul

61

Severin Bumbaru

caracterului ", obinndu-se irul abc"def. Acelasi ir de caractere putea fi scris sub forma "abc\u0022def", n care n loc de secvena escape \" s-a folosit direct cea care conine valoarea numerica din Unicode a caracterului ", respectiv \u0022. Exemplul 2 tiind c reprezentrile n Unicode ale literelor e i t sunt, respectiv, \u0074, instruciunea
System.out.println("Exemplu");

\u0065 i

poate fi scris sub forma


Sys\u0074\u0065m.ou\u0074.prin\u0074ln("Ex\u0065mplu");

Desigur c o astfel de nlocuire a caracterelor prin secvene escape nu este justificat n cazul caracterelor obinuite, dar este util n cazul folosirii caracterelor speciale, cum sunt caracterul de trecere la lini noua '\n' i altele.

Operaii i operatori pentru date de tip char


n limbajul Java, tipul char este considerat tip de date ntregi. n consecin, toate operaiile care se aplic tipurilor ntregi se aplic i asupra tipului char. Atunci cnd un caracter se folosete ca numar ntreg se opereaz, evident, cu reprezentarea intern a caracterului respectiv, tratat ca numar natural. Exemplu n programul de mai jos, dat in fiierul TestChar.java, se testeaz unele operaii cu date de tip char.

/* Operatii cu date de tip char */ class TestChar { public static void main(String args[]) { char c1='A', c2='a', c3='b', c4='1', c5='*', c6='\n'; System.out.println(c1+" "+c2+" "+c6+" "+c4+" "+c5+" "+c3); System.out.println((int)c1+" "+(int)c2+" "+(int)c6+" "+ (int)c4+" "+(int)c5); System.out.println(c1+c2); System.out.println(c1*c2); System.out.println((char)107); System.out.println('2'+" "+(int)'2'+" "+'3'+" "+(int)'3'+ " "+('2'+'3')); } }

La executarea acestui program, rezultatele afiate pe ecran sunt cele de mai jos:

A a 1 * b 65 97 10 49 42 162 6305 k 2 50 3 51 101

62

Programarea orientata pe obiecte n limbajul Java Dup afiarea caracterelor A i a s-a transmis ctre dispozitivul de afiare caracterul '\n', care a fost interpretat drept comanda de trecere la linie nou. Dup aceasta au fost afsate caracterele 1, * i b. Pe linia urmtoare sunt afiate caracterele deja afiate anterior, convertite n numere ntregi. Se observ c n Unicode caracterul 'A' este reprezentat prin numarul 65, caracterul 'a' prin numarul 97, caracterul '\n' prin 10 etc. Pe urmtoarele dou linii sunt afiate rezultatele operaiilor 'c1'+'c2' si 'c1'*'c2', obinndu-se respectiv valorile numerice 162 si 6305. Se observ c, ntruct caracterele au fost folosite ca operanzi ai unor operatori aritmetici, rezultatele obinute sunt numerice (de tip int). Pe linia urmtoare se afieaz numrul 107 convertit din int n char i interpretat deci drept 'k'; Pe ultima linie putem observa deosebirea dintre forma extern a caracterului (literalul de tip char) i codificarea lui interna. Literalul de tip char '2' este caracterul 2 si nu numarul 2. n consecin, acest caracter nu se reprezinta intern prin numarul ntreg 2, ci prin numrul ntreg 50. n mod corespunzator, caracterul '3' se reprezinta intern prin numarul 51. Suma codurilor numerice ale celor doua caractere este, evident, numrul 101.

ntrebri
Nivel 1
1. Ce este un comentariu? 2. Ce fel de comentarii pot s apar n fiierele surs Java? 3. Cum se reprezint un ir n program? 4. Ce este concatenarea i care este operatorul prin care se realizeaz? 5. Prin ce metode se afieaz un ir de caractere pe ecran? 6. Ce sunt identificatorii i cum se alctuiesc ei n Java? 7. Ce sunt cuvintele cheie? 8. Ce este un literal? 9. Ce separatori se folosesc n limbajul Java? 10. Ce sunt operatorii? 11. Ce este efectul lateral al operatorului? 12. Toi operatorii au efect lateral? 13. Ce sunt variabilele? 14. Ce este numele variabilei? 15. Ce se nelege prin declararea variabilei? 16. Ce este o variabil final? 17. Ce este un tip de date? 18. Ce tipuri de date primitive exist n limbajul Java? 19. Care este mulimea de valori a tipului boolean? 20. Care este operatorul de negaie, asupra crui tip de date se aplic i ce efect are? 21. Ce sunt operatorii logici & si &&? 22. Ce sunt operatorii logici | si ||? 23. Care sunt tipurile de date numerice? 24. Ce este operaia de atribuire?

63

Severin Bumbaru 25. Cum acioneaz operatorii == i !=? 26. Ce efect are operatorul logic ^? 27. Ce contine o declaraie de tip? 28. Ce este conversia de tip? 29. Ce este castul i care este forma lui sintactic? 30. Care sunt operatorii de incrementare i decrementare? 31. Ce operatori de comparaie se folosesc n cazul datelor de tipuri ntregi? 32. Cum se reprezint intern datele de tipuri ntregi? 33. Cum se scriu literalii n sistemul octal? 34. Cum se scriu literalii in sistemul hexazecimal? 35. Pot avea semn literalii octali i cei hexazecimali? 36. Ce sunt datele n virgul mobil i ce corespondent au ele n matematic? 37. Ce tipuri de date n virgul mobil exist n Java? 38. Ce sunt literalii n virgul mobil? 39. Ce valori speciale pot avea literalii n virgul mobil? 40. Ce operaii aritmetice se poa efectua asupra numerelor n virgul mobil? 41. Ce se ntmpl dac, la o mprire n virgul mobil, mpritorul are valoarea zero? 42. Ce fel de date conine tipul char? 43. Cum se reprezint literalii de tip char? 44. Ce este o secven escape? dai exemple. 45. Ce operaii se pot face supra datelor de tip char? 46. Care sunt operatorii de atribuire compus i ce efect au?

Nivel 2
1. Ce proprieti are operatorul de concatenare? 2. Este concatenarea asociativ? Dar comutativ? 3. Se poate oare folosi metoda print() n loc de println()? 4. Cu ce fel de caracter ncep n Java numele de clase? 5. Ce deosebire este ntre literali i identificatori? 6. De cte feluri sunt operatorii dup numrul de operanzi? 7. Cum se plaseaz operatorii unari n raport cu operanzii lor? Dar cei binari? 8. Exist operatori ternari? 9. Dai o definiie conceptului de variabil. 10. Prin ce simbol se termina o declaraie de variabile? 11. n ce mod se iniializeaz o variabil? 12. Ce sunt tipurile de date primitive? 13. Ce se stabilete la definirea unui tip de date primitive? 14. Ce sunt tipurile de date derivate? 15. Ce este o clas i n ce fel de limbaje se folosete? 16. Ce deosebire exist ntre modurile n care acioneaz operatorii logici & i &&? 17. Ce deosebire exist ntre modurile n care acioneaz operatorii logici | i ||? 18. Ce deosebiri exist ntre operatorii = i ==? 19. n ce situaii este obligatorie folosirea castului la conversiile datelor de tipuri primitive? 20. Care sunt operatorii aritmetici unari? 21. Ce deosebire este ntre aezarea operatorului de incrementare sau decrementare n faa operandului i dup acesta?

64

Programarea orientata pe obiecte n limbajul Java 22. Care sunt domeniile de valori pentru date de tipuri intregi? 23. Ce avantaj prezint folosirea literalilor hexazecimali sau octali fa de cei zecimali? 24. Cum se stabilete tipul rezultatului operaiilor aritmetice cu numere intregi? 25. n ce caz rezultatul unei operaii aplicate asura unui operand de tip byte este tot de tip byte? 26. Ce este mprirea ntreag? 27. Ce este excepia de mprire la zero i n ce situaii poate s apar? 28. Ce este depirea binar i n ce situaii poate s apar? 29. Cum acioneaz operatorul <<? 30. Cum acioneaz operatorul >>? 31. Ce deosebire este ntre operatorii >> i >>>? 32. Cum acioneaz operatorii ~, &, | i ^ cnd operanzii sunt de tipuri ntregi? 33. Cum se reprezinta intern datele n virgul mobil? 34. Ce sunt cifrele semnificative ale unui numr n virgul mobil? 35. n ce situaii rezultatul unei operaii n virgul mobil are valoarea infinit? 36. Cum se reprezint intern datele de tip char?

65

Severin Bumbaru

Expresii. Instruciuni simple i instruciuni structurate. Tratarea excepiilor


Expresii cu date primitive; precedena operatorilor; Expresia condiionala Instruciuni simple Principiile programrii structurate; Structurile de control fundamentale; Tehnica rafinrilor succesive; Instruciuni structurate (structuri de control) Blocul ca realizare a structurii secveniale; variabile locale i domenii de vizibilitate; Structura alternativ (if .. else); Structura de comutare (switch); Structuri repetitive Ciclul cu test iniial (while); Ciclul cu test final (do .. while); Ciclul for Instruciuni etichetate; Terminarea abrupt a execuiei instruciunilor structurate; Tratarea excepiilor n limbajul Java (try .. catch) ntrebari 66 70 71 74 74 78 79 79 81 85 86 86 89 90 93 93 95 97

Expresii cu date primitive


n programare, expresia este o combinaie permis ("legal", corect) de simboluri, care reprezint o valoare. Tipul expresiei este acelai cu tipul valorii ei. Putem avea, deci, expresii de tip boolean, int, long, float, double etc. Fiecare limbaj de programare are regulile sale, prin care se stabilete ce expresii sunt permise sau nepermise. n limbajul Java, expresia poate conine literali, variabile, operatori, operanzi, funcii i paranteze i trebuie s poat fi evaluat (calculat), astfel nct s se obin o valoare.

66

Programarea orientata pe obiecte n limbajul Java Construirea expresiei se face pas cu pas, avnd n vedere c: - un literal sau o variabil constituie o expresie; tipul i valoarea acestei expresii sunt cele ale literalului sau variabilei respective; Exemple de astfel de expresii sunt:
true -176 1.358746E-12 "sir de caractere" beta

- un operator mpreun cu operanzii lui constituie o expresie.

De exemplu:
alpha+3.765 (s-a folosit operatorul binar +) alpha++ (s-a folosit operatorul unar postfix ++) -alpha (s-a folosit operatorul unar prefix -)

- o expresie cuprins ntre paranteze constituie o nou expresie, a crei valoare este identic cu cea a expresiei din interior;

De exemplu:
(-176) (alpha++) (alpha+3.765)

- valoarea unei expresii poate fi folosit ca operand ntr-o alt expresie.

De exemplu:
(alpha+3.765)*(alpha++)

Se observ c, procednd astfel, se pot construi expresii din ce n ce mai complicate. Utilizarea funciilor n expresii va fi discutat ulterior. Mernionm ns c i operatorii acioneaz tot ca nite funcii. De exemplu, evaluarea expresiei alpha+3.765 este, de fapt, calcularea unei funcii, care are ca argumente valorile variabilei alpha i literalului 3.765 i are ca valoare suma acestora.

67

Severin Bumbaru

Expresia poate fi reprezentat ca un arbore sintactic, care are ca frunze literali sau variabile, iar ca rdcin are valoarea expresiei. Fiecare nod al arborelui sintactic conine un operator sau o funcie, care are ca operanzi valorile subexpresiilor din nodurile-fii. De exemplu, expresia
a*b+3*c

corespunde urmtorului arbore:

Precedena operatorilor
La evaluarea unei expresii, prezinta o importan deosebit ordinea n care se aplic operatorii pe care i conine, deoarece de aceast ordine poate s depind valoarea expresiei. n toate limbajele de programare, n care se folosesc expresii, se stabilesc i anumite reguli de preceden i de asociativitate, pe baza crora se stabilete ordinea de evaluare. Fiecrui operator i se asociaz o preceden, adic un nivel de prioritate n aplicarea operatorului respectiv. De exemplu, n expresia a+b*c operatorul * se va aplica naintea operatorului +, deoarece are precedena superioar. n consecin, aceasta expresie se va calcula ca i cnd ar fi scris sub forma a+(b*c). n limbajul Java, la stabilirea ordinii operaiilor se aplica urmtoarele reguli: - operatorii unari se aplic naintea celor binari; - expresiile din interiorul parantezelor se evalueaz naintea celor din exterior; - dac, ntr-o expresie, toi operatorii au acelai nivel de preceden, ei se aplic de la stnga la dreapta; - operanzii unui operator se evalueaza nainte de a se aplica operatorul respectiv (deci operatorul se aplic ntotdeauna asupra valorilor operanzilor si); dac operaia este binar, operandul din partea stng se evalueaz naintea celui din partea dreapt; - nivelul de preceden al operatorilor se stabilete conform cu tabela de mai jos, n care:

toi operatorii din aceeai celul a tabelei au acelai nivel de preceden; operatorii de pe un nivel superior se aplic naintea celor de pe nivelurile inferioare. Tabela de preceden a operatorilor n limbajul Java

68

Programarea orientata pe obiecte n limbajul Java


. ++ -+ unar ! * + binar << < <= >> > instanceof != & ^ | && || ?: = <<= += -= >>= |= *= /= %= >>>= &= ^= [] ~ new / () - unar (<tip>) % - binar >>> >=

==

Exemplu n programul de mai jos, a crui surs se gsete n fiierul EvExpresii.java, se calculeaz unele expresii cu numere ntregi i se afieaz rezultatele.
/* Evaluarea expresiilor */ class EvExpresii { public static void main(String args[]) { int a=23, b=500, c=17, d; System.out.println((a+b*c)+" "+((a+b)*c)+" "+(b/a*c)+ " "+(b/(a*c))); System.out.println((-a+b*c++/3+(d=c--%4))+" "+c+" "+d); System.out.println((d<1 && c--==0)+" "+c+" "+d); System.out.println((d<1 & ++d<c)+" "+c+" "+d); } }

La executarea acestui program, se obin pe ecran urmtoarele rezultate:

8523 8891 357 1 2812 17 2 false 17 2 false 17 3

Sa urmrim acum desfurarea calculelor care au condus la aceste rezultate. - s-a evaluat expresia (a+b*c), efectundu-se mai nti nmulirea b*c, deoarece operatorul

69

Severin Bumbaru * are precedena superioar operatorului +, i s-a obinut ca valoare numrul ntreg 8523; - urmtorul operator, +, are ca operanzi numrul ntreg 8523 i irul de caractere " ". n consecin, s-a convertit numarul 8523 ntr-un ir (trecndu-se de la forma intern a acestuia la cea extern) i s-a obinut irul "8523", care s-a concatenat cu irul " ", obinndu-se irul "8523 "; - s-a calculat expresia ((a+b)*c) obinndu-se numrul ntreg 8891; de data aceasta, s-a calculat mai nti subexpresia a+b, deoarece este ntre paranteze; - s-a convertit numrul 8891 din forma intern n cea extern i s-a concatenat cu irul obtinut anterior i cu sirul " ", rezultnd irul "8523 8891 "; - s-a calculat expresia (b/a*c). ntruct operatorii / i * au acelai nivel de preceden, calculul s-a fcut de la stnga la dreapta, astfel: . s-a efectuat mprirea ntreag b/a, obinndu-se valoarea 21; . s-a efectuat nmulirea 21*c, obinndu-se rezultatul 357. - s-a concatenat forma extern a numrului 357 cu irul obinut anterior i cu irul " ", obinndu-se irul "8523 8891 357 "; - s-a calculat expresia (b/(a*c)), efectundu-se acum mai nti nmultirea a*c, apoi mprirea ntreag a valorii lui b la rezultatul nmulirii i s-a obinut valoarea 1; - s-a concatenat forma extern a acestei valori cu irul obinut anterior, obinndu-se irul "8523 8891 357 1" care a fost afiat pe ecran, dup care s-a trecut la linie nou. Recomandm s urmrii n acelai mod cum s-au calculat i afisat celelalte expresii. Menionm c: - la evaluarea expresiei (-a+b*c++/3+(d=c--%4))prezinta interes cu ce valori intr n calcul variabila c i ce valoare are operandul din dreapta al ultimului operator +; - avand n vedere c valoarea expresiei d<1 este false, la aplicarea operatorului && nu s-a mai evaluat al doilea operand, deci variabila c a rmas la valoarea ei anterioar, in timp ce la aplicarea operatorului & a fost evaluat i al doilea operand, astfel c variabila d a fost incrementat.

Expresia condiional
Urmnd "tradiia" limbajului C, n limbajul Java exist operatorul ternar (cu trei operanzi) ?: numit operatorul condiional, care este utilizat n cadrul urmtoarei expresii condiionale:
operand1 ? operand2 : operand3

unde: operand1 - expresie boolean; operand2 ioperand3 - expresii de tipuri compatibile: fie ambii operanzi de tip boolean, fie ambii de tipuri numerice, fie ambii de tipuri referin. Evaluarea expresiei decurge astfel: - se evalueaz operand1 obinndu-se o valoare boolean; - dac operand1 are valoarea true, atunci valoarea expresiei condiionale este cea care se obine evalund operand2; altfel, este cea care se obine evalund operand3.

Exemplu n programul de mai jos, dat i n fiierul ExprCond.java, se exemplific mai multe cazuri de utilizare a expresiei condiionale.

70

Programarea orientata pe obiecte n limbajul Java

/* Testarea expresiei conditionale */ class ExprCond { public static void main(String args[]) { int m=17, n=-6, p=0, q=0; System.out.println(m>n ? m+1 : 2*n-2); System.out.println(m<=n ? 3*m : m-n); /* Se evalueaza numai operandul 2 */ System.out.println((m>=6 ? ++p*n : ++q-m)+" "+p+" "+q); /* Se evalueaza numai operandul 3 */ System.out.println((m<n+3 ? m-- : n++)+" "+m+" "+n); /* Un exemplu in care operanzii 2 si 3 sunt tot expresii conditionale */ System.out.println(m>p ? (n<0? m+1 : m-2) : (m>n ? m : n)); } }

Executnd acest program, obinem pe ecran urmatoarele rezultate:

18 23 -6 1 0 -6 17 -5 18

Din aceste rezultate putem constata cu uurin c s-au evaluat de fiecare dat numai acei operanzi, care erau necesari n evaluarea expresiei condiionale. n ultima instruciune se ilustreaz i un caz de utilizare drept operanzi a unor expresii condiionale.

Instruciuni simple
n limbajul Java, procesul de calcul este controlat de instruciuni (enunuri). Fiecare instruciune indic una sau mai multe aciuni pe care trebuie s le execute calculatorul. Corpul oricrei metode este constituit dintr-o succesiune de instruciuni. Executarea metodei const n executarea acestor instruciuni ntr-o ordine determinat. Instruciunile pot fi grupate n blocuri. Dup structura lor, instruciunile pot fi simple sau structurate. Instruciunile simple nu conin n interiorul lor alte instruciuni. Exist trei categorii principale de instruciuni (enunuri) simple: declaraiile de variabile locale, instruciunileexpresie i instruciunea vid. La scrierea lor se respect urmtoarele reguli:

71

Severin Bumbaru

toate instruciunile simple se termin cu caracterul ';' (punct i virgul). Instruciunea vid este format numai din acest caracter; declaraiile de variabile locale servesc pentru a specifica tipul, numele i (opional) valoarea iniial a variabilelor. Forma sintactic i utilizarea declaraiilor au fost prezentate anterior; instruciunile-expresie sunt formate dintr-o expresie de atribuire, de incrementare/decrementare sau de invocare de metod, urmat de caracterul ';'.

Not pentru programatorii n alte limbaje n limbajul Java, declaraiile de variabile locale sunt considerate instruciuni executabile, deci ele au efect la executarea programului. n majoritatea limbajelor compilate, declaraiile de variabile locale sunt luate n consideraie numai la compilare, deci sunt considerate instruciuni neexecutabile. n limbajul Java declaraiile sunt, de asemenea, luate n consideraie de compilator, care verific dac declaraia este corect sintactic i, de asemenea, verific la fiecare apariie a unei variabile locale n programul surs dac: - variabila respectiv a fost declarat; - tipul variabilei corespunde contextului n care este folosit variabila respectiv; - variabila are deja o valoare. Efectul declaraiilor de variabile locale din programele Java const n faptul c n momentul execuiei se aloc n memorie (pe stiv) spaiu pentru variabilele respective i se introduc valorile iniiale. n consecin: - declaraiile de variabile pot fi plasate oriunde n interiorul unui bloc (pot fi puse la nceputul acestuia sau pot fi intercalate cu alte instruciuni); - "executarea" declaraiei are loc de la stnga la dreapta i de sus n jos, astfel c la evaluarea expresiilor prin care se calculeaz valoarea iniial a unei variabile, se consider cunoscute valorile iniiale ale variabilelor declarate anterior. Instruciunile-expresie pot fi instruciuni de atribuire, de incrementare/decrementare sau de invocare de metod. Instruciunile de atribuire sunt instruciuni prin care unei variabile i se atribuie o nou valoare, modificndu-se astfel valoarea avut anterior. Instruciunea de atribuire este o expresie de atribuire sau de atribuire compus urmat de caracterul ';' (punct i virgul) deci are urmtoarea form sintactic:
expresie_de_atribuire;

Valoarea acestei expresii se ignor, astfel c aciunea care se efectueaza la executarea instruciunii de atribuire const numai n efectul lateral al acesteia, adic n modificarea valorii variabilei din partea stnga. De exemplu, dac a i b sunt variabile numerice, atunci a=b+7 este o expresie de atribuire, n timp ce
a=b+7;

n care la sfritul expresiei de atribuire s-a pus terminatorul punct i virgul, este o instruciune de atribuire. Se pot face atribuiri n lan, ca n exemplul urmtor: a=b=c=d=3;

72

Programarea orientata pe obiecte n limbajul Java

Instruciunile de incrementare/decrementare sunt instruciuni formate dintr-o expresie de incrementare sau decrementare, urmat de caracterul ';' (punct i virgul). De exemplu, a++ este o expresie de postincrementare, n timp ce
a++;

este o instruciune de postincrementare. Instruciunile de invocare de metod sunt instruciuni prin care se cere executarea unei metode, transmindu-i-se acesteia valorile parametrilor. Instruciunea const din numele metodei, urmat de o pereche de paranteze care conine valorile parametrilor i se termin prin caracterul ';' (punct i virgul). Aciunea cerut de instruciune const n executarea metodei respective. Daca metoda este o funcie, valoarea funciei se ignor, meninndu-se numai efectele laterale ale metodei respective. De exemplu:
System.out.println("ir de caractere"); este o instruciune prin care se invoc metoda println a cmpului out din clasa System, transmindu-i-se parametrul "ir de caractere". Aciunea care se

realizeaz astfel const din afiarea pe ecran a irului primit ca parametru. Exemplu n fiierul Instructiuni.java se d un exemplu simplu de program care conine o secvena de instruciuni simple: o declaraie de variabile, dou instruciuni de atribuire, o instruciune de incrementare i o invocare de metod.
/* Exemple de instructiuni simple */ class Instructiuni { public static void main(String args[]) { double a=3.76, b=-15, c=2*a-b, d, e; // declaratie de variabile d=3*a-7; // instructiune de atribuire b++; // instructiune de incrementare e=b-17; // instructiune de atribuire /* invocare de metoda */ System.out.println("a="+a+" b="+b+" c="+c+" d="+d+" e="+e); } }

Pentru mai multa claritate, fiecare instruciune a fost scrisa pe o linie de program separat i a fost nsoit de un comentariu. Se permite, ns, scrierea mai multor instruciuni pe o singur linie sau, invers, o instruciune se poate extinde pe mai multe linii. Singura restricie este ca trecerea de la o linie la alta s se fac la nivelul unui operator sau separator (s nu se rup in doua un simbol format din mai multe caractere, un identificator sau un literal). Remarcm c la declararea variabilei c s-a luat n consideratie faptul c variabilele a i b au deja valori iniializate anterior.

73

Severin Bumbaru

Principiile programrii structurate


Programarea structurat este o orientare n conceperea i alctuirea programelor, avnd ca obiectiv o mai bun gestionare a complexitii acestora, innd cont de particularitile gndirii umane. Conform metodei programrii structurate, la conceperea unui program, este recomandabil s se respecte urmtoarele principii: 1. Teorema de structur: orice program poate fi ntocmit folosind numai trei structuri de control fundamentale: structura secvenial, structura alternativ i structura repetitiv. 2. La conceperea programelor se recomand s se aplice tehnica de elaborare descendent (n englez Top-Down), numit i tehnica rafinrilor succesive. 3. Domeniile de valabilitate (de vizibilitate) ale variabilelor i structurilor de date trebuie s fie limitate. n limbajul Java, pentru rezolvarea problemei realizrii creterii eficienei muncii programatorilor s-a adoptat concepia modern a programrii orientate pe obiecte. In consecin, modulele de program sunt mici i rolul programrii structurate este sensibil redus. Totui, fiecare metod din limbajul Java este un mic program, la elaborarea cruia se aplic principiile programrii structurate, ceeace s-a avut n vedere i la adoptarea instruciunilor de baz oferite de acest limbaj. Este deci util ca i programatorii n Java sa cunoasc principiile fundamentale ale programrii structurate.

Structurile de control fundamentale


Aceste structuri se refer la modalitile n care se pot nlnui instruciunile dintr-un program, deci n care se transmite "controlul" de la o instruciune la alta n timpul executrii programului. Conform "teoremei de structur", sunt suficiente trei astfel de "structuri de control":

1. Structura secvenial
n mod "natural", se consider c instruciunile se execut n ordinea n care acestea figureaz n program. nlnuirea instruciunilor (transmiterea "controlului" de la o instruciune la alta) se face, n acest caz, conform schemei logice din figura 1.

74

Programarea orientata pe obiecte n limbajul Java

n pseudocod, aceeai secven de program se scrie astfel:


<instruciunea_1> <instruciunea_2> .... <instruciunea_n>

Exist, deci, un numr oarecare (n) de instruciuni, care se execut una dupa alta, n ordinea n care sunt scrise n program. Toate exemplele de programe date n capitolele i seciunile anterioare au structura secvenial.

2. Structura alternativ (condiional, de decizie)


Un fragment de program are structura alternativ (numit i structur condiional sau de decizie), atunci cnd se alege una din dou ci posibile, n funcie de modul n care este satisfcut sau nu o anumit condiie. Schema logic a structurii de control alternative este dat n figura 2.

n aceast schem logic, Condiie este o expresie boolean. Executarea acestui fragment de program decurge astfel: se verific mai nti dac este satisfcut condiia. Dac ea este satisfcut, deci expresia Condiie are valoarea true, se execut Instruciunea 1, iar n caz contrar se execut Instruciunea 2. In pseudocod, acest fragment de program se scrie astfel:
Dac <condiie> atunci <instruciunea_1>

75

Severin Bumbaru
altfel <instruciunea_2> Sfarit_dac

n unele convenii de pseudocod, n loc de Instruciunea_1 i Instructiunea_2 pot fi puse secvene de instruciuni. Se observ c exist o asemnare ntre instruciunea alternativ i expresia condiional. n ambele cazuri se verific dac este satisfacut o condiie i - n funcie de rezultatul obtinut se alege una din dou variante posibile. Deosebirea este urmtoarea: - n cazul expresiei condiionale se alege una din cele dou expresii coninute n aceasta, iar rezultatul obinut este valoarea expresiei astfel alese; - n cazul structurii de control alternative se alege una din cele doua instruciuni coninute n aceast structur; instruciunea astfel aleas este executat, iar rezultatul obinut este efectul (lateral) produs de executarea acestei instruciuni.

3. Structura repetitiv (ciclu, bucl)


n cazul structurii de control repetitive, o instruciune sau o secven de instruciuni se repet ct timp este satisfacut o anumit condiie. Structura repetitiv fundamental, acceptat n teoria programrii structurate, este cea de ciclu cu test iniial. Schema logic a acestei structuri de control este dat n figura 3.

Executarea acestei structuri are loc astfel: 1. se evalueaz expresia boolean care reprezint Condiia; 2. dac valoarea acestei expresii este true, deci condiia este satisfacut, se merge pe ramura DA i se executa instruciunea din corpul ciclului, dup care se trece la punctul 1; 3. altfel (deci dac condiia nu este satisfacut) se merge pe ramura NU i se iese din ciclu. Se observ, deci, c se va executa instruciunea n mod repetat, ct timp este satisfcut condiia. n pseudocod, aceast structur de control se programeaz astfel:
ct_timp <condiie> execut <instruciune> sfrit_ciclu

76

Programarea orientata pe obiecte n limbajul Java n unele versiuni de pseudocod, n loc de o singur <instruciune> se poate pune o secven de instruciuni. Dei, din punct de vedere al teoriei programrii structurate, ciclul cu test iniial este suficient ca structur repetitiv, n multe limbaje de programare (inclusiv Java), din motive de comoditate a programrii se admite i o a doua form de astfel de structur, numit ciclu cu test final. Schema logic a acestui ciclu este dat n figura 4.

Se observ c, n aceast schem logic, executarea instruciunii se repet, ca i n cazul ciclului precedent, ct timp este satisfacut condiia. Deosebirea dintre cele dou forme de cicluri este c, n ciclul cu test iniial, condiia este evaluat nainte de a se executa instruciunea din corpul ciclului, n timp ce n ciclul cu test final evaluarea condiiei se face dup ce instruciunea a fost deja executat. Aceasta este o deosebire important, deoarece, n cazul ciclului cu test initial, este posibil ca instruciunea s nu se execute niciodat (dac chiar de la prima evaluare condiia nu este satisfacut), n timp ce la ciclul cu test final instruciunea din corpul ciclului va fi executat cel puin o dat. Aa dar, ciclul cu test final poate fi nlocuit prin unul echivalent cu test iniial, dar nu i invers. Iat dece, n teoria programrii structurate, ciclul cu test iniial este considerat ca structur de control fundamental, n timp ce cel cu test final este o structur de control admis, dar nu fundamental. n pseudocod, ciclul cu test final reprezentat prin schema logic din figura 4 se scrie sub forma general:
execut <instruciune> ct_timp <condiie>

n unele limbaje (de exemplu n Pascal) pentru ciclul cu test final se adopt o schem logic n care singura deosebire fa de cea din figura 4 este doar prin faptul c cele dou ramuri DA i NU ii schimb locurile ntre ele, ceeace n pseudocod se scrie sub forma:
execut <instruciune> pn_cnd <condiie>

77

Severin Bumbaru n acest caz, instruciunea din corpul ciclului se va repeta ct timp NU este satisfacuta condiia, deci pn cnd se va constata pentru prima oar c ea este satisfcut. n ambele cazuri, n unele variante de pseudocod instruciunea din corpul ciclului poate fi nlocuit printr-o secvena de instruciuni. Dac se are n vedere utilizarea limbajului Java, utilizarea unei secvene nu este necesar, deoarece ea se poate nlocui printr-o singur instruciune compus, aa cum se va arta ulterior. Din examinarea structurilor de control prezentate n acest capitol, putem constata o proprietate important: schemele logice ale tuturor structurilor de control admise de metoda progrmarii structurate au fiecare un singur punct de intrare i un singur punct de ieire. Datorit acestei proprieti, ele pot fi folosite la elaborarea unor programe complexe prin tehnica rafinrilor succesive, aa cum se va arta n seciunea urmtoare.

Tehnica rafinrilor succesive


Adoptarea metodei programrii structurate a fcut posibil elaborarea programelor prin tehnica rafinrilor succesive (engl.: stepwise refinement), cunoscut i sub numele de tehnica descendent (engl.:top-down), care va fi prezentat succint n cele ce urmeaz. La elaborarea unui program se pornete de la specificaia acestuia, n care se precizeaz CE trebuie sa fac programul respectiv (CE problem trebuie rezolvat, CE rezultate trebuie obinute) i se ajunge n final la programul propriu-zis, care arat CUM trebuie acionat pentru a se obine aceste rezultate. De cele mai multe ori, programul elaborat conine un numr mare de instruciuni, cu numeroase ramificaii i cicluri. Scrierea unui astfel de program poate fi o sarcin extrem de dificil i greu de ndeplinit, dac nu se procedeaz sistematic. n plus, dac programul nu este suficient de clar i de bine documentat, va fi extrem de greu sau chiar imposibil s fie depanat (s se corecteze eventualele erori de programare) i s fie modificat ulterior, dac se modific specificaia. Tehnica rafinrilor succesive ofer o cale de a parcurge acest drum de la CE la CUM n mai muli pai, astfel nct s se porneasc de la un numr mic de enunuri (pseudoinstruciuni) de nivel de abstractizare ridicat, dup care - la fiecare pas de rafinare - fiecare din aceste instruciuni se descompune n mai multe instruciuni de nivel de abstractizare mai cobort (mai "concrete"), pn cnd se ajunge la instruciuni scrise direct n limbajul de programare folosit (de exemplu n Java). Se pune deci un accent deosebit pe abstractizarea datelor si a instruciunilor. Dupa cum arta E.W.Dijkstra, abstractizarea este calea prin care omul stapnete complexitatea. Dac privim schemele logice ale structurilor de control fundamentale, permise de metoda programrii structurate, constatm cu uurin c att blocurile care conin instruciuni, ct i structurile de control admise de metoda programarii structurate au fiecare un singur punct de intrare i un singur punct de ieire. Aceasta nseamn c orice bloc care conine o instruciune poate fi nlocuit n schema respectiv printr-o structur de control. Ca urmare, se poate aplica urmtoarea cale de elaborare a programului, specific tehnicii rafinrilor succesive: - iniial se consider c programul este alcatuit dintr-o singur pseudoinstruciune, de nalt

78

Programarea orientata pe obiecte n limbajul Java nivel de abstractizare, care const chiar din specificaia problemei pe care o va "rezolva" programul respectiv; - la pasul de rafinare urmtor, aceast "problem" se descompune n dou sau mai multe "subprobleme"; aceasta nseamn c unica pseudoinstruciune existent iniial se nlocuiete prin una din structurile admise de metoda programrii structurate (structura secvenial, alternativ sau repetitiv); aceast structur conine n ea una sau mai multe instruciuni sau pseudoinstruciuni; - la paii de rafinare urmtori, fiecare pseudoinstruciune, care nu are corespondenta direct n limbajul de programare utilizat, se inlocuiete, de asemenea, prin una din structurile de control admise; textul pseudoinstruciunii nlocuite poate fi, totusi, meninut sub form de comentariu, astfel nct s se neleag mai uor programul; - se continu acest proces de rafinri succesive, pn cnd toate instruciunile astfel obinute au corespondent n limbajul de programare utilizat.

Instruciuni structurate
Limbajul Java a fost alctuit astfel, nct programatorul este obligat sa respecte principiile programrii structurate. Aceasta se datorete faptului ca instruciunile structurate ale limbajului sunt cele prevzute de aceast metod de programare. Exist urmtoarele instruciuni structurate:

blocul - prin care se realizeaz structura secvenial; instruciunile if si if .. else - prin care se realizeaz structura alternativ; instruciunea switch - prin care se realizeaz structura de comutare (de selecie); instruciunile while, do .. while i for - prin care se realizeaz structurile repetitive.

n plus, n limbajul Java exist o structur de control dedicat tratrii excepiilor care apar n timpul executrii programului, realizat prin instruciunile try .. catch

Blocuri
Blocul este o secven de instruciuni cuprins ntre acolade. Forma sintactic a blocului este, deci, urmtoarea:
{ secven_de_instruciuni } unde secven_de_instruciuniconst dintr-un

numr oarecare de instruciuni succesive, putnd fi i vid. Instruciunile din aceast secven pot fi att simple, ct i structurate, inclusiv alte blocuri. Din punct de vedere al programrii structurate, blocul este realizarea structurii de control secveniale. Aceasta inseamn c instruciunile dintr-un bloc se execut una dupa alta, n ordinea n care ele sunt scrise n program. Tocmai de aceea se i folosete termenul secven

79

Severin Bumbaru de instruciuni pentru a indica ce conine blocul.

Exemplu n programul de mai jos, coninut n fiierul Blocuri.java, se exemplific folosirea unor blocuri imbricate (cuprinse unul n altul). Prin comentarii s-a semnalat nceputul i sfritul fiecrui bloc, dei aceasta nu se face n mod curent. Remarcm c nsui corpul metodei main (i al oricrei alte metode) este tot un bloc. Fiecare bloc conine att declaraii de variabile, ct i instruciuni-expresie
/* Exemplu de program care contine blocuri imbricate */ class Blocuri { // aici incepe corpul clasei Blocuri public static void main(String args[]) { // aici incepe blocul A int m=8, n=-3; double u=m*3.5+32, v=2, w; w=m*u+v; System.out.println("m="+m+" n="+n+" u="+u+" v="+v+" w="+w); m++; { // aici incepe blocul B, continut in A int a=5; double p=m*w-3.5, q; q=n*p-a; // s-a folosit n din blocul exterior { // aici incepe blocul C continut in B System.out.println("m="+m+" a="+a+" p="+p+" q="+q); } // aici se termina blocul C } // aici se termina blocul B } // aici se termina blocul A (corpul metodei main) } // aici se incheie corpul clasei Blocuri

La executarea acestui program se afieaz urmtoarele rezultate:

m=8 n=-3 u=60.0 v=2.0 w=482.0 m=9 a=5 p=4334.5 q=-13008.5

Remarcm c: - n expresiile prin care se calculeaz valoarea iniial a variabilei u s-a luat n consideraie valoarea variabilei m determinat anterior; - n blocul B, la calcularea valorii iniiale a variabilei p s-au folosit valorile variabilelor m si w calculate la executarea unor instruciuni-expresie anterioare; se confirm astfel c iniializarea variabilelor nu se face la compilare, cnd aceste valori nu sunt cunoscute, ci la executarea declaraiei.

Variabile locale i domenii de vizibilitate


Variabilele declarate ntr-un bloc sunt variabile locale ale blocului respectiv. Domeniul de vizibilitate al unei variabile locale ncepe n locul din program n care aceasta a fost declarat i se ncheie la sfritul blocului care conine declaraia respectiv. Variabila este deci "vizibil" (poate fi utilizat) n propriul su bloc i n toate blocurile interioare acestuia, n domeniul de vizibilitate.

80

Programarea orientata pe obiecte n limbajul Java Exemplu: n programul din fiierul Blocuri.java, dat ca exemplu mai sus, variabilele m, n, u, v i w sunt declarate n blocul A (n nsui corpul metodei main) i sunt vizibile (pot fi utilizate) att n acest bloc, ct i n blocurile interioare B i C. n schimb variabilele a, p i q pot fi utilizate numai n blocul B, n care sunt declarate, i n blocul C situat n interiorul acestuia.

n memoria mainii virtuale Java, variabilele locale sunt plasate pe stiva procesului curent. La executarea unei instruciuni-declaraie, variabilele coninute n aceasta sunt puse pe stiv, n ordinea n care ele apar n declaraia respectiv. Cnd se ajunge la sfritul blocului n care au fost declarate, variabilele sunt scoase de pe stiv. Ct timp se afl pe stiv, variabilele sunt vizibile i deci pot fi utilizate.

Structuri alternative
Instruciunea if
Instruciunea if servete pentru realizarea structurii alternative din programarea structurat. Sub forma ei cea mai simpl, aceast instruciune se scrie astfel:
if(expresie_boolean) instruciune

unde instruciunepoate fi orice instruciune valabil n limbajul Java: instruciune simpl sau structurat, inclusiv un bloc sau un alt if. Remarcm c n forma general de mai sus nu am pus la sfrit caracterul ';' (punct i virgul). Dac instruciune este o instruciune simpl, ea include i acest simbol. Semnificaia instruciunii if este urmtoarea: dac valoarea expresiei booleene din parantez este true, atunci se execut instruciune, iar altfel nu se execut nimic, continundu-se programul.

Exemple 1. Fie instruciunea


if(alpha<beta) x=2*alpha+beta;

n acest caz, instruciune este instruciunea-expresie


x=2*alpha+beta;

care se termin ea nsi prin punct i virgul. nstruciunea if se interpreteaz astfel: dac expresia boolean alpha<beta are valoarea true, atuncivariabileix i se atribuie valoarea expresiei aritmetice 2*alpha+beta. Altfel (dac expresia booleana are valoarea false) variabila x rmne la valoarea pe care a avut-o anterior. 2. Fie instruciunea
if(alpha<beta) { int gamma=alpha-3*beta; x=2*gamma; y=gamma-3; } n acest caz, instruciune este un bloc, care se execut numai dac expresia boolean alpha<betaare valoarea true. Remarcm ca dup acolada prin care se nchide blocul nu

s-a

mai pus punct i virgul.

81

Severin Bumbaru 3. Fie instruciunea n


if(alpha<beta) if(beta>0) System.out.println(alpha+" "+beta); acest caz, instruciune este un alt if.

Dei cuvntul then nu apare explicit, n specificaia limbajului Java aceast forma a lui if este cunoscut sub denumirea "instruciunea if-then" (if-then statement), care se traduce prin dac .. atunci. Remarcm c aceast instruciune realizeaz un caz particular al structurii alternative, unde pe ramura altfel nu se efectueaz nici o aciune.

Instruciunea if .. else
Instruciunea if .. else realizeaz ambele ramuri ale structurii alternative i are forma
if(expresie_boolean) instruciune_1 else instruciune_2

n care instruciune_1 i instruciune_2 pot fi instruciuni simple sau structurate. Interpretarea acestui if..else este urmtoarea: dac expresie_logic are valoarea true,atunci se execut instruciune_1, iar altfel se execut instruciune_2.

Dei cuvntul then nu apare explicit, n specificaia limbajului Java aceast instruciune se numete if-then-else. Exemple 1. Fie instuciunea n termin prin punct i virgul. 2. Fie instruciunea
if(a<b) { x=2*a-b; y=a+1; } else { x=a+b; y=b; } acest caz, instruciune_1 if(a<b) x=2*a-b; else x=a+b; acest caz, att instruciune_1,

ct i instruciune_2 sunt instruciuni-expresii i se

n i instruciune_2 sunt blocuri. Remarcm c dup acolada nchis a blocului nu s-a mai pus punct i virgul.

82

Programarea orientata pe obiecte n limbajul Java

Instruciuni if .. else imbricate


Att instruciunea if, ct i if..else, pot conine alte instruciuni if sau if..else. n acest caz se pune problema crui if i aparine un anumit else. O programare neatent poate conduce la greeli, n sensul c interpretarea dat de compilatorul Java poate fi diferit de cea avut n vedere de programator. Pentru a nu se produce astfel de confuzii, cel mai bine este s se grupeze instruciunile n blocuri. Exemplu Fie instruciunea
if(a<b) if(b<c) System.out.println("A"); else System.out.println("B"); else System.out.println("C");

Interpretarea corect este, n acest caz, c primul else aparine celui de al doilea if, iar ultimul else aparine primului if. Aceast structur se poate ntri scriind instruciunea astfel:
if(a<b) { if(b<c) System.out.println("A"); else System.out.println("B"); } else System.out.println("C");

ntruct s-au folosit acoladele pentru a pune instruciunea if..else interioar sub form de bloc, a devenit clar pentru oricine crui if i apartine fiecare din cei doi else.

Instruciunea switch
Dei n teoria programrii structurate se demonstreaz c, pentru a realiza programe cu structur ramificat, este suficient s se foloseasc structura de control alternativ, realizat n limbajul Java prin instruciunea if..else, n practica programrii se admit i structuri de comutare sau de selecie, care sunt prezente in diferite limbaje de programare. Aceste structuri permit s se aleag una din mai multe ramuri paralele,alegerea depinznd de valoarea unei expresii numit comutator sau selector. n acelai timp, ele respect principiul de baz al programrii structurate, conform cruia fiecare structur de control trebuie s aib un singur punct de intrare i un singur punct de ieire, astfel c se ncadreaz n aceast metod de elaborare a programelor. n limbajul Java, structura de comutare se realizeaz prin instruciunea switch, care are urmtoarea form general:
switch (expresie) { case valoare_1: secven_1 [break;] case valoare_2: secven_2 [break;] .......................... case valoare_N: secven_N [default: secven ] }

83

Severin Bumbaru n care: - switch, case si default sunt cuvinte cheie ale limbajului Java; - expresie este o expresie de tip byte, short, int sau char; - valoare este fie un literal de tip byte, short, int sau char, fie o expresie constant de tip int, adic o expresie care conine numai literali sau variabile finale din tipurile menionate; - secvenaeste o secven de instruciuni simple sau structurate; - parantezele drepte roii []nu apar n program, ci indic faptul c coninutul lor este opional (poate sa lipseasc). n limba englez, switch nseamn comutator. Conform acestei forme generale, dup cuvantul cheie switch, exist o expresie de tip int sau compatibil cu aceasta (deci poate fi i de tip char, byte sau short, dar nu de tip long), a crei valoare servete drept "comutator". Se deschide apoi acolada corpului instruciunii, n care exist mai multe "cazuri". Fiecare "caz" ncepe prin cuvantul cheie case, urmat de o valoare de tip ntreg, dup care apar una sau mai multe instruciuni (simple sau compuse) i opional intruciunea break. Dup ce s-au epuizat toate cazurile, opional se poate scrie cuvntul cheie default urmat de una sau mai multe instruciuni. La sfrit, se nchide acolada corpului instruciunii switch. Executarea instruciunii switch decurge astfel: se evalueaz mai nti expresie i se obine o valoare de tip ntreg, care servete drept comutator. Aceast valoare se compar, pe rnd de sus n jos, cu fiecare din valorile indicate dup cuvintele cheie case, pn cnd se gsete prima valoare care coincide cu cea a comutatorului. Dac s-a gsit o astfel de valoare, se execut toate instruciunile care ncep de la cazul respectiv, pn la prima instruciune break ntalnit sau, n lipsa acesteia, pn la acolada de nchidere a corpului instruciunii switch. Dac ns nici unul din cazuri nu conine valoarea potrivit a comutatorului, atunci se execut instruciunile care urmeaz dup cuvntul cheie default sau, n lipsa acestuia, nu se execut nimic. Exemplu n fiierul TestSwitch.java se d programul de mai jos, n care se testeaz instruciunea switch n dou situaii: n primul caz nu este utilizat instruciunea break, iar n al doilea caz este pus aceast instruciune la sfritul secvenei de instruciuni corespunztoare fiecrui caz. Remarcm, de asemenea, c n al doilea caz, ntruct comutatorul este de tip char, valorile numerice corespunztoare fiecrui caz au trebuit s se ncadreze n acest tip, adic s fie caractere sau numere ntregi pozitive n intervalul [0, 65535].

/* Testarea instructiunii switch */ class TestSwitch { public static void main(String args[]) { int a=7; char c='@'; double u=15.3782; System.out.println("Switch fara break si cu cazuri vide"); switch(a) { case 143: u++; System.out.println("A "+u); case 2: u+=a; System.out.println("B "+u);

84

Programarea orientata pe obiecte n limbajul Java


case 7: case case case case u--; System.out.println("C "+u);

'@': 148: 15: -87: u-=a; System.out.println("D case -12: u*=a; System.out.println("E case 'F': u%=a; System.out.println("F default: u=15.3782; System.out.println("G }

"+u); "+u); "+u); "+u);

System.out.println("Switch cu break dupa fiecare caz nevid"); switch(c) { case 143: u++; System.out.println("A "+u); break; case 2: u+=a; System.out.println("B "+u); break; case 7: u--; System.out.println("C "+u); break; case '@': case 148: case 15: case 87: u-=a; System.out.println("D "+u); break; case 12: u*=a; System.out.println("E "+u); break; case 'F': u%=a; System.out.println("F "+u); break; default: u=15.3782; System.out.println("G "+u); } } }

Rezultatul rulrii acestui program este urmtorul:

Switch fara break si cu cazuri vide C 14.3782 D 7.3782 E 51.6474 F 2.6473999999999975 G 15.3782 Switch cu break dupa fiecare caz nevid D 8.3782

85

Severin Bumbaru Se observ cu uurin c, n primul caz (fr instruciuni break), s-a nceput executarea secvenei de instruciuni n punctul "case 7" i s-a continuat pn la sfritul blocului instruciunii switch (inclusiv cazul default). Cnd s-a folosit instruciunea break, ieirea s-a fcut la ntalnirea acestei instruciuni.

Instruciuni pentru structuri de control repetitive


n limbajul Java, structurile de control repetitive se realizeaz prin trei instruciuni: - instruciunea while, prin care se programeaz ciclul cu test iniial; - instruciunea do..while, prin care se programeaz ciclul cu test final; - instruciunea for, care este o varianta modificat a ciclului cu test iniial, astfel nct s poat fi folosit i la realizarea ciclului cu contor. n cele ce urmeaz se vor prezenta instruciunile menionate mai sus.

Instruciunea

while

(ciclul cu test iniial)

Aceast instruciune are forma general


while (condiie) instruciune

n care
condiie - este o expresie de tip boolean; instruciune- poate fi orice instruciune (simpl inclusiv alt instruciune while.

sau structurat) a limbajului Java,

Executarea acestei instruciuni se face astfel: se evalueaz expresia boolean condiie i dac valoarea acesteia este true, deci condiia este satisfacut - se execut instruciune,dup care se revine la evaluarea condiiei. acest ciclu se repet ct timp este satisfacut condiia.

Exemplul 1. Se va calcula n mod repetat valoarea expresiei 2e-0.25ksin(0.1k-0.08) pentru valori ntregi ale variabilei k de la 0 la n, unde n este dat. n pseudocod, programul corespunztor se poate scrie astfel:
<#1. Se introduce valoarea lui n, de tip intreg> <#2. Se calculeaz i se afieaz valoarea expresiei 2e-0.35ksin(0.17k0.08) pentru valori ale lui k de la 0 la n >

Rafinarea pseudoinstruciunii #1 se poate face direct n program. La rafinarea pseudoinstruciunii #2 lum n consideraie caracterul repetitiv al aciunii solicitate, astfel c putem folosi structura de ciclu cu test iniial, iar programul devine:
<#1. Se introduce valoarea lui n, de tip intreg> /* #2. Se calculeaz i se afiseaz valoarea expresiei */ k=0; // Se iniializeaz k la prima sa valoare

86

Programarea orientata pe obiecte n limbajul Java


ct_timp k<=n afieaz_valoarea_expresiei 2e-0.35ksin(0.17k-0.08); k=k+1; // se trece la valoarea urmtoare a lui k sfrit_ciclu

Programul corespunztor n limbajul Java se gsete n fiierul Repetare1.java. Exemplul 2. Calcularea unei sume cu numr finit de termeni. Considerm c se cere s se calculeze suma

n care sunt date valorile variabilelor a i b, de tip real i n de tip ntreg. Aplicnd tehnica rafinrilor succesive, vom da pentru nceput programului urmtoarea structur secvenial:
<#1. Se introduc datele de intrare n de tip ntreg i a,b de tip real> <#2. Se calculeaz suma S> <#3. Se afieaz valoarea lui S>

Rafinarea pseudoinstruciunilor #1 i #3 se poate face direct n program. Pentru rafinarea pseudoinstruciunii #2, remarcm c suma S se poate calcula n modul urmtor: se pornete de la valoarea iniiala S=0 i se adaug la aceasta succesiv toi termenii sumei, pentru valori ale lui k de la 0 la n. Aciunea are un caracter repetitiv, deci se poate folosi n acest scop un ciclu cu test iniial. Se obine astfel programul urmtor n pseudocod:
<#1. Se introduc datele de intrare n de tip ntreg i a,b de tip real> /* #2. Se calculeaz S */ S=0; // Se atribuie lui S valoarea iniial k=0; // Se atribuie lui k valoarea iniial ct_timp k<=n <#2.1. Se calculeaz termenul curent al sumei i se adaug la valoarea precedent a lui S > k=k+1; // Se trece la valoarea urmtoare a lui k sfrit_ciclu afiseaz S;

Programul corespunztor n limbajul Java se gseste n fiierul Suma1.java. Exemplul 3. Calcularea sumei unei serii convergente. Fie S suma seriei convergente S=1+x+x2/(2!)+x3/(3!)+...+xk/(k!)+... n care k! este factorialul lui k. Demonstrarea existentei acestei sume (deci a convergenei seriei) este de domeniul analizei matematice. ntruct, ns, noi tim c aceast serie este

87

Severin Bumbaru convergent, putem s scriem un program pentru calcularea sumei S. Seria are un numr infinit de termeni, deci valoarea ei exact nu poate fi calculat direct, prin adunarea lor. Totui, valoarea aproximativ a sumei S se poate obine prin "trunchiere", adic lund n consideraie numai un numr finit de termeni. Vom calcula deci, de fapt, suma parial: Sn=1+x+x2/(2!)+x3/(3!)+...+xn/(n!) cu observaia c numrul de termeni n nu este dinainte cunoscut. Se tie (si se observ cu uurin) c termenii seriei sunt descresctori ca modul. Ne putem deci opri din evaluarea sumei, n momentul n care constatm c valoarea termenului curent este mult mai mic dect suma parial deja calculata. Putem deci adopta, pentru calcularea sumei, urmtorul program n pseudocod:
<#1. Se introduce valoarea lui x, de tip real> S=0; // Se iniializeaz suma S la valoarea 0 k=0; // Se iniializeaz indicele termenului curent la valoarea 0 t=1; // Se iniializeaz termenul curent la valoarea 1 (cea a primului termen) /* Se calculeaz suma S a seriei */ ct_timp (<#2.termenul curent t este semnificativ>) S=S+t; // Se adaug la suma precedent S valoarea termenului curent // i se obine noua valoare a sumei S k=k+1; // Se trece la indicele termenului urmtor; <#3.se calculeaz noua valoare t a termenului urmtor> sfrit_ciclu afieaz S.

Pentru a rafina pseudocondiia #2 avem n vedere c, n memoria calculatorului, numerele reale au lungime finit. n consecin, dac adunm dou numere foarte diferite ca ordin de mrime, "suma" lor va fi egal cu cel mai mare dintre ele. De exemplu, dac reprezentarea numerelor reale s-ar face n sistemul zecimal cu 6 cifre semnificative, atunci suma 32.7628+0.00006924 ar fi egala cu numarul cel mai mare, adica 32.7628, deoarece cifrele de la rezultat situate dup cea de a 6-a cifra semnificativ se pierd. n cazul seriei noastre, la un moment dat termenul curent t va deveni att de mic ca modul, nct adunat la suma deja calculata S nu o va mai modifica. Vom considera deci c termenul t este semnificativ, ct timp se ndeplinete condiia (S+t este_diferit_de S). Pentru a rafina #3, observm c ntre valorile termenului t la doi pai succesivi k i k-1 exista relaia: tk=tk-1*x/k. ntruct n program nu este necesar s folosim indicii pailor, vom scrie aceast relaie sub forma t=t*x/k, adic se atribuie ca nou valoare a termenului curent t valoarea precedent a acestui termen, nmulit cu raportul x/k. Cu observaiile de mai sus, programul de calculare a sumei seriei devine:
<#1. Se introduce valoarea lui x, de tip real> S=0; // Se iniializeaz suma S la valoarea 0 k=0; // Se iniializeaz indicele termenului curent la valoarea 0

88

Programarea orientata pe obiecte n limbajul Java


t=1; // Se iniializeaz termenul curent la valoarea 1 (cea a primului termen) /* Se calculeaz suma S a seriei */ ct_timp (S+t este_diferit_de S) S=S+t; // Se adaug la suma precedent S valoarea termenului curent // i se obine noua valoare a sumei S k=k+1; // Se trece la indicele termenului urmtor; t=t*x/k; // se calculeaz noua valoare t a termenului urmtor sfrit_ciclu afieaz S.

Programul corespunztor n limbajul Java este dat n fiierul Serie1.java. Pentru a nelege mai bine acest program, recomandm s calculai 3-4 termeni manual pentru a urmri cum se nlnuie acetia.

Instruciunea do..while (ciclul cu test final)


Forma general a instruciunii de control, prin care se realizeaz n limbajul Java ciclul cu test final este urmtoarea:
do instruciune while (condiie);

unde, la fel ca n cazul instruciunii while,condiie este o expresie de tip boolean, iar instruciune este orice instruciune (simpl sau structurat) din limbajul Java. Remarcm c la sfritul acestei instruciuni (dup condiie) se pune obligatoriu ';' (punct i virgul). Principala deosebire fa de instruciunea while pentru ciclul cu test iniial este c testarea condiiei se face dup ce a fost executat instruciunea din corpul ciclului. n consecin, corpul ciclului va fi executat cel puin o dat. n programul din fiierul DeosCicluri.java se face o comparaie ntre funcionarea ciclurilor cu test iniial i cu test final n condiii similare.

n programele din fiierele Repetare2.java,Suma2.java i Serie2.java se reiau exemplele din seciunea precedent (i realizate n fiierele Repetare1.java, Suma1.java i Serie1.java), dar folosind de data aceasta ciclul cu test final.

89

Severin Bumbaru

Instruciunea for (ciclul cu contor generalizat)


n unele limbaje de programare, pentru realizarea ciclurilor la care numrul de pai este dinainte cunoscut, se folosete o instruciune de control special, numit "ciclu cu contor". n pseudocod, aceast instruciune poate fi scris n modul urmtor:
pentru variabila de_la val_init la val_fin [cu_pasul pas] execut <instruciune sau secven de instruciuni> sfrit_ciclu

n care, de regul, variabila este o variabil (de regul de tip ntreg), numit i contorul ciclului,val_init i val_fin sunt respectiv valorile iniial i final ale acestei variabile, iar pas este pasul de variaie la fiecare parcurgere a ciclului. Pasul implicit este 1.

De exemplu, pentru a calcula produsul P=(a+5)*(a+6)*(a+7)*...*(a+n) se vor scrie urmtoarele pseudoinstruciuni:


P=1; pentru k de_la 5 la n execut P=P*(a+k); sfrit_ciclu

Remarcm c, n acest exemplu, instruciunea P=1 nu face parte din ciclu, dar ea a fost necesar pentru a da valoarea iniial a variabilei P. n mod similar, pentru a calcula suma S=7+10+13+16+...+31 se pot folosi instruciunile
S=0; pentru j de_la 7 la 31 cu_pasul 3 execut S=S+j; sfrit_ciclu

Remarcm c, pentru aceleai calcule, se pot folosi i ciclurile cu test iniial sau cu test final. Astfel, primul din aceste exemple, poate fi rescris folosind ciclul cu test iniial astfel:
P=1; k=5; ct_timp k<=n execut P=P*(a+k); k=k+1; sfrit_ciclu

Remarcm c, la trecerea de la ciclul cu contor la ciclul cu test iniial, s-au introdus urmtoarele instruciuni suplimentare: - nainte de intrarea n ciclu, s-a pus instruciunea k=5, prin care se atribuie variabileicontor valoarea iniial; - la sfritul corpului ciclului s-a introdus instruciunea k=k+1, prin care se trece la

90

Programarea orientata pe obiecte n limbajul Java valoarea urmtoare a variabilei-contor; - in instruciunea while s-a pus drept condiie compararea variabilei-contor cu valoarea ei final. Lsm cititorului ca exerciiu s scrie acelai program, folosind ciclul cu test final. n limbajul Java, urmnd tradiia limbajului C de la care acesta a preluat o bun parte a regulilor de sintax, se folosete o instructiune generalizat, prin care se realizeaz att ciclul cu contor, ct i ciclul cu test iniial. Aceast instruciune are forma:
for ([iniializare]; [condiie] ; [trecere_la_pasul_urmtor] ) [<instruciune_corp_ciclu>]

n care: format din una sau mai multe instruciuni, separate prin virgule, care se execut nainte de intrarea n ciclu, astfel c sunt folosite, de regul, pentru iniializarea acestuia; condiie - este o expresie de tip boolean folosit drept condiie de continuare a ciclului cu test iniial (condiia este testata nainte de a se executa corpul ciclului; trecere_la_pasul_urmtor := instruciune[,instruciune]* - una sau mai multe instruciuni, separate prin virgule, care se execut dup ce a fost executat corpul ciclului. astfel c sunt, n general, folosite pentru pregtirea trecerii la urmtoarea parcurgere a ciclului; <instruciune_corp_ciclu>- o instruciune (simpla sau structurat) care constituie corpul ciclului.
iniializare ::= instructiune[,instructiune]*- este

Respectnd aceasta form general, calcularea produsului dat ca exemplu mai sus n pseudocod, se programeaz n limbajul Java n modul urmator:
for(P=1,k=5; k<=n; k++) P*=a+k;

Se observ ca se iniializeaz P la valoarea 1 i k la valoarea 5, apoi ct timp este satisfacut condiia k<=n se execut instruciunea P*=a+k, dup care se execut instruciunea k++ (se trece la urmtoarea valoare a lui k). Dup cum se vede n forma general, diferitele componente ale acesteia sunt opionale; n consecin, instruciunea for poate fi scris sub diferite forme echivalente, de exemplu: a)
P=1; k=5; for(;k<=n;){ P*=a+k; k++; }

Observm c, de data aceasta, instruciunea for(;k<=n;) are exact acelai efect, pe care lar fi avut instruciunea while(k<=n). Remarcm, de asemenea, c cei doi separatori ';' din interiorul parantezei au fost mentinui, chiar dac lipsesc zonele de iniializare i de

91

Severin Bumbaru incrementare.


b) for(P=1,k=5;k<=n;P*=a+k,k++);

n ultimul caz, corpul ciclului este constituit numai dintr-o instruciune vid, reprezentat prin carecterul ';' pus dupa paranteza nchis. Aceste exemple sunt date i n programul din fiierul TestFor.java. Tot acolo se arat c variabila care servete drept contor al ciclului poate fi, n limbajul Java, i de tip real, iar creterea acesteia de la o parcurgere la alta a ciclului poate fi de asemenea de tip real i nu este obligatoriu s fie constant. Considerm c exemplele din acest program sunt suficiente pentru a arta ca instruciunea for permite programatorului posibiliti de utilizare foarte diverse, cu condiia ca acesta s neleaga corect modul ei de funcionare.

Declararea unor variabile n zona de iniializare a ciclului

for

Este permis ca n zona iniializare a ciclului for s fie incluse i unele declaraii de variabile. Aceste variabile sunt tratate drept variabile locale ale ciclului for respectiv i deci nu sunt vizibile (disponibile) dup ieirea din ciclu, putnd fi redefinite. Iat un astfel de exemplu:
x=0; for(int k=0; k<n; k++) S+=a*k;

n acest caz, variabila k a fost att declarat, ct i iniializat, n zona de iniializare a instruciunii for. n consecin aceast variabil este disponibil n interiorul acestei instruciuni, inclusiv n corpul ciclului, dar i pierde valabilitatea la ieirea din acest ciclu. Daca n zona de iniializare apare o declaraie, ea trebuie s fie singura instruciune din aceast zon. Astfel, n exemplul precedent nu ar fi fost permis, de exemplu, s se scrie
for(x=0, int k=0; k<n; k++) S+=a*k;

Este ns permis s se declare n zona de iniializare mai multe variabile de acelai tip. Astfel, exemplul anterior poate fi modificat dup cum urmeaz:
x=0; for(int k=0,i=9; k<n; k++, i--) S+=(a+i)*k;

Aceste exemple i altele similare se gsesc n programul din fiierul TestFor1.java.

Exemple de programe n care se folosete ciclul for n fiierele Repetare3.java, Suma3.java i Serie3.java se reiau exemplele date in fisierele Repetare1.java, Suma1.java i Serie1.java), dar folosind instruciunea for n loc de while. V recomandm s comparai n mod special programele din fiierele Serie1.java si Serie3.java si s explicai deosebirile constatate.

92

Programarea orientata pe obiecte n limbajul Java

Instruciuni etichetate
n principiu, orice instruciune n limbajul Java poate purta o etichet. Instruciunile etichetate au forma
etichet : instruciune

unde
etichet este un identificator; instruciuneeste o instruciune simpl

sau structurat.

Exemplu
alpha: x=2*a+b;

Se permite s se foloseasc drept etichete chiar i identificatori care mai sunt folosii n acelasi program ca nume de variabile, clase, metode etc., far a se crea prin aceasta confuzii, deoarece compilatorul face distincie ntre etichete i nume n funcie de contextul n care acestea sunt utilizate.

Terminarea abrupt a execuiei instruciunilor structurate


n seciunile anterioare, s-a artat c limbajul Java respect principiile programrii structurate. n consecin, instruciunile de control au fost concepute n conformitate cu aceste principii, iar instruciunea goto nu exist. Chiar dac, din precauie, cuvntul cheie gotoa fost meninut n limbaj, el nu este nc efectiv folosit. Cu toate acestea, avnd n vedere experiena practic i pentru a veni n ajutorul programatorilor, autorii limbajului Java au admis i anumite abateri de la structurile de control fundamentale acceptate de teoria programrii structurate, fr a nclca ns principiul de baz al acesteia, conform cruia fiecare asemenea structur trebuie sa aib un singur punct de intrare i un singur punct de ieire. Am artat deja, c astfel de excepii sunt instructiunile switch,do..while i for. Ne vom ocupa acum de o alta abatere de la programarea structurat pur, care const n folosirea instruciunilor break i continue i a instruciunilor etichetate.

Folosirea instruciunilor break i continue


Instructiunile break i continue au forma general urmtoare:
break [etichet]; continue [etichet];

unde eticheteste eticheta unei instruciuni i este un identificator. Eticheta este opional (de aceea a fost scris de noi ntre paranteze drepte). Instructiunea break se poate folosi n corpul unei instruciuni switch, while, do..while sau for i are ca efect ieirea forat (abrupt) din structura de control n care se gsete instruciunea respectiv. S-a artat deja cum se folosete instruciunea break n corpul unei instruciuni switch. Iat acum un exemplu de folosire ntr-un ciclu cu test iniial:
k=1; S=0; while(S+t!=S) {

93

Severin Bumbaru
t*=a/k; S+=t; if(t<1.0e-10*S) break; k++; }

n acest caz, n momentul n care este satisfacut condiia (t<1.0e-10*S) din instructiunea if se iese forat din ciclu, chiar dac condiia principal de continuare a ciclului (S+t!=S) este nc satisfacut. Iat i un exemplu similar, n care se iese forat din instruciunea for:
k=1; S=0; for(;;) { t*=a/k; if(S+t==S) break; S+=t; k++; }

ntruct iniializarea ciclului s-a fcut nainte de instructiunea for, iar condiia de ieire din ciclu i pregatirea continuarii ciclului se gsesc n corpul acestuia, n paranteza lui for toate cele trei zone au ramas vide. Instruciunea continue se poate folosi numai n corpul ciclurilor (while, do..while, for). Dac instruciunea continue nu are etichet, efectul este c se trece peste restul instruciunilor din corpul ciclului, ncepnd din punctul n care se gsete instruciunea continue pn la sfritul acestuia, dar se continu executarea ciclului, adic se reia executarea corpului acestuia ct timp este satisfacut condiia de continuare. S considerm, de exemplu, urmtorul fragment de program:
s=0; for(k=0; k<20; k++) { x*=a; s+=x; if(k<16) continue; System.out.println("k="+k+" x="+x+" s="+s); }

n acest caz, corpul ciclului se va repeta pentru valori ale lui k de la 0 la 19, dar instruciunea System.out.println(...) va fi "srit" pentru valori ale lui k mai mici dect 16, trecndu-se direct la acolada de nchidere a corpului ciclului, astfel c afirile se vor face numai ncepand cu k=16.

Folosirea etichetei n instruciunea break


Necesitatea utilizrii unei etichete apare atunci cnd exist dou astfel de structuri imbricate una n alta, iar noi dorim ca prin break s se iasa forat din cea exterioar, ca n exemplul urmator:
ciclu1: while(w>0.05){ w/=a;

94

Programarea orientata pe obiecte n limbajul Java


for(int k=0; k<n; k++) { s+=w; if(s>b) break ciclu1; y+=w*s } }

Instruciunea break se gsete, n acest exemplu, n corpul ciclului interior. Dac nu ar fi coninut eticheta ciclu1,aceast instruciune ar fi provocat numai ieirea dim ciclul interior (for), dar s-ar fi reluat execuia ciclului exterior (while), implicand, desigur, i reluarea ciclului interior continut de acesta. Dac ns este prezenta eticheta din break, se va iei forat din instruciunea de control care poart aceast etichet, n cazul de fa din ciclul exterior. Remarcam, deci, c eticheta coninut n instruciunea break indic faptul ca se va iei forat din structura de control care poart aceeai etichet. Aceasta nseamn c instruciunea break cu etichet constituie o abatere local de la principiul de baz al programrii structurate, conform cruia fiecare structur de control trebuie sa aib un singur punct de intrare i un singur punct de ieire. n ultimul exemplu, ciclul interior are dou puncte de ieire: unul este ieirea normal din ciclul for, iar celalalt este ieirea prin break. Daca luam ns n consideraie ciclul exterior, constatm ca acesta respect principiul menionat. Desigur c pot s existe mai multe instruciuni de control cuprinse una n alta i fiecare dintre ele poate avea o etichet, care poate fi utilizat ntr-o instruciune break. Testarea a diferite situaii de utilizare a instructiunii breakse face n programul din fiierul TestBreak.java.

Folosirea etichetei n instruciunea continue


S considerm acum urmtorul fragment de program:
ciclu1: for (int i=0; i<6; i++) { System.out.println("Control 1: i="+i); for(int j=3; j>0; j--) { System.out.println("Control 2: i="+i+" j="+j); if(i>1 && i<5) continue ciclu1; System.out.println("Control 3: i="+i+" j="+j); } // Sfarsitul ciclului interior System.out.println("Control 4: i="+i); } // Sfarsitul ciclului exterior

Instruciunea coninue eticheta ciclu1, care aparine ciclului exterior. n consecin, pentru valori ale variabilei i cuprinse ntre 1 i 5, se va trece forat la sfritul corpului ciclului exterior, deci nu se vor mai executa instruciunile de afiare "Control 3" i "Control 4". Programul de testare pentru instruciunea continue se gsete n fiierul TestCont.java.

Tratarea excepiilor
n timpul executrii programului, pot apare anumite situaii care altereaza desfurarea normal a acestuia. Cnd apare o astfel de situaie, de regul, se genereaz o excepie sau o eroare prin care se semnaleaz incidentul care a avut loc. Excepiile i erorile pot fi generate att de echipamente (excepii sau erori hardware), ct i de programe (excepii software).

95

Severin Bumbaru Exemple de excepii hardware pot fi ntreruperile, excepia de mprire la zero, unele incidente din subsistemele de intrare/ieire etc. Excepiile software sunt mult mai diverse, depinznd de specificul programelor care le genereaz. Deosebirea dintre excepii i erori este c excepiile sunt considerate c pot fi tratate prin program, n timp ce erorile sunt considerate mai curnd nerecuperabile. n programul din fiierul TestExcept1.java se testeaz apariia unei excepii de mprire la zero. ntruct variabila b are valoarea zero, la executarea mpririi a/b procesorul calculatorului genereaz o excepie aritmetic. ntruct n programul nostru nu exist instruciuni prin care s se trateze aceast excepie, programul se ntrerupe, trecndu-se controlul asupra sistemului de operare al calculatorului, iar acesta afieaza excepia survenit i oprete executarea programului. n limbajul Java, exist posibilitatea de a se trata prin program diferitele excepii care apar n timpul execuiei. n acest fel, programatorul poate s prevad ci alternative de continuare a executrii programului, fr a mai fi necesar oprirea executrii lui. n mediul de lucru Java, la apariia unei excepii se genereaz un obiect special numit excepie, care conine informaia despre excepia respectiv. Acest obiect poate fi captat prin program, iar informaia coninut n el poate fi utilizat pentru a decide calea pe care se va merge n continuare n derularea programului. Toate obiectele de excepie care se refer la acelai tip de incident formeaz o clas de excepii. Tratarea prin program a excepiilor se face, n limbajul Java, folosind instruciunea try urmat de una sau mai multe clauze catch i, opional, de o clauz finally sub forma urmatoare:
try { secventa } catch (ClasaExceptie1variabila1) { secventa1 } catch (ClasaExceptie2 variabila2) { secventa2 } ............... catch (ClasaExceptieN variabilaN) { secventaN } [finally { secventa_finalizatoare }]

n engleza, try nseamn ncearc, iar catch nseamn prinde. n corpul instruciunii try se pune secvena de instruciuni n care este posibil ca, la executarea programului, s apar excepii. Dac excepia a aprut ntr-un punct situat n corpul unei instruciuni try, aceasta instruciune se termin n mod abrupt, astfel c restul instruciunilor nu se mai execut, trecndu-se direct la acolada de nchidere a blocului. Se parcurg apoi, una dup alta, clauzele catch, pn se ajunge la cea care are ntre paranteze numele clasei excepiei care s-a produs i se execut secvena din corpul acestei clauze. Clauza finally este opional i conine o secven de instructiuni care se vor executa n final, adic dup ce a fost tratat excepia prin una din clauzele catch, sau dac nu a fost tratat prin

96

Programarea orientata pe obiecte n limbajul Java nici una dintre acestea.

Exemplul 1: n fiierul TestExcept2.java este dat o modificare a programului din fiierul TestExcept1.java, n care excepia este tratat prin instruciunea try. ntruct se tia c este posibil apariia unei excepii aritmetice, s-a ncercat s se capteze mai ntai aceast excepie. Ca rezerv, s-a prevzut i o clauza catch pentru clasa Exception, care va capta orice alta excepie. Comparnd rezultatele executrii celor dou programe menionate, constatm c, atunci cnd s-au tratat excepiile prin instruciunea try, programul nu a mai fost oprit anormal, ci s-a executat blocul clauzei catch(ArithmeticException e1), dup care s-a continuat executarea normal a programului. n schimb, instruciunile existente n blocul try, dup cea care a generat excepia, nu au mai fost executate. Exemplul 2: n fiierul TestExcept3.java se reia programul din exemplul anterior, dar a fost suprimat prima din clauzele catch. Executnd acest program, se poate observa c i de data aceasta excepia aritmetic a fost captata, nsa de clauza catch(Exception e). Exemplul 3: n fiierul TestExcept4.java se reia programul din Exemplul 1, dar dup captarea excepiei s-a introdus si clauza finally. Se observ ca secvena din aceasta clauz este executat chiar daca excepia a fost captat prin catch. Mai mult, n fiierul TestExcept5.java s-a reluat acelai program, dar s-a modificat valoarea numitorului fraciei, astfel c nu mai are loc o mprire la zero. Se observ ca secvena din clauza finallyeste executat i n acest caz.

ntrebri
Nivel 1
1. Ce este o expresie? 2. Cum se stabilete tipul unei expresii? 3. Fie a si b variabile de tip byte, c de tip int, u de tip float i v de tip double. Care sunt tipurile urmtoarelor expresii: a+b, a*c, a*c+u, u-2*v. 4. Ce este precedena operatorilor? 5. n ce ordine se aplic operatorii cu acelai nivel de preceden? 6. n ce ordine se evalueaz operanzii unui operator binar? 7. Ce forma sintactic are expresia condiional i care este semnificaia acestei expresii? 8. Ce este o instruciune? 9. Ce deosebire este ntre instruciunile simple i cele structurate? 10. Ce este instruciunea vid i cum se scrie? 11. Ce este o instruciune-expresie? 12. Ce deosebiri exist ntre o expresie i o instruciune-expresie? 13. n ce const teorema de structur din metoda programrii structurate? 14. Care sunt categoriile de instruciuni de control admise de metoda programarii structurate?

97

Severin Bumbaru 15. Ce fel de structur de control este un bloc i care este forma lui sintactic? 16. Ce sunt variabilele locale i care este domeniul lor de vizibilitate? 17. Prin ce instruciuni se realizeaz structura de control alternativ i care este forma lor sintactic? 18. Ce sunt excepiile? 19. Ce deosebire este ntre excepii i erori? 20. Care este forma sintactic a instruciunii de tratare a exceptiilor i cum trebuie ea interpretat?

Nivel 2
Construii arborele sintactic al urmtoarei expresii: (a+2*b/c)*(2*d-3)+3*e+5 Construii arborele sintactic al urmtoarei expresii: a=(b+=2*a)-c++*(d-=c+1) Construii arborii sintactici ai tuturor expresiilor din fiierul EvExpresii.java. Explicai rezultatele obinute la executarea programului din fiierul ExprCond.java. Ce este o instruciune de atribuire i care este efectul ei? Care este deosebirea dintre valorile expresiilor de preincrementare i postincrementare? Dar ntre efectele instruciunilor de preincrementare i postincrementare? 7. Ce este o instructiune de invocare de metod i care este efectul ei? 8. Care este schema logic a structurii de control secveniale i cum trebuie interpretat? 9. Care este schema logic a structurii de control alternative i cum trebuie interpretat? 10. Care este schema logic a ciclului cu test iniial i cum trebuie interpretat? 11. Care este schema logic a ciclului cu test final i cum trebuie interpretat? 12. Unde sunt plasate variabilele locale n memoria mainii virtuale Java? 13. Cnd sunt eliminate din memorie variabilele locale? 14. Cum se stabilete crui if i aparine clauza else n cazul instructiunilor if imbricate? 15. Care este forma sintactic a instruciunii switch i cum este ea interpretat? 16. Ce rol are instruciunea break n cadrul unui bloc switch? 17. Ce este o etichet i ce form sintactic are o instruciune etichetat? 18. Poate o etichet s aib acelai identificator cu cel al unui nume de variabil sau de metod? 19. Cum acioneaz o instruciune break fr etichet n corpul unui ciclu? 20. Cum acioneaz o instruciune continue fr etichet n corpul unui ciclu? 21. n ce situaie se folosete o instruciune break cu etichet? 22. n ce situaie se folosete o instruciune continue cu etichet? 23. La ce servete clauza catch i unde se plaseaz? 24. La ce servete clauza finally i unde se plaseaz? 1. 2. 3. 4. 5. 6.

98

Programarea orientata pe obiecte n limbajul Java

Tipul referin. Utilizarea claselor din pachetul java.lang. Tablouri. Utilizarea parametrilor din linia de comand
Tipul referin; declararea variabilelor referin; Clase, cmpuri, metode; Constructori; crearea obiectelor prin operatorul new; Motenirea i polimorfismul; ierarhia de clase Java; Atribuirea de valori variabilelor-referin; Pachetele de clase din Java API; declaratia import; Utilizarea claselor din pachetul java.lang Clasa Object; Clasele de excepii; Clasele String i StringBuffer; Clasa Class; Clasele acoperitoare de tip; Clasa Math; Clasa System; Tablouri Tablouri unidimensionale; Tablouri multidimensionale; Utilizarea parametrilor din linia de comand ntrebri. 99 101 102 102 103 104 105 105 107 108 111 112 119 120 121 122 126 133 134

Tipul referin
n limbajul Java exist dou categorii de tipuri de date: tipuri primitive i clase. Tipurile primitive sunt predefinite n limbaj, n sensul c numele, mulimea de date, mulimea de operaii i reprezentarea datelor n memoria intern a mainii virtuale Java pentru fiecare tip sunt definite n insi specificaia limbajului Java i nu mai pot fi modificate de programatori. n program, datele de tipuri primitive apar sub forma de variabile.

Fiecare variabil are un nume, un tip i o valoare i este plasat ntr-o anumita locaie de memorie. n locaia de memorie respectiv se gsete chiar valoarea variabilei. Pe programator nu il intereseaz ins adresa de memorie la care se gsete variabila, ci doar numele, tipul i valoarea acesteia.

99

Severin Bumbaru Clasele sunt tipuri de date structurate specifice programrii orientate pe obiecte. Clasele se definesc de programatori i se grupeaz n pachete de clase. La crearea unui program nou, programatorul poate utiliza clasele din pachetele deja existente, sau poate creea propriile sale clase. n program, fiecare clas poate avea mai multe instane, numite obiecte.

Comparnd clasele cu tipurile primitive, constatm c clasa este o extensie a conceptului de tip, iar obiectul este o extensie a conceptului de variabila. Deosebirea este c o variabil simpl este o locaie de memorie care conine o valoare primitiv, n timp ce obiectul este tot o zon de memorie, care conine ns o structur de date. n memoria mainii virtuale Java, obiectele sunt plasate ntr-o zon de memorie special, numit memorie dinamic (n englez: heap, adic "gramad"). Localizarea n memorie a obiectelor se face cu ajutorul unor variabile speciale, numite variabile referin. Valoarea unei variabile referin nu este obiectul nsui, ci o referin la acest obiect. Din aceast cauz, se consider c variabilele referint aparin unui tip de date numit tip referin. Mulimea de valori a acestui tip este mulimea referinelor, adic mulimea locaiilor (adreselor) din memoria dinamic. Operaiile permise asupra datelor de tip referina sunt cele date de operatorii de atribuire (=), egalitate (==) i inegalitate (!=) care au aceleai semnificaii i mod de utilizare ca pentru toate celelalte tipuri de date.

Referinele din Java sunt similare pointerilor din unele limbaje de programare tradiionale, cum sunt Pascal i C. Exist, totui, deosebiri importante: - valorile variabilelor-pointer sunt adrese din memorie care pot fi cunoscute de programator (de exemplu pot fi afiate) De asemenea, unei variabile-pointer i se poate atribui ca valoare o adresa dat explicit. n schimb, adresele la care se gsesc n memorie obiectele indicate de referinele din Java nu pot fi cunoscute de utilizator; - n limbajele tradiionale, pointerii pot indica nu numai adresele n memorie ale unor structuri de date, ci i pe cele ale unor variabile simple. n java, referinele pot fi folosite numai pentru obiecte; - n limbajele traditionale (de exemplu n C/C++) se pot face asupra pointerilor operatii aritmetice, ceeace nu este permis asupra referinelor n Java.

Declararea variabilelor referin


Declararea variabilelor referin se poate face la fel cu declararea variabilelor de tipuri primitive. Singura deosebire const n faptul c, n locul tipului primitiv, se folosete un nume de clasa. De exemplu, declaraia
String s1, s2, s3; arat c s1, s2 si s3 sunt

variabile referin ctre obiecte din clasa String, adic din

clasa irurilor de caractere. Atentie: s1, s2 si s3 nu sunt iruri de caractere (adic obiecte din clasa String) ci sunt doar referine ctre iruri de caractere. Aceasta nseamn c valoarea fiecreia deintre ele nu este un obiect, ci o referin la obiect. Obiectul propriu-zis nu se gsete n memorie n acelai loc

100

Programarea orientata pe obiecte n limbajul Java cu variabila, ci undeva n memoria dinamic. Prin contrast, n cazul declararii unor variabile primitive, de exemplu
int i1,i2,i3; variabilele i1, i2 si i3

sunt numere de tip int, adic au ca valori astfel de numere.

Vom arta ulterior i modul n care pot fi iniializate variabilele referin.

Clase, cmpuri, metode


Clasa este o structur de date, asociat cu o colecie de proceduri sau funcii, metode, care utilizeaz datele din aceast structur. Datele unei clase se numesc cmpuri, sau variabile membre. Cmpurile pot fi statice (ale clasei) sau nestatice (ale instanei). Cnd clasa este instaniat, n memoria mainii virtuale Java se construiete un obiect (o instan a clasei respective). Obiectul conine numai cmpuri nestatice. Cmpurile statice se pstreaza n memorie ntr-un singur loc, care este rezervat clasei respective. Metoda este o funcie, care ntoarce o valoare i poate avea, de asemenea, efect lateral. Ca i cmpurile, metodele pot fi statice(ale clasei) i nestatice (ale instanei). Metodele statice pot invoc numai cmpurile statice ale clasei respective, n timp ce metodele nestatice pot invoca att cmpurile statice, ct i pe cele nestatice (ale unei instane a clasei respective). Dac valoarea ntoars de metod este void, metoda respectiv este o procedur i trebuie s aib obligatoriu efect lateral. Invocarea unei metode statice (a clasei) se face printr-o expresie de forma
nume_clasa.nume_metoda(parametri_efectivi)

a crei valoare este valoarea ntoars de funcia respectiv. O astfel de invocare de funcie poate fi deci folosit ca o component ntr-o alt expresie. De exemplu, expresia Math.sqrt(a) serveste pentru a calcula rdcina patrat a lui a, n care scop este invocat funcia sqrt, care este o metod static a clasei Math (clasa funciilor matematice uzuale). Putem folosi aceast invocare de metod ntr-o expresie mai complicat, de exemplu
x=2*Math.sin(a)+3;

Invocarea unei metode nestatice (a instanei) se face sub forma


referina_la_obiect.nume_metod(parametri_efectivi)

deci numele metodei nu mai este calificat prin (nsoit de) numele clasei, ci prin cel al variabilei referin la obiectul respectiv, sau prin o expresie care are ca valoare o astfel de referin. De exemplu, daca r1 este o variabil referin care indic un anumit obiect din memorie, iar met(a)este o metod nestatic a clasei creia i aparine acest obiect, atunci r1.met(a) are ca efect invocarea metodei met pentru obiectul indicat de r1. n acest fel, metoda met(a) va folosi att cmpurile (nestatice ale) obiectului indicat de referina r1, ct i cmpurile (statice ale) clasei creia i aparine acest obiect. Dac o metoda are efect lateral, ea poate fi invocat i sub forma de instruciune. Aceast instruciune const numai din expresia de invocare a metodei, urmat de punct_i_virgul. n acest caz, valoarea ntoars de metod (valoarea expresiei) este ignorat, folosindu-se numai

101

Severin Bumbaru efectul lateral al metodei respective. Un exemplu cunoscut deja este instruciunea
System.out.println(sir);

Este evident c metodele care ntorc void (procedurile) pot fi invocate numai sub form de instruciuni, fiind folosite pentru efectul lor lateral.

Constructori
Constructorul este o procedur special, prin care se construiesc obiecte dintr-o anumit clas. Constructorul are ntotdeauna acelai nume cu clasa. n schimb, o clas poate avea mai muli constructori, care pot s difere ntre ei prin numrul i/sau tipul argumentelor. Constructorul aloc n memoria dinamic spaiul necesar pentru un obiect din clasa creia i aparine i iniializeaz cmpurile acestui obiect cu valori care depind de argumentele sale.

Crearea obiectelor prin operatorul new


Invocarea unui constructor se face prin operatorul new, urmat de numele constructorului respectiv i de lista de argumente a acestuia. Operatorul new este unar, iar operandul lui este un constructor, deci forma generala a expresiei de invocare a unui constructor este
new nume_constructor(parametri_efectivi)

Valoarea acestei expresii este o referin la obiectul nou construit. Efectul lateral al acestei expresii este construirea n memorie a unui obiect din clasa creia i aparine constructorul, iar valoarea acestei expresii este referina la obiectul nou construit. De exemplu, expresia
new String("acesta este un sir")

are ca efect (lateral) construirea n memorie a irului de caractere "acesta este un sir", iar valoarea expresiei este referina ctre acest ir. S considerm acum urmtoarele dou instruciuni:
String s1=new String("abcd_1234"), s2; s2=new String("alpha");

Prima dintre ele este o declaraie, prin care se specific faptul c s1 i s2 sunt variabile referin, ale cror valori sunt referine la obiecte din clasa String. Totodat, se aloc n memorie irul "abcd_1234" i se atribuie ca valoare iniial a variabilei s1 referina la acest ir. A doua dintre instruciunile de mai sus, este o instruciune de atribuire, n care variabilei s2 i se atribuie valoarea expresiei new String("alpha"). La executarea acestei expresii, se obine ca efect lateral alocarea n memorie a irului "alpha", iar referina la acest ir se atribuie ca valoare a variabilei s2

Motenirea i polimorfismul
Motenirea este una din proprietile fundamentale ale claselor n programarea orientat pe obiecte. Ea const n faptul c dintr-o clas se pot deriva alte clase. Clasa de baza se mai numeste i superclas, iar clasele derivate se numesc i subclase.

102

Programarea orientata pe obiecte n limbajul Java Fiecare clas derivata motenete cmpurile i metodele superclasei. Aceasta nseamn c toate cmpurile i metodele existente n superclas sunt utilizabile i n subclas, dar n aceasta din urm pot exista, de asemenea, cmpuri i/sau metode suplimentare. Polimorfismul este o alta proprietate fundamental a claselor. n limbajul Java este posibil ca o metod a superclasei s fie redefinit n subclas. Aceasta nseamn c ea va avea n subclas acelai nume i aceeasi lista de parametri i acelai tip de valoare ntoars ca n superclas, dar va avea un comportament diferit.

S considerm, de exemplu, c exista clasa Poligon, n care exist metoda double arie(). Aceasta metod este o funcie, a crei valoare este aria poligonului. Sa considerm acum c Triunghi i Patrat sunt doua clase derivate din clasa Poligon. n ambele clase derivate va exista metoda double arie(), dar este evident c modul de calcul al ariei triunghiului difer de cel al calculrii ariei patratului i, cu att mai mult, de modul de calcul al ariei unui poligon oarecare.

Ierarhia de clase Java


n general, n programarea orientat pe obiecte este permis motenirea multipl, adic o clas poate avea mai multe superclase. n limbajul Java este permis numai motenirea simpl, deci fiecare clas poate avea numai o singur superclas. Aceast ierarhie de clase este unic, adic orice clas are obligatoriu o superclas i numai una. Singura excepie o constituie clasa Object, care este rdcina ierarhiei de clase Java i nu are superclas. Vom arata ulterior c lipsa motenirii multiple este compensat n Java prin faptul c fiecare clasa poate avea mai multe interfee.

Atribuirea de valori variabilelor-referin


Unei variabile referin i se pot atribui ca valori referin la obiecte din clasa variabilei respective sau din clasele derivate. De exemplu, avnd n vedere c clasa String este derivat din clasa Object, urmatoarele instruciuni sunt corecte:
Object ob; String s=new String("abcd"); ob=s;

n primele dou instruciuni, s-au declarat variabilele-referin ob din clasa Object i s din clasa String, ultima fiind iniializat cu o referin ctre irul "abcd", care a fost creat folosind operatorul new. n a treia instruciune, variabilei-referin ob i se atribuie valoarea variabilei-referin s. n consecin, acum variabila ob din clasa Object are ca valoare o referina ctre obiectul "abcd" din clasa String.

103

Severin Bumbaru

Pachetele de clase din Java API


Clasele sunt grupate n pachete (englez: package). Pachetul este o colecie de clase reutilizabile destinate unui anumit domeniu de utilizare, care sunt puse la dispoziia programatorului sub form compilat (bytecode). Ar putea fi numit i "bibliotec de clase", dar autorii platformei Java au preferat denumirea de pachet. Pachetul poate avea subpachete. Daca pachetul p are subpachetul q, atunci p.q este numele complet (numele calificat) al subpachetului q. Acest subpachet poate avea, la rndul sau, alte subpachete. Java API (Application Programming Interface - interfaa de programare de aplicaii) este descrierea unui set standard de pachete necesare programrii n Java. Pentru pachetele coninute n Platforma Java 2 Standard Edition (J2SE) aceast documentaie poate fi gasit pe Internet la urmatoarea adres: java.sun.com/products/j2se/1.3/docs/api/index.html - la firma Sun Microsystems; Principalele pachete de clase sunt: java.lang - conine clasele de baz necesare programrii n limbajul Java; java.io - conine clasele necesare pentru programarea operaiilor de intrare/ieire; java.util - conine clase pentru anumite structuri de date tipice (list, stiv etc) i alte clase utile; java.awt si javax.swing - conin clase necesare pentru realizarea interfeelor grafice; java.applet - pentru programarea appleturilor. Exist ns i multe alte pachete, necesare n diferite domenii de aplicaie.

Declaraia import
Pentru a putea utiliza ntr-un fiier-sursa Java un anumit pachet (subpachet) de clase, la nceputul fiierului respectiv trebuie pus declaraia n al pachetului respectiv. De exemplu, pentru a utiliza orice clase din pachetul java.io se pune declaraia
import java.io.*; import nume_pachet.*; care nume_pachet este numele calificat

Pentru clasele din pachetul java.lang nu este necesar o declaraie de import, acestea fiind importate implicit. Pentru a importa numai o anumita clas dintr-un pachet, se foloseste declaraia
import nume_pachet.NumeClasa; De exemplu, pentru a importa clasa File din import java.io.File;

pachetul java.io se folosete declaraia

Declaraia
import nume_pachet.*;

se numete declaraie de import la cerere. Ea nu are semnificaia c se import toate clasele din pachetul (subpachetul) respectiv, ci numai acele clase care sunt utilizate efectiv n program.

104

Programarea orientata pe obiecte n limbajul Java

Utilizarea claselor din pachetul java.lang


Pachetul java.lang conine clasele fundamentale i exist pe orice platform Java. Pentru acest pachet nu este necesar declaraia import, clasele sale fiind importate implicit. Lista complet a claselor din pachetul java.lang i descrierea lor se gsesc n documentaia Java API de pe Internet. Noi vom prezenta aici cteva clase mai frecvent utilizate.

Clasa Object
Clasa Object este rdcina ierarhiei de clase a platformei Java. Este singura clas care nu are o superclas. Orice alt clasa este derivat direct sau indirect din clasa Object. Conceptual, instanele clasei Object sunt obiecte oarecare, fr atribute precizate. Variabilele referin la Object se folosesc atunci cnd, la elaborarea programului, se consider c lor li se pot da ca valori referine la orice fel de obiecte, indiferent de clasa creia i aparin. n clasa Object sunt declarate, de asemenea, metode care se consider ca trebuie s existe n toate celelalte clase. Unele din aceste metode vor trebui redefinite n clasele derivate, pentru a efectua aciuni specifice acestor clase.

Metodele clasei Object


Clasa Object nu are date membre. n consecin, obiectele acestei clase nu au stare (cu excepia faptului ce ele exist sau nu). Clasa are un singur constructor, Object(), care nu are parametri. Obiectele acestei clase nu conin date. n schimb, clasa dispune de un set de metode. Conform cu principiul motenirii, toate celelalte clase posed metodele clasei Object. Metodele clasei Object sunt descrise n Java API. Noi vom prezenta aici numai o parte dintre ele, care vor fi utilizate n cele ce urmeaz. Metoda equals() este declarat sub forma:
public boolean equals(Object obj)

ceeace nseamn c nivelul de acces este public, valoarea ntoars (valoarea obinut la evaluarea acestei funcii) este de tip boolean, iar unicul argument aparine clasei Object. Expresia a.equals(b) n care a i b sunt dou obiecte, ntoarce valoarea true dac a este identic cu b i valoarea false n caz contrar. Aa cum este ea definit n clasa Object, metoda equals() ntoarce valoarea true numai dac cele doua obiecte comparate sunt cu adevrat identice, adic au aceeai adres n memorie, ceeace se poate scrie i sub forma expresiei a==b. n clasele derivate, aceast metoda poate fi redefinit, respectnd principiul polimorfismului, astfel nct s compare cele dou obiecte dup coninut, chiar dac ele nu au aceeai referin.

105

Severin Bumbaru Metoda hashCode() este declarat sub forma


public int hashCode()

i ntoarce codul de dispersie al obiectului cruia i se aplic. Codul de dispersie (englez: hash code) este un numr ntreg (de tip int) care are urmtoarele proprieti: - dac se aplic de mai multe ori aceluiai obiect, metoda hashCode() ntoarce de fiecare dat acelai cod de dispersie; - dac dou obiecte sunt egale ntre ele n sensul definit prin metoda equals(), atunci codurile de dispersie obinute aplicnd metoda hashCode() fiecruia n parte trebuie s fie, de asemenea, egale; - este posibil ca, aplicnd metoda hashCode() la doua obiecte diferite, s se obin coduri de dispersie egale, nsa este preferabil ca aceast situaie s se ntlneasc ct mai rar cu putin.

Metoda hashCode() este util atunci cnd obiectele trebuie plasate n tabele de dispersie, cum sunt cele care fac parte din clasa java.util.Hashtable i java.util.HashMap. Metoda toString() este declarat sub forma
public String toString()

i ntoarce reprezentarea sub forma de ir de caractere (de obiect din clasa String) a obiectului cruia i se aplic. Asa dar, expresia a.toString(), n care a este un obiect, ntoarce reprezentarea sub forma de ir a obiectului a. n cazul obiectelor aparinnd clasei Object, aceasta metod ntoarce un ir de forma java.lang.Object@<cod_dispersie> n care <cod_dispersie> este codul de dispersie al obiectului respectiv, exprimat n hexazecimal. n clasele derivate aceasta metod este redefinit, astfel nct s se obin o reprezentare sub form de ir a coninutului obiectului respectiv.

Metoda clone() este declarat sub forma:


protected Object clone()

i are rolul de a ntoarce o clon a obiectului cruia i se aplic, deci ntoarce un obiect identic cu acesta, dar situat la o alt adres de memorie i deci avnd o alt referin. n consecin, dup ce se execut instruciunea
b=a.clone();

n care a i b sunt referine la obiecte, expresia a==b va avea valoarea false, deoarece valorile variabilelor referin a i b sunt diferite, n timp ce expresia a.equals(b) va ntoarce n mod normal valoarea true, deoarece cele dou obiecte comparate au coninuturi identice.

106

Programarea orientata pe obiecte n limbajul Java n schimb, dup ce se execut instruciunea


b=a;

variabila b va avea ca valoare aceeai referin ca i variabila a, adica a i b vor indica acelai obiect din memorie, astfel c expresia a==b ntoarce valoarea true. ntruct metoda clone() este protejat (are nivelul de acces protected) ea nu poate fi utilizat dect pentru obiectele din clasa Object. n schimb, ea poate fi redefinit la clasele descendente, astfel nct sa devin public. Metodele prezentate aici (exceptnd, desigur, metoda clone()) sunt testate n programul din fiierul TestObject.java. Metoda getClass() este declarat sub forma
public final Class getClass()

O expresie de forma a.getClass(), n care a este o referinta la un obiect, ntoarce ca valoare un obiect din clasa Class, care conine informaii despre clasa obiectului indicat de variabila a. Deocamdat vom folosi aceast metoda numai pentru a afia numele clasei, ca n ultimele trei instruciuni ale programului din fiierul TestObject.java.

Clase de excepii
n pachetul java.lang exist i numeroase clase de excepii. Instanele acestor clase sunt creeate de ctre maina virtual Java atunci cnd se produce o excepie, adic o situaie anormal n procesul de calcul. Toate aceste clase sunt descrise n documentatia Java API. Vom meniona aici numai dou dintre ele, celelalte urmnd s fie indicate la descrierea claselor care conin metode care pot genera excepii. n limbajul Java se face distincie ntre excepie i eroare. Se consider ca excepiile sunt incidente care pot fi captate prin mecanismul try .. catch i pot fi deci tratate prin program, n timp ce erorile sunt incidente grave, care - de regul - nu pot fi tratate prin program ci produc oprirea executrii acestuia.

Clasa Exception
Aceast clas este rdcina ierarhiei claselor de excepii. n consecin, atunci cnd dorim ca in clauza catch sa fie captat orice fel de excepie, scriem aceast clauz sub forma
catch(Exception e) { instructiuni_de_tratare_a_exceptiei e }

unde e este numele simbolic (identificatorul) dat excepiei captate. Clasa are doi constructori:
public Exception()

creeaz un obiect din clasa Exception (deci "o excepie") care nu conine nici un mesaj.

107

Severin Bumbaru
public Exception(String s)

creeaz un obiect din clasa Exception, care conine un mesaj sub forma irului s. Prin acest mesaj se indic, de regul, ce incident a condus la generarea excepiei respective. Vom arta ulterior cum putem folosi aceti constructori pentru a genera propriile noastre excepii. Clasa Exception nu are propriile ei metode.Totui, att pentru clasa Exception, ct i pentru toate celelalte clase de excepii se pot folosi metodele superclasei Object. n particular, se poate folosi pentru instanele oricrei clase de excepii metoda toString(), care pune instana respectiv sub forma unui ir de caractere. Acest ir conine, de regul, un mesaj privind felul exceptiei respective.

Clasa ArithmeticException
Instanele acestei clase sunt generate de maina virtual Java atunci cnd are loc o situaie anormal la efectuarea unei operaii aritmetice, cum ar fi, de exemplu, mprirea la zero a unui numr ntreg. Instana respectiv conine un mesaj care indic ce fel de excepie s-a produs. Exemple de utilizare a claselor de excepii s-au dat deja n capitolul "Tratarea excepiilor".

Clasele String i StringBuffer


Pentru irurile de caractere, pe care le vom numi n viitor simplu "iruri", exist n pachetul java.lang doua clase: String i StringBuffer. Obiectele clasei String conin irurile propriu-zise, iar cele ale clasei StringBuffer conin zone tampon pentru iruri.

Clasa String
Toate irurile n limbajul Java, inclusiv literalii-ir, de exemplu "ABCdef123", sunt obiecte ale clasei String. Obiectele din aceast clas sunt constante, adic irurile coninute n ele nu pot fi modificate. Dac este necesar s se foloseasc iruri modificabile, se recurge la clasa StringBuffer. n afar de metodele pe care le ofer, clasa String conine i suportul necesar pentru operatorul de concatenare'+'. Prin concatenarea a dou iruri se obine un nou ir, rezultat din punerea celor dou unul n continuarea celuilalt. De exemplu, expresia "ABC"+"defg" are ca valoare irul "ABCdefg". Dm aici o parte din constructorii i metodele mai frecvent utilizate ale clasei String. O prezentare mai ampl exist n indexul de clase. V recomandm s o consultai, pentru a cunoate ce constructori i metode conine. Amintim c prezentarea complet se gsete n documentaia Java API de pe Internet.

108

Programarea orientata pe obiecte n limbajul Java Construirea unui obiect din clasa ir se face cel mai frecvent cu constructorul String(String s). Acest constructor creeaza n memorie o copie a irului s primit ca argument. Dintre metodele foarte utile menionm aici urmtoarele:
int compareTo(String anotherString) Compara acest ir cu irul anotherString

primit ca argument. Dac cele dou iruri sunt identice, ntoarce 0 (zero). Dac acest ir l precede pe anotherString ntoarce o valoare negativ, iar daca i succede lui anotherString ntoarce o valoare pozitiv. Compararea irurilor se face n ordine lexicografic (n ordinea n care ar fi plasate ntr-un dicionar).
int compareToIgnoreCase(String str)

Compar lexicografic acest ir cu sirul str primit ca argument, ignornd deosebirea dintre literele majuscule i cele minuscule.
int length()

ntoarce lungimea acestui ir (numrul de caractere coninute).


String trim()

ntoarce un nou ir, obinut din acest ir prin eliminarea spaiilor de la nceput i de la sfrit.

int indexOf(int ch)

ntoarce indicele la care se gsete n ir prima apariie a caracterului ch. Dac acest caracter nu exist n ir, ntoarce -1.
int indexOf(int ch, int fromIndex)

Similar cu metoda precedent, dar cutarea in sir ncepe de la poziia fromIndex.


int indexOf(String str)

ntoarce indicele poziiei de la care n acest ir apare prima dat subirul str.
int indexOf(String str, int fromIndex)

Similar cu metoda precedent, dar cutarea n acest ir ncepe de la poziia fromIndex.


int lastIndexOf(int ch)

ntoarce indicele ultimei poziii pe care apare caracterul ch n acest ir.


int lastIndexOf(int ch, int fromIndex)

ntoarce indicele ultimei poziii pe care se gsete caracterul ch, dac se face cutarea napoi, ncepnd de la poziia fromIndex.
int lastIndexOf(String str)

ntoarce indicele ultimei apariii n acest ir a subirului str.


int lastIndexOf(String str, int fromIndex)

Similar cu metoda precedent, dar cutarea napoi se face de la poziia fromIndex.


String substring(int beginIndex)

109

Severin Bumbaru ntoarce un nou ir, care conine caracterele acestui ir, ncepnd de la poziia beginIndex, pn la sfrit.
String substring(int beginIndex, int endIndex) ntoarce subirul situat ntre pozitiile beginIndex i endIndex-1

inclusiv.

Exemplu n programul din fiierul TestStr.java se exemplific utilizarea clasei String.

Clasa StringBuffer
Obiectele clasei StringBuffer implementeaz iruri care pot fi modificate att ca lungime, ct i sub aspectul caracterelor pe care le conin. n englez buffer nseamn zon tampon. Aa dar, un "StringBuffer" este modelul unei zone tampon de memorie, n care se pot aduga noi caractere la irul existent i n care se pot nlocui total sau parial caracterele existente cu altele. Principalele operaii asupra unei astfel de "zone tampon" sunt metodele append() i insert(), prin care se poate aduga un ir nou n coada celui existent, sau se nsereaz acest ir nou n interiorul celui existent. Un obiect StringBuffer (zona tampon pentru caractere) se caracterizeaz prin lungime i capacitate. Lungimea este numrul de caractere coninut efectiv, iar capacitatea este dimensiunea la un moment dat a tabloului de caractere coninut n obiectul respectiv. Ambele se pot modifica n timp, ca urmare a aplicrii unor metode. Construirea unui nou StringBuffer se poate face cu unul din constructorii StringBuffer(), StringBuffer(int length) sau StringBuffer(String str). Primul dintre ei construiete o zon tampon de caractere, avnd o capacitate iniial predefinit; al doilea una de capacitate iniial length, iar al treilea construiete o zon tampon care conine iniial irul str. Cele mai importante metode sunt: public int length() - ntoarce lungimea curent a irului (numrul de caractere existente efectiv n buffer); public int capacity() - ntoarce capacitatea curent a buffer-ului; public StringBuffer append(char c) - adaug la buffer caracterul c; public StringBuffer insert(int offset, char c) - nsereaza n buffer caracterul c pe pozitia offset; public String toString() - ntoarce un ir care are acelai coninut cu cel din acest StringBuffer.

Exist, de fapt, o familie de metode append(), care difer ntre ele prin tipul argumentului:
append(boolean b), append(byte b), append(short s), append(int i), append(long l), append(char c), append(float f), append(double d),append(String str), append(Object obj).

110

Programarea orientata pe obiecte n limbajul Java Toate aceste metode adaug n coada zonei tampon argumentul lor, convertit ntr-un ir. Exist, de asemenea, o familie de metode insert(), care difer prin tipul celui de al doilea argument:
insert(int offset, boolean b), insert(int offset, byte b), insert(int offset, short s), insert(int offset, int i), insert, int offset, long l), insert(int offset, char c), insert(int offset, float f), insert(int offset, double d), insert(int offset, String str), insert(int offset, Object obj).

Toate aceste metode nsereaz n zona tampon, pe poziia offset, cel de al doilea argument convertit n ir. O prezentare mai ampl a clasei StringBuffer este dat n indexul de clase, iar descrierea complet se gsete pe Internet n documentaia Java API. Exemplu n fiierul TestStrB.java este dat un exmplu de program n care se testeaz clasa StringBuffer.

Clasa Class
O caracteristic important a limbajului i platformei Java este c clasele i interfeele utilizate n program sunt prezente n memoria mainii virtuale Java n timpul executrii programului, sub forma de instane ale clasei Class. n consecin, se pot obine n timpul executrii unui program informaii despre clasele crora le aparin obiectele din memorie. Clasa Class nu are un constructor public. n schimb, putem obine un obiect din aceast clas folosind metoda getClass() a clasei Object. Exist i instane ale clasei Class pentru tipurile de date primitive. Acestea sunt coninute sub forma de cmpuri statice n clasele acoperitoare ale tipurilor primitive respective. Iat cteva dintre metodele clasei Class:
public String getName() - ntoarce numele calificat al unei entiti (clase, interfee, tip primitiv) reprezentat de un obiect din clasa Class; public boolean isAssignableFrom(Class cls) - ntoarce true dac clasa creia i se aplic metoda este o superclas a clasei cls, primit ca argument; public boolean isInterface() - ntoarce true dac metoda este aplicat unei instane a clasei Class care reprezint o interfa; public boolean isPrimitive() - ntoarce true dac metoda este aplicat unui obiect din clasa Class care reprezint un tip de date primitiv; public Class getSuperclass() - ntoarce o instan a clasei Class care reprezint superclasa obiectului cruia i se aplic aceast metod.

n fiierul TestClass.java este dat un program de testare a obinerii obiectelor Class i a aplicrii unora dintre metodele acestora. Descrierea complet a clasei Class este dat n documentaia Java API. 111

Severin Bumbaru

Clasele acoperitoare de tip


n pachetul java.lang, pentru fiecare din tipurile de date primitive exist o clas acoperitoare de tip (englez: Type Wrapper). Aceste clase pun la dispoziia programatorului att variabile finale (constante), ct i metode necesare pentru a lucra cu tipul de date respectiv. Clasele acoperitoare de tip formeaz ierarhia din figura 1.

- Figura 1 n aceasta figur, clasele acoperitoare de tip sunt reprezentate cu negru. Clasa Number este o clasa abstract, din care sunt derivate toate clasele acoperitoare pentru tipuri de date numerice. Fiecare din celelalte clase acoper un anumit tip de date primitiv. Clasa Character acoper tipul char, iar clasa Integer acoper tipul int. Toate celelalte clase acopera tipul primitiv al carui nume l poart. Spre deosebire de numele tipurilor primitive, care sunt scrise cu litere mici, numele claselor acoperitoare ncep (ca la orice alte clase) cu majuscule. Toate clasele acoperitoare sunt clase finale, deci din ele nu mai pot fi derivate alte clase. Fiecare instan a unei clase acoperitoare conine un cmp de date nestatic n care se pastreaz o valoare aparinnd tipului primitiv de date corespunzator clasei respective. De exemplu, un obiect din clasa Boolean conine un cmp de tip boolean care, la rndul lui, conine valoarea logic true sau false. n mod similar, un obiect din clasa Double conine un cmp de tip double n care exist un numr n virgul mobil n dubl precizie. n afar de cmpul de date nestatic, fiecare clas acoperitoare conine mai multe cmpuri de date statice finale, n care se pstreaz diferite constante (variabile finale) specifice tipului de date corespunztor. Unele dintre metode sunt prezente n toate clasele acoperitoare, altele sunt specifice fiecrei clase sau unui grup de astfel de clase. Prezentm aici succint principalele metode prezente n toate clasele:
public boolean equals(Object obj) - este o redefinire a metodei equals()din clasa Object ; compar obiectul propriu cu obiectul obj primit ca argument i ntoarce true dac acestea sunt identice, sau false n caz contrar; public String toString() - este o redefinire a metodei toString() din clasa Object ; ntoarce valoarea primitiv coninut n obiectul respectiv, convertit ntr-un ir de

112

Programarea orientata pe obiecte n limbajul Java caractere, reprezentnd forma extern a valorii respective; public int hashCode() - este o redefinire a metodei hashCode() din clasa Object; intoarce codul de dispersie al obiectului propriu. Clasele acoperitoare ofer, de asemenea, metode prin care se pot converti datele din tipurile respective din forma extern (de iruri de caractere) n cea interna i invers.

Clasa Boolean
Clasa Boolean acoper tipul primitiv boolean. Clasa are doi constructori publici: Boolean(boolean value) i Boolean(String s). Primul primete ca argument o expresie cu valoare de tip boolean, iar al doilea primete un ir de caractere, care conine forma extern a unei valori de tip boolean. n afara de metodele equals(), toString() i hashCode(), care au fost deja menionate, clasa Boolean mai ofer urmtoarele metode specifice: public boolean booleanValue() - ntoarce valoarea primitiv de tip boolean coninut n obiectul propriu; public static Boolean valueOf(String s) - ntoarce o noua instan a clasei boolean, corespunztoare irului s: dac irul s este "True" ntoarce TRUE, altfel ntoarce FALSE. Are, practic, acelai efect cu aplicarea operatorului new cu constructorul Boolean(String s). Clasa Boolean motenete, de asemenea, metodele clasei Object. n programul din fiierul TestBoolean.java este testat clasa Boolean.

Clase acoperitoare pentru tipurile de date numerice


Clasa abstract Number
Este superclasa tuturor tipurilor de date numerice, cu excepia tipului char.Contine urmtoarele metode: public abstract byte byteValue() - ntoarce numrul convertit la tipul primitiv byte, ceeace poate avea ca efect rotunjirea sau trunchierea; public abstract short shortValue() - ntoarce numrul convertit la tipul primitiv short, ceeace poate avea ca efect rotunjirea sau trunchierea; public abstract int intValue() - ntoarce numrul convertit n tipul primitiv int, ceeace poate avea ca efect rotunjirea; public abstract long longValue() - ntoarce numrul convertit la tipul primitiv long, ceeace poate avea ca efect rotunjirea; public abstract float floatValue() - ntoarce numarul convertit la tipul primitiv float; public abstract double doubleValue() - ntoarce numarul convertit la tipul primitiv double.

113

Severin Bumbaru Remarcm c aceste metode se aplica tuturor claselor acoperitoare pentru numere, realiznd conversia numrului coninut ntr-o instan a unei clase acoperitoare numerice ctre tipul primitiv dorit de utilizator.

Clasele Byte, Short, Integer i Long


Instanele acestor clase acoper valori din tipurile primitive byte, short, int i long. ntre aceste clase exist o mare asemnare n ce privete cmpurile de date statice i metodele. Vom prezenta aci principalele faciliti oferite de clasa Integer. Pentru o prezentare complet a acestei clase, ct i pentru informaii privind celelalte clase, recomandm consultarea documentaiei originale Java API. Menionm c majoritatea metodelor statice din clasa Integer nu exist n celelalte clase acoperitoare pentru tipuri de date intregi, dar nici nu este necesar, deoarece se pot folosi aceste metode i cu argumente efective de tip byte sau short. Clasa Integer este clasa acoperitoare pentru tipul primitiv int. Clasa conine urmtoarele cmpuri de date statice:
public static final int MAX_VALUE

- conine valoarea maxim pentru tipul de - conine valoarea minim pentru tipul de date

date int, adic valoarea 2147483647;


public static final int MIN_VALUE

int, adic -2147483648;


public static final Class TYPE despre tipul primitiv int.

- conine un obiect din clasa Class cu informaii

Clasa are doi constructori:


public Integer(int value)

- construiete instana clasei Integer care conine

valoarea primitiv value;


public Integer(String s) - convertete irul s, primit ca argument, ntr-un numr de tip int i construiete obiectul Integer care conine acest numr; dac irul s nu reprezint forma extern a unui numr ntreg, se obine excepia NumberFormatException. Remarcm deci c se face analiza sintactic a irului s pentru a se verifica dac acesta este cu adevrat un numr ntreg.

Clasa ofer un numeroase metode, att de instan, ct i statice, care sunt utile cnd se lucreaz cu numere ntregi. Dintre acestea menionm: a/ metodele equals(), toString() i hashCode() existente n toate clasele acoperitoare; b/ metodele byteValue(), shortValue(), intValue(), longValue(), floatValue()si doubleValue() existente n toate subclasele clasei Number; c/ metode statice, utile n diverse operaii cu numere ntregi: public static int parseInt(String s) - face analiza sintactic a irului s, considerat ca forma extern a unui numr ntreg n sistemul de numeraie zecimal, i ntoarce valoarea de tip int corespunzatoare; dac irul s nu are forma corect a unui numr ntreg, se

114

Programarea orientata pe obiecte n limbajul Java obine excepia NumberFormatException;

public static int parseInt(String s, int radix) - acioneaza asemntor cu metoda precedent, cu deosebirea c se consider c irul s este un numr n sistemul de numeraie cu baza radix; public static String toBinaryString(int i) - ntoarce numrul ntreg i convertit ntr-un ir care l reprezint n sistemul de numeraie binar; public static String toHexString(int i) - ntoarce numrul ntreg i convertit ntr-un ir hexazecimal; public static String toOctalString(int i) - ntoarce numrul ntreg i convertit ntr-un ir n sistemul de numeraie octal; public static String toString(int i) - ntoarce numrul ntreg i convertit ntr-un ir n sistemul de numeraie zecimal (se deosebete de metoda toString(), motenit de la clasa Object, prin faptul ca nu este o metod a instanei, ci una static); public static String toString(int i, int radix) - ntoarce un ir care conine numrul intreg i convertit n sistemul de numeraie cu baza radix; public static Integer valueOf(String s) - acioneaz asemntor cu metoda parseInt(String s), dar ntoarce un obiect din clasa Integer; public static Integer valueOf(String s, int radix) - similara cu metoda precedent, dar se consider c irul s este un numr ntreg n baza de numeraie radix; public static Integer decode(String s) - analizeaz irul s i l decodific; dac acesta respect unul din formatele admise pentru numere ntregi, adic este forma extern a unui numr ntreg n unul din sistemele zecimal, hexazecimal (incepe cu 0x) sau octal (incepe cu 0), atunci il convertete n valoare intern de tip int i ntoarce obiectul de clasa Integer care contine aceasta valoare; altfel, ntoarce excepia NumberFormatException.

d/ metode ale instanei (n plus, fa de cele menionate la punctele a/ i b/): - compar propriul obiect din clasa Integer cu obiectul anotherInteger primit ca argument. Dac ele sunt egale, ntoarce zero; daca ntregul propriu este mai mic dect argumentul, ntoarce o valoare negativ, iar dac este mai mare ntoarce o valoare pozitiv; public int compareTo(Object obj) - dac obiectul-argument obj este tot un Integer, atunci aceast metod acioneaz la fel cu cea precedent; altfel, se obine excepia ClassCastException.
public int compareTo(Integer anotherInteger)

Exemplu: Programul din fiierul TestInt.java testeaz utilizarea unora dintre metodele clasei Integer. Executnd acest program se poate constata c analiza sintactic a irului primit ca argument decurge n acelai mod la metodele parseInt(String), valueOf(String) i la constructorul Integer(String). Se accept numai irurile care reprezint cu adevrat numere ntregi cuprinse n domeniul de valori al tipului int. Se admite ca numrul s fie precedat de semnul - (minus), dar nu de semnul +. Se observ, de asemenea, c la conversia de la Integer ctre byte sau short este posibil s se piard cifrele cele mai semnificative prin trunchiere.

Clasele Float i Double


Instanele claselor Float i Double "acoper" valori ale tipurilor primitive corespunztoare, respectiv float i double. Ele ofer, de asemenea, metode de conversie a irurilor n 115

Severin Bumbaru numere reale (cu analiza sintactic corespunztoare) i a numerelor reale n iruri. Vom prezenta aici clasa Double, dar aceleai faciliti exist i n clasa Float. Cmpuri de date statice: Clasa Double (i similar clasa Float) ofer urmtoarele cmpuri de date statice: public static final double MAX_VALUE - cea mai mare valoare pozitiv de tip double; public static final double MIN_VALUE - cea mai mic valoare pozitiv de tip double; public static final double NaN - valoarea NaN (Not a Number) pentru tipul double; public static final double POSITIVE_INFINITY - valoarea Infinitypentru tipul double; public static final double NEGATIVE_INFINITY - valoarea -Infinity pentru tipul double; public static final Class TYPE - un obiect din clasa Class cu informaii despre tipul primitiv double. Constructori: Clasa Double are doi constructori: Double(double value) - construiete o instan a clasei Double care conine valoarea primitiv value; Double(String s) - construiete o instan a clasei Double care conine valoarea primitiv de tip double a crei form extern este irul s primit ca argument; dac acest ir nu este corect sintactic, se obtine excepia NumberFormatException. Metode: Clasa Double ofer numeroase metode utile n lucrul cu date de tip double, dintre care mentionm: a/ metodele equals(), toString() si hashCode() existente n toate clasele acoperitoare; b/ metodele byteValue(), shortValue(), intValue(), longValue(), floatValue() si doubleValue() existente n toate subclasele clasei Number; c/ metode statice, utile n diverse operaii cu numere reale: public static double parseDouble(String s) - analizeaz sintactic irul s primit ca argument i - dac este corect - ntoarce valoarea primitiv double corespunzatoare; altfel genereaz excepia NumberFormatException; public static String toString(double d) - convertete n sir numrul primitiv primit ca argument;

public static Double valueOf(String s) - acioneaza asemntor cu metod parseDouble(String), dar intoarce un obiect din clasa Double;

116

Programarea orientata pe obiecte n limbajul Java


public static long doubleToLongBits(double value)

- ntoarce o valoare de tip long care este reprezentarea pe 64 bii, conform standardului IEEE 754, a numrului de tip double primit ca argument; public static double longBitsToDouble(long bits) - ntoarce o valoare de tip double, a crei reprezentare ca long (ntreg pe 64 bii) conform standardului IEEE 754 este cea primit ca argument; public static boolean isInfinite(double v) - ntoarce true dac argumentul v este infinit; public static boolean isNaN(double v) - ntoarce true dac argumentul v este NaN; d/ metode ale instanei (n plus, fa de cele menionate la punctele a/ i b/):

public int compareTo(Double anotherDouble) - compar propriul obiect din clasa Double cu obiectul anotherDouble primit ca argument; dac ele sunt egale, ntoarce zero; dac numrul propriu este mai mic dect argumentul ntoarce o valoare negativ, iar dac este mai mare ntoarce o valoare pozitiv; public int compareTo(Object obj) - dac obiectul-argument obj este tot un Double, atunci aceast metod acioneaz la fel cu cea precedent; altfel, se obine excepia ClassCastException. public boolean isInfinite() - ntoarce true dac valoarea coninut n obiectul propriu este infinit; public boolean isNaN() - ntoarce true dac valoarea coninuta n obiectul propriu este NaN;

Exemplu: Programul din fiierul TestDouble.java testeaz principalele metode ale clasei Double. Remarcm c, n acest caz, a fost considerat corect i un sir care reprezint un numr real precedat de semnul +. Pentru reprezentarea formatului intern al numrului s-a folosit metoda doubleToLongBits(), combinat cu metodele toBynaryString() i toHexString()din clasa Long.

Clasa Character
Fiecare obiect al clasei Character "acoper" o valoare primitiva de tip char. n plus, clasa Character ofer metode utile n lucrul cu caractere. Reamintim c, n limbajul Java, caracterele sunt reprezentate pe 16 bii, n sistemul Unicode. Cmpuri statice: Clasa Character conine numeroase cmpuri de date statice, prezentate n documentaia Java API. Cele mai multe dintre ele sunt coduri numerice ale diferitelor categorii de caractere (litere majuscule, litere minuscule, cifre zecimale, simboluri matematice etc), folosite n metodele care verific dac un anumit caracter corespunde categoriei respective. Printre ele exist ns i cmpul care
public static final Class TYPE conine un obiect din clasa Class cu informaii

despre tipul primitiv char.

117

Severin Bumbaru Constructori: Clasa Character are un singur constructor public Character(char value) - construiete un obiect al clasei Character care conine caracterul primit ca argument.

Metode statice: Clasa Character ofer numeroase metode statice utile n lucrul cu caractere, dintre care menionm: public static boolean isDigit(char ch) - ntoarce true dac argumentul ch este cifr; public static boolean isLetter(char ch) - ntoarce true dac argumentul este liter; public static boolean isLowerCase(char ch) - ntoarce true dac ch este liter mic; public static boolean isUpperCase(char ch) - ntoarce true daca ch este liter majuscul; public static boolean isLetterOrDigit(char ch) - verific dac ch este liter sau cifr; public static boolean isWhitespace(char ch) - verific dac ch este un spaiu liber sau un alt caracter asimilabil acestuia, de exemplu caracter de trecere la linie nou, de ntoarcere a carului, de tabulare orizontal sau vertical, de separare a fiierelor sau nregistrrilor etc (vezi documentaia). public static boolean isSpaceChar(char ch) - verific dac ch este caracterul spaiu; public static char toLowerCase(char ch) - ntoarce caracterul ch convertit n litera mic; dac nu este liter, l las neschimbat; public static char toUpperCase(char ch) - ntoarce caracterul ch convertit n litera majuscul; dac nu este liter, l las neschimbat; public static int getNumericValue(char ch) - ntoarce valoarea numerica Unicode a caracterului ch ca un ntreg nenegativ; public static int digit(char ch, int radix) - ntoarce valoarea numeric a caracterului ch considerat ca cifra a sistemului de numeraie cu baza radix; dac n sistemul respectiv nu exist o astfel de cifr, ntoarce -1; public static char forDigit(int digit, int radix) - ntoarce caracterul prin care este reprezentat cifra de valoare digit n sistemul de numeraie cu baza radix; daca n sistemul respectiv nu exista o asemenea cifr, ntoarce caracterul nul ('\u0000'); Metode nestatice: n afara de metodele generale equals(), toString() i hashCode(), clasa Character ofer, de asemenea, urmtoarele metode: public char charValue() - ntoarce caracterul primitiv coninut n obiectul propriu din clasa Character; public int compareTo(Character anotherCharacter) - compar caracterul din propriul obiect cu cel primit ca argument i ntoarce valoare nul dac sunt egale, negativ daca primul este mai mic dect al doilea i valoare pozitiv dac este mai mare;

118

Programarea orientata pe obiecte n limbajul Java - dac argumentul obj este un obiect din clasa Character, actioneaz similar cu metoda precedent; altfel genereaz excepia ClassCastException;
public int compareTo(Object obj)

Exemplu: n fiierul TestChar.java este dat un program de testare a metodelor oferite de clasa Character.

Clasa Void
Clasa Void nu este instaniabil (nu poate avea obiecte) i "acoper" tipul primitiv void. Ea conine numai un singur cmp static
public static final Class TYPE

care conine un obiect din clasa Class cu informaii despre tipul primitiv void.

Clasa Math
Clasa Math este foarte util n calcule tiinifice i inginereti. Ea conine un numr mare de funcii matematice (funcii trigonometrice, logaritmice, exponeniale etc) i dou constante matematice: numrul e i numrul pi. Constantele sunt reprezentate sub forma urmtoarelor dou cmpuri statice finale ale clasei: public static final double E - numrul e (baza logaritmilor naturali); public static final double PI - numarul pi (raportul dintre perimetrul i diametrul cercului). Aceste constante se folosesc n expresiile din program sub forma Math.E i Math.PI. Funciile matematice se prezint n aceast clas sub forma de metode statice. Menionm aici numai cteva din aceste funcii, cu precizarea c arcele (unghiurile) se exprim n radiani: public static double sin(double a) - sinusul trigonometric sin a. public static double cos(double a) - cosinusul trigonometric cos a. public static double tan(double a) - tangenta trigonometric tg a. public static double asin(double a) - arcsin a. public static double acos(double a) - arccos a. public static double atan(double a) - arctg a. a public static double exp(double a) - funcia exponential e . public static double log(double a) - logaritmul natural ln a. public static double sqrt(double a) - radacina patrat a lui a. Lista complet a funciilor este dat n indexul claselor.

119

Severin Bumbaru Utilizarea n expresiile din program a acestor funcii se face, ca la toate metodele statice, calificnd numele funciei prin numele clasei. De exemplu, sin(2*u+3) se va scrie Math.sin(2*u+3).

Clasa System
Clasa System conine cmpuri i metode utile pentru realizarea legturii dintre aplicaie i sistemul de execuie Java (cel care implementeaz maina virtual Java). Aceast clas nu poate fi instaniat. Cmpuri statice: Clasa System are trei cmpuri statice care reprezint unitile standard de intrare/ieire ale sistemului: public static final InputStream in - este intrarea standard a sistemului. De regul, aceasta este tastatura, dar poate fi i alt dispozitiv indicat de utilizator. public static final PrintStream out - este ieirea standard a sistemului. De regul este unitatea de afiare standard (ecranul) dar poate fi i alt dispozitiv indicat de utilizator. Afiarea datelor pe ecran se face, de regul folosind metoda System.out.println(sir) sau System.out.print(sir). public static final PrintStream err - unitatea standard de ieire pentru erori. De regul este aceeai ca pentru obiectul out, dar poate fi i alt dispozitiv indicat de utilizator. Metode: Dm aici numai metodele care sunt utilizate de noi n acest curs. Descrierea complet a tuturor metodelor clasei System poate fi gasit n documentaia Java API. public static void exit(int status)- provoaca incheierea executrii programului. Argumentul acestei metode este un cod de stare care se transmite mainii virtuale Java. Prin convenie, 0 nseamn ncheiere normal a executrii aplicaiei, iar un cod diferit de zero indic ncheiere anormal (cu cod de eroare). Metoda se folosete n program sub forma instructiunii System.exit(stare);.

public static void setIn(InputStream in)- schimb unitatea de intrare standard.

Noua unitate de intrare standard va fi obiectul din clasa InputStream dat prin argumentul in.
public static void setOut(PrintStream out)- schimba unitatea de ieire standard

pentru date. Noua unitate de ieire va fi obiectul din clasa OutputStream dat prin argumentul out.
public static void setErr(PrintStream err)- schimb unitatea de ieire standard

pentru erori. Noua unitate de iesire va fi obiectul din clasa OutputStream dat prin argumentul err.
public static long currentTimeMillis()- ntoarce timpul

curent n milisecunde. Acesta este un numr de tip long, care exprim timpul n milisecunde msurat cu ncepere de

120

Programarea orientata pe obiecte n limbajul Java la data de 1 ianuarie 1970 ora 0.

Tablouri
Conceptul de tablou
Tabloul (n englez Array) este o structur de date de acelasi tip, numite componente ale tabloului, care sunt specificate prin indici. n programare, tabloul poate fi privit ca o colecie indexat de variabile de acelai tip. Exemple tipice de tablouri sunt vectorul i matricea din matematic. Un vector este o colecie indexat de componente cu un singur indice. De exemplu x=[x0, x1, ... , xn-1] este un vector cu n componente. Componentele au acelai "nume" cu vectorul, dar se disting prin indici, care specific poziia componentei respective n cadrul tabloului. n limbajul Java, la fel ca n limbajele C/C++, indicii ncep de la 0. ntruct componentele vectorului sunt dispuse pe o singur direcie n spaiu, spunem c este un tablou unidimensional. La nivel conceptual, se consider c tabloul ocup o zon compact de memorie, n care componentele sale sunt aezate n ordinea cresctoare a indicilor, din care cauz mai este numit i masiv. Matricea este un tablou bidimensional. Componentele matricei sunt ordonate pe dou direcii n spaiu, iar poziia fiecrei componente este indicat prin doi indici: primul specific linia, iar al doilea coloana n care se gsete componenta respectiv. Iat un exemplu de matrice cu 4 linii i 5 coloane:

a00 a10 a20 a30

a01 a11 a21 a31

a02 a12 a22 a32

a03 a13 a23 a33

a04 a14 a24 a34

n acest exemplu, numele matricei, ca i numele fiecrui element al ei, este a. Poziia componentei n cadrul matricei este specificat prin cei doi indici. Conform conveniei de indexare din limbajul Java, indicii incep de la zero. Pot exista i tablouri cu mai mult de dou dimensiuni. Astfel, un tablou tridimensional poate fi imaginat ca un volum (o carte), avnd mai multe pagini, fiecare pagin fiind un tablou bidimensional (o matrice). n acest caz, primul indice specific linia, al doilea - coloana, iar al treilea - pagina n care se gsete componenta respectiv. n mod similar, un tablou cu patru dimensiuni poate fi privit ca o serie de volume; fiecare component, n acest caz, are patru indici, cel de al patrulea fiind numrul volumului n cadrul seriei. Putem, desigur, continua raionamentul i pentru tablouri cu mai muli indici.

121

Severin Bumbaru

Tablourile n limbajul Java


n limbajul Java, tablourile (engl.: Arrays) sunt considerate obiecte care aparin unor clase descendente din clasa Object. n consecin, variabilele care au ca valori tablouri sunt variabile referin, iar alocarea tablourilor n memorie se face dinamic, prin operatorul new, la fel ca n cazul celorlalte obiecte. Mai mult, unor variabile referin la Object li se pot da ca valori referine la tablouri, deoarece clasa Object este superclasa oricrei alte clase, deci i a oricarui tip de tablou. Tipul tabloului coincide cu tipul componentelor sale. Componentele pot aparine unor tipuri de date primitive, sau unor clase.

Tablouri cu un singur indice (unidimensionale)


Aceste tablouri corespund conceptului matematic de vector. Nu le vom numi totui astfel, pentru a nu face confuzie cu obiectele clasei Vector din pachetul java.util. Tabloul unidimensional este constituit dintr-un ansamblu de componente indexate (cu un singur indice), cruia i se asociaz i o variabila de tip int numita length, care reprezint lungimea tabloului (numrul de componente). Indicii elementelor de tablou sunt cuprini n intervalul [0, length-1]. Utilizarea unui indice situat n afara acestui interval genereaz o excepie. ntruct tablourile sunt obiecte, pentru indicarea lor n program se folosesc variabile referin.

Declararea i iniializarea tablourilor cu un singur indice


Variabilele referin la tablouri cu un singur indice pot fi declarate n dou moduri: a/ ntr-o declaraie de variabile se pune simbolul [] (o pereche de paranteze drepte) dup numele variabilei referin la tablou. Ca exemplu, s considerm declaraiile urmtoare:
int a, b, c[], d, e[]; String s1, ts1[], s2; n aceste declaraii, a, b, i d sunt variabile simple de tip double, deci ele pot primi valori simple de acest tip, iar s1 i s2 sunt variabile referin la obiecte din clasa String (la iruri de caractere). n schimb, c[] i e[] sunt variabile referin la tablouri de tip int (tablouri la care toate componentele sunt de tip int), iar ts1[] este o variabil referin la un tablou cu componente din clasa String.

b/ Parantezele se pun dup numele tipului de date sau al clasei, n care caz toate variabilele din declaraia respectiva sunt considerate drept referine la tablouri. De exemplu, n declaraiile
int[] i, j; long [] k, m; float []u, v; String[] ww; variabilele i, j, k, m, u, v, ww

sunt referine la tablouri cu componente de tipuri corespunztoare fiecarei declaraii. Remarcm c nu are importan dac parantezele sunt puse imediat dup numele tipului sau clasei (far spaiu liber) sau ntre acestea exist unul sau mai multe spaii. Iniializarea tablourilor unidimensionale se poate face, de asemenea, n dou moduri: a/ indicnd valorile componentelor tabloului, separate prin virgule i cuprinse ntre acolade, ca n exemplele urmtoare: 122

Programarea orientata pe obiecte n limbajul Java


int a=27, b=-15, c[]={-3,72,-21},d=-5,e[]={231,-98}; String s1="un sir", ts1[]={"sirul 0", "sirul 1", "sirul 2"}, s2="alt sir"; float[] u={-1.24076f, 0.03254f, 27.16f}, v={2.7698E-12f, -3.876e7f};

Remarcm c n ultima declaraie nu s-au mai pus paranteze dup numele variabilelor, deoarece ele apar dup numele tipului. b/ folosind operatorul new, urmat de numele tipului sau al clasei, nsoit de dimensiunea tabloului (numrul de elemente din tablou) scris ntre paranteze drepte, ca n exemplele urmtoare:
double aa[]=new double[3]; String str[]=new String[2];

n primul caz, se aloc n memorie spaiu pentru un tablou cu 3 componente de tip double, iar variabilei aa i se d ca valoare referina la acest tablou. n al doilea caz, se aloc n memorie un tablou de variabile referin la obiecte din clasa String, iar variabilei str i se d ca valoare referina la acest tablou. Iniializarea unei variabile referin la tablou cu componente aparinnd unei anumite clase se poate face att cu tablouri din clasa respectiv, ct i din clase descendente ale acesteia. De exemplu, n declaraia
Object tab1[]=new Object[2], tab2[]=new String[3], tab3[]={"aaa","bbb","ccc"}; variabila tab1 este initializata cu o referin la un tablou de componente din clasa Object, n timp ce variabilele tab2 i tab3 sunt iniializate cu referine la tablouri de iruri, clasa String(ca orice alta clas) fiind descendent a clasei Object.

n programul din fiierul InitTab1.java se testeaz declaraiile i iniializrile de mai sus i altele similare i se afieaz valorile componentelor tablourilor iniializate. Se observ c, n cazul folosirii operatorului new pentru alocarea de tablouri, componentele acestora se iniializeaz la valorile lor implicite: 0 pentru date numerice i null pentru obiecte.

Atribuirea de valori variabilelor referin la tablou


Unei variabile referin la tablou i se poate atribui ca valoare o referin la un tablou de acelasi tip, sau dintr-o clas descendent a acestuia. Aceast referin poate fi obinut prin operatorul new (n care caz se aloc n memorie un nou tablou), fie printr-o expresie care are ca valoare o referin la un tablou de tip corespunzator deja existent n memorie. n programul din fiierul Tab1.java se dau astfel de exemple.

123

Severin Bumbaru

Utilizarea tablourilor
Componentele tablourilor pot fi utilizate ca orice variabile simple. Referina la o component de tablou se face prin numele tabloului, insoit de indicele componentei pus ntre paranteze drepte. De exemplu, u[3] este componenta de indice 3 a tabloului u, iar aa[i] este componenta de indice i a tabloului aa. Indicele poate fi orice expresie de tip ntreg, cu condiia ca valoarea acesteia s nu iasa din cadrul domeniului de indici admis pentru tabloul respectiv. Un exemplu de utilizare a variabilelor indexate s-a dat deja n programul din fiierul InitTab1.java , cnd au fost afiate valorile componentelor tablourilor. Alte exemple se dau n programul din fiierul Tab1.java. Este instructiv s urmrim n figurile urmtoare cum evolueaz datele din memorie n timpul executrii acestui program.

- Fig. 1 n figura 1 sunt reprezentate datele din memorie dup executarea instruciunilor
double a[]={3.276, -5.83, 12.8}, b[]; String ts1[]={"aa","bb"}, ts2[]; b=a; ts2=ts1;

Prin prima declaraie s-au creat n memorie variabilele referin la tablouri de tip double a[] i b[], s-a creat, de asemenea, un tablou cu trei componente de tip double i s-a dat ca valoare variabilei a referina la acest tablou. Prin a doua declaratie, s-au creat variabilele referin la tablouri de tip String ts1[] si ts2[] i un tablou de tip String cu dou componente, iar variabilei ts1 i s-a dat ca valoare o referin la acest tablou. Prin instruciunea b=a i s-a atribuit variabilei b[] aceeai valoare-referin ca cea din a[], iar prin ultima instruciune s-a atribuit variabilei ts2[] acceai valoare-referin ca a lui ts1[]. Remarcm deosebirea important dintre tabloul de tip double i cel de tip String. Primul dintre ele are drept componente date de tip primitiv. n consecin, "celulele" tabloului conin chiar valorile de tip double ale componentelor corespunztoare. n schimb, cel de al doilea este un tablou de obiecte din clasa String, deci componentele lui sunt, de fapt, variabile referin la obiecte String, iar aceste obiecte sunt reprezentate n memorie separat. n ambele cazuri, componentele tabloului sunt tratate ca nite variabile al cror tip este corespunztor declaraiei. tim ns c variabilele de tipuri primitive au ca valori chiar date primitive, n timp ce pentru obiecte se folosesc variabile referin. n figura 2 este reprezentat situaia creeat dup ce s-au executat instruciunile de atribuire

124

Programarea orientata pe obiecte n limbajul Java


b[0]=-12.7; b[1]=283.6;

- Fig. 2 ntruct variabilele referin a[] i b[] indic acelai tablou, este normal ca valorile componentelor a[i] sunt i acum aceleai cu ale componentelor b[i], ceeace se constat i din afiarea prin program a datelor respective. n figura 3 este reprezentat situaia creat dup executarea instruciunii b=new double[4].

- Fig. 3 Prin operatorul new s-a alocat n memorie un nou tablou cu 4 componente double, iar lui b[] i s-a dat ca valoare referina la acest tablou. Imediat dup iniializare componentele noului tablou au valoarea zero, deoarece aceasta este valoarea implicit pentru tipurile de date numerice. n schimb, valoarea variabilei referin a[] a ramas aceeai, pe care a avut-o anterior. Acestor componente putem sa le dm acum valori prin program. n acelai program se testeaz i situaia n care se ncearc accesul la tabloul b[] cu un indice care iese din domeniul admis [0 ... b.lenght-1]. Se constat c se produce excepia java.lang.ArrayIndexOutOfBoundsException.

Conversii de tip pentru referine la tablouri


Tablourile cu componente aparinnd unor tipuri de date primitive sunt considerate c sunt obiecte ale unor clase cu numele
tip[]

De exemplu, un tablou cu componente double (deci care a fost declarat ca double[]), aparine clasei double[], care este descendent a clasei Object (nu a clasei Object[], care conine tablourile de obiecte). n mod asemantor, un tablou cu componente dintr-o anumit Clasa este considerat ca aparinnd clasei Clasa[] care, de asemenea, este

125

Severin Bumbaru descendenta a clasei Object. De exemplu, daca s-au fcut declaraiile
int a[]={54, 23, -17}, b[]; String str1[]={"abc","def"}, str2[], str3[]; Object ob1, ob3, tob1[];

sunt permise fara conversie explicit atribuiri de forma:


tob1=str1; ob1=a; ob3=str1; n primul caz, tob1 este o referin la un tablou cu componente din clasa Object, iar str1 este referin la un tablou cu componente din clasa String, care este descendenta a clasei Object. n urmtoarele dou cazuri, ob1 si ob3 sunt referine la Object, iar tablourile a[] i str1[] aparin claselor int[] i, respectiv, String[], care sunt i ele descendente ale clasei Object.

n schimb, atribuirile urmtoare necesit conversie explicit (prin cast), deoarece se fac de la superclas la clas:
str2=(String[])tob1; b=(int[])ob1; str3=(String[])ob3;

Pentru a face referin la componente din tablourile referite de variabilele ob1 sau ob3 este necesar, de asemenea, conversie explicit, deoarece ob1 siob3 nu au fost declarate ca tablouri. Se va scrie deci: ((int[])ob1).length, ((int[])ob1)[k], ((String[])ob3).length, ((String[])ob3)[j]. Nu trebuie, insa, facuta conversie explicit n cazul componentelor tabloului referit prin tob1[], deoarece vsrisbila tob1 a fost declarat ca referin la tablou, iar clasa Object este superclas a clasei String. Este, deci permis referina tob1[k]. Exemplele de mai sus, si altele, sunt testate n programul din fiierul ConvTip1.java. n acelai program, se testeaz i numele claselor-tablouri ntoarse de metoda getName() a clasei Class. Explicarea codificrilor respective este dat n documentaia java API, la descrierea acestei metode.

Tablouri cu doi sau mai muli indici (multidimensionale)


Tabloul cu N indici este considerat n limbajul Java drept un tablou de referine la tablouri cu N-1 indici. Vom exemplifica aceasta pentru cazul tabloului cu doi indici (bidimensional) i vom extinde apoi conceptul la tablouri cu mai mult de dou dimensiuni.

Tablouri cu doi indici


Tablourile bidimensionale din limbajul Java sunt o generalizare a conceptului de matrice, n matematic, toate liniile unei matrice au acelai numr de componente, n timp ce n Java

126

Programarea orientata pe obiecte n limbajul Java numrul de componente poate fi diferit de la o linie la alta (deci liniile "matricei" pot avea lungimi diferite). Tabloul cu doi indici este privit ca un tablou ale crui componente sunt referine la tablouri cu cte un singur indice. Putem, deci, s ne imaginm un "tablou coloan" care conine n fiecare component o referin ctre un "tablou linie". Fiecare din aceste "tablouri linie" are propria sa variabil length i deci propria sa lungime. n schimb, variabila length a "tabloului coloan" reprezint lungimea acestui tablou, adic numrul de linii. "Tipul tabloului" este, de fapt, tipul componentelor "liniilor" acestuia.

127

Severin Bumbaru

Declararea i iniializarea tablourilor cu doi indici


Tabloul bidimensional poate fi declarat n mod asemntor celui unidimensional, dar punnd dup numele variabilei dou perechi de paranteze drepte. Rmne valabil i regula c, dac perechea de paranteze drepte se pune dup numele tipului sau al clasei, ea se aplic tuturor variabilelor din declaraia respectiv. Fie, de exemplu, urmtoarele declaraii:
double u, v[], w[][]; int[] a, b[]; char[][] h1, h2; String ts[][];

Conform acestor declaraii: - u este o variabil simpl de tip double; - v este un tablou unidimensional, iar w un tablou bidimensional, ambele cu componente de tip double; - a este un tablou unidimensional, iar b un tablou bidimensional, ambele cu componente de tip int; - h1 i h2 sunt tablouri bidimensionale cu componente de tip char; - ts este un tablou bidimensional, avnd drept componente referine la String. Iniializarea tablourilor bidimensionale se face, de asemenea, asemntor cu a celor unidimensionale, avnd ns i unele trsturi specifice. Iat cum putem introduce n declaraiile de mai sus iniializri folosind forma cu acolade sau operatorul new:
double u=5.3127, v[]={1,25, -3.12, 2,6}, w[][]={{2.31,-4.15},{0.35,-12.6,-573.2},{10.9}}; int[] a={3,2,7}, b[]={{43,28,92,-6},{},{-1,17,29}}; char[][] h1={{'a','*'},{'+','$'}}, h2=new char[2][3], h3=new char[4][]; String ts[][]={{"abc","defg"},{"AB","CD","EF","GH"}};

Remarcam ca, la forma de iniializare cu acolade, tabloul bidimensional este tratat ca un tablou (acoladele exterioare) care are drept componente alte tablouri (acoladele interioare). Acestea din urm reprezint "liniile" tabloului bidimensional i pot avea lungimi diferite, unele din ele putnd avea chiar lungimea zero (n acest caz acoladele respective nu conin nimic), ca n cazul liniei a doua a tabloului b. La folosirea operatorului new exist urmatoarele posibiliti de iniializare: a/ se indic att numrul de linii, ct i numrul de coloane, de ex. new int[7][4]; n acest caz, se iniializeaz o matrice, n care toate liniile au acelai numr de componente. n exemplul nostru, matricea are 7 linii i 4 coloane, toate cele 7x4=28 componente fiind iniializate cu valorile implicite ale tipului respectiv (n cazul de fa zero); b/ se indic numai numrul de linii, de exemplu: new int[7][]. n acest caz se iniializeaza, de fapt, numai "vectorul coloan" care contine referine (deocamdata nule) ctre linii care, deocamdat, nu exist, urmnd sa fie atribuite ulterior. n figura 1 este reprezentat matricea w dupa iniializare.

128

Programarea orientata pe obiecte n limbajul Java

- Figura 1 Se observ c variabila w conine numai o referin ctre un tablou cu trei componente care, la rndul lor, conin referine ctre trei tablouri care conin cele trei linii ale tabloului bidimensional indicat de variabila w. In aceasta situaie, cele trei "linii" ale tabloului bidimensional pot s fie situate n locuri diferite din memorie, fr a mai forma o zon compact. n schimb, fiecare "linie" este, n acest caz, un tablou compact, ale crui componente sunt valori primitive de tip double. S considerm acum tabloul
String ts[][]={{"abc","defg"},{"AB","CD","EF","GH"}};

Acest tablou este reprezentat in figura 2.

- Figura 2 Componentele tabloului sunt aici, de fapt, referine la obiecte din clasa String. La nivel conceptual ns, noi privim acest tablou ca i cnd ar avea drept componente nsi aceste obiecte. Pentru a le distinge mai uor, n figura 2 obiectele din clasa String au fost trasate cu culoare albastr. Iniializrile de mai sus sunt testate n programul din fiierul Tab2.java.

Operaii cu tablouri bidimensionale

Numrul de componente
tim c fiecrui tablou unidimensional i este asociat o variabil length, care are ca valoare "lungimea" tabloului, adic numrul de componente ale acestuia. Ce reprezint variabila length n cazul unui tablou bidimensional? Sa privim din nou figura 1. ntrucat w.length este numrul de componente din tabloul unidimensional referit de variabila w, nseamn c el este egal cu numrul de linii al tabloului bidimensional. n schimb, numrul de componente

129

Severin Bumbaru din linia referit de componenta w[i] a tabloului w este dat de variabila w[i].length. De exemplu, numrul de componente din linia de indice 0 este w[0].length. n programul din fisierul Tab2.java se determin astfel numrul de linii i numrul de componente din fiecare linie pentru fiecare din tablourile bidimensionale iniializate n programul respectiv.

Referirea la componentele tabloului


Pentru a indica o anumit component a unui tablou bidimensional, se folosete variabila referin la tablou, nsoit de indicii componentei respective. De exemplu, w[i][j] este componenta situata n linia i i coloana j a tabloului referit de variabila w. Indicii pot fi literali ntregi, variabile sau expresii de tip ntreg, de exemplu w[2*k-1][j-3]. Referirile la componentele de tablou au fost folosite, de exemplu, n programul din fiierul Tab2.java la afiarea tablourilor. n acelai program se poate urmri i cum sunt afiate componentele tablourilor, n situaia cnd liniile acestor tablouri au lungimi diferite. Componentele de tablou astfel referite pot fi folosite n orice expresii din program, la fel ca variabilele simple. Iat doua exemple de instruciuni, n care se folosesc componentele tabloului bidimensional w:
t=2*w[1][0]*Math.cos(3.5*w[1][1]-0.23); w[j][k+1]=2*w[j-1][k]-w[j][k-1];

Bineneles, trebuie avut grij ca indicii s nu ias din domeniile admise pentru fiecare din ei deoarece, n caz contrar, vor apare excepii la executarea programului.

Referirea la tablou i la liniile tabloului


Variabila referin la tablou, nensoit de indici, este o referire la ntregul tablou. Dac folosim nsa variabila referin la un tablou bidimensional nsoit de un singur indice, aceasta este o referin la o linie a tabloului respectiv. De exemplu, n cazul tabloului bidimensional w, w[i] este o referin la linia i a tabloului indicat de variabila w. Variabilele w i w[i] pot fi folosite i ele n diferite expresii. Astfel s-a procedat mai sus, n expresiile w.length si w[i].length. S urmrim acum un exemplu, n care se ilustreaz folosirea acestor referine n instruciuni de atribuire. S urmarim programul din fiierul Tab2a.java, fcnd i schemele tablourilor din memorie in diferite etape de execuie a acestuia. Se fac mai inti urmtoarele declaraii cu iniializri de tablouri:
int a[][]={{-5,12,52},{8,-4},{},{105}}, b[]={31,-3,17,24}

Rezultatul aceztor initializari este reprezentat in figura 3.

130

Programarea orientata pe obiecte n limbajul Java

- Figura 3Se fac apoi urmatoarele atribuiri:


a[0][2]=2*b[1]-a[1][1]; a[2]=new int[3]; a[2][0]=b[3]; a[2][2]=a[3][0]; a[3]=b; b=a[1]; b[1]=88;

Situatia creat n memorie dup aceast secven de atribuiri este reprezentat in figura 4.

- Figura 4 n aceasta figur, pentru a fi urmrite mai uor, modificarile au fost fcute cu culoare roie. A fost creat, prin operatorul new, un nou tablou cu trei elemente, care a devenit noua linie a[2]. S-au atribuit valori pentru a[2][0] si a[2][2], iar componenta a[2][1] a rmas la valoarea implicit 0 cu care a fost iniializat. Fosta linie a[3], format numai dintr-o singur component cu valoarea 105, a rmas fr referin i va fi eliminat de ctre colectorul de reziduuri de memorie. Noua linie a[3] este acum fostul tablou b, iar tabloul unidimensional indicat de variabila referinta b este acum acelasi cu linia a[1]. Toate aceste modificari pot fi verificate executnd programul din fiierul Tab2a.java .

Conversii de tip la tablouri cu doi indici


Regulile aplicate pentru conversii la tablourile bidimensionale sunt aceleai cu cele pentru tablouri unidimensionale. S urmrim urmtorul exemplu, care este testat n programul din fiierul Tab2b.java. Fie declaraiile:
Object ob1, ob2, tob2[][]; int ti1[][]={{0,1},{10,11,12,13},{20,21,22}},ti2[][]; String ts[][]={{"aa","ab"},{"ba","bb","bc"},{"ca","cb"}},ts1[][];

131

Severin Bumbaru

Cu aceste declaraii, urmtoarele atribuiri


ob1=ti1; ob2=ts;

sunt corecte, deoarece clasele ti1[][] i ts[][] sunt descendente ale clasei Object. n schimb, atribuirile
ti2=ob1; ts1=ob2;

nu sunt corecte, deoarece se fac n sens "descendent". tiind, totusi, c variabilele ob1 i ob2 conin efectiv referine ctre obiecte din clasele int[][] i respectiv String[][], putem face conversii explicite sub forma:
ti2=(int[][])ob1; ts1=(String[][])ob2;

Numrul de linii al tabloului indicat de variabila referin ob1 este ((int[][])ob1).length, iar numarul de componente din linia i a aceluiasi tablou este ((int[][])ob1)[i].length. De asemenea, componenta situat n linia i i coloana j este((int[][])ob1)[i][j]. S ncercm acum atribuirea ti2=(int[][])ob2; n acest caz, compilatorul nu poate sesiza eroarea, deoarece n momentul compilrii nu are informaie despre adevarata clasa creia i aparine obiectul indicat de variabila ob2. n schimb, la execuie se constat c obiectul indicat de ob2 aparine clasei String[][], n timp ce variabila ti1 apartine clasei int[][], aa c se va genera excepia ClassCastException.

Tablouri cu mai muli indici


Modul de tratare al tablourilor cu doi indici poate fi extins i la tablouri cu mai muli indici (tablouri multidimensionale). Se are n vedere ca tabloul cu N indici conine referine la tablouri cu N-1 indici. De exemplu un tablou cu trei indici (tridimensional) poate fi considerat c conine mai multe "pagini", iar fiecare "pagin" este un tablou cu doi indici (bidimensional). n acest caz, primii doi indici specifica linia i, respeectiv, coloana, iar al treilea indice specifica "pagina" n care se gsete o anumit component. Un tablou cu patru indici poate fi asemnat cu un set de "volume", n care fiecare "volum" este un tablou cu trei indici, iar cel de al patrulea indice specifica numarul "volumului" din acest set. Putem sa ne imaginam astfel si semnificaii ale unor tablouri cu mai mult de patru indici. Totui, n practic, cele mai frecvent folosite tablouri au cel mult trei indici.

Tablouri eterogene
Prin definiie, componentele unui tablou trebuie s fie toate de acelai tip. n programarea orientat pe obiecte, aceast restricie a fost "relaxat", n sensul c un tablou poate avea drept componente i obiecte aparinnd claselor descendente din clasa de baz. Faptul c clasa Object este superclas a oricrei alte clase din limbajul Java, inclusiv a claselor de tablouri, permite s se creeze tablouri eterogene, adic tablouri cu componente care aparin unor clase foarte diferite. Acestea pot fi structuri complicate de date, realizate pornind de la structura de "tablou de obiecte". S consideram, de exemplu, structura de date din figura 5.

132

Programarea orientata pe obiecte n limbajul Java

- Figura 5 n programul din fiierul TabEterogen.javase construiete aceast structur de date eterogen i se afieaz unele dintre componentele ei.

Utilizarea parametrilor din linia de comand


A venit timpul s ne ocupm de argumentul args[] al metodei
public static main(String args[]) Remarcm ca argumentul formal args[] al acestei metode este un tablou unidimensional, ale crui componente sunt din clasa String, deci sunt iruri de caractere. La lansarea n

execuie a aplicaiei, acest argument preia drept componente de tablou parametrii din linia de comand prin care s-a fcut lansarea. Aceti parametri pot fi, astfel, folosii n program dup necesiti. Exemplu: s considerm urmtorul program din fiierul Parametri.java:

class Parametri { public static void main(String args[]) { if(args.length==0) System.out.println("Nu ati introdus parametri in linia de comanda"); else { System.out.println("Aplicatia are urmatorii parametri:); for(int i=0; i<args.length; i++) System.out.println(args[i]); } } }

Lungimea tabloului args (numrul de componente) este, dup cun tim, args.length. n acest program, dac numrul de parametri este nul, se afieaz mesajul "Nu ai introdus 133

Severin Bumbaru parametri n linia de comand". n caz contrar, se afieaz toi parametrii. S considerm c lansarea acestui program s-a fcut prin urmtoarea linie de comand:
java Parametri abcd EFG-HIjk 1376 7.3086 -15

La executarea programului se afieaz:

Aplicatia are urmatorii parametri: abcd EFG-HIjk 1376 7.3086 -15

Constatm, deci, c unicul separator ntre parametri este spaiul liber, iar numerele sunt preluate tot sub forma de iruri de caractere. Putem rula acum acest program n mod repetat cu diferite seturi de parametri, pentru a urmri cum se comport. Putem constata de asemenea c, dac ntre doi parametri exist mai multe spaii libere succesive, ele sunt tratate ca i un singur spaiu.

ntrebri
Nivel 1
1. Ce deosebire este ntre tipul referin i tipurile primitive? 2. Unde sunt plasate n memorie obiectele? 3. Care sunt operaiile permise asupra variabilelor-referin? 4. Cum se declara variabilele referin? 5. Ce este un cmp? 6. Ce deosebire este ntre cmpurile statice i cele nestatice? 7. Ce este o metod? 8. Ce deosebire este ntre metodele statice i nestatice? 9. Cum este invocat o metoda static? 10. Cum este invocat o metoda a instanei? 11. Ce este un constructor? 12. Cum este invocat un constructor? 13. Ce este motenirea? 14. Ce este o superclas? 15. Ce legatur este ntre o clas i clasele derivate din aceasta? 16. Ce este polimorfismul? 17. Ce fel de motenire este permis n Java? 18. Care este rdcina ierarhiei de clase n Java? 19. Ce este un pachet? 20. Ce este Java API? 21. Ce conine pachetul java.lang?

134

Programarea orientata pe obiecte n limbajul Java 22. La ce serveste declaratia import si ce forma are? 23. Cum este importat pachetul java.lang? 24. Fie a i b dou obiecte. Ce deosebire este ntre a.equals(b) i a==b? 25. Ce rol are metoda toString()? 26. Ce este o excepie? 27. Ce este clasa Exception? 28. Care este clasa irurilor de caractere? 29. Ce este concatenarea irurilor i prin ce operator se realizeaz? 30. Cum se compar dou iruri? 31. Ce este ordinea lexicografic? 32. Cum se determina lungimea unui ir? 33. La ce folosete metoda trim()? 34. Ce fel de obiecte aparin clasei StringBuffer? 35. Ce deosebire este ntre lungimea i capacitatea unui StringBuffer? 36. Care sunt principalele metode ale clasei StringBuffer? 37. Ce este o clas acoperitoare de tip? 38. Poate fi instaniat clasa Number? Justificai rspunsul. 39. Care sunt subclasele clasei Number? 40. Cum se poate determina cea mai mare valoare pe care poate s o aib un numr de tip int? 41. Cum se poate converti un numar ntreg din forma extern n cea intern? 42. Ce cmpuri statice conine clasa Double? 43. Cum se poate converti un numr n virgul mobil din forma extern n cea intern? 44. n ce cod sunt reprezentate caracterele n Java? 45. Ce este clasa Character? 46. Ce este clasa Math? 47. Cum se poate calcula sinusul trigonometric al unui numr? 48. Cum se poate calcula rdcina patrat a unui numr? 49. Cum se poate calcula logaritmul natural al unui numr? 50. Scriei n limbajul Java expresia prin care se calculeaza rdcina patrat din 2u2+eu. 51. Ce cmpuri statice conine clasa System? 52. Ce efect are metoda exit() din clasa System? 53. Ce este un tablou? 54. Cum se declar n Java un tablou unidimensional? 55. Ce semnificaie are declaraia int a, b[], c;? ce sunt a, b i c? 56. Ce semnificatie are declaratia int[] a, b, c;? ce sunt a, b i c? 57. Cum se iniializeaz n Java un tablou unidimensional? 58. Prin ce instruciune se creaz n Java un tablou cu 7 componente de tip double? 59. Cum se poate determina numrul de elemente dintr-un tablou unidimensional? 60. Cum sunt preluai parametrii din linia de comand? 61. Cum pot fi determinate valorile numerice ale parametrilor din linia de comand?

Nivel 2
1. Ce se gsete n zona de memorie afectat unei variabile care aparine unui tip primitiv? 2. Ce se gsete n zona de memorie afectat unei variabile referin?

135

Severin Bumbaru 3. Ce deosebire exist ntre o valoare primitiv i un obiect? 4. Fie declaraia Integer i1, i2; Ce sunt i1 i i2? 5. Fie declaratia int i1, i2; Ce sunt i1 i i2? 6. Care este efectul lateral al invocrii unui constructor? 7. Care este valoarea intoars de aplicarea operatorului new? 8. Ce este o declaratie de import la cerere i cum acioneaz? 9. Ce este codul de dispersie i prin ce metod se obine? 10. Ce rol are metoda clone()? 11. Ce deosebire este n Java ntre excepie i eroare? 12. Cum se determin poziia unui caracter ntr-un ir? 13. Cum se determin poziia unui subir ntr-un ir? 14. Prin ce metode se poate face adugarea de valori la un StringBuffer? 15. Prin ce metode se poate face nserarea de valori ntr-un StringBuffer? 16. Ce sunt instanele clasei Class? 17. Cum se poate determina numele clasei creia i aparine un obiect? 18. Cum se poate determina n timpul execuiei programului superclasa clasei unui obiect? 19. Prin ce metoda poate fi convertit din forma extern n cea intern un numar scris ntro baz oarecare? 20. Prin ce metoda se poate obine reprezentarea extern n sistemul binar a unui ntreg? 21. Prin ce metod poate fi obinut forma extern hexazecimal a unui ntreg? 22. Prin ce metod poate fi obinut forma extern octal a unui ntreg? 23. Cum se poate verifica dac un numar n virgula mobil are valoarea infinit? 24. Cum se poate verifica dac valoarea unei variabile n virgul mobil este un numr? 25. Cum se poate verifica dac un caracter este liter? 26. Cum se poate verifica dac un caracter este cifr? 27. Cum se poate face conversia literelor dintr-un ir din minuscule n majuscule? 28. Cum se poate face conversia literelor dintr-un ir din majuscule n minuscule? 29. Ce este clasa Void? 30. Scriei n limbajul Java expresia: e-|u|sin(2u+3)cos4u+ln(|u|+1). 31. Prin ce metod se poate determina timpul curent i n ce uniti se exprim acesta? 32. Prin ce metoda se poate schimba dispozitivul de intrare standard? 33. Prin ce metoda se poate schimba dispozitivul de ieire standard? 34. Crui concept matematic i corespunde conceptul de tablou unidimensional? 35. Crui concept matematic i corespunde conceptul de tablou bidimensional? 36. Ce legatur exist ntre conceptul de clas i cel de obiect? 37. Crei clase i aparine un tablou? 38. Cum se construiete o matrice cu 7 linii i 3 coloane cu elemente de tip double? 39. Este obligstoriu ca toate liniile unui tablou bidimensional s aib aceeai lungime? 40. Cum se poate determina lungimea unei linii dintr-un tablou bidimensional? 41. Cum se poate modifica n timpul execuiei lungimea unei linii dintr-un tablou bidimensional?

136

Programarea orientata pe obiecte n limbajul Java

Declararea claselor
Declararea claselor; Declararea cmpurilor. Cmpuri statice i cmpuri ale instanei. Iniializarea cmpurilor. Valori iniiale implicite; Declararea metodelor. Metode statice i metode ale instanei; Metode cu acelai nume; signatura metodei; Transferul parametrilor ctre metode la invocarea metodelor; Metode care ntorc o referin la un obiect construit n corpul lor; Metode care au ca argumente i/sau ca valori ntoarse referine la tablouri; Metode recursive; comparaie ntre iteraie i recursie; Metode care genereaz excepii; instruciunea throw i clauza throws; Clase publice Un exemplu: clasa complex Declararea clasei complex Utilizarea clasei complex Distrugerea obiectelor de ctre colectorul de reziduuri; Metoda finalize ntrebri.

Declararea claselor
Pn n prezent, s-a artat modul n care putem utiliza n programul nostru clase existente n biblioteci (n pachetele de clase). Vom studia n continuare cum putem crea propriile noastre clase. Cea mai simpl form a unei declaraii de clas este urmtoarea:
class NumeClasa { declaratii_de_membri }

Observm c declaraia ncepe cu cuvntul-cheie class, urmat de numele clasei i de corpul clasei, cuprins ntre acolade.

137

Severin Bumbaru Numele clasei este un identificator. Se obisnuiete ca numele clasei sa nceap cu liter majuscul. Dac numele este compus din mai multe cuvinte, fiecare din acestea ncepe cu majuscul. Corpul clasei cuprinde declaraii de membri ai clasei respective. Acestea pot fi: - declaraii de cmpuri; - declaraii de constructori; - declaraii de metode. Nu este obligatoriu ca ntr-o clas s existe toate aceste categorii de declaraii. Pot exista, de exemplu, clase n care apar numai declaraii de metode. n principiu, pot exista i clase care conin numai cmpuri i nu conin metode, dei astfel de situaii apar foarte rar n practic.

Declararea cmpurilor
Declaraiile de cmpuri servesc pentru a descrie structura de date specific clasei respective. Cmpurile se mai numesc i variabile membre i pot fi ale clasei sau ale instanei (ale obiectului). Se prefer denumirea de cmpuri, pentru a le deosebi de variabilele locale ale metodelor. Cmpurile instanei se declar la fel ca variabilele locale ale metodelor, numai c declaraia respectiv nu apare n blocul unei metode, ci n corpul clasei. De exemplu:
int m=172, n=2*m-4, r;

Aceste cmpuri pot avea valori diferite pentru fiecare instan a clasei respective. n consecin, cmpurile instanei sunt plasate n zona de memorie rezervat instanei respective, astfel c ele sunt distincte pentru fiecare instan. Cmpurile clasei se numesc i cmpuri statice. Declararea unor astfel de cmpuri se face asemntor cu cea a cmpurilor de instan, dar declaraia are n fa, n acest caz, modificatorul static.De exemplu:
static double u=3.65, v=2.87*u-3.1, x;

La iniializarea cmpurilor de instan se pot folosi att valori ale cmpurilor statice, ct i ale altor cmpuri de instan. n schimb, la iniializarea cmpurilor statice se pot folosi numai valori ale altor cmpuri statice.

Cmpurile statice (ale clasei) sunt plasate n memorie n zona rezervat clasei creia i aparin i nu n cea rezervata instanelor. n consecin, cmpurile clasei exist n memorie ntr-un singur exemplar, care este accesibil fiecrei instane. Valorile iniiale implicite ale cmpurilor: dac nu sunt iniializate explicit, cmpurile statice i cele nestatice primesc valori implicite astfel: - cmpurile booleene primesc valoarea false; - cmpurile numerice primesc valoarea 0 (chiar i cele de tip char, care este tot tip numeric!); - cmpurile referina primesc valoarea null. Remarcm, deci, c exist o deosebire ntre crearea cmpurilor (variabilelor membre) i crearea variabilelor locale. La crearea cmpurilor, acestora li se atribuie implicit o valoare iniial, n timp ce la crearea variabilelor locale acestora trebuie sa li se atribuie valori n mod

138

Programarea orientata pe obiecte n limbajul Java explicit. Dac o variabil local apare ntr-o expresie fr s aib o valoare atribuit anterior, compilatorul Java semnaleaza aceast situaie ca o eroare de programare.

Exemplu de clas care nu conine constructori explicii sau metode:

Acest exemplu este dat n scop didactic, pentru a ilustra declararea, iniializarea i utilizarea cmpurilor. Crearea unei clase fr metode nu corespunde principiului de baza al programrii orientate pe obiecte, conform cruia o clas conine att date, ct i metodele prin care acestea sunt tratate. n consecin, declararea unor clase fr metode se evit n practica programrii orientate pe obiecte, chiar dac o astfel de declaraie este permis. De altfel, chiar daca declaraia de clas nu conine constructori sau metode, ea are un constructor implicit (fr parametri) i motenete metodele superclasei, n particular metodele clasei Object. n exemplul din fiierul TestClasa1.java se declar i se utilizeaz o clas care nu conine constructori si metode, ci numai cmpuri de date. O astfel de clas este folosit, deci, ca o structur din limbajele neorientate pe obiecte (cum este struct n C sau record n Pascal). n acest fiier sunt declarate dou clase: clasa Proba1, care este o simpl structur de date fr metode proprii, i clasa TestClasa1, care conine metoda main si servete ca aplicaie n care se testeaz clasa Proba1. Clasa Proba1 este declarat astfel:

/* Declararea clasei Proba1 Clasa contine numai campuri de date */ class Proba1 { static int m=9, n=m-3; int a=7, b=m*a+1, c, d; char c1='@', c2; String s1="un sir", s2=s1+" extins", s3; }

n aceast clas, s-au definit cmpurile statice (ale clasei) m i n i cmpurile nestatice (de instan) a, b, c i d - toate de tip int. S-au declarat, de asemenea, cmpurile c1 i c2 de tip char i cmpurile s1, s2 i s3 care contin referine la instane ale clasei String. Unele din aceste cmpuri sunt iniializate, altele au valori iniiale implicite. La iniializarea cmpului de instan b s-a folosit i valoarea cmpului static a. Cmpurile c i d sunt iniializate implicit cu valoarea 0.

Amintim o deosebire important ntre modul cum sunt plasate n memorie valorile primitive i obiectele (instanele claselor): valorile primitive sunt plasate chiar n zona de memorie rezervat variabilelor respective, n timp ce instanele claselor sunt plasate n memoria

139

Severin Bumbaru dinamic. n consecin: - valorile cmpurilor primitive statice m i n sunt plasate n memorie o singur dat, n spaiul rezervat clasei Proba1; - valorile cmpurilor primitive nestatice a, b, c, d, c1 i c2 sunt plasate n cmpurile corespunztoare ale instanelor clasei Proba1, deci acestea vor avea cte o valoare pentru fiecare instan; - n campurile s1, s2 si s3 (care, n cazul nostru, sunt tot nestatice, deci se plaseaza n fiecare instan), ca valori se pun numai referine la instane ale clasei String. n consecin, irurile "un ir" i "un ir extins" se vor creea n memoria dinamic, sub forma de obiecte ale clasei String, iar n cmpurile s1 i s2 ale fiecrei instane a clasei Proba1 se vor pune numai referine la aceste iruri. Cmpul s3 va fi iniializat cu referina null. Clasa Proba1 poate fi utilizat n alte clase Java la fel ca o structur de date (nregistrare) "tradiional" cum ar fi struct n limbajul C, sau record n limbajul Pascal. Un exemplu de aplicaie, n care se utilizeaz clasa Proba1, este clasa TestClasa1 din fiierul TestClasa1.java, pe care o reproducem n continuare.

/* Programul in care se utilizeaza clasa Proba1 ca o structura obisnuita */ class TestClasa1 { public static void main(String args[]) { /* Se declara doua referinte catre instante ale clasei Proba1, iar prima din ele se si initializeaza */ Proba1 p1=new Proba1(), p2; /* Se mai creaza o instanta si se atribuie lui p2 */ p2=new Proba1(); /* Se afiseaza unele campuri ale instantelor p1 si p2; */ System.out.println("Campuri din p1: n="+p1.n+" m="+p1.m+" a="+ p1.a+" b="+p1.b+" c="+p1.c+" c1="+p1.c1+" c2="+p1.c2+ " (int)p1.c2="+(int)p1.c2); System.out.println("Campuri din p2: n="+p2.n+" m="+p2.m+" a="+ p2.a+" b="+p2.b+" c="+p2.c+"\n s1="+p2.s1+" s2="+p2.s2+ " s3="+p2.s3); /* Afisarea campurilor statice calificandu-le cu numele clasei */ System.out.println("Afisarea campurilor statice: m="+Proba1.m+ " n="+Proba1.n); /* Modificam atribuim p1.a si p2.a valori diferite, apoi reafisam toate campurile */ p1.a=12; p2.a=-9; System.out.println("Dupa modificarea valorilor campurilor a:"); System.out.println("Campuri din p1: n="+p1.n+" m="+p1.m+" a="+ p1.a+" b="+p1.b+" c="+p1.c); System.out.println("Campuri din p2: n="+p2.n+" m="+p2.m+" a="+ p2.a+" b="+p2.b+" c="+p2.c); /* Modificam campul static p1.m si reafisam p1.m, p2.m si Proba1.m */ p1.m=-12; System.out.println("Dupa modificare: p1.m="+p1.m+" p2.m="+p2.m+ " Proba1.m="+Proba1.m);

140

Programarea orientata pe obiecte n limbajul Java


/* Modificam campul static n folosind expresia Proba1.n si afisam */ Proba1.n=-25; System.out.println("Dupa modificare: p1.n="+p1.n+" p2.n="+p2.n+ " Proba1.n="+Proba1.n); /* Atribuim o valoare campului de instanta p1.c */ p1.c=1234; System.out.println("Dupa atribuire: p1.c="+p1.c+" p2.c="+p2.c); } }

La compilarea fiierului surs TestClasa1.java, vor fi create dou fiiere bytecode, cte unul pentru fiecare clas, numite n mod corespunztor Proba1.class i TestClasa1.class. Pentru executarea aplicaiei se va folosi comanda
java TestClasa1

Clasa Proba1 nu poate fi pus n execuie n acest mod, deoarece ea nu conine metoda main. Aceast clas poate fi folosit numai n cadrul altei clase. Rezultatele afiate pe ecran la executarea acestei aplicaii sunt urmtoarele:

Campuri din p1: n=6 m=9 a=7 b=64 c=0 c1=@ c2= (int)p1.c2=0 Campuri din p2: n=6 m=9 a=7 b=64 c=0 s1=un sir s2=un sir extins s3=null Afisarea campurilor statice: m=9 n=6 Dupa modificarea valorilor campurilor a: Campuri din p1: n=6 m=9 a=12 b=64 c=0 Campuri din p2: n=6 m=9 a=-9 b=64 c=0 Dupa modificare: p1.m=-12 p2.m=-12 Proba1.m=-12 Dupa modificare: p1.n=-25 p2.n=-25 Proba1.n=-25 Dupa atribuire: p1.c=1234 p2.c=0

Urmrind aceste rezultate, putem constata c: - cmpurile numerice neiniializate explicit (inclusiv cele de tip char) sunt iniializate implicit la valoarea zero; - valorile cmpurilor statice pot fi utilizate calificnd numele cmpului respectiv, att cu numele unei instane (de exemplu, p1.m), ct i calificandu-le cu numele clasei (de exemplu, Proba1.m); - valorile cmpurilor nestatice pot fi utilizate numai calificnd numele cmpului respectiv cu numele unei instane (de exemplu, p2.a); - dac se atribuie o nou valoare unui cmp nestatic al unei instane, valorile cmpurilor cu acelai nume ale celorlalte instane rmn nemodificate; - dac se atribuie o nou valoare unui cmp static, aceast modificare se constat n toate nstanele, deoarece cmpul respectiv este unic (exist numai n cadrul clasei).

Declararea metodelor
n programarea orientat pe obiecte, clasa conine, n mod normal, nu numai cmpuri de date, ci i metodele prin care se trateaz aceste cmpuri.

141

Severin Bumbaru Sub aspect conceptual, metoda este o funcie sau o procedur, care folosete drept date att valorile argumentelor sale, ct i cmpurile clasei creia i aparine metoda respectiv.

n principiu, deosebirea dintre funcie i procedur este c funcia "ntoarce" o valoare, n timp ce metoda nu ntoarce o valoare, ci are numai efect lateral. O funcie fr efect lateral este realizarea n program a conceptului matematic de funcie i este folosit n expresiile de calcul numai pentru valoarea ei. n limbajele C/C++ i Java, procedurile se scriu, din punct de vedere sintactic, la fel ca funciile, dar se consider c ele intorc o valoare special numit void. Acesta este un artificiu pentru a indica faptul c o asemenea "funcie" nu ntoarce o valoare. n limbajele de programare tradiionale, o funcie (sau procedura) folosete ca date argumentele sale i variabilele globale. n limbajul Java nu exist variabile globale i nici funcii independente (care s nu fie metode ale unor clase). n schimb, fiecare metod poate folosi ca date att argumentele salei variabilele locale, ct i cmpurile clasei creia i aparine metoda respectiv. Cea mai simpl form sintactic a declaraiei de metod este urmtoarea:
tip_valoare_intoarsa nume_metoda(declaratii_de_argumente) { corpul_metodei }

n care:
tip_valoare_intoarsa

- este tipul valorii primitive sau clasa valorii-referin ntoars de

aceasta metod;
nume_metoda- este un identificator care, n mod uzual, ncepe cu liter mic i constituie numele metodei; declaratii_de argumente - este o list de declaraii de argument separate prin virgul, deci ea poate avea forma: declaratie_argument1, declaratie_argument2, ... declaratie_argumentN

dar poate fi i vid. Lista declaraiilor de argument este cuprins ntre paranteze rotunde. Fiecare declaraie de argument are forma
tip_argument nume_argument

n care tipul sau clasa argumentului respectiv; un identificator care, n mod uzual, ncepe cu liter mic. Dup aceast list de argumente se deschide acolada unui bloc, care conine corpul metodei, adic secvena de instruciuni prin care se calculeaz valoarea funciei respective i/sau dac este cazul - se efectueaz aciunile care constituie efectele laterale ale acesteia.
tip_argument - este nume_argument- este

Instruciunea return
Dac funcia ntoarce o valoare (diferit de void), aceasta se indic prin instruciunea
return expresie;

Efectul acestei instruciuni este urmtorul: se evalueaza expresia expresie i se ncheie executarea funciei respective, ntorcnd valoarea astfel obinut. n consecin, chiar dac dup instruciunea return mai apar n corpul funciei respective i alte instruciuni, acestea nu vor mai fi executate. Dac metoda nu ntoarce o valoare (ntoarce void), folosirea instruciunii return nu este absolut necesar, ncheierea execuiei fcndu-se cnd se ajunge la acolada prin care se

142

Programarea orientata pe obiecte n limbajul Java sfrsete blocul funciei. Totui, dac este necesar s se ncheie n mod abrupt executarea corpului funciei, se poate folosi instruciunea return fr expresie.

Metode statice
La declararea metodelor statice, n faa tipului valorii ntoarse se pune modificatorul static. Metodele care conin n declaraie acest modificator se numesc statice sau ale clasei, spre deosebire de metodele obinuite care sunt ale instanei. n corpul metodelor statice se pot folosi numai cmpurile statice ale clasei respective i se pot invoca numai alte metode statice ale acestei clase. Exemplu n fiierul Cercuri.java se declar dou clase pentru cercuri: clasa Cerc1, n care aria i circumferina se calculeaza prin metode ale instanei, i clasa Cerc2, care conine metode statice.

/* Declararea clasei Cerc1 cu metode ale instantei */ class Cerc1 { static final double PI=3.141592653589793; double r; double arie() { return PI*r*r; } double circumferinta() { return 2*PI*r; } } /* Declararea clasei Cerc2 cu metode ale clasei (statice) */ class Cerc2 { static final double PI=3.141592653589793; static double arie(double r) { return PI*r*r; } static double circumferinta(double r) { return 2*PI*r; } }

Clasa Cerc1 conine cmpul static final PI i cmpul de instan r (raza cercului). Aceasta ntrucat numrul PI este o constant valabil pentru orice cerc, n timp ce raza cercului difer de la o instan la alta. Cele doua metode de instan, arie() i circumferinta(), nu au argumente, dar folosesc ca date cmpurile statice i de instan declarate n clasa respectiv.

143

Severin Bumbaru Invocarea acestor metode se face calificndu-le cu numele instanei. Clasa Cerc2 conine, de asemenea, cmpul static final PI, dar nu conine cmpul de instan r. n schimb, metodele sale sunt statice i primesc raza cercului ca argument. Invocarea acestor metode se face calificndu-le cu numele clasei. n fiierul Cercuri.java exist i clasa Cercuri, n care se folosesc clasele Cerc1 i Cerc2 declarate anterior. Iat aceast aplicaie:

/* Aplicatia in care se utilizeaza cele doua clase de cercuri declarate mai sus */ class Cercuri { public static void main(String args[]) { double r1=1, r2=7.32; Cerc1 c1=new Cerc1(), c2=new Cerc1(); c1.r=r1; c2.r=r2; System.out.println("Folosind metodele de instanta din clasa Cerc1:"); System.out.println("Pentru cercul c1: aria="+c1.arie()+ " circumferinta="+c1.circumferinta()); System.out.println("Pentru cercul c2: aria="+c2.arie()+ " circumferinta="+c2.circumferinta()); System.out.println("Folosind metodele statice din clasa Cerc2:"); System.out.println("Pentru raza r1: aria="+Cerc2.arie(r1)+ " circumferinta="+Cerc2.circumferinta(r1)); System.out.println("Pentru raza r2: aria="+Cerc2.arie(r2)+ " circumferinta="+Cerc2.circumferinta(r2)); } }

Remarcm c: - instanierea clasei Cerc1 s-a fcut folosind constructorul implicit Cerc1(); vom explica aceasta la capitolul "declararea constructorilor"; - atribuirea de valoare razei r a instanelor din clasa Cerc1 s-a fcut calificnd numele cmpului cu numele referinei la instan, de exemplu n instruciunea de atribuire c1.r=r1; - invocarea metodelor de instan s-a fcut calificnd numele metodei cu referina la instana respectiv: de exemplu c1.arie() calculeaz aria cercului cu referina c1 si, deci, va folosi implicit raza c1.r1; - invocarea metodelor statice ale clasei Cerc2 s-a fcut calificndu-le cu numele clasei i transmindu-le valoarea razei cercului ca argument, de exemplu Cerc2.arie(r1); - la compilarea fiierului surs Cercuri.java se obin trei fiiere de bytecode: Cerc1.class, Cerc2.class si Cercuri.class, corespunztoare celor trei clase declarate.

Metode cu acelai nume. Signatura metodei


n aceeai clas pot exista mai multe metode cu acelai nume, cu condiia ca ele s difere prin numrul i/sau tipul argumentelor. Pentru a deosebi ntre ele astfel de metode, s-a introdus conceptul de signatur.

144

Programarea orientata pe obiecte n limbajul Java Signatura metodei const din numele acesteia, nsoit de lista de argumente. n consecin, dou metode pot avea acelai nume, dac difer ntre ele prin signatur. Putem da exemple din clasele existente n pachetele deja studiate.

S considerm, de exemplu, urmtoarele metode ale clasei String:


int int int int indexOf(int ch) indexOf(int ch, int fromIndex) indexOf(String str) indexOf(String str, int fromIndex)

Se observ imediat c prima i a doua difer prin numrul argumentelor, prima i a treia difer prin tipul unicului argument, iar a doua i a patra difer prin tipul unuia din cele dou argumente.

Transferul de parametri ctre metode


La invocarea unei metode, este necesar s se transmit de la metoda care invoc la metoda invocat parametrii (argumentele) acesteia. De exemplu, la executarea invocrii Math.sin(a), este necesar s se transmit ctre metoda sin argumentul acesteia, a. n teoria i practica programrii se cunosc diferite moduri n car se poate face transmiterea argumentelor ctre o funcie sau procedur: - transmitere prin valoare: de la programul apelant ctre funcie (procedur) se transmit valorile argumentelor; - transmitere prin adresa: de la programul apelant ctre funcie (procedur) se transmit adresele la care se gsesc n memorie valorile argumentelor; - transmitere prin nume: de la programul apelant ctre funcie (procedur) se transmit numele argumentelor; - transmitere prin referin: de la programul apelant la funcie (procedur) se transmit referine ctre argumente. n limbajul Java, transmiterea parametrilor (argumentelor) metodelor se face prin valoare. Aceasta nseamn c: - dac argumentul aparine unui tip de date primitiv, se transmite chiar valoarea primitiv a argumentului respectiv; - dac argumentul aparine unui tip-referin (este instan a unei clase), se transmite - de fapt - o referin ctre un obiect din clasa respectiva sau dintr-o clasa derivat din aceasta.

Exemplu S considerm metoda int indexOf(String str, int fromIndex) din clasa String. Primul argument al acestei metode este o referin la un obiect din clasa String, iar al doilea argument este o valoare primitiv de tip int. n limbajul Java, cei doi parametri str si fromIndex sunt considerai variabile locale ale metodei indexOf, iar transmiterea parametrilor este echivalent cu operaia de atribuire. n consecin, dac se invoc aceast metod sub forma indexOf("abc", 3), variabilei-referin str i se atribuie ca valoare referina la sirul "abc" (i nu insui irul "abc", care rmne la locul lui n memoria

145

Severin Bumbaru dinamic), n timp ce variabilei fromIndex de tip int i se atribuie valoarea primitiv 3. S considerm acum c ntr-un program exist instruciunile:
int k=7, j; String s1="un exemplu de sir", s2="exem"; j=s1.indexOf(s2,k); Evaluarea metodei indexOf va decurge astfel: se transmit de la programul apelant ctre metoda indexOf valorile argumentelor s2 si k. Numai c s2 este o variabila-referin, deci valoarea ei este referina la irul "exem" i nu nsui acest ir. n schimb, valoarea variabilei k este chiar valoarea primitiv 7. n consecin, n irul indicat de s1, se va cuta subirul a crui referin este s2, ncepand cutarea de la poziia de indice 7.

n teoria programrii, argumentele (parametrii) care apar n declaraia unei metode (funcii, proceduri) se numesc parametri formali, iar valorile prin care se substituie aceti parametri formali la invocarea metodei respective se numesc parametri efectivi. Astfel, n exemplul de mai sus, str i fromIndex sunt parametri formali ai metodei indexOf, in timp ce "abc", 3, valoarea lui s2, i valoarea lui k sunt parametri efectivi. Consecina faptului c parametrii metodelor se transmit prin valoare este urmtoarea: chiar dac n corpul unei metode se atribuie unui argument formal al acesteia o nou valoare, aceast atribuire nu modific valoarea argumentului efectiv corespunztor din programul apelant. Daca ns, n cazul unui argument-referin, nu se modifica referina nsi, ci valorile cmpurilor obiectului indicat de ctre aceasta, modificarea respectiv se va transmite i la programul apelant, constituind efectul lateral al metodei respective.

Exemplu n fiierul TestParam.java este dat urmtorul program, n care se testeaz un caz de metod care i modific parametrii:
/* Testarea modului de transmitere a parametrilor catre metode */ /* O clasa oarecare, continand un camp a */ class Proba2 { int a; } class TestParam { /* O metoda in care se modifica valorile propriilor parametri formali */ static void modParam(int k, Proba2 p1, Proba2 p2) { System.out.println("La intrarea in modParam k="+k+" p1.a="+p1.a+ " p2.a="+p2.a); k=-111; // S-a modificat valoarea parametrului k de tip int p1.a=-222; // S-a modificat valoarea unui camp al obiectului cu // referinta p1, dar nu insasi referinta p1 p2=new Proba2(); // S-a modificat insasi referinta p2, catre // o noua instanta a clasei Proba2 p2.a=-333; // S-a atribuit valoare campului a al noii // instante referite prin p2 System.out.println("In modParam dupa modificarile de parametri:\n"+ "k="+k+" p1.a="+p1.a+" p2.a="+p2.a); }

146

Programarea orientata pe obiecte n limbajul Java

/* Metoda principala */ public static void main(String args[]) { // Se declara si se initializeaza variabilele int m=123; Proba2 pr1=new Proba2(), pr2=new Proba2(); pr1.a=333; pr2.a=444; System.out.println("In main inainte de a invoca modParam:\n"+ "m="+m+" pr1.a="+pr1.a+" pr2.a="+pr2.a); // Se invoca metoda modParam modParam(m, pr1, pr2); // Se afiseaza valorile parametrilor dupa revenirea din modParam System.out.println("In main dupa ce s-a invocat modParam:\n"+ "m="+m+" pr1.a="+pr1.a+" pr2.a="+pr2.a); } }

Executnd acest program, obinem afiate pe ecran urmtoarele rezultate:

In main inainte de a invoca modParam: m=123 pr1.a=333 pr2.a=444 La intrarea in modparam k=123 p1.a=333 p2.a=444 In modParam dupa modificarile de parametri k=-111 p1.a=-222 p2.a=-333 In main dupa ce s-a invocat modParam: m=123 pr1.a=-222 pr2.a=444

Remarcm c, dei n metoda modParam s-au modificat valorile lui k, p1.a si p2.a, la revenirea din modParam n main valorile lui m i pr2.a (care corespund respectiv lui k i p2.a din modParam) au rmas cele anterioare invocrii acestei metode, n timp ce pr1.a (corespunztoare lui p1.a) s-a modificat. Iat cum se explic cele constatate: 1/ Parametrul formal k este de tipul primitiv int. n consecin, la invocarea metodei modParam, parametrul efectiv corespunzator se transmite prin valoare, adic se poate considera c variabilei locale k din modParam i s-a atribuit valoarea lui m, respectiv 123. n schimb, valoarea variabilei m din main a rmas nemodificat. 2/ Parametrul formal p1 este de tip referin la o instan a clasei Proba2. La invocarea metodei modParam, acestui parametru i s-a atribuit valoarea variabilei referina pr1 din main, adic o referin ctre obiectul din clasa Proba2 care a fost creat n main i are cmpul a=333. n modParam se modific valoarea cmpului a din acest obiect. Este deci normal s constatm c, la revenirea din modParam, valoarea cmpului pr1.a s-a modificat, deoarece pr1.a==pr2.a. 3/ Parametrul formal p2, la fel ca p1, este o referin la o instan a clasei Proba2. La intrarea n modParam, lui p2 i se atribuie valoarea parametrului efectiv pr1 din main, adic o referin la obiectul n care campul pr1.a are valoarea 444. n metoda modParam se modific valoarea parametrului p2, adic se creeaza o nou instan a clasei Proba2 i se atibuie lui p2 ca valoare o referin la aceasta nou instan. Cnd se face apoi atribuirea p2.a=-333, se modific valoarea cmpului a din aceast nou instan, fr a se modifica valoarea cmpului pr2.a al obiectului referit iniial. n consecin, la revenirea n main constatm c pr2.a a rmas la valoarea anterioar invocarii metodei modParam.

147

Severin Bumbaru

Metode care ntorc o referin la un obiect construit n corpul lor


n limbajul Java este posibil ca o metod s ntoarc o referin la un obiect construit n interiorul ei. Un astfel de exemplu este dat n fiierul TestRef.java, care conine urmtorul program:
/* Testarea unei metode care intoarce un sir */ class TestRef { static String metoda1() { String str=new String("un sir"); System.out.println("In metoda1 str="+str); return str; } static void metoda2(String s) { String s1=new String("alt sir"); s=s1; System.out.println("In metoda2 s="+s); } public static void main(String args[]) { String sir1=null, sir2=null; sir1=metoda1(); metoda2(sir2); System.out.println("In main sir1="+sir1+"\nsir2="+sir2); } }

n metoda1 se creeaz prin operatorul new un nou ir, iar referina str la acesta este "ntoars" de aceast metod la executarea instruciunii return. n metoda2 se creeaz de asemenea un nou ir, dar referina la acesta se atribuie argumentului s al metodei. La executarea acestui program se obin urmtoarele rezultate:

In metoda1 str=un sir In metoda2 s=alt sir In main sir1=un sir sir2=null

Se observ c metoda1 a ntors corect referina ctre irul "un sir" care a fost creat n interiorul ei. n schimb, metoda2 nu a avut ca efect lateral transmiterea catre variabilareferin sir2 din main a referinei ctre obiectul "alt sir" creat n aceast metod deoarece, dup cum s-a artat anterior, transmiterea parametrilor se face prin valoare i deci modificarea n corpul metodei a valorii parametrului formal s nu afecteaz valoarea parametrului efectiv str2 prin care aces ta a fost substituit la invocarea metodei respective.

148

Programarea orientata pe obiecte n limbajul Java

Metode care au ca argumente i/sau ca valori ntoarse referine la tablouri


n limbajul Java, tablourile sunt obiecte. n consecin, dac parametrii formali ai unei metode sunt tablouri, numele lor sunt, de fapt, variabile-referin. De exemplu, n signatura metodei main
main(String args[]) parametrul formal args[] este o referin la un tablou, ale crui elemente aparin clasei String (sunt iruri de caractere). n consecin, tot ce s-a prezentat n seciunea anterioar cu

privire la folosirea ca parametri formali a variabilelor- referin este valabil i pentru tablouri. Pentru exemplificare, considerm programul urmtor, din fiierul TestTab.java.
/* Metode care au ca parametri si ca valori intoarse referinte la tablouri */ class TestTab { static int[] alpha(int a[], double b[]) { System.out.print("La intrarea in metoda alpha\n Tabloul a: "); for(int i=0; i<a.length; i++) System.out.print(a[i]+" "); System.out.print("\nTabloul b: "); for(int i=0; i<b.length; i++) System.out.print(b[i]+" "); /* Se creaza tabloul c si se dau valori elementelor lui */ int c[]=new int[4]; for(int i=0; i<c.length; i++) c[i]=2*i+1; System.out.println("\nTabloul c alocat si initializat in aceasta "+ "metoda:"); for(int i=0; i<c.length; i++) System.out.print(c[i]+" "); /* Se modifica valorile primelor doua elemente ale tabloului b */ b[0]=-777.77; b[1]=-999.99; /* Se creaza un nou tablou, iar referinta catre el se atribuie parametrului formal a: */ a=new int[3]; a[0]=1000; a[1]=1001; a[2]=1002; System.out.println("Inainte de iesirea din metoda alpha:"); System.out.print("Tabloul a: "); for(int i=0; i<a.length; i++) System.out.print(a[i]+" "); System.out.print("\nTabloul b: "); for(int i=0; i<b.length; i++) System.out.print(b[i]+" "); System.out.println(); return c; } public static void main(String args[]) { int p[]={10, 11, 12, 13, 14}, q[]; double w[]={1.1, 1.2, 1.3, 1.4, 1.5, 1.6}; q=alpha(p,w); System.out.println("In main dupa revenirea din alpha:"); System.out.print("Tabloul p: "); for(int i=0; i<p.length; i++) System.out.print(p[i]+" "); System.out.print("\nTabloul q: "); for(int i=0; i<q.length; i++) System.out.print(q[i]+" "); System.out.print("\nTabloul w: ");

149

Severin Bumbaru

for(int i=0; i<w.length; i++) System.out.print(w[i]+" "); System.out.println(); } }

Rezultatele afiate la executarea acestui program sunt urmtoarele:

La intrarea in metoda alpha Tabloul a: 10 11 12 13 14 Tabloul b: 1.1 1.2 1.3 1.4 1.5 1.6 Tabloul c alocat si initializat in aceasta metoda: 1 3 5 7 Inainte de iesirea din metoda alpha: Tabloul a: 1000 1001 1002 Tabloul b: -777.77 -999.99 1.3 1.4 1.5 1.6 In main dupa revenirea din alpha: Tabloul p: 10 11 12 13 14 Tabloul q: 1 3 5 7 Tabloul w: -777.77 -999.99 1.3 1.4 1.5 1.6

Urmrind executarea programului, constatm c: - dei parametrului formal a i s-a atribuit n interiorul metodei alpha o referin la alt tablou, nou construit, aceasta nu a afectat tabloul referit n metoda main prin parametrul efectiv corespunztor p; - ntruct n metoda alpha s-au modificat valorile elementelor tabloului referit prin parametrul formal b, aceste modificri apar i n metoda main n tabloul referit de parametrul efectiv corespunzatorw (deoarece b i w sunt, de fapt, referine la acelai tablou); - referina la tabloul c, creat n corpul metodei alpha, a fost intoars de aceast metod i a fost atribuit n metoda main variabilei referin q; n consecin, c i q sunt referine la acelai tablou. Remarcm c, la ieirea din metoda alpha, variabila local c este eliminat de pe stiva sistemului. Cu toate acestea, tabloul creat n metoda alpha i referit de aceast variabil local nu este eliminat din memorie, deoarece ctre el indic n continuare variabila-referin q din metoda main.

Metode recursive. Comparaie ntre iteraie i recursie


O metod (funcie sau procedur) care se invoc pe sine nsi se numete metod recursiv. Dou sau mai multe metode care se invoc una pe alta (metoda A invoc metoda B i reciproc) se numesc mutual recursive. Limbajul Java permite utilizarea metodelor recursive i mutual recursive. Vom ilustra aceasta prin exemple. Vom arta, de asemenea c, de regul, aceleai funcii pot fi calculate att recursiv, ct i iterativ (folosind cicluri). n general, n limbajele funcionale se utilizeaz predominant funciile recursive, n timp ce n limbajele procedurale se prefera iteraia, dei n unele dintre ele (cum este i limbajul Java) se pot folosi att iteraia, ct i recursia.

150

Programarea orientata pe obiecte n limbajul Java Remarcam c, la fel ca n cazul ciclurilor iterative, n metodele recursive trebuie s existe o condiie de oprire a repetrii. n caz contrar recursia ar continua pn la depirea spaiului de memorie alocat pentru memorarea datelor intermediare (numit stiv). Comparnd metodele recursive cu cele iterative se constat c: - metodele recursive sunt "mai elegante", fiind i mai uor de ineles de ctre om dect cele iterative; - din punct de vedere computaional, metodele iterative sunt mai eficiente, deoarece solicit mai puin memorie i sunt mai rapide dect cele recursive. Deosebirea este cu att mai mare, cu ct numrul de invocari succesive, respectiv de repetri, este mai mare. Exemplul 1: Un exemplu tipic de funcie recursiv este calcularea factorialului. Din punct de vedere matematic, factorialul este o funcie factorial(n) = 1*2*3*...*n care poate fi definit recursiv astfel: factorial(0)=1; factorial(n)=n*factorial(n-1) pentru n>0; Pentru n<0 funcia factorial nu este definit. Calcularea acestei funcii poate fi facut prin metoda urmtoare:
public static long factorial(int n) throws Exception { if(n<0) throw Exception("factorial(n): n<0"); if(n==0) return 1; return n*factorial(n-1); }

n corpul metodei se verific, mai nti dac argumentul n se ncadreaz n domeniul admis, iar n caz contrar se genereaz o excepie. Dac argumentul este valabil, se aplic formulele de calcul recursiv al factorialului date mai sus. Recursia se ncheie cnd se ajunge la n==0. Atunci cnd o metod invoca alta metod (fie ea recursiv sau nu), datele metodei care invoc, inclusiv adresa instruciunii care urmeaza celei care a fcut invocarea, sunt puse ntro structur de memorie numita stiv, dup care se transmit ctre metoda invocat argumentele i i se d acesteia controlul. Stiva (engleza: stack) este o structura de memorie n care ultima dat introdus este prima extras (n englez: LIFO - Last In First Out). La revenirea din metoda invocat se obine valoarea ntoars de aceasta i se extrag din stiv datele puse acolo nainte de invocare, continundu-se calculul. S urmarim acest proces n cazul invocrii metodei factorial(n) pentru n=4: factorial(4)=4*factorial(3); se pune 4 n stiv i se invoc factorial(3); stiva conine numrul 4; factorial(3)=3*factorial(2); se pune 3 n stiv i se invoc factorial(2); stiva conine numerele 3 4; factorial(2)=2*factorial(1); se pune 2 n stiv i se invoc factorial(1); stiva conine numerele 2 3 4; 151

Severin Bumbaru factorial(1)=1*factorial(0); se pune 1 n stiv i se invoc factorial(0); stiva conine numerele 1 2 3 4; factorial(0)=1; recursia s-a incheiat, deoarece funcia nu se mai invoc pe ea nsi. Se continu calculul fuciei factorial(1)care a invocat-o pe factorial(0). n acest scop se scoate din stiv 1 i se calculeaz factorial(1)=1*1=1; stiva conine 2 3 4. S-a ncheiat calculul lui factorial(1) i se revine n factorial(2)cu valoarea intoarsa 1; se continu factorial(2), extrgnd din stiv pe 2: factorial(2)=2*1=2; stiva conine 3 4; factorial(3)=3*2=6; stiva conine 4; factorial(4)=4*6=24; stiva este vid, deci calculul funciei recursive s-a incheiat, intorcndu-se valoarea 24. Se observa c, cu ct recursia este mai "profund" (funcia recursiv se invoc de mai multe ori pe sine nsi), cu att este necesar o stiv de capacitate mai mare. Daca recursia este prea "profund", este posibil ca stiva s nu aib capacitate suficient. n acest caz se obine eroarea de depire de stiv StackOverflowError (atenie: este o eroare, nu o excepie). Calcularea factorialului se poate face i iterativ, folosind urmtoarea funcie, n care factorialul se calculeaz printr-un ciclu for:
public static long factorial(int n) throws Exception { long fact; if(n<0) throw new Exception("factorial(n): n<0"); fact=1; for(int i=2; i<=n; i++) fact*=i; return fact; }

Ambele metode de calculare a factorialului sunt testate n aplicaia din fiierul TestRecursii.java. n acest fiier se declar dou clase: clasa Recursii, care conine metode statice recursive i mutual-recursive i clasa Iteraii, care conine metode iterative. n acelai fiier exist i clasa-aplicaie TestRecursii, care testeaz metodele din celelalte dou clase. Pentru a se compara metodele din punctul de vedere al timpului de calcul, n aplicaia TestRecursii s-a procedat astfel: nainte i dup invocarea fiecrei metode s-a determinat timpul sistemului n milisecunde, folosind metoda System.currentTimeMillis(), apoi s-a fcut diferena. Se constata astfel c timpul de calcul al factorialului pe cale recursiv este mai mare decat pe cale iterativ. Exemplul 2: Un alt exemplu tipic de funcie recursiv este funcia lui Fibonacci definit astfel: fibonacci(0)=0; fibonacci(1)=1; fibonacci(n)=fibonacci(n-1)+fibonacci(n-2) pentru n>1. n fiierul TestRecursii.java sunt declarate dou metode statice pentru funcia Fibonacci: una recursiva, n clasa Recursii, i alta iterativ, n clasa Iteratii. Cele dou metode sunt apoi testate i comparate n clasa TestRecursii. Se poate constata c, la valori mici ale

152

Programarea orientata pe obiecte n limbajul Java argumentului n, metoda recursiv este chiar mai rapid dect cea iterativ. n schimb, la valori mari ale lui n, timpul de calcul al metodei recursive crete foarte rapid, devenind sensibil mai mare dect al celei iterative. Exemplul 3: n clasa Recursii din fisierul TestRecursii.java sunt declarate i dou funcii mutualrecursive: fct1(n,x)=2*fct2(n, 0.4*x+0.3)+x pentru n>=0 fct2(0,y)=y fct2(n,y)=y*fct1(n-1, 1.27*y-0.89)-1 pentru n>0 Se observ c funcia fct1() invoc funcia fct2() i reciproc.

Metode care genereaz excepii


Instruciunea throw
Cunoatem deja c, la apariia anumitor anomalii n executarea programului, maina virtual Java genereaz excepii. Excepiile sunt obiecte din clasa Exception s-au dintr-o subclas a acesteia. Este posibil ca programatorul s prevad, n anumite puncte ale programului, generarea unor excepii, folosind n acest scop instruciunea throw, care are forma urmtoare:
throw new ConstructorExceptie(lista_argumente);

n limba englez, throw este imperativul de la "a arunca". n aceast instruciune, se folosete operatorul new pentru a genera un obiect al clasei de excepii creia i aparine constructorul invocat, dup care acest obiect este "aruncat", fie pentru a fi "prins" (captat) printr-o structura try .. catch i tratat prin program, fie pentru a fi preluat de maina virtual Java care, n acest caz, oprete execuia programului. Exemplu Instruciunea
if(a>1000) throw new Exception("Exceptie 102: a="+a);

"arunc" o excepie din clasa Exception, care contine un mesaj sub forma argumentului furnizat constructorului.

Clauza throws
n mod normal, excepiile generate ntr-o metod sunt tratate prin structuri try .. catch. chiar n metoda n care au fost generate. Este ns posibil ca metoda respectiv s "arunce" mai departe excepiile generate n corpul ei. Pentru a indica aceast proprietate, la declararea metodei, dup paranteza care conine lista declaraiilor argumentelor formale se pune clauza

153

Severin Bumbaru
throws ClasaDeExceptii,

n care se indic numele clasei excepiei care este "aruncat" ctre metoda invocatoare (Cuvantul throws este persoana a treia singular a verbului to throw, "a arunca"). Exemplu n programul din fiierul TestExceptie.java exist metoda static int factorial(int n), care calculeaz factorialul argumentului n. n aceast metod este folosit instruciunea throw de doua ori: pentru cazul n care argumentul este negativ i pentru cel n care argumentul este prea mare (rezultatul depete valoarea maxim pentru tipul int al valorii ntoarse). n ambele cazuri, n instruciunea throw se folosete constructorul clasei Exception, furnizndu-i ca argument un mesaj care arat ce eroare s-a produs. ntrucat aceste excepii nu sunt tratate n metoda factorial, n declaraia metodei factorial s-a folosit clauza throws. n metoda main se capteaz i se afieaz att aceste excepii, ct i excepia NumberFormatException generat de metoda int Integer.parseInt(String s) atunci cnd argumentul acesteia nu este forma extern a unui numr ntreg.

/* Testarea unei metode care genereaza exceptii. Lansarea in executie a aplicatiei se face prin comanda: java TestExceptie <numar_intreg> Daca <numar_intreg> este un numar intreg cuprins intre 0 si 12 se afiseaza factorialul acestui numar. Altfel, se afiseaza un mesaj de eroare */ class TestExceptie { /* O metoda in care se genereaza exceptii prin clauza throw */ static int factorial(int n) throws Exception { if(n<0) throw new Exception("factorial: argument negativ n="+n); if(n>12) throw new Exception("factorial: argument prea mare: "+n); int fact=1; for(int k=1; k<=n; k++) fact*=k; return fact; } /* In metoda main se capteaza si trateaza exceptiile generate de metodele factorial si parseInt */ public static void main(String args[]) { if(args.length==0) { System.out.println("Lipsa argument in linia de comanda"); System.exit(1); } try { int n=Integer.parseInt(args[0]); int m=factorial(n); System.out.println("Factorialul lui "+n+" este "+m); } catch(Exception e) { System.out.println(e); }

154

Programarea orientata pe obiecte n limbajul Java


} }

Clase publice
Clasele publice sunt clase care pot fi utilizate i n alte pachete, dect cel din care fac parte. Fiecare clas public se declar ntr-un fiier separat, care are obligatoriu acelai nume cu cel al clasei i extensia java. n declaraia de clas, n faa numelui clasei se pune modificatorul public. Dm n continuare ca exemplu clasa Complex.

155

Severin Bumbaru

Declararea clasei Complex


Clasa Complex este un exemplu de clas prin care se modeleaz conceptul matematic de numr complex. Dup cum este cunoscut, numrul complex a+b.ieste compus din dou numere reale a i b, numite respectiv partea real i partea imaginar. Simbolul i este numit unitatea imaginar i are proprietatea i2= -1. n fiierul Complex.java este dat un exemplu de declaraie a clasei Complex. Iat aceast declaraie:
/* Clasa numerelor complexe */ public class Complex { private double re; // partea reala private double im; // partea imaginara /* Constructori */ public Complex() { re=0; im=0; } public Complex(double parteaReala) { re=parteaReala; im=0; } public Complex(double parteaReala, double parteaImaginara) { re=parteaReala; im=parteaImaginara; } public Complex(Complex z) { re=z.re; im=z.im; } /* Metode */ public double real() { // intoarce partea reala return re; } public double imag() { // intoarce partea imaginara return im; } public double modul() { // intoarce modulul numarului complex return Math.sqrt(re*re+im*im); } public double arg() { // intoarce argumentul numarului complex return Math.atan2(im,re); } public static Complex complex(double modul, double argument) throws Exception { if(modul<0) throw new Exception("Complex: modul negativ: "+modul); Complex z=new Complex();

156

Programarea orientata pe obiecte n limbajul Java

z.re=modul*Math.cos(argument); z.im=modul*Math.sin(argument); return z; } public Complex plus(Complex a) { Complex z=new Complex(); z.re=re+a.re; z.im=im+a.im; return z; } public Complex plus(double d) { return new Complex(re+d, im); } public static Complex plus(double d, Complex z) { return new Complex(d+z.re, z.im); } public Complex minus(Complex a) { Complex z=new Complex(); z.re=re-a.re; z.im=im-a.im; return z; } public Complex minus(double d) { return new Complex(re-d, im); } public static Complex minus(double d, Complex z) { return new Complex(d-z.re, -z.im); }

public Complex inmultitCu(Complex a) { Complex z=new Complex(); z.re=re*a.re-im*a.im; z.im=re*a.im+im*a.re; return z; } public Complex inmultitCu(double d) { return new Complex(re*d, im*d); } public static Complex inmultitCu(double d, Complex z) { return new Complex(d*z.re, d*z.im); } public Complex impartitLa(Complex a) throws Exception { Complex z=new Complex(); double w=a.re*a.re+a.im*a.im; // patratul modulului numitorului if(w==0) throw new Exception("Complex impartitLa: impartire la zero");

157

Severin Bumbaru

z.re=(re*a.re+im*a.im)/w; z.im=(im*a.re-re*a.im)/w; return z; } public Complex impartitLa(double d) throws Exception { if(d==0) throw new Exception("Complex impartitLa: impartire la zero"); return new Complex(re/d, im/d); } public static Complex impartitLa(double d, Complex z) throws Exception { double w=z.re*z.re+z.im*z.im; if(w==0) throw new Exception("Complex impartitLa: impartire la zero"); return new Complex(d*z.re/w, -d*z.im/w); } public String toString() { StringBuffer b=new StringBuffer("("+re); if(im>=0) b.append('+'); b.append(im+"*i)"); return b.toString(); } public boolean equals(Object obj) { if(this==obj) return true; if(getClass()!=obj.getClass()) return false; if(re==(((Complex)obj).re)&&(im==(((Complex)obj).im))) return true; return false; } public int hashCode() { return (int)(100000*modul()+100*arg()); } }

Declaraia clasei incepe prin public class Complex, deci este o clasa public. Clasa conine dou cmpuri de tip double, reprezentnd respectiv partea real i partea imaginar a numrului complex. S-au prevzut mai muli constructori. Primul dintre acetia nu are argumente i creeaz un numr complex la care, att partea real, ct i cea imaginar sunt nule. Avnd n vedere c s-a declarat un constructor cu dou argumente de tip double, reprezentnd partea real i cea imaginar a numrului complex nou creat, nu a mai fost posibil s se creeze nc un constructor, care s aib ca argumente modulul i argumentul noului numr complex (acestea fiind tot numere reale). Din aceast cauz, el a fost nlocuit prin metoda static
public static Complex complex(double modul double argument)

al crei nume ncepe cu liter mic. Au fost redefinite metodele toString, equals i hashCode ale superclasei Object, pentru a ine seama de specificul clasei Complex. Au fost declarate, de asemenea, metode pentru

158

Programarea orientata pe obiecte n limbajul Java efectuarea de calcule ntre dou numere complexe, ntre un numr complex i unul real i intre unul real i unul complex. Ultimele au fost declarate ca metode statice, deoarece operandul din stnga nu aparine clasei complex. n toate metodele, n care pot s apar situaii anormale, s-a prevazut generarea de excepii.

Utilizarea clasei complex


Testarea diferitelor situaii de utilizare a clasei complex este exemplificat n fiierul TestComplex.java.

Colectorul de reziduuri
Dac un obiect nu mai este necesar, el poate fi distrus, adic eliminat din memorie. n maina virtual Java, exist un colector de reziduuri de memorie (englez: garbage collector) care elibereaz automat spaiul de memorie ocupat de obiectele ctre care nu mai exist nici o referin. n consecin, programatorul nu mai este pus n situaia s prevad explicit n program distrugerea obiectelor i, deci clasele nu mai conin destructori, ca n alte limbaje de POO. n programul din fiierul Referinte.java se d un exemplu de situaie n care unele obiecte rmn fr referine. Dac, dup ce s-a ajuns n situaia din Figura 2, se execut instruciunile:
e=b; a="Sir nou"; c=new String(a);

se ajunge n situaia din Figura 3.

- Figura 3 S-au fcut, fa de situaia din Figura 2, urmtoarele transformri: - referinei e i s-a atribuit aceeai valoare ca referinei b; - s-a construit un obiect cu coninutul "ir nou", iar variabila aa primit ca valoare referina la acest obiect; - s-a construit un obiect cu acelai continut ca cel indicat de a, iar variabila c indic acum

159

Severin Bumbaru acest nou obiect. n consecin, dou din obiectele "un ir" construite initial au rmas fr referine. Nu mai exist nici o cale n program de a folosi aceste obiecte, deci ele trebuie s fie eliminate. Acest rol este ndeplinit de colectorul de reziduuri. Programatorul nu are ns posibilitatea de a decide n ce moment se va produce eliminarea efectiv a acestor obiecte, decizia aparinand numai colectorului de reziduuri.

Metoda finalize
n clasa Object exista metoda
protected void finalize() throws Throwable

Aceasta metod este invocat de colectorul de reziduuri, atunci cnd acesta determin c nu mai exist referine ctre obiectul respectiv. n clasa Object, aceast metod nu efectueaz nimic. Metoda finalize poate fi redefinit n orice alt clas, pentru a elibera resurse sau a efectua orice alte aciuni necesare nainte de distrugerea obiectului respectiv. De exemplu, dac obiectul respectiv a deschis anumite fiiere sau conexiuni externe, n metoda finalize se poate efectua nchiderea lor. Metoda finalize nu este apelat explicit n programul de aplicaie. Apelarea metodei finalize se face numai de ctre colectorul de reziduuri (garbage collector), dar nu imdeiat ce un obiect a rmas fr referin, ci abia atinci cnd acest obiect a "intrat n atenia" colectorului. Este posibil ca executarea aplicaiei s se incheie nainte ca "finalizarea" unor obiecte s aib loc. Exemplu n aplicaia din fiierul Finalizari.java este declarat clasa ProbaFinaliz, n care este redefinit metoda finalize() din clasa Object. n clasa Finalizari din acelai fisier se construiesc dou obiecte din clasa ProbaFinaliz, dup care se elimin referinele ctre aceste obiecte. Avnd n vedere c imediat dup aceea se ncheie executarea aplicaiei, cel mai probabil este c nu va avea loc invocarea de ctre colectorul de reziduuri a metodei finalize().

ntrebri
Nivel 1
1. 2. 3. 4. Care este cea mai simpl form a unei declaraii de clas? Ce sunt membrii unei clase? Ce este numele clasei din punct de vedere sintactic? Cu ce ncepe numele unei clase?

160

Programarea orientata pe obiecte n limbajul Java 5. Ce conine corpul clasei? 6. Ce asemnare este ntre cmpuri i variabilele locale? 7. Ce deosebire este ntre cmpuri i variabille locale? 8. Ce sunt cmpurile statice i prin ce se deosebesc de cele nestatice? 9. Pot exista clase care nu conin metode? 10. Care este cea mai simpl form a unei declaraii de metod? 11. Ce este numele metodei din punct de vedere sintactic? 12. Ce este corpul metodei i ce conine el? 13. Cum se declar argumentele metodei? 14. Cum se declar tipul valorii ntoarse? 15. Ce form i ce semnificaie are instruciunea return? 16. Ce este o metod static? 17. Ce restricii trebuie respectate la declararea unei metode statice? 18. Ce este signatura metodei? 19. Pot exista n aceeai clas mai multe metode cu acelai nume? 20. Cum se face transferul argumentelor (parametrilor) de la metoda invocatoare la cea invocat? 21. Cum pot fi generate excepii n corpul unei metode? 22. Ce form are instruciunea throw i la ce servete? 23. La ce serveste clauza throws? 24. Ce deosebire este ntre throw i throws? 25. Ce sunt clasele publice? 26. Cum se declara o clas public? 27. Ce este colectorul de reziduuri?

Nivel 2
Care sunt valorile iniiale implicite ale cmpurilor? Ce deosebire este ntre iniializarea cmpurilor i iniializarea variabilelor locale? Ce deosebire este intre o funcie i o procedur? Prin ce se deosebete o metod prin care se realizeaz o procedur de una care realizeaz o funcie? 5. n ce mod se invoc, n mod normal, o metod prin care se realizeaz o funcie propriu-zis (a carei valoare ntoars nu este void)? 6. n ce mod poate fi invocata o metoda care ntoarce void? 7. Exist n limbajul Java variabile globale? 8. Ce deosebire este ntre parametrii formali ai unei metode i cei efectivi? 9. Ce se ntmpl dac n corpul unei metode se modific valoarea unui argument formal? 10. Ce se ntmpl dac n corpul unei metode se modific coninutul unui obiect referit de ctre un parametru formal al metodei respective? 11. Ce se ntmpl dac n corpul unei metode se modific valoarea unui parametru formal de tip referin (n sensul c i se d ca valoare o referin la alt obiect)? 12. n ce situaie, la revenirea dintr-o metod, poate s aib loc un efect lateral? 13. Este posibil ca o metod s ntoarc o referin la un obiect construit n corpul acesteia? 14. Ce se ntmpl dac, n corpul unei metode care are ca argument formal un tablou, se modific elementele acestui tablou? 15. Ce se ntmpl dac, n corpul unei metode care are ca argument formal un tablou, i se 1. 2. 3. 4.

161

Severin Bumbaru d acestui argument ca valoare o referina la alt tablou? 16. Poate o metod s ntoarc drept valoare o referin la un tablou creat n interiorul ei? 17. Ce este o metod recursiv? 18. Ce deosebiri exist ntre iteraie i recursie? 19. n ce scop se redefinete ntr-o clas metoda toString() a clasei Object? 20. n ce scop se redefinete ntr-o clas metoda equals(Object ob) a clasei Object? 21. Poate fi declarat o metod care creeaz un obiect nou al clasei creia i apartine metoda respectiv? Prin ce se deosebete ea de un constructor? 22. Ce este metoda finalize()? 23. n ce scop este redefinit metoda finalize()? 24. n ce situaii este invocat metoda finalize()?

162

Programarea orientata pe obiecte n limbajul Java

Caracteristicile obiectelor i claselor i reflectarea lor n declararea claselor. Interfee. Clase imbricate
Caracteristici ale obiectelor i claselor i reflectarea lor n declararea claselor: ncapsularea; cmpuri i metode publice i private; Modificatori de acces pentru cmpuri i metode; Declararea constructorilor; Agregarea; Motenirea; Membrii protejati ai clasei; Referinele this i super; Declararea clasei derivate; clauza extends; Declararea constructorului clasei derivate; Redefinirea metodelor; Ascunderea (acoperirea) cmpurilor; Ascunderea metodelor statice; Metode finale; Declararea propriilor clase de excepii; Clase finale; Polimorfismul; Un exemplu: clasa Persoana i subclasa Student; Declararea clasei Persoana; Declararea clasei Student; Utilizarea celor dou clase; Instanierea clasei care conine metoda main; Clase abstracte; Interfee; Clase imbricate i clase interioare ntrebri 163 166 167 167 170 171 171 171 171 172 172 175 175 177 177 177 177 180 180 181 183 184 186 186 190 195

Caracteristicile obiectelor i claselor


n majoritatea surselor bibliografice asupra POO, se consider drept principale caracteristici ale obiectelor ncapsularea, motenirea ipolimorfismul. La acestea se mai pot adaug i alte caracteristici importante, cum sunt identitatea, agregarea i clasificarea. Identitatea (englez: Identity) se refer la faptul c datele sunt grupate n entiti discrete, numite obiecte. Fiecare obiect din POO modeleaz starea i comportamentul unui anumit

163

Severin Bumbaru obiect din lumea real, care poate fi un obiect fizic (de exemplu automobil, calculator, furnal, om, animal etc.) sau unul conceptual (de exemplu figur geometric, orar etc.). Fiecare obiect are propria lui identitate, astfel c dou obiecte sunt considerate distincte, chiar daca atributele lor (cum ar fi numele, culoarea etc.), sunt identice. Pentru a face aceasta distincie, obiectul este indicat printr-o referin unic. Modul n care este reprezentata aceast referin poate sa difere n diverse limbaje de programare (de ex. adres de memorie, nume etc.), important ns este c fiecare obiect are o singur referin i nu exist dou obiecte distincte cu aceeai referin. ncapsularea (englez: encapsulation) este proprietatea obiectelor de a-i ascunde o parte din date i metode. Din exteriorul obiectului sunt accesibile ("vizibile") numai datele i metodele publice. Putem deci sa ne imaginm obiectul ca fiind format din dou straturi, ca n Figura 1.

- Figura 1 Obiectul se comport ca i cnd ar avea doua "nveliuri": unul "transparent", care permite accesul la datele i metodele publice ale obiectului, i un al doilea inveli "opac", care cuprinde datele i metodele invizibile (inaccesibile) din exterior. Starea obiectului depinde att de datele publice, ct i de cele ncapsulate. Metodele publice ale obiectului au acces la datele i metodele ncapsulate (ascunse) ale acestuia. In consecin, starea obiectului poate fi modificata att prin modificarea direct, din exterior, a valorilor variabilelor publice, fie prin utilizarea unor metode publice care modifica valorile variabilelor ncapsulate. n mod similar, valorile variabilelor ncapsulate pot fi obinute numai utilizand metode publice ale obiectului respectiv. ncapsularea obiectelor prezint avantaje importante n programare, deoarece mrete sigurana i fiabilitatea programelor, prin eliminarea posibilitii modificrii accidentale a valorilor acestora, ca urmare a accesului neautorizat din exterior. Din aceast cauz, programatorii evit n general s prevad ntr-un obiect date publice, preferand ca accesul la date s se fac numai prin metode. Partea vizibil (public) a obiectului constituie interfaa acestuia cu "lumea exterioar". Este posibil ca dou obiecte diferite s aib interfee identice, adic s prezinte n exterior aceleai date i metode. Datorit faptului c partea ncapsulat difer, astfel de obiecte pot avea comportament diferit. Agregarea (englez: aggregation) este proprietatea obiectelor de a putea ncorpora alte obiecte. Aa dar, "datele" coninute ntr-un obiect pot fi nu numai date primitive, ci i obiecte. Se pot astfel crea obiecte cu structuri din ce n ce mai complexe.

164

Programarea orientata pe obiecte n limbajul Java Clasificarea (englez: classification) este proprietatea obiectelor care au aceeai structur de date i acelai comportament (aceleai metode) de a putea fi grupate ntr-o clas. Clasa este o abstractizare, care conine acele proprieti ale obiectelor, care sunt importante ntr-o aplicaie sau ntr-o categorie de aplicaii, i le ignor pe celelalte. De exemplu, n aplicaii privind situaia profesional a studenilor, clasa Student conine astfel de atribute ca numele i prenumele studentului, facultatea, anul de studii, examenele promovate i notele obinute, dar ignor atribute ca nlimea, culoarea ochilor sau a prului, greutatea etc., care nu sunt necesare n aplicaia respectiv. Spre deosebire de agregare, care este o relaie ntre obiecte, clasificarea este o relaie ntre concepte reprezentate prin clase. n functie de nivelul de abstractizare, clasele pot forma o structura ierarhic. De exemplu, clasa mijloacelor de transport cuprinde subclasele mijloacelor de transport terestre, navale i aeriene. Clasa mijloacelor de transport terestre le cuprinde pe cele rutiere i feroviare. Clasa mijloacelor de transport rutiere cuprinde clasele automobilelor i autocamioanelor etc. Fiecare subclas a unei clase este ea nsi o clas. O astfel de ierarhie de clase este reprezentat n Figura 2.

- Figura 2 Cu cat o clas se afla n aceast ierarhie pe un nivel mai nalt, cu att ea este mai abstract, deci descrie un numr mai mic de atribute ale obiectelor care i aparin. Clasa A este rdcina acestei ierarhii, fiind situat pe cel mai nalt nivel de abstractizare. Clasele B, C i D sunt subclase ale lui A, iar clasele E si F sunt subclase ale clasei B. n acelai timp, clasa Aestesuperclas a clasei B, iar aceasta este superclas a clasei F. n programarea orientat pe obiecte se spune, de asemenea, c clasa B este derivat din clasa A, iar clasa F este derivat din clasa B sau, n general, o subclas este derivat din superclasa sa. Un obiect care aparine unei clase se numete i instan a clasei (este o instaniere, o realizare particulara a clasei respective). De exemplu, clasa Barbat i clasa Femeie sunt subclase ale clasei Om. n schimb, Ion_Popescu este o instana clasei Barbat (un obiect care aparine acestei clase), iar Maria_Preda este o instan a clasei Femeie. n principiu, o clas poate avea o infinitate de instane. Practic, desigur, numrul lor este finit. Toate instanele unei clase au aceleai atribute (aceleai "cmpuri"), dar valorile acestora pot s difere de la o instan la alta.

165

Severin Bumbaru Motenirea (englez: inheritance) este proprietatea unei clase de a conine toate atributele (cmpurile) i metodele superclasei sale. n consecin, trecerea de la clas la subclas se face prin adugarea de atribute i/sau de metode. De exemplu, clasa Barbat i clasa Femeie au ambele toate atributele clasei Om, dar fiecare din acestea are i atribute specifice. n general, n programarea orientat pe obiecte, motentirea poate fi simpl sau multipl. n cazul motenirii simple fiecare clas are cel mult o superclas, ca n Figura 2. n cazul motenirii multiple o clas poate avea mai multe superclase, ca n Figura 3.

- Figura 3 n aceast figur se observ c clasa D motenete clasele A i B, iar clasa H motenete clasele D, E siF. Aceasta corespunde situaiei din lumea real n care, de exemplu, un student_sportiveste n acelai timp i student, i sportiv, deci deine atributele ambelor clase. Dei exist limbaje de programare, ca limbajul C++, care admit motenirea multipl, aceasta creeaz unele dificulti. Astfel, n exemplul din Figura 3, metodele i datele clasei B sunt motenite de clasa H pe dou ci: pe traseul BDH i pe traseul BEH. Pentru a se evita astfel de situaii, n limbajul Java se admite numai motenirea simpl. Lipsa motenirii multiple este compensat n limbajul Java prin introducerea conceptului de interfa care va fi prezentat ulterior. Polimorfismul (englez: polymorphism) permite ca aceeai operaie s se realizeze n mod diferit n clase diferite. S considerm, de exemplu, c n clasa Figura_geometrica exist metoda arie(), care calculeaza aria figurii respective. Clasele Cerc, Triunghi, Patrat sunt subclase ale clasei Figura_geometrica si vor moteni, deci, de la aceasta metoda arie(). Este ns evident c aria cercului se calculeaz n alt mod dect aria patratului sau cea a triunghiului. Pentru fiecare din instanele acestor clase, la calcularea ariei se va aplica metoda specific clasei respective.

ncapsularea
ncapsularea este una din proprietile fundamentale ale claselor n programarea orientat pe obiecte. Cmpurile, constructorii i metodele dintr-o clas pot fi ncapsulate, astfel nct s nu fie vizibile din exteriorul clasei sau instanei n care se afl. Aceasta se realizeaz folosind la declararea cmpului, constructorului sau metodei respective modificatorul private.

166

Programarea orientata pe obiecte n limbajul Java De exemplu, prin declaraia de cmpuri


private double a, b, c;

se creeaz cmpurile private a, b, c care nu sunt vizibile din exteriorul instanei n care se afla. n mod similar, prin declaraia de metod
private int ex1(int k) { return 2*k+1); }

se declar metoda privat ex1. Cmpurile i metodele declarate astfel se numesc private. n opoziie cu acestea, sunt cmpurile i metodele publice, care sunt declarate folosind modificatorul public i sunt vizibile din orice alt clas.

Modificatori de acces pentru cmpuri i metode


n limbajul Java exist trei modificatori de acces pentru cmpuri i metode: - private - pentru a specifica cmpuri sau metode private; - public - pentru a specifica cmpuri sau metode publice; - protected - pentru a specifica cmpuri sau metode protejate (care vor fi prezentate n seciunea despre motenire). Membrii privati ai claselor (cmpuri sau metode) sunt accesibili numai din clasa respectiv. Membrii publici sunt accesibili din orice clas. Membrii protejati sunt accesibili numai din clasa n care se afl sau din subclasele acesteia. Dac la declararea cmpurilor sau metodelor nu se folosesc modificatori de acces, acestea sunt considerate vizibile numai din clasele care sunt situate n acelai pachet cu clasa creia i aparin. n particular, pentru clasele declarate de ctre noi, aceste cmpuri i metode sunt vizibile numai din clasele situate pe disc n acelai director. Se spune, n astfel de cazuri, c modul de acces este prietenos (englez: friendly) sau de pachet (englez: package).

Declararea constructorilor
Constructorii sunt utilizati impreuna cu operatorul new pentru a creea instane ale claselor. Constructorii pot fi implicii sau explicii. Constructorii, ca i metodele, sunt niste subprograme. Fa de metode, constructorii prezint urmtoarele trsturi specifice: - numele constructorului este ntotdeauna acelai cu al clasei creia i aparine; - constructorul nu ntoarce o valoare. n consecin, la declararea constructorului nu se specific tipul valorii ntoarse, ca la metode; - constructorii nu pot fi statici; - invocarea constructorilor se face numai prin operatorul new. Ca i n cazul metodelor, o clas poate avea mai multi constructori, care sa difere ntre ei prin signatur.

Constructorul implicit
Dac ntr-o clas nu este declarat explicit nici un constructor, ea are un constructor implicit. Acest constructor nu are argumente, iar efectul lui const n iniializarea tuturor cmpurilor instanei care se creeaz cu valorile implicite corespunztoare tipurilor cmpurilor respective.

167

Severin Bumbaru ATENIE: dac clasa are unul sau mai multi constructori declarai explicit, ea nu mai are constructor implicit. Exemplu: n aplicaia Cercuri din fiierul Cercuri.java, la crearea instanelor clasei Cerc1 s-a folosit constructorul implicit al acestei clase.

Constructori explicii
Declararea constructorului se face sub forma
modificator_acces nume_clasa(declaratii_de_argumente) { corpul_constructorului }

Se observ imediat c declararea constructorului se face la fel cu a unei metode, cu deosebirea c lipsete tipul valorii ntoarse, iar numele constructorului este cel al clasei. Modificatorul de acces al constructorului este, cel mai frecvent, public. El poate, totui, sa lipseasc dac se consider c instanierea clasei se va face numai n metode ale claselor din acelai pachet. n corpul constructorului pot fi programate orice fel de aciuni care trebuie executate imediat dup ce se aloc n memorie spaiu pentru o instan a clasei respective. Cel mai frecvent, n corpul constructorilor se iniializeaz valorile cmpurilor instanei nou create.

Exemplu n fiierul Cercuri1.java este declarat clasa Cerc n modul urmtor:

class Cerc { public static final double PI=3.141592653589793; private double r; public Cerc(double raza) { r=raza; } public double raza() { return r; } public double arie() { return PI*r*r; } public double circumferinta() { return 2*PI*r; } public static double arie(double r) { return PI*r*r; } public static double circumferinta(double r) { return 2*PI*r;

168

Programarea orientata pe obiecte n limbajul Java

} }

Clasa Cerc are att metodele de instan, ct i metodele statice pentru calcularea ariei i circumferinei, care existau n clasele Cerc1 i Cerc2 din exemplul dat n fiierul Cercuri.java. n plus, remarcm urmtoarele: - cmpul r1 (raza cercului) a fost declarat privat, deci el nu este accesibil din exteriorul clasei; - s-a declarat un constructor care, la crearea unui obiect din clasa Cerc, iniializeaz cmpul r1. ntruct clasa Cerc nu conine nici o metod prin care s se modifice valoarea acestui cmp, raza cercului nu mai poate fi modificat dup ce acesta a fost creat, aa cum era posibil n cazul instanelor clasei Cerc1. n acelai fiier surs, este declarata i clasa Cercuri1, n care se utilizeaza clasa Cerc. Aplicaia menionat este declarat astfel:

/* Aplicatia in care se utilizeaza cele doua clase de cercuri declarate mai sus */ class Cercuri1 { public static void main(String args[]) { double r1=1, r2=7.32; /* Instantierea a doua cercuri */ Cerc c1=new Cerc(r1), c2=new Cerc(r2); /* Utilizarea metodelor de instanta */ System.out.println("Utilizand metodele de instanta:"); System.out.println("Pentru cercul c1:\n aria="+c1.arie()+ " circumferinta="+c1.circumferinta()+" raza="+c1.raza()); System.out.println("Pentru cercul c2:\n aria="+c2.arie()+ " circumferinta="+c2.circumferinta()+" raza="+c2.raza()); /* Utilizarea metodelor statice */ System.out.println("Folosind metodele statice ale clasei Cerc:"); System.out.println("Pentru raza r1: aria="+Cerc.arie(r1)+ " circumferinta="+Cerc2.circumferinta(r1)); System.out.println("Pentru raza r2: aria="+Cerc.arie(r2)+ " circumferinta="+Cerc2.circumferinta(r2)); System.out.println("Pentru raza r=9.23 aria="+Cerc.arie(9.23)+ " circumferinta="+Cerc.circumferinta(9.23)); /* Acelasi calcul, facut calificand numele metodelor statice prin referinte la instante ale clasei Cerc */ System.out.println("Aria cercului cu raza 9.23: "+ c1.arie(9.23)+" "+c2.arie(9.23)); } }

Se observ c iniializarea celor dou cercuri (instane ale clasei Cerc) c1 i c2 s-a fcut folosind constructorul Cerc(double raza). Dup ce a fost construit cercul, raza lui nu mai poate fi modificat. Calculara ariei cercului c1 se face invocnd metoda c1.arie(), care aparine instanei c1. n acest caz, metoda nu are argumente, deoarece se va folsi raza cercului c1. Aria unui cerc oarecare poate fi calculat ns i invocnd metoda staticCerc.arie(raza),

169

Severin Bumbaru

creia ns i se d ca argument raza cercului. Chiar dac aceast metod static este invocat prin intermediul referinei la o instan sub forma c1.arie(raza), nu se va folosi n calcul raza instanei c1, ci raza primit ca argument. Compilatorul face distincie intre metodele arie() i arie(double raza) ntruct au semnturi diferite.

Agregarea
Agregarea este o caracteristic fundamental a programrii orientate pe obiecte, conform creia un obiect poate conine alte obiecte. n limbajul Java, la declararea claselor, este permis ca att cmpurile clasei, ct i ale instanei s aib ca valori obiecte din alte clase. Se poate porni astfel de la clase simple, care au drept cmpuri date din tipuri primitive, i construi pas cu pas clase cu structuri din ce in ce mai complicate, realizate prin agregarea claselor cu structuri mai simple. Un exemplu de agregare este clasa Pers din fisierul Pers.java, pe care l reproducem aici.

class Pers { private String numePers, prenumePers; private int anNasterePers; Pers(String nume, String prenume, int anNastere) { numePers=nume; prenumePers=prenume; anNasterePers=anNastere; } String nume() { return numePers; } String prenume() { return prenumePers; } int anNastere() { return anNasterePers; } }

Instanele clasei Pers conin datele unei persoane. Se observ c obiectele din clasa Pers conin cmpurile nume i prenume, care sunt referine la obiecte ale clasei String. Remarcm de asemenea c, ntruct cmpurile de date sunt private, iniializarea lor se face folosind un constructor. Dup crearea obiectului, aceste cmpuri nu mai pot fi modificate. Testarea clasei Pers se face n aplicaia din fiierul TestPers.java.

Motenirea
Conceptul de motenire

170

Programarea orientata pe obiecte n limbajul Java Motenirea este o trstur fundamental a programrii orientate pe obiecte, conform creia: - dintr-o clas se pot deriva alte clase. Dac din clasa A este derivat clasa B, atunci A se numete clas de baz, sau superclas, iar B se numete clas derivat, sau subclas; - subclasa mosteneste cmpurile i metodele superclasei; - metodele superclasei pot fi redefinite n subclas prin alte metode cu aceeai signatur; - metodele statice ale superclasei pot fi ascunse n subclas; - cmpurile superclasei pot fi ascunse n subclas prin cmpuri cu acelai nume dar care pot avea, eventual, alt tip. - cmpurile unei clase pot fi ascunse chiar i n metodele clasei respective, dac aceste metode au argumente sau variabile locale cu acelai nume.

Membrii protejai ai clasei


Exist trei moduri de acces la membrii claselor (att la cmpuri, ct i la metode): public, privat si protejat. Pn n prezent am folosit numai modificatorii de acces public i private, deoarece nu am declarat clase derivate. Introducem acum i modificatorul de acces protected. Cmpurile sau metodele declarate cu acest modificator de acces sunt vizibile (accesibile) n propria clas i n clasele derivate din aceasta. Iat, deci, care sunt cei trei modificatori de acces la membrii unei clase folositi n declaraiile de clase: - public - pentru cmpuri i metode care sunt accesibile din orice clas (inclusiv din clase aparinnd altor pachete); - protected - pentru cmpuri i metode care sunt accesibile n propria clas i n subclasele acesteia, dar nu sunt vizibile din alte clase; - private - pentru cmpurile i metodele care sunt accesibile numai din propria clas. Acestea nu sunt accesibile din nici o alta clas (nici chiar din subclasele propriei lor clase). Amintim c, n lipsa modificatorului de acces, cmpurile i metodele respective sunt accesibile din clasele aceluiai pachet. Acest mod de acces este cunoscut sub numele de prietenos (englez: friendly) sau de pachet (englez: package).

Referinele this i super


n orice clas pot fi utilizate dou referine predefinite: this - este o referin la "aceast" instan, adic la instana (obiectul) din care se face referina respectiv; super - este o referin la superclas.

Declararea clasei derivate. Clauza extends


n declaraia clasei derivate (subclasei), numele clasei care se declar este urmat de clauza extends, n care se indic numele superclasei. n consecin, clasa derivat poate fi declarat astfel:
class NumeClasa extends NumeSuperclasa { declaratii_de_membri }

171

Severin Bumbaru Amintim c n limbajul Java orice clas are o superclas i numai una. Excepie face clasa Object, care este rdcina ierarhiei de clase. Daca lipsete clauza extends, superclasa implicit este Object.

Declararea constructorului clasei derivate


Pentru a se da valori iniiale cmpurilor superclasei, n declaraia constructorului subclasei poate fi invocat constructorul superclasei prin instruciunea
super(lista_parametri_efectivi);

unde lista parametrilor efectivi este cea a constructorului superclasei. Aceasta instruciune, dac exist, trebuie s fie prima instruciune din corpul constructorului clasei derivate. n lipsa ei, va fi invocat constructorul fr parametri al superclasei. Este posibil, de asemenea, ca ntr-un constructor s se invoce alt constructor al aceleeai clase, sub forma
this(lista_parametri_efectivi);

Redefinirea metodelor
Metodele de instan (nestatice) ale unei clase pot fi redefinite n subclasele acesteia. Redefinirea unei metode se face declarnd n subclas o metod avnd aceeai signatur cu una din superclas. Atunci cnd se redefinete o metoda protejat, modificatorul de acces al acesteia poate fi meninut, sau poate fi transformat n public. n subclas pot fi folosite, totui, i metodele superclasei care au fost redefinite, dac la invocarea acestor metode se foloseste referina super.

Exemplu: n fiierul S1.java este declarata clasa S1, iar in fiierul CD1.java este declarata clasa CD1, care extinde clasa S1 (este, deci, derivat din aceasta). Reproducem aici declaraiile celor dou clase:
/* Clasa S1 din care vor fi derivate alte clase */ public class S1 { public int a; protected double b; private int c; public final static int alpha=12; public S1(int a, double b, int c) { // constructorul clasei S1 this.a=a; this.b=b; this.c=c; } private double f1() { // o metoda privata return a*c+b; }

172

Programarea orientata pe obiecte n limbajul Java

protected int f2() { // o metoda protejata return a+2*c; } public double f3() { // o metoda publica in care se folosesc f1 si f2 return 2*f1()+f2(); } public String toString() { // redefinirea metodei Object.toString() return "(S1: "+a+" "+b+" "+c+")"; } public static int f4(int k) { return 2*k+alpha; } } /* O clasa derivata din S1, in care se redefinesc unele metode */ class CD1 extends S1 { public CD1(int a, double b, int c) { super(a,b,c); } public int f2() { // redefinirea metodei f2() din superclasa return 2*a; } public double f3() { // redefinirea metodei f3() din superclasa return f2()+super.f3(); } }

Remarcm urmtoarele: - n metodele clasei S1 pot fi folosite toate cmpurile declarate n aceast clas, fie ele publice, protejate sau private; de asemenea, pot fi invocate toate metodele din aceast clas; - n clasa S1 a fost redefinit metoda toString din clasa Object, astfel inct s se ntoarca un ir care conine valorile cmpurilor a, b i c; - metoda static f4() din clasa S1 utilizeaz numai cmpul static alpha al acestei clase; - n constructorul clasei CD1 a fost invocat constructorul clasei S1 sub forma super(a,b,c). n acest mod au fost iniializate toate cmpurile din superclasa S1, inclusiv cmpul privat c, care nu este direct accesibil din clasa CD1; - n clasa CD1 au fost redefinite metodele f2 i f3 din superclasa S1 i a fost iari redefinit metoda toString; - n mod normal, n clasa CD1 se folosesc metodele f2 i f3 redefinite n aceast clas. Este totui posibil ca n clasa CD1 s se apeleze metodele superclasei, dac n expresia de invocare se folosete referinta super. Astfel, n metoda f3 din clasa CD1 exist expresia super.f3(), prin care se invoca metoda f3 din superclasa S1; - la redefinirea metodei f2, modul de acces a fost modificat din protected in public; - n metodele clasei CD1 nu au putut fi folosite cmpurile i metodele private ale superclasei S1. Testarea claselor S1 si CD1 se face n clasa TestCD1, care se gsete n fiierul TestD1.java. Iat aceasta clas:

173

Severin Bumbaru

/* Testarea claselor S1 si CD1 */ class TestCD1 { public static void main(String args[]) { S1 s=new S1(1, 1.1, 2); CD1 cd=new CD1(10, 10.2, 20); System.out.println("s="+s+" cd="+cd); System.out.println("s.f2()="+s.f2()+" s.f3()="+s.f3()); System.out.println("cd.f2()="+cd.f2()+" cd.f3()="+cd.f3()); System.out.println("CD2.f4(3)="+CD2.f4(3)+" S1.f4(3)="+S1.f4(3)); System.out.println("cd.f4(3)="+cd.f4(3)+" s.f4(3)="+s.f4(3)); } }

Executnd aplicaia TestCD1 se obin urmatoarele rezultate:

s=(S1: 1 1.1 2) cd=(S1: 10 10.2 20) s.f2()=5 s.f3()=11.2 cd.f2()=20 cd.f3()=460.4 CD2.f4(3)=18 cd.f4(3)=18

Remarcm c: - crearea instanelor claselor S1 i CD1 s-a fcut aplicnd operatorul new asupra constructorilor claselor respective; - n instruciunea
System.out.println("s="+s+" cd="+cd);

este de dou ori invocat implicit metoda toString, pentru a converti n iruri afiabile obiectele s i cd; prima dat este invocat metoda s.toString() din clasa S1. A doua oar ar trebui sa fie invocat metoda cd.toString() din clasa CD1 dar, intruct metoda nu a fost redefinit n aceasta clas, a fost aplicat efectiv metoda toString() din superclasa S1; - n expresiile s.f2() si s.f3() sunt invocate metodele din clasa S1, careia i aparine s, iar in expresiile cd.f2() i cd.f3() sunt invocate metodele corespunztoare din clasa CD1; - metoda static f4() din clasa S1 a fost invocat n patru moduri: calificnd numele metodei f1 cu numele clasei S1 (creia i aparine de fapt aceast metod), cu numele subclasei CD1 (care motenete aceast metod) i cu numele instanelor s i cd ale acestor clase. Cum era de ateptat, n toate cele patru cazuri s-a obinut acelai rezultat. Puteti compila cele trei fiiere menionate i pune n executie aplicaia TestCD1 pentru a verifica respectarea afirmaiilor de mai sus. Putei, de asemenea, face modificri n metodele celor trei clase menionate, astfel nct s verificai: - ce se ntmpl dac ntr-o metoda a clasei CD1 se ncearc folosirea cmpurilor sau metodelor private ale superclasei S1; - ce se ntmpl dac n clasa TestDC1 se ncearc folosirea cmpurilor sau metodelor private sau protejate din clasele S1 i CD1.

Ascunderea cmpurilor

174

Programarea orientata pe obiecte n limbajul Java Cmpurile declarate ntr-o clas pot fi ascunse prin cmpuri cu acelai nume declarate n subclas, chiar dac acestea au tipuri diferite. Aceasta nseamna c, n mod normal, n metodele clasei se folosesc cmpurile declarate n clasa respectiv, i nu cele cu acelai nume ale superclasei. n subclas pot fi, totui, folosite i cmpurile superclasei, dac sunt calificate cu referina super.

Ascunderea metodelor statice


Metodele statice nu aparin instanelor, ci clasei. Din aceast cauz, dac ntr-o subclas se declara o metoda static cu aceeai signatur ca o metod a superclasei, atunci se spune c metoda din subclas o ascunde pe cea din superclas (nu o redefinete). Modul de lucru cu metodele ascunse este similar cu cel n care se lucreaz cu cmpurile ascunse. Vom nelege mai bine deosebirea dintre redefinire i ascundere cnd vom studia polimorfismul. Exemplu n fiierul CD2.java este declarat clasa CD2, care extinde clasa S1 din exemplul precedent. n clasa CD2 exist declaraia public double a, b, m; prin care se creeaz cmpuri ale instanelor acestei clase, dintre care a i b ascund cmpurile cu aceleai nume ale superclasei. De asemenea, n clasa CD2 este declarat metoda static f4(int h), care ascunde metoda static cu aceeai signatura din superclasa S1.
/* O clasa in care se ascund unele din campurile superclasei */ class CD2 extends S1 { public double a, b, m; // campurile a, b le ascund pe cele cu // aceleasi nume din superclasa public CD2(int a1, double b1, int c1, double a2, double b2, double m2) { super(a1,b1,c1); // initializarea campurilor din superclasa a=a2; b=b2; m=m2; // initializarea campurilor proprii } public void afisare() { System.out.println("Campuri din CD2: a="+a+" b="+b+" m="+m); System.out.println("Campuri din S1: a="+super.a+" b="+super.b); } public static int f4(int h) { // ascunde metoda statica f4() din // superclasa return h+alpha; } public String toString() { return "(CD2: "+super.toString()+" "+a+" "+b+" "+m+")"; } }

Remarcm c: - n constructorul clasei CD2 este mai nti invocat constructorul superclasei, prin care se iniializeaz cmpurile din S1, dup care se iniializeaz i cmpurile din CD2; - ntruct metoda afisare() este declarat n clasa CD2, ea opereaz cu cmpurile a, b i m

175

Severin Bumbaru declarate n CD2. Totui, n acesast metod se poate lucra i cu cmpurile a i b din S1, folosindu-se n mod corespunztor expresiile super.a i super.b; - n redefinirea metodei toString() s-a folosit expresia super.toString() pentru a invoca metoda cu aceeasi signatur din superclasa S1. Observm c pentru a utiliza n aceasta metod n mod direct cmpurile a i b din S1 (care sunt ascunse n clasa CD2), ar fi trebuit utilizate expresiile super.a i super.b; Testarea clasei CD2 se face n aplicaia din fiierul TestCd2.java, care are coninutul urmtor:

/* Testarea clasei CD2 */ class TestCD2 { public static void main(String args[]) { CD2 cd=new CD2(1, 2.45, 3, 10.23, 12.5, 17.08); System.out.println("Imediat dupa ce s-a creat instanta clasei CD2:"); cd.afisare(); System.out.println("cd.toString(): "+cd.toString()); cd.a=-17.83; cd.b=28.16; cd.m=127.9; System.out.println("dupa ce s-au schimbat valorile "+ "campurilor din CD2:"); cd.afisare(); System.out.println("cd.toString(): "+cd.toString()); System.out.println("S1.f4(3)="+S1.f4(3)+" CD2.f4(3)="+CD2.f4(3)+" CD1.f4(3)=cd1.f4(3)); } }

Executnd aplicaia TestCD2 obinem urmtoarele rezultate:

Imediat dupa ce s-a creat instanta clasei CD2: Campuri din CD2: a=10.23 b=12.5 m=17.08 Campuri din S1: a=1 b=2.45 cd.toString()=(CD2: (S1: 1 2.45 3) 10.23 12.5 17.08) dupa ce s-au schimbat valorile campurilor din CD2: Campuri din CD2: a=-17.83 b=28.16 m=127.9 Campuri din S1: a=1 b=2.45 cd.toString()=(CD2: (S1: 1 2.45 3) -17.83 28.16 127.9) S1.f4(3)=18 CD2.f4(3)=15 CD1.f4(3)=18

Remarcm c: - n metoda afiare() din clasa CD2 se opereaz corect att cu cmpurile a i b din clasa CD2, ct i cu cele ascunse de acestea din clasa S1; - n metoda toString() din CD2 se opereaz direct cu cmpurile a i b declarate n aceast clas i cu metodele declarate n CD2 i se opereaza indirect (folosind referina super) cu cmpurile i metodele din superclasa S1 care sunt ascunse sau redefinite n CD2; - n expresiile S1.f4(3) i CD1.f4(3) este invocat metoda static a clasei S1, n timp ce n expresia CD2.f4(3) este invocat metoda cu aceeai signatur a clasei CD2, care o ascunde pe cea din clasa S1.

176

Programarea orientata pe obiecte n limbajul Java

Metode finale
Metodele finale sunt metode care nu mai pot fi redefinite n clasele derivate. Astfel de metode se declar cu modificatorul final. De exemplu, n clasa Object, metoda getClass este o metoda final, fiind declarat sub forma public final Class getClass(). Aceasta inseamn c n nici o alt clas nu este posibil ca aceasta metod s fie redefinit. Cnd declarm propriile noastre clase, avem i noi posibilitatea s declarm c unele din metodele lor sunt finale.

Declararea propriilor clase de excepii


Dei Java API ofer o varietate destul de mare de clase de excepii, uneori programatorul poate simi nevoia s ii creeze propriile sale clase de exceptii. Aceasta se poate realiza derivnd clasele respective din clasa Exception, existent n pachetul java.lang. Corpul declaraiei clasei de excepii conine numai declaraii de constructori, n care se apeleaz constructorul corespunztor al superclasei. Exemplu: n fiierul TestExceptie.java se d ca exemplu declararea i utilizarea clasei ExceptieDomeniuFactorial, care este generat la calcularea funciei factorial(n), dac argumentul acesteia n este negativ. S-au creat doi constructori: unul fr argument, altul avnd un argument din clasa String. Dintre acetia a fost folosit unul singur. Putei modifica programul pentru a-l utiliza i pe al doilea.

Clase finale
Dac se dorete ca o clas s nu poat avea subclase, la declararea acesteia se folosete modificatorul final. De exemplu, dac se dorea ca clasa CD1, dat ca exemplu mai sus, s fie finala, ea trebuia declarata sub forma
public final class CD1 extends S1

sau, dac nu se dorea sa fie publica, sub forma


final class CD1 extends S1

Polimorfismul
Polimorfismul se manifest atunci cnd unei variabile-referin pentru superclas i se atribuie ca valoare o referin ctre o instan a unei subclase a acesteia, n care una sau mai multe metode ale superclasei au fost redefinite. n limbajul Java se consider c metodele sunt legate dinamic (englez: dynamic method binding). Aceasta nseamn c stabilirea metodei care va fi invocat se face n momentul execuiei, fiind invocat metoda din clasa creia i aparine efectiv obiectul indicat de referina respectiv. Fie A o clas, iar B o subclas a clasei A i fie declaraiile
A a1, a2, a3; B b1; Object ob1, ob2, ob3;

Unei variabile referin dintr-o clas, i se pot atribui ca valori referine la instane ale 177

Severin Bumbaru subclaselor sale. n consecin, pot exista instruciuni de atribuire de forma
a1=new A(); a2=new B(); b1=new B(); a3=b1; ob1=new B(); ob2=a1; ob3=b1;

Ultimele dou atribuiri sunt posibile deoarece, n limbajul Java, toate clasele sunt subclase ale clasei Object. Se pune ntrebarea: dac o metod din clasa A, fie aceasta metoda1(), a fost redefinit n clasa B, care din ele va fi executata n expresia a2.metoda1()? Observm c, n aceast expresie, variabila a2 aparine clasei A, n timp ce obiectul indicat de aceast variabil aparine efectiv clasei B. Conform principiului polimorfismului, va fi executata metoda1() din clasa B.

Atenie: polimorfismul se aplic numai metodelor de instan. n cazul cmpurilor statice i metodelor statice, care sunt redeclarate n subclasa, nu are loc o redefinire, ci o ascundere. n consecin, legarea acestora este static (la compilare), iar la execuie se vor folosi cmpurile i metodele statice din clasa creia ii aparine variabila-referina, nu din clasa creia i aparine instana indicat de aceasta. n atentia programatorilor de C++ n limbajul C++ polimorfismul se manifest numai pentru metodele virtuale. Metodele care nu au fost declarate cu modificatorul virtual sunt legate static (la compilare), deci la execuie se invoc n astfel de cazuri metoda clasei creia i aparine variabila-referina (sau pointerul) i nu cea creia i aparine obiectul indicat. Folosind conceptele din C++, se poate considera c n limbajul Java toate metodele de instan sunt implicit virtuale (sunt legate dinamic), n timp ce metodele statice nu sunt virtuale (sunt legate static).

Conversia unei referine la clas ntr-o referin la subclas


Am artat mai sus c atribuiri de forma ob1=new B() sau ob2=a1 (unde ob1 i ob2 sunt variabile-referin la Object, iar a1 este variabila-referin la A) sunt permise, deoarece unei variabile referin dintr-o clasa i se pot da ca valori referine la instane ale unor subclase. n schimb, dac ncercm s utilizm expresia ob1.metoda1() sau ob2.metoda1() obinem erori de compilare, deoarece metoda1() nu exist n clasa Object. Pentru a evita astfel de erori, este necesar s convertim explicit (prin cast) referina la Object n referin la clasa A sau B, n care exist metoda1(). n acest scop, vom folosi expresiile ((B)ob1).metoda1() sau, respectiv, ((A)ob2).metoda1(). Avnd n vedere c B este subclas a lui A, iar variabila ob1 indic efectiv un obiect din clasa B, att n expresia ((B)ob1).metoda1(), ct i n expresia ((A)ob1).metoda1() se va invoca metoda1() din clasa B, adic din clasa creia i aparine efectiv obiectul indicat de variabila-referin ob1.

Exemplu n fiierul Polimorf1.java se da urmtorul exemplu de aplicaie n care se testeaz polimorfismul, folosind clasa S1 i subclasele ei CD1 i CD2 definite anterior:
class Polimorf1 { public static void main(String args[]) {

178

Programarea orientata pe obiecte n limbajul Java

Object ob1, ob2, ob3, ob4; S1 s1a, s1b, s1c; CD1 cd1a; CD2 cd2a; String s1="sirul1"; s1a=new S1(1, 2.5, 3); cd1a=new CD1(-1, -2.5, -3); cd2a=new CD2(10, 20.5, 30, 100, 200.5, 300); s1b=cd1a; s1c=cd2a; ob1=s1; ob2=s1a; ob3=cd1a; ob4=cd2a; System.out.println("s1a="+s1a+" s1b="+s1b); System.out.println("s1c="+s1c); System.out.println("s1a.f2()="+s1a.f2()+" s1a.f3()="+s1a.f3()); System.out.println("s1b.f2()="+s1b.f2()+" s1b.f3()="+s1b.f3()); System.out.println("s1c.f2()="+s1c.f2()+" s1c.f3()="+s1c.f3()); System.out.println("ob1="+ob1+" ob2="+ob2+" ob3="+ob3); System.out.println("ob4="+ob4); System.out.println("cd1a.f2()="+cd1a.f2()+" cd1a.f3()="+cd1a.f3()); System.out.println("cd2a.f2()="+cd2a.f2()+" cd2a.f3()="+cd2a.f3()); System.out.println("((S1)ob2).f2()="+((S1)ob2).f2()+ " ((S1)ob2).f3()="+((S1)ob2).f3()); System.out.println("((S1)ob3).f2()="+((S1)ob3).f2()+ " ((S1)ob3).f3()="+((S1)ob3).f3()); System.out.println("((CD1)ob3).f2()="+((CD1)ob3).f2()+ " ((CD1)ob3).f3()="+((CD1)ob3).f3()); System.out.println("((S1)ob4).f2()="+((S1)ob4).f2()+ " ((S1)ob4).f3()="+((S1)ob4).f3()); System.out.println("((CD2)ob4).f2()="+((CD2)ob4).f2()+ " ((CD2)ob4).f3()="+((CD2)ob4).f3()); } }

La executarea acestei aplicaii se obin pe ecran urmtoarele rezultate:

s1a=(S1: 1 2.5 3) s1b=(S1: -1 -2.5 -3) s1c=(CD2: (S1 10 20.5 30) 100.0 200.5 300.0) s1a.f2()=7 s1a.f3()=18.0 s1b.f2()=-2 s1b.f3()=-3.0 s1c.f2()=70 s1c.f3()=711.0 ob1=sirul1 ob2=(S1: 1 2.5 3) ob3=(S1: -1 -2.5 -3) ob4=(CD2: (S1 10 20.5 30) 100.0 200.5 300.0) cd1a.f2()=-2 cd1a.f3()=-3.0 cd2a.f2()=70 cd2a.f3()=711.0 ((S1)ob2).f2()=7 ((S1)ob2).f3()=18.0 ((S1)ob3).f2()=-2 ((S1)ob3)f3()=-3.0 ((CD1)ob3.f2()=-2 ((CD1)ob3).f3()=-3.0 ((S1)ob4).f2()=70 ((S1)ob4).f3()=711.0 ((CD2)ob4).f2()=70 ((CD2)ob4).f3()=711.0

Remarcm urmtoarele: - atribuiri de forma s1b=cd1a sau ob1=s1 sunt corecte, ntruct unei variabile-referin dintro clas i se pot da ca valori referine la instane ale subclaselor acesteia; - expresiile s1a.f2() i ((S1)ob2).f2() au aceeai valoare (7), intrucat in ambele cazuri este invocata metoda f2() din clasa S1;

179

Severin Bumbaru - n expresia ((S1)ob2).f2() s-a folosit castul pentru a converti referina la Object intr-o referin la S1, ntrucat n clasa Object nu exist o metoda f2(); - expresiile s1b.f2(), cd1a.f2(), ((S1)ob3).f2() i ((CD1)ob3).f2()au aceeasi valoare (-2), deoarece n toate cele trei cazuri metoda f2() se aplic asupra aceluiai obiect; - n expresia s1b.f2() nu a fost necesar s se foloseasc o conversie explicit (cast) de forma ((CD1)s1b).f2(), deoarece o metoda cu signatura f2() exist i n clasa S1, creia i aparine variabila s1b. Totui, n momentul execuiei, se aplic efectiv metoda f2() din clasa CD2, creia i aparine obiectul indicat de s1b; - n mod similar, expresiile s1c.f2(), cd2a.f2(), ((S1)ob4).f2() si ((CD2)ob4).f2() au aceeai valoare (70); - n instruciunea System.out.println("s1a="+s1a+" s1b="+s1b); se folosete implicit metoda toString()pentru a se converti obiectele indicate de variabilele-referin s1a i s1b n iruri. Se folosete n ambele cazuri metoda toString() din clasa S1, deoarece n clasa CD1 nu a fost redefinit o astfel de metod; - n instruciunea System.out.println("s1c="+s1c); se folosete implicit metoda toString() din clasa CD2, creia i aparine efectiv obiectul indicat de variabila s1c;

Un exemplu: clasa Persoana si subclasa Student


Studentul are toate atributele unei persoane, dar are i atribute i metode specifice. n consecin, clasa Student poate fi derivat din clasa Persoana. n continuare dm exemple de declarare i de testare a celor dou clase.

Declararea clasei Persoana


n fiierul Persoana.java, reprodus aici, este declarat clasa Persoana.
public class Persoana { private String nume, prenume; private int anNastere; public Persoana(String nume, String prenume, int anNastere) { this.nume=nume; this.prenume=prenume; this.anNastere=anNastere; } public Persoana(Persoana pers) { nume=pers.nume; prenume=pers.prenume; anNastere=pers.anNastere; } public String nume() { return nume; } public String prenume() { return prenume; }

180

Programarea orientata pe obiecte n limbajul Java


public int anNastere() { return anNastere; } public int varsta(int anCurent) { return anCurent-anNastere; } public String toString() { return nume+" "+prenume+" "+anNastere; } public int hashCode() { return nume.hashCode()+prenume.hashCode()/1000+anNastere%100; } }

Clasa contine trei cmpuri private: dou referine la String (nume i prenume) i un cmp de tip int (anNatere). ntruct cmpurile sunt private, ele nu sunt vizibile din alte clase (nici chiar din subclasele clasei Persoana). Clasa Persoana are doi constructori. Primul constructor primete ca argumente valorile celor trei cmpuri: nume, prenume, anNatere. ntruct argumentele au aceleai nume cu cmpurile corespunztoare, n corpul constructorului numele de cmpuri sunt calificate cu referina this. Aceasta se putea evita schimband numele argumentelor. Al doilea constructor are ca argument o instan a clasei Persoana, fiind ceeace se numete un "constructor de copiere". Vom vedea utilitatea lui in continuare, la declararea clasei Student. Metodele nume(), prenume() i anNastere() au rolul de a ntoarce fiecare valoarea cmpului corespunzator. Fiind publice, ele pot fi utilizate n alte clase. Aa dar, este posibil s obinem n alt clas valorile cmpurilor unui obiect Persoana, dar nu putem modifica aceste valori. Remarcm c este posibil ca numele unei metode s coincid cu cel al unui cmp. Nu are loc nici o confuzie, ntruct numele metodei este insoit ntotdeauna de paranteze, ca n expresia p1.nume(), care are ca valoare numele persoanei p1. Metoda varsta(int anCurent) ntoarce vrsta persoanei, fiind dat ca argument anul pentru care se calculeaz. Este un exemplu de metod care ntoarce un atribut al persoanei (vrsta), care nu este memorat ntr-un cmp, ci se obine prin calcul. Metodele toString() i hashCode() redefinesc metodele corespunztoare ale superclasei Object.

Declararea clasei Student


Clasa public Student este declarat n fiierul Student.java i este reprodus aici.
public class Student extends Persoana { private String fac, gr; private int anStudii; public Student(String nume, String prenume, int anNastere, String facultate, int an, String grupa) { super(nume, prenume, anNastere); fac=facultate; anStudii=an; gr=grupa;

181

Severin Bumbaru
} public Student(Persoana pers, String facultate, int an, String grupa) { super(pers); fac=facultate; anStudii=an; gr=grupa; } public Student(Student stud) { super(stud.nume(), stud.prenume(), stud.anNastere()); fac=stud.fac; anStudii=stud.anStudii; gr=stud.gr; } public String facultate() { return fac; } public int an() { return anStudii; } public String grupa() { return gr; } public String toString() { return super.toString()+" fac: "+fac+" an: "+anStudii+ " grupa: "+gr; } }

Clasa Student motenete cmpurile i metodele superclasei Persoana. n plus, conine urmtoarele cmpuri private: dou referine la String (fac - facultatea i gr - grupa) i un int (anStudii). Au fost declarai trei constructori. Primul are ca argumente valorile tuturor cmpurilor, att ale celor motenite de la superclas, ct i ale celor proprii. ntruct cmpurile superclasei sunt private, nu a fost posibil iniializarea lor direct, prin operaii de atribuire, ci prin apelarea constructorului superclasei sub forma
super(nume, prenume, anNastere);

Al doilea constructor are ca prim argument o referin la persoan, iar ultimele trei argumente sunt aceleai ca la constructorul precedent. Pentru iniializarea cmpurilor superclasei a fost invocat constructorul acesteia sub forma
super(pers); n care pers este referina la o Persoana. S-a utilizat aici constructorul de copiere Persoana(Persoana pers). Remarcm c nu am fi putut utiliza instruciunea super(pers.nume, pers.prenume, pers.anNastere);

deoarece cmpurile clasei Persoana sunt private i nu sunt, deci, accesibile din clasa Student. n lipsa constructorului de copiere, am fi putut utiliza in schimb instructiunea
super(pers.nume(), pers.prenume(), pers.anNastere()); deoarece metodele nume(), prenume() i anNastere() sunt publice.

Metodele publice facultate(), an() i grupa() ntorc valorile cmpurilor specifice clasei Student, respectiv fac, anStudii i gr. Metoda toString() redefinete metoda cu aceeai signatur a superclasei. 182

Programarea orientata pe obiecte n limbajul Java

Utilizarea claselor Persoana i Student


Aplicaia din fiierul TestStud.java are ca obiectiv testarea claselor Persoana i Student.
class TestStud { public static void main(String args[]) { Persoana p1=new Persoana("Vasiliu","George",1981), p2; Student s1=new Student(p1, "NIE",2,"2221a"), s2=new Student("Ionescu","Maria", 1980, "NIE", 2, "2322b"), s3; Object ob1, ob2, ob3; Persoana tabPers[]=new Persoana[3]; ob1=s1; ob2=p2=s2; ob3=p1; System.out.println("p1="+p1); System.out.println("s1="+s1); System.out.println("s2="+s2); System.out.println("ob1="+ob1); System.out.println("p2="+p2); System.out.println("ob2="+ob2); System.out.println("ob3="+ob3); System.out.println("Numele lui p1: "+p1.nume()); System.out.println("Numele lui s1: "+s1.nume()); System.out.println("Numele lui ob1: "+((Persoana)ob1).nume()); s3=(Student)ob2; System.out.println("s3="+s3); System.out.println("In anul 2000, s3 are "+s3.varsta(2000)+" ani"); System.out.println("p2.hashCode()="+p2.hashCode()); System.out.println("s1.hashCode()="+s1.hashCode()); tabPers[0]=p1; tabPers[1]=s1; tabPers[2]=s2; System.out.println("Tabloul de persoane tabPers contine:"); System.out.println("Clasa lui p1: "+p1.getClass().getName()); System.out.println("Clasa lui ob2: "+ob2.getClass().getName()); for(int i=0; i<tabPers.length; i++) System.out.println(tabPers[i]); } }

Se testeaz funcionarea metodelor polimorfe toString() din clasele Persoan i Student, funcionarea castului de la Object la Student si funcionarea metodei hashCode(), redefinit n clasa Persoana i mostenit de clasa Student. Se testeaz, de asemenea, metoda getClass(), motenita de la clasa Object. Se construiete i se utilizeaz un tablou de referine la Persoana.

O variant n care se utilizeaz cmpuri protejate


n fiierele Persoana1.java, Student1.java si Test1.java sunt date variante ale fiierelor comentate mai sus, n care sunt fcute urmtoarele modificri: - n clasa Persoana1 cmpurile nu mai sunt private, ci protejate; - n clasa Persoana1 s-a introdus n plus un constructor fr argumente. Acest constructor este necesar pentru a fi invocat implicit de constructorul clasei Student1, aa cum vom arta mai jos; - n primul constructor al clasei Student1 nu a mai fost invocat explicit constructorul clasei 183

Severin Bumbaru Persoana. Aceasta nseamn c, la construirea instanei Student1, a fost invocat implicit constructorul fr argumente Persoana1() al superclasei. Atribuirea de valori cmpurilor protejate ale superclasei se face, apoi, direct n corpul constructorului clasei Persoana1. S-au folosit, n acest scop, instruciuni de forma this.nume=nume, ntruct numele cmpului coincide cu cel al argumentului. Referina this este utilizat corect, intruct cmpul superclasei Persoana1 a fost motenit de clasa Student1, ne fiind acoperit n aceasta. Se putea folosi, ns, i referina super sub forma super.nume=nume, deoarece cmpul nume aparine, de fapt, superclasei; - n al doilea constructor al clasei Student1 nu a fost invocat explicit, de asemenea, constructorul superclasei. Atribuirea de valori cmpurilor protejate ale superclasei Persoana1 s-a fcut direct n corpul clasei Student1, prin instruciuni de forma nume=pers.nume, unde Pers este argumentul din clasa Persoana1; - s-au nlocuit peste tot, n cele trei fiiere, numele de clase Persoana i Student prin Persoana1 i Student1. Complilnd fiierul TestStud1.java i executnd aplicaia TestStud1 constatm c se obin aceleai rezultate ca n cazul aplicaiei TestStud. ntruct clasele Persoana1 i Student1 sunt publice, compilarea explicit a fiierelor respective nu este necesar, deoarece ea se face automat cnd se compileaz fiierul TestStud1.java.

Instanierea clasei care conine metoda main


Clasa care conine metoda main este clasa principal a unei aplicaii, deci este prima clas care se ncarc n maina virtual Java la punerea n execuie a aplicaiei respective. n acelai timp, ea este o clas ca oricare alta, care poate avea i instane. Metoda main(), fiind static, nu poate utiliza direct dect cmpurile statice i metodele statice ale acestei clase. Totui, n metoda main() sau n alte metode, pot fi create instane ale acestei clase, putndu-se astfel utiliza i cmpurile i metodele de instan ale acestora. Exemplu n fiierul Aplic.java este dat un exemplu de aplicaie, n care clasa Aplic, care conine metoda main(), are cmpuri i metode statice i de instan i constructor.
/* O clasa care contine metoda main() si poate fi instantiata */ class Aplic { static int a=10; // un camp static (al clasei) double b; // camp al instantei String s; // camp al instantei Aplic(double b, String s) { // constructorul clasei Aplic this.b=b; this.s=s; } double f1(double x) { // o metoda (functie) de instanta return a*b+1; // se utilizeaza campul static si cel de instanta } static int f2(int m) { // o metoda (functie) statica return m+a; // se utilizeaza numai campul static

184

Programarea orientata pe obiecte n limbajul Java

} public static void main(String args[]) { String s0="sir implicit 0", s1="sir implicit 1"; Aplic a0, a1; // Doua referinte la instante ale clasei Aplic if(args.length>=1) s0=args[0]; if(args.length>=2) s1=args[1]; /* Se creaza doua instante ale clasei Aplic */ a0=new Aplic(12.47, s0); a1=new Aplic(-15.28, s1); /* Campul static a si metoda statica f2 pot fi utilizate direct, sau calificandu-le cu numele clasei sau cu referinta la o instanta */ System.out.println("a="+a+" Aplic.a="+Aplic.a+" a0.a="+a0.a+ " a1.a="+a1.a); System.out.println("f2(2)="+f2(2)+" Aplic.f2(2)="+Aplic.f2(2)+ " a0.f2(2)="+a0.f2(2)+" a1.f2(2)="+a1.f2(2)); /* Campurile si metodele de instanta se folosesc prin intermediul referintelor la instantele respective */ System.out.println("a0.b="+a0.b+" a0.s="+a0.s); System.out.println("a1.b="+a1.b+" a1.s="+a1.s); System.out.println("a0.f1(1.5)="+a0.f1(1.5)+ " a1.f1(1.5)="+a1.f1(1.5)); /* Modificam campul static a si il afisam in diferite moduri */ a=20; System.out.println("Dupa modificari:"); System.out.println("a="+a+" Aplic.a="+Aplic.a+" a0.a="+a0.a+ " a1.a="+a1.a); /* Modificam campul b din fiecare instanta si afisam */ a0.b=32.5; a1.b=-121.8; System.out.println("a0.b="+a0.b+" a1.b="+a1.b); } }

Remarcm urmatoarele: - clasa Aplic are cmpuri statice i de instan i alte metode statice i de instan, pe lng metoda main(); - clasa Aplic are i un constructor (putea avea chiar mai muli, sau numai pe cel implicit); - n metoda main() se creeaz dou instane ale clasei Aplic, cu referinele a0 i a1; - n metodele statice main()i f2(), cmpul static a i metoda statica f2() pot fi utilizate direct, sau calificndu-le cu numele clasei sau cu o referin la o instan a acesteia. n toate cazurile se obtine acelai rezultat; - cmpurile i metodele de instan nu pot fi utilizate direct n metoda static main(), dar pot fi utilizate cele ale instanelor, calificandu-le cu referinele la aceste instane, de exemplu a0.b sau a0.f1(1.5); - n metodele de instan pot fi utilizate direct att cmpurile clasei, ct i ale instanei. Astfel, n metoda de instan f1() se folosete expresia a*b+1, n care apar cmpul static a i cmpul de instan b.

185

Severin Bumbaru

Clase abstracte
Clasele abstracte conin n declaraia lor modificatorul abstract. Clasele abstracte nu pot fi instaniate. Remarcm nsa c pot exista clase care nu pot fi instaniate dei nu sunt abstracte, cum sunt, de exemplu, clasele care nu au dect constructori privai. Cu toate c clasa abstract nu poate fi instaniat, se pot declara variabile aparinnd unor clase abstracte. Acestor variabile li se pot da nsa ca valori numai referine ctre instane ale unor subclase concrete. De exemplu, daca A este o clas abstracta, iar B este o subclas concreta a clasei A, atunci este corect declaraia
A a1=new B();

Din punct de vedere conceptual, clasa abstract modeleaz un concept general, care trebuie apoi dezvoltat prin subclase. Subclasele unei clase abstracte pot fi, la rndul lor, abstracte sau concrete. De exemplu, clasa abstract FiguraPlana poate avea ca subclase clasele Cerc, Elipsa, Poligon etc. Din punct de vedere al progrmarii, clasa abstract conine cel puin o metod abstract, adic o metod pentru care s-a declarat numai antetul, fr s i se defineasc i corpul. O clas poate s conin o metod abstract n mai multe moduri: a/ n corpul clasei este declarat explicit o metod abstract; b/ clasa mostenete de la superclasa ei o metod abstract, care nu este definita nici n corpul clasei curente; c/ clasa implementeaza o interfa, dar nu definete una sau mai multe din metodele acesteia. Dac apare o astfel de situaie, iar clasa nu este declarat n mod explicit abstract, se genereaza o eroare la compilare. Declararea unei metode abstracte: - antetul metodei trebuie sa conina modificatorul abstract; - corpul metodei se nlocuiete prin caracterul ';' (punct i virgul).

Exemplu: n fiierul FiguriPlane.java sunt declarate clasa abstract FiguraPlana i clasele instaniabile Cerc i Patrat. Este declarat, de asemenea clasa-aplicaie n care se testeaz aceste clase.

186

Programarea orientata pe obiecte n limbajul Java

Interfee
Conceptul de interfa
Conform principiului ncapsulrii, fiecare clas are "interfaa" sa intrinsec, prin care poate fi accesata din exterior. Aceasta "interfa" conine toate datele i metodele publice ale clasei respective. Pentru a compensa lipsa motenirii multiple, n limbajul Java s-a admis c o clas poate avea mai multe interfee i c mai multe clase pot implementa aceeai interfa. S-a introdus astfel o nou categorie de componente, numite interfee, care se declar n mod asemntor cu nite clase abstracte, dar nu sunt nglobate, aa cum sunt clasele abstracte, n ierarhia unic de clase .

Interfaa este o specificaie care descrie metodele publice i variabilele finale publice pe care trebuie sa le aib o clas care implementeaza interfaa respectiv. Dac o clas implementeaz mai multe interfee, ea conine toate metodele publice i variabilele finale publice ale acestora. Interfaa nu este o clas, dar poate fi utilizat de programator ca i cnd ar fi o clas abstract. Se pot declara variabile referin la o interfa n mod asemntor cu declararea variabilelor referina la obiecte aparinnd unei clase, adic sub forma:
interfaa nume_variabila1[=initializare1], ..., nume_variabilaN[=initializareN];

n care interfaa este numele unei interfee, iar celelalte elemente ale declaraiei sunt aceleai ca n cazul declarrii de referine la obiecte. Interfeele pot fi i ele organizate ierarhic, aplicndu-se principiul motenirii. n schimb, pentru interfee, ierarhia nu mai este unic, aa cum este n cazul claselor, i se admite motenirea multipl. Remarcam c, la fel ca i clasele abstracte, interfeele nu pot fi instaniate. n schimb, unei variabile referin la o interfa i se pot da ca valori referine ctre obiecte din orice clas care implementeaz acea interfa sau este descendent a unei astfel de clase. Pentru a le distinge mai uor, n documentaia Java API numele interfeelor sunt scrise cu litere cursive (stil italic), n timp ce numele claselor sunt scrise cu litere normale (drepte). De exemplu, n pachetul java.lang exist interfaa Cloneable care este implementat de toate clasele din SDK care implementeaz metoda clone(), deci ale cror obiecte pot fi clonate. Sa considerm acum exemplul din Figura 1, n care clasele B i C implementeaza interfeele I1 i I2, iar clasele C si D implementeaz interfeele I2 i I3.

187

Severin Bumbaru

- Figura 1 n acest exemplu, interfetele I1 i I2 sunt derivate din interfata I0 deci motenesc variabilele finale i metodele acesteia, putnd avea fiecare, de asemenea, date finale, cmpuri i metode proprii. Clasa B implementeaz interfaa I1, deci conine variabilele finale i metodele interfeei I1 i pe cele mostenite de aceasta de la interfaa I0. Clasa C implementeaz interfeele I1 i I2, deci conine variabilele finale i metodele interfeelor I1 i I2, inclusiv pe cele motenite de acestea de la interfaa I0. Totodat, clasele A, B i C motenesc datele i metodele clasei A. Faptul c variabilele finale i metodele interfeei I0 se propag la clasa C att pe traseul I0-I1-C, ct i pe traseul I0-I2-C nu mai produce dificulti, ca n cazul motenirii multiple a claselor, deoarece implementarea efectiv a acestor variabile i metode se face n clasa C i nu in interfee. Pentru exemplul din Figura 1, s considerm acum urmtoarele declaraii i instruciuni de atribuire valabile, n care A(), B(),C() si D() sunt constructori ai claselor respective:
A v1=new A(), v2; B v3=new B(), v4; C v5=new C(), v6; I0 w1=new B(),w2; I1 w3=new C(), w4; I2 w5, w6; v2=v5; w2=new D(); v4=v3; w4=v3; v6=new C(); w5=v6; w2=w4;

Constatm c variabilele referin la interfee (w1, w2, w3 etc.) sunt utilizate la fel ca i variabilele referinta la obiecte ale claselor. Dac, ins, tiind c variabila w1 are ca valoare o referin la un obiect din clasa B, vom dori sa folosim instruciunea
v4=w1;

vom constata c apare o eroare de compilare, deoarece v4 este referin la un obiect al unei clase, n timp ce w1 este o referin la interfa. n aceast situaie este necesar o conversie explicit (cast), astfel c vom folosi instruciunea
v4=(B)w1;

188

Programarea orientata pe obiecte n limbajul Java

Declararea interfeelor
O declaraie de interfa introduce un nou tip referin, ai crui membri sunt cmpuri statice finale i metode abstracte. n consecin, interfaa se aseamn cu o clasa abstract pur, care nu conine dect metode abstracte i cmpuri statice finale i nu se ncadreaz n ierarhia unic de clase descendente din Object (amintim ca o clasa abstract, n afar de una sau mai multe metode abstracte, poate conine i cmpuri de date i metode concrete i este descendent a clasei Object). Dei nu se ncadreaz n ierarhia claselor, interfeele se pot constitui in diverse ierarhii de interfee, aplicndu-li-se principiul mostenirii. O clas poate implementa mai multe interfee. Cel mai important avantaj al folosirii interfeelor este c mai multe clase, de pe diferite ramuri ale arborelui ierarhic al claselor, pot fi "vzute" printr-o singur interfa. Se pot declara variabile referin la interfa la fel cum se pot declara variabile referin la clas. Interfaa este abstract i deci nu poate fi instaniat. n schimb, unei variabile referin la interfa i se pot atribui ca valori referine la obiecte din orice clas care implementeaz interfaa respectiv. Declaraia de interfa are forma general urmtoare:
[public] interface NumeInterfata [extends lista_superinterfete] { declaratii_de_membri_ai_interfetei }

n afar de modificatorul public, se poate folosi i modificatorul abstract, numai c acesta este implicit, deci folosirea lui este de prisos. Spre deosebire de clase, la care motenirea multipl este interzis (o clas poate avea numai o singura superclas), n cazul interfeelor motenirea multipl este permis. n consecin, clauza extends poate conine o list de nume de interfee separate prin virgule. Corpul interfeei conine una sau mai multe declaraii de membru al interfeei. Declaraiile de membri ai interfeei pot fi: a/ Declaraia de cmpuri statice finale, numit i declaraie de constante, sub forma:
tip NUME_CAMP1=valoare1,NUME_CAMP2=valoare2,... , NUME_CAMP_N=valoareN;

n care tip este un tip primitiv. Modificatorii public, static i final pentru cmpurile interfeei sunt implicii, deci folosirea lor este de prisos. Aceasta nseamn c toate cmpurile unei interfee sunt publice, statice i finale, deci ele trebuie s fie iniializate la declarare i nu mai pot fi modificate ulterior. Se obisnuiete ca numele de cmp ale interfeelor s fie scrise numai cu majuscule.

Exemplu:
interface CuloareDeBaza { int ROSU=1, VERDE=2, ALBASTRU=4; }

189

Severin Bumbaru
interface Culoare extends CuloareDeBaza { int GALBEN=3, ORANGE=5, INDIGO=6, VIOLET=7; }

b/ Declaraia de metod abstract, care const din antetul metodei urmat de simbolul ';' (punct i virgul). Ea este deci la fel ca o declaraie de metod abstract din corpul unei clase, cu urmtoarele observaii: - modificatorii public i abstract sunt impliciti, deci folosirea lor este de prisos (dar este permis); - modificatorul final nu poate fi folosit, deoarece se declar o metod abstract; - corpul metodei este nlocuit prin simbolul punct i virgul, ca la orice metod abstract.

Exemplu:
interface Interf1 { double metoda1(); int metoda2(int a, int b, double c); }

Ambele metode din exemplul de mai sus sunt implicit publice i abstracte. Orice clas, care implementeaz aceasta interfa, trebuie sa conin declaraii de metode cu aceeai semntur cu cele din interfa. La definirea acestor metode m cadrul claselor, folosirea identificatorului public este obligatorie.

Clase imbricate i clase interioare


n limbajul Java se permite ca o clas s aib ca membri alte clase. Acestea se numesc clase imbricate sau clase ncuibate (engleza: nested classes). Ca i ceilali membri, clasele imbricate pot fi statice sau nestatice i se declar n corpul clasei care le ncorporeaz. Clasele imbricate nestatice se numesc clase interioare (englez: inner classes). O clas care ncorporeaz (imbric) alte clase se declar astfel:
[public] class NumeClasa { declaratii_de_membri_ai_clasei [modificatori_de_camp] class NumeClasaImbricata { declaratii_de_membri_ai_clasei_imbricate } declaratii_de_membri_ai_clasei }

Se recurge la aceasta tehnic atunci cnd utilizarea unei clase are sens numai n cadrul altei clase. Aadar, prin imbricare se creeaz o legatur strnsa ntre dou clase. Este posibil, desigur, ca o clasa s conin mai multe clase imbricate. Remarcm c declaraia clasei imbricate este tratata ca oricare alta declaraie de membru al clasei, putnd avea i modificatori de cmp (de exemplu static). Fiind membru al clasei, clasa imbricat are acces la toi membrii clasei care o conine, chiar i la cei privai. Dac clasa imbricat este static, ea nu poate referi direct dect membrii statici

190

Programarea orientata pe obiecte n limbajul Java ai clasei care o conine. Clasa imbricat static exist, la fel ca i cmpurile sau metodele statice, numai n cadrul clasei care o conine, nu i n instanele acesteia. n consecin, pentru a referi membrii acestei clase, se folosete pentru calificare numele clasei. Clasa interioar (clasa imbricat nestatic) are cte o instan n interiorul fiecrei instane a clasei care o conine. n consecin, accesul la membrii ei se poate face folosind drept calificator referina la o instan. Clasa interioar are acces la toi membrii clasei care o conine, att la cei statici, ct i la cei de instan (nestatici).

Exemplu: n seciunea Interfee a acestui curs, a fost dat un exemplu de aplicaie (din fiierul Integrare.java), n care se face integrarea funciilor prin metoda trapezelor. n fiierul Integrare.java, toate clasele sunt declarate n mod obinuit, ca nite clase autonome. n consecin, dup compilare se obin urmatoarele fiiere cu extensia class: Functie1.class, FunctieReala.class, Integrare.class, Integrator.class, IntegrareTrapeze.class. Clasa IntegrareTrapeze poate fi folosit n diferite aplicaii, deci are sens s fie declarat ca o clasa separat. n schimb, clasa Funcie1 este specifica numai unei singure aplicaii. Este deci preferabil s fie declarata ca o clas interioar a acestei aplicaii, aa cum se face n fisierul Integrare1.java. Clasa Functie1, din acest exemplu, a fost declarat ca o clasa interioar (clas imbricat nestatic) a clasei-aplicaie Integrare1. n consecin, accesul la membrii ei se poate face numai printr-o instan a clasei Integrare1. n acest scop, s-a procedat astfel: a/ s-a creat n metoda main() o instan a clasei Integrare1 prin instruciunea
Integrare1 int1=new Integrare1();

b/ s-a creat o instan a clasei Functie1 prin instruciunea


Functie1 f1=int1.new Functie1(arg1,arg2,arg3,arg4);

c/ Referina f1 la o instan a clasei interioare f1 a fost apoi utilizat n mod obinuit, ca argument al metodei integrare(); Atragem atenia asupra modului cum s-a fcut instanierea clasei interioare Functie1: operatorul new a fost calificat cu referinta int1 la o instan a clasei Integrare1, care o conine. Procedeul de mai sus a fost necesar, ntrucat metoda main() este static, astfel c nu poate accesa direct un membru nestatic al clasei, ci numai prin crearea unei instane a acesteia. Pentru comparaie, n acelai fiier s-a declarat (tot n clasa-aplicaie Integrare1) i o clasa imbricat static numit Functie2. Remarcm c instanierea acesteia s-a fcut n mod "obinuit" prin instruciunea
Functie2= func2=new Functie2(arg1,arg2,arg3); iar utilizarea funciei statice f2() coninute n aceasta s-a facut sub forma "obinuit" Functie2.f2(arg1,arg2) . De asemenea, utilizarea funciei nestatice f() a acestei clase s-a fcut "obinuit", sub forma func2.f(arg), iar instana func2 a fost transmis i ca argument

al metodei de integrare. Dup compilarea fiierului Integrare1.java, constatm c au fost creeate urmtoarele fiiere cu extensia class: FunctieReala.class, Integrare1.class, Integrare1$Functie1.class,

191

Severin Bumbaru Integrare1$Functie2.class, IntegrareTrapeze.class, Integrator.class. Remarcam ca numele fiieror de bytecode care conin clase imbricate sau interioare ncep prin numele clasei care le conine, urmat de caracterul $ i de numele clasei imbricate (interioare) respective. n acest fel, devine posibil ca n dou aplicaii distincte s existe clase imbricate sau interioare cu acelai nume, fr s se creeze confuzii.

192

Programarea orientata pe obiecte n limbajul Java

Exemplu de declarare, implementare i utilizare a unor interfee


Considerm c dorim s realizm diferite clase de integratoare numerice, care calculeaz prin diferite metode valoarea integralei pe intervalul [inf, sup] a funciei reale f(x). Dorim ca, n oricare din aceste integratoare, s existe metoda de calculare a integralei:
double integrala(double inf, double sup, FunctieReala func)

n care inf i sup sunt, respectiv, marginea inferioara i cea superioara a intervalului de integrare, iar func este o referin la un obiect care contine funcia de integrat f(x). Avnd n vedere c nu avem, deocamdat, n vedere o metoda de integrare numeric particular, vom declara interfaa

interface Integrator { double integrala(double inf, double sup, FunctieReala func); }

n care metoda de integrare apare ca o metoda abstract. Cu aceasta ocazie remarcam c, spre deosebire de limbajele de programare tradiionale, cum sunt Pascal sau C/C++, n limbajul Java nu exist posibilitatea ca o funcie (metod) s aib ca argument o referina la alt funcie (metod). n schimb, putem s-i oferim ca argument o referina la un obiect care conine funcia respectiv. Astfel, n cazul nostru, func este referin la un obiect care conine funcia de integrat f(x). Avnd n vedere c dorim ca integratoarele noastre s fie valabile pentru orice funcie real f(x), vom declara o interfa:

interface FunctieReala { double f(double x); }

care conine metoda abstract f(x) pe care trebuie s o conin orice obiect pe care l oferim ca argument metodei de integrare din interfaa Integrator. S realizm acum un integrator concret, pentru o anumita metod particular de integrare. Pentru simplitate, vom implementa integrarea prin metoda trapezelor. tiind c integrala poate fi interpretat geometric ca aria suprafeei cuprinse ntre graficul funciei respective i axa ox, putem mpri intervalul de integrare [inf, sup] n n subintervale de lungime egala h=(sup-inf)/n, ca n Figura 1.

193

Severin Bumbaru

- Figura 1 nlocuind pe fiecare din aceste subintervale curba f(x) prin coarda ei, obtinem n trapeze. Considerand c ariile cuprinse ntre curb i coarda curbei n fiecare din subintervale sunt mici, aproximm aria de sub curb prin suma ariilor celor n trapeze. Se obine astfel pentru calcularea integralei I cunoscuta formul a integrrii numerice prin metoda trapezelor dat n Figura 2.

- Figura 2 Pentru calcularea integralei este necesar s se impun i numrul de pai n, pe care l vom nota n continuare cu nrPasi. Putem astfel declara clasa IntegrareTrapeze, care implementeaza interfaa Integrator, n modul urmtor:

class IntegrareTrapeze implements Integrator { int nrPasi; // Numarul de pasi de integrare /* Constructorul initializeaza numarul de pasi de integrare */ public IntegrareTrapeze(int nrPasi) throws Exception { if(nrPasi<=0) throw new Exception("IntegrareTrapeze: nrPasi<=0"); this.nrPasi=nrPasi; } /* Metoda de modificare a numarului de pasi de integrare */ public void puneNrPasi(int nrPasi) throws Exception { if(nrPasi<=0) throw new Exception("IntegrareTrapeze: nrPasi<=0"); this.nrPasi=nrPasi; } /* Implementarea metodei abstracte din interfata Integrator */ public double integrala(double inf, double sup, FunctieReala func) { double h, s; h=(sup-inf)/nrPasi; // h este pasul de integrare /* Calcularea sumei ordonatelor s */ s=0; for(int i=1; i<nrPasi; i++) s+=func.f(inf+i*h);

194

Programarea orientata pe obiecte n limbajul Java

/* Calcularea valorii integralei si intoarcerea rezultatului */ return ((func.f(inf)+func.f(sup))/2+s)*h; } }

La calcularea integralei s-a aplicat formula din Figura 2, lund n consideraie c xi=inf+i*h. Remarcm c funcia f(x) nu a fost nc precizat. S-a indicat numai sub forma func.f(inf+i*h) c se folosete funcia (metoda) f(x) a obiectului func, care implementeaz interfaa FunctieReala. Integratorul nostru are deci o utilizare foarte larg, putnd integra funcia f(x) din orice obiect care implementeaz aceast interfa. Remarcm, de asemenea, c putem aplica i alte metode de integrare numeric, dac creem pentru fiecare din aceste metode o clasa care implementeaz interfaa Integrator. S considerm acum c dorim s integrm funcia
f(x)=a*sin(b*x+c)+d*cos(b*x)

n careparametrii a, b, c i d sunt numere reale. Pentru aceasta vom creea o clas care implementeaz interfaa FunctieReala i, totodat, conine drept cmpuri parametrii funciei:

class Functie1 implements FunctieReala { private double a, b, c, d; // parametrii functiei /* Constructorul clasei introduce valorile parametrilor functiei */ public Functie1(double a, double b, double c, double d) { this.a=a; this.b=b; this.c=c; this.d=d; } /* implementarea metodei abstracte din interfata */ public double f(double x) { return a*Math.sin(b*x+c)+d*Math.cos(b*x); } }

Putem acum s scriem o aplicaie n care se calculeaz integrala acestei funcii. n fiierul Integrare.javasunt date att declaraiile de interfee i clase prezentate mai sus, ct i cea a clasei-aplicaie n care se folosesc acestea.

ntrebri
Nivel 1
1. 2. 3. 4. 5. 6. 7. 8. Ce este ncapsularea? Care sunt modificatorii de acces pentru cmpuri i metode? Ce sunt constructorii? Ce particulariti prezint declaraiile de constructori? Poate avea o clas mai multi constructori? cum se disting acetia? Ce este constructorul implicit? Ce este agregarea? Ce este motenirea?

195

Severin Bumbaru 9. Ce relaie exist ntre o clas i superclasa ei? 10. Cte superclase poate avea o clas n limbajul Java? 11. Ce sunt membrii protejai ai clasei? 12. Ce sunt this si super? 13. Ce particulariti prezint constructorul unei clase derivate? 14. Ce se nelege prin redefinirea metodelor? 15. Ce fel de metode pot fi redefinite? 16. Ce este o metod final? 17. Ce se nelege prin ascunderea cmpurilor? 18. n ce situaie o metoda poate fi ascuns? 19. Este posibil declararea unei clase de excepii proprie? 20. Ce este o clas final? 21. Ce este polimorfismul? 22. n ce situaii se manifest polimorfismul? 23. Cum se face conversia unei referine dintr-o clasa n referin dintr-o subclas? 24. Poate fi instaniata clasa care conine metoda main()? 25. Ce este o clas abstract? 26. Ce este o metod abstract? 27. Cum se declar o clas abstract? 28. Ce este o interfa? 29. Ce efect are faptul c o clas implementeaz o interfa? 30. Ce este o clasa imbricat? 31. Ce este o clasa interioar?

Nivel 2
Enumerai caracteristicile obiectelor i claselor Ce se nelege prin identitatea obiectelor? Ce se nelege prin clasificare, ca proprietate a obiectelor? Ce este motenirea? Ce fel de motenire este permis n limbajul Java n cazul claselor? Ce se nelege prin ascunderea cmpurilor? Cum poate fi accesat dintr-o clas un cmp ascuns al superclasei? Este posibil s utilizm ntr-o clas un membru privat al superclasei? Este posibil s declarm ntr-o clas o metod cu aceeai signatur ca o metod privat din superclas? 10. Ce se ntmpl dac un argument sau o alt variabil local a unei metode are acelai nume cu un cmp al clasei respective? 11. Cum putem utiliza ntr-o metod a unei clase un cmp ascuns al propriei clase? 12. Sa considerm c n subclasa B a clasei A a fost redefinit metoda met(); cum putem utiliza n B metoda met() din A? 13. Ce este o metoda static? 14. Ce se ntmpl dac ntr-o clas se declar o metod static cu aceeai signatura ca a unei metode statice din superclas? 15. Cum poate fi invocat o metod static? 16. Cum poate fi invocat o metod de instan? 17. Dai un exemplu de declarare a unei clase de excepii. 18. Ce metode, n limbajul Java, nu sunt supuse polimorfismului? 1. 2. 3. 4. 5. 6. 7. 8. 9.

196

Programarea orientata pe obiecte n limbajul Java 19. Dai un exemplu de situaie n care trebuie folosit castul pentru a converti o referin. 20. n ce scop au fost definite n clasa Object metodele equals() i toString()? 21. S considerm c clasa A conine att metoda main(), ct i un cmp nestatic a i o metod nestatica met(). Cum putem utiliza n main cmpul a i metoda met()? 22. Ce asemnri i deosebiri exist ntre interfee i clasele abstracte? 23. Poate exista motenire multipl n cazul interfeelor? 24. Care sunt proprietile implicite ale cmpurilor unei interfee? 25. Care sunt proprietile implicite ale metodelor unei interfee? 26. Poate fi declarat ca final o metod a unei interfee? Justificati rspunsul. 27. Ce avantaj prezint declatrarea interfeei Integrator ca o interfa i nu ca o clas? 28. Ce avantaj prezint folosirea unei interfee ca argument al unei metode? 29. Ce deosebire exist ntre clasa imbricat i clasa interioar?

197

Severin Bumbaru

Interfee utilizator grafice i programarea orientat pe evenimente


Interfee utilizator grafice; Interfaa utilizator grafic a unei aplicaii Clasa Component Un exemplu introductiv de interfa utilizator grafic Programarea orientat pe evenimente Modelul de evenimente de pe platforma Java 2 Clase de evenimente Interfee i clase adaptoare pentru asculttori de evenimente Evenimentele generate de o fereastr Terminarea aplicatiei la inchiderea ferestrei; utilizarea clasei WindowAdapter Evenimente de mouse Evenimente de tast Adugarea unei componente la fereastra principal a aplicaiei Gestionarea poziionrii componentelor Clasa BorderLayout Clasa FlowLayout Clasa GridLayout Clasa BoxLayout Poziionarea absolut a componentelor (fr gestionar de poziionare) Gruparea componentelor prin utilizarea containerelor auxiliare Clasele Panel si JPanel Clasa Box ntrebri. 198 200 200 201 203 204 205 206 206 208 209 213 216 219 220 222 226 228 231 233 234 235 237

Interfee utilizator grafice


Interfaa utilizator, numit i interfaa om-main, este mijlocul de comunicare ntre un sistem informatic i utilizator. n programare, conceptul de interfa utilizator a aprut n legtur cu utilizarea programelor n regim interactiv. Un asemenea regim permite utilizatorului s comunice cu procesul de calcul n timpul desfurrii acestuia. n prezent, se cunosc dou tipuri principale de interfee utilizator: - interfaa prin linie de comand;

198

Programarea orientata pe obiecte n limbajul Java - interfaa grafic. n modul de comunicare prin linie de comand, operatorul uman transmite calculatorului comenzi, pe care le introduce de la tastatur sub forma unor linii de text, folosind un anumit limbaj de comand. Exemplele cele mai cunoscute sunt limbajele de comand ale sistemelor de operare MS-DOS i Unix. Interfaa utilizator grafic (englez: GUI - graphical user interface) este o interfa ommain care permite operatorului s dea comenzi i s introduc date prin acionarea asupra unor obiecte grafice vizualizate pe ecran: butoane, pictograme, meniuri etc.

Interfaa utilizator grafic a fost introdus pentru prima dat la Palo Research Center al firmei Xerox n anii 1970 i a fost apoi aplicat de firma Apple pe calculatoarele Macintosh n 1984. n prezent, cele mai rspndite interfee utilizator grafice sunt sistemul Windows al firmei Microsoft i cele de tip X-Window folosite n sistemele de operare din categoria Unix. Un avantaj important al platformei Java 2 este c ofer pachete de clase, care permit programatorului realizarea comod i eficient a interfeelor grafice. n prezent, exist dou grupuri de pachete de clase pentru interfee grafice, care corespund la dou principii diferite de realizare a interfeei: 1. AWT (englez: Abstract Windowing Toolkit - setul de dezvoltare de ferestre abstracte) este un set de clase care permit realizarea de interfee grafice n care se folosesc obiectele grafice specifice platformei pe care se execut programul. Aceasta nseamn c, dac programul se execut - de exemplu - sub Windows, diferitele obiecte grafice (butoane, meniuri, bare de defilare etc.) vor avea aspectul specific sistemului Windows, n timp ce dac se executa sub X-Window vor avea aspectul specific acestui sistem.

Principalele pachete utilizate n acest set sunt: java.awt,java.applet,java.awt.color si java.awt.event. Acestea se completeaz i cu alte subpachete ale pachetului java.awt, care sunt descrise n documentaia Java API. 2. JFC (englez: Java Foundation Classes - clase de baz Java), este un set de pachete de clase, care extind posibilitile oferite de AWT, pentru realizarea de interfee utilizator de calitate superioar. Dintre acestea, cele mai larg folosite constituie setul cunoscut sub numele de cod Swing (sau JFC/Swing), care ofer posibilitatea de a realiza interfee grafice al cror aspect nu depinde de platforma pe care se execut programul.

Principalele pachete din JFC/Swing sunt javax.swing i javax.swing.event, la care se adaug multe alte subpachete ale pachetului javax.swing descrise n documentaia Java API. Este important s menionm c pachetele din JFC/Swing nu se substituie, ci le completeaz pe cele din AWT. Modul de realizare al interfeei grafice folosind AWT este prezentat destul de amplu in lucrarea "Interfaa grafica utilizator n limbajul Java". n cursul de fa ne vom referi n special realizarea interfeei grafice utilizator folosind JFC/Swing i vom folosi 199

Severin Bumbaru clasele din AWT numai acolo unde va fi absolut necesar.

Se tie c autorii limbajului Java i-au propus ca programele scrise n acest limbaj s poat fi executate pe orice platform. Sub acest aspect, realizarea interfeei grafice a ridicat probleme dificile deoarece, pe diferite platforme, att setul de obiecte grafice utilizate, ct i aspectul acestora, pot fi diferite. La realizarea setului de dezvoltare AWT s-a acceptat ideea c n program se lucreaz cu nite obiecte grafice abstracte, care sa fie comune tuturor platformelor. Obiectul grafic abstract, aa cum este el luat n consideraie n AWT, se caracterizeaz prin anumite atribute i un anumit comportament, dar aspectul su pe ecran poate sa difere de la o platform la alta. Avantajul utilizrii AWT este c utilizatorul vede pe ecran obiectele care compun interfaa grafic sub forma cu care el este obinuit pe platforma pe care lucreaz. La aceasta se adaug i faptul c AWT se nelege i se utilizeaz relativ usor. Dezavantajul este c o astfel de interfa nu poate folosi dect obiectele grafice existente pe toate platformele (mulimea de clase de obiecte grafice din AWT este "intersecia" mulimilor de clase grafice de pe diferite platforme), ceeace restrnge posibilitatea programatorilor de a realiza interfee utilizator diversificate i originale. Autorii setului de dezvoltare JFC/Swing au decis s realizeze un set de clase de interfa care sunt complet independente de platform. n acest scop, s-a renunat la metodele native, clasele Swing fiind programate total n Java. Unele din aceste clase le extind sau le dubleaz pe cele din AWT, iar altele sunt complet noi. Mai mult, se d posibilitatea programatorului s dezvolte propriile sale clase de obiecte grafice prin extinderea celor existente. Este drept ins c aceasta se pltete prin creterea complexitii interfeei grafice i a nivelului de competen cerut de la programator.

Interfaa utilizator grafic a unei aplicaii


Orice interfa utilizator grafic este un obiect grafic structurat, n alctuirea cruia intr componente grafice. n sistemele AWT i JFC/Swing, toate componentele grafice fac parte din clase care constituie un arbore, a crui rdcin este clasa Component. Deosebim componente atomice i containere. Containerele sunt componente grafice care conin alte componente. Containerele aparin unor clase care formeaz o ierarhie, a crei rdcin este clasa Container. Clasa Container este derivat din clasa Component. Aceasta nseamn ca orice container este o el nsui component, deci un container poate s conin alte containere.

Clasa Component
Avnd n vedere c ntreaga ierarhie de clase de obiecte de interfa utilizator grafic folosite n Java (att cele din AWT, ct i din JFC/Swing) are ca rdcin clasa Component, este util s ncepem studiul cu aceast clas. Componenta este un obiect grafic care este afiabil pe ecran i poate interaciona cu utilizatorul.

200

Programarea orientata pe obiecte n limbajul Java Clasa Component este o clas abstract, derivat direct din clasa Object.

Dintre numeroasele metode ale acestei clase, prezentm aici numai cteva mai frecvent folosite: - testeaz dac aceast component este vizibil, atunci cnd este vizibil i containerul n care se gsete; public void setVisible(boolean visible) - face componenta sa fie vizibil sau nu, dup cum argumentul este true sau false; public boolean isShowing() - determin dac componenta este efectiv afiat pe ecran; public Point getLocation() - ntoarce locaia componentei (poziia colului din stnga sus n containerul-printe) sub forma unei instane a clasei Point; public void setLocation(Point location) - seteaz noua poziie a componentei n cadrul containerului printe; public Dimension getSize() - ntoarce dimensiunea componentei; public void setSize(int latime, int inaltime) - seteaz noile dimensiuni ale componentei.
public boolean isVisible()

n aceste metode se utilizeaz i clasele auxiliare Point i Dimension din pachetul java.awt. Instanele clasei Point conin coordonatele unui punct. Se consider c originea sistemului de coordonate se afl n colul din stnga sus, axa Ox este orientat ctre dreapta, iar axa Oy este orientata n jos. Instanele clasei Dimension conin dimensiunile componentei: limea i nlimea. O prezentare mai ampl a metodelor acestei clase este dat n indexul de clase. Descrierea complet este dat n documentaia Java API.

Un exemplu introductiv de interfa utilizator grafic


ntruct interfaa grafic conine componente, ea este un container. Vom studia ulterior diferite clase de containere dar, deocamdat, ne vom opri asupra clasei JFrame, care se folosete n aplicaiile Java. n sistemul JFC/Swing, interfaa utilizator grafic a unei aplicaii este o instan a clasei JFrame din pachetul javax.swing, sau este o subclas a acesteia. n mod obinuit, instanele clasei JFrame sunt ferestre care au la partea superioara o bar de titlu. n partea stng a barei de titlu exist un buton, la apsarea cruia se desfaoar un menu cu urmatoarele opiuni: Restore, Move,Size, Minimize, Maximize, Close. Cnd meniul este desfurat, acste opiuni pot fi selectate cu mouse-ul sau acionnd tasta corespunztoare literei subliniate. La partea dreapt a barei de titlu exista trei butoane, care au acelasi efect ca opiunile Minimize, Maximize i Close din meniul menionat. Selecionarea opiunilor sau acionarea butoanelor din bara de titlu produce asupra ferestrei efectul corespunztor. Fereastra poate fi deplasat pe ecran dac punem cursorul mouse-lui

201

Severin Bumbaru pe bara de titlu i o tragem, innd butonul de mouse apsat. Dimensiunile ferestrei pot fi modificate trgnd cu mouse-ul oricare din laturile sau din colurile ei. Modul cel mai simplu de a realiza o aplicaie cu interfa grafic este s folosim direct o instan a clasei javax.swing.JFrame, care extinde clasa Frame din AWT. Clasa are o structur destul de complicat i este descris complet n documentaia Java.API. Pentru a nu intra de la nceput n detalii, vom da, deocamdat, numai cateva informaii strict necesare pentru folosirea acestei clase, urmnd s revenim ulterior cu indicaii suplimentare. Principalul constructor este:
JFrame(String titlu) unde titlu este titlul ferestrei.

Clasa JFrame are numeroase metode, att proprii, ct i motenite de la superclasele ei. n afar de metodele motenite de la clasa Component, deocamdat, vom mai meniona aici numai dou, care sunt motenite de la clasa Frame:
public String getTitle() - ntoarce titlul ferestrei; public void setTitle(String titlu) - pune ferestrei

un titlu (n locul celui

existent). La crearea ei, instana clasei JFrame nu este vizibil. Pentru a o face vizibil se folosete metoda public void setVisible(boolean visible) a clasei Component. Constructorii i metodele clasei Frame se gasesc n indexul de clase. Descrierea complet se gsete n documentaia Java API.

Exemplu: introducerea unui JFrame ntr-o aplicaie n fiierul TestJFrame1.java este dat un exemplu de aplicaie care are o interfa utilizator din clasa JFrame. Iat coninutul acestui fiier:

import java.awt.*; import javax.swing.*; class TestJFrame1 { static JFrame iug; public static void main(String args[]) throws Exception { iug=new JFrame("Exemplu de JFrame"); iug.setSize(300,100); iug.setLocation(new Point(100,50)); iug.setVisible(true); System.out.println("Titlul ferestrei este: "+iug.getTitle()); System.out.println("Coltul din stanga sus este in punctul: "+ iug.getLocation()); System.out.println("Dimensiunile ferestrei: "+iug.getSize()); } }

202

Programarea orientata pe obiecte n limbajul Java

n prima linie este importat pachetul javax.swing, care conine principalele clase ale JFC/Swing, inclusiv clasa JFrame. n clasa TestJFrame1 (care este aplicaia noastr), s-a declarat cmpul static iug, care este o referin la JFrame. n prima instruciune din metoda main se creeaza o instan a clasei JFrame i se d cmpului iug ca valoare referina la instana nou creat. Se folosesc apoi metodele setSize(), setLocation() i setVisible() din clasa Component, pentru a stabili dimensiunile ferestrei i pozitia ei pe ecran i a o face vizibil. Se afieaza apoi n fereastra terminalului de la care s-a lansat aplicaia (la ieirea standard a sistemului) titlul, coordonatele i dimensiunile ferestrei, folosind metodele adecvate din clasele JFrame i Component. La lansarea n execuie a acestei aplicaii, n colul din stnga sus al ecranului apare o fereastr de dimensiuni 300x100 pixeli, cu titlul "Exemplu de JFrame", iar la ieirea standard apar toate mesajele afiate prin instruciunile System.out.println(...) din metoda main. Putem acum s acionm asupra ferestrei cu mouse-ul, avnd grij s nu dam comanda Close (nici din menu, nici acionnd butonul din dreapta sus marcat cu X): putem s deplasm fereastra tragnd cu mouse-ul de bara de titlu, s o iconificm (minimizm), deiconificm, maximizam, restaurm. Putem, de asemenea, s modificm dimensiunile ferestrei, trgnd cu mouse-ul de marginile acesteia. La sfrit, putem da comanda Close (din meniul ferestrei sau apasnd butonul marcat cu X) i fereastra se nchide. Constatm ns c nchiderea ferestrei nu are drept consecina i ncheierea executrii aplicaiei: n fereastra terminalului din care am lansat aplicaia nu a aprut promptul sistemului de operare. Pentru a ncheia executarea aplicaiei, trebuie s dm de la terminal comanda <Control>-C. Pentru a avea o interfa grafic functional, este necesar: - s adaugm la interfa componente grafice; - s asigurm interaciunea utilizatorului cu aceste componente i cu nsi fereastra aplicaiei. Ne vom ocupa de aceste aspecte n seciunile urmtoare.

Programarea orientat pe evenimente


Cnd se lucreaz cu o interfa grafic, pe ecranul staiei de lucru apar diferite obiecte grafice: ferestre, meniuri, butoane, bare de defilare etc. Operatorul poate utiliza tastatura staiei de lucru, la fel ca n cazul progrmarii tradiionale, dar, n plus, utilizeaz un dispozitiv de selecie numit mouse, cu ajutorul cruia poate alege diferite obiecte grafice de pe ecran i poate da anumite comenzi prin apsarea unuia din butoanele acestui dispozitiv. Se numeste eveniment orice modificare care are loc, fie n starea dispozitivelor de intrare, fie n cea a obiectelor grafice de pe ecran: apsarea sau eliberarea unei taste, deplasarea mouseului, apsarea sau eliberarea unui buton al mouse-ului, deschiderea sau nchiderea unei ferestre, efectuarea unui clic de mouse pe un obiect de control (buton, caseta de validare, bara de defilare etc.), intrarea cursorului de mouse n cmpul activ al unui obiect grafic sau

203

Severin Bumbaru prsirea acestuia etc. Pot exista, desigur, i alte tipuri de evenimente, dar aici ne intereseaz numai cele legate de interfaa grafic a aplicaiei. Interaciunea dintre operator i aplicaie ntr-un sistem bazat pe evenimente decurge astfel: operatorul provoac generarea unui eveniment, acionnd asupra tastaturii, mouse-ului sau a altui dispozitiv de intrare, iar programul "rspunde" la acest eveniment prin executarea unei anumite aciuni. Acest mod de lucru impune o nou concepie n proiectarea programelor, numit programarea orientat pe evenimente.

n programarea procedural tradiional, procesul de calcul este n ntregime ghidat de instruciunile programului. Imediat ce s-a ncheiat executarea unei instruciuni, se trece la instruciunea urmtoare, respectnd fluxul de instruciuni al programului respectiv. Aceasta se refer i la interaciunea dintre program i utilizator. Chiar dac programul este interactiv, initiaiva privind ce date trebuie introduse i n ce moment se introduc acestea aparine programului. Operatorului uman nu i rmne dect s se conformeze solicitrilor programului i s introduc date atunci cnd ele sunt cerute de acesta. Este evident c un asemenea rol nu este deloc convenabil pentru om, care dorete s aib el iniiativa aciunilor. Apariia interfeelor grafice a permis introducerea unei noi concepii n interaciunea dintre operator i aplicatie, astfel ca iniiativa s i revin operatorului uman, iar programul s execute comenzile acestuia. S-a trecut, astfel, de la programarea procedural tradiional la programarea orientat pe evenimente (englez: Event-Oriented Programming), cunoscuta i sub numele de programare ghidat de evenimente (englez: Event Driven Programming). Exist diferite modele de generare, captare i tratare a evenimentelor. n lucrarea de fa va fi prezentat modelul de evenimente specific platformei Java 2.

Modelul de evenimente de pe Platforma Java 2


In JDK 1.0 s-a folosit un model de evenimente bazat pe motenire, reprezentat prin clasa Event. Aceast clas este meninuta n continuare, din motive de compatibilitate a programelor din JDK 1.0 cu cele din versiunile ulterioare, dar nu mai este recomandat. ncepnd cu JDK 1.1 s-a introdus un nou model de evenimente, bazat pe delegare (englez: Delegation Event Model). Conform acestui model, distingem trei catedorii de obiecte care au relaii cu evenimentele: - obiecte care genereaz evenimente, numite surse de evenimente (engleza: Event Source); - obiecte care capteaz i trateaz evenimentele, numite asculttori de evenimente (englez: Event Listener); - evenimentele propriu-zise (englez: Event), care sunt tot obiecte, generate de surse i captate de asculttori. Un eveniment generat de o surs poate fi interceptat de mai muli asculttori. Este posibil ca un obiect s se "asculte" pe sine nsui, deci s i trateze propriile evenimemte. Tocmai aceast legatur strnsa ntre sursele i asculttorii de evenimente este caracteristica eseniala a "modelului delegrii": ea const n faptul c sursa transmite evenimentele generate de ea

204

Programarea orientata pe obiecte n limbajul Java numai ctre asculttorii care au fost ataai la sursa respectiv, iar asculttorul primete evenimente numai de la sursele la care a fost ataat.

n modelul de evenimente din JDK 1.0 sursa transmitea evenimentele fr o destinaie anume, iar consumatorii de evenimente trebuiau sa depisteze singuri ce fel de evenimente sunt acestea i de la ce surs provin i, n funcie de aceasta, s decid dac intercepteaz sau nu evenimentul respectiv. Remarcm, deci, c se aplic cu consecven principiul programrii orientate pe obiecte, n sensul c aplicaia este constituit dintr-un ansamblu de obiecte care interacioneaz. Putem spune c evenimentul este o nou forma de mesaj, care se transmite ntre obiectele-surs i obiectele-asculttori. Fiecare ascultator trebuie "adugat" la surs. n acest fel, sursa "tie" cror asculttori s le transmit evenimentele pe care le genereaz. Este important sa reinem faptul c, n acest model de evenimente, sursele sunt ntotdeauna componente ale interfeei grafice. Cnd cursorul mouse-ului intr n interiorul unei componente sau iese din aceasta, sau cnd facem click de mouse pe o componenta, evenimentul nu este generat direct de ctre mouse, ci de ctre componenta respectiv a interfeei. n mod similar, cnd apsm sau eliberm o tast, evenimentul nu este generat direct de ctre tast, ci de ctre acea component a interfeei grafice, care este activ n momentul respectiv. Evenimentele pot fi generate de o component i atunci cnd au loc modificari ale strii acesteia ca urmare a executrii unor instruciuni din program (de exemplu cnd se deschide sau se nchide o fereastr, etc.).

Clase de evenimente
Clasele de evenimente se gsesc n pachetele java.awt.event i javax.swing.event i formeaz o ierarhie de clase, care are ca radacin clasa abstract java.awt.AWTEvent. Aceasta, la rndul ei, extinde clasa java.util.EventObject din pachetul java.util. Orice eveniment conine urmtoarele metodele declarate n clasa java.util.EventObject:
public Object getSource()

- care ntoarce o referin ctre obiectul care a generat - care ntoarce o reprezentare sub forma de ir a

evenimentul respectiv;
public String toString()

obiectului. Orice eveniment AWT (generat de componente AWT sau JFC/Swing) conine un cmp protejat de tip int numit id, a crui valoare indic tipul evenimentului. Toate clasele de evenimente conin cmpuri statice finale de tip int, al cror nume indic tipul de eveniment i a cror valoare este valoarea corespunztoare a cmpului id. Valoarea acestui cmp se poate obine prin metoda
public int getId()

Evenimentele pot fi de nivel cobort (low level event) sau semantice. Numele claselor de evenimente de nivel cobort indic fie componenta, fie dispozitivul de intrare care le-a generat, de exemplu: ComponentEvent, WindowEvent, MouseEvent, KeyEvent. Numele claselor de evenimente semantice indic mai curnd tipul de eveniment, dect sursa acestuia,

205

Severin Bumbaru de exemplu: ActionEvent, TextEvent. Descrierea claselor de evenimente este dat complet n documentaia Java API.

Interfee i clase adaptoare pentru asculttori de evenimente


Evenimentele generate de surse, sunt captate i tratate de asculttori. Sursele sunt componente ale interfeei grafice care, de regul, sunt preluate din pachetele de clase ale platformei Java 2, deci nu sunt programate de ctre programatorul de aplicaie, ci doar utilizate de acesta. n schimb, programatorul de aplicaie trebuie s creeze clasele de asculttori de evenimente specifice aplicaiei pe care o dezvolt. Metodele acestor clase trebuie sa reacioneze la apariia evenimentelor i s execute aciunile corespunztoare, conform cu obiectivele aplicaiei. n consecin, platforma Java 2 nu pune la dispoziie clase asculttoare predefinite, ci doar interfeele pe care trebuie s le implementeze aceste clase, pentru a putea trata evenimentele pe care le recepioneaz. Exist cte o interfa de asculttor pentru fiecare clas de eveniment. De exemplu, pentru ComponentEvent exist interfaa ComponentListener, pentru WindowEvent exista intefaa WindowListener etc. Pentru a se uura munca programatorilor, pentru unele interfee care conin mai multe metode, se ofer i prototipuri de clase care implementeaz interfaa respectiv, numite adaptoare. De exemplu, clasa WindowAdapter implementeaz interfaa WindowListener, clasa MouseAdapter implementeaz interfaa MouseListener etc. Adugarea asculttoarelor la sursele de evenimente se face prin metode de adugare corespunztoare, existente n clasele de surse. De exemplu, pentru a se aduga la o instan a clasei Window sau a subclaselor acesteia (de exemplu JFrame) un asculttor de evenimente de fereastr, n clasa Window exist metoda
public void addWindowListener(WindowListener l)

Descrierea complet a interfeelor i adaptoarelor pentru clasele de asculttori de evenimente este dat n documentaia Java API.

Evenimentele generate de o fereastr


Pentru a ne familiariza cu modelul de evenimente al platformei Java 2, vom urmri acum evenimentele generate de o fereastr i modul cum acestea pot fi tratate. Vom folosi n acest scop o interfa din clasa javax.swing.JFrame. Aceasta este derivat din clasa java.awt.Frame care, la rndul ei, este derivat din clasa java.awt.Window. Evenimentele prezentate n aceast seciune sunt generate de orice instan a clasei Window i ale subclaselor sale. Evenimentele generate de fereastr sunt instane ale clasei WindowEvent i sunt ascultate de instane ale unor clase care implementeaz interfaa WindowListener sau extind clasa WindowAdapter. Toate aceste clase i interfee se gsesc n pachetul java.awt.event.

Metodele interfeei WindowListener sunt urmtoarele: public void windowOpened(WindowEvent e)- fereastra a fost deschis public void windowClosing(WindowEvent e)- fereastra se nchide

206

Programarea orientata pe obiecte n limbajul Java


public public public public public void void void void void windowClosed(WindowEvent e)- fereastra a fost inchis windowIconified(WindowEvent e)- fereastra a fost iconificat windowDeiconified(WindowEvent e)- fereastra a fost deiconificat windowActivated(WindowEvent e)- fereastra a fost activat windowDeactivated(WindowEvent e)- fereastra a fost dezactivat

Pentru a se trata evenimentele generate de fereastr, este necesar s se declare o clas care implementeaz interfaa WindowListener. n aceast clas se definesc toate metodele interfeei, astfel nct acestea s execute aciunile adecvate evenimentelor corespunztoare.

Exemplu n fiierul Evenim1.java este dat ca exemplu urmtorul program, n care se urmresc evenimentele generate de o fereastr din clasa JFrame.
import java.awt.*; import java.awt.event.*; import javax.swing.*; class Evenim1 { static JFrame iug; // referinta la interfata grafica static AscultFereastra af; // referinta la ascultator /* Clasa imbricata pentru ascultatorul de fereastra */ static class AscultFereastra implements WindowListener { public void windowOpened(WindowEvent e) { System.out.println("Fereastra a fost deschisa: "+e); } public void windowClosing(WindowEvent e) { System.out.println("Fereastra se inchide: "+e); } public void windowClosed(WindowEvent e) { System.out.println("Fereastra a fost inchisa: "+e); } public void windowIconified(WindowEvent e) { System.out.println("Fereastra a fost iconificata: "+e); } public void windowDeiconified(WindowEvent e) { System.out.println("Fereastra a fost deiconificata: "+e); } public void windowActivated(WindowEvent e) { System.out.println("Fereastra a fost activata: "+e); } public void windowDeactivated(WindowEvent e) { System.out.println("Fereastra a fost dezactivata: "+e); } } // se incheie clasa ascultatorului de fereastra /* Metoda principala */ public static void main(String args[]) throws Exception { af=new AscultFereastra(); // instantierea ascultatorului iug=new JFrame("Urmarire evenimente fereastra"); iug.setSize(300,100); iug.setLocation(new Point(100,50)); iug.setVisible(true);

207

Severin Bumbaru

iug.addWindowListener(af); // adaugarea ascultatorului System.out.println("Titlul ferestrei este: "+iug.getTitle()); System.out.println("Coltul din stanga sus este in punctul: "+ iug.getLocation()); System.out.println("Dimensiunile ferestrei: "+iug.getSize()); } }

Pentru asculttorul de fereastr a fost creat clasa imbricat static AscultFereastra, n care sunt implementate toate metodele interfeei WindowListener. n cazul de fa, aceste metode nu fac altceva, dect c afieaz pe terminal un mesaj privind evenimentul care s-a produs. Acest mesaj conine i evenimentul interceptat e, convertit n ir. n metoda main(), se construiesc instanele claselor JFrame i AscultFereastra, dup care se adaug asculttorul af la fereastra iug prin metoda addWindowListener(). Se stabilesc, de asemenea, dimensiunea i poziia ferestrei i se face fereastra vizibil. Dup ce a fost pus aplicaia n execuie, pe ecran apare o fereastr cu titlul "Urmarire evenimente fereastra". La terminal putem urmri succesiunea evenimentelor care se produc. Ca i n exemplul precedent, ieirea din aplicaie se face de la tastatura, prin comanda <Control>-C. Remarcm c, n exemplul de mai sus, a fost necesar ca, n clasa care implementeaz interfata WindowListener, s se defineasc toate metodele acesteia. Dac ne sunt necesare numai unele din aceste metode, este preferabil sa obinem clasa AscultFereastra prin extinderea clasei WindowAdapter. Aceast ultim clas conine toate metodele interfeei WindowListener, dar corpurile lor sunt vide, deci metodele nu fac nimic. n acest fel, n clasa derivat este suficient s redefinim numai metodele care ne sunt necesare, ca n exemplul din seciunea urmtoare.

Terminarea aplicaiei la nchiderea ferestrei


Pentru ca la acionarea butonului de nchidere din colul din dreapta-sus al ferestrei s se nchid nu numai fereastra respectiv, ci si aplicaia, este necesar ca metoda windowClosing() a asculttorului de fereastr s conin invocarea metodei System.exit(0) din clasa System. Dac nu dorim s utilizam i alte metode de tratare a evenimentelor generate de fereastr, vom deriva clasa de ascultare a ferestrei AF din clasa WindowAdapter. Exemplu n fiierul Inchidere.java se d o modificare a clasei Evenim1 din exemplul precedent.
import java.awt.*; import java.awt.event.*; import javax.swing.*; class Inchidere { static JFrame iug; // referinta la fereastra static AF af; // referinta la ascultator /* Clasa imbricata pentru ascultatorul de fereastra */ static class AF extends WindowAdapter {

208

Programarea orientata pe obiecte n limbajul Java

public void windowActivated(WindowEvent e) { System.out.println("Fereastra a fost activata"); } public void windowDeactivated(WindowEvent e) { System.out.println("Fereastra a fost dezactivata"); } public void windowClosing(WindowEvent e) { System.out.println("Fereastra se inchide"); System.exit(0); // incheierea executarii aplicatiei } } /* Metoda principala */ public static void main(String args[]) throws Exception { af=new AF(); // instantierea ascultatorului iug=new JFrame("Urmarire evenimente fereastra"); iug.setSize(300,100); iug.setLocation(new Point(100,50)); iug.setVisible(true); iug.addWindowListener(af); // adaugarea ascultatorului System.out.println("Titlul ferestrei este: "+iug.getTitle()); System.out.println("Coltul din stanga sus este in punctul: "+ iug.getLocation()); System.out.println("Dimensiunile ferestrei: "+iug.getSize()); } }

n acest program, n afar de modificarea numelor claselor, s-au mai fcut urmtoarele modificri: - clasa de ascultare a evenimentelor AF extinde clasa WindowAdapter, deci implementeaz in mod indirect interfaa WindowListener, prin intermediul acesteia; - s-au definit numai trei din cele apte metode ale intefeei WindowListener; celelalte metode sunt motenite de la clasa WindowAdapter, deci nu fac nimic; - n metoda windowClosing()s-a introdus instruciunea System.exit(0); n consecin, cnd acionm butonul de nchidere al ferestrei, sau selectm optiunea Close din meniu, se ncheie executarea aplicaiei.

Evenimente de mouse
Evenimentele de mouse sunt instane ale clasei java.awt.event.MouseEvent i sunt generate de ctre orice component a interfeei grafice, atunci cnd asupra ei se acioneaza cu mouseul. Clasa MouseEvent este derivat din clasa java.awt.event.InputEvent. Evenimentele de mouse sunt intrarea cursorului de mouse ntr-o component sau ieirea din aceasta, apsarea unui buton de mouse sau eliberarea lui, efectuarea unui click de mouse (simplu sau multiplu) pe suprafaa componentei, micarea mouse-ului. Pentru ascultarea evenimentelor de mouse se folosesc interfeele java.awt.event.MouseListener,java.awt.event.MouseMotionListener i javax.swing.event.MouseInputListener. Asculttoarele de mouse se pot obine, de asemenea, prin extinderea claselor java.awt.event.MouseAdapter,java.awt.event.MouseMotionAdapter i

209

Severin Bumbaru javax.swing.event.MouseInputAdapter.

n AWT se face distincie ntre evenimentele de mouse discrete i evenimentele care caracterizeaz micarea continu a mouse-lui. a/ Evenimente de mouse - a fost apsat un buton al mouse-ului (MOUSE_PRESSED); - a fost eliberat un buton al mouse-ului (MOUSE_RELEASED); - s-a fcut click de mouse, adic un buton al acestuia a fost apsat i eliberat imediat (MOUSE_CLICKED); - cursorul mouse-ului a intrat ntr-o component (MOUSE_ENTERED); - cursorul mouse-ului a ieit din component (MOUSE_EXITED). Ascultarea acestor evenimente se face cu instane ale claselor care implementeaza interfaa java.awt.event.MouseListener. b/ Evenimente de micare a mouse-ului - mouse-ul s-a micat pe suprafaa componentei (MOUSE_MOVED); - mouse-ul a fost "tras" pe suprafaa componentei, adic a fost micat innd un buton apsat (MOUSE_DRAGGED). Aceste evenimente sunt ascultate cu instane ale claselor care implementeaz interfaa java.awt.event.MouseMotionListener. n JFC/Swing s-a introdus n plus interfaa javax.swing.event.MouseInputListener, care ascult ambele categorii de evenimente de mouse, motenind cele dou interfee menionate mai sus.

Exemplu n fiierul EvMouse.java este dat un exemplu de aplicaie n care se ascult evenimentele de mouse generate de o instan a clasei JFrame i se afieaz la terminal coninutul acestor evenimente. n acest scop, n clasa imbricat AMouse au fost implementate toate metodele interfeei MouseListener, dar aceste metode nu fac altceva, dect s afieze la terminal evenimentul recepionat.
import java.awt.*; import java.awt.event.*; import javax.swing.*; class EvMouse { static JFrame iug; // referinta la fereastra static AF af; // referinta la ascultator de fereastra static AMouse am; // referinta la ascultator de mouse /* Clasa imbricata pentru ascultatorul de fereastra */ static class AF extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); // incheierea executarii aplicatiei } }

210

Programarea orientata pe obiecte n limbajul Java

/* Clasa imbricata pentru ascultatorul de mouse */ static class AMouse implements MouseListener { public void mouseClicked(MouseEvent e) { System.out.println(e); } public void mousePressed(MouseEvent e) { System.out.println(e); } public void mouseReleased(MouseEvent e) { System.out.println(e); } public void mouseEntered(MouseEvent e) { System.out.println(e); } public void mouseExited(MouseEvent e) { System.out.println(e); } } /* Metoda principala */ public static void main(String args[]) throws Exception { af=new AF(); // instantierea ascultatorului am=new AMouse(); // instantierea ascultatorului de mouse iug=new JFrame("Urmarire evenimente de mouse"); iug.setSize(300,100); iug.setLocation(new Point(100,50)); iug.setVisible(true); iug.addWindowListener(af); // adaugarea ascultatorului de fereastra iug.addMouseListener(am); // adaugarea ascultatorului de mouse } }

Executnd acest program, putem urmri pe ecran succesiunea de evenimente care se produc atunci cnd acionm cu mouse-ul asupra ferestrei aplicaiei.

Evenimentul de mouse conine urmtoarele informaii: - tipul evenimentului (cmpul id); - coordonatele punctului n care s-a produs evenimentul; - modul n care s-a produs evenimentul, caracterizat printr-un numar ntreg, n care fiecare bit are o anumit semnificaie. Acest numr poate fi decodificat cu ajutorul mtilor existente n clasa java.awt.event.InputEvent; - contorul de click-uri (util cnd au loc mai multe clickuri succesive); - numrul de ordine al ferestrei (n ordinea n care ferestrele au fost creeate). Aceste informaii pot fi obinute folosind metodele i mtile din clasele java.awt.event.MouseEvent i java.awt.event.InputEvent. Exemplu n fiierul EvMouse1.java este dat un exemplu de aplicaie, n care se urmresc situaiile n care este apsat unul dintre butoanele mouse-ului, atunci cnd cursorul acestuia se gsete pe suprafaa ferestrei aplicaiei. ntruct nu se folosesc toate metodele interfeei MouseListener, clasa asculttorului de mouse AMouse s-a creat prin extinderea clasei java.awt.event.MouseAdapter.

211

Severin Bumbaru

import java.awt.*; import java.awt.event.*; import javax.swing.*; class EvMouse1 { static JFrame iug; // referinta la fereastra static AF af; // referinta la ascultator de fereastra static AMouse am; // referinta la ascultator de mouse /* Clasa imbricata pentru ascultatorul de fereastra */ static class AF extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); // incheierea executarii aplicatiei } } /* Clasa imbricata pentru ascultatorul de mouse */ static class AMouse extends MouseAdapter { public void mousePressed(MouseEvent e) { int x=e.getX(), y=e.getY(), n=e.getClickCount(), mod=e.getModifiers(), buton=0; String mesaj="S-a apasat butonul "; if((InputEvent.BUTTON1_MASK & mod) != 0) buton=1; else if((InputEvent.BUTTON2_MASK & mod) !=0) buton=2; else if((InputEvent.BUTTON3_MASK & mod) !=0) buton=3; mesaj+=buton+" x="+x+" y="+y+" contor="+n+" mod="+mod; if(e.isControlDown()) mesaj+=" Ctrl"; if(e.isAltDown()) mesaj+=" Alt"; if(e.isShiftDown()) mesaj+=" Shift"; System.out.println(mesaj); } } /* Metoda principala */ public static void main(String args[]) throws Exception { af=new AF(); // instantierea ascultatorului am=new AMouse(); // instantierea ascultatorului de mouse iug=new JFrame("Urmarire evenimente de mouse"); iug.setSize(300,100); iug.setLocation(new Point(100,50)); iug.setVisible(true); iug.addWindowListener(af); // adaugarea ascultatorului de fereastra iug.addMouseListener(am); // adaugarea ascultatorului de mouse } }

n metoda mousePressed() a clasei AMouse se determin coordonatele punctului n care s-e gsete cursorul la apsarea butonului, invocnd metodele getX() i getY() ale clasei MouseEvent. Se determin numrul de apsri succesive rapide, invocnd metoda getClickCount() a aceleeai clase. Pentru a afla ce buton a fost apsat, se procedeaz astfel: - se determin codul modificatorilor, invocnd metoda getModifiers() din clasa InputEvent; - se aplic asupra acestui cod mtile butoanelor, folosind operatorul de intersecie pe bii

212

Programarea orientata pe obiecte n limbajul Java

&. Butonul de mouse a crui masc, intersectat cu codul mod, d rezultat nenul este cel apsat. Codul modificatorilor mod poate fi folosit i pentru a determina daca, n timp ce s-a apsat butonul de mouse, era apsat i una din tastele auxiliare Ctrl, Alt sau Shift, folosind mtile corespunztoare acestor taste. Totui, aici s-a preferat utilizarea metodelor isControlDown(), isAltDown() i isShiftDown() ale clasei InputEvent. Toate mtile folosite n aceast aplicaie sunt definite n clasa java.awt.event.InputEvent.

Evenimente de tast
De cte ori se apas sau se elibereaz o tast, componenta activ a interfeei grafice genereaz un eveniment de tast din clasa java.awt.event.KeyEvent. Acesta poate fi tratat cu un "asculttor de taste" care implementeaz interfaa java.awt.event.KeyListener sau care extinde clasa java.awt.event.KeyAdapter. Se disting urmtoarele evenimente generate la acionarea tastelor: - a fost apasat o tast (KEY_PRESSED); - a fost eliberat o tast (KEY_RELEASED); - a fost "tiprit" un caracter, adic a fost apasat i eliberat o tast care transmite un caracter tipribil (KEY_TYPED). Aceste situaii pot fi detectate cu metodele corespunztoare ale interfeei KeyListener. Evenimentul generat de tast conine, n afar de codul tastei acionate, i informaii privind starea tastelor auxiliare Ctrl, Alt i Shift n momentul producerii evenimentului respectiv. Aceste stri pot fi detectate cu metodele corespunztoare ale interfeei superclasei java.awt.event.InputEvent.

Exemplu n fiierul EvTaste.java se d un exemplu de aplicaie, n care se urmrete apariia unor evenimente de tast, care sunt generate de fereastra aplicaiei, atunci cnd ea este activ i se actioneaz o tast.
import java.awt.*; import java.awt.event.*; import javax.swing.*; class EvTaste { static AF af=new AF(); // ascultatorul de fereastra static ATaste at=new ATaste(); // ascultatorul de taste static IUG iug=new IUG("Urmarirea evenimentelor de tasta"); /* Clasa imbricata pentru interfata utilizator */ static class IUG extends JFrame { /* Constructorul interfetei utilizator */

213

Severin Bumbaru

IUG(String titlu) { super(titlu); setSize(300,100); setLocation(new Point(100,50)); setVisible(true); addWindowListener(af); // adaugarea ascultatorului de fereastra addKeyListener(at); // adaugarea ascultatorului de taste } } /* Clasa imbricata pentru ascultatorul de fereastra */ static class AF extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); // incheierea executarii aplicatiei } } /* Clasa imbricata pentru ascultatorul de taste */ static class ATaste implements KeyListener { public void keyTyped(KeyEvent e) { System.out.println(e); } public void keyPressed(KeyEvent e) { System.out.println(e); } public void keyReleased(KeyEvent e) { System.out.println(e); } } /* Metoda principala */ public static void main(String args[]) { } }

Asculttorul de taste este realizat prin clasa imbricat ATaste, care implementeaz interfaa KeyListener. Aa cum sunt ele redefinite aici, metodele asculttorului de taste afieaz evenimentul respectiv la terminal. Punnd n execuie aceast aplicaie, putem urmri la terminal succesiunea evenimentelor care sunt generate atunci cnd acionam tastele. Remarcm, de asemenea, c aceste evenimente sunt generate numai atunci cnd fereastra aplicaiei este activ.

Pentru a detecta n ce condiii a fost generat evenimentul (codul tastei care a fost apasat, inscripia de pe tast, ce taste auxiliare erau apsate), putem utiliza metodele claselor KeyEvent i superclasei acesteia InputEvent.

Exemplu n fiierul EvTaste1.java este dat un exemplu de aplicaie n care se folosesc metodele din clasele KeyEvent i InputEvent pentru a detecta situaiile n care au aprut evenimentele captate de ctre asculttorul de taste. Acesta a fost realizat prin extinderea clasei

214

Programarea orientata pe obiecte n limbajul Java

KeyAdapter.
import java.awt.*; import java.awt.event.*; import javax.swing.*; class EvTaste1 { static AF af=new AF(); // ascultatorul de fereastra static ATaste at=new ATaste(); // ascultatorul de taste static IUG iug=new IUG("Urmarirea evenimentelor de tasta"); /* Clasa imbricata pentru interfata utilizator */ static class IUG extends JFrame { /* Constructorul interfetei utilizator */ IUG(String titlu) { super(titlu); setSize(300,100); setLocation(new Point(100,50)); setVisible(true); addWindowListener(af); // adaugarea ascultatorului de fereastra addKeyListener(at); // adaugarea ascultatorului de taste } } /* Clasa imbricata pentru ascultatorul de fereastra */ static class AF extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); // incheierea executarii aplicatiei } } /* Clasa imbricata pentru ascultatorul de taste */ static class ATaste extends KeyAdapter { public void keyPressed(KeyEvent e) { int cod=e.getKeyCode(), mod=e.getModifiers(); String mesaj="S-a apasat tasta de cod "+cod+" "+e.getKeyText(cod); if(mod!=0) mesaj+=" cu modificatorii: "+e.getKeyModifiersText(mod); System.out.println(mesaj); } public void keyTyped(KeyEvent e) { System.out.println("S-a introdus caracterul "+e.getKeyChar()); } } /* Metoda principala */ public static void main(String args[]) { } }

Punnd n execuie aceast aplicaie, putem urmri la terminal evenimentele de apsare a unei taste (KEY_PRESSED) i de introducere a unui caracter (KEY_TYPED) afiate sub form decodificat. Pentru detalii privind metodele disponibile n clasele KeyAdapter, KeyEvent i InputEvent se poate consulta documentaia Java API.

215

Severin Bumbaru

Adugarea unei componente la fereastra principal a aplicaiei


Pn n prezent, am artat c, atunci cnd folosim JFC/Swing, fereastra principal a aplicaiei este o instan a clasei javax.swing.JFrame sau a unei subclase a acesteia. Pentru a construi o interfa utilizator grafic este necesar ca n fereastra principal s introducem diverse componente. Acestea pot fi componente simple, ca etichete, butoane, casete de validare, cmpuri de text etc., sau pot fi containere, care conin - la rndul lor - alte componente. Pentru realizarea acestor componente simple i containere se folosesc clasele din pachetele java.awt i javax.swing, care sunt descrise n documentaia Java API. Adugarea de componente nu se face direct la instanele clasei JFrame. n JFrame exist un Container (un obiect dintr-o subclas a clasei Container) numit contentPane, la care se pot aduga componente. O referin la acest Container se obine prin metoda public Container getContentPane(), existent n clasa JFrame. Adugarea de componente se face prin una din metodele add() ale clasei Container. Dac, de exemplu, comp este referin la o component, atunci expresia getContentPane().add(comp), folosit ntr-o metod a clasei JFrame sau a subclaselor ei, adaug componenta comp la containerul contentPane coninut n JFrame. O prezentare succint a clasei JFrame este dat n Indexul de clase, iar cea complet se gsete n Java API, completat cu cea din Tutorialul Java.

Exemplul 1 n fiierul AdComp.java este un exemplu de aplicaie, n care se testeaz adugarea la fereastra principal a unui buton i se face contorizarea numrului de apsri pe butonul respectiv. n acest exemplu se arat: - cum se adaug la fereastra aplicaiei un buton (o instan a clasei JButton); - cum se trateaz evenimentele de aciune generate la apasarea butonului. n locul unui buton se putea folosi orice alt component.
import java.awt.*; import java.awt.event.*; import javax.swing.*; class AdComp { static String textButon="Numar de actionari: "; static int contorActionari=0; static AF af=new AF(); static AB ab=new AB(); static JButton buton=new JButton(textButon+contorActionari); static IUG iug=new IUG("Un buton de contorizare a apasarilor"); /* clasa imbricata pentru interfata utilizator grafica */

216

Programarea orientata pe obiecte n limbajul Java

static class IUG extends JFrame { IUG(String titlu) { // constructorul clasei IUG super(titlu); setSize(300, 80); setLocation(200, 150); getContentPane().add(buton); // adaugarea butonului addWindowListener(af); // adaugarea ascultatorului de fereastra buton.addActionListener(ab); // adaugarea ascult. de actiune setVisible(true); } } /* Clasa ascultatoare de fereastra */ static class AF extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); // incheierea executarii aplicatiei } } /* Clasa ascultatoare de actiuni asupra butonului */ static class AB implements ActionListener { public void actionPerformed(ActionEvent e) { contorActionari++; buton.setText(textButon+contorActionari); } } /* Metoda principala a aplicatiei */ public static void main(String args[]) { } }

Remarcm urmtoarele: - S-au declarat trei clase imbricate: . clasa IUG, care este interfaa utilizator grafic; . clasa AF, care este asculttorul evenimentelor de fereastr, necesar pentru nchiderea aplicaiei; . clasa AB, care asculta i trateaz evenimentele de aciune generate de buton. - n constructorul clasei IUG se adaug la containerul de coninut al ferestrei principale (contentPane) butonul button, din clasa JButton. n acest scop, se folosete instruciunea
getContentPane().add(buton);

- n acelai constructor, se adaug la buton asculttorul de evenimente de fereastr af i asculttorul de evenimente de aciune ab. Obiectele indicate de referinele buton af i ab au fost construite nainte de a se construi interfaa grafic. - Metoda actionPerformed(Event e) din clasa imbricat AB este invocat atunci cnd se produce un "eveniment de aciune". ntrucat n programul nostru sursa evenimentelor de aciune (la care a fost inregistrat instana ab a clasei AB) este butonul buton, evenimentele de aciune vor fi generate atunci cnd se apas pe buton (se face click de mouse pe suprafaa butonului). n aceast metod se incrementeaz variabila contorAcionri i se pune n buton un nou text, care indic valoarea contorului. n acest scop se folosete instruciunea buton.setText(text). Cnd punem n execuie aceast aplicaie, pe ecran apare o fereastr cu titlul "Un buton de

217

Severin Bumbaru contorizare a apsrilor", n interiorul creia se gsete un buton pe care apare inscripia "Numr de acionri: 0". De fiecare dat, cnd facem click de mouse pe acest buton, constatm c s-a modificat textul continut, indicand noua valoare a contorului de acionri. Exemplul 2 Folosirea unei clase de buton de contorizare proprie, derivat din clasa JButton Avnd n vedere ca butonul de contorizare a apsrilor poate fi, n principiu, folosit i n mai multe aplicaii, putem s l declarm ca o clasa public ntr-un fiier separat, ca n fiierul ButonContor.java, reprodus aici:

/* Buton care contorizeaza numarul de apasari si afiseaza acest numar pe suprafata sa, dupa numele butonului. In acest scop, butonul isi asculta propriile evenimente de actiune. */ import java.awt.event.*; import javax.swing.*; public class ButonContor extends JButton implements ActionListener { private int contor; // contorul de apasari private String nume; // numele butonului public ButonContor(String nume) { // constructorul butonului contor=0; this.nume=nume+" #"; setText(this.nume+contor); addActionListener(this); // butonul se asculta pe sine } public void actionPerformed(ActionEvent e) { contor++; setText(nume+contor); } public int numarApasari() { // se intoarce numarul de apasari return contor; } public void reset() { // se pune contorul la zero contor=0; setText(nume+contor); } }

n fiierul AdComp1.java se d o modificare a aplicaiei din exemplul precedent, n care, n locul unei instane a clasei JButton, se folosete o instan a clasei ButonContor. n acest caz nu a mai fost necesar s se creeze o clas de ascultare a butonului, ntruct butonul din clasa ButonContor se ascult pe el nsui.

import java.awt.event.*; import javax.swing.*;

218

Programarea orientata pe obiecte n limbajul Java

class AdComp1 { static AF af=new AF(); static ButonContor buton=new ButonContor("Contor apasari"); static IUG iug=new IUG("Un buton de contorizare a apasarilor"); /* clasa imbricata pentru interfata utilizator grafica */ static class IUG extends JFrame { IUG(String titlu) { // constructorul clasei IUG super(titlu); setSize(300, 80); setLocation(200, 150); getContentPane().add(buton); // adaugarea butonului addWindowListener(af); // adaugarea ascultatorului de fereastra setVisible(true); } } /* Clasa ascultatoare de fereastra */ static class AF extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); // incheierea executarii aplicatiei } } /* Metoda principala a aplicatiei */ public static void main(String args[]) { } }

Gestionarea poziionrii componentelor


Am artat n seciunea precedent cum se poate plasa ntr-un container (n particular ntr-un contentPane) o singur component. n mod normal ns, ntr-un comtainer se plaseaz mai multe componente. n acest caz, este foarte important s se stabileasc modul n care aceste componente sunt poziionate pe suprafaa containerului. n acest scop, a fost introdus conceptul de gestionar de poziionare (n englez: Layout Manager). Gestionarul de poziionare este o clas care asigur poziionarea i redimensionarea automat a componentelor situate ntr-un container, att la crearea containerului, ct i la modificarea dimensiunilor acestuia. Orice gestionar de poziionare implementeaz interfaa java.awt.LayoutManager sau subinterfaa acesteia java.awt.LauoutManager2. n cele ce urmeaz, vom studia cele mai larg utilizate clase de gestionare a poziionrii, existente n pachetele java.awt i javax.swing. Fiecare clas de container are un gestionar de poziionare implicit. Acesta este BorderLayout pentru Frame i JFrame.contentPane i FlowLayout pentru clasa Panel. Modificarea gestionarului de pozitionare se face prin metoda
public void setLayout(LayoutManager manager)

219

Severin Bumbaru din clasa java.awt.Container.

Clasa BorderLayout
ncepem cu aceast clas, deoarece este gestionarul de poziionare implicit pentru coninutul instanelor clasei JFrame. n acest caz, se consider c suprafaa containerului este imparit n cinci zone numite, respectiv, NORTH, SOUTH, WEST, EAST si CENTER. n fiecare din aceste zone se poate plasa numai o singur component, care poate fi ns ea nsi un container. Adugarea de componente la container se face, n acest caz, folosind metoda add(componenta, BorderLayout.ZONA), unde componenta este referina la componenta adaugat, iar ZONA este una din cele cinci zone menionate mai sus. Dac se folosete metoda add(componenta), fr a indica zona, componenta respectiv este plasat implicit n zona CENTER, aa cum s-a procedat n seciunea precedenta, n exemplul din fiierul AdComp.java. Exemplu n fiierul Butoane.java este dat un exemplu, n care se plaseaz n fereastra aplicaiei cte un buton n fiecare din zonele NORTH,WEST, CENTER i EAST i o etichet (instan a clasei javax.swing.JLabel) n zona SOUTH. Pe suprafaa fiecrui buton este afiat numrul de apsri succesive. n eticheta de la partea de jos se afieaz numrul total de acionri asupra tuturor butoanelor.
import java.awt.*; import java.awt.event.*; import javax.swing.*; class Butoane { static AF af=new AF(); // ascultatorul de fereastra static AA aa=new AA(); // ascultatorul de actiuni static IUG iug=new IUG("Adaugare de butoane"); static int totalActionari=0; static class IUG extends JFrame { JLabel lab=new JLabel("Actionati butoanele"); ButonContor b1, b2, b3, b4; IUG(String titlu) { super(titlu); Container cp=getContentPane(); setSize(400,300); setLocation(200,150); addWindowListener(af); b1=new ButonContor("N"); b1.addActionListener(aa); cp.add(b1, BorderLayout.NORTH); b2=new ButonContor("E"); b2.addActionListener(aa); cp.add(b2, BorderLayout.EAST); b3=new ButonContor("W"); b3.addActionListener(aa); cp.add(b3, BorderLayout.WEST); b4=new ButonContor("C");

220

Programarea orientata pe obiecte n limbajul Java

b4.addActionListener(aa); cp.add(b4, BorderLayout.CENTER); cp.add(lab, BorderLayout.SOUTH); setVisible(true); } } static class AA implements ActionListener { public void actionPerformed(ActionEvent e) { totalActionari++; iug.lab.setText("Total actionari: "+totalActionari); } } static class AF extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); } } public static void main(String args[]) { } }

Remarcm urmtoarele: - clasa ButonContor extinde clasa JButton i implementeaz interfaa ActionListener, fiind definit de noi ca o clasa public n fiierul ButonContor.java. n constructorul acestei clase exist instruciunea addActionListener(this), astfel c fiecare buton i ascult propriile evenimente de aciune; - n metoda actionPerformed(ActionEvent e) din clasa ButonContor se incrementeaz contorul intern al butonului respectiv i se afieaz valoarea contorului pe suprafaa butonului; - n constructorul clasei imbricate IUG se adaug cte un ButonContor n fiecare din zonele NORTH, WEST, EAST si CENTER ale ferestrei principale. - pentru a fi totalizat numrul de apsri al tuturor butoanelor, la fiecare buton se adaug, de asemenea, asculttorul de aciune ac, instan a clasei AC, care incrementeaz cmpul total al clasei Butoane; - eticheta din zona SOUTH face parte din clasa javax.swing.JLabel. Instanele acestei clase au ca principal rol afiarea pe suprafaa lor a unui text i/sau a unei pictograme. n exemplul nostru se afieaz numarul total de acionri ale butoanelor (valoarea cmpului total al clasei Butoane); - adugarea la fereastra aplicaiei a butoanelor i a etichetei se face n constructorul clasei IUG. Punnd n execuie aceast aplicaie, putem vedea cum se plaseaz cele cinci componente pe suprafaa ferestrei. Putem urmri, de asemenea, cum se modific automat dimensiunile componentelor atunci cnd modificm cu mouse-ul dimensiunile ferestrei. Dac facem click de mouse pe oricare din butoane, se modific att contorul afiat pe butonul respectiv, ct i numrul total de acionari afiat pe eticheta din partea inferioar a ferestrei.

221

Severin Bumbaru

Clasa FlowLayout
Gestionarul de poziionare java.awt.FlowLayout plaseaz componentele pe suprafaa containerului una dup alta, n ordinea n care acestea sunt adugate, de la stnga la dreapta i de sus n jos. Cnd s-a terminat o linie, se trece la linia urmtoare. Numrul de componente pe o linie depinde de limea componentelor i de limea containerului n care sunt acestea plasate. Este posibil s se specifice modul de aliniere a componentelor: la stnga, la dreapta sau la centru. Aceasta se face fie specificnd alinierea ca argument al constructorului, fie invocnd metoda
public void setAlignement(int align)

n care argumentul align poate fi FlowLayout.LEFT, FlowLayout.RIGHT sau FlowLayout.CENTER.

Exemplul 1 n fiierul ButoaneF.java este dat un exemplu de aplicaie, n care se testeaz gestionarul de poziionare FlowLayout. n fereastra aplicaiei sunt plasate mai multe butoane din clasa ButonContor i un buton de anulare a tuturor contoarelor. Numrul de butoane de contorizare este dat la punerea n execuie a aplicatiei, ca parametru n linia de comanda. Modificnd cu mouse-ul dimensiunile ferestrei, putem constata cum se modific n mod corespunzator dimensiunile i amplasarea butoanelor. truct la crearea gestionarului de poziionare nu s-a precizat alinierea componentelor, modul de aliniere este implicit CENTER.
/* Testarea gestionarului de pozitionare FlowLayout. In fereastra aplicatiei apar mai multe butoane din clasa ButonContor si un buton de anulare, a carui apasare anulaza toate contoarele. La lansarea in executie se da ca parametru in linia de comanda numarul de butoane de contorizare */ import java.awt.*; import java.awt.event.*; import javax.swing.*; class ButoaneF { static AF af=new AF(); // ascultatorul de fereastra static Anulare anulare=new Anulare(); // ascultatorul // butonului de anulare static IUG iug; // fereastra aplicatiei static int numarButoane; static class IUG extends JFrame { JLabel lab=new JLabel("Actionati butoanele"); ButonContor bc[]; JButton br=new JButton("Reset"); IUG(String titlu) { // constructorul ferestrei aplicatiei super(titlu);

222

Programarea orientata pe obiecte n limbajul Java

Container cp=getContentPane(); setSize(300,150); setLocation(200,150); addWindowListener(af); cp.setLayout(new FlowLayout()); // setarea gestionarului // de pozitionare bc=new ButonContor[numarButoane]; for(int i=0; i<numarButoane; i++) { bc[i]=new ButonContor("B"+(i+1)); // crearea butoanelor cp.add(bc[i]); // adaugarea butoanelor la contentPane } cp.add(br); // adaugarea butonului de anulare br.addActionListener(anulare); // adaugarea ascultatorului setVisible(true); } } static class AF extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); } } static class Anulare implements ActionListener { public void actionPerformed(ActionEvent e) { for(int i=0; i<numarButoane; i++) iug.bc[i].reset(); } } public static void main(String args[]) throws Exception { if(args.length!=1) { System.out.println("Utilizare: java ButoaneF <numarButoane>"); System.exit(1); } numarButoane=Integer.parseInt(args[0]); // crearea tabloului de // butoane iug=new IUG("FlowLayout cu "+numarButoane+ " butoane de contorizare"); // crearea ferestrei aplicatiei } }

Remarcm c aplicaia ButoaneF este o modificare a aplicaiei Butoane din fiierul Butoane.java i se deosebete de aceasta prin urmtoarele: - n metoda main se preia un argument din linia de comand, care trebuie s fie numrul de butoane de acionare solicitat de utilizator, dup care se construiete fereastra aplicaiei; - s-a introdus tabloul bc[] care conine referine la instanele clasei ButonContor. Att acest tablou, ct i butoanele respective, se creeaz n constructorul clasei IUG; - dup adugarea butoanelor de contorizare, se adaug la fereastra aplicaiei butonul de anulare br, din clasa JButton; - pentru ascultarea acionrii butonului de anulare, a fost declarat clasa imbricat Anulare, care implementeaz interfaa ActionListener.

223

Severin Bumbaru Exemplul 2 n fiierul Aliniere.java este dat o modificare a aplicaiei din exemplul precedent, n care sau introdus trei butoane suplimentare, care au ca efect modificarea alinierii butoanelor pe suprafaa containerului. n acest scop: - Pentru a se afla care buton a fost acionat, n metoda actionPerformed() a clasei imbricate de ascultare a evenimentelor de aciune Actiuni s-a invocat metoda getActionCommand()a clasei ActionEvent. Aceast metod ntoarce un String care, n mod obisnuit, este textul de pe butonul respectiv. Este posibil, totui, s se modifice acest ir folosind metoda setActionCommand(String command), care exist n toate clasele care genereaz evenimente de aciune, de exemplu n clasa AbstractButton, din care este derivat i clasa JButton. - Modificarea alinierii se face invocnd pentru gestionarul de poziionare metoda setAlignment(int align) a clasei FlowLayout. Dupa ce s-a aplicat aceast metod, se invoc pentru coninutul ferestrei (contentPane) metoda doLayout() a clasei Container, pentru a se aplica efectiv noua poziionare.
/* Testarea alinierii componentelor cand se foloseste gestionarul de pozitionare FlowLayout. In fereastra aplicatiei apar mai multe butoane din clasa ButonContor, trei butoane de aliniere si un buton de anulare. La lansarea in executie se da ca parametru in linia de comanda numarul de butoane de contorizare Actionarea unuia din butoanele de aliniere are ca efect modificarea corespunzatoare a alinierii componentelor pe suprafata containerului Actionarea butonului de anulare produce anuloarea tuturor contoarelor. */ import java.awt.*; import java.awt.event.*; import javax.swing.*; class Aliniere { static AF af=new AF(); // ascultatorul de fereastra static Actiuni actiuni=new Actiuni(); // ascultatorul // butoanelor de aliniere si de anulare static IUG iug; // fereastra aplicatiei static int numarButoane; static FlowLayout layout=new FlowLayout(); static class IUG extends JFrame { JLabel lab=new JLabel("Actionati butoanele"); ButonContor bc[]; JButton br=new JButton("Anulare"); JButton bas=new JButton("Stanga"), bac=new JButton("Centru"), bad=new JButton("Dreapta"); IUG(String titlu) { // constructorul ferestrei aplicatiei super(titlu);

224

Programarea orientata pe obiecte n limbajul Java

Container cp=getContentPane(); setSize(300,150); setLocation(200,150); addWindowListener(af); cp.setLayout(layout); // setarea gestionarului de pozitionare bc=new ButonContor[numarButoane]; for(int i=0; i<numarButoane; i++) { bc[i]=new ButonContor("B"+(i+1)); // crearea butoanelor cp.add(bc[i]); // adaugarea butoanelor la contentPane } cp.add(bas); cp.add(bac); cp.add(bad); // adaugare butoane // de aliniere cp.add(br); // adaugarea butonului de anulare br.addActionListener(actiuni); // adaugarea ascultatorului bas.addActionListener(actiuni); bac.addActionListener(actiuni); bad.addActionListener(actiuni); setVisible(true); } } static class AF extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); } } static class Actiuni implements ActionListener { public void actionPerformed(ActionEvent e) { String comanda=e.getActionCommand(); if(comanda.equals("Anulare")) for(int i=0; i<numarButoane; i++) iug.bc[i].reset(); else { if(comanda.equals("Stanga")) layout.setAlignment(FlowLayout.LEFT); else if(comanda.equals("Centru")) layout.setAlignment(FlowLayout.CENTER); else if(comanda.equals("Dreapta")) layout.setAlignment(FlowLayout.RIGHT); iug.getContentPane().doLayout(); } } } public static void main(String args[]) throws Exception { if(args.length!=1) { System.out.println("Utilizare: java Aliniere <numarButoane>"); System.exit(1); } numarButoane=Integer.parseInt(args[0]); // crearea tabloului de // butoane iug=new IUG("FlowLayout cu "+numarButoane+ " butoane de contorizare"); // crearea ferestrei aplicatiei } }

225

Severin Bumbaru

Clasa GridLayout
Gestionarele de poziionare din clasa java.awt.GridLayout plaseaz componentele n celulele unei grile rectangulare. n consecin, toate componentele de pe aceeai coloan sunt aliniate vertical. Clasa are doi constructori:
public GridLayout(int rows, int cols)

- are ca argumente numrul de linii i de - are n plus ca

coloane al grilei;
public GridLayout(int rows, int cols, int hgap, int vgap)

argumente spaiul orizontal i, respectiv, vertical ntre componente. Dei n constructor se indic att numrul de linii, ct i cel de coloane ale grilei, n realitate numai numrul de linii este respectat, n timp ce numrul de coloane este practic ignorat. La stabilirea amplasrii componentelor n container, dac numarul lor total este mai mic sau egal cu cel de linii, toate componentele vor fi aezate vertical, una sub alta. Dac numrul de componente este mai mare dect numrul de linii, numrul de coloane se stabilete automat, prin mprirea numrului de componente la cel de linii, cu rotunjire n plus. Plasarea efectiv a componentelor n celulele grilei astfel creeate se face apoi de la stnga la dreapta i de sus in jos, la fel ca n cazul gestionarului FlowLayout, dar respectnd alinierea vertical i orizontal impus de gril.

Exemplu n fiierul Grila.java se d un exemplu de aplicaie, n care se testeaz gestionarul de poziionare GridLayout. La punerea n execuie a aplicaiei, se dau ca parametri n linia de comand numrul total de butoane de contorizare, numrul de linii al grilei i numrul de coloane. Se poate observa ordinea n care sunt butoanele aezate pe gril i modul n care se schimb aspectul ferestrei, dac se modific cu mouse-ul dimensiunile acesteia. Se poate verifica i ce se ntmpl dac numrul de coloane dat ca parametru este mai mic sau mai mare dect cel necesar.
/* Testarea alinierii componentelor cand se foloseste gestionarul de pozitionare GridLayout. In fereastra aplicatiei apar mai multe butoane din clasa ButonContor si un buton de anulare. Punerea in executie a aplicatiei se face prin comanda java Grila <numarContoare> <nrLinii> <nrColoane> Actionarea butonului de anulare produce anuloarea tuturor contoarelor. */ import java.awt.*; import java.awt.event.*; import javax.swing.*; class Grila { static AF af=new AF(); // ascultatorul de fereastra

226

Programarea orientata pe obiecte n limbajul Java

static Actiuni actiuni=new Actiuni(); // ascultatorul // butonului de anulare static IUG iug; // fereastra aplicatiei static int numarButoane, nrLinii, nrColoane; static class IUG extends JFrame { JLabel lab=new JLabel("Actionati butoanele"); ButonContor bc[]; JButton br=new JButton("Anulare"); IUG(String titlu) { // constructorul ferestrei aplicatiei super(titlu); Container cp=getContentPane(); setSize(400,250); setLocation(200,150); addWindowListener(af); cp.setLayout(new GridLayout(nrLinii, nrColoane)); // setarea // gestionarului de pozitionare bc=new ButonContor[numarButoane]; for(int i=0; i<numarButoane; i++) { bc[i]=new ButonContor("B"+(i+1)); // crearea butoanelor cp.add(bc[i]); // adaugarea butoanelor la contentPane } cp.add(br); // adaugarea butonului de anulare br.addActionListener(actiuni); // adaugarea ascultatorului setVisible(true); } } static class AF extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); } } static class Actiuni implements ActionListener { public void actionPerformed(ActionEvent e) { String comanda=e.getActionCommand(); if(comanda.equals("Anulare")) for(int i=0; i<numarButoane; i++) iug.bc[i].reset(); } } public static void main(String args[]) throws Exception { /* Verificarea numarului de argumente din linia de comanda */ if(args.length!=3) { System.out.println( "Utilizare: java <numarButoane> <nrLinii> <nrColoane>"); System.exit(1); } /* Preluarea argumentelor din linia de comanda */ numarButoane=Integer.parseInt(args[0]); nrLinii=Integer.parseInt(args[1]); nrColoane=Integer.parseInt(args[2]); /* Crearea ferestrei aplicatiei */ iug=new IUG("GridLayout cu "+numarButoane+ " butoane de contorizare"); } }

227

Severin Bumbaru

Clasa BoxLayout
Gestionarul de poziionare javax.swing.BoxLayout plaseaz toate componentele containerului pe o singur direcie, care poate fi orizontal sau vertical. Constructorul clasei este
public BoxLayout(Container target, int axis) n care target este o referina la containerul int (al crui gestionar de poziionare este creat), iar axis poate fi BoxLayout.X_AXIS sau BoxLayout.Y_AXIS i indic direcia (axa)

dup care vor fi plasate componentele.

Exemplul 1 n fiierul ButoaneBox.java se d un exemplu de aplicaie, n care se testeaz clasa BoxLayout. n acest caz, gestionarul BoxLayout a fost folosit direct n containerul contentPane al ferestrei aplicaiei. La lansarea aplicaiei n execuie, se indic numrul de butoane de contorizare i direcia dup care acestea vor fi plasate (x sau y). Se poate urmri efectul modificrii cu mouse-ul a dimensiunilor ferestrei. Se observ c dimensiunile componentelor rmn constante, fr a mai fi influenate de dimensiunile ferestrei.
/* Testarea gestionarului de pozitionare BoxLayout. In fereastra aplicatiei apar mai multe butoane din clasa ButonContor si un buton de anulare, a carui apasare anulaza toate contoarele. La lansarea in executie se da ca parametru in linia de comanda numarul de butoane de contorizare si numele axei in lungul careia vor fi plasate componentele (X sau Y). De exemplu, comanda java ButoaneBox 5 Y are ca efecte punerea in executie a aplicatiei cu 5 butoane contor si un buton de anulare, toate plasate unul sub altul */

import java.awt.*; import java.awt.event.*; import javax.swing.*; class ButoaneBox { static AF af=new AF(); // ascultatorul de fereastra static Anulare anulare=new Anulare(); // ascultatorul // butonului de anulare static IUG iug; // fereastra aplicatiei static int numarButoane; static int axa; static class IUG extends JFrame { JLabel lab=new JLabel("Actionati butoanele");

228

Programarea orientata pe obiecte n limbajul Java

ButonContor bc[]; JButton br=new JButton("Reset"); IUG(String titlu) { // constructorul ferestrei aplicatiei super(titlu); Container cp=getContentPane(); setSize(350,350); setLocation(200,150); addWindowListener(af); cp.setLayout(new BoxLayout(getContentPane(), axa)); bc=new ButonContor[numarButoane]; for(int i=0; i<numarButoane; i++) { bc[i]=new ButonContor("B"+(i+1)); // crearea butoanelor cp.add(bc[i]); // adaugarea butoanelor la contentPane } cp.add(br); // adaugarea butonului de anulare br.addActionListener(anulare); // adaugarea ascultatorului setVisible(true); } } static class AF extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); } } static class Anulare implements ActionListener { public void actionPerformed(ActionEvent e) { for(int i=0; i<numarButoane; i++) iug.bc[i].reset(); } } public static void main(String args[]) throws Exception { if(args.length!=2 ) { System.out.println( "Utilizare: java ButoaneBox <numarButoane> <axa>"); System.exit(1); } String numeAxa=args[1].toUpperCase(); if(numeAxa.equals("Y")) axa=BoxLayout.Y_AXIS; else if(numeAxa.equals("X")) axa=BoxLayout.X_AXIS; else { System.out.println("Axa nu poate fi decat X sau Y"); System.exit(1); } numarButoane=Integer.parseInt(args[0]); iug=new IUG("BoxLayout cu "+numarButoane+ " butoane de contorizare"); } }

n loc de a folosi gestionarul BoxLayout ntr-un container oarecare, se prefer s se foloseasca clasa javax.swing.Box, care are acest gestionar implicit.

229

Severin Bumbaru Exemplul 2 n fiierul TestBox.java se d o variant a aplicaiei din exemplul precedent, n care se utilizeaz drept container pentru butoane o instan a clasei Box. n constructorul ferestrei aplicaiei, dup ce se creeaza aceast instan a clasei Box, se adaug la ea succesiv toate componentele, dup care este ea nsi adaugat la coninutul ferestrei aplicaiei (la contentPane). n aceast situaie, gestionarul de poziionare BoxLayout este folosit prin intermediul instanei clasei Box, n care sunt plasate componentele.
/* Testarea clasei javax.swing.Box In fereastra aplicatiei apar mai multe butoane din clasa ButonContor si un buton de anulare, a carui apasare anulaza toate contoarele. La lansarea in executie se da ca parametru in linia de comanda numarul de butoane de contorizare si numele axei in lungul careia vor fi plasate componentele (X sau Y). De exemplu, comanda java TestBox 5 Y are ca efecte punerea in executie a aplicatiei cu 5 butoane contor si un buton de anulare, toate plasate unul sub altul */

import java.awt.*; import java.awt.event.*; import javax.swing.*; class TestBox { static AF af=new AF(); // ascultatorul de fereastra static Anulare anulare=new Anulare(); // ascultatorul // butonului de anulare static IUG iug; // fereastra aplicatiei static int numarButoane; static int axa; static class IUG extends JFrame { JLabel lab=new JLabel("Actionati butoanele"); ButonContor bc[]; JButton br=new JButton("Reset"); Box box; IUG(String titlu) { // constructorul ferestrei aplicatiei super(titlu); setSize(350,350); setLocation(200,150); addWindowListener(af); box=new Box(axa); // se creeaza o instanta a clasei Box // orientata pe directia axa bc=new ButonContor[numarButoane]; for(int i=0; i<numarButoane; i++) { bc[i]=new ButonContor("B"+(i+1)); // crearea butoanelor box.add(bc[i]); // adaugarea butoanelor la caseta box } box.add(br); // adaugarea butonului de anulare br.addActionListener(anulare); // adaugarea ascultatorului getContentPane().add(box); // adaugarea casetei box la

230

Programarea orientata pe obiecte n limbajul Java

// contentPane setVisible(true); } } static class AF extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); } } static class Anulare implements ActionListener { public void actionPerformed(ActionEvent e) { for(int i=0; i<numarButoane; i++) iug.bc[i].reset(); } } public static void main(String args[]) throws Exception { if(args.length!=2 ) { System.out.println( "Utilizare: java Box <numarButoane> <axa>"); System.exit(1); } String numeAxa=args[1].toUpperCase(); if(numeAxa.equals("Y")) axa=BoxLayout.Y_AXIS; else if(numeAxa.equals("X")) axa=BoxLayout.X_AXIS; else { System.out.println("Axa nu poate fi decat X sau Y"); System.exit(1); } numarButoane=Integer.parseInt(args[0]); iug=new IUG("Box cu "+numarButoane+ " butoane de contorizare"); } }

Poziionarea absolut a componentelor n container


n general, este recomandabil ca pentru amplasarea componentelor n containere s se foloseasc gestionari de poziionare. n acest fel se asigur modificarea automat a poziiei i dimensiunilor componentelor, atunci cnd se modific dimensiunile containerului. Exist totui situaii, n care se prefer ca poziiile i dimensiunile componentelor s fie fixe i s fie indicate prin program. Din aceast cauz, n afar de amplasarea flexibil a componentelor n containere, folosind clasele de gestionare a poziionrii, este posibil s se proiecteze i interfee grafice n care poziionarea componentelor se face folosind coordonatele i dimensiunile absolute ale acestora. n acest scop: a/ pentru a se indica faptul c nu se folosete un gestionar de poziionare, se recurge la instruciunea: setLayout(null); b/ pentru stabilirea coordonatelor colului din stnga sus i dimensiunilor fiecrei componente se folosete metoda
public void setBounds(int x, int y, int width, int height);

231

Severin Bumbaru din clasa java.awt.Component. n acest mod, fiecare component este plasat n container cu colul stnga-sus n punctul de coordonate (x,y)i are dimensiunile date prin limea width i nlimea height. n locul metodei setBounds se pot folosi i metodele
public void setLocation(Point location) public void setSize(int latime, int inaltime)

care exist, de asemenea, n clasa Component i permit setarea separat a poziiei i dimensiunilor componentelor. Poziia i dimensiunile astfel stabilite ale componentelor rmn neschimbate, chiar dac se modific dimensiunile containerului care le conine.

Exemplu: n fiierul PozAbs.java se d un exemplu de aplicaie, n care se recurge la poziionarea absolut a componentelor pe suprafaa ferestrei principale a aplicaiei, care este o instan a clasei JFrame. n fereastr (mai exact n containerul contentPane al ferestrei) se plaseaz urmtoarele componente: - o etichet cu textul "Butoane de contorizare"; - patru butoane de contorizare ale clasei ButonContor, creat de noi anterior; - o etichet cu textul "Anularea tuturor contoarelor >>>"; - un buton din clasa JButton cu inscriptia "Reset", care servete aici pentru a comanda punerea la zero a tuturor contoarelor. Pentru a realiza poziionarea absolut a acestor componente, se seteaza la null gestionarul de poziionare al containerului contentPane coninut n fereastra aplicaiei, iar pentru fiecare component se indic poziia i dimensiunile, invocnd metoda setBounds().

/* Pozitionarea absoluta a componentelor in container */ import java.awt.*; import java.awt.event.*; import javax.swing.*; class PozAbs { static AF af=new AF(); // ascultatorul de fereastra static AA aa=new AA(); // ascultatorul de actiuni static IUG iug=new IUG("Pozitionare absoluta"); static class IUG extends JFrame { JLabel et1=new JLabel("Butoane de contorizare"); JLabel et2=new JLabel("Anularea tuturor contoarelor >>>"); JButton br=new JButton("Reset"); int numarContoare=4; ButonContor bc[]=new ButonContor[numarContoare]; /* Constructorul ferestrei aplicatiei */

232

Programarea orientata pe obiecte n limbajul Java

IUG(String titlu) { super(titlu); Container cp=getContentPane(); setSize(420,220); setLocation(200,150); addWindowListener(af); cp.setLayout(null); // se elimina gestionarul de pozitionare din // contentPane et1.setBounds(150, 5, 160,10); // pozitia si dimensiunile etichetei cp.add(et1); // adaugarea etichetei for(int i=0; i<numarContoare; i++) { bc[i]=new ButonContor("B"+i); // crearea butoanelor-contor bc[i].setBounds(10+100*i, 20, 90,70); // stabilirea pozitiei // si dimensiunilor butoanelor-contor cp.add(bc[i]); // adaugarea butoanelor-contor la contentPane } et2.setBounds(10, 140, 200,10); // locul si dimens. etichetei 2 cp.add(et2); // adaugarea etichetei 2 la contentPane br.setBounds(210, 120, 70, 60); // pozitia si dimensiunile // butonului de anulare br.addActionListener(aa); // ascultarea butonului de anulare cp.add(br); // adaugarea butonului de anulare la contentPane setVisible(true); } } /* Ascultatorul actiunilor butonului de anulare. Cand este apasat acest buton, se pun la zero toate contoarele */ static class AA implements ActionListener { public void actionPerformed(ActionEvent e) { for(int i=0; i<iug.numarContoare; i++) iug.bc[i].reset(); } } /* Ascultarea evenimentelor de fereastra */ static class AF extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); } } public static void main(String args[]) { } }

Gruparea componentelor
Pentru a poziiona componentele n structuri mai complicate dect cele oferite de clasele de gestionare a poziiei existente, se poate recurge la gruparea mai multor componente n containere auxiliare, care se plaseaz apoi n containerul principal. Drept containere auxiliare, se folosesc cel mai frecvent instane ale claselor java.awt.Panel, javax.swing.JPanel i javax.swing.Box.

233

Severin Bumbaru

Clasele Panel si Jpanel


Clasa java.awt.Panel (panou) reprezinta cel mai simplu container, care este o suprafa dreptunghiular fr bordur. Gestionarul de poziionare implicit este FlowLayout, dar se poate pune oricare altul. Panourile sunt frecvent folosite pentru a plasa pe ele diferite componente, formnd un grup care se plaseaza apoi ntr-un alt container. Clasa javax.swing.JPanel este varianta de Panel folosit n JFC/Swing, fiind un container genreric. Exemplu n fiierul Panouri.java este dat un exemplu n care fereastra aplicaiei, cu gestionar de pozitionare GridLayout, conine n cele patru celule ale reelei dou panouri i dou butoane de anulare. Un panou conine 5 butoane de contorizare amplasate cu gestionar BorderLayout, iar alt panou conine trei butoane de contorizare amplasate cu FlowLayout (gestionarul implicit). Fiecare buton de anulare pune la zero contoarele de apsri dintr-un panou.

import java.awt.*; import java.awt.event.*; import javax.swing.*; class Panouri { static ButonContor bc[]=new ButonContor[8]; static JButton br1=new JButton("Reset 1"), br2=new JButton("Reset 2"); static Anulare anulare=new Anulare(); static IUG iug=new IUG("Gruparea componentelor pe panouri"); static class IUG extends JFrame { JPanel p1=new JPanel(); // p1 are implicit FlowLayout JPanel p2=new JPanel(new BorderLayout()); // p2 primeste BorderLayout IUG(String titlu) { super(titlu); Container cp=getContentPane(); setSize(500,400); addWindowListener(new AF()); cp.setLayout(new GridLayout(2,2)); /* Crearea butoanelor */ for(int i=0; i<8; i++) bc[i]=new ButonContor("B"+i); /* Completarea cu butoane a panoului p2 */ p2.add(bc[0], BorderLayout.NORTH); p2.add(bc[1], BorderLayout.WEST); p2.add(bc[2], BorderLayout.CENTER); p2.add(bc[3], BorderLayout.EAST); p2.add(bc[4], BorderLayout.SOUTH); /* Completarea panoului p1 */ for(int i=5; i<8; i++) p1.add(bc[i]); /* Adaugarea de ascultatori la butoanele de anulare */ br1.addActionListener(anulare); br2.addActionListener(anulare); /* Adaugarea de panouri si butoane la controlPane */ cp.add(p2); cp.add(p1); cp.add(br1);

234

Programarea orientata pe obiecte n limbajul Java

cp.add(br2); setVisible(true); } } static class AF extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); } } static class Anulare implements ActionListener { public void actionPerformed(ActionEvent e) { String actiune=e.getActionCommand(); if(actiune.equals(br1.getText())) for(int i=0; i<5; i++) bc[i].reset(); else if(actiune.equals(br2.getText())) for(int i=5; i<8; i++) bc[i].reset(); } } public static void main(String args[]) { } }

Clasa Box
Clasa javax.swing.Box are ca instane containere speciale, care nu pot folosi dect gestionarul de poziionare javax.swing.BoxLayout. Orice incercare de a-i pune alt gestionar produce o eroare de execuie din clasa AWTError. ntr-un container din clasa Box, componentele pot fi amplasate numai pe o singur direcie: orizontal sau vertical.

Clasa dispune de metode statice pentru crearea de "casete" (instane ale clasei Box) orizontale sau verticale:
public static Box createHorizontalBox() public static Box createVerticalBox()

Se pot creea, de asemenea "componente invizibile" de dimensiuni fixe sau variabile, care pot fi folosite la distanarea componentelor vizibile. n acest scop, se folosesc metodele public static Component createRigidArea(Dimension d) - creeaza o "component ascuns" de dimensiune fix; public static Component createHorizontalStrut(int width) - creeaza o "component ascuns" de lime fix, dar de nlime variabil; public static Component createVerticalStrut(int height) - creeaza o "component ascuns" de nalime fix, dar de lime variabil; public static Component createGlue() - creaza o "component ascuns" cu ambele dimensiuni variabile;

235

Severin Bumbaru Combinarea adecvat de containere din clasa Box i folosirea n acestea a diferitelor componente vizibile i ascunse permite crearea de interfee grafice cu aspecte foarte diversificate.

Exemplu n fiierul Casete.java este dat o aplicaie n care se folosesc trei casete din clasa Box: dou verticale i una orizontal.

/* Exemplu de utilizare a containerelor din clasa javax.swing.Box */ import java.awt.*; import java.awt.event.*; import javax.swing.*; class Casete { static ButonContor bc[]=new ButonContor[5]; static JButton br1=new JButton("Reset 1"), br2=new JButton("Reset 2"); static Anulare anulare=new Anulare(); static IUG iug=new IUG("Gruparea componentelor in casete"); static class IUG extends JFrame { Box c1=Box.createVerticalBox(); Box c2=Box.createVerticalBox(); Box c3=Box.createHorizontalBox(); IUG(String titlu) { super(titlu); setSize(280,160); addWindowListener(new AF()); /* Crearea butoanelor */ for(int i=0; i<5; i++) bc[i]=new ButonContor("B"+i); /* Completarea cu butoane a casetei c1 */ c1.add(Box.createVerticalStrut(18)); // deplasare in jos c1.add(bc[0]); c1.add(bc[1]); c1.add(Box.createVerticalStrut(10)); // deplasare in jos c1.add(br1); /* Completarea casetei c2 */ for(int i=2; i<5; i++) c2.add(bc[i]); c2.add(Box.createVerticalStrut(5)); // deplasare in jos c2.add(br2); /* Adaugarea de ascultatori la butoanele de anulare */ br1.addActionListener(anulare); br2.addActionListener(anulare); /* Adaugarea casetelor c1 si c2 la caseta c3 */ c3.add(Box.createGlue()); // pentru alinierea la centru c3.add(c1); c3.add(Box.createHorizontalStrut(10)); c3.add(c2); /* Adaugarea casetei c3 la contentPane */ getContentPane().add(c3); setVisible(true);

236

Programarea orientata pe obiecte n limbajul Java

} } static class AF extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); } } static class Anulare implements ActionListener { public void actionPerformed(ActionEvent e) { String actiune=e.getActionCommand(); if(actiune.equals(br1.getText())) for(int i=0; i<2; i++) bc[i].reset(); else if(actiune.equals(br2.getText())) for(int i=2; i<5; i++) bc[i].reset(); } } public static void main(String args[]) { } }

Remarcm urmtoarele: - butoanele au fost plasate n cele dou casete verticale, c1 i c2; - ntruct numrul de butoane din cele dou casete este diferit, n caseta c1 s-a introdus o component ascuns pentru alinierea la partea inferioar. De asemenea, n ambele casete verticale s-au introdus n faa ultimului buton componente ascunse pentru distanare; - cele dou casete verticale au fost introduse n cea orizontal; - componenta ascuns cu dimensiuni variabile, introdus n faa primei casete din c3, a fost pus pentru a se obine alinierea pe centru a casetelor c1 i c2. n lipsa acesteia, caseta c1 ar fi fost aliniat la stnga; - caseta c3 a fost introdus n contentPane. Urmrii ce se ntmpl cnd modificai cu mouse-ul dimensiunile ferestrei aplicaiei.

ntrebri
Nivel 1
1. 2. 3. 4. 5. 6. 7. 8. 9. Ce este interfaa utilizator? Ce este interfaa utilizator grafic? Ce sunt obiectele grafice? Ce este AWT? Ce este JFC/Swing? Ce rol are clasa Component i din ce pachet face parte? Ce deosebire este ntre componentele atomice i containere? Care este clasa folosit n JFC/Swing pentru fereastra principal a aplicaiei? Ce conin la partea superioar instanele clasei JFrame?

237

Severin Bumbaru 10. Ce sunt evenimentele n cazul interfeei utilizator grafice? 11. Ce este programarea orientat pe evenimente? 12. Care este modelul de evenimente folosit pe platforma Java 2? 13. Cum sunt generate evenimentele? 14. Cum sunt utilizate evenimentele? 15. Ce deosebire este ntre evenimentele de nivel jos i cele semantice? 16. Care este rdcina claselor de evenimente generate de obiectele interfeei grafice? 17. Ce clase de evenimente cunoastei? 18. n ce pachete se gsesc clasele de evenimente? 19. Ce sunt interfeele pentru ascultarea de evenimente i la ce folosesc? 20. Care este rolul unei clase asculttoare de evenimente? 21. Ce este un adaptor pentru ascultarea de evenimente? 22. Cum poate fi comandat prin interfaa utilizator grafic ncheierea executrii aplicaiei? 23. Care este componenta instanei clasei JFrame la care se adaug componentele interfeei grafice? 24. Ce este un gestionar de poziionare? 25. Care sunt interfeele gestionarilor de poziionare? 26. Care este gestionarul de poziionare implicit pentru contentPane? 27. Care este gestionarul de poziionare implicit pentru Panel i JPanel? 28. Cum sunt amplasate componentele n cazul gestionarului BorderLayout? 29. Cum sunt amplasate componentele n container n cazul gestionarului FlowLayout? 30. Cum sunt aliniate componentele n cazul gestionarului FlowLayout? 31. Ce fel de evenimente genereaz un buton? 32. Cum sunt amplasate componentele n cazul gestionarului GridLayout? 33. Cum se stabileste numarul de linii i de coloane pentru gestionarul GridLayout? 34. Cum sunt plasate componentele ntr-un BoxLayout?

Nivel 2
1. Ce categorii de interfee utilizator cunoastei? 2. Ce este un limbaj de comand i ce astfel de limbaje cunoastei? 3. Care sunt n prezent cele mai larg folosite interfee utilizator grafice? 4. Prin ce pachete se realizeaz AWT pe platformele Java? 5. Prin ce pachete se realizeaz JFC/Swing pe platforma Java 2? 6. In ce const deosebirea de abordare ntre AWT i JFC/Swing? 7. Ce metode ale clasei Component cunoastei? 8. Ce metode ale clasei JFrame cunoastei? 9. Cum este ghidat procesul de calcul n programarea procedural tradiional? 10. Cine are iniiativa aciunilor n programarea orientat pe evenimente? 11. Care sunt obiectele care intervin atunci cnd se genereaz un eveniment? 12. Ce sunt evenimentele de mouse i cum sunt ele generate? 13. Ce sunt evenimentele de tast i cum sunt ele generate? 14. Care sunt evenimentele generate de o fereastr i cum sunt ele ascultate? 15. Care sunt evenimentele de mouse? 16. Cum sunt ascultate evenimentele de mouse? 17. Care sunt evenimentele de tasta? 18. Cum sunt ascultate evenimentele de tasta? 19. n ce stare trebuie sa fie fereastra pentru a genera evenimente de tast?

238

Programarea orientata pe obiecte n limbajul Java 20. n ce clas exist metoda getContentPane() i la ce folosete? 21. Cum se adaug un asculttor la o surs? 22. Poate un obiect grafic s-i asculte propriile evenimente? Cum se programeaz aceasta? 23. Care sunt zonele unui BorderLayout i cte componente pot fi plasate n fiecare zon? 24. Ce se ntmpl cu componentele unui container cu gestionar BorderLayout dac se modific dimensiunile acestuia? 25. Dac ntr-un container exist mai multe butoane, cum se poate afla care din ele a fost acionat atunci cnd este receptat un eveniment de aciune? 26. Ce se ntmpl cu componentele unui container cu gestionar FlowLayout, dac se modific laimea acestuia? 27. Ce se ntmpl n cazul gestionarului GridLayout, dac numarul de componente coninute este mai mare dect numrul de celule ale grilei stabilite la crearea containerului? 28. n ce ordine se plaseaz componentele adugate la un container cu gestionar GridLayout? 29. Ce legatur exist ntre clasele Box i BoxLayout? 30. Ce se nelege prin poziionarea absolut a componentelor? 31. Cum se seteaz gestionarul de poziionare pentru a realiza poziionarea absolut? 32. Ce metode se folosesc pentru poziionarea absolut a componentelor? 33. Ce fel de containere auxiliare se folosesc pentru gruparea componentelor? 34. Ce este un Panel sau un JPanel? 35. Ce reprezint clasa Box? 36. Cum pot fi create instanele clasei Box? 37. Ce componente ascunse se pot pune ntr-un container din clasa Box?

239

Severin Bumbaru

Componente grafice din JFC/Swing


Componente ale interfeei utilizator grafice Clasa JComponent Componente de control Butoane Clasa AbstractButton Butoane obinuite (cu o singur stare stabil) Butoane cu dou stri stabile Casete de validare Butoane radio Liste Liste ascunse Cmpuri de text Rigle cu cursor Meniuri Meniuri cu bar Meniuri volante Componente de afiare Componente de afiare needitabile Componente de afiare editabile ntrebri. 240 241 244 244 244 245 245 246 246 249 250 253 256 258 258 260 262 262 263 265

Componentele din JFC/Swing


Pentru a realiza interfaa utilizator grafic a unei aplicaii folosind JFC/Swing, este necesar ca la fereastra aplicaiei (din clasa JFrame) s se adauge diferite obiecte grafice numite componente. Deosebim: 1. Componente de control: butoane, butoane radio, casete de validare, liste, liste ascunse, meniuri, rigle ajustabile, cmpuri de text. 2. Componente de afiare needitabile: etichete, indicatoare, etc. 3. Componente de afiare editabile: zone de text, tabele editabile, selectoare de culori, selectoare de fiiere, arbori. 4. Containere: panouri, panouri glisante, etc.

O prezentare a acestor componente nsoit de ilustraii sugestive i de descrierea detaliat a utilizrii fiecreia se gsete n lecia Using Swing Components din sectiunea Creating a GUI

240

Programarea orientata pe obiecte n limbajul Java with JFC/Swing din Java Tutorial. Noi nu vom face aici, din lips de timp, dect o scurta prezentare a unor componente mai larg folosite i a modului lor de utilizare. Majoritatea claselor de componente din JFC/Swing sunt derivate din clasa JComponent, motenind caracteristicile acestei clase.

Clasa JComponent
Clasa abstracta javax.swing.JComponent extinde clasa java.awt.Container. In consecin, orice componenta Swing are i caracteristici de container. Iat, ca exemplu, cteva faciliti pe care le ofera orice JComponent: - posibilitatea de a-i ataa componentei o "inscripie volanta" (englez: ToolTip), adic o inscripie explicativ care apare cnd punem cursorul de mouse pe componenta respectiv, fr s apsm butonul. O astfel de inscripie se ataeaz componentei prin metoda public void setToolTipText(String text); - posibilitatea de a-i pune componentei o bordur, folosind metoda
public void setBorder(Border border);

- posibilitatea de a modifica culoarea de fond i culoarea de primplan ale componentei folosind metodele:
public void setBackground(Color color); public void setForeground(Color color); Mai multe metode sunt indicate n Indexul de clase.

O specificaie mai detaliat a clasei JComponent este dat n indexul de clase. Specificaia complet a clasei JComponent este dat in documentaia Java API, iar o descriere ampl a facilitilor i modului de utilizare se gsete n capitolul The JComponent class din tutorialul Java.

Caracteristicile componentelor JFC/Swing


Fiecare component a interfeei utilizator grafice se caracterizeaz prin aspect, stare i comportament. Aspectul este dat de figura prin care este reprezentat pe ecran componenta respectiv. Fiecare clas de componente ofer un aspect tipic al instanelor sale. n JFC/Swing programatorului i se pun nsa la dispoziie metode i clase prin care poate modifica aspectul componentelor. Starea componentei este dat, ca la orice obiect, de valorile cmpurilor sale. Starea se poate modifica fie datorit aciunilor utilizatorului, fie datorit invocrii prin program a unor metode ale acesteia. n general, la modificarea strii componenta genereaz un eveniment, iar uneori i schimb i aspectul. Comportamentul componentei este modul n care aceasta reacioneaz atunci cnd se acioneaz asupra ei de ctre utilizator sau cnd este invocat o metod i const n modificarea strii i a aspectului i n generarea de evenimente.

241

Severin Bumbaru Componentele din JFC/Swing ofer programatorului unele faciliti importante privind stabilirea aspectului i comportamentului acestora. Iat unele ditre ele: - posibilitatea de a introduce n component un text, o imagine, sau ambele; - posibilitatea de a aduga la fiecare component a unui text explicativ volant (englez: Tool Tip), care conine indicaii care apar cnd se pune cursorul mouse-ului pe componenta respectiv, fr a apsa butonul de mouse. - posibilitatea de a pune n jurul componentei una sau mai multe borduri (englez: Border), cu diferite aspecte: chenar simplu, chenar cu titlu, bordur care d aspect de supranlare, bordur care d aspect de scufundare; - posibilitatea de a alege aspectul general al tuturor componentelor interfeei grafice (englez: Look and Feel).

Pentru a ataa componentei un text volant se folosete metoda clasei JComponent


public void setToolTipText(String text);

Pentru a pune o bordur se folosete clasa javax.swing.BorderFactory care ofer metode pentru crearea unor borduri standard. Clasele de borduri i interfaa Border se gasesc n pachetul javax.swing.border. Adugarea bordurii la component se face prin metoda clasei JComponent
public void setBorder(Border border);

Iat unele din metodele clasei BorderFactory:


public static Border createLineBorder(Color color)

- creeaz o bordur (un -

chenar) dintr-o singur linie;


public static Border createLineBorder(Color color, int thickness)

creeaz o bordur format dintr-o linie de grosime (thickness) dat; public static Border createRaisedBevelBorder() - creeaza o bordur cu aspect de nlare a componentei; public static Border createLoweredBevelBorder() - creeaza o bordura cu aspect de scufundare a componentei;
public static Border createBevelBorder(int type, Color highlight, Color shadow) - creeaza o bordur pentru care se impun tipul i culorile, unde: type - tipul bordurii, care poate fi BevelBorder.RAISED sau BevelBorder.LOWERED; highlight - culoarea marginii care creeaz aspectul de nlare sau coborre; shadow - culoarea umbrei. public static TitledBorder createTitledBorder(String title) - creeaza o

bordur cu titlu.
public static CompoundBorder createCompoundBorder(Border outsideBorder, Border insideBorder) - creeaza o bordur compus, indicndu-se

bordura exterioar (outsideBorder) i cea interioara (insideBorder).

Exemplu n fiierul TestComp.java este dat un exemplu de testare a posibilitii de a stabili aspectul

242

Programarea orientata pe obiecte n limbajul Java

componentelor i a le ataa texte volante. Drept componente s-au folosit, deocamdat, instane ale clasei JButton, care a mai fost deja utilizat n capitolul precedent. Acelai mod de lucru poate fi ns folosit pentru orice alte clase care sunt derivate din JComponent.
import import import import java.awt.*; java.awt.event.*; javax.swing.*; javax.swing.border.*;

class TestComp { static AF af=new AF(); static IUG iug=new IUG("Butoane cu diferite aspecte"); /* clasa imbricata pentru interfata utilizator grafica */ static class IUG extends JFrame { //JLabel lab1, lab2, lab3, lab4; //JPanel panel; JButton b1,b2,b3,b4,b5,b6,b7; IUG(String titlu) { // constructorul clasei IUG super(titlu); setSize(300, 400); setLocation(200, 150); Container cp=getContentPane(); addWindowListener(af); // adaugarea ascultatorului de fereastra //panel=new JPanel(); cp.setLayout(new GridLayout(7,1)); //panel.setBackground(Color.red); b1=new JButton("Un buton obisnuit"); //b1.setBackground(Color.blue); b2=new JButton("Un buton cu bordura liniara"); b2.setBorder(BorderFactory.createLineBorder(Color.red, 4)); b2.setToolTipText("Bordura este rosie cu grosimea 4"); b3=new JButton("Un buton cu bordura cu titlu"); b3.setBorder(BorderFactory.createTitledBorder("Un titlu")); b4=new JButton("Un buton ridicat"); b4.setBorder(BorderFactory.createRaisedBevelBorder()); b5=new JButton("Un buton coborat"); b5.setBorder(BorderFactory.createLoweredBevelBorder()); b6=new JButton(new ImageIcon("buton_go.gif")); b6.setBorder(BorderFactory.createTitledBorder( "Un buton cu titlu, care contine o imagine")); b7=new JButton("Un buton cu bordura compusa"); Border bord1, bord2, bord3; bord1=BorderFactory.createBevelBorder(BevelBorder.RAISED, Color.green, Color.blue); bord2=BorderFactory.createBevelBorder(BevelBorder.LOWERED, Color.cyan, Color.yellow); bord3=BorderFactory.createCompoundBorder(bord1, bord2); b7.setBorder(bord3); cp.add(b1); cp.add(b2); cp.add(b3); cp.add(b4); cp.add(b5); cp.add(b6); cp.add(b7); setVisible(true);

243

Severin Bumbaru

} } /* Clasa ascultatoare de fereastra */ static class AF extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); // incheierea executarii aplicatiei } } /* Metoda principala a aplicatiei */ public static void main(String args[]) { } }

Remarcm urmtoarele: - pentru a lucra cu borduri, a fost necesar s se importe pachetul javax.swing.border; - s-au folosit bordurile standard din clasa BorderFactory; - butonului al doilea (b2, cel cu bordura roie groas) i s-a ataat un text explicativ volant; dac punem cursorul de mouse deasupra acestui buton fr s apsm i ateptm cteva secunde, apare textul volant; - n penultimul buton (b6) s-a introdus imaginea care se gsete n fiierul buton_go.gif. Dac dorii sa testati programul, aceast imagine trebuie s existe n acelai director cu clasa TestComp (deci n directorul curent al dvs). Pentru a realiza acest lucru, punei cursorul mouse-ului pe aceast imagine, apasai butonul din dreapta i va apare un meniu din care selectai opiunea "Save image as ..." sau "Save picture as ...", apoi salvai imaginea n acelai director cu fiierul TestComp.java.

Componente de control
Componentele de control sunt dispozitive de intrare virtuale, uor de utilizat, prin intermediul crora utilizatorul poate introduce anumite comenzi. Din aceast categorie fac parte butoanele, riglele ajustabile, listele, listele ascunse, meniurile i cmpurile de text.

Butoane
Butoanele sunt obiecte grafice, al cror aspect este similar celor al butoanelor folosite n aparatura electronic i electric. Acionarea butonului se face punnd deasupra lui cursorul mouse-ului i apasnd un buton al acestuia. n JFC/Swing exist mai multe tipuri de butoane: butonul simplu, caseta de validare, butonul radio i articolul de meniu. Toate acestea sunt subclase ale clasei abstracte javax.swing.AbstractButton.

Clasa AbstractButton
Clasa javax.swing.AbstractButton definete caracteristicile comune ale diferitelor tipuri de butoane din JFC/Swing. Iat cteva dintre acestea:

244

Programarea orientata pe obiecte n limbajul Java - orice buton poate avea un text, care poate fi pus prin metoda void setText(String text) i poate fi aflat prin metoda String getText(); - orice buton poate avea cel puin o pictogram, care poate fi pus prin metoda void setIcon(Icon defaultIcon) i obinut prin metoda Icon getIcon(); - orice buton poate avea o mnemonic, adic i se poate asocia o tast, a crei apasare are acelai efect cu apsarea cu mouse-ul a butonului respectiv. Mnemonica se pune cu metoda void setMnemonic(int mnemonic), al crei argument este codul tastei care trebuie acionat; - butonul genereaz trei tipuri de evenimente: . ActionEvent, cnd se acioneaza asupra lui; . ChangeEvent, cnd i modific starea; . ItemEvent, cnd butonul este selectat sau deselectat. Exist metode de adugare a asculttoarelor pentru aceste trei tipuri de evenimente:
void addActionListener(ActionListener a), void addChangeListener(ChangeListener c), void addItemListener(ItemListener i);

- butonul are un nume al aciunii de comand pe care o exercit, sub forma unui ir de caractere; implicit, acest nume este identic cu textul butonului, dar el poate fi modificat prin metoda void setActionCommand(String command) i poate fi aflat prin metoda String getActionCommand(); O prezentare mai ampl a clasei AbstractButton este dat n Indexul de clase. n seciunile urmtoare vom prezenta modul de utilizare a diferitelor tipuri de butoane, folosind clasele corespunztoare ale pachetului javax.swing.

Butonul obinuit (cu o singur stare stabil)


Butoanele obinuite se realizeaz folosind clasa javax.swing.JButton, derivat din clasa javax.swing.AbstractButton, aa cum am artat n exemplele date n capitolul precedent. Butonul obinuit are o singur stare stabil, n care ajunge cnd este eliberat. Ct timp se ine butonul de mouse apsat deasupra lui, butonul se afl n starea "apsat" ("acionat"). De fiecare dat cnd este acionat, butonul genereaz un AcionEvent i un ChangeEvent. Cnd este eliberat, genereaz numai un ChangeEvent. Butonul genereaz de asemenea, ca orice alt component, evenimente de component, de mouse i de tast. Totui, n cazul butoanelor obinuite, cel mai frecvent se folosesc evenimentele de aciune (ActionEvent), care sunt ascultate de un asculttor de aciune (ActionListener). Clasele Button i JButton sunt specificate mai detaliat n Indexul de clase.

Butonul cu dou stri stabile


Clasa javax.swing.JToggleButton este derivata din javax.swing.AbstractButton i reprezint butoane cu dou stri stabile. Trecerea de la o stare la alta este impus de utilizator prin click de mouse sau este comandat prin program. n practic, cel mai frecvent se folosesc caseta de validare i butonul radio, realizate prin subclase ale clasei ToggleButton i prezentate n continuare. O specificare mai detaliat a clasei JToggleButton este dat n indexul de clase.

245

Severin Bumbaru

Caseta de validare
Caseta de validare este un obiect de control cu dou stri stabile. La fiecare click de mouse pe suprafata casetei de validare, aceasta trece dintr-o stare n cealalt. n mod obinuit, caseta de validare este reprezentat grafic printr-un patrat, n care apare un simbol de bifare (de validare), cum ar fi simbolul V sau X, cnd caseta se gsete n starea "selectat". n starea opus (deselectat), caseta este vid. Imaginea casetei este insoit i de un text explicativ. n unele sisteme de interfa grafic, n locul casetei de validare se foloseste un comutator ("switch"). Acesta are aspectul unui buton, la care ambele stri ("apsat" i "eliberat") sunt stabile, trecerea de la o stare la alta fcndu-se la fiecare click de mouse pe suprafaa butonului. Din punct de vedere funcional, astfel de comutatoare se comporta identic cu casetele de validare, diferena fiind numai n aspectul grafic. n JFC/Swing casetele de validare se realizeaz folosind clasa javax.swing.JCheckBox, care este derivat din clasa javax.swing.JToggleButton.

Dintre evenimentele generate de caseta de validare, cel mai important este java.awt.event.ItemEvent, care este ascultat de clase cu interfaa java.awt.event.ItemListener. Astfel de evenimente sunt generate n momentele n care caseta a fost selectat sau deselectat. Metoda prin care se capteaz astfel de evenimente ntrun ItemListener este
public void itemStateChanged(ItemEvent e)

Pentru a afla n ce stare se gasete caseta la un moment dat, se folosete metoda


public boolean isSelected()

din superclasa javax.swing.AbstractButton.

Butonul radio
Butonul radio este un buton cu dou stri stabile, care face parte dintr-un grup de butoane, astfel c la un moment dat numai unul dintre ele poate fi "selectat". n momentul n care este selectat ("apsat") un buton al grupului, se deselecteaz automat cel care era selectat anterior. n JFC/Swing, butoanele radio sunt realizate ca instane ale clasei javax.swing.JRadioButton, care este derivat din clasa javax.swing.JToggleButton. Gruparea butoanelor se face folosind clasa javax.swing.ButtonGroup.

Exemplu n fiierul TestButoane.java se d un exemplu de aplicaie, n care se testeaz butoanul simplu, caseta de validare i butonul radio.
import java.awt.*; import java.awt.event.*;

246

Programarea orientata pe obiecte n limbajul Java

import javax.swing.*;

class TestButoane { static AF af=new AF(); static Ascultator ascult=new Ascultator(); static IUG iug=new IUG("Diferite tipuri de butoane"); /* clasa imbricata pentru interfata utilizator grafica */ static class IUG extends JFrame { JButton b1,b2; JCheckBox cb1, cb2; JRadioButton rb1, rb2, rb3; ButtonGroup grup; Box box1, box2, box3, box4; JLabel label; IUG(String titlu) { // constructorul clasei IUG super(titlu); setSize(300, 150); setLocation(200, 50); Container cp=getContentPane(); addWindowListener(af); // adaugarea ascultatorului de fereastra /* Se creeaza doua butoane, b1 si b2, care se pun in caseta box1 */ b1=new JButton("B1 (F1)"); b1.addActionListener(ascult); b1.setMnemonic(KeyEvent.VK_F1); b2=new JButton("B2 (F2)"); b2.addActionListener(ascult); b2.setMnemonic(KeyEvent.VK_F2); box1=Box.createVerticalBox(); box1.add(new JLabel("Butoane simple")); box1.add(b1); box1.add(b2); /* Se creeaza doua casete de validare, care se pun in box2 */ cb1=new JCheckBox("Caseta 1 (A)"); cb1.addItemListener(ascult); cb1.setMnemonic(KeyEvent.VK_A); cb2=new JCheckBox("Caseta 2 (S)"); cb2.addItemListener(ascult); cb2.setMnemonic(KeyEvent.VK_S); box2=Box.createVerticalBox(); box2.add(new JLabel("Casete validare")); box2.add(cb1); box2.add(cb2); /* Se creeaza trei butoane radio, care se grupeaza si se pun in box3 */ rb1=new JRadioButton("BR 1 (F5)"); rb1.setMnemonic(KeyEvent.VK_F5); rb1.addActionListener(ascult); rb2=new JRadioButton("BR 2 (F6)"); rb2.setMnemonic(KeyEvent.VK_F6); rb2.addActionListener(ascult); rb3=new JRadioButton("BR 3 (F7)"); rb3.setMnemonic(KeyEvent.VK_F7); rb3.addActionListener(ascult); box3=Box.createVerticalBox(); box3.add(new JLabel("Butoane radio"));

247

Severin Bumbaru

box3.add(rb1); box3.add(rb2); box3.add(rb3); grup=new ButtonGroup(); grup.add(rb1); grup.add(rb2); grup.add(rb3); /* box1, box2 si box3 se pun in box4 , iar aceasta se pune in controlPane */ box4=Box.createHorizontalBox(); box4.add(Box.createHorizontalGlue()); box4.add(box1); box4.add(Box.createHorizontalStrut(15)); box4.add(box2); box4.add(Box.createHorizontalStrut(15)); box4.add(box3); box4.add(Box.createHorizontalGlue()); cp.add(box4, BorderLayout.CENTER); label=new JLabel("Actionati butoanele si urmariti mesajul"); cp.add(label, BorderLayout.SOUTH); setVisible(true); } } /* Clasa ascultatoare de fereastra */ static class AF extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); // incheierea executarii aplicatiei } } /* Clasa ascultatoare de actiuni si de selectari */ static class Ascultator implements ActionListener, ItemListener { public void actionPerformed(ActionEvent e) { iug.label.setText("A fost apasat butonul "+e.getActionCommand()); } public void itemStateChanged(ItemEvent e) { JCheckBox cb=(JCheckBox)e.getItem(); String selectie; if(cb.isSelected()) selectie="A fost selectata "; else selectie="A fost deselectata "; iug.label.setText(selectie+cb.getText()); } } /* Metoda principala a aplicatiei */ public static void main(String args[]) { } }

n fereastra principal a aplicaiei apar: - dou butoane simple din clasa JButton, cu textele B1 i B2; butoanele sunt referite prin b1 i b2 i sunt puse n caseta vertical box1; - dou casete de validare din clasa JCheckBox, cu textele Caseta 1 i Caseta 2, referite prin cb1 i cb2 i puse n caseta vertical box2; - trei butoane radio din clasa JRadioButton, cu textele BR1, BR2 i BR3, referite prin br1,

248

Programarea orientata pe obiecte n limbajul Java br2 i br3 si puse n caseta vertical box3; - cele trei casete verticale, box1, box2 i box3, sunt plasate n caseta orizontal box4, iar aceasta este pus n zona CENTER a panoului controlPane; - n zona SOUTH a controlPane este pus o etichet din clasa JLabel, folosit pentru a afia evenimentele. Ascultarea evenimentelor de aciune (ActionEvent) i de selecie (ItemEvent) se face cu clasa Ascultare, care implementeaz interfeele ActionListener i ItemListener. Detectarea butonului care a fost apsat, fie c este vorba de un buton simplu sau unul radio, se face n metoda actionPerformed(ActionEvent action) folosind metoda String getActionCommand() din clasa ActionEvent. Pentru a constata care caseta de validare care a fost selectat sau deselectat, n metoda itemStateChanged(ItemEvent item) se procedeaz astfel: se determin mai nti obiectul selectabil (n cazul nostru caseta de validare) care a generat evenimentul, folosind metoda Object getItem() din clasa ItemEvent, dup care se aplic metoda boolean isSelected() a acestui obiect. Fiecrui buton (sau caset de validare) i-a fost ataat o mnemonic. Pentru comoditatea utilizatorului, tasta corespunztoare a fost menionat ntre paranteze, n textul fiecrui buton. Dac se d comanda Alt-<Tast mnemonic> se obine acelai efect ca atunci cnd se face click de mouse pe butonul respectiv. De exemplu, n loc de a apsa cu mouse-ul butonul B2, se apas simultan tastele Alt i F2. Simbolurile tastelor se gsesc n clasa java.awt.event.KeyEvent. Pentru aprofundarea folosirii diferitelor tipuri de butoane, recomandm capitolul How to use Buttons, Check Boxes and Radio Buttons din Java Tutorial.

Liste
n cazul interfeelor utilizator grafice, se numete list o component care conine articole selectabile. Selectarea lor se face de ctre utilizator, prin click de mouse pe articolul respectiv. Lista poate fi cu selecie simpl sau cu selecie multipl, dup cum pot fi selectate simultan unul sau mai multe articole. n JFC/Swing, listele se realizeaz ca instane ale clasei javax.swing.JList. Articolele din list pot fi, n principiu, orice obiecte afiabile. La crearea listei, constructorului i se d ca argument tabloul obiectelor pe care le va conine lista. Ulterior este posibil s se adauge articole la list, sau s se elimine. Daca lista este mai lunga dect spaiul de afiare disponibil, ea poate fi pus pe un panou glisant, din clasa javax.swing.JScrollPane.

Selectarea simpl a unui articol se face prin click de mouse pe articolul respectiv. Selectarea multipl se face n dou moduri: - se face click de mouse pe primul articol din zona care trebuie selectat, apoi se apas tasta

249

Severin Bumbaru Shift i se face click pe ultimul articol din aceast zon. n acest fel se selecteaz toate articolele din zona respectiv; - se face click de mouse pe primul articol din zon, apoi se apas tasta Shift i se acioneaz tastele cu sgei sus/jos pn cnd sunt selectate toate articolele din zona respectiv. De cte ori se face o selecie de articole din list, se genereaz un eveniment din clasa javax.swing.event.ListSelectionEvent, care este ascultat cu ajutorul unei clase care implementeaz interfaa javax.swing.event.ListSelectionListener. Punerea articolelor n list poate fi fcut astfel: - la crearea listei, folosind unul din constructorii public JList(Object[] listData) - primete ca argument un tablou de obiecte, care sunt articolele din list public JList(Vector listData)- primete ca argument o instan a clasei java.util.Vector, care are ca elemente articolele listei; - n timpul utilizrii listei, invocndu-se una din metodele
public void setListData(Object[] listData) public void setListData(Vector listData)

Pentru a afla articolele selectate dintr-o list se pot folosi metodele: public int[] getSelectedIndices() - ntoarce tabloul indicilor articolelor selectate public Object[] getSelectedValues() - ntoarce tabloul articolelor selectate. Clasa are numeroase alte metode. Pentru aprofundare, recomandm capitolul How to Use Lists din Java Tutorial.

Liste ascunse
Lista ascuns este o list din care se vede un singur articol (cel care este selectat), deci ocupa pe ecran spaiu mult mai putin dect una obinuit. Celelalte articole ale listei sunt "ascunse" i devin vizibile numai dac se face click pe articolul vizibil. Dac acum facem click de mouse pe un alt articol din lista devenit vizibil, acest nou articol este selectat (rmne vizibil), iar celelalte dispar. ntr-o list ascuns nu este posibil selecia multipl. n JFC/Swing, pentru realizarea listelor ascunse se folosete clasa javax.swing.JComboBox.

Cnd este selectat un nou articol din lista ascuns, aceasta genereaz un eveniment de articol din clasa java.awt.event.ItemEvent, care este ascultat cu un java.awt.event.ItemListener. La fiecare acionare asupra listei ascunse, se genereaz, de asemenea, un java.awt.ActionEvent. n mod implicit, instanele clasei JComboBox nu sunt editabile. Totui, este posibil ca acestea sa fie fcute editabile, n care caz ele se comport ca o combinaie ntre list i cmpul de text: utilizatorul poate s introduc textul manual, sau poate s aleag unul din list. Punerea articolelor n list se poate face astfel: - la crearea listei ascunse, folosind unul din constructorii

250

Programarea orientata pe obiecte n limbajul Java


public JComboBox(Object[] items) public JComboBox(Vector items)

- n timpul utilizrii listei, folosind metodele


public void addItem(Object anObject) - adaug un articol la sfritul listei; public void insertItemAt(Object anObject, int index) - nsereaz un articol pe poziia index.

Eliminarea unui articol din list se face cu una din metodele public void removeItem(Object anObject) - elimin articolul anObject; public void removeItemAt(int anIndex) - elimin articolul de pe poziia anIndex. Pentru a afla articolul selectat se folosete metoda
public Object getSelectedItem()

iar pentru a afla indicele articolului selectat se foloeste metoda


public int getSelectedIndex()

Pentru ca lista ascuns sa devin editabil, se folosete metoda public void setEditable(boolean aFlag)- n care parametrul boolean aFlag indic dac lista va fi sau nu editabil. Pentru aprofundarea folosirii listelor ascunse recomandm capitolul How to Use Combo Boxes din Java Tutorial.

Exemplu n fiierul Liste.java este dat un exemplu de aplicaie n care se folosesc instane ale claselor JList i JComboBox.

import import import import

java.awt.*; java.awt.event.*; javax.swing.*; javax.swing.event.*;

class Liste { static AF af=new AF(); static AAL ascult=new AAL(); static AEA ascult1=new AEA(); static IUG iug=new IUG("Diferite tipuri de liste"); /* clasa imbricata pentru interfata utilizator grafica */ static class IUG extends JFrame { JList lista1, lista2; JComboBox combo; JLabel label; IUG(String titlu) { // constructorul clasei IUG super(titlu);

251

Severin Bumbaru

setSize(350, 240); setLocation(200, 50); Container cp=getContentPane(); addWindowListener(af); // adaugarea ascultatorului de fereastra /* Se creeaza o lista cu zilele saptamanii. Listei nu i se pune un model de selectie, deci se pot face implicit selectii multiple intr-o singura zona continua */ String zile[]={"Luni", "Marti", "Miercuri", "Joi", "Vineri", "Sambata", "Duminica"}; lista1=new JList(zile); lista1.setBorder(BorderFactory.createTitledBorder( "Lista")); lista1.addListSelectionListener(ascult); // ascultarea listei cp.add(lista1, BorderLayout.WEST); /* Se creeaza o lista cu lunile anului, pusa intr-un panou glisant. Listei i se pune un model de selectie care permite numai selectarea unui singur articol */ String luni[]={"Ianuarie", "Februarie", "Martie", "Aprilie", "Mai", "Iunie", "Iulie", "August", "Septembrie", "Octombrie", "Noiembrie", "Decembrie"}; lista2=new JList(luni); lista2.setBorder(BorderFactory.createTitledBorder( "Lista glisanta")); lista2.setSelectionModel(new DefaultListSelectionModel()); lista2.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); lista2.addListSelectionListener(ascult); JScrollPane scroll=new JScrollPane(lista2); // panoul glisant // care contine lista nou creata, lista2 cp.add(scroll, BorderLayout.CENTER); /* Se creeaza o lista ascunsa (din clasa JComboBox) */ String ordinea[]={"Primul ", "Al doilea", "Al treilea", "Al patrulea"}; combo=new JComboBox(ordinea); combo.setBorder(BorderFactory.createTitledBorder( "Lista ascunsa")); combo.addItemListener(ascult1); JPanel panel=new JPanel(); panel.add(combo); cp.add(panel, BorderLayout.EAST); /* Se creeaza o "eticheta" pentru afisarea mesajelor */ label=new JLabel("Selectati articolele si urmariti efectul"); label.setBorder(BorderFactory.createTitledBorder( "Afisarea mesajelor privind articolele selectate")); cp.add(label, BorderLayout.SOUTH); setVisible(true); } } /* Clasa ascultatoare de fereastra */ static class AF extends WindowAdapter { public void windowClosing(WindowEvent e) {

252

Programarea orientata pe obiecte n limbajul Java

System.exit(0); // incheierea executarii aplicatiei } } /* Clasa ascultatoare de selectari ale articolelor de lista folosita pentru JList. La aparitia unui astfel de eveniment, se afiseaza toate articolele selectate din lista sursa */ static class AAL implements ListSelectionListener { public void valueChanged(ListSelectionEvent e) { JList sursa=(JList)e.getSource(); Object selectie[]=sursa.getSelectedValues(); StringBuffer buff=new StringBuffer(); for(int i=0; i<selectie.length; i++) buff.append(selectie[i].toString()+" "); iug.label.setText(buff.toString()); } } /* Clasa ascultatoare de evenimente de articol folosita pentru JComboBox. La aparitia unui astfel de eveniment, se afiseaza articolul care l-a produs */ static class AEA implements ItemListener { public void itemStateChanged(ItemEvent e) { iug.label.setText(e.getItem().toString()); } } /* Metoda principala a aplicatiei */ public static void main(String args[]) { } }

Cmpul de text
Cmpul de text este principalul instrument al interfeei grafice prin care utilizatorul introduce date de la tastatur. El se prezint sub forma unei ferestre dreptunghiulare editabile, n care se poate introduce o singur linie de text. De obicei, prin intermediul cmpului de text se introduce o singur valoare numeric sau un ir de caractere. n JFC/Swing, cmpurile de text se realizeaz ca instane ale clasei javax.swing.JTextField. Cnd cmpul de text este activ i se apas tasta Enter, este generat un eveniment de aciune din clasa java.awt.ActionEvent.

Textul coninut n cmpul de text poate fi obinut n dou moduri: - prin metoda public String getText() a clasei JTextField; - prin metoda public String getActionCommand() a clasei ActionEvent. Dac n cmpul de text se introduce o valoare numeric, ea trebuie verificata sintactic i

253

Severin Bumbaru convertit din forma extern (de ir de caractere) n forma intern. n acest scop, se folosesc metodele de analiz i conversie din clasele acoperitoare. De exemplu, pentru un numar de tip double se va folosi metoda
public double parseDouble(String str)

din clasa acoperitoare java.lang.Double, unde str este irul care trebuie analizat. ntruct aceste metode pot s genereze excepii de format incorect (NumberFormatException), ele trebuie utilizate n secvene try .. catch; Pentru aprofundarea utilizrii cmpurilor de text, recomandm capitolul How to Use Text Fields din Java Tutorial. Menionm c, n afara clasei JTextField, exist i clasa javax.swing.JPasswordField, care se folosete pentru introducerea parolelor.

Exemplu n fiierul CmpuriText.java este dat un exemplu de aplicaie n care se utilizeaz trei cmpuri de text, pentru a introduce, respectiv, un ir de caractere, un numr ntreg i un numr n virgul mobil. n clasa imbricat Actiuni, prin care este realizat asculttorul de evenimente de aciune, se poate observa cum se determin care cmp de text a generat evenimentul de aciune i cum se preia i analizeaz textul din cmpul respectiv, n funcie de tipul valorii pe care acest cmp trebuie s o conin.
import java.awt.*; import java.awt.event.*; import javax.swing.*; class CampuriText { static AF af=new AF(); static Actiuni act=new Actiuni(); static IUG iug=new IUG("Campuri de text"); /* clasa imbricata pentru interfata utilizator grafica */ static class IUG extends JFrame { JPanel panel; JTextField tf1, tf2, tf3; JLabel label; IUG(String titlu) { // constructorul clasei IUG super(titlu); setSize(450, 150); setLocation(200, 50); Container cp=getContentPane(); addWindowListener(af); // adaugarea ascultatorului de fereastra /* Crearea panoului pentru campurile de text */ panel=new JPanel(); panel.setLayout(new GridLayout(3,2)); /* Adaugarea la panou a etichetelor si campurilor de text */ panel.add(new JLabel("Un sir de caractere: "));

254

Programarea orientata pe obiecte n limbajul Java

tf1=new JTextField(); tf1.addActionListener(act); panel.add(tf1); panel.add(new JLabel("Un numar intreg")); tf2=new JTextField(); tf2.addActionListener(act); panel.add(tf2); panel.add(new JLabel("Un numar real: ")); tf3=new JTextField(); tf3.addActionListener(act); panel.add(tf3); /* Adaugarea la contentPane a panoului cu campuri de text */ cp.add(panel, BorderLayout.CENTER); /* Se creeaza o "eticheta" pentru afisarea mesajelor */ label=new JLabel("Introduceti date in campuri si urmariti efectul"); label.setBorder(BorderFactory.createTitledBorder( "Afisarea mesajelor privind campurile de text")); cp.add(label, BorderLayout.SOUTH); setVisible(true); } } /* Clasa ascultatoare de fereastra */ static class AF extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); // incheierea executarii aplicatiei } } /* Clasa ascultatoare a actiunilor asupra campurilor de text */ static class Actiuni implements ActionListener { public void actionPerformed(ActionEvent e) { JTextField sursa=(JTextField)e.getSource(); String text=e.getActionCommand(), text1="Ati introdus in campul "; if(sursa==iug.tf1) iug.label.setText(text1+"1 textul: "+text); else if(sursa==iug.tf2) try { int n=Integer.parseInt(text); iug.label.setText(text1+" 2 numarul intreg "+n); } catch(Exception e1) { iug.label.setText("In campul 2 nu este un numar intreg!"); } else if(sursa==iug.tf3) try { double d=Double.parseDouble(text); iug.label.setText(text1+"3 numarul real "+d); } catch(Exception e2) { iug.label.setText("In campul 3 nu este un numar real!"); } } } /* Metoda principala a aplicatiei */

255

Severin Bumbaru

public static void main(String args[]) { } }

Rigla cu cursor
Clasa javax.swing.JSlider ofer o component care are aspectul unei rigle prevzute cu cursor. Prin deplasarea cursorului cu ajutorul mouse-ului se modific valoarea indicat de rigl. Valoarea minim i cea maxim de pe scala riglei i valoarea unei diviziuni se indic prin program. Rolul riglei poate fi asemnat cu cel al unui dispozitiv de ajustare continu, cum este poteniometrul din aparatura electronic. La deplasarea cursorului, rigla genereaz evenimente din clasa javax.swing.event.ChangeEvent, care sunt ascultate cu o clas care implementeaz interfaa javax.swing.event.ChangeListener.

Crearea riglei se face folosind unul dintre constructorii ei, dintre care cel mai complet este
public JSlider(int orientation, int min, int max, int value)

n care
orientation - orientarea riglei, care poate fi JSlider.HORIZONTAL sau JSlider.VERTICAL; min, max - valorile minim i maxim de pe scala riglei; value - valoarea indicat iniial de cursorul riglei (trebuie s fie n intervalul

[min,max]).

Pentru a stabili aspectul riglei se folosesc metodele


public public public public void void void void setMajorTickSpacing(int n) - stabilirea valorii diviziunilor mari setMinorTickSpacing(int n) - stabilirea valorii diviziunilor mici setPaintTicks(boolean b) - determin dac diviziunile vor fi vizibile setPaintLabels(boolean b) - determin dac vor fi afiate valorile

numerice ale diviziunilor. Pentru aprofundarea utilizrii riglelor cu cursor, recomandm consultarea capitolului How to Use Sliders din Java Tutorial. Exemplu n fiierul TestRigla.java este dat un exemplu de aplicaie n care se testeaz o rigl cu cursor realizat ca instan a clasei JSlider. La partea superioar a ferestrei apare o rigl n poziie orizontal. Cnd se modific cu mouse-ul poziia cursorului, n eticheta de la partea inferioar a ferestrei aplicaiei se afieaza noua valoare indicat de rigl.

import java.awt.*; import java.awt.event.*; import javax.swing.*;

256

Programarea orientata pe obiecte n limbajul Java

import javax.swing.event.*;

class TestRigla { static AF af=new AF(); static AscultRigla ascult=new AscultRigla(); static IUG iug=new IUG("O rigla ajustabila"); /* clasa imbricata pentru interfata utilizator grafica */ static class IUG extends JFrame { JSlider rigla; JLabel label;

IUG(String titlu) { // constructorul clasei IUG super(titlu); setSize(450, 150); setLocation(200, 50); Container cp=getContentPane(); addWindowListener(af); // adaugarea ascultatorului de fereastra /* Se creeaza o "eticheta" pentru afisarea mesajelor */ label=new JLabel("Deplasati cursorul riglei si urmariti efectul"); label.setBorder(BorderFactory.createTitledBorder( "Afisarea mesajelor privind valoarea ajustata")); cp.add(label, BorderLayout.SOUTH); rigla=new JSlider(JSlider.HORIZONTAL, -20, 80, 35); rigla.setBorder(BorderFactory.createTitledBorder( "Ajustarea valorii")); rigla.setMajorTickSpacing(10); rigla.setMinorTickSpacing(1); rigla.setPaintTicks(true); rigla.setPaintLabels(true); rigla.addChangeListener(ascult); cp.add(rigla, BorderLayout.CENTER); setVisible(true); } } /* Clasa ascultatoare de fereastra */ static class AF extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); // incheierea executarii aplicatiei } } /* Clasa ascultatoare a evenimentelor de ajustare a riglei */ static class AscultRigla implements ChangeListener { public void stateChanged(ChangeEvent e) { iug.label.setText("Noua valoare: "+iug.rigla.getValue()); } } /* Metoda principala a aplicatiei */

257

Severin Bumbaru

public static void main(String args[]) { } }

Meniuri
La fel ca listele sau butoanele radio, meniurile permit utilizatorului s aleag una din mai multe opiuni posibile. n JFC/Swing se disting dou categorii de meniuri: - meniuri cu bar, care pornesc dintr-o bar situat la partea superioar a ferestrei aplicaiei; - meniuri derulante (pop-up), care apar n poziia n care se gsete cursorul de mouse.

Meniuri cu bar
Bara de meniu se poate plasa, daca este necesara, numai la partea superioara a ferstrei aplicatiei si se realizeaza ca o instanta a clasei javax.swing.JMenuBar. Bara de meniu poate sa conin unul sau mai multe meniuri, care se realizeaz ca instane ale clasei javax.swing.JMenu. La rndul su, fiecare meniu poate conine unul sau mai multe articole, care sunt instane ale claselor javax.swing.JMenuItem sau javax.swing.JCheckBoxMenuItem. Este ns posibil ca un articol de meniu s fie el nsui un meniu (din clasa JMenu). Dac utilizatorul alege cu mouse-ul un aricol de meniu, sunt posibile deci dou situaii: - acesta este un articol propriu-zis (un JMenuItem), n care caz opiunea respectiv este selectat; - articolul ales este el nsui un meniu (un JMenu), n care caz noul (sub)meniu se desfoar i cutarea continu.

Barele de meniu nu pot fi adugate la un container ca nite componente obinuite. Pentru a pune bara de meniu la partea superioar a ferestrei aplicaiei se folosete metoda clasei JFrame
public void setJMenuBar(JMenuBar menubar)

Adugarea de meniuri la bara de meniu se face prin metoda clasei JMenuBar


public JMenu add(JMenu c)

iar adugarea de articole sau submeniuri la un meniu se face prin metodele clasei JMenu
public public public public JMenuItem Component JMenuItem JMenuItem add(JMenuItem menuItem) add(Component c) add(String s) add(Action a)

Pentru a introduce n meniu o linie orizontal de separare a dou articole se folosete metoda
public void addSeparator()

Atunci cnd este selectat un articol de meniu simplu (din clasa JMenuItem), acesta acioneaz ca un buton obinuit, adic genereaz un eveniment de aciune (ActionEvent). Dac se selecteaz un articol de meniu sub forma de caset de validare (din clasa JCheckBoxMenuItem), acesta se comporta ca o caseta de validare, adic genereaz un

258

Programarea orientata pe obiecte n limbajul Java eveniment de articol (ItemEvent). Ascultarea acestor evenimente se face cu clase care implementeaz interfeele ActionListener, respectiv ItemListener. Posibilitile oferite de meniuri sunt mult mai bogate dect s-a artat aici. Pentru aprofundare recomandm consultarea capitolului How to Use Menus din Java Tutorial. Exemplu n fiierul Meniuri.java este dat un exemplu de aplicaie cu bar de meniu.
import java.awt.*; import java.awt.event.*; import javax.swing.*; class Meniuri { static AF af=new AF(); static AA aa=new AA(); static IUG iug=new IUG("O fereastra cu bara de menu"); /* clasa imbricata pentru interfata utilizator grafica */ static class IUG extends JFrame { JMenuBar menuBar; JMenu menu1, menu2; JLabel label; JMenuItem mi1, mi2, mi3, mi4, mi5; IUG(String titlu) { // constructorul clasei IUG super(titlu); setSize(350, 150); setLocation(200, 50); Container cp=getContentPane(); addWindowListener(af); // adaugarea ascultatorului de fereastra menuBar=new JMenuBar(); // se creeaza bara de menu setJMenuBar(menuBar); // bara de menu se adauga la fereastra /* Se creeaza meniurile si se adauga la bara de meniu */ menu1=new JMenu("Un menu"); menuBar.add(menu1); menu2=new JMenu("Alt menu"); menuBar.add(menu2); /* Se creaza articole de menu si se adauga la meniuri */ mi1=new JMenuItem("A"); mi1.addActionListener(aa); menu1.add(mi1); mi2=new JMenuItem("B"); mi2.addActionListener(aa); menu1.add(mi2); mi3=new JMenuItem("C"); mi3.addActionListener(aa); menu2.add(mi3); /* La menu2 se aduga un submeniu cu doua articole */ JMenu menu3=new JMenu("Un submeniu"); mi4=new JMenuItem("Alpha"); mi4.addActionListener(aa); menu3.add(mi4); mi5=new JMenuItem("Beta"); mi5.addActionListener(aa); menu3.add(mi5); menu2.add(menu3);

259

Severin Bumbaru

/* Se creeaza o "eticheta" pentru afisarea mesajelor */ label=new JLabel("Selectati articole de meniu si urmariti efectul"); label.setBorder(BorderFactory.createTitledBorder( "Afisarea mesajelor privind selectarea articolelor de meniu")); cp.add(label, BorderLayout.SOUTH); setVisible(true); } } /* Clasa ascultatoare de fereastra */ static class AF extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); // incheierea executarii aplicatiei } } /* Ascultator de actiuni pentru articolele de menu */ static class AA implements ActionListener { public void actionPerformed(ActionEvent e) { iug.label.setText("A fost selectata optiunea: "+ e.getActionCommand()); } } /* Metoda principala a aplicatiei */ public static void main(String args[]) { } }

Meniuri volante (pop-up)


Spre deosebire de meniurile cu bar, meniurile volante sunt tratate ca nite componente obinuite, care pot s fie afiate prin program, atunci cnd este necesar. n JFC/Swing, meniurile volante se realizeaz ca instane ale clasei javax.swing.JPopupMenu. n rest, meniul pop-up se comport la fel ca un meniu cu bar. Afiarea meniului pop-up trebuie programat, folosindu-se n acest scop metoda din clasa JPopupMenu
public void show(Component invoker, int x, int y)

n care invoker este referina la componenta in spaiul creia trebuie s apar meniul, iar x i y sunt coordonatele punctului n care acesta va fi afiat. De obicei, se doreste ca afiarea meniului pop-up s se fac atunci cnd se efectueaz o anumit aciune a mouse-lui asupra componentei respective. n acest scop, se creeaz o clas asculttoare de mouse (care implementeaz interfaa MouseListener sau extinde clasa MouseAdapter) i - n corpul metodei corespunzatoare situaiei n care trebuie s se afieze meniul (mousePressed, mouseReleased sau mouseClicked) se invoc metoda show menionat mai sus, dac a fost acionat butonul de mouse care ne intereseaz. Se demonstreaz acest procedeu n exemplul de mai jos.

260

Programarea orientata pe obiecte n limbajul Java Exemplu n fiierul Popup.java se d un exemplu de aplicaie n care se testeaz utilizarea unui menu pop-up. Drept component pe suprafaa creia trebuie s apar meniul s-a ales eticheta de la partea inferioar a ferestrei aplicaiei. Evenimentul care declaneaz apariia meniului este apsarea pe butonul din dreapta al mouse-ului, atunci cnd acesta se gsete n spaiul ferestrei. Acest eveniment este urmrit de instana clasei AfisPopup, care este ataata etichetei label n calitate de asculttor de mouse.

import java.awt.*; import java.awt.event.*; import javax.swing.*; class Popup { static AF af=new AF(); static AA aa=new AA(); static AfisPopup afisare=new AfisPopup(); static IUG iug=new IUG("Exemplu de menu pop-up"); /* clasa imbricata pentru interfata utilizator grafica */ static class IUG extends JFrame { JPopupMenu popup; JLabel label; JMenuItem mi1, mi2, mi3; IUG(String titlu) { // constructorul clasei IUG super(titlu); setSize(350, 150); setLocation(200, 50); Container cp=getContentPane(); addWindowListener(af); // adaugarea ascultatorului de fereastra /* Se creeaza meniul pop-up */ popup=new JPopupMenu(); /* Se creaza articole de menu si se adauga la meniuri */ mi1=new JMenuItem("A"); mi1.addActionListener(aa); popup.add(mi1); mi2=new JMenuItem("B"); mi2.addActionListener(aa); popup.add(mi2); mi3=new JMenuItem("C"); mi3.addActionListener(aa); popup.add(mi3); /* Se creeaza o "eticheta" pentru afisarea mesajelor */ label=new JLabel(" Apasati pe aceasta eticheta butonul drept al mouse-ului"); label.setBorder(BorderFactory.createTitledBorder( "Afisarea mesajelor privind selectarea articolelor de meniu")); cp.add(label, BorderLayout.SOUTH); /* Se adauga la eticheta label ascultatorul de mouse pentru afisarea meniului popup

261

Severin Bumbaru

*/ label.addMouseListener(afisare); setVisible(true); } } /* Clasa ascultatoare de fereastra */ static class AF extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); // incheierea executarii aplicatiei } } /* Clasa ascultatoare de mouse pentru afisarea meniului pop-up */ static class AfisPopup extends MouseAdapter { public void mousePressed(MouseEvent e) { if((e.getModifiers()&InputEvent.BUTTON3_MASK)!=0) iug.popup.show(e.getComponent(), e.getX(), e.getY()); } } /* Ascultator de actiuni pentru articolele de menu */ static class AA implements ActionListener { public void actionPerformed(ActionEvent e) { iug.label.setText("A fost selectata optiunea: "+ e.getActionCommand()); } } /* Metoda principala a aplicatiei */ public static void main(String args[]) { } }

Componente de afiare
Componentele de afiare sunt cele care servesc pentru a afia anumite texte sau imagini i pot fi needitabile sau editabile.

Componente de afiare needitabile


Componentele de afiare needitabile sunt realizate ca instane ale urmtoarelor clase: - javax.swing.JLabel - pentru realizarea unor "etichete" n care pot fi afiate texte sau imagini, fr a putea fi editate de utilizator; - javax.swing.JTooltip - pentru afiarea de "inscripii volante", cnd se pune cursorul de mouse deasupra unei alte componente; - javax.swing.JProgressBar - pentru realizarea unor "bare de progres" adic a unor bare de lungime variabil, care arat cum evolueaz realizarea unei anumite activiti (de la 0% la

262

Programarea orientata pe obiecte n limbajul Java 100%).

Utilizarea etichetelor i a inscripiilor volante a fost deja prezentat. Pentru aprofundarea acestora i pentru a studia folosirea barelor de progres recomandm capitolele How to Use Labels, How to Use Tool Tips i How to Monitor Progress din Java Tutorial.

Componente de afiare editabile


Componentele de afiare editabile permit utilizatorului operaii de editare n timpul executrii programului. n JFC/Swing exist un numr important de clase pentru astfel de componente. Astfel, pentru editare de texte exist clasele javax.swing.JTextArea, javax.swing.JTextPane i javax.swing.JEditorPane. n aceeai categorie pot fi ncadrate i clasele javax.swing.JTextField i javax.swing.JPasswordField, care au fost prezentate anterior. Tot n categoria componentelor editabile intr i clasele javax.swing.JTable (pentru realizarea de tabele editabile), javax.swing.JFileChooser (pentru realizarea de selectoare de fiiere), javax.swing.JTree (pentru realizarea de arbori) i javax.swing.JColorChooser (pentru realizarea de selectoare de culori). Vom prezenta aici numai clasa JTextArea, iar pentru celelalte recomandm folosirea documentaiei indicate.

Pentru aprofundare recomandm folosirea capitolelor Using Text Components, How to Use Tables, How to Use File Choosers, How to Use Trees, si How to Use Color Choosers din Java Tutorial.

Clasa JtextArea
Instanele clasei javax.swing.JTextArea (arie de text) sunt suprafee de afiare a unor texte editabile cu mai multe linii. Componenta are comportamentul unui editor de text simplu: permite s se introduc text de la tastatur, s se tearg textul n ntregime sau pe poriuni, s se adauge sau s se nsereze text. Prin metode speciale se poate seta componenta astfel, nct s se realizeze automat trecerea de la un rnd la altul. Se ofer metode prin care se poate aduga text prin program, sau se poate obine sub forma de String textul existent. Iat unele dintre metodele oferite de clasa JTextArea: public int getRows() - ntoarce numrul maxim de linii din aria de text; public void setRows(int rows) - seteaz numrul maxim de linii; public int getColumns() - ntoarce numrul maxim de coloane din aria de text; public void setColumns(int columns) - seteaz numrul maxim de coloane;

263

Severin Bumbaru
public void setFont(Font f) - seteaz fontul; public void setLineWrap(boolean wrap) - indic dac se

face trecere automat la

linie nou;
public void setWrapStyleWord(boolean word) - indic dac trecerea automat la linie nou se face la sfrit de cuvnt; public int getLineCount() - ntoarce numrul de linii de text coninute efectiv; public void insert(String str, int pos) - nsereaz irul str ncepnd de la poziia pos; public void append(String str) - adaug la sfrit textul str; public void replaceRange(String str, int start, int end) - nlocuiete prin irul str caracterele cuprinse ntre poziiile start i end; public String getText() - ntoarce sub forma de String textul coninut; public String getSelectedText() - ntoarce textul selectat. Ultimele dou metode sunt motenite de la superclasa javax.swing.text.JTextComponent.

Exemplu n fiierul ZonaText.java se d un exemplu simplu de creare a unei instane a clasei JTextArea, setnd trecerea automat la linie nou la sfrit de cuvant (astfel nct un cuvnt s nu se mpart pe dou linii). Punnd n execuie aceast aplicaie, constatm cum aria de text se comport ca un mic editor de text: putem s introducem de la tastatur text nou sau s modificm textul existent. Dac modificm cu mouse-ul dimensiunile ferestrei, observm cum se rearanjeaz automat liniile de text.
import java.awt.*; import java.awt.event.*; import javax.swing.*; class ZonaText { static AF af=new AF(); // static AA aa=new AA(); //static AfisPopup afisare=new AfisPopup(); static IUG iug=new IUG("O zona de text"); /* clasa imbricata pentru interfata utilizator grafica */ static class IUG extends JFrame { JTextArea ta; JLabel label; IUG(String titlu) { // constructorul clasei IUG super(titlu); setSize(450, 150); setLocation(200, 50); Container cp=getContentPane(); addWindowListener(af); // adaugarea ascultatorului de fereastra ta=new JTextArea (); ta.setLineWrap(true); ta.setWrapStyleWord(true); cp.add(ta, BorderLayout.CENTER); setVisible(true); } } /* Clasa ascultatoare de fereastra */

264

Programarea orientata pe obiecte n limbajul Java

static class AF extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); // incheierea executarii aplicatiei } }

/* Metoda principala a aplicatiei */ public static void main(String args[]) { } }

ntrebri
Nivel 1
1. Ce categorii de componente grafice cunoatei? 2. Care este rdcina ierarhiei claselor de componente? 3. Care sunt caracteristicile componentelor din JFC/Swing? 4. Cum se stabilete aspectul componentelor din JFC/Swing? 5. Prin ce se caracterizeaz starea componentei? 6. Prin ce se caracterizeaza comportamentul componentei? 7. Care este deosebirea dintre componentele atomice i containere? 8. Ce poate conine o component atomic din JFC/Swing? 9. Care sunt componentele de control i ce rol au? 10. Ce reprezint clasa AbstractButton? 11. Ce reprezint clasa JToggleButton? 12. Ce este o caset de validare i prin ce clas se realizeaz? 13. Ce este un buton radio i prin ce clas se realizeaz? 14. La ce servete clasa ButtonGroup? 15. Ce este o list n JFC/Swing i prin ce clas se realizeaz? 16. Ce este o list ascuns i prin ce clas se realizeaz? 17. Prin ce clas se realizeaz cmpul de text i ce conine el? 18. Care este principala utilizare a cmpului de text? 19. Ce evenimente genereaz un cmp de text i cnd le genereaz? 20. Ce este o rigl ajustabil i prin ce clas se realizeaz? 21. Care este dispozitivul electronic pe care l simuleaz o rigl ajustabil? 22. Ce este un meniu? 23. Ce categorii de meniuri exist n JFC/Swing? 24. Unde poate fi plasat un meniu cu bara? 25. Prin ce clas se realizeaz bara de meniu? 26. Ce conine bara de meniu? 27. Prin ce clas se realizeaz un meniu utilizabil ntr-o bar de meniu? 28. Ce conine un meniu? 29. Prin ce clase se realizeaz articolele de meniu? 30. Ce este un meniu derulant i prin ce clas se realizeaz?

265

Severin Bumbaru 31. Ce sunt componentele de afiare needitabile? 32. Ce componente de afiare needitabile cunoatei? 33. Ce sunt componentele de afiare editabile? 34. Ce componente de afiare editabile cunoatei? 35. Ce sunt instanele clasei JTextArea i cum se comport ele?

Nivel 2
1. Care este superclasa clasei JComponent i ce decurge din aceasta? 2. Ce este un text volant i cum este el ataat unei componente? 3. Cum se adaug bordura unei componente? 4. Care este clasa prin care se realizeaz bordurile? 5. Cum se poate pune un text ntr-o component? 6. Cum se poate pune o imagine ntr-o component? 7. Cum se adaug component la container? 8. Care sunt caracteristicile unui AbstractButton? 9. Ce este o mnemonic? 10. Ce evenimente genereaz un AbstractButton? 11. Cum se poate detecta momentul apsrii unui buton? 12. Cum se poate afla care buton a fost apsat? 13. Cum se poate determina momentul schimbrii strii unei casete de validare? 14. Cum se poate afla n ce stare se gsete la un moment dat o caset de validare? 15. Cum se face selectarea unui articol dintr-o list? 16. Ce deosebire este ntre selecia simpl i selecia multipl? 17. Cum pot fi selectate mai multe articole ale listei? 18. Cum poate fi determinat momentul selectrii unui articol din list? 19. Cum se poate determina ce articole de list sunt selectate la un moment dat? 20. Sunt oare editabile instanele clasei JComboBox? 21. Cum se poate afla textul coninut ntr-un cmp de text? 22. Cum se poate converti textul preluat din cmpul de text ntr-o valoare numeric? 23. Ce orientare poate avea o rigl ajustabil? 24. Cum se pot trasa diviziunile riglei ajustabile? 25. Cum se stabilete intervalul de valori al riglei ajustabile? 26. Cum se poate obine valoarea indicat de rigl? 27. Prin ce metod se pune bara de meniu n fereastra aplicaiei i crei clase i aparine aceast metod? 28. Cum se adaug un articol la un meniu? 29. Ce evenimente genereaz un articol de meniu? 30. Cum se programeaz afiarea pe ecran a unui meniu pop-up? 31. Ce reprezint instanele clasei JTable? 32. Care este clasa de componente folosite la alegerea culorii? 33. Ce clase de componente pot fi folosite pentru a realiza un selector de fiier? 34. Ce metode ale clasei JTextArea cunoastei? 35. Ce clase pot fi folosite la realizarea de componente cu text editabil?

266

Programarea orientata pe obiecte n limbajul Java

Utilizarea ferestrelor de dialog. Desenarea


In aceasta sectiune vom studia utilizarea ferestrelor de dialog si a unor clase necesare pentru reprezentari grafice. Utilizarea ferestrelor de dialog Alegerea culorii Clasa Color Alegerea culorii folosind clasa JColorChooser Elemente de grafic Contextul grafic Metodele paint i repaint ntrebri. 267 270 272 278 280 280 283 289

Utilizarea ferestrelor de dialog


Ferestrele de dialog sunt ferestre care se afieaz pe ecran numai temporar, pentru a transmite anumite mesaje sau a permite introducerea unor date. Principalul avantaj al folosirii ferestrelor de dialog este c apar pe ecran numai atunci cnd sunt necesare i nu ncarc fereastra principal a aplicaiei cu elemente care nu sunt necesare n permanen. n JFC/Swing, ferestrele de dialog se realizeaz folosind clasa javax.swing.JDialog. Instanele acestei clase se comport asemanator cu cele ale clasei JFrame, permind adugarea oricror componente. La fel ca la JFrame, aceste componente nu se adaug direct la fereastr, ci la panoul contentPane coninut n aceasta i obinut prin metoda public Container getContentPane(). Fereastra de dialog poate avea ca "proprietar" (owner) o instan a claselor java.awt.Frame, javax.swing.JFrame, java.awt.Dialog sau javax.swing.JDialog. Proprietarul se transmite ca argument al constructorului ferestrei de dialog. Se permite ca, n loc de proprietar, s se pun argumentul null, n care caz se atribuie un proprietar implicit. Pentru afiarea pe ecran a ferestrei de dialog se invoc metoda public void show(), iar pentru ascunderea ei se invoc metoda public void hide(). n fine, pentru a elimina fereastra de dialog, elibernd toate resursele pe care le folosete, se invoc metoda public void dispose(). Aceste trei metode sunt motenite de JDialog de la superclasa java.awt.Dialog. Cnd fereastra de dialog este deschis, ea trece n prim plan sau n plan secund mpreun cu proprietarul ei. Ferestrele de dialog pot fi modale sau nemodale. Cnd este afiat pe ecran o fereastr modal, toate celelalte ferestre existente pe ecran sunt blocate (nu se poate aciona asupra lor), pn cnd se ncheie lucrul cu fereastra de dialog modal respectiv.

267

Severin Bumbaru Clasele Dialog i JDialog sunt prezentate ceva mai detaliat n indexul de clase. Clasa JDialog este folosit pentru realizarea unor ferestre de dialog configurate de programator dup dorina sa. n multe situaii, este ns suficient s se foloseasc ferestre de dialog standard, preconfigurate, ceeace uureaz programarea. n acest scop, n JFC/Swing a fost creat clasa javax.swing.JOptionPane care este prezentat n indexul de clase.

Clasa JOptionPane ofer metode statice pentru a creea patru tipuri de ferestre de dialog: - pentru dialog de mesaj (showMessageDialog) - fereastra conine o informaie i un buton OK care se apas pentru a nchide fereastra; - pentru dialog de confirmare (showConfirmDialog) - n fereastra se afieaz un mesaj (o ntrebare) i trei butoane de confirmare: Yes/No/Cancel; la apsarea unuia dintre ele, metoda ntoarce valoarea corespunzatoare i fereastra de dialog dispare; - pentru dialog de intrare (showInputDialog) - fereastra conine un mesaj, un cmp de text i dou butoane: OK i Cancel. Utilizatorul introduce n cmpul de text o valoare (un ir de caractere sau un numr) i apasa tasta <Enter> sau actioneaza cu mouse-ul butonul OK. n ambele cazuri fereastra de dialog dispare, iar metoda ntoarce irul introdus n cmpul de text. Dac se apas butonul Cancel, fereastra de dialog dispare, iar metoda ntoarce null. - pentru dialog de opiune (showOptionDialog), care ntrunete caracteristicile celor trei tipuri de mai sus. Pentru fiecare din aceste patru tipuri de ferestre de dialog exist mai multe metode cu numele corespunztor, care difer ntre ele prin lista de argumente. Pentru detalii trimitem la documentaia Java API.

Exemplu n fiierul Dialog1.java este dat un exemplu de aplicaie, n care se testeaz diferitele tipuri de ferestre de dialog create cu metodele statice ale clasei javax.swing.JOptionPane. Fereastra principal a aplicaiei conine un buton cu inscripia "Introducere text" i o arie de text (JTextArea). Cnd este acionat butonul, apare o fereastr de dialog de intrare, cu mesajul "Introducei un text". Dac se acioneaza butonul OK fr s fi introdus nimic n cmpul de text, apare o noua fereastr de dialog, care conine mesajul de avertisment "Nu se permite un ir vid". Dac se introduce un ir n cmpul de text i se acioneaza butonul OK sau tasta Enter, apare o nou fereastr de dialog, care cere confirmarea c acest text trebuie introdus n aria de text. Dac se rspunde prin acionarea butonului Yes, se face adugarea, iar dac se rspunde prin apsarea butonului No sau Cancel, fereastra de dialog dispare fr s se fac adugarea textului. ntruct ntregul dialog este declanat, n cazul de fa, prin acionarea butonului "Introducere text", programul prin care se realizeaz dialogul a fost plasat n metoda actionPerformed a clasei IntroducereText care ascult evenimentele de aciune generate de butonul menionat.

/* Alegerea culorilor folosind obiectele de culoare predefinite din clasa Color

268

Programarea orientata pe obiecte n limbajul Java

*/ import java.awt.*; import java.awt.event.*; import javax.swing.*; //import javax.swing.event.*;

class Dialog1 { static AF af=new AF(); static IntroducereText it=new IntroducereText(); static IUG iug=new IUG("Utilizarea unei ferestre de dialog"); /* clasa imbricata pentru interfata utilizator grafica */ static class IUG extends JFrame { JTextArea arieText; IUG(String titlu) { // constructorul clasei IUG super(titlu); setSize(250, 200); setLocation(100, 50); Container cp=getContentPane(); addWindowListener(af); // adaugarea ascultatorului de fereastra JButton buton1=new JButton("Introducere text"); buton1.addActionListener(it); cp.add(buton1, BorderLayout.NORTH); arieText=new JTextArea(); arieText.setLineWrap(true); arieText.setWrapStyleWord(true); cp.add(arieText, BorderLayout.CENTER); setVisible(true); } } /* Clasa ascultatoare de fereastra */ static class AF extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); // incheierea executarii aplicatiei } } /* Clasa pentru introducerea textului prin fereastra de dialog */ static class IntroducereText implements ActionListener { public void actionPerformed(ActionEvent e) { String sirIntrodus; boolean terminat=false; while(!terminat) { sirIntrodus=JOptionPane.showInputDialog("Introduceti un text"); if(sirIntrodus!=null) { if(sirIntrodus.trim().equals("")) JOptionPane.showMessageDialog(iug, "Nu se permite un sir vid!", "Avertisment", JOptionPane.WARNING_MESSAGE); else { int raspuns=JOptionPane.showConfirmDialog(iug, "Doriti adaugarea textului: "+sirIntrodus+"?"); if(raspuns==JOptionPane.YES_OPTION) iug.arieText.append(sirIntrodus+"\n");

269

Severin Bumbaru

terminat=true; } } else terminat=true; } } } /* Metoda principala a aplicatiei */ public static void main(String args[]) { } }

Cu privire la metoda actionPerformed din clasa IntroducereText remarcm urmtoarele: 1) Instruciunea


sirIntrodus=JOptionPane.showInputDialog("Introduceti un text");

are ca efect afiarea pe ecran a unei ferestre de dialog de intrare. irul introdus n cmpul de text al acestei ferestre este intors i atribuit variabilei sirIntrodus. Dac s-a acionat butonul Cancel, metoda ntoarce null. 2) Instruciunea
JOptionPane.showMessageDialog(null, "Nu se permite un sir vid!","Avertisment", JOptionPane.WARNING_MESSAGE);

are ca efect afiarea unei ferestre de dialog care conine un mesaj de avertisment. 3) Instruciunea
int raspuns=JOptionPane.showConfirmDialog(iug, "Doriti adaugarea textului: "+sirIntrodus+"?");

are ca efect afiarea unei ferestre de dialog de confirmare, care ntoarce o valoare de tip int, care poate fi egal cu una din cosnstantele YES_OPTION, NO_OPTION sau CANCEL_OPTION care sunt definite n clasa JOptionPane. n rest, considerm c procedura de dialog rezult clar din textul metodei. Pentru aprofundarea utilizrii ferestrelor de dialog, recomandm consultarea capitolului How to Make Dialogs din Java Tutorial.

Alegerea culorii
n multe aplicaii, la proiectarea interfeei utilizator grafice este necesar s se impun culorile de fond i de primplan ale diferitelor componente, folosind metodele clasei Component public void setBackground(Color color) - pentru culoarea de fond; public void setForeground(Color color) - pentru culoarea de prim-plan (a textului). Pentru reprezentarea i manipularea informaiei despre culoare se folosete clasa java.awt.Color. Cea mai simpl utilizare a acestei clase este utilizarea culorilor predefinite, pe care le conine sub forma de cmpuri statice. De exemplu, culoarea albastru este reprezentat prin cmpul static Color.blue, iar culoarea galben prin Color.yellow. n consecin, dac dorim s punem componentei comp culoarea

270

Programarea orientata pe obiecte n limbajul Java de fond albastru i culoarea de primplan galben, vom folosi instruciunile:
comp.setBackground(Color.blue); comp.setForeground(Color.yellow);

Pentru a afla toate culorile predefinite i celelalte specificaii privind clasa Color trimitem cititorii la documentaia Java API. Culorile predefinite sunt folosite i n exemplul care urmeaz.

Exemplu n fiierul Culori.java se d un exemplu de aplicaie, n care se demonstreaz utilizarea culorilor predefinite din clasa java.awt.Color. Fereastra aplicaiei conine o list cu denumirile culorilor predefinite din clasa Color i un panou pe care se afieaz culorile respective, prin setarea corespunztoare a culorii de fond a panoului. Cnd se selecteaz o culoare din list, se observa imediat modificarea corespunztoare a culorii panoului. n acest scop, n program au fost folosite dou tablouri: numeCulori - este un tablou de iruri (String[]) care conin numele culorilor; tablouCulori - este un tablou de instane ale clasei Color, care conine toate culorile predefinite din aceasta clas. Lista de culori listaCulori din clasa JList este construit pe baza tabloului numeCulori i deci conine ca articole numele culorilor (denumirile puteau fi date n limba romn, dar am preferat ca cititorii s se familiarizeze cu cele existente n clasa Color). Cnd se selecteaz un articol din list, se genereaz un ListSelectionEvent. Pentru ascultarea lui s-a creeat clasa AscultaLista. n metoda valueChanged a acestei clase, se determin indicele articolului care a fost selectat i se seteaz drept culoare de fond a panoului culoarea cu acelai indice din tablouCulori.

/* Alegerea culorilor folosind obiectele de culoare predefinite din clasa Color */ import import import import java.awt.*; java.awt.event.*; javax.swing.*; javax.swing.event.*;

class Culori { static AF af=new AF(); static IUG iug=new IUG("Alegerea culorii din lista"); /* clasa imbricata pentru interfata utilizator grafica */ static class IUG extends JFrame { JPanel panouCuloare; // panoul pe care se prezinta culoarea String[] numeCulori={"black", "darkGray", "gray", "lightGray", "white", "blue", "cyan", "green", "orange", "yellow", "red", "pink", "magenta"}; Color[] tablouCulori={Color.black, Color.darkGray, Color.gray, Color.lightGray, Color.white, Color.blue, Color.cyan, Color.green, Color.orange, Color.yellow, Color.red, Color.pink, Color.magenta};

271

Severin Bumbaru

JList listaCulori; IUG(String titlu) { // constructorul clasei IUG super(titlu); setSize(250, 200); setLocation(100, 50); Container cp=getContentPane(); addWindowListener(af); // adaugarea ascultatorului de fereastra panouCuloare=new JPanel(); // crearea panoului pentru culoare cp.add(panouCuloare, BorderLayout.CENTER); Color[] tablouCulori={Color.black, Color.darkGray, Color.white}; listaCulori=new JList(numeCulori); listaCulori.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); listaCulori.addListSelectionListener(new AscultLista()); JScrollPane panouCulori=new JScrollPane(listaCulori); cp.add(panouCulori, BorderLayout.WEST); setVisible(true); } }

/* Clasa ascultatoare de fereastra */ static class AF extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); // incheierea executarii aplicatiei } } /* Clasa ascultatoare a listei de culori */ static class AscultLista implements ListSelectionListener { public void valueChanged(ListSelectionEvent e) { int indiceCuloare=iug.listaCulori.getSelectedIndex(); iug.panouCuloare.setBackground(iug.tablouCulori[indiceCuloare]); } } /* Metoda principala a aplicatiei */ public static void main(String args[]) { } }

Clasa Color
Clasa Color ncapsuleaz informaiile despre culoare. n Java AWT se folosete modelul de culori RGB (englez: red, green, blue) n care fiecare culoare este considerat ca fiind compus din trei culori fundamentale: rou, verde i albastru. n consecin, culoarea este dat prin trei numere cuprinse n intervalul [0, 255], reprezentnd ponderile celor trei culori fundamentale. n figura de mai jos este reprezentat schema de combinare a acestor trei culori fundamentale.

272

Programarea orientata pe obiecte n limbajul Java

Prin modificarea ponderilor celor trei culori se pot obine, n principiu, toate culorile posibile, de la negru [r=0,g=0,b=0] la alb [r=255,g=255,b=255]. Dac ponderile celor trei culori sunt egale, se obin diferite nuane de gri. Culoarea galben are ponderile [r=255,g=255,b=0], culoarea cyan (azuriu) are ponderile [r=0,g=255,b=255] iar culoarea magenta are ponderile [r=255,g=0,b=255]. Alte culori: orange: [r=255,g=200,b=0], pink (roz): [r=255,g=175,b=175]. Clasa Color conine i un al patrulea cmp, numit alpha, care poate avea, de asemenea, valori ntregi n intervalul [0..255] i exprima opacitatea culorii respective. Daca alpha=255, culoarea este complet opaca. Aceasta nseamn c, dac o figur cu aceast culoare se suprapune peste alta, o mascheaz complet. Dac alpha=0, culoarea este complet transparent, deci practic invizibil. ntre aceste valori extreme putem avea diferite opaciti intermediare, cuprinse intre 0 si 255. Culoarea n sistemul RGB poate fi exprimat nu numai printr-o instan a clasei Color, ci i printr-un numr ntreg (de tip int), n care cei patru octei au, respectiv, valorile componentelor alpha, r, g, b exprimate n intervalul [0..255]. Componentele sunt plasate astfel: alpha n biii 24..31, r n biii 16..23, g n biii 8..15 i b n biii 0..7. Clasa Color conine, de asemenea, constructori i metode care suport sistemele de culori sRBG i HSB. Standardul sRGB definete o variant standardizat a sistemului RGB, destinat monitoarelor cu tub catodic. n acest sistem, parametrii r, g, b i alpha se exprim prin numere reale n intervalul [0.0...1.0].

Sistemul de culori HSB (englez: Hue, Saturation and Brightness) ofera o descriere a culorilor independent de sistemul de afiare, folosind urmtorii trei parametri: Nuana (englez: Hue) care se exprim n grade, n intervalul [0..360], unde 0 este rosu, 60 este galben, 120 este verde etc. Saturaie (englez: Saturation) este puritatea culorii, exprimat n procente, n intervalul [0..100]. La valoarea 0, nuana (Hue) nu are semnificatie, iar la valoarea 100 culoarea este pur. Strlucire (englez: Brightness) este exprimat de asemenea n procente, n intervalul [0..100]. Valoarea 0 nseamn negru (iluminare 0%), deci parametrii Hue i Saturation nu au

273

Severin Bumbaru sens. Valoarea 100 reprezint strlucirea maxim. Diagrama de mai jos d o reprezentare a culorilor exprimate n sistemul HSB.

n clasa Color, parametrii Hue, Saturation i Brightness se exprim prin numere reale (tipul float) n intervalul [0.0 .. 1.0]. Dac valorile sunt n afara acestui interval, se ia n consideraie numai partea fracionara: de exemplu valoarea 2.73 se consider echivalent cu 0.73. n aceste condiii, dac se consider saturaia i strlucirea egale cu 1.0 (100%), valorile parametrului Hue (nuan) pentru principalele culori sunt: red: h=0.0; yellow: h=0.6666 (600); green: h=0.3333 (1200); cyan: h=0.5 (1800); blue: h=0.6666 (2400); magenta: h=0.8333 (3000) Culoarea neagra (black) se obtine punnd strlucirea Brightness=0, iar culoarea alb (white) se obine punand saturaia Saturation=0 i strlucirea Brightness=1. Dac se menine saturaia la valoarea 0 i se dau strlucirii diferite valori ntre 0 i 1 se obin nuanele de gri.

Variabile: Clasa Color conine variabile statice finale (constante) care sunt instanieri ale clasei pentru diferite culori tipice:
black, blue, cyan, darkGray, gray, green, lightGray, magenta, orange, pink, red, white yellow.

Acestea sunt, respectiv, culorile negru, albastru, azuriu, gri inchis, gri, verde, gri deschis, mov, roz, rosu, alb i galben. De exemplu, culoarea verde va fi reprezentata prin Color.green. Toate aceste culori sunt opace, deci au componenta alpha cu valoarea 255.

274

Programarea orientata pe obiecte n limbajul Java

Constructori: Clasa Color are mai muli constructori, dintre care menionm aici pe cei mai frecvent folosii: public Color(int r, int g, int b) - n care argumentele r,g,b sunt numere ntregi n intervalul [0..255], reprezentnd ponderile culorilor red, green, blue, iar componenta alpha are implicit valoarea 255; public Color(int r, int g, int b, int alpha) - similar cu cel precedent, indicndu-se n plus gradul de opacitate alpha, de asemenea n intervalul [0..255]; public Color(int rgb) - creeaz o culoare opac cu parametrii r,g,b dai ultimii trei octei ai argumentului rgb; public Color(int rgba, boolean hasalpha) - creeaz o culoare pornind de la parametrii alpha,r,g,b mpacetai n cei patru octei ai argumentului rgba. Daca al doilea argument este true, parametrul alpha (bitii 24..31 ai argumentului) este luat n consideraie; public Color(float r, float g, float b) - creeaz o culoare opac n sistemul sRGB, n care r,g,b sunt ponderile culorilor fundamentale n intervalul [0.0...1.0], iar alpha are valoarea implicit 1.0; public Color(float r, float g, float b, float alpha) - creeaz o culoare n sistemul sRGB, fiind dai toti cei patru parametri. Metode: Menionm aici metodele cel mai frecvent utilizate.
public public public public public public public int getRed() - ntoarce ponderea culorii red (rosu); int getGreen() - ntoarce ponderea culorii green(verde); int getBlue() - ntoarce ponderea culorii blue(albastru); int getAlpha() - ntoarce componenta alpha(opacitatea culorii); Color brighter() - creeaz o versiune mai luminoas a acestei culori; Color darker() - creeaz o versiune mai ntunecat a acestei culori; static Color getHSBColor(float h, float s, float b) - creeaz o

instan a clasei Color (deci n sistemul RGB) pornind de la parametrii h, s i b ai culorii respective, exprimai is sistemul HSB, n intervalul [0.0 ... 1.0]; public static int HSBtoRGB(float h, float s, float b) - transform parametrii h,s,b ai culorii exprimate n sistemul HSB prin numere reale n intervalul [0.0 ... 1.0] ntr-un numr ntreg (int), n care cei patru octei sunt parametrii r,g,b,alpha ai aceleeai culori exprimate n sistemul RGB; O prezentare mai complet a cmpurilor, constructorilor i metodelor clasei Color este dat n Indexul de clase. Exemplul 1: n fiierul TestRGB.java este dat un exemplu de aplicaie, n care se testeaz compunerea diferitelor culori n sistemul RGB. n partea stng a ferestrei sunt trei rigle de ajustare (JSlider) pentru cele trei culori fundamentale (rou, verde, albastru). n dreptul fiecrei rigle exist un cmp de text n care se afieaz valoarea indicat, n ntervalul [0, 255]. n partea dreapt a ferestrei exist un panou (JPanel) a crui culoare de fond corespunde combinaiei de culori date de cele trei rigle.

275

Severin Bumbaru Putei ajusta culorile i urmri efectul produs. Exemplul 2: n fiierul TestHSB.java este dat un exemplu de aplicaie n care se testeaz alegerea culorilor n sistemul HSB. Fereastra se aseaman cu cea din exemplul precedent, dar cele trei rigle servesc pentru ajustarea componentelor HSB: nuana, saturaie i strlucire. Valorile corespunztoare sunt indicate n cmpurile de text alturate, ca numere reale n intervalul [0.0, 1.0]. La partea inferioar a ferestrei sunt afiate componentele culorii n sistemul RGB.

/* Alegerea culorilor in sistemul HSB (Hue, Saturation, Brightness) */ import import import import java.awt.*; java.awt.event.*; javax.swing.*; javax.swing.event.*;

class TestHSB { static AF af=new AF(); static IUG iug=new IUG("Alegerea culorii in sistemul HSB"+ " (Hue, Saturation, Brightness)"); /* clasa imbricata pentru interfata utilizator grafica */ static class IUG extends JFrame { AjustCuloare hue, satur, bright; // rigle de ajustare a culorilor Box box1; // caseta riglelor de ajustare JPanel panouCuloare; // panoul pe care se prezinta culoarea Color culoare; // culoarea panoului panouCuloare JLabel culoriRGB; // pentru afisarea culorilor in sistem RGB IUG(String titlu) { // constructorul clasei IUG super(titlu); setSize(500, 200); setLocation(100, 50); Container cp=getContentPane(); addWindowListener(af); // adaugarea ascultatorului de fereastra /* Se creeaza caseta cu dispozitive de ajustare */ box1=Box.createVerticalBox(); hue=new AjustCuloare("Nuanta "); // ajustarea nuantei box1.add(hue); satur=new AjustCuloare("Saturatie "); // ajustarea saturatiei box1.add(satur); bright=new AjustCuloare("Stralucire "); // ajustarea stralucirii bright.ajustare.setPaintLabels(true); box1.add(bright); cp.add(box1, BorderLayout.WEST); panouCuloare=new JPanel(); // crearea panoului pentru culoare cp.add(panouCuloare, BorderLayout.CENTER); culoriRGB=new JLabel(); // crearea etichetei cu valori RGB cp.add(culoriRGB, BorderLayout.SOUTH); puneCuloarea(); // se pune culoarea initiala setVisible(true); }

276

Programarea orientata pe obiecte n limbajul Java

/* Metoda de determinare a culorii RGB */ void puneCuloarea() { culoare=new Color(Color.HSBtoRGB(hue.fval, satur.fval, bright.fval)); // conversie din HSB in RGB panouCuloare.setBackground(culoare); culoriRGB.setText("Culori RGB -> rosu: "+ culoare.getRed()+" verde: "+culoare.getGreen()+ " albastru: "+culoare.getBlue()); } } /* Un "dispozitiv" de ajustare a valorii unei culori */ static class AjustCuloare extends Box implements ChangeListener { JTextField valoare; // camp pentru afisarea valorii HSB JSlider ajustare; // rigla de ajustare a valorii float fval=1.0f; // valoarea HSB (in intervalul 0,..,1). AjustCuloare(String culoare) { super(BoxLayout.X_AXIS); add(new JLabel(culoare)); add(Box.createHorizontalGlue()); ajustare=new JSlider(JSlider.HORIZONTAL, 0, 100,100); ajustare.setMajorTickSpacing(20); ajustare.setMinorTickSpacing(10); ajustare.setPaintTicks(true); ajustare.addChangeListener(this); add(ajustare); add(Box.createHorizontalStrut(5)); valoare=new JTextField("1.00",4); valoare.setHorizontalAlignment(JTextField.RIGHT); valoare.setEditable(false); valoare.setBackground(Color.white); valoare.setMaximumSize(valoare.getMinimumSize()); add(valoare); add(Box.createHorizontalStrut(5)); } /* metoda de ascultare a deplasarii cursorului riglei */ public void stateChanged(ChangeEvent e) { fval=ajustare.getValue()/100.0f; // determinarea valorii reale // in intwervalul 0,..1 valoare.setText((fval+" ").substring(0,4)); // afisarea valorii iug.puneCuloarea(); // modificarea culorii panoului } }

/* Clasa ascultatoare de fereastra */ static class AF extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); // incheierea executarii aplicatiei } }

/* Metoda principala a aplicatiei */ public static void main(String args[]) {

277

Severin Bumbaru

} }

Ajustnd valorile prin intermediul riglelor, constatm urmtoarele: - Dac strlucirea este 0.0, culoarea obinut este negru, indiferent de valorile celorlalte dou componente. Cu ct valoarea strlucirii este mai mare, culoarea obinut este mai deschis. - Dac saturaia este 0.0, valoarea nuanei nu are efect: n acest caz, modificnd strlucirea de la 0.0 la 1.0 se obin diferite nuane de gri, de la negru la alb. - Dac saturaia i strlucirea au valori diferite de 0.0, culoarea se poate ajusta prin modificarea nuanei. Cu ct saturaia este mai mare, nuana respectiv este mai pronunat, iar cu ct strlucirea este mai mare, culoarea este mai deschis.

Alegerea culorii folosind clasa JColorChooser


Pentru a alege culoarea n mod interactiv, n JFC/Swing este prevazut clasa javax.swing.JColorChooser. Instanele acestei clase sunt panouri de selectare a culorii, care pot fi folosite att prin ncorporarea lor ntr-o fereastr obinuit, ct i sub forma unei ferestre de dialog. Pentru a creea o fereastr de dialog, care conine n ea un JColorChooser i ntoarce culoarea selectat, n clasa JColorChooser exist metoda
public static JDialog createDialog(Component c,String title, boolean modal, JColorChooser chooserPane, ActionListener okListener, ActionListener cancelListener)

n care: - c este componenta beneficiar (owner) a ferestrei de dialog create; - title este titlul ferestrei de dialog create; - argumentul boolean modal indic dac fereastra este modal; - chooserPane este instana clasei JColorChooser care se ntroduce n fereastra de dialog; - okListener si cancelListener sunt asculttoarele de aciune care reacioneaza la apsarea butonului OK, respectiv Cancel al selectorului de culoare. Folosind un JColorChooser, alegerea culorii se poate face n trei moduri: - folosind un tablou de culori, n care fiecare celul este colorat n alt culoare; - n sistemul RGB, folosind trei rigle de ajustare a culorilor fundamentale; - n sistemul HSB, selectnd culoarea prin alegerea cu mouse-ul a punctului de pe panou care are culoarea potrivita (trei butoane alturate, notate H, S, B, arat care din cele trei componente se menine constant, celelalte dou fiind date de coordonatele punctului ales pe panou). Exemplu n fiierul SelectCulori.java se d un exemplu de aplicaie n care, pentru alegerea culorii unui panou, se folosete o fereastr de dialog, n care se gsete un JColorChooser.

/* Alegerea culorilor folosind un JColorChooser */ import java.awt.*; import java.awt.event.*;

278

Programarea orientata pe obiecte n limbajul Java

import javax.swing.*; class SelectCulori { static AF af=new AF(); static AscultDialog ascultDialog=new AscultDialog(); static AscultButon ascultButon=new AscultButon(); static IUG iug=new IUG("Alegerea culorii folosind JColorChooser"); /* clasa imbricata pentru interfata utilizator grafica */ static class IUG extends JFrame { JPanel panouCuloare; // panoul pe care se prezinta culoarea JColorChooser selectorCuloare; JDialog dialogCuloare; IUG(String titlu) { // constructorul clasei IUG super(titlu); setSize(350, 200); setLocation(100, 50); Container cp=getContentPane(); addWindowListener(af); // adaugarea ascultatorului de fereastra panouCuloare=new JPanel(); // crearea panoului pentru culoare cp.add(panouCuloare, BorderLayout.CENTER); selectorCuloare=new JColorChooser(); JButton butonCuloare=new JButton("Schimbarea culorii"); butonCuloare.addActionListener(ascultButon); butonCuloare.setToolTipText("Selectarea culorii panoului"); cp.add(butonCuloare, BorderLayout.SOUTH); dialogCuloare=JColorChooser.createDialog(butonCuloare, "Alegerea culorii", true, selectorCuloare, ascultDialog, ascultDialog); setVisible(true); } } /* Clasa ascultatoare de fereastra */ static class AF extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); // incheierea executarii aplicatiei } } /* Ascultator actiuni fereastra dialog */ static class AscultDialog implements ActionListener { public void actionPerformed(ActionEvent e) { if(e.getActionCommand().equals("OK")) iug.panouCuloare.setBackground( iug.selectorCuloare.getColor()); } } /* Ascultarea butonului de comanda */ static class AscultButon implements ActionListener { public void actionPerformed(ActionEvent e) { iug.dialogCuloare.show(); } } /* Metoda principala a aplicatiei */

279

Severin Bumbaru

public static void main(String args[]) { } }

Elemente de grafic
Java API ofera programatorilor posibiliti ample privind realizarea de desene, text stilizat i alte construcii grafice. Ne vom rezuma aici numai la cteva noiuni elementare, utile n realizarea unor aplicaii grafice simple. Pentru aprofundare recomandm lectia Working with Graphics din Java Tutorial. Studiul poate fi apoi continuat cu seciunea 2D Graphics a aceluiai tutorial. In principiu, desenarea se poate face pe orice component grafic. Exist ns clasa java.awt.Canvas, ale crei instane sunt simple panouri destinate desenrii (n englez Canvas este pnza pictorului). Pentru desenare se mai folosesc frecvent i clasele JPanel i JLabel. Sistemul de coordonate folosit pentru grafic are originea n colul din stnga sus al componentei, axa Ox este orientat catre dreapta, iar axa Oy este orientat n jos. Coordonatele se exprim n numere ntregi (int), avnd ca unitate de msur pixelul (punctul de pe ecran).

Contextul grafic
Modul de realizare a imaginilor i desenelor este strns dependent att de echipament (hardware) ct i de sistemul de operare. Pentru a se asigura independena de platform, n Java API a fost introdus clasa abstract java.awt.Graphics. Aceasta este clasa de baz a tuturor contextelor grafice, care permit trasarea de desene pe suprafaa componentelor grafice realizate pe diverse dispozitive fizice. Pe fiecare platform, n mediul de execuie Java, trebuie s existe o implementare a contextului grafic, adic o extindere a clasei Graphics, care conine toate cmpurile i metodele acestei clase, dar este specific platformei respective. Un obiect din clasa Graphics ncapsuleaz informaia de stare a contextului grafic la care se refer i anume: - referina la obiectul din clasa Component (sau dintr-o subclasa a acesteia) pe care se deseneaz; - o translaie a originii sistemului de coordonate; toate coordonatele din desen sunt raportate la aceast origine; - decupajul curent (dreptunghiul n interiorul cruia se traseaz desenul); - culoarea curent; - fontul curent; - operaia logic pe pixeli curent (XOR sau paint); - alternarea curent de culori pentru operaia pe pixeli XOR.

280

Programarea orientata pe obiecte n limbajul Java

Originea sistemului de axe (punctul de coordonate 0,0) se gsete n colul din stnga-sus al dreptunghiului de desenare. Axa 0x este ndreptat spre dreapta, iar axa 0y - in jos. Practic, clasa abstract Graphics conine acele metode, care trebuie s existe n orice context grafic. Coninutul concret al acestor metode, deci modul efectiv n care se realizeaz funciile respective, depinde de contextul grafic real, deci de dispozitivul fizic pe care se face desenarea i de sistemul de operare folosit. Pe programatorul de aplicaii sau miniaplicaii n Java nu l intereseaz ns acest lucru, deoarece el folosete n programele sale metodele clasei abstracte Graphics, fr s se preocupe de modul n care acestea vor fi executate.

Principalele metode ale clasei Graphics sunt urmtoarele:


public abstract Graphics create() - creeaz i ntoarce un nou obiect din clasa Graphics, care este o copie a obiectului pentru care se aplic aceast metod; public abstract Graphics create(int x, int y, int width, int height) creeaz i ntoarce o copie a obiectului din clasa Graphics cruia i se aplic, ns cu o noua translaie a originii (x,y) i cu valori noi valori ale limii i nlimii dreptungiului de desenare (suprafeei de decupare); public abstract void translate(int x, int y) - translateaz originea sistemului de coordonate n punctul (x,y) al sistemului de coordonate curent; public abstract Color getColor() - ntoarce culoarea de desenare curent; public abstract void setColor(Color c) - seteaz culoarea de desenare curent; public abstract Font getFont() - ntoarce fontul curent; public abstract void setFont(Font f) - seteaz fontul curent; public abstract FontMetrics getFontMetrics() - ntoarce metrica fontului curent; public abstract void setFontMetrics(FontMetrics fm) - seteaz metrica fontului curent; public abstract Rectangle getClipBounds() - ntoarce dreptunghiul de decupare curent; public abstract void setClip(int x, int y, int width, int height) seteaz dreptunghiul de decupare curent; public abstract void copyArea(int x, int y, int width, int height, int dx, int dy) - copiaza suprafaa dreptunghiulara cu originea (x,y), limea width i

nlimea height ntr-o noua zon de aceleai dimensiuni, avnd originea (x+dx, y+dy).. public abstract void setPaintMode() - seteaz operaia logic pe pixeli curent la modul paint, adic desenarea se face peste fondul existent, folosinduse culoarea de desenare curent, fr a lua n consideraie culoarea fondului. public abstract void setXORMode(color c1) - seteaz operaiile pe pixeli la modul XOR, adic se alterneaz pixelii de culoare curent cu cei din culoarea c1; aceasta nseamn c, dac un pixel nou plasat are aceeai culoare curent cu cea existent anterior n acelai loc, ea va fi nlocuita cu c1; invers, dac pixelul existent anterior avea culoarea c1, ea va fi nlocuit cu culoarea curent. public abstract void drawLine(int x1, int y1, int x2, int y2) - se traseaza o linie dreapt din punctul de coordonate (x1,y1) pn n punctul (x2,y2); public abstract void drawRect(int x, int y, int width, int height) - se traseaz un dreptunghi cu colul din stnga sus n punctul (x,y), avnd limea width i

281

Severin Bumbaru nlimea height;


public abstract void fillRect(int x, int y, int width, int height) umple cu culoarea curent interiorul dreptunghiului cu colul din dreapta sus n punctul (x,y) i cu dimensiunile (width, height); public abstract void clearRect(int x, int y, int width, int height) terge coninutul dreptunghiului de coordonate i dimensiuni specificate, umplndu-l cu culoarea de fond; public abstract void drawRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) - traseaz un dreptunghi cu colurile rotunjite, unde

arcWidth si arcHeight sunt respectiv diametrul orizontal i diametrul vertical al arcelor de rotunjire;
public abstract void fillRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) - umple cu culoarea curent interiorul unui dreptunghi cu

colurile rotunjite;
public abstract void draw3DRect(int x, int y, int width, int height, boolean raised) - deseneaz un dreptunghi astfel luminat, nct el apare c iese din

suprafaa de baza, dac raised=true, sau este scufundat n aceasta suprafa, dac raised=false;
public abstract void fill3dRect(int x, int y, int width, int height, boolean raised) - umple cu culoarea curent interiorul unui dreptunghi tridimensional,

lund n consideraie i iluminarea;


public abstract void drawOval(int x, int y, int width, int height)

- se

deseneaz ovalul nscris n dreptunghiul cu colul din stnga sus n punctul (x,y) i cu dimensiunile (width, height); - se umple cu culoarea curent coninutul ovalului nscris n dreptunghiul cu colul stnga sus n punctul (x,y) i de dimensiuni (width, height);
public abstract void drawArc(int x, int y, int width, int height, int startAngle, int arcAngle) - se deseneaz un arc circular sau eliptic, care se nscrie n public abstract void fillOval(int x, int y, int width, int height)

dreptunghiul specificat. Putem s ne imaginm c din elipsa nscris n acest dreptunghi i avnd centrul n centrul dreptunghiului, se traseaz efectiv numai arcul care ncepe de la unghiul startAngle i se extinde pe un unghi egal cu arcAngle. Unghiurile sunt msurate n grade. Unghiul 0 este corespunzator poziiei de la ora 3 a acului de ceasornic, iar sensul pozitiv al unghiurilor este cel contra acelor de ceasornic;
public abstract void fillArc(int x, int y, int width, int height, int startAngle, int arcAngle) - umple cu culoarea curent sectorul mrginit de arcul

specificat prin parametri i de razele de la capete;


public abstract void drawPolyline(int[] xPoints, int[] yPoints, int nPoints) - traseaz o linie frnt, care trece prin punctele ale cror coordonate (x,y) sunt

date n tabelele xPoints i yPoints; numrul de puncte este nPoints;


public abstract void drawPoligon(int[] xPoints, int[] yPoints, int nPoints) - traseaz un poligon cu nPoints vrfuri, situate n punctele ale cror coordonate

(x,y) sunt date n tabelele xPoints i yPoints;


public abstract void drawPoligon(Poligon p)

- traseaz poligonul specificat ca

argument;
public abstract void fillPoligon(int[] xPoints, int[] yPoints, int nPoints) - umple cu culoarea curenta un poligon cu nPoints vrfuri, situate n punctele

ale cror coordonate (x,y) sunt date n tabelele xPoints i yPoints; public abstract void fillPoligon(Poligon p) - umple cu culoarea curent poligonul specificat ca argument; public abstract void drawString(String str, int x, int y) - traseaz irul

282

Programarea orientata pe obiecte n limbajul Java de caractere str, folosind fontul i culoarea curente; baza primului caracter al irului este n punctul de coordonate (x,y);
public abstract void drawString(AttributedCharacterIterator iterator, int x, int y) - traseaz un ir de caractere coninute n obiectul iterator, care specific nu

numai caracterele propriuzise ci i fontul fiecrui caracter; baza primului caracter este n punctul de coordonate (x,y);
public abstract void drawChars( char[] data, int offset, int length, int x, int y) - traseaz length caractere din tabloul data, ncepnd cu caracterul cu

indicele offset; baza primului caracter se gsete n punctul de coordonate (x,y); fontul i culoarea sunt cele curente;

Metodele paint si repaint


Pentru desenarea pe suprafaa unei componente, n clasa java.awt.Component (rdcina ierarhiei de clase a componentelor) exist metoda
public void paint(Graphics g)

Aceast metod traseaza efectiv desenul, folosind n acest scop contextul grafic g primit ca argument. Contextul grafic nu este instaniat de ctre programator, ci este transmis acestei metode de ctre maina virtual Java. n schimb, metoda paint trebuie redefinit n program pentru orice component pe care dorim s se traseze un desen. n aceast scop se folosesc n metoda paint metodele de desenare ale clasei Graphics. Metoda paint nu este invocat explicit n program. Ea este invocat implicit (de ctre maina virtual Java) atunci cnd componenta respectiv este afiat pe ecran sau i modific dimensiunile i/sau poziia. Dac, totui, programatorul dorete s solicite explicit desenarea, folosete metoda
public void repaint()

Aceasta metod care exist, de asemenea, n clasa java.awt.Component, nu trebuie redefinit, singurul ei rol fiind de a apela metoda paint.

Exemplul 1: n fiierul Desen.java este dat un exemplu de aplicaie simpl, n care se testeaz diferite metode ale clasei Graphics. n acest scop, s-a creat clasa PanouDesen ca o extensie a clasei Canvas. n aceast clas, a fost redefinit metoda paint(), astfel nct s se traseze diferite desene: un dreptunghi gol, un dreptunghi plin, un dreptunghi gol cu colurile rotunjite, un dreptunghi plin cu colurile rotunjite, un oval gol, un oval plin, o linie frnt i un poligon. Sau testat n acest fel metodele clasei Graphics. n fereastra aplicaiei s-a introdus o instan a clasei PanouDesen.

/* Testarea clasei Graphics In fereastra aplicatiei iug se introduce suprafata de desenare panouDesen din clasa PanouDesen, care este derivata din clasa Canvas In clasa PanouDesen, metoda paint() este redefinita, astfel incat sa traseze mai multe desene, testandu-se metodele clasei Graphics */

283

Severin Bumbaru

import java.awt.*; import java.awt.event.*; import javax.swing.*; class Desen { static Sfarsit sfarsit=new Sfarsit(); static IUG iug=new IUG("Exemplu de desenare"); static class IUG extends JFrame { PanouDesen panouDesen; IUG(String titlu) { super(titlu); addWindowListener(sfarsit); panouDesen=new PanouDesen(); setLocation(200,150); getContentPane().add(panouDesen); setSize(220,200); setVisible(true); } }

static class Sfarsit extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); } } static class PanouDesen extends Canvas { public void paint(Graphics g) { setBackground(Color.white); g.setColor(Color.black); g.drawRect(5,5,40,25); g.drawRect(50,5,40,25); g.setColor(Color.blue); g.fillRect(50,5,40,25); g.setColor(Color.red); g.drawRoundRect(100,5,40,25,10,10); g.drawRoundRect(150,5,40,25,10,10); g.setColor(Color.green); g.fillRoundRect(150,5,40,25,10,10); g.drawOval(5,40,40,25); g.drawOval(50,40,40,25); g.setColor(Color.magenta); g.fillOval(50,40,40,25); g.setColor(Color.black); g.drawArc(100,40,40,25,-5,130); g.drawArc(150,40,40,25,-5,130); g.setColor(Color.green); g.fillArc(150,40,40,25,-5,130); g.setColor(Color.black); int[] xlf={5,30,55,80,100,125}, ylf={100,70,85,75,75,80}; g.drawPolyline(xlf,ylf,6); int[] xp={15,50,75,65,55}, yp={100,90,95,120,150}; g.drawPolygon(xp,yp,5);

284

Programarea orientata pe obiecte n limbajul Java

g.setColor(Color.yellow); g.fillPolygon(xp,yp,5); } } public static void main(String args[]) { } }

Exemplul 2: n fiierul GraficeFunctii.java este dat un exemplu de aplicaie pentru trasarea graficelor unor funcii. n fereastra aplicaiei s-au pus: - panoul fct, care conine o list de selectie a funciei de reprezentat i trei cmpuri de text, n care se introduc de la tastatur marginile inferioar i superioar a intervalului n care se traseaz funcia (sub forma de numere reale) i numrul de subintervale n care se mparte acesta; - suprafaa de afiare gr, pe care se traseaz graficul; - eticheta mesaj, n care se afieaz eventualele mesaje de eroare. Pentru panoul fct a fost creat clasa Functii, derivat din clasa JPanel i s-a folosit gestionarul de poziionare GridLayout. Pentru suprafaa de afiare s-a creat clasa Grafic, derivat din clasa Canvas. Clasa Actiuni intercepteaz evenimentele generate de fereastra principal, cmpurile de text i lista de selecie a funciilor. n acest scop, ea este derivat din clasa WindowAdapter i implementeaz interfeele ActionListener i ItemListener. Trasarea graficului se face sub forma unei linii frnte, folosind metoda drawPoliline(int x[],int y[],int nrPuncte), n care vectorii x i y conin coordonatele punctelor prin care trece curba. Scrile de reprezentare pe cele dou axe se aleg automat, astfel nct graficul s ocupe ntreaga suprafa de desenare. n acest scop, se calculeaz mai nti valorile reale ale funciei de reprezentat, completndu-se cu ele vectorul real valy. Se determin apoi ymax i ymin, iar dimensiunile suprafeei de desenare se determin prin metodele getWidth() i getHeight(), iar xmin i xmax sunt date. Folosind aceste date se calculeaz scrile pe x i y, dup care se calculeaz coordonatele pe desen ale punctelor, completndu-se astfel vectorii x i y. Aceste calcule se fac n metoda calcul() din clasa Actiuni, iar trasarea graficului se face n metoda paint() din clasa Grafic.

/* Aplicatie de trasare a graficelor unor functii. Se selecteaza functia de trasat si se introduc valorile marginilor intervalului de reprezentare. Trasarea functiei se face fie cand se selecteaza o noua functie, fie cand este selectat unul din campurile de text si se apasa tasta <Enter>. Daca se introduc date gresite, nu se traseaza functia, ci apare un mesaj de eroare */

285

Severin Bumbaru

import java.awt.*; import java.awt.event.*; import javax.swing.*; class GraficeFunctii { static Actiuni act=new Actiuni(); static Functii fct=new Functii(); static Grafic gr=new Grafic(); static Label mesaj=new Label(); static boolean trasare=false; static int nrPasi=200; // numarul de subintervale static int nrNoduri=nrPasi+1; // numarul de puncte ale graficului static int indFunc; // indicele functiei care se reprezinta grafic // Tabele de coordonate ale punctelor graficului functiei static int x[]=new int[nrNoduri], y[]=new int[nrNoduri]; // inaltimea si latimea suprafetei de desenare si pozitiile axelor static int inaltime, latime, xord, yabsc;

public static void main(String args[]) { JFrame fp=new JFrame("Grafice de functii"); Container cp=fp.getContentPane(); cp.add(fct,"North"); cp.add(gr,"Center"); gr.setBackground(Color.cyan); cp.add(mesaj,"South"); mesaj.setBackground(Color.green); fp.addWindowListener(act); fp.setSize(500,500); fp.setVisible(true); } // Introducerea datelor si calcularea coordonatelor static class Functii extends JPanel { // Componenta de selectare a functiei JLabel lab=new JLabel("Alegeti functia de reprezentat"); Choice f=new Choice(); // Campurile de text pentru introducerea marginilor intervalului // si numarului de subintervale JTextField inf=new JTextField("-6.28"); JTextField sup=new JTextField("6.28"); JTextField pasi=new JTextField("200"); // Constructorul clasei Functii Functii() { // Adaugarea de functii la lista de optiuni f.add("x^2"); f.add("x^3"); f.add("log(1+x^2)-1"); f.add("sin(x)"); f.add("cos(x)"); f.add("exp(-abs(0.1*x))*cos(x)"); f.add("cos(x)/sqrt(1+x*x)"); // Setarea gestionarului de pozitionare setLayout(new GridLayout(4,2)); // Adaugarea componentelor

286

Programarea orientata pe obiecte n limbajul Java

add(new Label("Alegeti functia de reprezentat: ")); add(f); add(new Label("Marginea inferioara a intervalului: ")); add(inf); add(new Label("Marginea superioara a intervalului: ")); add(sup); add(new Label("Numarul de subintervale pentru trasare: ")); add(pasi); // Adaugarea la componente a interceptorului de evenimente inf.addActionListener(act); sup.addActionListener(act); pasi.addActionListener(act); f.addItemListener(act); } // Calcularea valorii functiei in punctul de abscisa x double func(double x) { switch(indFunc) { case 0: return x*x; case 1: return x*x*x; case 2: return Math.log(1+x*x)-1; case 3: return Math.sin(x); case 4: return Math.cos(x); case 5: return Math.exp(-Math.abs(0.1*x))*Math.cos(x); case 6: return Math.cos(x)/Math.sqrt(1.0+x*x); } return 0.0; }

} // Captarea si tratarea evenimentelor static class Actiuni extends WindowAdapter implements ActionListener, ItemListener { public void windowClosing(WindowEvent e) { System.exit(0); } public void actionPerformed(ActionEvent e) { reprezinta(); } public void itemStateChanged(ItemEvent e) { reprezinta(); } public void reprezinta() { try { calcul();//Se calculeaza coordonatele punctelor graficului gr.repaint();//Se traseaza graficul functiei } catch(Exception e) { mesaj.setText("eroare: "+e); } } // Calcularea coordonatelor tuturor punctelor graficului void calcul() throws Exception { double xmin,xmax,ymin,ymax,pas,scarax,scaray; // Initializari mesaj.setText("");

287

Severin Bumbaru

trasare=false; gr.repaint(); // Preluarea datelor introduse in campurile de text int nrP=Integer.parseInt(fct.pasi.getText()); if(nrP<1) throw new Exception("Numar de intervale incorect"); if(nrP != nrPasi) { nrPasi=nrP; nrNoduri=nrPasi+1; x=new int[nrNoduri]; y=new int[nrNoduri]; } xmin=Double.parseDouble(fct.inf.getText()); // marginea din stanga xmax=Double.parseDouble(fct.sup.getText()); // marginea din dreapta if(xmin==xmax) throw new Exception("xmin==xmax"); pas=(xmax-xmin)/nrPasi; // Lungimea subintervalului double valy[]=new double[nrNoduri];// tabloul ordonatelor // Preluarea indicelui functiei selectate indFunc=fct.f.getSelectedIndex(); // se afla indicele functiei // Determinarea dimensiunilor suprafetei de desenare inaltime=gr.getHeight(); // inaltimea suprafetei de desenare latime=gr.getWidth(); // latimea suprafetei de desenare // Calcularea ordonatelor punctelor graficului for (int i=0; i<nrNoduri; i++) valy[i]=fct.func(xmin+i*pas); // Determinarea valorilor minima si maxima ale lui y ymin=valy[0]; ymax=valy[0]; for (int i=1; i<nrNoduri; i++) { if(valy[i]>ymax) ymax=valy[i]; if(valy[i]<ymin) ymin=valy[i]; } // Determinarea scarilor de reprezentare pe cele doua directii scarax=latime/(xmax-xmin); scaray=inaltime/(ymax-ymin); // Calcularea coordonatelor de pe desen ale punctelor graficului for(int i=0; i<nrNoduri; i++) { y[i]=inaltime-(int)Math.round((valy[i]-ymin)*scaray); x[i]=(int)Math.round(i*pas*scarax); } // Determinarea pozitiilor pe desen ale axelor de coordonate yabsc=inaltime+(int)Math.round(ymin*scaray); xord=(int)Math.round(-xmin*scarax); trasare=true; } } // Componenta pe care se traseaza desenul static class Grafic extends Canvas { // Metoda de trasare a graficului public void paint(Graphics g) { if(!trasare) return; // Trasarea axelor de coordonate g.setColor(Color.blue); if(yabsc>=0 && yabsc<=inaltime) g.drawLine(0,yabsc,latime,yabsc); if(xord>=0 && xord<=latime) g.drawLine(xord,0,xord,inaltime); // Trasarea curbei (sub forma de linie franta) g.setColor(Color.red); g.drawPolyline(x,y,nrNoduri); }

288

Programarea orientata pe obiecte n limbajul Java

} }

ntrebri
Nivel 1
1. 2. 3. 4. 5. 6. 7. 8. 9. Ce sunt ferestrele de dialog? Ce deosebire exist ntre ferestrele de dialog modale i cele nemodale? Ce sunt ferestrele de dialog standard? Cum se creeaza ferestrele de dialog standard? Cum se stabilete culoarea de fond a unei componente? Ce este culoarea de prim plan a unei componente i prin ce metod se modific? Ce sunt instanele clasei Color? Care este principalul model de culori folosit n Java? Prin ce tip de date se exprim culorile n sistemul RGB i care este intervalul n care acestea iau valori? 10. Care este culoarea pentru care cele trei culori fundamentale RGB au valoarea 0? 11. Care este culoarea pentru care toate cele trei culori fundamentale au valoarea 255? 12. La ce folosete clasa JColorChooser? 13. Pe ce fel de componente se poate face desenarea? 14. Care este sistemul de coordonate pentru reprezentri grafice? 15. Care este unitatea de msur folosit pe axele de coordonate pentru reprezentri grafice? 16. Ce este contextul grafic? 17. Prin ce clas abstract este reprezentat contextul grafic n Java API? 18. n ce clas este declarat metoda paint i ce rol are ea? 19. Cum este invocat metoda paint? 20. n ce scop este redefinit metoda paint? 21. Ce trebuie s conin corpul metodei paint pentru a se trasa un desen? 22. La ce folosete metoda repaint? 23. Se redefineste n program metoda repaint?

Nivel 2
1. Prin ce clas se realizeaz ferestrele de dialog n JFC/Swing? 2. Ce relaie exist ntre fereastra de dialog i proprietarul ei? 3. Prin ce metod se afieaz pe ecran o fereastr de dialog? 4. Prin ce metode se nchide o fereastr de dialog? 5. Care tipuri de ferestre pot fi create folosind metodele clasei JOptionPane? 6. Ce conine o fereastr de dialog de mesaj? 7. Ce conine o fereastr de dialog de confirmare? 8. Ce conine o fereastr de dialog de intrare i cum este ea utilizat? 9. Ce este modelul HSB? 10. Prin ce tip de date se exprim componentele modelului HSB i n ce interval de valori?

289

Severin Bumbaru 11. Pentru ce fel de culori HSB saturaia are valoarea 0.0? 12. Cum se creeaz o instan a clasei JColorChooser? 13. Cum poate fi afiat un JColorChooser sub form de fereastr de dialog? 14. Ce modele de culori se folosesc n JColorChooser? 15. Ce cmpuri conine un obiect al clasei Graphics? 16. Ce fel de metode conine clasa Graphics? 17. Unde se plaseaz n program redefinirea metodei paint?

290

Programarea orientata pe obiecte n limbajul Java

Introducere n HTML. Crearea i utilizarea appleturilor


Introducere n HTML Ce este un hipertext Ce este WWW Ce este HTML Ctructura documentului HTML Carcaje de formatare a textului folosite frecvent Legaturi catre alte pagini Marcajul APPLET Utilizarea marcajelor HTML n textele introduse n componentele JFC/Swing Applet-uri Clasa Applet ntrebri. 291

Introducere n HTML
Dei prezentarea limbajului HTML nu constituie un obiectiv al acestui manual, vom da aici unele noiuni introductive asupra acestui limbaj, fiind utile pentru o mai bun nelegere a utilizrii appleturilor.

Ce este un hipertext
Hipertextul (englez: hypertext) este o colecie de documente, numite i noduri sau pagini, unite ntre ele prin legturica n Figura 1.

291

Severin Bumbaru

- Figura 1 Este necesar, desigur, s se adopte o convenie privind modul n care se nsereaza n pagina de hipertext legturile ctre alte pagini. Pentru utilizatorul care vede pe ecran pagina respectiv, aceast legtur apare, de regul, sub forma unui cuvnt sau unui grup de cuvinte puse n eviden prin subliniere, colorare sau prin ambele procedee. Dac se face click cu mouse-ul pe o astfel de "legtura", pagina curent se schimb cu pagina ctre care indic legtura respectiv. Citirea unui asemenea hipertext nu se face cu un editor de texte obinuit, ci cu un program special numit navigator sau browser. Paginile (nodurile) hipertextului sunt stocate sub forma de fiiere, situate pe un singur calculator, sau pe mai multe calculatoare legate n reea.

Ce este WWW
World-Wide Web (WWW) este un sistem de regsire a informaiei distribuite pe Internet. n limba englez, web nseamn "plasa", "reea", "pnz de pianjen", ceeace sugereaz legaturile existente ntre noduri ntr-un hipertext. Asadar, WWW este o astfel de "pnz de pianjen" care acopera ntreaga lume i ale crei noduri sunt documente. Documentele sunt stocate sub form de fiiere pe diferite calculatoare, care acioneaza ca servere de web. Utilizatorul poate naviga pe aceast reea, folosind un program numit browser de web (navigator). Cele mai rspndite browsere de web sunt, n prezent, Netscape Navigator i Internet Explorer. Putem deci considera c WWW este perceput de utilizator ca un hipertext, ale crui noduri sunt raspndite n ntreaga lume. Transmiterea prin Internet a paginilor WWW se face folosind un protocol special, numit HTTP (Hypertext Transfer Protocol), iar pentru marcarea paginilor de WWW, cu scopul de a nsera n ele legturile necesare, se folosete un limbaj numit HTML.

Ce este HTML
HyperText Markup Language (HTML) este un limbaj de marcare a hipertextelor. n esten, o pagin HTML este un fiier de text ASCII, care conine nite simboluri speciale, numite marcaje sau taguri. Prin aceste marcaje se indic legturile ctre alte documente i ctre

292

Programarea orientata pe obiecte n limbajul Java appleturi, imagini sau secvene audio incluse n document, dndu-se, de asemenea, informaii privind formatarea documentului i altele. Fiecare marcaj (tag) este de forma <tag> ... </tag>, deci ncepe printr-un nume de marcaj (tag) cuprins ntre paranteze unghiulare i se termin prin acelai marcaj, avnd n faa numelui simbolul / (slash). Astfel, fiecare document HTML ncepe cu marcajul <html> i se termin cu </html>. n limbajul HTML nu se face distincie n marcaje ntre literele mari i cele mici, deci tagul <HTML> ... </HTML> este echivalent cu tagul <html> ... </html>. Aceste marcaje pot fi cuprinse unul n altul, ca n Figura 2.a, dar nu este permis ca domeniile lor s se intersecteze, ca n Figura 2.b.

- Figura 2 Pentru crearea de documente HTML se poate folosi un editor de text simplu, n mod ASCII, dar - n acest caz - cel care creeaz documentul trebuie s cunoasc bine sintaxa HTML i toate tagurile acestuia. Mult mai comoda este folosirea unor editoare speciale de pagini Web, cum sunt Netscape Composer sau Front Page, care prezint interfa utilizator grafic, iar pe ecran se vede documentul sub forma n care acesta apare i in browser.

Structura documentului HTML


Un document HTML are urmatoarea structur: <HTML> <HEAD> Antetul documentului </HEAD> <BODY> Corpul documentului </BODY> </HTML> Modul de punere n pagin nu are importan, deoarece ntreaga informaie despre structur i formatare este coninuta n marcaje (taguri). Acelai document poate fi pus n pagina, de exemplu, astfel: <HTML><HEAD>Antetul documentului </HEAD><BODY>Corpul documentului </BODY></HTML> Antetul documentului conine, opional, titlul acestuia i informaii despre autor, tipul de document etc. O component important a antetului este titlul documentului, care are forma:

293

Severin Bumbaru <TITLE>Titlul documentului</TITLE> Titlul este un text, care apare n bara de titlu a browserului care vizualizeaz documentul respectiv. Corpul documentului este documentul propriu-zis, care se afieaz pe ecran, inclusiv legturile coninute n documentul respectiv.

Marcaje de formatare a textului folosite frecvent


Marcarea paragrafelor
Fiecare paragraf este cuprins ntre marcajele <P> .. </P>. Totusi, folosirea marcajului de sfrit de paragraf </P> nu este obligatorie. Atunci cnd documentul este vizualizat n browser, fiecare paragraf ncepe de la capt de linie. n interiorul paragrafului, trecerea la linie nou se face automat, cnd se ajunge la marginea din dreapta a paginii. Se poate, totui, fora trecerea la linie nou prin marcajul <br> (prescurtare de la break). n marcajul <P> se pot introduce i indicaii privind culoarea de fond, culoarea caracterelor i forma caracterelor din paragraful respectiv. Aceste indicaii se dau prin parametri de forma nume=valoare. Culoarea caracterelor se indic prin parametrul color=culoare, unde culoare poate fi: black (negru), gray (gri), silver (argintiu), white (alb), red (rosu), green (verde), blue (albastru), yellow (galben), lime (verde deschis), aqua (albastru deschis), fuchsia (roz), purple (purpuriu), maroon (maron), olive (oliv), navy (bleu marin), teal (verde inchis). Remarcm c sunt alte nume de culori dect cele din clasa java.awt.Color. Culoarea fondului se indic prin parametrul bgcolor=culoare, unde numele culorilor sunt aceleai ca pentru caractere. Forma caracterelor cu care este scris paragraful este indicat prin parametrul face=forma. n funcie de platform, se pot folosi diferite forme de caractere. Exist, totui, trei forme care sunt disponibile pe orice platform: Serif, sansSerif si Monospace. Primele dou au caractere de lime variabil (de exemplu, m este mai lat decat i), iar ultimul are toate caracterele de aceeasi lime (exemplu: n cuvantul lime, scris cu astfel de caractere, m i i au aceeai lime). Deosebirea ntre Serif i SansSerif este prezent, respectiv absena serifurilor. Acestea sunt liniuele mici care delimiteaz unele linii ale literelor, cum se poate observa comparnd caracterele din cuvintele de mai jos:

Serif SansSerif
Indicarea fontului
Se numete font tipul de liter folosit ntr-un text. Termenul este preluat din tipografie i se refer la reprezentarea formei i mrimii unui caracter. S-a menionat mai sus cum pot fi indicate forma i culoarea caracterelor dintr-un paragraf ca parametri n marcajul <P>. Exista ns i situaii n care un anumit font se folosete numai ntr-o poriune de paragraf, sau se extinde pe mai multe paragrafe. n acest scop, se folosete marcajul <font parametri> text</font>. Parametrii din marcajul <font > sunt face=form, color=culoare i size=mrime. Forma i culoarea se indic n acelai mod ca n marcajul <P>. Mrimea este un numr ntreg cu sau 294

Programarea orientata pe obiecte n limbajul Java fr semn. Dac se folosete un numr ntreg fr semn, acesta indic mrimea absolut a fontului. Mrimea indicat ca numar intreg cu semn n intervalul [-3, +3] arat mrimea relativ, fa de cea pentru care este setat browserul utilizat. Aa dar, de exemplu, parametrii size=3 si size=+3 indic fonturi de mrimi diferite. Exemplu Textul HTML urmtor:
<font face=serif color=purple size=+1> proba de text </font>

va apare scris pe ecran sub forma

proba de text
Nu este obligatoriu s se indice toi cei trei parametri. Se folosesc numai cei prin care noul font difer de cel anterior.

Indicarea stilului
n afar de forma, marimea i culoarea fontului, textul se caracterizeaz i prin stil: pstrnd forma fontului, textul poate s apar ngroat, cursiv, subliniat etc. n HTML, stilul textului se indic prin marcaje speciale: <B> ... </B> pentru text aldin, ngrosat (englez: bold); <I> ... </I> pentru text cursiv (englez: italic); <U> ... </U> pentru text subliniat (englez: underline); <strike> ... </strike> pentru text tiat cu o linie (englez: strikethrough); <sub> ... </sub> text scris mai mic i mai jos dect textul de baz (englez: subscript); <sup> ... </sup> text scris mai mic i mai sus dect cel de baz (englez: superscript). Aceste stiluri pot fi i combinate. De exemplu, textul HTML
<B><I><U>text aldin, cursiv i subliniat</U></I></B>

apare pe ecran sub forma: text aldin, cursiv i subliniat

Marcarea titlurilor i subtitlurilor


Titlurile diferitelor seciuni ale textului (capitole, subcapitole etc) se pun n eviden prin faptul c apar scrise cu caractere diferite de restul textului (de regul mai mari) i sunt distanate prin cte o linie att de textul de deasupra, ct i prin cel de dedesubt. Pentru marcarea titlurilor se folosete marcajul <Hn>titlu</Hn> n care n este un numr ntreg cuprins n intervalul [1, 6]. Cu ct cifra n este mai mare, titlul respectiv se afieaz scris cu caractere mai mici. De exemplu, textul HTML
<H1>Primul titlu></H1><H2>Al doilea titlu</H2><H3>Al treilea titlu</H3>

apare pe ecran sub forma

Primul titlu
Al doilea titlu
Al treilea titlu
Se poate astfel continua pn la marcajul <H6>.

295

Severin Bumbaru

Text preformatat
S-a artat mai sus c aezarea textului n pagin se face de ctre browser, respectnd marcajele de formatare din textul HTML. n consecin, dac se modific dimensiunile ferestrei, se modifica i aezarea n pagin a textului. Spaiile i caracterele speciale din textul HTML, cum sunt caracterul de trecere la linie nou sau de ntoarcere a carului sunt ignorate de browser i nu au efect la afiarea pe ecran. Exist, totui un marcaj care impune ca textul sa fie aezat pe ecran aa cum este el n pagina HTML. Acest marcaj este <PRE> text preformatat </PRE>. De exemplu, textul
<PRE> un exemplu de text preformatat scris pe trei linii </PRE>

va apare pe ecran sub forma


un exemplu de text preformatat scris pe trei linii

Legturi ctre alte pagini


Legturile cu alte documente sunt marcate prin ancore, care sunt taguri de forma: <A HREF="referin la document">text de legtur</A> Parametrul HREF (Hypertext Reference) reprezint indicarea locului n care poate fi gsit documentul ctre care se face trimiterea (referina la document). Aceast referin nu este vizibil n fereastra de browser n care este afiat documentul. n schimb, este vizibil textul de legtur, sub forma unui text subliniat i avnd o culoare diferit de a restului documentului. Referina la document depinde de locul n care acesta se gsete. a/ Documentul int se gsete pe acelasi calculator. n acest caz, referina poate fi: a1/ Referina absolut, de forma: cale/document unde cale (engleza: path) este succesiunea de directoare parcurse de la rdcina arborelui de directoare, pn la directorul n care se gsete fiierul care conine documentul; pentru separarea directoarelor se folosete bara (slash, /), conform conveniei din sistemul de operare Unix. De exemplu:
"C:/d1/d2/d3/docum.html"

este o referin la documentul docum.html, care se gsete pe discul C, urmnd calea d1/d2/d3/ unde d1, d2 si d3 sunt directoare. Dac documentul int se gsete pe acelai disc cu documentul n care apare aceast referin, discul poate fi omis, punnd referina sub forma
"/d1/d2/d3/docum.html"

dar avnd grij s nceap cu "/", ceeace nseamn c se pornete de la rdcin, deci este o referin absolut. a2/ Referina relativ, n care calea se traseaz pornind de la directorul n care se gsete documentul surs.La indicarea cii, simbolul .. (doua puncte succesive) nseamn deplasare cu un director napoi, iar / nseamna deplasare cu un director nainte. De exemplu, referina:
"../../d2/d3/docum.html"

are semnificaia urmtoare: pornind de la directorul n care se gsete documentul surs, ne deplasm dou directoare "napoi" ctre rdacin, dup care parcurgem "nainte" calea d2/d3 i ajungem la documentul docum.html. b/ Documentul int se gsete pe un alt calculator. n acest caz, referina la document este

296

Programarea orientata pe obiecte n limbajul Java un URL (englez: Uniform Resource Locator), care este modul de adresare caracteristic pentru WWW. Iat exemple de URL-uri:
"http://www.w3.org/default.html" "http://java.sun.com/docs/books/jls/html/index.html" "http://lib.cs.ugal.ro/~sbumbaru/CursJava/Sapt01/poo.html"

Prima parte a URL-ului (n cazul de fa http:) reprezint protocolul de transmisie folosit. Cele dou bare (//) indic modul de acces (n cazul de fa - adresa pe Internet a unui calculator, de exemplu java.sun.com). Urmeaza calea absolut parcurs pe calculatorul respectiv (de exemplu /docs/books/jls/html/) i numele documentului (index.html).

Modul de adresare pe Internet este, n principiu, urmtorul: Internetul este mprit n domenii, care pot fi domenii naionale (de exemplu: ro - Romania, fr - Franta, uk - Marea Britanie, de - Germania etc) sau domenii profesionale (com - comercial, edu - educaional, org - organizaii, net - retele). Fiecare domeniu este imparit n subdomenii (de ex.: n domeniul ro exist subdomeniul ugal - Universitatea din Galati, iar n domeniul com exist subdomeniul sun - firma Sun Microsystems). Subdomeniile pot fi mprite n subsubdomenii s.a.m.d pn se ajunge la calculatoare individuale. De exemplu, locaia atlas.stud.ugal.ro nseamn calculatorul atlas din subreeaua stud, din subdomeniul ugal al domeniului ro.

Marcajul APPLET
Pentru a introduce ntr-un document HTML o referin la un applet, se folosete marcajul (tagul) APPLET, care are forma urmtoare: <APPLET CODE=fiier_class [CODEBASE=localizare] WIDTH=lime HIGHT=nlime[ALIGN=aliniere]> [<PARAM NAME=nume VALUE=valoare>]* [text_de_nlocuire] </APPLET> n care: fiier_class - fiierul cu extensia .class, n care se afl bytecode-ul appletului (indicarea extensiei nu este obligatorie), de exemplu: CODE=TestFlowAp.class sau CODE=TestFlowAp localizare - referina la directorul n care se gsete bytecode-ul appletului; aceast referin poate fi absolut, relativ sau sub forma de URL, la fel ca n cazul legturilor ctre alte documente, cu observaia c nu se mai termin prin numele documentului int, acesta fiind cel din parametrul CODE; dac fiierul bytecode al appletului se gsete n acelai director cu fiierul HTML n care acesta este invocat, parametrul CODEBASE lipsete; lime si nlime - numere ntregi, reprezentnd limea i nlimea appletului; aliniere - alinierea appletului n pagina de browser, poate fi una din urmtoarele: left | right | top | texttop | middle | absmiddle | baseline | bottom | absbottom unde left i right indic aliniere la stnga sau la dreapta, top - aliniere cu elementul cel mai nalt din linie (fie el text, imagine sau alt applet), texttop - aliniere cu cel mai nalt element de text din linia respectiv, middle - mijlocul appletului se aliniaz cu mijlocul liniei de baz a textului, absmiddle - mijlocul appletului se aliniaz cu mijlocul elementului cel mai mare din linie, baseline sau bottom - baza appletului se aliniaz cu linia de baz a textului, absbottom - baza appletului va fi elementul cel mai de jos din linie. text_de_nlocuire- un text care va apare n locul appletului, dac browserul folosit pentru vizualizarea documentului HTML nu este capabil sa utilizeze appleturi.

297

Severin Bumbaru Dac este necesar, marcajul APPLET poate s conin unul sau mai muli parametri, care se vor transmite appletului la lansarea acestuia. Aceti parametri apar n subtagul PARAM, pentru fiecare din ei indicndu-se un nume i o valoare.

Exemplul 1: marcajul <APPLET CODE="CBGroupAp" WIDTH=180 HEIGHT=80> Testarea clasei CheckboxGroup </APPLET> se folosete pentru a include n documentul HTML a unui applet, al crui fiier de bytecode este CBGroupAp.class i se gsete n acelasi director cu documentul HTML n care exist acest tag. Appletul va avea limea 180 i nlimea 80. Dac browserul folosit nu suport appleturi java, n locul rezervat appletului va apare textul de nlocuire "Testarea clasei CheckboxGroup". Exemplul 2: marcajul <APPLET CODE=PrimApplet CODEBASE=../Sapt01/surse WIDTH=200 HEIGHT=100>Primul applet</APPLET> se folosete pentru a include n documentul HTML appletul al crui fiier bytecode este PrimApplet.class i care se gsete n alt director dect fiierul HTML, dar pe acelai disc. n CODEBASE s-a folosit forma relativa a cii. Exemplul 3: marcajul <APPLET CODE=PrimApplet CODEBASE=/CursJava/Sapt11/surse WIDTH=200 HEIGHT=100> Primul applet </APPLET> are aceeai semnificaie ca cel din exemplul anterior, dar n CODEBASE s-a folosit forma absolut a cii. Exemplul 4: marcajul <APPLET CODE=PrimApplet CODEBASE=http://lib.cs.ugal.ro/~sbumbaru/CursJava/Sapt11/surse WIDTH=200 HEIGHT=100> Primul applet </APPLET> are aceeai semnificaie ca cel din exemplul anterior, dar n CODEBASE se folosete un URL la care poate fi gsit appletul respectiv.

Folosirea de parametri n appleturi


n marcajul APPLET pot fi introdui i unul sau mai muli parametri, folosind n acest scop sub-marcajul [<PARAM NAME=nume VALUE=valoare>]* Att numele, ct i valoarea sunt iruri. Preluarea n applet a fiecruia din aceti parametri se face invocnd metoda
public String getParameter(String name)

care primete ca argument numele parametrului i ntoarce valoarea acestuia sub forma de ir. Avantajul este c valorile parametrilor pot fi modificate direct n fiierul HTML, fr s mai

298

Programarea orientata pe obiecte n limbajul Java fie necesar s se modifice i s se recompileze programul appletului. Exemplu: n fiierul DouaTexte.java este dat un exemplu de applet n care sunt preluai doi parametri, cu numele textul1 si textul2. Aceti parametri sunt iruri de caractere, care se afieaz alternativ ntr-o etichet. Schimbarea textului se face la apsarea pe buton. Acest applet este inclus n pagina HTML din fiierul DouaTexte.html prin urmtorul marcaj: <APPLET CODE=DouaTexte WIDTH=250 HEIGHT=100 ALIGN=middle> <PARAM NAME=textul1 VALUE="Acesta este primul text"> <PARAM NAME=textul2 VALUE="Acesta este al doilea text"> </APPLET> Pentru a se afia alte texte, este suficient s se modifice n mod corespunztor valorile parametrilor din acest marcaj, fr a se face modificri n programul appletului.

Utilizarea marcajelor HTML n textele pentru componentele JFC/Swing


n mod obinuit, textul introdus n componentele AWT sau JFC/Swing prin metoda void setText(String text) apare pe ecran pe suprafaa componentei respective sub forma unui text scris pe o singura linie, folosind fontul SansSherif, culoarea neagra i o mrime implicit. ncepnd cu platforma Java 2 (SDK 1.2) n textele introduse n componentele JFC/Swing (cum ar fi cele din clasele JButton, JLabel, JPanel etc.) pot fi folosite marcaje HTML. Dac textul introdus prin metoda setText() ncepe cu marcajul <HTML>, el este interpretat ca un text HTML i tratat n mod corespunztor. Aceasta nseamn c textul poate s apar pe suprafaa componentei respective pe mai multe linii, s aib diferite fonturi, culori i stiluri, conform cu marcajele HTML utilizate. Dac, ns, sintaxa HTML nu este respectat, metoda genereaz o excepie.

Exemplu n fiierul TextHTML.java este dat un exemplu de aplicaie, n care se experimenteaz folosirea textelor HTML n componentele interfeei grafice. n fereastra aplicaiei sunt plasate urmtoarele componente: - o arie de text (JTextArea), n care se afieaz un text iniial, care poate fi apoi modificat de utilizator; - o etichet (JLabel) pe suprafaa creia se afieaz textul existent n aria de text din partea stng; - un buton cu inscripia Vizualizare text, a crui acionare are ca efect afiarea pe suprafaa etichetei a textului din aria de text; - un al doilea buton, cu inscripia Reset, a crui acionare are ca efect revenirea la textul

299

Severin Bumbaru afiat iniial n aria de text. nscripiile de pe cele dou butoane au fost formatate folosind marcaje HTML. n aria de text este introdus iniial un text HTML, care poate fi vizualizat apsnd pe butonul Vizualizare text. Acest text poate fi ns modificat n fereastra din stnga i vizualizat n eticheta din dreapta, apsnd pe acelai buton. Dac se dorete, apoi, revenirea la textul iniial, se apas butonul Reset. Se pot experimenta, astfel, diferite modificri ale textului iniial sau se poate introduce oricnd un text obinuit sau un hipertext nou.
/* Experimentarea folosirii marcajelor HTML in textele pentru componente JFC/Swing */ import java.awt.*; import java.awt.event.*; import javax.swing.*; class TextHTML extends JFrame { JTextArea ta; JLabel label; Sfarsit sfarsit; /* Textul introdus initial in aria de text */ String textInitial="<html>\n<h2>Proba HTML</h2>Text normal<br>\n"+ "<i>Text italic <b>Text italic aldin</b></i><br>\n"+ " <font face=serif color=blue size=4>\n"+ " Text albastru cu font serif\n </font>\n<p bgcolor=aqua>"+ "Revenire la text normal<br>cu fond aqua\n</html>"; /* Constructorul clasei TextHTML construieste interfata grafica */ TextHTML() { super("Incercare de texte HTML"); Container cp=getContentPane(); sfarsit=new Sfarsit(); // incheierea executarii aplicatiei addWindowListener(sfarsit); ta=new JTextArea(15,10); // aria in care se introduce textul HTML ta.setLineWrap(true); ta.setWrapStyleWord(true); ta.append(textInitial); ta.setBorder(BorderFactory.createTitledBorder( "Introduceti aici un text HTML")); Box vb=Box.createVerticalBox(); Box hb=Box.createHorizontalBox(); vb.add(ta); String textButon="<html><font color=red size=4>"+ "<b><i>Vizualizare text</i></b></font>"; JButton buton=new JButton(textButon); // butonul de comanda a // vizualizarii textului buton.addActionListener(new Vizualizare()); buton.setBorder(BorderFactory.createRaisedBevelBorder()); hb.add(buton); JButton reset=new JButton("<html><font color=blue size=4>"+ "<b>Reset</b></font>"); // butonul de revenire la textul initial reset.setBorder(BorderFactory.createRaisedBevelBorder()); reset.addActionListener(new Reset()); hb.add(reset); vb.add(hb);

300

Programarea orientata pe obiecte n limbajul Java

cp.add(vb,BorderLayout.WEST); label=new JLabel(); // eticheta pe care se vizualizeaza textul HTML label.setBorder(BorderFactory.createTitledBorder( "Vizualizarea textului HTML")); label.setOpaque(true); label.setBackground(Color.white); cp.add(label,BorderLayout.CENTER); setLocation(50,50); setSize(450,300); setVisible(true); } /* Clasa de ascultare a inchiderii ferestrei principale*/ class Sfarsit extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); } } /* clasa de ascultare a butonului de vizualizare a textului */ class Vizualizare implements ActionListener { public void actionPerformed(ActionEvent e) { try { /* afisarea pe componenta label a textului extras din aria de text ta */ label.setText(ta.getText()); } catch(Exception ex) { // s-a constatat o eroare in textul HTML label.setText("Eroare de sintaxa HTML"); } } } /* Clasa de ascultare a butonului de Reset */ class Reset implements ActionListener { public void actionPerformed(ActionEvent e) { ta.setText(textInitial); label.setText(""); } } public static void main(String args[]) { TextHTML text=new TextHTML(); // instantierea aplicatiei } }

Remarcm c, n aceast aplicaie, s-au introdus urmtoarele abordri noi fa de aplicaiile anterioare: - s-a considerat c interfaa grafic este nsi clasa principala TextHTML, derivata din clasa JFrame. n consecin, adugarea componentelor la fereastra principal se face n constructorul clasei TextHTML; - clasele interioare i cmpurile clasei TextHTML nu au mai fost declarate statice, n schimb, n metoda main() s-a creat o instan a acestei clase. Desigur c acest mod de construire a aplicaiei nu are legtura cu tema acesteia, fiind doar o ilustrare a unui alt mod de lucru posibil n Java.

301

Severin Bumbaru

Applet-uri
Miniaplicaia (englez: applet) este un mic program cu interfa utilizator grafic, care nu poate rula n mod independent, ci este nglobat ntr-o alt aplicaie, numit context de applet. Pentru executarea unui applet trebuie s existe deci dou entiti: applet-ul propriu-zis i contextul n care acesta se execut (englez: applet context). n mod normal, contextul de executare a unui applet este un navigator de Web (englez: web browser), cum sunt Netscape Navigator, Internet Explorer sau HotJava. Pentru testare, appletul poate fi executat, de asemenea, folosind drept context un program de vizualizare special, existent in SDK, numit appletviewer. Orice applet este realizat ca o clas, derivat din clasa Applet, existent n pachetul java.applet, sau derivat din clasa JApplet, care extinde clasa Applet i exist n pachetul javax.swing. ntruct utilizarea clasei JApplet este mai complicat, ne vom rezuma aici la descrierea i exemplificarea utilizrii clasei Applet.

Clasa Applet
Clasa Applet se gsete n pachetul java.applet i este o subclas a clasei Panel din pachetul java.awt. n consecin, applet-ul este, de fapt, un caz special de container. Clasa Applet este superclasa tuturor miniaplicaiilor care sunt ncorporate n pagini Web sau pot fi vizualizate cu un Java Applet Viewer. Clasa Applet motenete metodele superclaselor sale Component, Container i Panel, oferind i metode specifice. Dintre acestea, cele mai importante sunt : init(), start(), stop() i destroy(). Aceste metode sunt apelate de ctre browser n momentele importante ale ciclului de via al unui applet, respectiv n momentul ncrcrii acestuia n memorie, n momentul nceperii sau ntreruperii execuiei i nainte ca appletul s fie distrus. Aa cum sunt ele oferite de clasa Applet, aceste metode nu fac nimic. Ele pot fi ns redefinite de programatori n subclasele clasei Applet, astfel nct s execute anumite aciuni specifice momentelor n care sunt invocate. Metoda init() este utilizat pentru a crea partea "static" a applet-ului: adugarea de componente la applet, nregistrarea asculttorilor de evenimente etc. Ea este redefinit n marea majoritate a applet-urilor. Metodele start() i stop() se folosesc numai pentru lansarea i oprirea proceselor dinamice (de exemplu animaie i/sau sunete) care nu trebuie s continuie cnd appletul nu este vizibil pe ecran. n fine, metoda destroy() se folosete n special pentru a distruge firele de execuie paralele care au fost create de ctre applet, sau a elibera anumite resurse ocupate de acesta.

Principalele metode ale clasei Applet: Vom prezenta aici metodele mai frecvent utilizate. Pentru celelalte recomandm consultarea documentaiei originale.
public void init()

- metoda este invocat de ctre browser sau appletviewer atunci

302

Programarea orientata pe obiecte n limbajul Java cnd appletul este ncrcat n memorie, deci nainte de prima invocare a metodei start(); public void start() - metoda este invocat de ctre browser atunci cnd appletul trebuie s i nceap execuia, adic atunci cnd este vizitat sau revizitat pagina Web n care acesta este inclus; public void stop() - metoda este invocat de ctre browser atunci cnd pagina de Web, n care se gsete appletul, este nlocuit de alta, fr a fi ns eliminat din memorie. ntruct appletul nu mai este vizibil pe ecran, acesta poate sa i nceteze temporar execuia; metoda este invocat, de asemenea, naintea invocrii metodei destroy(); public void destroy() - metoda este invocat de ctre browser nainte de distrugerea appletului; public boolean isActive() - determin dac appletul este activ; public String getAppletInfo() - dac este redefinit n subclase, metoda poate intoarce informaii despre applet: autorul, versiunea, drepturi de autor etc. n clasa Applet metoda ntoarce null; public AppletContext getAppletContext() - ntoarce o referin ctre contextul appletului; public URL getCodeBase() - ntoarce URL-ul (locaia pe Internet) la care se gsete bytecode-ul appletului; public URL getDocumentBase() - ntoarce URL-ul la care se gsete documentul care conine appletul; public String getParameter(String name) - ntoarce valoarea parametrului cu numele dat ca argument, coninut n tagul APPLET al documentului HTML.

Dm n continuare trei exemple de applet-uri, mpreun cu fiierele HTML n care se afieaza acestea. Pentru compatibilitate, s-au utilizat numai componente din pachetele java.applet i java.awt.

Exemplul 1: n introducere a fost deja dat un exemplu de applet simplu, n care nu se redefinete nici o metod a clasei Applet, folosindu-se numai o invocare de metod prin care se scrie un text pe suprafaa appletului. Programul acestui applet se gsete n fiierul PrimApplet.java, iar fiierul HTML n care este folosit acest applet este PrimApplet.html. Exemplul 2: n fiierul CBGroupAp.java este dat un applet de testare a unui grup de casete de validare (butoane radio) din fiierul TestCheckboxGroup.java. Remarcm urmtoarele deosebiri fa de o aplicaie similar: - nu mai exist o fereastr principal sub form de cadru (Frame sau JFrame) ca n cazul aplicaiei, acest rol fiind ndeplinit chiar de ctre applet; - n consecin, nu mai este necesar o clas care sa intercepteze evenimentele generate de fereastra principal; - adugarea componentelor la applet, setarea culorilor i nregistrarea interceptorului de evenimente, care n cazul aplicaiei se fac n metoda main() sau n constructorul interfeei utilizator grafice, acum se fac n metoda init(); - avnd n vedere c, pentru clasa Applet, gestionarul de poziionare implicit este 303

Severin Bumbaru FlowLayout, pentru a utiliza gestionarul BorderLayout acesta a trebuit adugat n mod explicit. Pentru vizualizarea appletului se foloseste fiierul CBGroupAp.html. Exemplul 3: n fiierul TestFlowAp.java se prezint un applet de testare a gestionarului de poziionare FlowLayout. Vizualizarea din browser a acestui applet se face folosind fiierul TestFlow.html. Pe suprafaa appletului apar dou butoane de comand ("Pune" i "Elimina") pentru adaugarea sau eliminarea de etichete i trei butoane radio, prin care se selecteaz modul de aliniere a etichetelor pe suprafaa containerului ("Stnga", "Centru", "Dreapta"). Acionand aceste butoane se poate testa modul de aranjare al etichetelor pentru diferite tipuri de aliniere. Oricare din aceste applet-uri poate fi vizionat i ntr-un appletviewer, dac (din fereastra Xwindow sau MS-DOS) se d comanda:
appletviewer fisierHTML

De exemplu, pentru a vizualiza applet-ul TestFlowAp, se d comanda


appletviewer TestFlow.html

unde TestFlow.html este fiierul HTML n care este invocat acest applet.

ntrebri
Nivel 1
1. Ce este un hipertext? 2. Ce sunt nodurile hipertextului? 3. Ce este WWW? 4. Ce este un browser de Web? 5. Ce este HTTP? 6. Ce este HTML? 7. Ce form au marcajele HTML? 8. Care este marcajul cu care ncepe i se termin un document HTML? 9. Care este structura unui document HTML? 10. n ce zon a documentului HTML se specific titlul acestuia? 11. Cum se specific titlul unui document HTML? 12. Prin ce se marcheaz, ntr-un document HTML, legturile ctre alte pagini ale hipertextului? 13. La ce servete marcajul APPLET i ce conine el? 14. Cum sunt folosite marcajele HTML n componentele JFC/Swing? 15. Ce este un applet? 16. Ce clase se folosesc pentru realizarea applet-urilor? 17. Ce este un context de applet? 18. Ce contexte de applet cunoatei? 19. Din ce clas este derivat clasa Applet? dar clasa JApplet? 20. Care sunt principalele metode ale unui applet i de ctre ce program sunt invocate ele? 21. La ce servete metoda init() n cazul unui applet? 22. Cnd sunt invocate metodele start() i stop() ale unui applet? 23. n ce scop se folosete metoda destroy() a unui applet?

304

Programarea orientata pe obiecte n limbajul Java 24. Cum este utilizat un appletviewer?

Nivel 2
1. Cum se marcheaz paragrafele ntr-un document HTML? 2. Este absolut necesar ca un paragraf s se ncheie cu marcajul </P>? 3. Cum se marcheaz ntr-un document HTML trecerea forat la linie nou? 4. Cum se specific, ntr-un document HTML, culoarea fondului unui paragraf? 5. Cum se specific culoarea caracterelor ntr-un document HTML? 6. Cum se specific forma caracterelor ntr-un document HTML? 7. Care sunt principalele tipuri (forme) de caractere folosite n documentele HTML? 8. Ce conine marcajul <font> i ce semnificaie are? 9. Ce este stilul textului? 10. Cum se marcheaz stilul textului ntr-un document HTML? 11. Cum se marcheaza titlurile i subtitlurile de capitole ntr-un document HTML? 12. Ce este un text preformatat i cum se marcheaz el ntr-un document HTML? 13. Cum se reprezinta, ntr-o legatur HTML, o referin absoluta la alt pagin de pe acelai calculator? 14. Cum se reprezint, ntr-o legatur HTML, o referin relativ la alt pagina de pe acelai calculator? 15. Cum se reprezint, ntr-o legatur HTML, o referin la o pagin situat pe alt calculator de pe Internet? 16. Cum pot fi introdui parametri n marcajul APPLET i la ce folosesc? 17. Ce componente ale interfeei grafice permit folosirea textelor HTML? 18. Prin ce metod se introduce un text HTML ntr-o component JFC/Swing? 19. Ce se ntampl dac, ntr-un text care se pune ntr-o component JFC/Swing, exist o eroare de sintaxa HTML? 20. Ce efect au metodele init(), start() i stop() ale unui applet, aa cum sunt ele coninute n clasa Applet? 21. Este obligatoriu ca, la crearea unei noi clase de applet, s fie redefinite toate cele patru metode principale init(), start(), stop() i destroy()?

305

Severin Bumbaru

Fluxuri de intrare/ieire i fiiere


Fluxuri de intrare/ieire Introducere Pachetul java.io Clasele de baz ale ierarhiilor de fluxuri de intrare/ieire Clasa Reader Clasa Writer Clasa InputStream Clasa OutputStream Consideraii generale privind utilizarea fluxurilor Clasele PrintStream i PrintWriter Fiiere Clasa File Citirea fiierelor Citirea fiierelor de octei: clasa FileIntputStream Citirea fiierelor de caractere: clasa FileReader Scrierea n fiiere Scrierea n fiiere de octei: clasa FileOutputStream Scrierea n fiiere de caractere: clasa FileWriter Fiiere cu acces direct Fluxuri de prelucrare Fluxuri de date Fluxuri de obiecte ntrebri. 306 306 307 310 310 311 312 312 313 313 315 316 319 319 310 322 322 323 324 327 327 329 331

Fluxuri de intrare/ieire i fiiere Introducere


n majoritatea aplicaiilor, este necesar s se transmit date ntre diferite componente cum sunt: memoria intern, tastatura, ecranul, fiierele de pe disc, reeaua de calculatoare etc. Poate fi necesar, de asemenea, s se transmit date ntre dou aplicaii sau ntre dou fire de execuie ale aceleeai aplicaii. n limbajul Java, fluxul (englez: stream) este o cale de comunicaie ntre o surs de date i o destinaie (Figura 1).

306

Programarea orientata pe obiecte n limbajul Java - Figura 1 Fluxul este un concept situat pe un nivel nalt de abstractizare, fiind privit ca o simpl succesiune de octei sau de caractere care se transmite ntre surs i destinaie. Nu prezint importan nici natura sursei sau a destinaiei, nici modul n care trebuie interpretat secvena de octeti sau de caractere respectiv. De exemplu, un grup de 32 de octei transmii ntre surs i destinaie poate s reprezinte 32 de caractere ASCII sau 16 caractere Unicode sau 8 numere de tip int sau 4 numere de tip double etc. Aceast abstractizare permite s se trateze n mod unitar toate tipurile de transmisii de date. Se disting doua feluri de fluxuri: de ieire i de intrare. Pentru un proces dat, toate fluxurile transmise de acesta ctre exterior se numesc fluxuri de ieire, iar cele primite din exterior se numesc fluxuri de intrare. n consecin, acelai flux este de ieire n raport cu sursa i de intrare n raport cu destinaia. Principalele operaii care au loc asupra unui flux sunt:

La surs (flux de ieire) - Deschiderea fluxului - ct timp (exist date de transmis) scriere n flux -nchiderea fluxului

La destinaie (flux de intrare) -Deschiderea fluxului - ct timp (exist date de citit) citire din flux -nchiderea fluxului

Programatorului procesului surs i revine obligaia de a pregti, sub forma unei succesiuni de caractere sau de octei, datele care urmeaz a fi transmise pe fluxul de ieire. Interpretarea i tratarea datelor coninute n flux se face de ctre procesul de destinaie, deci ntreaga responsabilitate i revine celui care programeaz acest proces. Desigur c este necesar ca interpretarea datelor din flux la destinaie s corespund cu cea de la surs. Programarea operaiilor de intrare/ieire poate fi destul de complicat, dar n limbajul Java ea este totui uurat de existena unui numr destul de mare de clase cu aceast destinaie, grupate n pachetul java.io.

Pachetul java.io
n Java 2 SDK se consider c fluxurile pot fi de caractere saude octei. n primul caz, de la surs la destinaie se transmite o succesiune de caractere Unicode (de cte 16 bii), iar n al doilea caz - o succesiune de octei (de 8 bii). n mod corespunztor, pentru fiecare din cele dou categorii de fluxuri exist cte o ierarhie de clase de fluxuri de intrare i o ierarhie de clase de fluxuri de iesire. Pentru fluxurile de caractere, rdcinile ierarhiilor de clase sunt clasele abstracte Reader i Writer.Pentru fluxurile de octei, rdcinile acestor ierarhii sunt clasele abstracte InputStream i OutputStream. Aceste ierarhii de clase sunt reprezentate n figurile 2, 3, 4 i 5. n afar de cele patru ierarhii menionate, n pachetul java.io exist i clase auxiliare i interfete. Distingem trei tipuri de clase, care sunt reprezentate n aceste figuri prin culori diferite: - clase abstracte (culoare albastr); - clase care efectueaz operaiile de intrare sau de ieire propriu-zise (culoare verde) i modeleaz sursele sau destinaiile fluxurilor (englez: Data Sink Streams);

307

Severin Bumbaru - clase care efectueaz unele operaii de transformare a datelor de pe flux (culoare violet) i reprezinta "fluxuri de prelucrare" (englez: Processing Streams).

- Figura 2 - Ierarhia claselor pentru fluxuri de intrare de caractere

- Figura 3 - Ierarhia claselor pentru fluxuri de ieire de caractere

308

Programarea orientata pe obiecte n limbajul Java

- Figura 4 - Ierarhia claselor pentru fluxuri de intrare de octei

- Figura 5 - Ierarhia claselor pentru fluxuri de ieire de octeti Se observ corespondena ntre clasele de fluxuri de intrare i de ieire n cadrul aceleeai categorii de fluxuri. De exemplu, n cazul fluxurilor de caractere, unui BufferedReader i corespunde un BufferedWriter, unui CharArrayReader i corespunde un CharArrayWriter etc. n mod similar, n cazul fluxurilor de octei, unui FileInputStream i corespunde un FileOutputStream, unui PipedInputStream i corespunde un PipedOutputStream etc. Aceasta reflect "simetria" operaiilor de intrare i de ieire. Exist totui i clase de intrare fr corespondent la ieire (de exemplu StringBufferInputStream sau PushbackInputStream) sau clase de ieire fr corespondent la intrare (de exemplu PrintStream).

n JDK 1.0 existau numai clasele de fluxuri de octei. Fluxurile de caractere au fost introduse ncepand cu JDK 1.1. n prezent se folosesc ambele categorii de fluxuri. Pentru transmiterea textelor sau a datelor reprezentate n format extern i codificate n Unicode este preferabil, evident, s se foloseasc fluxuri de caractere. Pentru transmiterea datelor codificate binar sau a textelor n care caracterele sunt codificate pe un octet (de exemplu n codul ASCII) este preferabil folosirea fluxurilor de octei.

309

Severin Bumbaru Fluxurile pot fi nlnuite, astfel nct ieirea unui flux poate fi intrare a altui flux. Astfel, n Figura 6 este dat schema unei nlnuiri de fluxuri de intrare: ieirea fluxului InputStream (sub forma de fluxului de octei flux1) este dat la intrarea fluxului InputStreamReader, care o convertete n fluxul de caracrtere flux2, iar acesta - la rndul lui - este preluat fe fluxul de intrare de caractere cu zon tampon BufferedReader.

- Figura 6- nlnuire de fluxuri de intrare n Figura 7 este reprezentat o nlnuire similar de fluxuri de ieire: ieirea fluxului de caractere BufferedWriter este aplicat la intrarea fluxului OutputStreamWriter, iar acesta face conversia ntr-un flux de octei, pe care l transmite la un OutputStream (de exemplu la un PrintStream sau la un FileOutputStream).

- Figura 7 - nlnuire de fluxuri de ieire Avnd n vedere complexitatea programrii operaiilor de intrare/ieire, n cele ce urmeaz vom cuta s facem o prezentare gradual, de la simplu la complex. Vom ncepe ns cu prezentarea comparativ a claselor abstracte care constituie rdcinile celor patru ierarhii de clase de fluxuri. Aceasta ne va permite s ne formm o vedere de ansamblu asupra principalelor metode folosite n lucrul cu fluxuri.

Clasele de baz ale ierarhiilor de fluxuri de intrare/ieire


Clasa Reader
Clasa abstract java.io.Reader este rdcina ierarhiei de clase de fluxuri de intrare de caractere. Metode: citete din fluxul de intrare un singur caracter; ntoarce caracterul citit (n domeniul 0 .. 16383) sau -1 dac s-a ajuns la sfrit de fiier; metoda produce blocarea procesului n care este invocat, pn cnd apare un caracter n fluxul de intrare; public int read(char[] cbuf) throws IOException - citete din flux o secven de caractere i le depune ntr-o zon tampon (buffer) constituit din tabloul de caractere cbuf; ntoarce numrul de caractere citite sau -1 dac s-a atins sfritul de fiier; metoda produce blocarea procesului pn cnd apar caractere n fluxul de intrare, sau se ajunge la sfrit de fiier;
public int read() throws IOException -

310

Programarea orientata pe obiecte n limbajul Java


public abstract int read(char[] cbuf, int off, int len) throws IOException - acioneaz asemntor cu metoda precedent, dar depunerea caracterelor

citite n zona tampon de destinaie se face ncepnd de la poziia off (offset), iar numrul maxim de caractere citite este len; public long skip(long n) throws IOException - se sare peste n caractere din fluxul de intrare, care nu vor fi citite; procesul apelant este blocat pan cnd apare cel puin un caracter n fluxul de intrare; dac se ntlnete sfritul de fiier, se genereaz o excepie de intrare/ieire; ntoarce numrul de caractere srite efectiv; public boolean ready() - ntoarce true dac fluxul de intrare este gata pentru a putea fi citit; public void mark(int readAheadLimit) throws IOException - marcheaz poziia curent n fluxul de intrare, pentru a se putea reveni la ea ulterior; argumentul readAheadLimit indic numrul de caractere care vor putea fi ulterior citite din flux,fr ca acest marcaj s se piard; excepia de intrare/ieire apare dac fluxul nu suport marcarea sau dac se produce alt eroare de intrare/ieire; public boolean markSupported() - indic dac fluxul suport marcarea; public void reset() throws IOException - dac fluxul a fost marcat, este readus la poziia corespunztoare ultimului marcaj; dac fluxul nu a fost marcat sau nu suport resetarea, se genereaz o excepie de intrare/ieire; public abstract void close() throws IOException - nchide fluxul; din acest moment, invocarea metodelor read(), ready(), mark() sau reset pentru acest flux va genera o excepie de intrare/ieire.

Clasa Writer
Clasa abstract java.io.Writer este rdcina ierarhiei de clase pentru fluxuri de ieire de caractere. Metode:
public void write(int c) throws IOException -

scrie n fluxul de ieire scrie n fluxul de ieire

caracterul c;
public void write(char[] cbuf) throws IOException -

caracterele coninute n tabloul cbuf;


public abstract void(char[] cbuf, int off, int len) throws IOException

scrie n fluxul de ieire len caractere din tabloul cbuf, ncepnd de la poziia off (offset); public void write(String str) throws IOException - scrie n flux caracterele existente n irul str;
public void write(String str, int off, int len) throws IOException -

scrie n flux len caractere din irul str, ncepnd de la poziia off (offset); public abstract void flush() throws IOException - "descarc" fluxul de ieire; dac fluxul a salvat ntr-o zon tampon anumite caractere scrise cu metodele write(), aceste caractere sunt scrise efectiv n fluxul de destinaie; dac aceast destinaie este tot un flux, invoc i metoda flush() a acestuia, astfel c se "descarc" ntregul lan de fluxuri; public abstract void close() throws IOException - se nchide fluxul de ieire; invocarea ulterioar a metodelor write() sau flush() pentru acest flux va produce o excepie de intrare/ieire.

311

Severin Bumbaru

Clasa InputStream
Clasa java.io.InputStream este rdcina ierarhiei de clase pentru fluxuri de intrare organizate pe octei. Metode: citete din fluxul de intrare un singur octet; ntoarce octetul citit (in domeniul 0 .. 255) sau -1 dac s-a ajuns la sfrit de fiier; metoda produce blocarea procesului n care este invocat, pn cnd apare un octet n fluxul de intrare; public int read(byte[] buf) throws IOException - citete din flux o secven de octei i i depune ntr-o zon tampon (buffer) constituit din tabloul de octei buf; ntoarce numrul de octei citii sau -1 dac s-a atins sfritul de fiier; metoda produce blocarea procesului pn cnd apar octei n fluxul de intrare, sau se ajunge la sfrit de fiier;
public int read() throws IOException public abstract int read(byte[] buf, int off, int len) throws IOException - acioneaz asemntor cu metoda precedent, dar depunerea octeilor citii n tabloul de destinaie byte[] se face ncepnd de la poziia off (offset), iar numrul maxim

de octei citii este len;


public long skip(long n) throws IOException - se sare peste n octei din fluxul de intrare, care nu vor fi citii; procesul apelant este blocat pn cnd apare cel puin un octet n fluxul de intrare; dac se ntlnete sfritul de fiier se genereaz o eroare de intrare/ieire; ntoarce numrul de octei srii efectiv; public int available() throws IOException - ntoarce numrul de octei disponibili pentru citire n fluxul de intrare; public void mark(int readAheadLimit) throws IOException - marcheaz poziia curenta n fluxul de intrare, pentru a se putea reveni la ea ulterior; argumentul readAheadLimit indic numrul de octei care vor putea fi ulterior citii din flux, fr ca acest marcaj s se piard; excepia de intrare/ieire apare dac fluxul nu suport marcarea sau dac se produce alt eroare de intrare/ieire; public boolean markSupported() - indic dac fluxul suport marcarea; public void reset() throws IOException - dac fluxul a fost marcat, este readus la poziia corespunztoare ultimului marcaj; dac fluxul nu a fost marcat sau nu suporta resetarea, se genereaz o excepie de intrare/ieire; public abstract void close() throws IOException - nchide fluxul; din acest moment, invocarea metodelor read(), ready(), mark() sau reset() pentru acest flux va genera o excepie de intrare/ieire.

Clasa OutputStream
Clasa java.io.OutputStream este rdcina ierarhiei de clase pentru fluxuri de iesire de octei. Metode:
public void write(int c) throws IOException -

scrie n fluxul de ieire ultimul scrie n fluxul de ieire

octet al numrului c;
public void write(byte[] buf) throws IOException -

octeii coninuti n tabloul buf;


public abstract void(byte[] buf, int off, int len) throws IOException -

scrie n fluxul de ieire len octei din tabloul buf, ncepnd de la poziia off (offset); public abstract void flush() throws IOException - "descarc" fluxul de

312

Programarea orientata pe obiecte n limbajul Java ieire; dac fluxul a salvat ntr-o zon tampon anumii octei scrii cu metodele write(), aceti octei sunt scrii efectiv n fluxul de destinaie; dac aceast destinaie este tot un flux, invoc i metoda flush() a acestuia, astfel c se "descarc" ntregul lan de fluxuri; public abstract void close() throws IOException - se nchide fluxul de ieire; invocarea ulterioar a metodelor write() sau flush() pentru acest flux va produce o excepie de intrare/ieire.

Consideraii privind utilizarea fluxurilor


Se remarc cu uurin faptul c metodele claselor Reader i InputStream sunt similare att ca seigatur (i deci ca mod de invocare), ct i ca funcionalitate. Metodele read(), skip(), mark(), markSupported(), reset() i close() exist n ambele clase. Deosebirea este ca n clasa Reader metoda read() citete din fluxul de intrare un caracter, iar n clasa InputStream citete un octet. Metodele read() pentru citirea de secvene de caractere, respectiv de octei, se deosebesc numai prin aceea ca n clasa Reader se folosesc ca destinaie tablouri de caractere, iar n clasa InputStream se folosesc tablouri de octei. Metodele claselor Writer i OutputStream sunt, de asemenea, similare ca signatur i funcionalitate. Metodele write(), flush() i close() exist n ambele clase, ns n clasa Writer metoda write() scrie n fluxul de ieire un caracter, iar n clasa OutputStream scrie un octet. n cazul c n metodele write() se scrie n flux coninutul unui tablou, n clasa Writer acesta este un tablou de caractere, iar in clasa OutputStream este un tablou de octei. Remarcm c ierarhiile de clase Reader i Writer, introduse ncepnd cu JDK 1.1, nu nlocuiesc pe cele anterioare, avnd ca rdcini clasele InputStream i OutputStream, ci le completeaz. Se vor putea deci folosi, dup necesiti, att clasele de fluxuri de caractere, ct i cele de fluxuri de octei.

Clasele PrintStream i PrintWriter


Clasele java.io.PrintStream i java.io.PrintWriter se folosesc pentru a transmite ctre un flux se ieire date formatate pentru tiprire (afiare). Se tie c forma intern a datelor difer de forma extern. De exemplu, numerele ntregi sunt reprezentate intern sub form binar, n timp ce pe ecranul calculatorului sau la imprimant apar sub forma unor iruri de cifre zecimale, precedate eventual de semn. Metodele claselor PrintStream i PrintWriter fac aceast conversie din forma intern n cea extern a diferitelor tipuri de date, genernd reprezentrile datelor respective sub forma de iruri de octei (caractere n codul ASCII) sau, respectiv, de caractere Unicode. Aceste clase nu se folosesc n mod independent, ci adaug altui flux de ieire (de octei sau, respectiv, de caractere) capacitatea de formatare a datelor n vederea tipririi.

Clasa PrintStream
Clasa PrintStream conine doua feluri de metode de scriere a datelor: metodele cu numele write() scriu ntotdeauna octei (fr formatare), n timp ce cele cu numele print() sau println() formateaz datele, respectnd convenia de codificare (pe octeti sau pe caractere) specific platformei pe care ruleaza aplicaia respectiv. Totui, se recomand ca pentru a obine fluxuri de caractere s se foloseasc clasa PrintWriter. Deosebirea dintre print() i println() este c metodele cu numele println() adaug, la sfritul irului de octei generat, un caracter de sfrit de linie ('\n'). n consecin, dac se 313

Severin Bumbaru folosete metoda print(), afiarea se face fr a se trece la o linie nou, n timp ce dac se folosete metoda println(), dup afiare se trece la linie nou. Dac fluxul este cu descrcare automat, metoda println() provoac, de asemenea, descrcarea acestuia (flush). Constructori:
public PrintStream(OutputStream out) - creeaz un nou flux de formatare pentru tiprire, conectat la fluxul de ieire out; acest flux nu se descarc automat; public PrintStream(OutputStream out, boolean autoFlush) - creeaza un nou flux de formatare a datelor pentru tiprire, conectat la fluxul de ieire out; al doilea argument indic dac fluxul se descarc automat atunci cnd se ntlneste n flux caracterul '\n' (linie nou) sau se execut metoda println() sau se tiprete un tablou de octei.

Metode:
public void flush() -

descarc fluxul (golete zonele tampon, transmind de ieire un singur octet (ultimul octet al

coninutul lor la ieire);


public void close() - nchide fluxul; public void write(int b) - scrie n fluxul

argumentului); se scriu n fluxul de ieire len octei din tabloul de octeti buf (buffer), ncepnd de la poziia off (offset); public void print(boolean b) - transmite n fluxul de ieire forma extern a valorii variabilei booleene b, respectiv cuvntul true sau false; public void print(char c) - se afieaz caracterul c (pe unul sau doi octei, depinznd de platform); public void print(int i) - se afieaz numrul ntreg i; public void print(long l) - se afieaz numrul ntreg lung l; public void print(float f) - se afieaz numrul real n simpl precizie f; public void print(double d) - se afieaz numrul real n dubl precizie d; public void print(char[] s) - se afieaz coninutul tabloului de caractere s; public void print(String s) - se afieaz irul de caractere s; public void print(Object obj) - se afieaza obiectul obj convertit n ir de caractere prin aplicarea metodei String.valueOf(obj) care, la rndul ei, apeleaza metoda obj.toString() din clasa creia i aparine obiectul; public void print() - introduce n fluxul de ieire codul caracterului '\n' (linie nou); public void println(boolean b) - transmit n fluxul de ieire forma extern a valorii variabilei booleene b, respectiv cuvntul true sau false; public void println(char c) - se afieaz caracterul c (pe unul sau doi octei, depinznd de platform); public void println(int i) - se afieaz numrul ntreg i; public void println(long l) - se afieaz numrul ntreg lung l; public void println(float f) - se afieaz numrul real n simpl precizie f; public void println(double d) - se afieaz numrul real n dubl precizie d; public void println(char[] s) - se afieaz coninutul tabloului de caractere s; public void println(String s) - se afieaz irul de caractere s; public void println(Object obj) - se afieaz obiectul obj convertit n ir de caractere prin aplicarea metodei String.valueOf(obj);
public void write(byte[] buf, int off, int len) -

314

Programarea orientata pe obiecte n limbajul Java

Clasa PrintWriter
Constructori: - creeaz un nou flux de formatare pentru afiare, fr descrcare automat, conectndu-l la fluxul de ieire pe caractere out; public PrintWriter(Writer out, boolean autoFlush) - la fel ca i constructorul precedent, dar al doilea argument specific dac are loc descrcarea automat a fluxului; public PrintWriter(OutputStream out) - creeaz un nou flux de formatare pe caractere, fr descrcare automat, conectndu-l la fluxul de ieire pe octei out; el creeaz i un OutputStreamWriter intermediar, care face conversia caracterelor pe unul sau doi octei, dependent de platform; public PrintWriter(OutputStream out, boolean autoFlush) - la fel ca i constructorul precedent, dar al doilea argument indic dac se face descrcare automat a fluxului.
public PrintWriter(Writer out)

Metode: Aceast clasa implementeaz aceleai metode ca i clasa PrintStream, cu excepia celor care scriu octei bruti (write()).

Fiiere
n memoria extern a calculatorului, datele se pstreaz sub forma de fiiere. Fiierul (englez: File) este o colecie de nregistrri situat, de regul, pe un suport extern i identificat printr-un nume. Fiecare nregistrare (englez: Record) este o grupare de informaii sau de date care poate fi tratat n mod unitar. Fiierele pot fi clasificate dup diferite criterii. Dup formatul nregistrrilor, distingem fiiere de text i fiiere de date. n fiierele de text, fiecare nregistrare este o linie de text, adic un ir de caractere care se termin cu un marcaj de trecere la linie nou. Acest marcaj depinde de platform. De exemplu, n fiierele MS-DOS marcajul de sfrit de linie este format din secvena de caractere "\r\n", adic din caracterul de ntoarcere la cap de linie (Carriage Return, '\r' ) i caracterul de linie nou (New Line, '\n'), care au codurile ASCII 0x0D i respectiv 0x0A. Pe platforme Unix, marcajul de sfrit de linie este constituit numai din caracterul '\n' (New Line, 0x0A). Liniile textului pot avea lungimi diferite. Codificarea caracterelor n fiier depinde, de asemenea, de platform. n prezent, pentru fiierele de text se folosete cel mai frecvent codul ASCII, dar pot exista i platforme pe care se folosete Unicode sau o alt convenie de codificare. n fiierele de date, nregistrrile au, de regul, lungime predefinit, iar fiecare nregistrare este constituit din mai multe cmpuri de date. n principiu, toate nregistrrile unui fiier de date au acelai format. Prin formatul nregistrrii se nelege descrierea structurii acesteia, care const din specificarea cmpurilor de date pe care le conine, a lungimii fiecrui cmp, a tipului de date coninut n fiecare cmp i a modului de reprezentare a datelor. Datele din cmpuri pot fi reprezentate fie sub forma lor extern, fie sub form binar, iar formatul nregistrrilor difer de la un fiier la altul.

315

Severin Bumbaru Dup modul de exploatare, fiierele pot fi de intrare, de ieire sau de intrare/ieire (de manevr). n cazul fiierelor de intrare, din momentul deschiderii fiierului i pn n momentul nchiderii acestuia se pot efectua numai operaii de citire. n cazul fiierelor de ieire, ntre momentele de deschidere i de nchidere a fiierului respectiv se pot face numai operaii de scrieire. Desigur ns c, dup ce s-a ncheiat scrierea ntr-un anumit fiier de ieire i acesta a fost nchis, el poate fi deschis ca fiier de intrare. Acelai fiier poate fi citit de mai multe ori. Fiierele de intrare/ieire permit ca, dup ce au fost deschise, s se efectueze att operaii de scriere, ct i de citire. Dup modul de acces fiierele pot fi cu acces secvenial sau cu acces direct. Fiierele cu acces secvenial se caracterizeaz prin faptul c nregistrrile lor pot fi parcurse ntr-un singur sens, n ordinea n care acestea sunt plasate n fiier. n cazul fiierelor cu acces direct, numite i fiiere cu acces aleator (englez: random access file) ordinea de parcurgere a nregistrrilor din fiier este arbitrar, n sensul c la fiecare operaie de intrare/ieire fcut asupra fisierului respectiv se poate indica adresa sau numrul de ordine al nregistrrii care va fi citit sau scris. n limbajul Java, fiierul este privit ca sursa sau destinaia unui flux. n cazul citirii din fiier, datele se transmit de la acesta ctre memoria intern sub forma unui flux de intrare. n cazul operaiei de scriere, datele se transmit de la memoria intern la fiier sub forma unui flux de ieire. n principiu, comunicarea ntre memoria intern i un fiier de text se face sub forma unui flux de caractere. Totui, pe platformele pe care reprezentarea caracterelor se face pe un octet (de exemplu n cod ASCII), acesta poate fi tratat i ca un flux de octei. n cazul fiierelor de date, comunicarea dintre memoria intern i fiier se poate face prin fluxuri de caractere numai dac datele din fiier sunt reprezentate exclusiv n format extern (deci sub forma de iruri de caractere). Dac ns exist i cmpuri de date n format binar, legatura dintre memoria intern i fiierul de date se face, de regula, prin fluxuri de octei. Operaiile cu fiierul se fac n ordinea urmtoare: 1/ se deschide fiierul, n care scop trebuie s se comunice sistemului de operare numele fiierului, locul n care se gsete (de exemplu unitatea de disc i calea ctre directorul care l conine) i modul n care va fi utilizat (pentru citire, pentru scriere sau n ambele moduri); 2/ se exploateaz fiierul, efectund o succesiune de operaii de citire/scriere; 3/ se nchide fiierul. n limbajul Java, se consider c, n operaiile de intrare/ieire, ntre fiier i memorie se transmit numai fluxuri de caractere sau de octei, far s se ia n consideraie informaia pe care o conin aceste fluxuri. ntreaga responsabilitate privind interpretareaacestor fluxuri revine programelor care le prelucreaz.

Clasa File
Instanele clasei java.io.File conin informaii privind numele fiierului i calea pe care se gseste acesta (engleza: Path). Clasa File ofer, de asemenea, metode prin care se pot face unele operaii legate de prezena fiierului respectiv: se poate afla dac fiierul exist, dac el poate fi citit sau scris, se poate crea un fiier nou, se poate terge un fiier existent etc.

316

Programarea orientata pe obiecte n limbajul Java Calea indic modul n care poate fi localizat fiierul de pe disc. Calea poate fi absolut sau relativ. Calea absolut const n indicarea unitii de disc i a succesiunii de directoare prin care se ajunge de la rdacin la fiierul care ne intereseaz. Calea relativ, arat cum se poate ajunge de la directorul curent la fiierul cutat. Se tie c, pe diferite platforme, calea se reprezint n moduri diferite. De exemplu, n sistemul Unix, calea relativa "../../alpha/beta/fisier1.txt" indic faptul c, pornind de la directorul curent, se face o deplasare ctre rdcin cu doua directoare, dup care se merge nainte (ctre frunzele arborelui director) trecnd la subdirectorul alpha i de aici la subdirectorul beta, n care se gsete fiierul cutat cu numele fiier1.txt. Remarcm c separarea directoarelor se face prin caracterul '/' (slash). Pe platformele firmei Microsoft (MS-DOS, Windows), ca separator se folosete caracterul '\' (backslash), care n limbajele C i Java se reprezint sub forma '\\'. n consecin, aceeai cale relativ se va scrie pe o astfel de platforma sub forma "..\\..\\alpha\\beta\\fisier1.txt". n clasa File, reprezentarea cii se face sub o form independent de platform. n acest scop, n instanele clasei File, calea se pstreaz sub forma unui tablou de iruri de caractere, n care se memoreaza numele fiecrui director coninut n cale. Separatorul se pstreaz ntr-un cmp separat i este setat automat n funcie de sistemul de operare al calculatorului pe care se execut programul. n acest fel, portabilitatea programului crete, ntruct nu trebuie modificate cile fiierelor folosite n program atunci cnd se trece de pe o platform pe alta. ATENIE: pentru asigurarea portabilitii programelor surs, este recomandabil ca, n cile date ca argumente ale metodelor clasei File, s se foloseasc numai varianta Unix de separatori. Compilatorul javac de pe platformele Microsoft nlocuiete automat separatorul '/' prin ' \\' in timp ce pe platformele Unix (Linux) nu se face nlocuirea invers. Remarcm c numele clasei File poate s ne induc n eroare, lsndu-ne s credem c instanele acestei clase sunt fiiere. n realitate, instanele ei conin cile i numele fiierelor.

317

Severin Bumbaru

Clasa File prezentat n detaliu


Cmpuri: conine caracterul prin care se separ directoarele dintr-o cale; acest carecter este dependent de platforma, fiind '/' (slash) pe platforme Unix i '\' (backslash) pe platforme Microsoft; public static final String separator - conine caracterul de separare (separatorChar) sub forma de String; public static final char pathSeparatorChar - conine caracterul de separare a cilor; acest caracter este dependent de platform, fiind ':' (dou puncte) sub Unix i ';' (punct i virgul) pe platforme Microsoft; public static final String pathSeparator - caracterul de separare a cilor (pathSeparatorChar) sub form de String. NOT: aceste cmpuri se completeaz automat, n funcie de platforma pe care ruleaz programul.
public static final char separatorChar -

Constructori:
public File(String pathname) -

creeaz o instan a clasei File, care conine calea

dat ca argument;
public File(String parent, String child) - creeaz o instan a clasei File, n care calea este compus dintr-o cale "printe" (format numai din directoare) i o cale "copil" (care poate fi director sau fiier); public File(File parent, String child) - se deosebete de constructorul precedent numai prin faptul c "printele" este o instan a clasei File.

Metode: Specificm aici principalele metode ale clasei File. public String getName() - ntoarce numele fiierului (ultimul nume din cale); dac aceast cale este vid, ntoarce un ir vid; public String getParent() - ntoarce calea printe; public File getParentFile() - ntoarce calea printe sub forma de instan a clasei File; public String getPath() - ntoarce calea coninut n aceast instan; calea va conine separatorii implicii de pe platforma curent; public boolean isAbsolute() - intoarce true dac aceast cale este absolut (dac este prefixat cu '/' pe platformele Unix sau cu '\\' pe platformele Microsoft); public String getAbsolutePath() - ntoarce calea absolut corespunztoare cii coninute n aceast instan; public File getAbsoluteFile() - ntoarce o instan a clasei File care conine calea absolut corespunzatoare celei din instana curent; public URL toURL() - ntoarce un URL (Uniform Resource Locator) corespunztor cii din aceast instan; forma acestui URL este dependent de sistem (Nota: URL-ul se folosete pentru a localiza un fiier cu ajutorul unui browser de Web); public boolean canRead() - testeaz dac aplicaia poate citi fiierul indicat de aceast instan a clasei File; public boolean canWrite() - testeaz dac aplicaia poate scrie n fiierul indicat; public boolean exists() - testeaz dac fiierul indicat exist; public boolean isDirectory() - testeaz dac ultimul nume din aceast cale este al unui director;

318

Programarea orientata pe obiecte n limbajul Java


public boolean isFile() -

testeaz dac ultimul nume din aceast cale este al unui

fiier; timpul la care s-a fcut ultima modificare n fiierul indicat de aceast cale (exprimat n milisecunde de la 1 ianuarie 1970 ora 00:00:00 GMT); public long length() - ntoarce lungimea fiierului indicat de aceast instan (n octei); public boolean createNewFile() throws IOException - dac fiierul indicat n aceast cale nu exist, creeaz un fiier nou vid; public boolean delete() - terge fiierul; ntoarce truedac tergerea a avut loc; public void deleteOnExit() - cere ca fiierul s fie ters cnd se ncheie funcionarea mainii virtuale Java (are efect numai dac funcionarea se ncheie normal); public String[] list() - ntoarce un tablou de iruri, care conine numele de directoare i de fiier din aceast cale; public File[] listFile() - dac aceast cale nu se ncheie cu un nume de director, ntoarce null; altfel ntoarce un tablou de instane ale clasei File, cte una pentru fiecare nume de fiier din directorul indicat de aceast cale.
public long lastModified() - ntoarce

Exemplu: n fiierul TestFile.java este dat un exemplu de aplicaie, n care se testeaz utilizarea metodelor clasei File. Metodele se aplic pentru un fiier situat n directorul curent, pentru un director i pentru un fiier situat n alt director.

Citirea fiierelor
Citirea fluxurilor de octei: clasa FileInputStream
Clasa java.io.FileInputStream permite citirea datelor din fiiere sub forma de fluxuri de octei. Orice instan a acestei clase este un flux de intrare, care are ca surs un fiier. La crearea acestei instane se caut i se deschide fiierul indicat ca argument al constructorului. Dac fiierul nu exist, sau nu poate fi deschis pentru citire, se genereaz o excepie.

319

Severin Bumbaru

Constructorii i metodele clasei FileInputStream


Metodele acestei clase permit s se citeasc din fiierul de intrare octei sau secvene de octei, fr a le da nici o interpretare. Constructori:
public FileInputStream(String name) throws FileNotFoundException - se creeaz un flux de intrare de octei avnd ca surs fiierul name; (name este numele fiierului; dac acesta nu se afl n directorul curent, atunci irul name conine i calea); public FileInputStream(File file) throws FileNotFoundException - se creeaz un flux de intrare de octei avnd ca surs fiierul indicat de instana file a clasei File; public FileInputStream(FileDescriptor fdObj) - se creeaz un nou flux de intrare de octei, care este conectat la fluxul de intrare fdObj deja existent.

Metode:
public int read() throws IOException - citete din fiier un singur octet; dac octetul nu este nca disponibil n fluxul de intrare, programul intr n ateptare; public int read(byte[] b) throws IOException - se citesc din fiier cel mult b.length octei, care se pun n tabloul b; ntoarce numrul de octei citit efectiv, sau zero dac s-a intlnit sfritul de fisier fr s se citeasc nici un octet; dac n fluxul de intrare nu mai sunt octei de citit, dar nu s-a ntlnit sfritul de fiier, programul intr n ateptare; public int read(byte[] b, int off, int len) throws IOException - se citesc din fluxul de intrare cel mult len octei, care se pun n tabloul b ncepnd de la poziia off (offset); ntoarce numrul de octei citit efectiv; dac s-a ntlnit sfritul de fiier fr s se citeasc nici un octet, intoarce -1; dac nu s-a ntlnit sfritul de fiier i nu sunt octei disponibili pentru citire n fluxul de intrare, programul intr n ateptare; public long skip(long n) throws IOException - se sare peste n octei din fiierul de intrare; se ntoarce numrul de octei srii efectiv; public int available() throws IOException - ntoarce numrul de octei disponibili pentru citire din fluxul de intrare; public void close() throws IOException - nchide fiierul; public final FileDescriptor getFD() throws IOException - ntoarce un descriptor al acestui fiier.

NOTA: descriptorii de fiiere sunt obiecte care aparin clasei java.io.FileDescriptor i pot fi folosii ca argument al constructorului pentru a crea un nou flux conectat la un fiier deja deschis. Clasa FileDescriptor conine, de asemenea, cmpurile statice in, out i err, care sunt descriptori ai fluxurilor de intrare/ieire standard. n consecin, dac se folosete ca argument al constructorului clasei FileInputStream obiectul FileDescriptor.in, se creaza un flux care citete datele de la tastatura. Exemplu: n fiierul TestFileInput.java este un exemplu de aplicaie, n care se testeaza metodele clasei FileInputStream. n aplicaie se deschide fiierul f1, prin care se citesc octei dintr-un fiier de text, al crui nume se d ca parametru n linia de comand, dup care octeii respectivi se afieaz. ntruct se tie c f1 este un fiier de text, octeii sunt afiati convertii n caractere. Se deschide apoi un al doilea flux, f2, care este echivalent cu f1, deoarece au acelai descriptor. n consecin, n continuare fluxurile f1 i f2 citesc date din acelai fiier. n final, se creeaz un nou flux (cu referina f1), care citete datele de la tastatura, deoarece la creare s-

320

Programarea orientata pe obiecte n limbajul Java a folosit descriptorul FileDescriptor.in. Acesta este cmpul in din clasa java.io.FileDescriptor i este o referin la fluxul de intrare standard, deci trateaz fluxul de la tastatur ca pe un fiier folosit pentru citire.

Citirea din fiiere de caractere: Clasa FileReader


Citirea unui fiier de text se poate face nu numai folosind o instan a clasei FileInputStream, ci i o instan a clasei FileReader. Deosebirea este c aceast ultim clas creeaz un flux de caractere, n loc de un flux de octei. Chiar dac fiierul nu este codificat n Unicode, ci n alt cod de caractere (de cele mai multe ori ASCII), se face automat conversia n Unicode. Clasa java.io.FileReader este derivat din clasa java.io.InputStreamReader i folosete metodele acesteia. Constructori:
public FileReader(String fileName) throws FileNotFoundException -

deschide ca flux de caractere de intrare fiierul cu numele fileName (eventual acest ir cuprinde i calea); public FileReader(File file) - throws FileNotFoundException - deschide ca flux de intrare de caractere fiierul cu calea file; public FileReader(FileDescriptor fd) - deschide un nou flux de intrare de caractere i l conecteaz la fluxul deja existent, al crui descriptor este fd. Metode: Clasa FileReader nu are metode proprii, dar motenete urmtoarele metode ale clasei InputStreamReader:
public int read() throws IOException -

citete din fluxul de intrare un singur

caracter i-l ntoarce convertit n int;


public int read(char[] buf, int off, int len) throws IOException -

citete din fluxul de intrare cel mult len caractere, pe care le pune n tabloul buf ncepnd de la poziia off (offset); public boolean ready() throws IOException - verific dac fluxul de intrare este gata pentru citire (dac conine caractere care pot fi citite); public void close() throws IOException - nchide fluxul de intrare; public String getEncoding() - ntoarce numele canonic al codului folosit pentru caractere. Exemplu: n fiierul TestFileReader.java este dat un exemplu de aplicaie n care se testeaz metodele clasei FileReader. Fiierul care se citete poate fi acelai ca i n cazul citirii cu un flux de octei (din clasa FileInputStream). n aceast aplicaie, citirea fiierului se face de trei ori, folosind diverse metode.

321

Severin Bumbaru

Scrierea n fiiere
Clasa FileOutputStream
Fiecare instan a clasei java.io.FileOutputStream este un flux de octei de ieire conectat la un fiier, n care se sriu octeii primii din flux. Fluxul se poate conecta i la un flux de octeti de ieire deja existent.

Constructorii i metodele clasei FileOutputStream


Constructori:
public FileOutputStream(String name) throws FileNotFoundException -

Deschide pentru scriere fiierul cu numele (i, eventual, calea) name i creeaz un flux de octei ctre acest fiier; dac fiierul nu exist, se va crea pe disc un fiier nou, cu numele dat ca argument; excepia se genereaz dac fiierul nu exist i nici nu poate fi creat; scrierea n fiier se va face de la nceputul acestuia ("peste" ceeace, eventual, exista deja scris);
public FileOutputStream(String name, boolean append) throws FileNotFoundException - acioneaz la fel ca n cazul constructorului precedent,

dar dac al doilea parametru este true, scrierea se va face n coada fiierului deja existent (scrierea ncepe dup ultima nregistrare deja existent); public FileOutputStream(File file) throws IOException - se deschide pentru scriere fiierul indicat de calea file i se creeaz un flux de octei ctre acesta; dac fiierul nu exist, se creeaz unul nou; scrierea se face de la nceputul fiierului; public FileOutputStream(FileDescriptor fd) - creeaza un nou flux de octei de ieire, care se conecteaz la fluxul deja existent cu descriptorul fd. Metode:
public void write(int b) throws IOException -

scrie n fiier un singur octet, scrie n fiier toti octeii scrie

coninut n argumentul b;
public void write(byte[] b) throws IOException -

coninuti n tabloul b;
public void write(byte[] b, int off, int len) throws IOException -

n fiier len octei din tabloul b ncepnd de la poziia off (offset); public void close() throws IOException - nchide fiierul;
public final FileDescriptor getFD() throws IOException - ntoarce un

descriptor al acestui fiier;

Exemplu: n fiierul TestFileOutput.java se d un exemplu de aplicaie, n care se testeaz metodele clasei FileOutputStream. Se deschide un fiier cu numele "ProbaScriere.txt" (dac nu exist, se creeaz unul nou). n fiier se scrie textul dat n linia de comand. n acest scop, lansarea n execuie se face sub forma java TestFileOutput text_de_scris_n_fiier Dup ce s-a scris textul, fiierul este nchis, apoi este redeschis pentru citire i coninutul este afiat pe ecran. Se nchide i se redeschide iari, dar de data aceasta pentru scriere "n coada" coninutului existent. Se scriu cuvintele "Text adugat", dup care se nchide, se redeschide pentru citire i se afieaz. Metoda de scriere n fiier folosit de fiecare dat este cea n care

322

Programarea orientata pe obiecte n limbajul Java se scrie un tablou de octei. Pentru afiare pe ecran, a doua oar s-a folosit tot un flux creat ca instan a clasei FileOutputStream, dar care a fost conectat la fluxul standard de iesire java.ioFileDescriptor.out, fiind astfel tratat acest flux ca un fiier.

Clasa FileWriter
Scrierea ntr-un fiier de text se poate face, de asemenea, folosind clasa FileWriter. Instanele acestei clase sunt fluxuri de ieire de caractere, prin care se face scrierea ntr-un fiier. Clasa FileWriter este derivat din java.io.OutputStreamWriter i folosete metodele acesteia. Constructori:
public FileWriter(String fileName) throws IOException - deschide fiierul fileName pentru scriere i creeaz un flux de caractere de ieire conectat la acest fiier; dac fiierul nu exist, l creeaz; public FileWriter(String fileName, boolean append) throws IOException

la fel ca n cazul constructorului precedent, dar, dac al doilea parametru este true, scrierea n fiier se va face n coada celui deja existent; public FileWriter(File file) throws IOException - deschide pentru scriere fiierul indicat prin calea file i creeaz un flux de caractere de ieire conectat la acest fiier; public FileWriter(FileDescriptor fd) - creeaz un flux de caractere de ieire i l conecteaz la fluxul deja existent, cu descriptorul fd;
-

Metode: Metodele clasei FileWriter sunt motenite de la clasa OutputStreamWriter.


public void write(int c) throws IOException -

scrie n fiier un singur

caracter;
public void write(char[] cbuf, int off, int len) throws IOException -

scrie n fiierul de ieire len caractere din tabloul de caractere cbuf, ncepnd de la poziia off (offset);
public void write(String str, int off, int len) throws IOException -

scrie n fiier len caractere din irul str ncepnd de la poziia off; public void flush() throws IOException - golete coninutul zonei tampon, descrcndu-l n fiierul de ieire; public void close() throws IOException - nchide fiierul de ieire; public String getEncoding() - ntoarce numele canonic al codului de caractere utilizat de acest flux. Exemplu: n fiierul TestFileWriter.java este dat un exemplu similar cu cel din fiierul TestFileOutput.java, n care n locul claselor FileInputStream i FileOutputStream s-au folosit clasele FileReader i, respectiv, FileWriter.

323

Severin Bumbaru

Fiiere cu acces direct


Fiierele cu acces direct, numite i fisiere cu acces aleator (engl.: Random Access File), sunt fiiere la care programatorul poate indica prin program locul (adresa) din fiier de la care ncepe operaia de citire sau de scriere. De regul, astfel de fiiere pot fi utilizate att pentru citire, ct i pentru scriere. Pentru ca nregistrrile sale s poat fi parcurse ntr-o ordine arbitrar, fiierul cu acces direct trebuie s fie stocat pe un suport adresabil, cum ar fi discul magnetic, discul optic, memoria RAM sau ROM. n JDK, fiierele cu acces direct sunt instane ale clasei RandomAccessFile.

Clasa RandomAccessFile
Clasa java.io.RandomAccessFile este derivat direct din clasa Object, deci nu face parte din niciuna din cele patru ierarhii de fluxuri de intrare/ieire prezentate anterior, dei face parte, ca i acestea, din pachetul java.io. Fiierul cu acces direct este privit aici ca un tablou de octei memorat ntr-un sistem de fiiere (de regul n memoria extern). Exist un cursor al fiierului (numit n englez File Pointer), care se comport ca un indice al acestui tablou. Valoarea acestui indice (poziia cursorului de fiier relativ la nceputul acestuia) poate fi "citit" cu metoda getFilePointer() i poate fi modificat cu metoda seek(). Orice citire sau scriere se face ncepnd de la poziia pe care se gsete acest cursor. La sfritul operaiei, cursorul se deplaseaz pe o distan corespunzatoare cu numarul de octei care au fost citii sau scrii efectiv. Fiierul cu acces direct poate fi deschis n modul read (numai pentru citire), write (numai pentru scriere) sau read/write. n ultimul caz, este posibil s se efectueze att citiri , ct i scrieri.

Scrierea n fiierele cu acces direct se poate face att n mod text (succesiunea de octei fiind privit ca o succesiune de caractere), ct i n mod binar, la fel ca n fiierele de date, n care scrierea s-a fcut folosind un DataOutputStream. n consecin, clasa RandomAccessFile ofer att metode de scriere i de citire de octei, ct i metode de scriere i de citire pentru toate tipurile de date primitive i pentru iruri de caractere, la fel ca n cazul claselor DataOutputStream i DataInputStream. Este evident c, la citirea din fiier, trebuie s se respecte modul n care acesta a fost scris. Dac la citire se ntlnete sfritul de fiier, se genereaz o excepie de sfrit de fiier din clasa EOFException (End of File Exception), care este derivat din IOException. n toate celelalte cazuri cnd nu se poate efectua o operaie de citire sau de scriere se genereaza o IOException (Input-Output Exception).

Constructori
public RandomAccessFile(String file, String mode) throws FileNotFoundException - deschide fiierul cu acces direct cu numele file n

modul de exploatare mode. Modul poate fi "r" (numai citire) sau "rw" (citire si scriere); dac este "rw"

324

Programarea orientata pe obiecte n limbajul Java i fiierul nu exist, se creeaz un fiier nou;
public RandomAccessFile(File file, String mode) throws IOException -

acioneaz asemntor cu constructorul precedent, dar calea i numele fiierului care se deschide sunt date de instana file a clasei File. Metode
public final FileDescriptor getFD() throws IOException - ntoarce

descriptorul de fiier; citete din fiier un singur octet (sau ntoarce -1 dac s-a atins sfritul fiierului); dac n fluxul de intrare nu este disponibil nici un octet, se intr n ateptare; public int read(byte[] b) throws IOException - citete maximum b.length octei pe care i pune n tabloul b; ntoarce numrul de octei citit efectiv;
public int read() throws IOException public int read(byte[] b, int offset, int length)throws IOException -

citete cel mult length octei pe care i pune n tabloul b ncepnd de la poziia offset; ntoarce numrul de octei cititi efectiv sau -1; public final void readFully(byte[] b) throws IOException - citete exact b.length octei, pe care i pune n tabloul b; se blocheaz dac nu are sufucieni octei, iar la ntlnirea sfritului de fiier genereaz o EOFException;
public final void readFully(byte[] b, int offset, int length) throws IOException - citete exact length octei, pe care i depune n tabloul b ncepnd de la

poziia offset;
public int skipBytes(int n) - throws IOException - ncearca

s sar peste n

octei; ntoarce numrul de octei srii efectiv;


public void write(int n) throws IOException - scrie n fiier un singur octet; public void write(byte[] b) throws IOException - scrie n fiier coninutul

tabloului b;
public void write(byte[] b, int offset, int length)throws IOException -

scrie length octei din tabloul b ncepnd cu cel de pe poziia offset;


public long getFilePointer() throws IOException - ntoarce poziia

cursorului de fiier;
public void seek(long pos) throws IOException -

deplaseaz cursorul de fiier

pe poziia pos;
public long length() throws IOException - ntoarce lungimea fiierului

(exprimat n octeti);
public void setLength(long newLength) throws IOException -

seteaz noua

lungime a fiierului;
public void close() throws IOException - nchide fiierul; public final boolean readBoolean() throws IOException -

citete o valoare

boolean (un octet);


public final byte readByte() throws IOException -

citete o valoare primitiv

de tip byte; citete un singur octet, pe care l interpreteaz ca numr ntreg fr semn (n intervalul 0 .. 255); public final short readShort() throws IOException - citete un ntreg scurt (pe doi octei); public final int readUnsignedShort() throws IOException - citete doi octei, pe care i interpreteaz ca un numar ntreg scurt fr semn; public final char readChar() throws IOException - citete doi octei, pe care i interpreteaz ca un caracter Unicode;
public final int readUnsignedByte() throws IOException -

325

Severin Bumbaru
public final int readInt() throws IOException -

citete un int (pe patru citete un long (pe opt citete un float (pe citete un double (pe

octei);
public final long readLong() throws IOException -

octei);
public final float readFloat() throws IOException -

patru octei);
public final double readDouble()throws IOException -

opt octei); citete din fiier o linie de text, adic un ir de caractere ncheiat prin marcajul de sfrit de linie ('\n' pe platforme Unix sau '\r' '\n' pe platforme Microsoft); public final String readUTF() throws IOException - citete un ir de caractere n format UTF-8; public final void writeBoolean(boolean b) throws IOException - scrie o valoare boolean (pe un octet); public final void writeByte(byte v) throws IOException - scrie o valoare de tip byte; public final void writeShort(short v) throws IOException - scrie un short (pe doi octei); public final void writeChar(char v) throws IOException - scrie un caracter Unicode (pe doi octei); public final void writeInt(int v) throws IOException - scrie un int (pe patru octei); public final void writeLong(long v) throws IOException - scrie un long (pe opt octei); public final void writeFloat(float v) throws IOException - scrie un float (pe patru octei); public final void writeDouble(double v) throws IOException - scrie un double (pe opt octei); public final void writeBytes(String s) throws IOException - scrie un ir de caractere convertit n secven de octei (fiecare caracter este reprezentat pe un octet, eliminndu-se octetul superior al codului caracterului); public final void writeChars(String s) throws IOException - scrie un ir de caractere Unicode; public final void writeUTF(String s) throws IOException - scrie un ir de caractere n format UTF-8.
public final String readLine() throws IOException -

Exemplu n fiierul AccesDirect.java este dat un exemplu de aplicaie, n care se creeaz i se utilizeaz un fiier cu acces direct, cu numele "Proba.fad". Prima dat fiierul este deschis n mod "rw" (read/write). Se fac dou serii de scrieri de date, care apoi sunt citite i afiate. nainte de fiecare citire a unei serii de date se poziioneaz cursorul de fiier la nceputul seriei respective, iar datele se citesc respectnd modul n care acestea au fost scrise. Fiierul este apoi nchis i redeschis n mod "r" ("read"), dup care se poziioneaz cursorul la nceputul celei de a doua serii de date, care este citit i afiat.

326

Programarea orientata pe obiecte n limbajul Java

Fluxuri de prelucrare
Fluxurile de prelucrare se conecteaz la alte fluxuri de intrare/ieire pentru a face anumite transformri asupra datelor din fluxul respectiv. Clasele de fluxuri de prelucrare din Java API au fost prezentate pe scurt la descrierea pachetului java.io. n aceast seciune ne vom ocupa de dou categorii de fluxuri de prelucrare: fluxurile de date i fluxurile de obiecte.

Fluxuri de date
n unele aplicaii se dorete s se transmit ntr-un flux de ieire sau s se recepioneze dintrun flux de intrare date primitive reprezentate binar (de tip boolean, char, byte, short, int, long, float sau double) i iruri de caractere. n acest scop, pot fi folosite clasele java.io.DataOutputStream i java.io.DataInputStream.Se pot citi cu un DataInputStream numai date care au fost scrise cu un DataOutputStream. Instanele acestor clase nu sunt fluxuri de intrare/ieire propriu-zise, ci fluxuri de prelucrare. n consecin, ele nu se conecteaz direct la surs sau la destinaie, ci la alte fluxuri. Astfel, ieirea unui DataOutputStream se poate conecta la intrarea unui FileOutputStream, ByteArrayOutputStream sau PipedOutputStream. Se poate conecta, de asemenea la intrarea unui BufferedOutputStream care, la rndul lui, este conectat la oricare din cele trei menionate anterior. n mod similar, intrarea unui DataInputStream poate fi conectat la ieirea unui FileInputStream, ByteArrayInputStream sau PipedInputStream.

Clasa DataOutputStream
Clasa java.io.DataOutputStream este derivat din clasa java.io.FilterOutputStream i implementeaz interfaa java.io.DataOutput. Ea permite s se transmit date primitive ctre un flux de ieire ntr-o form portabil (independent de platform), cu condiia ca aceste date s fie citite ulterior printr-un DataInputStream. Constructor: - creeaz un nou flux de ieire de date, conectat la ieire la un OutputStream (adic la o instan a unei clase derivate din clasa OutputStream).
public DataOutputStream(OutputStream out)

Metode: Aceasta clas conine metodele clasei java.io.OutputStream, la care se adaug urmtoarele metode specifice, destinate scrierii n fluxul de ieire a datelor primitive sau a unor iruri de caractere:
public final void writeBoolean(boolean v) throws IOException

- scrie o

valoare boolean;
public final void writeChar(char v) throws IOException

- scrie o valoare de - scrie o valoare de - scrie o valoare

tip char, n format Unicode;


public final void writeByte(byte v) throws IOException

tip byte pe un octet;


public final void writeShort(short v) throws IOException

de tip short pe doi octei;


public final void writeInt(int v) throws IOException

- scrie o valoare de tip

327

Severin Bumbaru int pe 4 octei;


public final void writeLong(long v) throws IOException

- scrie o valoare de - scrie o valoare - scrie o

tip long pe 8 octei;


public final void writeFloat(float v) throws IOException

de tip float pe 4 octei;


public final void writeDouble(double v) throws IOException

valoare de tip double pe opt octei;


public final void writeBytes(String v) throws IOException - scrie un ir de caractere, convertit ntr-un ir de octei prin suprimarea octetului superior al fiecrui caracter; public final void writeChars(String v) throws IOException - scrie n flux un ir de caractere (n Unicode); public final void writeUTF(String v) throws IOException - scrie un ir de caractere codificat n formatul UTF-8 ntr-o form independent de main (se scrie mai nti lungimea irului pe doi octei, apoi fiecare caracter din ir pe cte un singur octet); public final int size() - ntoarce numrul de octei scrii n acest flux de ieire.

Clasa DataInputStream
Un DataInputStream este un flux de intrare de octei care este conectat la intrare la un alt InputStream i citeste din acesta date primitive ntr-o form independent de platform. Se pot citi cu DataInputStream numai date care au fost scrise cu DataOutputStream. Clasa java.io.DataInputStream este derivat din clasa java.io.FilterInputStream i implementeaz interfaa java.io.DataInput.

Constructor:
public DataInputStream(InputStream in) - creeaz un citete date din fluxul de intrare in, primit ca argument.

flux de date de intrare, care

Metode: Aceasta clas conine toate metodele clasei java.io.InputStream, la care se adaug urmtoarele metode specifice, prin care se implementeaz interfaa java.io.DataInput: - citete din fluxul de intrare un numr de octei egal cu lungimea tabloului b, primit ca argument, i i pune n acest tablou. Dac n fluxul de intrare nu sunt nca suficieni octei, dar nu s-a atins sfritul de fiier, procesul este pus n ateptare pn apar noi octei. Dac se ntlnete sfritul de fiier (EOF - End of File), se genereaz o EOFException;
public final void readFully(byte[] b) throws IOException public final void readFully(byte[] b, int off, int len) throws IOException - acioneaz similar cu metoda precedent, dar se citesc len octei, care sunt

depui n tabloul b, ncepand de la poziia off;


public final void skipBytes(int n) throws IOException - sare peste n octei din fluxul de intrare; ntoarce numrul de octei srii efectiv (este posibil s nu reueasc s sar n octeti, de exemplu dac a ntalnit sfritul fluxului); public final boolean readBoolean() throws IOException - citete un octet din fluxul de intrare i l convertete n valoare boolean; public final byte readByte() throws IOException - citete din fluxul de intrare

328

Programarea orientata pe obiecte n limbajul Java un singur octet, pe care l trateaz ca un numr ntreg cu semn n intervalul [-128, 127]; se consider c a fost scris cu writeByte(byte v); public final int readUnsignedByte() throws IOException - citete din fluxul de intrare un singur octet, pe care l trateaz ca numr ntreg fr semn n intervalul [0, 255] i l ntoarce sub form de int; public final short readShort() throws IOException - citete doi octei din fluxul de intrare i i interpreteaz ca un numr de tip short, scris anterior cu writeShort(short v); public final int readUnsignedShort() throws IOException - citete din fluxul de intrare doi octei, pe care i interpreteaz ca numr ntreg fr semn i-l ntoarce sub form de int; public final char readChar() throws IOException - citete din fluxul de intrare un char (doi octei, format Unicode); public final int readInt() throws IOException - citete patru octei si i interpreteaz ca un numr de tip int scris cu writeInt(int v); public final long readLong() throws IOException - citeste opt octei si i interpreteaz ca un numr de tip long, scris cu writeLong(long v); public final float readFloat() throws IOException - citete patru octei si i interpreteaz ca un numr de tip float, scris cu writeFloat(float v); public final double readDouble() throws IOException - citete opt octei si i interpreteaz ca un numr de tip double, scris cu writeDouble(double v); public final String readUTF() throws IOException - citete un ir de caractere n format UTF (care a fost scris cu writeUTF(String str)); Exemplu n fiierul FisierDate.java se d un exemplu de aplicaie, n care se creeaz un fiier de date i se scriu date n acest fiier folosind un DataOutputStream legat la un FileOutpusStream. Dup ce au fost scrise datele, se nchide fiierul pentru scriere i se redeschide pentru citire, dup care se citesc datele n aceeai ordine n care au fost scrise. Datele scrise n fiier i cele citite sunt afiate pe ecran pe perechi, pentru comparaie.

Fluxuri de obiecte
Fluxurile de obiecte sunt fluxuri de prelucrare care permit s se transmit obiecte. n acest scop, obiectele transmise trebuie s fie serializate, nainte de a fi transmise, adic s fie puse sub forma unei serii de octeti, ntr-un format care s permit la destinaie reconstituirea n memorie a obiectului respectiv. Astfel de obiecte se numesc serializabile. Pe platforma Java 2, fluxurile de obiecte se realizeaz prin clasele java.io.ObjectOutputStream i java.io.ObjectInputStream. Obiectele transmise de aceste fluxuri trebuie sa implementeze interfaa java.io.Serializable.

Interfaa Serializable
Orice obiect care se transmite pe un flux trebuie s aparin unei clase care implementeaz interfaa java.io.Serializable. Aceasta inseamn c trebuie ndeplinite urmtoarele condiii:

329

Severin Bumbaru - la declararea clasei respective, se pune clauza implements Serializable; - clasa trebuie s conin un constructor fr argumente; - toate cmpurile obiectului trebuie s fie serializabile, adic fie s aparina unor tipuri de date, primitive, fie unor clase care implementeaz interfaa Serializable. Interfaa Serializable nu conine cmpuri sau metode. Clauza implements Serializable constituie doar o indicaie pentru compilatorul Java s o pun sub forma serializabil.

Dac, la transmiterea obiectelor pe flux, se constat c unul din acestea nu este serializabil, se genereaz excepia NotSerializableException. Clasele care necesit o manipulare special la serializare sau deserializare trebuie s conina metode cu signaturile urmtoare:
private void writeObject(java.io.ObjectOutputStream out) throws IOException private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException;

O prezentare mai ampl a acestei interfee se gsete n documentaia Java API.

Clasa ObjectOutputStream
Clasa java.io.ObjectOutputStream este clasa fluxurilor de prelucrare pentru obiecte, avnd rolul de a serializa obiectele care urmeaz s fie puse ntr-un flux de ieire. Fluxurile de obiecte se conecteaz la ieire la un alt flux, de preferin la un FileOutputStream, ByteArrayOutputStream sau PipedOutputStream, iar utilizarea lor este asemntoare cu cea a fluxurilor de date (DataOutputStream). ntr-un flux de obiecte se pot scrie att obiecte serializate, ct i date primitive sau iruri. Clasa ObjectOutputStream conine toate metodele de scriere a datelor primitive i a irurilor, care exist i n clasele DataOutputStream i RandomAccessFile. n plus, ea conine metode necesare pentru scrierea n flux a obiectelor, cea mai frecvent folosit fiind urmtoarea: public final void writeObject(Object obj)throws IOException - scrie n fluxul de ieire obiectul obj sub form serializat; Informaii mult mai ample despre aceast clas pot fi gsite n documentaia Java API.

Clasa ObjectInputStream
Clasa java.io.ObjectInputStream servete pentru citirea (deserializarea) fluxurilor de obiecte care au fost scrise folosind clasa java.io.ObjectOutputStream. Intrarea unui ObjectInputStream este conectat la ieirea unui alt flux de intrare, de preferin FileInputStream, ByteArrayInputStream sau PipedInputStream. Clasa ObjectInputStream conine toate metodele de citire a datelor primitive i a irurilor existente n clasa DataInputStream. n plus, ea conine metode necesare pentru citirea

330

Programarea orientata pe obiecte n limbajul Java obiectelor serializate, dintre care cea mai frecvent folosit este
public final Object readObject() throws OptionalDataException, ClassNotFoundException, IOException

Informaii mai ample despre aceast clas se gsesc n documentaia Java API. Exemplu n fiierul FisierObiecte.java este dat un exemplu de aplicaie, n care se testeaz clasele ObjectOutputStream i ObjectInputStream. n prima parte a metodei main(), se creeaz un fiier (Proba1.dat) n care se scriu att obiecte (din clasele Persoana i Student), ct i date primitive, iruri i tablouri. Pentru scrierea obiectelor i a tablourilor se folosete metoda void writeObject(Object obj), iar pentru datele primitive i pentru iruri se folosesc metodele specifice pentru scrierea tipurilor respective. Dup ce s-a ncheiat scrierea datelor, se nchide fiierul Proba1.dat. n partea a doua a metodei main() se deschide fiierul Proba1.dat pentru citire i se citesc din el toate datele scrise anterior, n ordinea n care au fost scrise. ntruct metoda Object readObject() ntoarce un Object, acesta este convertit prin cast ntr-un obiect din clasa cruia i aparine n realitate. n ultima parte a metodei main() se afieaz pe ecran datele citite, putndu-se astfel verifica faptul c serializarea i deserializarea s-au fcut corect. Remarcm c, n afar de date primitive i obiecte, au fost scrise n fiier (prin metoda writeObject) i tablouri unidimensionale i bidimensionale, care au fost apoi citite corect (prin metoda readObject). Din acest exemplu se poate constata c clasele ObjectOutputStream i ObjectInputStream constituie un instrument foarte puternic de salvare i restaurare a datelor din memorie la nivelul obiectelor (al structurilor de date), care l scutesc pe programator de munca laborioas i dificil se a programa aceste operaii la nivelul inferior al fluxurilor de octei sau la nivelul fluxurilor de date primitive.

ntrebri
Nivel 1
1. Ce este un stream? 2. Ce deosebire este ntre fluxurile de ieire i cele de intrare? 3. Care sunt etapele de utilizare a unui flux de iesire? 4. Care sunt etapele de utilizare a unui flux de intrare? 5. Ce conine pachetul java.io? 6. Ce deosebire este ntre fluxurile de caractere i cele de octei? 7. Care sunt rdcinile ierarhiilor de clase pentru fluxuri de caractere? 8. Care sunt rdcinile ierarhiilor de clase pentru fluxuri de octei? 9. Ce sunt fluxurile de prelucrare? 10. Ce este un fiier? 11. Care sunt clasele folosite pentru citirea fiierelor? 12. Care sunt clasele folosite pentru scrierea fiierelor? 13. Cum se deschide un fiier? 14. Cum se nchide un fiier? 15. Ce clase se folosesc pentru a scrie date ntr-un fiier de octei i pentru a citi date

331

Severin Bumbaru dintr-un astfel de fiier? 16. Ce sunt fiierele cu acces direct? 17. Crei clase i aparin fiierele cu acces direct? 18. Ce fel de operaii se pot face asupra unui fiier cu acces direct? 19. Ce este cursorul (pointerul) fiierului cu acces direct? 20. Care sunt modurile n care poate fi deschis un fiier cu acces direct? 21. Ce sunt fluxurile de prelucrare? 22. Ce sunt fluxurile de date? 23. Prin ce clase se realizeaz fluxurile de date? 24. Ce este un flux de obiecte? 25. Prin ce clase se realizeaz fluxurile de obiecte? 26. Ce proprietate trebuie sa aib obiectele pentru a putea fi transmise ntr-un flux de obiecte? 27. Ce reprezint interfaa Serializable? 28. Cum este folosit interfaa Serializable? 29. Ce condiii trebuie s ndeplineasc o clas pentru a fi serializabil? 30. Ce metode conine interfaa Serializable?

Nivel 2
1. Dece fluxul este un obiect abstract? 2. Clasele Reader i Writer sunt abstracte sau instaniabile? 3. Ce se nelege prin marcarea unui flux i prin ce metod se realizeaz? 4. Cum se poate reveni ntr-un flux la marcajul fcut anterior? 5. Clasele InputStream i OutputStream sunt sau nu instaniabile? 6. n ce situaii este obligatorie folosirea fluxurilor de octei? 7. Ce clas se folosete pentru a scrie date ntr-un fiier de caractere? 8. Ce clas se folosete pentru a citi date dintr-un fiier de caractere? 9. Prin ce metode se scriu datele primitive ntr-un fiier cu acces direct? 10. Prin ce metode se citesc datele primitive dintr-un fiier cu acces direct? 11. Prin ce metode se scriu irurile de caractere ntr-un fiier cu acces direct? 12. Ce este UTF? 13. Pot fi fluxurile de date conectate direct la un fiier? 14. La ce fluxuri se conecteaz fluxurile de date? 15. Ce se ntampl dac se ncearc introducerea ntr-un flux de obiecte a unui obiect neserializabil? Cnd se constat anomalia: la compilare sau la execuie? 16. Un flux de obiecte poate conine i date primitive? dece? 17. Pot fi puse tablourile ntr-un flux de obiecte?

332

Programarea orientata pe obiecte n limbajul Java

Fire de execuie
Conceptul de proces. Procese paralele i concurente Fire de execuie Clasa Thread Interfaa Runnable Sincronizarea firelor de execuie ntrebri. 333 335 335 346 348 354

Conceptul de proces. Procese paralele i concurente


n general, se numete proces o succesiune de transformri sau de operaii care conduce la realizarea unui anumit rezultat. Esenial pentru un proces este caracterul su temporal: fiecare transformare elementar necesit un anumit timp, iar procesul n ansamblu este o succesiune de astfel de transformri elementare. Termenul este folosit n domenii diferite: procese fizice, procese chimice, procese tehnologice, procese biologice, procese economice, procese sociale, procese juridice etc. n informatic, procesul este un program n execuie. n consecin, fiecrui proces i se asociaz un program, i un ansamblu de resurse necesare executrii acestui program: o anumit zon din memoria intern n care se pstreaz datele programului, acces la procesorul sistemului, acces la anumite dispozitive de intrare/ieire etc. Procesul const tocmai n efectuarea n timp a succesiunii de operaii prevzut n program, folosind n acest scop resursele alocate. n mod tradiional, programul este executat de ctre un singur procesor (dispozitiv de prelucrare), care poate efectua, la un moment de timp dat, numai o singur operaie. n consecin, operaiile prevzute n program trebuie executate secvenial, astfel nct operaia urmtoare nu poate ncepe dect dup ncheierea celei precedente. Toate programele prezentate de noi n capitolele precedente se ncadreaz n aceast categorie.

Este posibil ca mai multe procese s se desfoare simultan, adic intervalele de timp corespunztoare acestor procese s se suprapun total sau parial. Astfel de procese pot fi paralele sau concurente.

333

Severin Bumbaru

Dac procesele de calcul care au loc simultan folosesc resurse diferite (sunt executate de procesoare diferite, folosesc zone de memorie intern i extern diferite etc.), ele se numesc procese paralele. Dac procesele care se desfoar n acelai interval de timp folosesc anumite resurse comune, ele se numesc procese concurente. Cel mai frecvent se ntlnete situaia, n care mai multe procese folosesc n comun acelai procesor. ntruct, la un moment dat, procesorul nu poate efectua dect o singur operaie, nseamn c este necesar s se adopte o anumit strategie, conform creia timpul de funcionare al procesorului este partajat ntre diferitele procese concurente. n principiu, aceste strategii se mpart n dou categorii: 1. Se acord fiecruia dintre procesele concurente un anumit nivel de prioritate. Dac mai multe procese solicit simultan aceeai resurs, ea este alocat procesului cu prioritate superioar.

Conform acestei strategii, dac, n timpul derularii unui proces A, procesorul este solicitat de un alt proces B de prioritate superioar, procesul A este ntrerupt, trecndu-se la executarea procesului B. Dup ncheierea executrii procesului prioritar B, se revine la procesul A, care este continuat din starea n care a fost ntrerupt. Este nsa posibil ca, n timp ce se deruleaza procesul B, procesorul sa fie solicitat de un alt proces C, de prioritate i mai nalta. n acest caz, i procesul B va fi ntrerupt, trecndu-se la executarea procesului C i aa mai departe. 2. Timpul total de funcionare a procesorului este porionatsau divizat (mprit n intervale de durate egale sau diferite), acordndu-se succesiv cte un astfel de nterval de timp fiecruia dintre procesele concurente. La expirarea intervalului de timp alocat, numit i felie sau tran de timp (englez: time slice), procesul n curs este ntrerupt i se trece la executarea procesului urmtor, prin rotaie. O astfel de utilizare a procesorului se numete "partajare a timpului" (englez: time sharing sau time slicing). Cele dou strategii menionate aici pot fi aplicate n diferite variante i pot fi combinate n diferite moduri. Cel mai frecvent, partajarea timpului este aplicat numai pentru procesele cu acelai nivel de prioritate. Majoritatea sistemelor de operare ale calculatoarelor moderne permit executarea n acelai timp a mai multor programe, deci permit concurena proceselor la nivel de program (de aplicaie). De exemplu, n timp ce editm un text, putem tipri alt text la imprimant, putem atepta sosirea de pe reea a unei pagini de Web etc. Studierea acestui mod de funcionare a calculatorului, cunoscut sub numele de multitasking, se face la cursul de "Sisteme de operare". Pentru a pune n eviden distincia ntre program i proces, putem meniona c acelai program poate da natere la procese diferite: dac programul conine ramificaii i/sau cicluri, parcurgerea efectiv a acestora (ce ramuri vor fi executate efectiv i de cte ori se vor parcurge ciclurile) depinde de datele de intrare. n cadrul multitaskingului, este chiar posibil ca doi utilizatori s utilizeze simultan acelai program folosind date diferite, astfel nct se genereaz procese diferite.

334

Programarea orientata pe obiecte n limbajul Java

Fire de execuie
Firul de execuie (n englez: Thread) este, n esen, un subproces strict secvenial. Meninnd definiia procesului ca un program n curs de execuie, putem considera acum c procesul este format din mai multe fire de execuie care se deruleaz n paralel, concurnd la utilizarea resurselor alocate procesului respectiv. n limbajul Java, exist posibilitatea de a se crea programe care conin mai multe fire de execuie. Aceasta nseamn c, la executarea lor, se vor crea mai multe subprocese care se vor desfura simultan, folosind acelai procesor i aceeai zon de memorie. Acest mod de funcionare se numete n englez multithreading.

Chiar i n cazul programelor Java n care nu sunt prevzute explicit mai multe fire de execuie, n timpul executrii lor coexist cel puin dou astfel de fire: cel al aplicaiei propriu-zise i cel al colectorului de reziduuri (garbage collector). Colectorul de reziduuri este un fir de execuie cu nivel de prioritate cobort, care funcioneaz atunci cnd apar ntreruperi n desfurarea aplicaiei propriu-zise (de exemplu, cnd se ateapt efectuarea unor operaii de intrare/ieire). n consecin, maina virtual Java are intrinsec o funcionare de tip multithreading. Exist dou moduri de a programa un fir de execuie: - prin extinderea clasei Thread; - prin implementarea interfeei Runnable.

Clasa Thread
Clasa java.lang.Thread realizeaz un fir de execuie. Acesta poate fi un fir de execuie obinuit, sau un demon. Demonul (englez: daemon thread) este un fir de execuie de prioritate cobort, care nu este invocat n mod explicit. El st "adormit" i intr automat n execuie atunci cnd sunt ndeplinite anumite condiii. Un exemplu tipic de demon este colectorul de reziduuri. Dup cum tim deja, acesta este un fir de execuie de prioritate cobort, care intr n funciune atunci cnd n memorie apar obiecte ctre care nu mai exist referine. Crearea unui fir de execuie se face invocnd unul dintre constructorii clasei Thread. Dintre acetia, i menionm aici pe urmtorii:

- creeaz un nou fir de execuie cu numele implicit Thread-n, unde n este un numr de ordine; public Thread(String name) - creeaz un nou fir de execuie cu numele name; public Thread(Runnable target) - creeaz un nou fir de execuie, care conine obiectul target cu interfaa Runnable, iar numele firului este cel implicit;
public Thread()

335

Severin Bumbaru
public Thread(Runnable target, String name) - creeaz un conine obiectul target cu interfaa Runnable i are numele name.

nou fir de execuie,

care

Cele mai frecvent utilizate metode ale clasei Thread sunt run(), start() i sleep(). Iat o list a principalelor metode ale acestei clase:

public void run() - conine programul care trebuie executat de firul respectiv; Aa cum este ea n clasa Thread, metoda nu face nimic (are corpul vid). Aceast metod trebuie redefinit fie prin crearea unei subclase a clasei Thread, fie prin crearea unei obiect cu interfaa Runnable, care s fie nglobat n acest Thread (folosind constructorul Thread(Runnable target)); public void start() - pune firul nou creat n starea "gata pentru execuie"; public static void sleep(long millis) throws InterruptedException oprete temporar execuia acestui fir, pentru o durata de millis milisecunde; public static void yield() - oprete temporar execuia acestui fir, permind monitorului s dea controlul altui fir de aceeai prioritate; public static Thread currentThread() - ntoarce o referin la firul care este executat n momentul curent; public final void setPriority(int newPriority) - seteaza prioritatea firului de execuie; prioritatea trebuie sa fie cuprins n intervalul [Thread.MIN_PRIORITY, Thread.MAX_PRIORITY] (valorile lor fiind, respectiv, 1 i 10). Nerespectarea acestui interval genereaza o IllegalArgumentException. Daca nu este stabilit explicit, prioritatea este Thread.NORM_PRIORITY (are valoarea 5). public final int getPriority() - ntoarce prioritatea curent a firului de execuie. public final void setName(String name) - pune firului de execuie un nou nume; public final String getName() - ntoarce numele firului de execuie; public final void setDaemon(boolean on) - d firului de execuie calitatea de demon (dac argumentul este true) sau de fir obinuit (dac argumentul este false); Metoda poate fi invocat numai dac firul nu este activ, altfel se genereaz o IllegalThreadStateException. public final boolean isDaemon() - testeaz dac firul de execuie este demon.

La programarea unui fir de execuie, principala atenie se acord metodei run(), deoarece ea conine programul propriu-zis, care trebuie executat de acest fir. Totui, metoda run()nu este invocat explicit. Ea este invocat de maina virtual Java, atunci cnd firul respectiv este pus n mod efectiv n execuie. Pentru redefinirea metodei Run este necesar sa creem o subclas a clasei Thread sau sa creem o clas cu interfaa Runnable, i s dm o instan a acestei clase ca argument constructorului clasei Thread. Dup ce firul de execuie a fost creat (de exemplu prin expresia new Thread()), el exist n memorie, dar nca nu poate fi executat. Se gsete, deci, n starea "nou creat" (engleza: born). Pentru a-l face gata de execuie, pentru firul respectiv este invocat metoda start().

Dup invocarea metodei start(), firul este executabil, dar aceasta nu nseamn c el este

336

Programarea orientata pe obiecte n limbajul Java pus n execuie imediat: noul fir devine concurent cu cele deja existente (n primul rnd cu cel care l-a creat), i va fi pus n execuie n mod efectiv (i se va acorda acces la procesor) atunci cnd i vine rndul, conform cu strategia de alocare a resurselor adoptat. Un fir n curs de execuie poate fi oprit temporar ("adormit") invocnd metoda static sleep(long millis). Argumentul acestei metode este intervalul de timp ct procesul se va gsi n stare de "somn", exprimat n milisecunde.

Referitor la utilizarea acestei metode, remarcm dou aspecte: - ntruct ea poate "arunca" o InterruptedException, este necesar s fie prins ntr-un bloc try..catch; - ntrucat metoda este static i nu are ca argument un fir de execuie, ea nu poate fi invocat dect n metodele firului de execuie cruia i se aplic. Fiecrui fir de execuie i se asociaz o anumit prioritate. Aceasta este un numar ntreg, cuprins ntre valorile Thread.MIN_PRIORITY i Thread.MAX_PRIORITY (avnd valorile 1 i respectiv 10). Dac metoda setPriority(int newPriority) nu este invocat explicit, firului i se d prioritatea implicita Thread.NORM_PRIORITY, respectiv 5. Daca firul de execuie solicit o operaie de intrare/ieire, el rmne blocat pe ntreaga durat a executrii operaiei respective. n timpul n care firul de execuie "doarme" (ca urmare a invocrii metodei sleep()) sau este blocat (deoarece asteapta terminarea unei operatii de intrare/iesire), se pot executa alte fire, de prioritate egal sau inferioar. n schimb, firele de prioritate superioar pot ntrerupe n orice moment executarea celor de prioritate inferioar. Un proces poate fi pus, de asemenea, n ateptare prin invocarea metodei wait(). n acest caz, firul ateapt confirmarea efecturii unei anumite aciuni, prin invocarea metodei notify() sau notifyAll(). Aceste trei metode exist n clasa Object i servesc la sincronizarea firelor de execuie.

Avnd n vedere cele de mai sus, punem n eviden urmatoarele stri n care se poate gsi un fir de execuie pe durata ciclului su de via: - nou creat (englez: born) - este starea n care se gsete imediat ce a fost creat prin operatorul new; n aceast stare, firul nu poate fi executat; - gata de execuie (englez: ready) - este starea n care firul poate fi pus n execuie; punerea efectiv n execuie se face de ctre maina virtuala Java atunci cnd procesorul este liber i nu sunt gata de execuie fire de prioritate superioar; - n execuie (englez: running) - este starea n care procesul se execut efectiv (ocup procesorul); - adormit (englez: sleeping) - este starea de oprire temporar, ca urmare a invocrii metodei sleep(); - blocat (englez: blocked) - este starea n care ateapt incheierea unei operaii de intrare/ieire; - n ateptare (englez: waiting) - este starea n care firul se gsete din momentul n care

337

Severin Bumbaru se invoc metoda wait(), pn cnd primete o confirmare dat prin invocarea metodei notify(); - mort (englez: dead) - este starea n care intr firul de execuie dupa ce s-a ncheiat executarea metodei run(). Relaiile dintre aceste stri sunt reprezentate grafic n figura de mai jos.

Denumirile strilor firului de execuie au fost date n limba englez, pentru a putea fi urmarit mai uor documentaia original din Java API. Trecerea de la starea Born la starea Ready (gata) se face prin invocarea metodei start(). Trecerea de la starea Ready la starea Running (n execuie) se face de ctre maina virtual Java (de ctre dispecerul firelor) atunci cnd sunt create condiiile necesare: procesorul este liber i nici un fir de execuie de prioritate superioar nu se gsete n starea Ready. Trecerea de la starea Running la starea Ready se face la executarea metodei yield(), sau atunci cnd a expirat trana de timp alocat procesului (n cazul sistemelor cu diviziune a timpului). Trecerea de la starea Running la starea Sleeping se face la executarea metodei sleep(). Trecerea de la starea Sleeping la starea Ready se face cnd a expirat intervalul de timp de

338

Programarea orientata pe obiecte n limbajul Java "adormire" (intervalul dat ca argument n metoda sleep(long millis)). Trecerea de la starea Running la starea Blocked are loc atunci cnd firul de execuie respectiv solicit efectuarea unei operaii de intrare ieire. Trecerea de la starea Blocked la starea Ready are loc cnd s-a ncheiat operaia de intrare/ieire solicitat de acest fir. Trecerea de la starea Running la starea Waiting se face la invocarea metodei wait(). Trecerea de la starea Waiting la starea Ready se face cnd se primete o confirmare prin invocarea metodei notify() sau notifyAll(). Trecerea de la starea Running la starea Dead are loc atunci cnd se ncheie executarea metodei run() a firului de execuie respectiv. Se observ c orice fir de execuie i ncepe ciclul de via n starea Born i l ncheie n starea Dead. Punerea firului n execuie efectiv (trecerea de la Ready la Running) se face numai de ctre dispecerul firelor. n toate cazurile n care se ncheie o stare de oprire temporar a execuiei (Sleeping, Waiting sau Blocked), firul de execuie respectiv trece n starea Ready, ateptnd ca dispecerul s-l pun efectiv n execuie (s-l treac n starea Running). n timpul ct firul de execuie se gsete n orice alt stare dect Running, procesorul calculatorului este liber, putnd fi utilizat de alte fire de execuie sau de alte procese.

Exemplul 1 Fiierul DouaFireA.java conine un exemplu de aplicaie, n care se creeaz fire de execuie folosind o clas care extinde clasa Thread.
/* Crearea si utilizarea unei clase de fire de executie care extinde clasa Thread dar nu foloseste metodele sleep sau yield. Se creeaza doua fire de aceeasi prioritate (Thread.NORM_PRIORITY). */ class DouaFireA { /* Clasa firelor de executie */ static class Fir extends Thread { Fir(String numeFir) { super(numeFir); System.out.println("S-a creat firul "+getName()); } /* Redefinirea metodei run() din clasa Thread */ public void run() { System.out.println("Incepe executarea firului "+getName()); for(int i=0; i<6; i++) {

339

Severin Bumbaru

System.out.println("Firul "+getName()+" ciclul i="+i); } } } /* incheierea clasei Fir */ public static void main(String args[]) throws Exception { Fir fir1, fir2; System.out.println("Se creeaza firul Alpha"); fir1=new Fir("Alpha"); System.out.println("Se creeaza firul Beta"); fir2=new Fir("Beta"); System.out.println("Se pune in executie firul Alpha"); fir1.start(); System.out.println("Se pune in executie firul Beta"); fir2.start(); System.out.println("Sfarsitul metodei main()"); } /* Sfarsitul metodei main() */ }

Clasa Fir din aceast aplicaie extinde clasa Thread, deci instanele ei sunt fire de execuie. n clasa Fir s-a redefinit metoda run(), astfel nct s conin programul firului respectiv. n cazul nostru, firul execut un ciclu, n care afieaz la terminal un mesaj, coninnd numele firului i indicele ciclului executat. n metoda main() a aplicaiei se creeaz dou instane ale clasei Fir, dndu-le, respectiv, numele Alpha i Beta, apoi se lanseaz n execuie aceste fire. Iat un exemplu de rezultat al executrii acestei aplicaii:

Se creeaza firul Alpha S-a creat firul Alpha Se creeaza firul Beta S-a creat firul Beta Sfarsitul metodei main() Incepe executarea firului Alpha Firul Alpha ciclul i=0 Firul Alpha ciclul i=1 Firul Alpha ciclul i=2 Firul Alpha ciclul i=3 Firul Alpha ciclul i=4 Firul Alpha ciclul i=5 Incepe executarea firului Beta Firul Beta ciclul i=0 Firul Beta ciclul i=1 Firul Beta ciclul i=2 Firul Beta ciclul i=3 Firul Beta ciclul i=4 Firul Beta ciclul i=5

Remarcm cele ce urmeaz. - n realitate, n afar de firele de execuie Alpha i Beta create explicit de ctre noi, mai exista inc dou fire de execuie: cel al aplicaiei propriu-zise (executarea metodei main()) i cel al colectorului de reziduuri. ntruct nu s-au setat explicit prioritile, firele Alpha, Beta i main() au toate prioritatea Thread.NORM_PRIORITY.

340

Programarea orientata pe obiecte n limbajul Java - ntruct toate firele au aceeai prioritate, durata executrii fiecrui fir este mic i nu s-au folosit metode de suspendare a execuiei (yield(), sleep(), wait()), n momentul n care ncepe executarea unui fir acesta se execut pn la capt, dup care procesorul sistemului este preluat de firul urmtor. n consecin s-a executat mai nti metoda main() pn la incheierea ei (confirmat prin mesajul "Sfritul metodei main()"), dup care se execut complet firul Alpha i apoi firul Beta (n ordinea lansrii). - Aplicaia se ncheie n momentul n care s-a ncheiat ultimul fir de execuie.

Exemplul 2 n fiierul DouaFireA1.java se reia aplicaia din exemplul precedent, dar la sfritul fiecrui ciclu de indice i se invoc metoda yield() care suspend firul n curs i permite astfel s se transmit controlul urmtorului fir de aceeai prioritate.
/* Crearea si utilizarea unei clase de fire de executie care extinde clasa Thread. Se foloseste metoda yield() pentru a ceda controlul altui fir de aceeasi prioritate. Se creeaza doua fire de aceeasi prioritate (Thread.NORM_PRIORITY). */ class DouaFireA1 { /* Clasa firelor de executie */ static class Fir extends Thread { Fir(String numeFir) { super(numeFir); System.out.println("S-a creat firul "+getName()); } /* Redefinirea metodei run() din clasa Thread */ public void run() { System.out.println("Incepe executarea firului "+getName()); for(int i=0; i<6; i++) { System.out.println("Firul "+getName()+" ciclul i="+i); yield(); // cedarea controlului procesorului } } } /* incheierea clasei Fir */ public static void main(String args[]) throws Exception { Fir fir1, fir2; System.out.println("Se creeaza firul Alpha"); fir1=new Fir("Alpha"); System.out.println("Se creeaza firul Beta"); fir2=new Fir("Beta"); System.out.println("Se pune in executie firul Alpha"); fir1.start(); System.out.println("Se pune in executie firul Beta"); fir2.start(); System.out.println("Sfarsitul metodei main()");

341

Severin Bumbaru

} /* Sfarsitul metodei main() */ }

Rezultatul executarii acestei aplicatii este urmatorul:

Se creeaza firul Alpha S-a creat firul Alpha Se creeaza firul Beta S-a creat firul Beta Sfarsitul metodei main() Incepe executarea firului Alpha Firul Alpha ciclul i=0 Incepe executarea firului Beta Firul Beta ciclul i=0 Firul Alpha ciclul i=1 Firul Beta ciclul i=1 Firul Alpha ciclul i=2 Firul Beta ciclul i=2 Firul Alpha ciclul i=3 Firul Beta ciclul i=3 Firul Alpha ciclul i=4 Firul Beta ciclul i=4 Firul Alpha ciclul i=5 Firul Beta ciclul i=5

Se observ cu uurin c, n acest caz, executarea celor dou fire, Alpha i Beta, are loc intercalat, deoarece, dup fiecare parcurgere a unui ciclu ntr-un fir, se invoc metoda yield() , cedndu-se procesorul sistemului n favoarea celuilalt fir. Aceasta nu s-ar fi ntmplat, dac cele doua fire ar fi avut prioriti diferite.

Exemplul 3 n fiierul DouaFireB.java s-a reluat aplicaia din Exemplul 1, aducndu-i-se urmtoarele modificri: - n ciclul cu contorul i din metoda run() a clasei Fir s-a mai introdus un ciclu interior (cu contorul j) care se parcurge de 100000000 ori, pentru a mri n mod artificial durata de execuie; n locul acestuia se putea pune, evident, orice alta secvena de instruciuni cu durata de execuie comparabil; - cele dou cicluri (pe i i pe j) au fost introduse i n metoda main(), pentru a putea urmri executarea acesteia dup lansarea firelor Alpha i Beta. Fragmentele de program nou adugate sunt puse n eviden n textul de mai jos cu caractere aldine (ngroate).
/* Crearea si utilizarea unei clase de fire de executie. In metoda run a firului nu se folosesc metodele sleep() sau yield(), dar se parcurge un ciclu de contorizare (pe j) de 100000000 ori pentru a mari durata de executie a ciclului exterior (pe indicele i). Se creeaza doua fire de aceeasi prioritate (Thread.NORM_PRIORITY). */

342

Programarea orientata pe obiecte n limbajul Java

class DouaFireB { /* Clasa firelor de executie */ static class Fir extends Thread { Fir(String numeFir) { super(numeFir); System.out.println("S-a creat firul "+getName()); } /* Redefinirea metodei run() din clasa Thread */ public void run() { System.out.println("Incepe executarea firului "+getName()); for(int i=0; i<5; i++) { for(int j=0; j<100000000; j++); System.out.println("Firul "+getName()+" ciclul i="+i); } } } /* incheierea clasei Fir */ public static void main(String args[]) throws Exception { Fir fir1, fir2, fir3; System.out.println("Se creeaza firele Alpha si Beta"); fir1=new Fir("Alpha"); fir2=new Fir("Beta"); System.out.println("Se pun in executie cele doua fire"); fir1.start(); fir2.start(); for (int i=0; i<5; i++) { for(int j=0; j<100000000; j++); System.out.println("main() ciclul i="+i); } System.out.println("Sfarsitul metodei main()"); } /* Sfarsitul metodei main() */ }

Iat un exemplu de rezultat obinut prin executarea acestei aplicaii:

Se creeaza firele Alpha si Beta S-a creat firul Alpha S-a creat firul Beta Incepe executarea firului Alpha Incepe executarea firului Beta Firul Alpha ciclul i=0 Firul Beta ciclul i=0 main() ciclul i=0 main() ciclul i=1 Firul Alpha ciclul i=1 Firul Beta ciclul i=1 main() ciclul i=2 Firul Alpha ciclul i=2 Firul Beta ciclul i=2 main() ciclul i=3 Firul Alpha ciclul i=3 Firul Beta ciclul i=3

343

Severin Bumbaru

main() ciclul i=4 Sfarsitul metodei main() Firul Alpha ciclul i=4 Firul Beta ciclul i=4

Constatm c, ntrucat durata de execuie a fiecrui fir a devenit mult mai mare dect n exemplul precedent i toate cele trei fire (Alpha, Beta si main()) au aceeai prioritate (Thread.NORM_PRIORITY), se aplic o strategie de partajare a timpului, astfel nct timpul de funcionare al procesorului este alocat sub forma de trane succesive fiecruia dintre procese. n consecin, se creeaza impresia c cele trei procese se desfoar n paralel, simultan n timp.

Exemplul 4 n fiierul DouaFireC.java se reia aplicaia din exemplul precedent, dar s-a renunat la ciclurile interioare (cu contorul j), n schimb dup parcurgerea fiecrui ciclu de indice i se pune firul respectiv in ateptare timp de 1000 milisecunde prin invocarea metodei sleep. Aceast metod arunc excepia InterruptedException care trebuie captat. n mod similar s-a procedat i n ciclul din metoda main. Avnd ns n vedere c metoda main() nu se gsete ntr-o clasa derivata din Thread, la invocarea metodei statice sleep a fost necesar s se indice clasa creia i aparine, deci invocarea s-a fcut sub forma Thread.sleep(1000).

/* Crearea i utilizarea unei clase de fire de execuie. n metoda run a firului se foloseste metoda sleep(1000) pentru a pune firul in asteptare pe o durata de 1000 milisecunde. Similar se procedeaza in metoda main() */ class DouaFireC { /* Clasa firelor de executie */ static class Fir extends Thread { Fir(String numeFir) { super(numeFir); System.out.println("S-a creat firul "+getName()); } /* Redefinirea metodei run() din clasa Thread */ public void run() { System.out.println("Incepe executarea firului "+getName()); for(int i=0; i<5; i++) { System.out.println("Firul "+getName()+" ciclul i="+i); try { sleep(1000); } catch(InterruptedException e) {}

344

Programarea orientata pe obiecte n limbajul Java

} } } /* incheierea clasei Fir */ public static void main(String args[]) throws Exception { Fir fir1, fir2, fir3; System.out.println("Se creeaza firele Alpha si Beta"); fir1=new Fir("Alpha"); fir2=new Fir("Beta"); System.out.println("Se pun in executie cele doua fire"); fir1.start(); fir2.start(); for (int i=0; i<5; i++) { System.out.println("main() ciclul i="+i); try { Thread.sleep(1000); } catch(InterruptedException e) {} } System.out.println("Sfarsitul metodei main()"); } /* Sfarsitul metodei main() */ }

Iat rezultatul executrii acestei aplicaii:

Se creeaza firele Alpha si Beta S-a creat firul Alpha S-a creat firul Beta Se pun in executie cele doua fire main() ciclul i=0 Incepe executarea firului Alpha Firul Alpha ciclul i=0 Incepe executarea firului Beta Firul Beta ciclul i=0 main() ciclul i=1 Firul Alpha ciclul i=1 Firul Beta ciclul i=1 main() ciclul i=2 Firul Alpha ciclul i=2 Firul Beta ciclul i=2 main() ciclul i=3 Firul Alpha ciclul i=3 Firul Beta ciclul i=3 main() ciclul i=4 Firul Alpha ciclul i=4 Firul Beta ciclul i=4 Sfarsitul metodei main()

n timp ce un fir "doarme", se pot executa alte fire, chiar dac ele sunt de prioritate inferioar!

345

Severin Bumbaru

Interfaa Runnable
Interfaa java.lang.Runnable trebuie implementat de orice clas care nu este descendent a clasei java.lang.Thread, dar ale crei instane trebuie tratate ca nite fire de execuie. Singura metod a acestei interfee este
public void run()

care are acelai rol cu cea din clasa Thread. Necesitatea implementrii interfeei Runnable apare atunci cnd dorim s creem o clasa de fire de execuie care nu extinde clasa Thread. Motivul ar putea fi, de exemplu, cel c clasa nou creat, B, trebuie sa extind o alta clas, A, care nu este descendent a clasei Thread Se tie c n Java nu exist motenire multipl, deci clasa B nu poate avea ca superclase att clasa A, ct i clasa Thread. n acest caz, vom crea o clas B care extinde clasa A i implementeaza interfaa Runnable, care conine metoda run(). Utilizarea instanelor claselor cu interfaa Runnable se face, punndu-le ca argumente ale urmtorilor constructori ai clasei Thread: O se comport ca i cum ar fi instana unei extensii a clasei Thread care ar conine metoda run() a obiectului target cu interfaa Runnable.
public Thread(Runnable target) public Thread(Runnable target, String name) instan a clasei Thread creat cu un astfel de constructor,

Exemplul 1 n fiierul DouaFireAR.java se d un exemplu de aplicaie similar cu cea din fiierul DouaFireA1.java, cu deosebirea c clasa Fir nu extinde clasa Thread, ci implementeaz interfaa Runnable. Fragmentele de program modificate sunt puse n evidena n textul surs de mai jos prin caractere aldine (ingroate).
/* Crearea si utilizarea unei clase cu interfata Runnable. Se foloseste metoda yield() pentru a ceda controlul altui fir de aceeasi prioritate. Se creeaza doua fire de aceeasi prioritate (Thread.NORM_PRIORITY), utilizand ca argument al constructorului instante ale clasei Fir cu interfata Runnable. */ class DouaFireAR { /* Clasa cu interfata Runnable */ static class Fir implements Runnable { /* Definirea metodei run() din interfata Runnable */ public void run() { System.out.println("Incepe executarea firului "+ Thread.currentThread().getName()); for(int i=0; i<6; i++) { System.out.println("Firul "+

346

Programarea orientata pe obiecte n limbajul Java

Thread.currentThread().getName()+" ciclul i="+i); Thread.yield(); // cedarea controlului procesorului } } } /* incheierea clasei Fir */ public static void main(String args[]) throws Exception { Thread fir1, fir2; System.out.println("Se creeaza firul Alpha"); fir1=new Thread(new Fir(), "Alpha"); System.out.println("Se creeaza firul Beta"); fir2=new Thread(new Fir(), "Beta"); System.out.println("Se pune in executie firul Alpha"); fir1.start(); System.out.println("Se pune in executie firul Beta"); fir2.start(); System.out.println("Sfarsitul metodei main()"); } /* Sfarsitul metodei main() */ }

Comparnd cu Exemplul 2 din sectiunea Clasa Thread, constatm cele ce urmeaz. - Clasa Fir nu mai extinde clasa Thread, ci implementeaza interfaa Runnable. - n metoda run() a clasei Fir s-a avut n vedere c aceasta nu extinde clasa Thread i deci nu motenete metodele ecesteia. n consecin: . metoda static yield() a clasei Thread a fost invocat sub forma Thread.yield(); . pentru a obine o referin la instana curent a clasei Thread, necesar invocrii metodei getName(), s-a folosit metoda static Thread.getCurrentThread(). - Crearea celor dou fire de execuie n metoda main() s-a fcut folosind un constructor al clasei Thread, cruia i s-au dat ca parametri o instan a clasei Fir i numele firului respectiv, de exemplu:
fir1=new Thread(new Fir(), "Alpha");

Dac se compileaz i se execut aceast aplicaie, se obin exact aceleai rezultate ca n cazul cnd s-a recurs la extinderea clasei Thread.

Exemplul 2 n fiierul Bondari.java este dat un exemplu de aplicaie, n care se pot crea mai multe fire de execuie, fiecare avnd propria sa interfa grafic. Fiecare fir de execuie este o instana a clasei Bondar, care extinde clasa JFrame i implementeaz interfaa Runnable. Aplicaia propriu-zis (care conine metoda main()) este clasa Bondari, care extinde i ea clasa JFrame. Fereastra principal a aplicaiei (interfaa clasei Bondari) conine numai un buton cu inscripia "Creare nou bondar". De cte ori se apas acest buton, se creeaza o noua instan a clasei Bondar. Clasa Bondar are propria ei interfa grafic, n care exist dou rigle pentru ajustarea perioadei i amplitudinii i o fereastr n care evolueaz "bondarul". Acesta este un mic

347

Severin Bumbaru dreptunghi rou, a crui micare o simuleaza pe cea a unei insecte n zbor. Amplitudinea, ct i perioada deplasrilor "bondaruliui" sunt ajustate cu cele dou rigle. Dac se acioneaza butonul de nchidere a ferestrei "bondarului" (cel marcat cu X din colul dreapta-sus), se ncheie ciclul de via al firului de execuie respectiv. Aceasta are loc, ntrucat ciclul din metoda run() a firului continu ct timp variabila booleana esteViu are valoarea true. Cnd se acioneaza butonul de nchidere a ferestrei "bondarului", evenimentul este captat de metoda windowClosing() a clasei SfarsitBondar, care pune variabila esteViu a "bondarului" respectiv la valoarea false. Dac se acioneaz butonul de nchidere a ferestrei principale (cea care conine butonul "Creare nou bondar"), evenimentul este captat de metoda windowClosing() a clasei Iesire, astfel c se execut metoda exit(0). Efectul este ncheierea execuiei tuturor firelor i oprirea mainii virtuale Java.

Sincronizarea firelor de execuie


Pan n prezent, am considerat c fiecare fir (Thread) se execut independent, fr legtura cu celelalte fire ale aceleeai aplicaii. Exist ns situaii, n care este necesar s se stabileasc anumite interdependene ntre fire. Aceasta se ntmpl, n special, atunci cnd un fir trebuie s foloseasc datele produse de alt fir: este evident c nu le poate folosi nainte ca ele s fie produse. n limbajul Java, sincronizarea firelor de execuie se face prin intermediul monitoarelor. Se numete monitor instana unei clase care conine cel puin o metod sincronizat, sau o metod care conine un bloc sincronizat. Se numete metod sincronizat orice metod care conine n antetul su modificatorul synchronized, deci este declarat sub forma
[modif]synchronized tip nume_metoda(declaratii_argumente) {corpul_metodei}

unde modif reprezinta ali eventuali modificatori (public, static etc.). Cnd un fir ncepe executarea uni metode sincronizate a unui monitor, el devine "proprietarul" monitorului cruia i aparine aceast metod (englez: owner) i deine aceast calitate pn la ncheierea executrii metodei sincronizate respective, sau pn cnd se autosuspend invocnd metoda wait(), aa cum vom explica ulterior. Pe toata durata ct un fir de execuie este proprietarul unui monitor, nici un alt fir nu poate invoca o metod sincronizat a monitorului respectiv. Aa dar, orice fir care, n acest interval de timp, ar ncerca s invoce o metod sincronizat a unui monitor al crui proprietar este alt fir, trebuie s atepte pn cnd monitorul respectiv este eliberat de proprietarul existent. n acest fel, se evit situaiile n care un fir de execuie ar interveni s fac modificri asupra unui obiect, n timp ce acesta se gsete deja n curs de prelucrare de ctre un alt fir. De exemplu, dac un fir de execuie efectueaz ordonarea datelor dintr-un tablou, nu este corect ca un alt fir, n acest timp, s modifice datele din acest tablou.

348

Programarea orientata pe obiecte n limbajul Java

Relaia productor/consumator i utilizarea metodelor wait(), notify() i notifyAll()


n aplicaiile limbajului Java, pentru sincronizarea firelor se folosete frecvent modelul productor/consumator. Considerm c un fir de execuie "produce" anumite date, pe care le "consum" alt fir. Pentru efectuarea acestor operaii folosim un monitor, care conine att datele transmise, ct i o variabil boolean, numit variabila de condiie a monitorului, care indic dac sunt disponibile date noi, puse de producator i neutilizate de consumator. Att punerea de date noi, ct i preluarea acestora se fac numai folosind metode sincronizate ale monitorului. n corpul acestor metode sincronizate, se pot folosi metodele wait(), notify() i notifyAll() ale clasei Object. Metoda
public final void wait() throws InterruptedException

i variantele ei
public final void wait(long timeout) throws InterruptedException public final void wait(long timeout, int nanos) throws InterruptedException

au ca efect trecerea firului de execuie activ din starea Running n starea Waiting (vezi schema). Metoda wait() fr argumente face aceast trecere pentru un timp nedefinit, n timp ce celelalte dou metode primesc ca argument intervalul de timp maxim pentru care se face suspendarea execuiei firului. Metodele
public final void notify() public final void notifyAll()

au ca efect trecerea firului de execuie din starea Waiting n starea Ready, astfel nct el poate fi activat de ctre dispecer n momentul n care procesorul sistemului devine disponibil. Deosebirea dintre ele este ca metoda notify() trece n starea Readyun singur fir de execuie dintre cele care se gasesc n momentul respectiv n starea Waiting provocat de acest monitor (care din ele depinde de implementare), n timp ce notifyAll() le trece n starea Ready pe toate. Clasa monitor conceput pentru asigurarea relaiei productor/consumator are urmtoarea form:
class NumeClasaMonitor { // declaraii cmpuri de date ale monitorului boolean variabilaConditie=false; [public] synchronized void puneDate(declaraii_argumente) { if(variabila_condiie) { try { wait(); // se asteapta folosirea datelor puse anterior } catch(InterruptedException e) { /* instruciuni de executat dac a aprut o excepie de ntrerupere */ } } /* punerea de date noi n cmpurile de date ale monitorului */ variabilaConditie=true; // s-au pus date noi

349

Severin Bumbaru
notify(); // se notifica punerea de noi date } // sfarsit puneDate [public] synchronized tip preiaDate(declaratii_argumente) { if(!variabilaConditie) { try { wait(); // se ateapt s se pun date noi } catch(InterruptedException e) { /* Instruciuni de executat dac a aprut o excepie de ntrerupere */ } } /* instruciuni prin care se folosesc datele din monitor i se formeaz valoarea_ntoars */ variabilaConditie=false; // datele sunt deja folosite notify(); // se notific folosirea datelor return valoarea_intoarsa; } // sfarsit preiaDate /* Alte metode ale monitorului (sincronizate sau nesincronizate) */ } // sfarsit clasa monitor

Iniial, variabila variabilaConditie a monitorului are valoarea false, ntrucat deocamdat - nu exist date noi. Dac firul de execuie productor a ajuns n starea, n care trebuie s pun n monitor date noi, el invoc metoda sincronizat puneDate, devenind astfel proprietar (owner) al monitorului. n aceast metod, se verific, n primul rnd, valoarea variabilei variabilaConditie. Dac aceast variabil are valoarea true, nseamn c n monitor exist deja date noi, nca nefolosite de consumator. n consecin, se invoc metoda wait() i firul de execuie monitor este suspendat, trecnd n starea Waiting, astfel c el nceteaz s mai fie proprietar (owner) al monitorului. Dac un alt fir (n cazul de fa consumatorul) invoc o metod sincronizat a aceluiai monitor care, la rndul ei, invoc metoda notify() sau notifyAll(), firul pus n ateptare anterior trece din starea Waiting n starea Ready i, deci, poate fi reactivat de ctre dispecer. Dac variabila variabilaConditie are valoarea false, firul productor nu mai intr n ateptare, ci execut instruciunile prin care modific datele monitorului, dup care pune variabilaConditie la valoarea true i se invoc metoda notify() pentru a notifica consumatorul c exista date noi, dup care se ncheie executarea metodei puneDate. Funcionarea firului de execuie consumator este asemntoare, dar acesta invoc metoda preiaDate. Executnd aceast metod, se verific mai nti dac variabilaConditie are valoarea false, ceeace nseamn c nu exist date noi. n aceast situaie, firul consumator intr n ateptare, pn va primi notificarea c s-au pus date noi. Dac, ns, variabilaConditie are valoarea true, se folosesc datele monitorului, dup care se pune variabilaConditie la valoarea false, pentru a permite productorului s modifice datele i se invoc metoda notify() pentru a scoate productorul din starea de ateptare. Este foarte important s avem n vedere c metoda puneDate este conceput pentru a fi invocat de firul productor, n timp ce metoda preiaDate este conceput pentru a fi invocat de ctre firul consumator. Numele folosite aici att pentru clasa monitor, ct i pentru metodele acesteia i variabila de condiie sunt convenionale i se aleg de ctre

350

Programarea orientata pe obiecte n limbajul Java programator, din care cauz au fost scrise n cele de mai sus cu rou cursiv.

Exemplul 1 n fiierul Sincro.java se d un exemplu de aplicaie n care se sincronizeaza dou fire de execuie folosind modelul productor/consumator. Pentru a uura citirea programului, clasele au fost denumite chiar Producator, Consumator i Monitor, dar se puteau alege, evident, orice alte nume. Firul de execuie prod, care este instana clasei Producator, parcurge un numr de cicluri impus (nrCicluri), iar la fiecare parcurgere genereaza un tablou de numere aleatoare, pe care l depune n monitor. Firul de execuie cons, care este instan a clasei Consumator, parcurge acelai numr de cicluri, n care folosete tablourile generate de firul prod. Transmiterea datelor se face prin intermediul monitorului monit, care este instan a clasei Monitor. Aceast clas conine tabloul de numere ntregi tab i variabila de condiie valoriNoi, care are iniial valoarea false, dar primete valoarea true atunci cnd productorul a pus n monitor date noi i primete valoarea false, atunci cnd aceste date au fost folosite de consumator. Pentru punerea de date noi n monitor, productorul invoc metoda sincronizat puneTablou. Pentru a folosi datele din monitor, consumatorul invoc metoda sincronizat preiaTablou. Fiecare din aceste metode testeaz valoarea variabilei de condiie valoriNoi i pune firul de execuie curent n ateptare, dac valoarea acestei variabile nu este corespunztoare. Dup ce s-a efectuat operaia de punere/utilizare a datelor, metoda sincronizat prin care s-a fcut aceast operaie invoc metoda notify(). Dac ar fi putut exista mai multe fire n starea Waiting, era preferabil sa se invoce metoda notifyAll().
class Sincro { Producator prod; Consumator cons; Monitor monit; int nrCicluri; /* Clasa Producator. Producatorul genereaza un tablou de date si il pune in monitor pentru a fi transmis consumatorului */ class Producator extends Thread { public void run() { System.out.println("Incepe executarea firului producator"); for (int i=0; i<nrCicluri; i++) { int n=((int)(5*Math.random()))+2; int tab[]=new int[n]; for(int j=0; j<n; j++) tab[j]=(int)(1000*Math.random()); monit.puneTablou(tab); System.out.print("Ciclul i="+i+" S-a pus tabloul: "); for(int j=0; j<n; j++) System.out.print(tab[j]+" "); System.out.println(); } System.out.println("Sfarsitul executiei firului Producator"); } } /* Sfarsitul clasei Producator */ /* Clasa Consumator. Consumatorul foloseste (in cazul de fata doar afiseaza) datele preluate din monitor

351

Severin Bumbaru

*/ class Consumator extends Thread { public void run() { System.out.println("Incepe executarea firului Consumator"); int tab[]; for(int i=0; i<nrCicluri; i++) { tab=monit.preiaTablou(); System.out.print("Ciclul i="+i+ " s-a preluat tabloul "); for(int j=0; j<tab.length; j++) System.out.print(tab[j]+" "); System.out.println(); } System.out.println("Sfarsitul executiei firului Consumator"); } } /* Sfarsitul clasei Consumator */ /* Clasa Monitor. Monitorul contine date si metode folosite in comun de Producator si Consumator. In acest scop, producatorul si consumatorul folosesc metodele sincronizate ale monitorului */ class Monitor { int tab[]; // tabloul de date care se transmit boolean valoriNoi=false; // variabila de conditie a monitorului /* Metoda prin care producatorul pune date in monitor */ public synchronized void puneTablou(int tab[]) { if(valoriNoi) { try { wait(); // se asteapta sa fie folosite datele puse anterior } catch(InterruptedException e) {} } this.tab=tab; // se modifica tabloul tab din monitor valoriNoi=true; // monitorul contine date noi notify(); // se notifica consumatorul ca s-au pus date noi } /* Metoda prin care consumatorul preia datele din monitor */ public synchronized int[] preiaTablou() { if(!valoriNoi) { try { wait(); // se asteapta sa se puna date noi } catch(InterruptedException e) {} } valoriNoi=false; // datele puse anterior au fost folosite notify(); // se notifica producatorul ca datele au fost preluate return tab; } } /* Sfarsitul clasei Monitor */ public Sincro(int numarCicluri) { nrCicluri=numarCicluri; prod=new Producator(); cons=new Consumator(); monit=new Monitor(); prod.start(); cons.start();

352

Programarea orientata pe obiecte n limbajul Java

} public static void main(String args[]) { int numarCicluri=8; System.out.println("Incepe executarea metodei main()"); Sincro sinc=new Sincro(numarCicluri); System.out.println("Sfarsitul metodei main()"); } }

Referitor la acest program, remarcm urmatoarele: - instruciunile care constituie subiectul acestei lecii au fost puse n eviden prin ngrosare; - metodele run() din clasele Productor i Consumator sunt scrise ca i cnd ele s-ar executa n mod independent, ns sincronizarea firelor se face prin invocarea metodelor sincronizate puneTablou i preiaTablou ale clasei Monitor; n aceste metode, sincronizarea se face folosind variabila de condiie boolean dateNoi i invocnd n mod corespunztor metodele wait() i notify(). Iat un exemplu de executare a acestei aplicaii:

Incepe executarea metodei main() Sfarsitul metodei main() Incepe executarea firului producator Ciclul i=0 S-a pus tabloul: 827 789 Incepe executarea firului Consumator Ciclul i=1 S-a pus tabloul: 464 312 Ciclul i=0 s-a preluat tabloul 827 789 Ciclul i=2 S-a pus tabloul: 455 995 271 40 583 Ciclul i=1 s-a preluat tabloul 464 312 Ciclul i=3 S-a pus tabloul: 581 193 9 635 Ciclul i=2 s-a preluat tabloul 455 995 271 40 583 Ciclul i=4 S-a pus tabloul: 621 164 215 Ciclul i=3 s-a preluat tabloul 581 193 9 635 Ciclul i=5 S-a pus tabloul: 554 626 791 444 Ciclul i=4 s-a preluat tabloul 621 164 215 Ciclul i=6 S-a pus tabloul: 204 961 Ciclul i=5 s-a preluat tabloul 554 626 791 444 Ciclul i=7 S-a pus tabloul: 476 692 Sfarsitul executiei firului producator Ciclul i=6 s-a preluat tabloul 204 961 Ciclul i=7 s-a preluat tabloul 476 692 Sfarsitul executiei firului Consumator

Se observ c, dei cele dou fire se deruleaz n mod autonom, exista ntre ele o sincronizare corect, n sensul c datele puse de productor la un ciclu cu un anumit indice, sunt preluate de consumator la ciclul cu acelai indice (de exemplu datele puse de producator n ciclul 3 sunt luate de consumator tot n ciclul 3). Aa dar, nu exist date pierdute sau preluate de dou ori.

353

Severin Bumbaru Exemplul 2 n fiierul Bondari1.java se d un exemplu de aplicaie cu interfa grafic, n care exist trei fire de execuie (n afar de cel al metodei main()): dou fire din clasa Bondar, care calculeaza fiecare micrile unui "bondar", i un fir de executie din clasa Fereastr, care reprezint grafic micrile celor doi bondari. n acest caz, ambii "bondari" se mica n aceeai fereastr. Pentru c fiecare din acestea extinde cte o clasa de interfa grafic (respectiv clasele JPanel i Canvas), pentru realizarea firelor de execuie s-a folosit interfaa Runnable. Cele dou fire "bondar" (respectiv fir1 i fir2) au rolul de productor, iar firul care conine fereastra de afiare (respectiv fir3) are rolul de consumator. Rolul monitorului este ndeplinit de instana clasei CutiePotal, care nu conine dect variabila de condiie a monitorului valoareNoua i dou metode sincronizate amPus i amLuat. Avnd n vedere c exist posibilitatea ca, la un moment dat, s existe n starea Waiting mai multe fire de ateptare care trebuie reactivate, n aceste metode s-a folosit invocarea notifyAll() n loc de notify(). Dac se execut aceast aplicaie se poate vedea cum cei doi "bondari" evolueaz n mod independent n aceeai fereastr, putndu-se ajusta n mod independent perioada i amplitudinea fiecruia.

ntrebri
Nivel 1
1. Ce este un proces (n general)? 2. Cum se definete procesul n informatic? 3. Ce se nelege prin multitasking? 4. Ce sunt firele de execuie? 5. Ce se nelege prin multithreading? 6. n ce moduri se poate programa o clas de fire de execuie? 7. Ce este clasa Thread? 8. Care sunt principalele metode ale clasei Thread? 9. La ce servete metoda run() a clasei Thread? 10. n ce mod este invocat metoda run() a clasei Thread? 11. Ce este interfaa Runnable i la ce folosete? 12. n ce stare se gsete firul de execuie imediat dup ce el a fost creat? 13. n ce clas exist metodele wait(), notify() i notifyAll() i la ce folosesc ele? 14. Ce metode conine interfaa Runnable? 15. Cum se creeaza un fir de execuie folosind un obiect cu interfaa Runnable?

Nivel 2
1. Ce sunt procesele paralele? 2. Ce sunt procesele concurente? 3. n ce situaii i cum se iau n consideraie prioritile proceselor?

354

Programarea orientata pe obiecte n limbajul Java 4. Ce se nelege prin partajarea timpului? 5. Ce fire de execuie exist obligatoriu n timpul funcionrii mainii virtuale Java? 6. Ce este un demon? 7. n ce stare trece firul de execuie dup invocarea metodei start()? 8. La ce servete metoda sleep() i n ce stare trece firul de execuie la invocarea ei? 9. Prin ce metod se modific prioritatea unui fir de execuie? 10. Care este prioritatea implicit a unui fir de execuie? 11. n ce stare trece firul de execuie n timpul executrii unei operaii de intrare/ieire? 12. n ce stare trece firul de execuie dup ce a invocat metoda wait()? 13. n ce stare trece firul de execuie dup ce a expirat intervalul de "somn" dat prin metoda sleep()? 14. n ce stare trece un fir de execuie blocat dup ce s-a ncheiat operaia de intrare/ieire solicitat? 15. Cnd se ncheie executarea unui fir de execuie i n ce stare trece el n acest caz? 16. Dece este necesar sincronizarea firelor de execuie? 17. Cum se sincronizeaz firele de execuie n Java? 18. Ce este un monitor? 19. Ce este o metod sincronizat i la ce folosete? 20. n ce situaie firul de execuie devine proprietarul unui monitor? 21. Ce se ntampl n timpul ct un fir de execuie este proprietarul unui monitor? 22. Cum se realizeaz sincronizarea ntre un fir de execuie productor i unul consumator? 23. La ce servete variabila de condiie a monitorului? 24. n ce fel de metode se pot invoca metodele wait(), notify() i notifyAll()? 25. Care este efectul invocrii metodei notify()? 26. Care este efectul invocrii metodei notifyAll()?

355

Severin Bumbaru

Index de clase i de interfee


n acest index sunt cuprinse rezumate ale descrierilor de clase i interfete din Java API care sunt folosite n acest curs practic. n Java API exist mult mai multe pachete, clase i interfee dect se prezint aici. Descrierile complete ale tuturor claselor i interfetelor pot fi gsite n documentaia Java API la urmtoarele adrese: java.sun.com/j2se/1.4/docs/api/ - la firma Sun Microsystems; http://lib.cs.ugal.ro/java/jdk140/api/index.html - pe intranetul Catedrei de Calculatoare si Informatica Aplicata al Universitii "Dunrea de Jos" din Galai

Pachetul java.lang
Clase
Byte - clas acoperitoare pentru tipul byte - v.cap.4 Boolean - clas acoperitoare pentru tipul boolean v. cap.4 Character - clas acoperitoare pentru tipul char v.cap.4 Class - clasa claselor v.cap.4 Double - clas acoperitoare pentru tipul double v.cap.4 Float - clas acoperitoare pentru tipul float v. cap.4 Integer - clas acoperitoare pentru tipul int v. cap.4 Long - clas acoperitoare pentru tipul long v. cap.4 Math - clas care ofer metode pentru calcularea funciilor matematice uzuale v.cap.4 i completarea din acest index, pag. 361 Number - clas abstract, rdcina claselor acoperitoare numerice v. cap.4 Object - rdcina ierarhiei de clase Java (un obiect oarecare) v.cap.4 i completarea din acest index pag. 363 Short - clasa acoperitoare pentru tipul short v.cap.4 String - clasa irurilor de caractere nemodificabile - v.cap.4 i completarea din acest index pag. 364 StringBuffer - clasa irurilor de caractere modificabile (instana este o zon tampon care conine un ir modificabil) v. cap.4 i completarea din acest index pag. 369 System - clasa sistemului de execuie v. cap.4 Thread - clasa firelor de execuie v.cap.12 Void - clas acoperitoare pentru tipul void v.cap.4

Interfee
Cloneable - implementat de clasele pentru care se poate folosi metoda clone() din clasa Object. Nu contine metode. Comparable - implementat de clasele ale cror instane sunt comparabile ntre ele (formeaz o mulime ordonat). v. specificatia de la pag. 372 Runnable - implementat de clasele, ale cror instane pot fi rulate ca fire de execuie. v.cap.12.

Pachetul java.io
Conine clase i interfee necesare pentru operaiile de intrare/ieire (input/output - io).

356

Programarea orientata pe obiecte n limbajul Java

Clase
(ierarhiile de clase de intrare/ieire sunt prezentate n cap.11, seciunea pachetul java.io din acest manual) BufferedInputStream - clasa fluxurilor de intrare de octei, cu zon tampon v. cap.11 si completarea de la pag.373 BufferedOutputStream - clasa fluxurilor de ieire de octei, cu zon tampon v.cap.11 i completarea de la pag. 373. BufferedReader - clasa fluxurilor de intrare de caractere, cu zon tampon v.cap.11 i completarea de la pag. 374. BufferedWriter - clasa fluxurilor de ieire de caractere, cu zon tampon v.cap.11 i completarea de la pag. 374. ByteArrayInputStream - clasa fluxurilor care citesc dintr-un tablou de octei situat n memoria intern + v.cap.11 i completarea de la pag. 374. ByteArrayOutputStream - clasa fluxurilor care scriu ntr-un tablou de octei situat n memoria intern + v.cap.11 i completarea de la pag. 374. CharArrayReader - clasa fluxurilor care citesc dintr-un tablou de caractere situat n memoria intern v. cap.11 i pag. 376. CharArrayWriter - clasa fluxurilor care scriu ntr-un tablou de caractere situat n memoria intern v. cap.11 i pag.376 DataInputStream - clasa fluxurilor de octei de intrare pentru date - v. cap.11 DataOutputStream - clasa fluxurilor de octei de ieire de date v. cap.11 File - clas ale crei instane conin informaii despre fiiere v. cap.11 FileDescriptor - clasa descriptorilor de fiiere v. cap.11 i pag.377 FileInputStream - clasa fluxurilor de octei de intrare din fiiere (clasa fiierelor deschise pentru intrare) v. cap.11 FileOutputStream - clasa fluxurilor de octei de ieire n fiiere (clasa fiierelor deschise pentru ieire) v. cap.11. FileReader - clasa fluxurilor de caractere de citire din fiiere v. cap.11 FileWriter - clasa fluxurilor de caractere de scriere n fiiere v. cap.11 FilterInputStream - clasa fluxurilor de intrare de octei cu filtru v. cap.11 i pag. 377. FilterOutputStream - clasa fluxurilor de ieire de octei cu filtru v.cap.11 i pag. 378. FilterReader - clasa flucurilor de intrare de caractere cu filtru v. cap.11 i pag. 378. FilterWriter - clasa flucurilor de ieire de caractere cu filtru v. cap.11 i pag.378. InputStream - clasa fluxurilor de intrare de octei v. cap.11 ObjectInputStream - clasa fluxurilor de intrare de obiecte v. cap.11 ObjectOutputStream - clasa fluxurilor de ieire de obiecte v. cap.11 OutputStream - clasa fluxurilor de ieire de octei v. cap.11 PrintStream - clasa fluxurilor de imprimare de octei v. cap.11 PrintWriter - clasa fluxurilor de imprimare de caractere v. cap.11 RandomAccessFile - clasa fiierelor cu acces direct (acces aleator). v. cap.11 Reader - clasa fluxurilor de intrare de caractere v. cap.11 Writer - clasa fluxurilor de ieire de caractere v. cap.11

Interfee
Serializable - interfa pe care trebuie s o aib obiectele serializabile (care pot fi scrise cu ObjectOutputStream i citite cu ObjectInputStream) v. cap.11

357

Severin Bumbaru

Pachetul java.util
Clase
EventObject - clasa obiectelor care conin informaii despre evenimente v. cap. 7 i pag. 379

Interfee
EventListener - interfa generic pentru asculttoarele de evenimente. v. cap.7 i pag. 379

Pachetul java.awt
Clase
AWTEvent - superclasa asculttoarelor de evenimente generate de componentele interfeei grafice v. cap.7 i pag. 380. BorderLayout - gestionar de poziionare v. cap.7 i pag. 381. Button - clasa butoanelor simple v. cap.8 i pag. 382. Canvas - clas special de componente pe care se traseaz desene - v. cap.9 i pag. 383 CardLayout - gestionar de poziionare v. cap. 7 i pag. 383 Color - clasa culorilor v. cap.9 i pag. 384 Component - superclasa tuturor claselor de componente ale interfeei grafice. v. cap.7 i pag. 387 Container - clasa containerelor (componente care conin alte componente) v. cap.7 i pag. 393. Dialog - clasa ferestrelor de dialog + v. cap.9 i pag. 394. Dimension - dimensiunile unei componente v. cap.9 i pag. 396. Event - clasa evenimentelor din JDK1.0 (nlocuit acum prin clasa AWTEvent) v. cap.7 i pag. 396. FlowLayout - gestionar de poziionare v. cap.7 i pag. 397. Font - clasa fonturilor v. cap.9 i pag. 398. Frame - clasa ferestrelor principale ale aplicaiilor. v. cap.7 i pag. 399. Graphics - clasa contextelor grafice simple v. cap.9 Graphics2D - clasa contextelor grafice 2D v. cap.9 i pag. 401. GridBagLayout - gestionar de poziionare v. cap.7 i pag. 401. GridLayout - gestionar de poziionare v. cap.7 i pag. 401. Insets - clasa inseriilor (marginilor libere ale containerelor) + v. pag. 402. Panel - clasa panourilor v. cap.7 i pag. 402. Point - clasa punctelor v. pag. 403. Rectangle - clasa dreptunghiurilor v. pag. 404. Window - clasa ferestrelor. + v. cap.7 i pag. 405.

Interfee
LayoutManager - interfa pentru clsasele de gestionare a poziionrii v. cap.7 i pag. 406 LayoutManager2 - interfa pentru clasele de gestionare a poziionrii cu restricii v. cap.7 i pag. 407.

358

Programarea orientata pe obiecte n limbajul Java

Pachetul java.awt.event
Clase
ActionEvent - eveniment de aciune v. cap.8 i pag. 408. AdjustementEvent - eveniment de ajustare v. cap.8 i pag. 408. ComponentAdapter - adaptor pentru asculttoarele de evenimente de component.- v.cap.8 i pag. 409. ComponentEvent - eveniment de component v.cap.8 i pag. 409. InputEvent - clas abstract. Rdcina ierarhiei claselor de evenimente de intrare v.cap.7 i pag.410. ItemEvent - eveniment de articol (selectare sau deselectare) v.cap.8 i pag.411. KeyAdapter - adaptor pentru ascultarea evenimentelor de tast v.cap.7 i pag.411. KeyEvent - eveniment de tast v.cap.7 i pag.412. MouseAdapter - adaptor pentru ascultarea evenimentelor de mouse v.cap.7 i pag.416. MouseEvent - eveniment de mouse v.cap.7 i pag.416. MouseMotionAdapter - adaptor pentru ascultarea evenimentelor de micare a mouse-ului v.cap.7 i pag.417. TextEvent - eveniment de text - v.cap.8 i pag.417. WindowAdapter - adaptor pentru ascultarea evenimentelor de fereastr v.cap.7 i pag.418. WindowEvent - eveniment de fereastr - v. cap.7 i pag.418.

Interfee
ActionListener - interfa pentru asculttoarele de evenimente de aciune v.cap.8 i pag.419 AdjustmentListener - interfa pentru asculttoarele de evenimente de ajustare v.cap.8 i pag.420. ComponentListener - interfa pentru asculttoarele de evenimente de component v.cap.8 i pag.420. ItemListener - interfa pentru asculttoarele de evenimente de articol v.cap.8 i pag.421. KeyListener - interfa pentru asculttoare de evenimente de tast v.cap.7 i pag.421. MouseListener - interfa pentru asculttoare de evenimente de mouse v.cap.7 i pag.421. MouseMotionListener - interfa penteru asculttoare de evenimente de micare a mouseului v.cap.7 i pag.422. TextListener - interfa pentru asculttoare de evenimente de text v.cap.8 i pag.422. WindowListener - interfa pentru asculttoare de evenimente de fereastr v.cap.7 i pag.423

Pachetul javax.swing
Clase
AbstractButton - clas abstract. Superclasa claselor de butoane v.cap.8 i pag. 423. BorderFactory - clas care permite producerea de borduri pentru componentele Swing v. cap.8. Box - container sub form de caset v. cap.8. Box.Filler - clasa componentelor invizibile, folosite pentru distanare n instanele clasei Box + v. cap.8 i pag.425. BoxLayout - gestionar de poziionare n caset v. cap.7.

359

Severin Bumbaru ButtonGroup - clasa grupurilor de butoane v.cap.8 i pag.426. JApplet - clasa applet-urilor din Swing v.cap.10 i pag. 426. JButton - clasa butoanelor cap.8 i pag.427. JCheckBox - clasa casetelor de validare v. cap.8. JCheckBoxMenuItem - clasa articolelor de meniu cu caset de validare v. cap.8 i pag.427. JColorChooser - clasa selectorului de culori + v.cap.9. JComboBox - clasa listelor ascunse v. cap.8. JComponent - rdcina ierarhiei de clase de componente Swing v.cap.8 i pag.428. JDialog - clasa ferestrelor de dialog v.cap.9 i pag.430. JEditorPane - clas pentru editoare de text formatat v.cap.8 i pag.432. JFileChooser - clasa selectoarelor de fiiere v.cap.8 i pag.432. JFrame - clas folosit n special pentru ferestrele principale ale aplicaiilor v.cap.7 i pag.433. JLabel - clasa etichetelor (componente de afiare needitabile) + v.cap.8 i pag.435. JList - clasa listelor afiabile n interfaa grafic v. cap.8. JMenu - clasa meniurilor v. cap.8 i pag.436. JMenuBar - clasa barelor de menu v. cap.8 i pag.437. JMenuItem - clasa articolelor de meniu v. cap.8 i pag.438. JOptionPane - clas cu metode pentru realizarea unor ferestre de dialog standard v. cap.9 i pag.439. JPanel - clasa panourilor (containere simple) v.cap.7 i pag.441. JPasswordField - clasa cmpurilor pentru introducerea parolei v. cap.8 i pag.441. JPopupMenu - clasa meniurilor volante (meniuri pop-up) v. cap.8. JProgressBar - clasa barelor de progres v. cap.8 i pag.442. JRadioButton - clasa butoanelor radio v. cap.8. JRadioButtonMenuItem - clasa articolelor de meniu cu buton radio v. cap.8 i pag.443. JScrollBar - clasa barelor de defilare v. cap.8 i pag. 444. JScrollPane - clasa panourilor cu bare de defilare v. cap.7 i pag.445. JSeparator - clasa separatoarelor de meniu v. cap.8 i pag.446. JSlider - clasa riglelor cu cursor v. cap.8. JSplitPane - clasa panourilor care pot fi scindate - v. cap.7 i pag.447. JTabbedPane - clasa panourilor tabulate v. cap.8 i pag.448. JTable - clasa tabelelor v. cap.8 i pag. 450. JTextArea - clasa ariilor de text v. cap.8. JTextField - clasa cmpurilor de text v. cap.8. JTextPane - clas pentru editoare de text stilizat v. cap.8 i pag.450. JToggleButton - superclasa butoanelor cu dou stri stabile v. cap.8 i pag.451 JWindow - clasa ferestrelor v. cap.7 i pag. 451.

Pachetul javax.swing.event
Clase
ChangeEvent - eveniment de schimbare a strii sursei v. cap.7 i pag.452. ListDataEvent - eveniment de modificare a datelor dintr-o list v.cap.8 i pag.452. ListSelectionEvent - clasa evenimentelor de selectare a articolelor de list v.cap.8 i pag.453 MenuEvent - clasa evenimentelor de meniu v. cap.8 i pag.453. MouseInputAdapter - adaptor pentru asculttoarele de evenimente de mouse v. cap.7 i

360

Programarea orientata pe obiecte n limbajul Java pag.454. PopupMenuEvent - clasa evenimentelor generate de meniuri pop-up v.cap.8 i pag.454.

Interfee
ChangeListener - asculttor de evenimente de schimbare a strii v.cap.7 i pag.454. ListDataListener - asculttor de evenimente de modificare a coninutului unei liste v.cap.8 i pag.455. ListSelectionListener - asculttor de evenimente de modificare a articolelor selectate dintr-o list v. cap.8 i pag.455. MenuListener - asculttor al evenimentelor de meniu v. cap.8 i pag.455. MouseInputListener - asculttor de mouse - v. cap.7 i pag.456. PopupMenuListener - asculttor al evenimentelor de meniu pop-up v. cap.8 i pag.456.

361

Severin Bumbaru Completri la descrierea claselor i interfeelor

Clasa Math
public final class Math extends Object

Clasa Math contine metode statice pentru calcularea unor functii matematice uzuale, cum sunt functiile trigonometrice, radacina patrata si altele. Campuri:
public static final double E public static final double PI

- numarul e (baza logaritmilor naturali); - numarul pi (raportul dintre circumferinta cercului si

diametru). Metode:
public static double sin(double a)- intoarce sinusul

trigonometric sin a, unde unghiul

a este in radiani.
public static double cos(double a)- intoarce cosinusul

trigonometric cos a, unde

unghiul a este in radiani;


public static double tan(double a)- intoarce tangenta trigonometrica

tg a, unde

unghiul a este in radiani;


public static double asin(double a)- intoarce arcsin public static double acos(double a)- intoarce arccos public static double atan(double a)- intoarce arctg

a in intervalul [-pi/2, pi/2]; a in intervalul [0.0, pi];

a in intervalul [-pi/2, pi/2]; argumentul angDeg din

public static double toRadians(double angdeg)- converteste

grade in radiani;
public static double toDegrees(double angrad)- converteste

argumentul angrad din

radiani in grade;
public static double exp(double a)- calculeaza functia

exponentiala ea; natural ln a;

public static double log(double a)- calculeaza logaritmul public static double sqrt(double a)- calculeaza radacina

patrata a argumentului a.

Daca argumentul este negativ sau NaN, rezultatul este NaN.


public static double IEEEremainder(double f1, double f2)- calculeaza restul impartirii f1/f2 conform prescriptiilor standardului IEEE 754. Restul este egal matematic cu

362

Programarea orientata pe obiecte n limbajul Java valoarea expresiei f1-f2*n, unde n este numarul intreg cel mai apropiat de valoarea exacta a raportului f1/f2. Daca restul este zero, el are semnul primului argument.
public static double ceil(double a)- intoarce,

sub forma de valoare double, cel mai mic numar intreg care nu este mai mic decat argumentul (rotunjire prin adaos);
public static double floor(double a)- intoarce,

sub forma de valoare double, cel mai mare numar intreg care nu este mai mare decat argumentul (rotunjire prin micsorare);
public static double rint(double a)- intoarce,

sub forma de valoare double, numarul

intreg cel mai apropiat de argument;


public static double atan2(double a, double b)- calculeaza arctg(a/b) in

intervalul [-pi, pi] tinand seama de semnele argumentelor a si b (se considera ca se calculeaza argumentul theta la conversia din coordonate carteziene (b, a) in coordonate polare (r, theta)).
public static double pow(double a, double b)- calculeaza a . Daca (a==0 sau daca (a<=0 si b nu este un numar intreg) se genereaza o exceptie aritmetica. public static int round(float a)- se intoarce numarul
b

si b<=0)

intreg cel mai apropiat de argument. Daca acest intreg este mai mic decat marginea inferioara pentru tipul int, rezultatul este Integer.MIN_VALUE. Daca acest intreg este mai mare decat marginea superioara pentru tipul int, se obtine rezultatul Integer.MAX_VALUE.
public static long round(double a)- intoarce numarul

intreg cel mai apropiat de

argument (cu aceleasi observatii ca la metoda precedenta).


public static double random()- intoarce un

numar pseudoaleator in intervalul [0.0, 1.0], avand o lege de repartitie (aproximativ) uniforma in acest interval.
public static int abs(int a)- intoarce modului

argumentului a (valoarea absoluta); argumentului a (valoarea absoluta);

public static long abs(long a)- intoarce modului public static float abs(float a)- intoarce

modulul argumentului a (valoarea

absoluta);
public static double abs(double a)- intoarce modulul

argumentului a (valoarea

absoluta);
public static int max(int a, int b)- intoarce cel public static long max(long a, long b)- intoarce

mai mare din cele doua argumente; cel mai mare din cele doua

argumente;
public static float max(float a, float b)- intoarce

cel mai mare din cele doua

argumente;

363

Severin Bumbaru
public static double max(double a, double b)- intoarce

cel mai mare din cele doua

argumente;
public static int min(int a, int b)- intoarce cel

mai mic din cele doua argumente; mai mic din cele doua

public static float min(float a, float b)intoarce cel

argumente;
public static double min(double a, double b)intoarce cel

mai mic din cele doua

argumente;

Class Object
java.lang.Object -------------------------------------------------------------------------------public class Object

Clasa Object este radacina ierarhiei de clase Java. Orice alta clasa ore clasa Object ca superclasa. Toate celelalte clase, inclusiv tablourile, implementeaza metodele acestei clase ------------------------------------------------------------------------------Constructor:
public Object()

Metode:
protected Object clone()

Creaza si intoarce o copie a acestui obiect.


public boolean equals(Object obj)

Indica daca acest obiect este sau nu "egal cu" obiectul obj primit ca argument.
protected void finalize()

Este apelata de colectorul de reziduuri atunci cand acesta constata ca nu mai exista referinte la obiectul respectiv.
public Class getClass()

Intoarce clasa caruia ii apartine obiectul.


public int hashCode()

Intoarce codul de dispersie al obiectului


public void notify()

Notifica un singur fir de executie dintre cele care asteapta acest obiect.

364

Programarea orientata pe obiecte n limbajul Java


public void notifyAll()

Notifica toate firele de executie care asteapta acest obiect


public String toString()

Intoarce reprezentarea sub forma de String a acestui obiect.


public void wait()

Pune firul de executie curent in asteptare, pana cand alt fir de executie invoca metoda notify sau notifyAll() pentru acest obiect.
public void wait(long timeout)

Pune firul de executie curent in asteptare, pana cand alt fir de executie invoca metoda notify sau notifyAll() pentru acest obiect, sau pana cand exprira intervalul de timp dat timeout dat ca argument. Timpul este exprimat in milisecunde.
public void wait(long timeout, int nanos)

Pune firul de executie curent in asteptare, pana cand alt fir de executie invoca metoda notify sau notifyAll() pentru acest obiect, sau pana cand exprira intervalul de timp dat timeout dat ca argument, sau pana cand alt fir de asteptare il intrerupe pe cel curent. Timpul de asteptare, exprimat in nanosecunde, este in acest caz 1000000*timeout+nanos, unde nanos este un intreg in intervalul 0..999999.

Clasa String
public final class String extends Object implements Serializable, Comparable

Instantele clasei String sunt siruri de caractere. Orice literal sir in limbajul Java, de exemplu "abc", este un astfel de obiect. Sirurile sunt constante, deci continutul lor nu poate fi modificat. Pentru a obtine siruri modificabile se va folosi clasa StringBuffer. Nota: amintim ca in limbajul Java reprezentarea interna a caracterelor se face pe 16 biti, in Unicode. Campuri:
public static Comparator CASE_INSENSITIVE_ORDER Campul contine un Comparator care ordoneaza obiectele-sir

cand ele sunt comparate

cu metoda comparetoIgnoreCase(). Constructori:


public String()

Creeaza un sir vid.


public String(byte[] bytes)

Creeaza un obiect al clasei String care contine caracterele din tabloul de octeti primit ca argument. Se considera ca in acest tablou caracterele sunt reprezentate pe 8 biti, in codul local valabil pe calculatorul pe care se executa programul. Daca referinta la tablou este nula se genereaza o NullPointerException. 365

Severin Bumbaru
public String(byte[] bytes, int offset, int length)

Actioneaza similar cu constructorul precedent, cu observatia ca se preiau din tabloul bytes numai length octetii de pe pozitiile care incep de la indicele offset. Pot fi generate NullPointerException daca referinta la tablou este nula, sau o IndexOutOfBoundsException daca indicii sunt gresiti.
public String(byte[] bytes, int offset, int length, String enc)

Actioneaza similar cu constructorul precedent, dar la conversia din octet in Unicode se foloseste sistemul de codificare a caracterelor enc. Pot fi generate NullPointerException daca referinta la tablou este nula, sau o IndexOutOfBoundsException daca indicii sunt gresiti,sau UnsupportedEncodingException daca argumentul enc este gresit.
public String(byte[] bytes, String enc)

Construieste un sir care contine caracterele din tabloul de octeti bytes. Se considera ca in acest tablou caracterele sunt reprezentate in codul enc. Se genereaza NullPointerException daca referinta la tablou este nula, sau UnsupportedEncodingException daca argumentul enc este gresit..
public String(char[] value)

Construieste un sir care contine caracterele din tabloul de caractere value. Se genereaza NullPointerException daca referinta la tablou este nula.Pot fi generate NullPointerException daca referinta la tablou este nula, sau o IndexOutOfBoundsException daca indicii sunt gresiti.
public String(char[] value, int offset, int count)

Actioneaza similar cu constructorul precedent, dar preia din tabloul value numai count caractere, incepand cu cel de pe pozitia offset. Pot fi generate NullPointerException daca referinta la tablou este nula, sau o IndexOutOfBoundsException daca indicii sunt gresiti.
public String(String value)

Creeaza un nou sir, in care il copiaza pe cel dat ca argument.


public String(StringBuffer buffer)

Creeaza un nou sir, care contine aceleasi caractere ca cele din argumentul buffer, care apartine clasei StringBuffer (deci este o zona-tampon pentru siruri). Metode:
public char charAt(int index)

Intoarce caracterul situat in sir pe pozitia index. Se genereaza IndexOutOfBoundsException daca indicele este gresit.
public int compareTo(Object o) Compara acest sir cu obiectul o

primit ca argument. Daca acest obiect nu este un sir, se genereaza o exceptie de incompatibilitate de clase (ClassCastException). Daca o este un sir, atunci compararea se face la fel ca in metoda urmatoare.
public int compareTo(String anotherString) Compara acest sir cu sirul anotherString primit

ca argument. Daca cele doua siruri sunt identice, intoarce 0 (zero). Daca acest sir il precede pe o intoarce o valoare negativa, iar

366

Programarea orientata pe obiecte n limbajul Java daca ii succede lui o intoarce o valoare pozitiva. Compararea sirurilor se face in ordine lexicografica (in ordinea in care ar fi plasate intr-un dictionar).
public int compareToIgnoreCase(String str) Compara lexicografic acest sir cu sirul str primit

ca argument, ignorand deosebirea

dintre literele majuscule si cele minuscule.


public String concat(String str)

Concateneaza acest sir cu sirul str primit ca argument.


public static String copyValueOf(char[] data)

Intoarce un sir care contine aceleasi caractere cu cele din tabloul data. Se poate genera NullPointerException daca referinta la tablou este nula.
public static String copyValueOf(char[] data, int offset, int count) Similar cu metoda precedenta, dar se preiau din tabloul data numai count caractere incepand cu pozitia offset. Se poate genera NullPointerException daca referinta la tablou

este nula
public boolean endsWith(String suffix)

Testeaza daca acest sir se termina cu subsirul suffix.


public boolean equals(Object anObject)

Testeaza daca acest sir este "egal" cu obiectul anObject.


public boolean equalsIgnoreCase(String anotherString)

Testeaza daca acest sir contine aceleasi caractere ca argumentul anotherString, ignorand deosebirea dintre literele mici si cele mari.
public byte[] getBytes()

Converteste acest sir intr-un tablou de octeti, luind in consideratie codificarea locala de pe calculatorul pe care ruleaza programul.
public byte[] getBytes(String enc)

Similara cu metoda precedenta, dar conversia se face folosind codificarea enc. Se genereaza UnsupportedEncodingException daca argumentul enc este gresit.
public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin) Copiaza caracterele din acest sir in tabloul de caractere de destinatie char[]. Copierea incepe de la caracterul de pe pozitia srcBegin si se termina la caracterul de pe pozitia srcEnd-1. Plasarea in tabloul de destinatie incepe cu pozitia dstBegin. Se poate genera

NullPointerException daca referinta la tablou este nula sau IndexOutOfBoundsException daca indicii sunt gresiti..
public int hashCode()

Intoarce codul de dispersie pentru acest sir.


public int indexOf(int ch)

Intoarce indicele la care se gaseste in sir prima aparitie a caracterului ch. Daca acest caracter nu exista in sir, intoarce -1.

367

Severin Bumbaru
public int indexOf(int ch, int fromIndex)

Similar cu metoda precedenta, dar cautarea in sir incepe de la pozitia fromIndex.


public int indexOf(String str)

Intoarce indicele pozitiei de pe care in acest sir apare prima data subsirul str.
public int indexOf(String str, int fromIndex)

Similar cu metoda precedenta, dar cautarea in acest sir incepe de la pozitia fromIndex.
public String intern()

Intoarce o reprezentare canonica a acestui obiect-sir.


public int lastIndexOf(int ch)

Intoarce indicele ultimei pozitii pe care apare caracterul ch in acest sir.


public int lastIndexOf(int ch, int fromIndex)

Intoarce indicele ultimei pozitii pe care se gaseste caracterul ch daca se face cautarea inapoi incepand de la pozitia fromIndex.
public int lastIndexOf(String str)

Intoarce indicele ultimei aparitii in acest sir a subsirului str.


public int lastIndexOf(String str, int fromIndex)

Similar cu metoda precedenta, dar cautarea inapoi se face de la pozitia fromIndex.


publicint length()

Intoarce lungimea acestui sir (numarul de caractere continute).


public boolean regionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int len) Testeaza daca o regiune din acest sir este egala cu o regiune din sirul other primit ca argument. Daca primul argument (ignoreCase) are valoarea true, comparatia se face ignorand deosebirea dintre caracterele mari si cele mici. Argumentele tooffset si ooffset

reprezinta indicii pozitiilor de la care incep regiunile comparate in acest sir si, respectiv, in sirul-argument other. Argumentul len este lungimea celor doua zone comparate.
public boolean regionMatches(int toffset, String other, int ooffset, int len)

Similar cu metoda precedenta, dar se ia in consideratie deosebirea intre literele mici si cele mari.
public String replace(char oldChar, char newChar)

Intoarce un nou sir, care are acelasi continut cu acest sir, dar in care toate aparitiile caracterului oldChar sunt inlocuite prin caracterul newChar.
public boolean startsWith(String prefix) Testeaza daca acest sir incepe cu subsirul prefix. public boolean startsWith(String prefix, int toffset) Testeaza daca subsirul prefix incepe in acest sir de pe pozitia index.

368

Programarea orientata pe obiecte n limbajul Java


public String substring(int beginIndex)

Intoarce un nou sir, care contine caracterele acestui sir incepand de la pozitia beginIndex, pana la sfarsit.
public String substring(int beginIndex, int endIndex) Intoarce subsirul situat intre pozitiile beginIndex si endIndex-1. public char[] toCharArray()

Converteste acest sir intr-un tablou de caractere.


public String toLowerCase()

Intoarce un nou sir, in care literele mari ale acestui sir sunt inlocuite cu litere mici.
public String toLowerCase(Locale locale)

Similar cu metoda precedenta, dar inlocuirea literelor mari cu cele mici se face respectand conventia locale.
public String toString()

Intoarce chiar acest sir.


public String toUpperCase()

Intoarce un nou sir, provenit din acest sir, in care toate literele mici au fost inlocuite cu litere mari.
public String toUpperCase(Locale locale)

Similar cu metoda precedenta, dar conversia se face respectand conventia locale.


public String trim()

Intoarce un nou sir, obtinut din acest sir prin eliminarea spatiilor de la inceput si de la sfarsit.
public static String valueOf(boolean b)

Intoarce reprezentarea sub forma de sir a unui argument de tip boolean.


public static String valueOf(char c)

Intoarce un sir care contine numai caracterul c.


public static String valueOf(char[] data)

Intoarce reprezentarea sub forma de sir a tabloului de caractere data. Se genereaza NullPointerException daca referinta la tablou este nula.
public static String valueOf(char[] data, int offset, int count) Intoarce reprezentarea sub forma de sir a subtabloului de lungime count cuprins tabloul data incepand de la indicele offset. Se genereaza NullPointerException daca

in

referinta la tablou este nula.


public static String valueOf(double d)

Intoarce reprezentarea sub forma de sir a unui argument de tip double.


public static String valueOf(float f)

Intoarce reprezentarea ca sir a unui argument de tip float.

369

Severin Bumbaru
public static String valueOf(int i)

Intoarce reprezentarea ca sir a unui argument de tip int.


public static String valueOf(long l)

Intoarce reprezentarea ca sir a unui argument de tip long.


public static String valueOf(Object obj) Intoarce reprezentarea ca sir a obiectului obj.

Metode mostenite de la clasa java.lang.Object:


clone, finalize, getClass, notify, notifyAll, wait

Clasa StringBuffer
public final class StringBuffer extends Object implements Serializable

Un StringBuffer implementeaza un sir de caractere care poate fi modificat. El reprezinta o zona tampon din memorie, in care se ppoate plasa un sir de caractere. Operatiile principale asupra unui StringBuffer sunt metodele append si insert. Fiecare din ele converteste o data intr-un String, pe care apoi il adauga la sirul din StringBuffer sau il insereaza in acesta pe o pozitie data. Fiecare StringBuffer are o capacitate si o lungime. Lungimea este numarul efectiv de caractere continute, iar capacitatea este numarul maxim de caractere care incap in zona tampon rezervata in memorie. Daca, printr-o noua adaugare de caractere, lungimea depaseste capacitatea, atunci capacitatea se mareste in mod automat.

Constructori:
public StringBuffer()

- construieste un StringBuffer vid cu capacitatea 16 caractere. lungime length.

public StringBuffer(int length)- construieste un StringBuffer vid de Daca length este negativ, se genereaza o NegativeArraySizeException. public StringBuffer(String str)- construieste iar capacitatea este lungimea lui str plus 16.

un StringBuffer care contine sirul str,

Metode:
public int length()-

intoarce lungimea sirului continut in StringBuffer (numarul de

caractere).
public int capacity()- intoarce

capacitatea curenta a zonei tampon. 370

Programarea orientata pe obiecte n limbajul Java


public void ensureCapacity(int minimumCapacity)- asigura capacitatea minima a zonei tampon. Daca capacitatea curenta este mai mica decat minimumCapacity, se aloca in

memorie o noua zona tampon si se transfera in ea sirul curent. Capacitatea noului StringBuffer este cea mai mare dintre valoarea argumentului minimumCapacity si dublul vechii capacitati.
public void setLength(int newLength)- seteaza noua lungime a acestui StringBuffer. Daca noua lungime newLength este mai mica decat cea existenta, sirul este trunchiat. Daca newLength este mai mare decat cea curenta, se adauga un numar suficient de caractere nule

(\0000) pentru a se obtine noua lungime. Daca argumentul newLength este negativ se genereaza o exceptie IndexOutOfBoundsException.
public char charAt(int index)- intoarce

caracterul de pe pozitia de indice index. Daca indicele nu se incadreaza in lungimea sirului curent, se genereaza o IndexOutOfBoundsException.
public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)

Caracterele situate in StringBuffer intre pozitiile srcBegin si srcEnd-1 sunt copiate in tabloul de caractere dst incepand de la pozitia dstBegin. Daca dst este null se genereaza o NullPointerException. Daca srcBegin, srcEnd sau dstBegin nu sunt corecte, se genereaza o IndexOutOfBondsException.
public void setCharAt(int index, char ch)- se pune caracterul ch Daca index este incorect, se genereaza o IndexOutOfBoundsException. public StringBuffer append(Object obj)- se adauga obiectul obj public StringBuffer append(String str)- se adauga sirul str. public StringBuffer append(char[] str)- se adauga toate caracterele tabloul str.

pe pozitia index.

convertit in sir.

continute in

public StringBuffer append(char[] str, int offset, int len)- se adauga la acest StringBuffer len caractere din tabloul str, incepand de la pozitia offset din acest tablou. public StringBuffer append(boolean b)- se

adauga valoarea booleana b convertita in

sir.
public StringBuffer append(char c)- se adauga

caracterul c. convertit in sir. intreg llung l convertit in sir. real f convertit in sir. real d convertit in sir.

public StringBuffer append(int i)- se adauga intregul i public StringBuffer append(long l)- se adauga numarul

public StringBuffer append(float f)- se adauga numarul

public StringBuffer append(double d)- se adauga numarul

371

Severin Bumbaru
public StringBuffer delete(int start, int end)- se elimina caracterele de pe pozitiile de la indicele start pana la end-1. Daca start este negativ, mai mare ca lungimea sau mai mare ca end se genereaza o StringIndexOutOfBoundsException. public StringBuffer deleteCharAt(int index)- se elimina caracterul index sau se genereaza o StringIndexOutOfBoundsException.

de pe pozitia

public StringBuffer replace(int start, int end, String str)- caracterele situate in StringBuffer pe pozitiile de la start la end-1 se inlocuiesc prin subsirul str. Daca indicii start sau end nu sunt corecti se genereaza o StringIndexOutOfBoundsException. public String substring(int start)- intoarce subsirul sau genereaza o StringIndexOutOfBoundsException.

care incepe de la pozitia start

public String substring(int start, int end)- intoarce subsirul pozitia end-1 sau genereaza o StringIndexOutOfBoundsException. public StringBuffer insert(int index, char[] str, int offset, int len)

de la pozitia start la

Incepand de la pozitia index insereaza in StringBuffer len caractere situate in tabloul str de la pozitia offset sau se genereaza o StringIndexOutOfBoundsException.
public StringBuffer insert(int offset, Object obj)- insereaza incepand

de la pozitia offset obiectul obj reprezentat ca sir. Daca offset nu este corect se genereaza o StringingIndexOutOfBoundsException.
public StringBuffer insert(int offset, String str)- se insereaza incepand pozitia offset sirul str. Daca offset este incorect se genereaza o StringIndexOutOfBoundsException.

de la

public StringBuffer insert(int offset, char[] str)- incepand de la pozitia offset se insereaza caracterele din tabloul str. Daca offset este incorect se genereaza o StringIndexOutOfBoundsException. public StringBuffer insert(int offset, boolean b)- se insereaza incepand pozitia offset valoarea booleana b convertita in sir, sau se genereaza o StringIndexOutOfBoundsException. public StringBuffer insert(int offset, char c)- pe pozitia offset caracterul c sau se genereaza o StringIndexOutOfBoundsException. public StringBuffer insert(int offset, int i)- incepand insereaza numarul intreg i convertit in sir sau se genereaza o StringIndexOutOfBoundsException.

de la

se insereaza

de la pozitia offset se

public StringBuffer insert(int offset, long l)- incepand

de la pozitia offset se

insereaza numarul intreg lung l convertit in sir, sau se genereaza o StringIndexOutOfBoundsException. 372

Programarea orientata pe obiecte n limbajul Java


public StringBuffer insert(int offset, float f)- incepand

de la pozitia offset se

insereaza numarul real f convertit in sir sau se genereaza o StringIndexOutOfBoundsException.


public StringBuffer insert(int offset, double d)- incepand

de la pozitia offset se

insereaza numarul real f convertit in sir sau se genereaza o StringIndexOutOfBoundsException.


public StringBuffer reverse()- se pun

caracterele din StringBuffer in ordine inversa

celei actuale.
public String toString()- intoarce un String StringBuffer.

care are acelasi continut cu acest

-------------------------------------------------------------------------------Metode mostenite de la clasa Object:


clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait

Interfaa Comparable
java.lang.Comparable

Interfaa este implementat de clasele ale cror instane pot fi comparate ntre ele, deci fac parte dintr-o mulime ordonat. Interfaa conine o singur metod: - compar obiectul de care aparine cu obiectul obj primit ca argument. Valoarea ntoars este: 0 (zero) - dac cele dou obiecte sunt egale; valoare negativ, dac obiectul propriu l precede pe obj; valoare pozitiv, dac obiectul propriu este succesor al lui obj.
public int compareTo(Object obj)

Fie a i b dou obiecte, aparinnd unei clase cu interfaa Comparable. n acest caz: a.compareTo(b)<0 dac a<b (a precede lui b); a.compareTo(b)==0 dac a==b; a.compareTo(b)>0 dac a>b (a succede lui b).

Clasa BufferedInputStream
Face parte din pachetul java.IO i extinde clasa FilterInputStream. Instanele acestei clase sunt fluxuri de intrare de octei, care conin o zon tampon (buffer). Octeii sunt citii unul cte unul din aceast zon tampon. Cnd zona tampon se golete, ea se

373

Severin Bumbaru umple din nou, n mod automat, prin citirea din fluxul de intrare cruia acest BufferedInputStream i este ataat.

Constructori
public BufferedInputStream(InputStream in) ataat fluxului de intrare in.

- se creeaz un BufferedInputStream

public BufferedInputStream(InputStream in, int size) - se creeaz un BufferedInputStream ataat fluxului de intrare in, lungimea zonei tampon fiind de size

octei.

Metode
Aceleai ca n clasa InputStream.

Clasa BufferedOutputStream
Face parte din pachetul java.io i extinde clasa FilterOutputStream

Constructori
public BufferedOutputStream(OutputStream out) - creeaz o instana a clasei BufferedOutputStream conectat la ieire la fluxul out i coninnd o zon tampon cu

lungimea implicit de 512 octei;


public BufferedOutputStream(OutputStream out, int size) - creeaz o instana a clasei BufferedOutputStream conectat la ieire la fluxul out i coninnd o zon tampon cu lungimea de size octei;

Metode
Aceleai ca n clasa OutputStream.

Clasa BufferedReader
Face parte din pachetul java.io i extinde clasa Reader.

Constructori
- creeaz un flux de intrare de caractere, cu zon tampon de lungime implicit, conectat la ieirea fluxului de intrare de caractere in.
public BufferedReader(Reader in)

374

Programarea orientata pe obiecte n limbajul Java


public BufferedReader(Reader in, cu zon tampon de lungime sz, conectat

- creeaz un flux de intrare de caractere, la ieirea fluxului de intrare de caractere in.


int sz)

Metode
Aceleai ca n clasa Reader.

Clasa BufferedWriter
Face parte din pachetul java.io i extinde clasa Writer. Caracterele primite sunt acumulate ntr-o zon tampon i sunt transmise la ieire numai cnd aceast zon tampon s-a umplut, sau cnd se execut metoda flush().

Constructori
- creeaz un flux de ieire de caractere, cu zon tampon de lungime implicit, conectat la ieire la fluxul de caractere out.
public BufferedWriter(Writer out) public BufferedWriter(Writer out, int sz) - creeaz un flux de ieire de caractere, zon tampon de lungime sz, conectat la ieire la fluxul de caractere out.

cu

Metode
Aceleai ca n clasa Writer.

Clasa ByteArrayInputStream
Face parte din pachetul java.io i extinde clasa InputStream. Acest flux conine o zon tampon (buffer) din care se citesc datele, situat n memoria intern.

Cmpuri
protected byte[] buf - tabloul de octei din care se face citirea, situat n memoria intern. protected int pos - indicele urmtorului octet care va fi citit din tabloul de octei de intrare buf[]. protected int mark - poziia marcat din flux (este iniializat implicit la zero i poate fi modificat prin metoda mark()). protected int count - numrul de octei existeni efectiv n tabloul buf (este cel puin 0 i

cel mult egal cu lungimea tabloului)

Constructori
public ByteArrayInputStream(byte[] buf) - creeaz un citete din tabloul buf[] situat n memoria intern.

flux de intrare de octei, care

375

Severin Bumbaru
public ByteArrayInputStream(byte[] buf, int offset, int length) - creeaz un flux de intrare de octei, care citete dintr-o zon a tabloului de octei buf[] care ncepe de la poziia de indice offset a acestui tablou i are lungimea length.

Metode
Aceleai ca la clasa InputStream.

Clasa ByteArrayOutputStream
Face parte din pachetul java.io i extinde clasa OutputStream. Flux de ieire de octei, care scrie ntr-un tablou de octei situat n memoria intern. Zona tampon (tabloul) n care se scrie are capacitate variabil: capacitatea lui se marete automat dac prin o nou scriere se depete capacitatea existent. Referina la zona tampon pentru scriere se obine prin metoda toByteArray().

Cmpuri
protected byte[] buf - tabloul de octei n care se face scrierea, situat n memoria protected int count - numrul de octei valizi existeni n tabloul buf[].

intern.

Constructori
- creeaz un flux de ieire de octei care scrie ntr-o zon tampon (tablou) care are iniial capacitatea de 32 octei, dar capacitatea crete automat, dac este necesar.
public ByteArrayOutputStream()

- creeaz un flux de ieire de octei care scrie ntr-o zon tampon (tablou) care are iniial capacitatea de size octei, dar capacitatea crete automat, dac este necesar.
public ByteArrayOutputStream(int size)

Metode
Metodele sunt cele din clasa OutputStream, la care se adaug:
public void writeTo(OutputStream out) throws IOException - scrie n fluxul ieire out ntregul coninut al tabloului (yonei tampon) buf, ca i cnd s-ar fi fi fcut invocarea de metod out.write(buf, 0, cont). public byte[] toByteArray() - ntoarce un coninutul valid al yonei tampon buf.

de

nou tablou de octei, n care este copiat

public int size() - ntoarce dimensiunea curent a zonei tampon (valoarea cmpului count).

Clasa CharArrayReader

376

Programarea orientata pe obiecte n limbajul Java Face parte din pachetul java.io i extinde clasa Reader. Instanele acestei clase sunt fluxuri de intrare de carractere, care citesc dintr-un tablou de caractere situat in memoria intern.

Constructori
public CharArrayReader(char[] buf) - creeaz un flux de intrare de caractere, citete din tabloul de caractere buf[], situat ]n memoria intern.

care de

public CharArrayReader(char[] buf, int offset, int length) - creeaz un flux intrare de caractere, care citete din tabloul de caractere buf[], situat ]n memoria intern. Citirea ncepe de la poziia de indice offset, iar yona de citire are lungimea length.

Metode
Aceleai ca n clasa Reader.

Clasa CharArrayWriter
Face parte din pachetul java.io i extinde clasa Writer. Instanele sunt fluxuri de ieire de caractere, care scriu ntr-o zon tampon sub form de tablou de caractere extensibil, situat n memoria intern. Datele din zona tampon de ieire pot fi obinute prin metodele toCharArray() i toString().

Constructori
- creeaz un flux de ieire de caractere, care scrie ntr-o zon tampon situat n memoria intern, a crei lungime este dat implicit.
public CharArrayWriter()

- creeaz un flux de ieire de caractere, care scrie ntr-o zon tampon situat n memoria intern, a crei lungime este initialSize.
public CharArrayWriter(int initialSize)

Metode
Aceleai ca n clasa Writer, la care se adaug:
public void writeTo(Writer out) throws IOException n fluxul de ieire de caractere out.

- scrie datele din zona tampon

public char[] toCharArray() - ntoarce un tablou de caractere, avnd acelai coninut cu zona tampon de ieire.
public int size()

- ntoarce lungimea curent a zonei tampon. - ntoarce un ir, care are acelai coninut cu zona tampon.

public String toString()

Clasa FileDescriptor
377

Severin Bumbaru Face parte din pachetul java.io. Instanele clasei FileDescriptor servesc ca manipulatori ai unor fiiere sau socluri deja deschise. Principala utilizare este la crearea unor fluxuri din clasele FileInputStream sau FileOutputStream, conectate la fiiere deja deschise.

Cmpuri
public static final FileDescriptor in sistemului, System.in.

- descriptorul fiierului de intrare standard a - descriptorul fiierului de ieire standard a - descriptorul fiierului de ieire pentru erori

public static final FileDescriptor out sistemului, System.out public static final FileDescriptor err a sistemului, System.err

Constructori
public FileDescriptor()

- creeaz o instan a clasei Filedescriptor, care nu este valid

(nu indic nici un fiier) Observaie: pentru a obine un descriptor de fiier valid se folosete metoda public final FileDescriptor getFD()throws IOException - existent n clasele FileInputStream i FileOutputStream. Aceast metod ntoarce descriptorul fiierului respectiv.

Metode
public boolean valid()

- indic dac acest descriptor de fiier este valid (se refer la un - foreaz sincroniarea zonelor

fiier sau soclu deschis).


public void sync() throws SyncFailedException

tampon ale sistemului pentru dispozitivul corespunztor.

Clasa FilterInputStream
Face parte din pachetul java.io. Este superclasa claselor de fluxuri de intrare de octei, care realizeaz anumite operaii de filtrare (prelucrare) a datelor de intrare. De fapt, metodele acestei clase sunt cele motenite de la superclasa InputStream, deci nu fac nici o prelucrare. Aceste metode pot fi ns redefinite n subclase, pentru a realiza astfel de prelucrri. n pachetul java.io exist subclasele DataInputStream, BufferedInputStream i PushbackInputStream. Putem crea i propriile noastre subclase.

Constructor
protected FilterInputStream(InputStream in) filtru, care preia fluxul de intrare in.

- creeaz un flux de intrare de octei cu

Metode
Aceleai ca n clasa InputStream.

378

Programarea orientata pe obiecte n limbajul Java

Clasa FilterOutputStream
Face parte din pachetul java.io. Este superclasa claselor de fluxuri de ieire de octei, care realizeaz anumite operaii de filtrare (prelucrare) a datelor de ieire. De fapt, metodele acestei clase sunt cele motenite de la superclasa OutputStream, deci nu fac nici o prelucrare. Aceste metode pot fi ns redefinite n subclase, pentru a realiza astfel de prelucrri. n pachetul java.io exist subclasele DataOutputStream, BufferedOutputStream, PrintStream i altele. Putem crea i propriile noastre subclase.

Constructor
- creeaz un flux de ieire de octei cu filtru, care transmite datele la fluxul de ieire de octei out.
public FilterOutputStream(OutputStream out)

Metode
Metodele sunt aceleai ca n clasa OutputStream.

Clasa FilterReader
Face parte din pachetul java.io. Este superclasa claselor de fluxuri de intrare de caractere, care realizeaz anumite operaii de filtrare (prelucrare) a datelor de intrare. De fapt, metodele acestei clase sunt cele motenite de la superclasa Reader, deci nu fac nici o prelucrare. Aceste metode pot fi ns redefinite n subclase, pentru a realiza astfel de prelucrri. n pachetul java.io exist subclasa PushbackReader. Putem crea i propriile noastre subclase.

Constructor
protected FilterReader(Reader in) care preia fluxul de intrare in.

- creeaz un flux de intrare de caractere cu filtru,

Metode
metodele sunt la fel cele din superclasa Reader.

Clasa FilterWriter
Face parte din pachetul java.io. Este superclasa claselor de fluxuri de ieire de caractere, care realizeaz anumite operaii de filtrare (prelucrare) a datelor de ieire. De fapt, metodele acestei clase sunt cele motenite de la superclasa Writer, deci nu fac nici o prelucrare. Aceste metode pot fi ns redefinite n subclase, pentru a realiza astfel de prelucrri.

379

Severin Bumbaru

Constructor
protected FilterWriter(Writer out) - creeaz un flux de ieire de caractere cu filtru, care transmite datele la fluxul de ieire de caractere out.

Metode
Aceleai ca n superclasa Writer.

Clasa EventObject
public class EventObject extends Object implements Serializable Face parte din pachetul java.util. Este rdcina ierarhiei de clase de evenimente. Fiecare eveniment este generat de o surs (source). Fiecare instan a clasei EventObject conine o referin la aceast surs i o metod prin care ea este obinut.

Constructor
public EventObject(Object source)

- se genereaz un eveniment, indicndu-se sursa.

Metode
public Object getSource() public String toString()

- ntoarce sursa evenimentului.

- ntoarce reprezentarea sub form de String a evenimentului.

Interfaa EventListener
public interface EventListener Face parte din pachetul java.util. Este o interfa generic, pe care trebuie s o extind direct sau indirect - orice interfa de asculttoare de evenimente. Interfaa nu conine nici o metod.

Clasa AWTEvent
public abstract class AWTEvent extends EventObject Face parte din pachetul java.awt. Este superclasa tuturor claselor de evenimente AWT. Orice eveniment AWT are un identificator, reprezentat prin cmpul id. Clasa conine cmpuri

380

Programarea orientata pe obiecte n limbajul Java statice, care au ca valori mti pentru selectarea dup id a diferitelor tipuri de evenimente. Clasele de evenimente create n afara pachetelor din Java API trebuie s aib valoarea cmpului id superioar valorii maxime din cmpul RESERVED_ID_MAX. Clasa AWTEvent nlocuiete clasa Event din JDK 1.0, care a fost meninut n pachet numai pentru compatibilitate. Subclasele directe ale clasei AWTEvent sunt: ActionEvent, AdjustmentEvent, AncestorEvent, ComponentEvent, HierarchyEvent, InputMethodEvent, InternalFrameEvent, InvocationEvent, ItemEvent, TextEvent. Ele se gsesc n pachetul java.awt.event, cu excepia clasei InternalFrameEvent, care se gsete n pachetul javax.swing.event.

Cmpuri
protected int id

- identificatorul tipului de eveniment. - masca pentru selectarea

public static final long COMPONENT_EVENT_MASK

evenimentelor de component.
public static final long CONTAINER_EVENT_MASK

- masca pentru selectarea

evenimentelor de container.
public static final long FOCUS_EVENT_MASK

- masca pentru selectarea evenimentelor

de focalizare
public static final long KEY_EVENT_MASK

- masca pentru selectarea evenimentelor de

tast.
public static final long MOUSE_EVENT_MASK

- masca pentru selectarea evenimentelor

de mouse.
public static final long MOUSE_MOTION_EVENT_MASK

- masca pentru selectarea

evenimentelor de micare a mouse-ului.


public static final long WINDOW_EVENT_MASK

- masca pentru selectarea evenimentelor

de fereastr.
public static final long ACTION_EVENT_MASK

- masca pentru selectarea evenimentelor

de aciune.
public static final long ADJUSTMENT_EVENT_MASK

- masca pentru selectarea

evenimentelor de ajustare.
public static final long ITEM_EVENT_MASK

- masca pentru selectarea evenimentelor de

articol.
public static final long TEXT_EVENT_MASK

- masca pentru selectarea evenimentelor de

text.
public static final long INPUT_METHOD_EVENT_MASK

- masca pentru selectarea

evenimentelor de metod de intrare.

381

Severin Bumbaru
public static final long PAINT_EVENT_MASK

- masca pentru selectarea evenimentelor

de desenare.
public static final long INVOCATION_EVENT_MASK

- masca pentru selectarea

evenimentelor de invocare.
public static final long HIERARCHY_EVENT_MASK

- masca pentru selectarea

evenimentelor de ierarhie.
public static final long HIERARCHY_BOUNDS_EVENT_MASK

- masca pentru selectarea

evenimentelor de margini ale ierarhiei.


public static final int RESERVED_ID_MAX

- valoarea maxim rezervat pentru id.

Constructori
- construiete un obiect din clasa AWTEvent, folosind paramerii unei instane a clasei Event.
public AWTEvent(Event event)

- construiete o nou instan a clasei AWTEvent, specificndu-se sursa i tipul de eveniment.


public AWTEvent(Object source, int id)

Metode principale
Metodele clasei EventObject, la care se adaug:
public int getID()

- ntoarce tipul de eveniment. - ntoarce reprezentarea sub form de String a evenimentului.

public String toString()

- ntoarce un ir care conine parametrii evenimentului. Se folosete n special la depanarea programului.


public String paramString()

Clasa BorderLayout
public class BorderLayout extends Object implements LayoutManager2, Serializable Suprafaa containerului prevzut cu acest gestionar de poziionare se mparte n cinci zone: NORTH, SOUTH, WEST, EAST i CENTER. n fiecare din aceste zone poate fi pus cte o singur component. Dm aici un exemplu de utilizare a unui gestionar de poziionare din clasa BorderLayout:
p.setLayout(new BorderLayout()); p.add(new Button("OK"), BorderLayout.SOUTH);

n prima instruciune, pentru containerul p se seteaz gestionarul de poziionare BorderLayout. n a doua instruciune, se pune butonul cu inscripia "OK" n zona SOUTH a aceluiai container. Dac se omite zona, se consider implicit c adugarea componentei se face n zona CENTER.

382

Programarea orientata pe obiecte n limbajul Java

Constructori
- se creeaz un gestionar de poziionare BorderLayout, fr distanare ntre componente.
public BorderLayout()

- se creeaz un gestionar de poziionare BorderLayout, avnd distanri ntre componente hgap pe orizontal i vgap pe vertical.
public BorderLayout(int hgap, int vgap)

Metode
Metodele din interfeele LayoutManager i LayoutManager2, la care se adaug urmtoarele:
public int getHgap()

- ntoarce distanarea pe orizontal ntre componente.

public void setHgap(int hgap) - seteaz distanarea pe orizontal ntre componente.


public int getVgap()

- ntoarce distanarea pe vertical ntre componente. - seteaz distanarea pe vertical ntre componente.

public void setVgap(int vgap)

Clasa Button
public class Button extends Component implements Accessible Instanele acestei clase sunt butoane care conin un text numit "etichet" (engl: label). Cnd este apsat, butonul genereaz un eveniment de aciune, care poate fi ascultat cu un ActionListener.

Constructori
public Button()

- construiete un buton care nu conine text. - construiete un buton care conine eticheta specificat.

public Button(String label)

Metode
Metodele sunt cele ale clasei Component la care se adaug urmtoarele:
public String getLabel()

- ntoarce eticheta butonului. - seteaz eticheta butonului.

public void setLabel(String label)

- seteaz numele aciunii de comand generat de buton. Dac nu se folosete aceast comand, implicit acest nume este identic cu eticheta butonului.
public void setActionCommand(String command) public String getActionCommand()

- ntoarce numele aciunii de comand generat de

buton.

383

Severin Bumbaru
public void addActionListener(ActionListener l)

- adaug la buton un asculttor de - elimin asculttorul de

evenimente de aciune.
public void removeActionListener(ActionListener l)

evenimente de aciune specificat.

Clasa Canvas
public class Canvas extends Component implements Accessible Instanele acestei clase sunt suprafee rectangulare albe, pe care se pot trasa desene (n englez, canvas este pnza pe care se picteaz). Pentru a realiza un desen, se creeaz o subclas a clasei Canvas, pentru care se redefinete metoda paint.

Constructori
public Canvas()

- creeaz o nou instan a clasei Canvas. - creeaz o nou instan a clasei

public Canvas(GraphicsConfiguration config) Canvas, folosind configuraia grafic config.

Medtode
Metodele clasei Component, dintre care cea mai utilizat este metoda:
public void paint(Graphics g) folosind contextul grafic g.

- deseneaz pe suprafaa acestei componente (Canvas),

Clasa CardLayout
public class CardLayout extends Object implements LayoutManager2, Serializable Instanele acestei clase sunt gestionari de poziionare, care plaseaz componentele n container una peste alta, ca ntr-un pachet de cri de vizit.La un moment dat este vizibil numai componenta de deasupra, ns componentele i pot schimba locurile ntre ele prin rotaie.

Constructori
public CardLayout()

- construiete un CardLayout fr spaiu liber n jurul componentelor. cardLayout care are pe

public CardLayout(int hgap, int vgap) - construiete un margini spaiile libere hgap pe orizontal i vgap pe vertical.

384

Programarea orientata pe obiecte n limbajul Java

Metode
Metodele interfeelor LayoutManager i LayoutManager2, la care se adaug urmtoarele:
public int getHgap()

- ntoarce spaiul liber pe orizontal. - seteaz spaiul liber pe orizontal.

public void setHgap(int hgap) public int getVgap()

- ntoarce spaiul liber pe vertical. - seteaz spaiul liber pe vertical. - pune deasupra prima component din

public void setVgap(int vgap)

public void first(Container parent)

containerul printe specificat.


public void next(Container parent)

- pune deasupra urmtoarea component a

containerului specificat. - pune deasupra componenta precedent a containerului specificat.componenta cu numele name din containerul specificat.
public void previous(Container parent)

public void show(Container parent, String name) - pune deasupra


public void last(Container parent)

- pune deasupra ultima component din

containerul specificat.

Clasa Color
Clasa Color ncapsuleaz culorile din spaiul de culori implicit sRGB, sau culori dintrun spqaiu de culori arbitrar, identificat prin ColorSpace. Fiecare culoare conine, n afar de componentele de culoare fundamentale, i o component numit alpha, care semnific opacitatea i are valori reale n intervalul 0.0 ... 1.0 sau valori ntregi n intervalul 0 .. 255. Valoarea alpha=0 nseamn opacitate nul (culoare total transparent), iar valoarea maxim a lui alpha nseamn opacitate maxim (culoare total netransparent). n mod implicit se admite opacitatea maxim. Culorile fundamentale din sistemul sRGB (standard RGB) sunt urmtoarele: red (rou), green (verde) i blue (albastru). Acestea pot fi date prin numere ntregi n intervalul 0 .. 255 sau prin numere reale n intervalul 0.0 .. 1.0. Aceste valori reprezint intensitatea culorii fundamentale respective n culoarea dat. Orice culoare se obine prin combinarea acestor trei componente fundamentale, cu intensiti diferite. Explicaii suplimentare sunt date i n seciunea "Clasa Color" din acest manual. Valorile componentelor fundamentale ale culorii pot fi date i mpachetate ntr-un singur numr de tip int, n care fiecare octet conine una din componente (n intervalul 0 .. 255) astfel: blue - biii 0 ..7; green: biii 8 .. 15; red: biii 16 .. 23; alpha: biii 24 .. 31. Clasa Color conine i cmpuri finale pentru culorile tipice.

385

Severin Bumbaru

Cmpuri
public static final Color white

- culoarea alb. - culoarea gri deschis.

public static final Color lightGray public static final Color gray

- culoarea gri. - culoarea gri nchis.

public static final Color darkGray public static final Color black public static final Color red

- culoarea neagr.

- culoarea roie. - culoarea roz. - culoarea portocalie (orange). - culoarea galben.

public static final Color pink

public static final Color orange public static final Color yellow public static final Color green

- culoarea verde. - culoarea violet.

public static final Color magenta public static final Color cyan public static final Color blue

- culoarea azuriu (albastru deschis) - culoarea albastr.

Constructori
- creeaz o instan a clasei Color pentru cu culoarea cu componentele RGB specificate prin numere ntregi cuprinse ntre 0 i 255.
public Color(int r, int g, int b)

- creeaz o instan a clasei Color pentru cu culoarea cu componentele RGB i componenta a (alpha) specificate prin numere ntregi cuprinse ntre 0 i 255.
public Color(int r, int g, int b, int a)

- creeaz o instan a clasei Color, dndu-i ca argument un numr de tip int (pe 4 octei), care n primii trei octei conine cele trei componente fundamentale.
public Color(int rgb)

public Color(int rgba, boolean hasalpha) - creeaz o instan a clasei Color, dndu-i ca argument un numr de tip int (pe 4 octei), care n primii trei octei conine cele trei componente fundamentale, iar n ultimul octet componenta alpha. Al doilea argument indic dac exist sau nu componenta alpha. public Color(float r, float g, float b) - creeaz o instan a clasei Color pentru cu culoarea cu componentele RGB specificate prin numere reale cuprinse ntre 0.0 i 1.0. public Color(float r, float g, float b, float a) - public Color(int r, int g, int b, int a) - creeaz o instan a clasei Color pentru cu culoarea cu componentele RGB i componenta a (alpha) specificate prin numere reale cuprinse ntre 0.0 i 1.0. 386

Programarea orientata pe obiecte n limbajul Java


public Color(ColorSpace cspace, float[] components, float alpha) - creeaz o instan a clasei Color, dndu-se spaiul de culori cspace (instan a clasei ColorSpace), tabloul de componente components i opacitatea alpha.

Metode
public int getRed()

- ntoarce componenta roie. - ntoarce componenta verde.

public int getGreen() public int getBlue()

- ntoarce componenta albastr. - ntoarce componenta alpha.

public int getAlpha() public int getRGB()

- ntoarce un int, care conine sub form mpachetat cele patru componente (r, g, b, alpha).
public Color brighter() public Color darker()

- ntoarce o variant mai deschis a acestei culori.

- ntoarce o variant mai nchis a acestei culori.

public static Color decode(String nm) throws