Intrebari Java

60
Ce este Java Java este un limbaj de programare cu larga utilizare ce permite sa scriem aplicatii indifferent de domeniul de utilizare. Caracteristici ale limbajului Java -simplu-are o sintaxa asemnatoare cu C++ dar simplificat prin numarul de date primitive -s-a introdus tipul de date Boolean -s-a introdus clasa string -s-au eliminate pointerii -s-a renuntat la supraincarcarea operatorilor -limbajul este strict tipizat -nu se mai foloseste mostenirea multipla ci doar simpla -nu mai sunt destructori -administrare automata a memoriei -este orientate pe obiecte -portabilitatea Maşina virtuală Java -este implementata software -pe fiecare calculatr trebuie sa avem o masina virtual pentru a rula programe java -ea este un calculator abstract care se ocupa cu incarcarea claselor, organizarea memoriei, conventiile de reprezentare a datelor in memorie, managementul memoriei tip, verificarea codului de octeti Tipuri de produse software scrise in Java aplicaţie - este un produs software care se instalează pe un anumit calculator şi funcţionează direct sub controlul sistemului de operare, având acces la toate resursele calculatorului respectiv. Una din clasele aplicaţiei trebuie sa conţină metoda principală , cu care începe execuţia aplicatiei. applet (miniaplicaţie) - este un program care se transmite sub formă de cod de octeţi (bytecode) prin reţeaua de calculatoare şi este executat în cadrul unui navigator (browser) de Web, fără a avea acces la fişierele sau sistemul de intrare/ieşire al calculatorului pe care se execută; servlet - un program care se execută pe un server dein reţea. 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 conţine un ansamblu de clase şi obiecte, care comunică între ele prin mesaje. Clasa este o extensie a conceptului de tip de date şi conţine o structură de date, împreună cu metodele (functiile) care se aplica acestor date. 1

description

java cu Cocu UGAL

Transcript of Intrebari Java

Ce este JavaJava este un limbaj de programare cu larga utilizare ce permite sa scriem aplicatii indifferent de domeniul de utilizare.

Caracteristici ale limbajului Java-simplu-are o sintaxa asemnatoare cu C++ dar simplificat prin numarul de date primitive-s-a introdus tipul de date Boolean-s-a introdus clasa string-s-au eliminate pointerii-s-a renuntat la supraincarcarea operatorilor-limbajul este strict tipizat-nu se mai foloseste mostenirea multipla ci doar simpla-nu mai sunt destructori-administrare automata a memoriei-este orientate pe obiecte-portabilitatea

Maşina virtuală Java-este implementata software-pe fiecare calculatr trebuie sa avem o masina virtual pentru a rula programe java-ea este un calculator abstract care se ocupa cu incarcarea claselor, organizarea memoriei, conventiile de reprezentare a datelor in memorie, managementul memoriei tip, verificarea codului de octeti

Tipuri de produse software scrise in Java  aplicaţie - este un produs software care se instalează pe un anumit calculator şi funcţionează direct sub controlul sistemului de operare, având acces la toate resursele calculatorului respectiv. Una din clasele aplicaţiei trebuie sa conţină metoda principală , cu care începe execuţia aplicatiei.applet (miniaplicaţie) - este un program care se transmite sub formă de cod de octeţi (bytecode) prin reţeaua de calculatoare şi este executat în cadrul unui navigator (browser) de Web, fără a avea acces la fişierele sau sistemul de intrare/ieşire al calculatorului pe care se execută; servlet - un program care se execută pe un server dein reţea.

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 conţine un ansamblu de clase şi obiecte, care comunică între ele prin mesaje.

Clasa este o extensie a conceptului de tip de date şi conţine 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.

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.

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.

1

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.

Şablonul unei aplicaţii simple in limbajul Java

class <nume_clasa> {         public static void main(String args[]) {           // corpul metodei main         }     } Editarea fişierului sursaDe exemplu, clasa PrimaAplicatie va fi editată sub forma unui fişier de text cu numele PrimaAplicatie.java. Este preferabil să puneţi acest fişier într-un subdirector separat. De exemplu puteti crea un subdirector numit javaLab, în care să creaţi un alt subdirector numit sapt1, în care sa puneţi fişierul PrimaAplicatie.java.

Compilarea si eliminarea erorilor semnalate de compilatorTranslatarea programului sursă în program sub forma de cod de octeţi (bytecode) se face cu ajutorul compilatorului Java, numit javac. În acest scop, va deplasaţi în subdirectorul în care se găseşte programul sursă pe care doriţi să-l compilaţi şi daţi comanda     javac <fisier_sursa>

După ce aţi dat această comandă, veţi obţine unul din următoarele rezultate:

1. Pe ecran apare din nou promptul sistemului de operare, fără a se afişa un mesaj de eroare. În acest caz, compilarea a decurs normal, iar dacă daţi comanda dir veţi constata ca în subdirectorul curent a apărut un nou fişier, care poartă numele clasei şi extensia class. Acesta este fişierul care conţine bytecode-ul clasei compilate.

2. Obţineţi 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 aţi cerut compilarea. În ambele cazuri, este necesar să eliminaţi erorile şi să reluaţi compilarea.

Executarea aplicatieiDacă în directorul curent există fişierul <nume_aplicaţie>.class, executarea acestei aplicaţii se solicită prin comanda    java <nume_aplicaţie> Remarcăm că se dă ca parametru numai numele clasei, fără extensia class. Efectul acestei comenzi este, fie executarea aplicatiei, fie aparitia unui mesaj de eroare de execuţie. Prin comanda java se pune în execuţie interpretorul maşinii virtuale Java. Acest interpretor verifică dacă în directorul curent există fişierul <nume_aplicaţie>.class. Daca acesta există, încarcă în memorie codul de octeţi pe care îl conţine şi pune în execuţie metoda public static void main(). Dacă fişierul nu există, sau dacă el nu conţine o astfel de metodă, se semnalează printr-un mesaj de eroare.

Şiruri de caractereŞirul se reprezintă în program printr-o succesiune de caractere cuprinsă între ghilimele. Iată câteva exemple de şiruri: "sir de caractere" "ABCDefgh" "1A23bc7" "*+_/?" "" Ultimul exemplu este un şir vid (care nu conţine nici un caracter).

Operaţii asupra şirurilor de caractereConcatenarea

2

Asupra şirurilor se poate aplica operaţia de concatenare , reprezentata prin operatorul +. Expresia şir1+şir2, în care operatorul + este plasat între două şiruri, are ca rezultat un nou şir, care conţine cele două şiruri-operanzi puse unul după altul. De exemplu, expresia     "abcde"+"fgh" dă ca rezultat şirul "abcdefgh".

Metode pentru afişarea pe ecran a şirurilorÎn capitolul precedent, am folosit deja pentru afişarea şirurilor de caractere metoda     System.out.println(<şir>) la care vom adăuga acum şi metoda     System.out.print(<şir>) În ambele metode, argumentul <şir> este un şir de caractere, care se afişeaza pe ecran. Deosebirea dintre ele constă în faptul că, după afişarea şirului, metoda println transmite şi comanda de trecere la linie nouă, în timp ce metoda print nu transmite o astfel de comandă. În consecinţă, în cazul afişării cu println, următoarea afişare se va face de la început de linie nouă, iar la afişarea cu print afişarea următoare se va face în continuare, pe aceeaşi linie.

Unităţile lexicale ale limbajului JavaUnităţile lexicale, numite şi lexeme (engl. token, lexeme)  sunt construcţiile elementare ale limbajului ("atomii" acestuia). Acestea sunt simboluri, formate din unul sau mai multe caractere, care au o anumită semnificaţie în limbaj. După rolul îndeplinit, unităţile lexicale sunt: identificatori, cuvinte cheie, cuvinte rezervate, literali, separatori,operatori, comentarii şi spaţii

IdentificatoriNumele date programelor sau componentelor acestora (clase, variabile, metode etc.) se numesc identificatori. Identificatorii se aleg de către programator, respectând 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 conţine spaţii libere sau alte caractere, decât cele menţionate aici.

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ă următoarele cuvinte cheie :

abstract double int strictfp

boolean else interface super

break extends long switch

byte final native synchronized

case finally new this

catch float package throw

char for private throws

class goto protected transient

const if public try

continue implements return void

default import short volatile

do instanceof static while

Dintre acestea,  const  şi  goto  nu sunt folosite în prezent, dar ele au fost introduse în tabela cuvintelor cheie în vederea unei eventuale utilizări viitoare.

3

Observăm acum că toate exemplele de cuvinte cheie date la începutul acestei secţiuni (class, public, static, void) sunt prezente în tabela de mai sus.

Cuvinte rezervate

Se consideră cuvinte rezervate acele cuvinte, care nu pot fi folosite ca identificatori, având semnificaţii 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 adevărat şi fals, iar al treilea are semnificaţia de referinţă nulă. De fapt, aceste cuvinte rezervate sunt forme speciale de literali.

LiteraliLiteralii sunt reprezentările în fişierele 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;     - referinţa nulă: null. Am subliniat faptul că literalul este forma sub care o anumita valoare este reprezentată în fişierul sursă, deci în programul scris în limbaj de nivel superior (în cazul nostru în limbajul Java). Vom arăta ulterior că forma de reprezentare a aceloraşi valori în memoria internă a calculatorului (forma internă) este diferită de cea externă. Vom reveni asupra regulilor de scriere a literalilor când vom prezenta tipurile de date din limbajul Java.

SeparatoriSeparatorul este un caracter care delimitează formele sintactice sau le separă între ele. În limbajul Java se folosesc următorii separatori:                               {  }  (  )  [  ]  ;  ,  . Spaţiul liber şi operatorii indeplinesc, de asemenea, rolul de separatori. Aproape toţi aceşti separatori au fost deja folosiţi în exemplele date în acest capitol.

OperatoriOperatorii sunt simboluri ale unor operaţii. Am folosit deja simbolul +  ca operator de concatenare (deci simbol al operaţiei de concatenare). Operatorul poate fi format din unul sau mai multe caractere.   Entitatea asupra căreia se aplică operatorul se numeşte operand. După numărul de operanzi, operatorii pot fi unari, binari sau ternari.  

După numărul 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 faţa operandului; uneori însă se foloseste şi forma "postfix"     operand operator în care operatorul se pune după operand;     operatori binari, care se aplică asupra a doi operanzi, operatorul fiind situat între aceştia; 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

4

( ?:)folosit în expresiile condiţionale. 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 acelaşi tip).

Din exemplele de mai sus, observăm că semnificaţia unui operator poate să depindă de context, ca în cazul operatorului +, care a fost folosit atât pentru operaţia de concatenare a şirurilor, cât şi pentru cea de adunare a numerelor.

Din punct de vedere matematic, operatorii sunt funcţii 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 funcţie de argumente a si b, care are ca valoare suma valorilor celor două argumente. După efectul operatorului asupra operanzilor, operatorii pot fi fără efect lateral, care lasa valorile operanzilor nemodificate, şi cu efect lateral, care modifică valorile operanzilor. Astfel, operatorul + din exemplul anterior, este un operator fără efect lateral. În schimb, în expresia ++a operatorul de incrementare ++ are efect lateral deoarece, în urma efectuarii operaţiei, valoarea operandului a creşte cu o unitate.

Comentarii în fişierul sursă

După cum s-a aratat deja, în fişierele sursă pot fi introduse comentarii, care au rolul de a da omului, care citeşte programul respectiv, anumite explicaţii necesare pentru o mai buna înţelegere a acestuia. Din punct de vedere sintactic, întregul comentariu este privit ca o singură unitate lexicală, care este ignorată de către compilator, deci nu are efect asupra codului de octeţi generat de acesta.

Spaţii

Între unităţile lexicale ale programului pot fi introduse oricât de multe spaţii libere, fără ca acestea să aibă influenţă asupra sintaxei sau semanticii programului. Mai multe spaţii libere succesive sunt tratate de compilator ca şi când ar fi un singur spaţiu

VariabileIn matematică, variabila este un simbol dat unei valori, care aparţine unei mulţimi de valori ce constituie domeniul de definiţie al variabilei respective. În programare, variabila este un nume căruia i se asociază o valoare. Numele variabilei este un identificator, iar valoarea variabilei trebuie să aparţină unui anumit tip de date. Asupra valorilor variabilelor pot fi efectuate prin program anumite operaţii.Valoarea variabilei trebuie să  fie reprezentată în memoria calculatorului la o anumită adresă şi să ocupe acolo un anumit spaţiu (un anumit număr de biţi).  În consecinţş, numim variabilă o zonă de memorie care poarta un nume şi care conţine o anumită valoare , apartinând unui tip de date . Programatorul care foloseşte 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 internă a acesteia, fiind suficient să-i cunoasca numele şi tipul. Alocarea de spaţiu în memorie pentru fiecare variabilă se face, după caz, de către compilator sau interpretor. În schimb, numele şi tipul variabilei trebuie declarate de către programator. Remarcăm că în matematică operaţiile 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 importanţa ce valoare are variabila a, egalitatea fiind întotdeauna adevarată. În programare se are în vedere faptul că, atât timp cât ea exista în memorie, variabila are întotdeauna o valoare (deoarece zona de memorie aferentă nu poate fi vidă), iar operaţiile se fac asupra valorilor variabilelor şi nu asupra numelor acestora.

5

Declararea si iniţializarea variabilelor

În limbajul Java, orice variabilă trebuie declarată înainte de a fi utilizată . Prin declararea variabilei se înţelege precizarea, pentru compilator, a tipului şi numelui acesteia.  Iniţializarea variabilei se face atunci, când acesteia i se dă pentru prima dată o valoare şi deci  i se alocă spaţiu în memorie. Dacă, la declararea variabilei, aceasta nu este şi iniţializată în mod explicit, atunci ea este iniţializata cu o valoare implicită, care va fi specificată la descrierea fiecărui tip.

Remarcam că:

declaraţia de tip este o instructiune care se termină obligatoriu prin simbolul ; (punct şi virgulă); este posibil ca, într-o singură declaraţie, să apară  mai multe variabile; în acest caz, specificaţiile

variabilelor respective sunt separate prin virgule; indicarea valorii variabilei este opţională.

În declaraţia de tip, valoarea iniţială 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 conţine să aiba deja valori date anterior.

Prin convenţie, î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 când numele variabilei este format din mai multe cuvinte ale limbii naturale, de exemplu vitezaMedie.

Variabile finaleÎn limbajul Java, se numesc variabile finale acele "variabile", ale căror valori nu pot fi modificate prin program. Acestea sunt deci, de fapt, nişte constante cu nume. Ele se aseamănă cu variabilele propriu-zise prin faptul că sunt tot perechi nume - valoare, numai că valoarea lor se dă o singură dată, sub forma de iniţializare în declaraţia de tip sau sub forma de atribuire, după care nu mai poate fi modificată. Se obişnuieşte ca numele de variabile finale să fie scrise în întregime cu majuscule. Declaraţia de tip este la fel cu cea pentru variabile obişnuite, dar are in faţă modificatorul final, care este un cuvânt cheie.  

De exemplu, declaraţia     final int ALPHA=17, BETA=-1453; serveşte pentru a specifică faptul că ALPHA şi BETA sunt variabile 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, nişte constante).

Tipuri de date Tipul de date este unul din conceptele fundamentale ale programării calculatoarelor. Tipul de date este o mulţime de valori, asociată cu o mulţime de operaţii care se pot face asupra valorilor respective. În limbajul Java, tipurile de date se împart în două categorii: tipuri primitive şi tipuri referinţă.

Tipuri de date primitive

Tipurile de date primitive sunt predefinite în limbaj. Aceasta înseamnă că numele, mulţimea de valori,   mulţimea de operaţii şi tipul rezultatului operaţiilor 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:

6

tipul boolean; tipurile numerice

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

Operaţia de atribuire simplăOperaţia de atribuire se poate aplica tuturor tipurilor de date, deci şi celor numerice. În expresia     variabilă = expresie daca variabila din partea stângă aparţine 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 stângă. Prin tip compatibil înţelegem fie acelaşi tip cu cel al variabilei din stânga, fie un tip numeric care poate fi convertit implicit la acesta. Dacă tipul operandului din dreapta este numeric, dar nu se converteşte implicit la cel din stânga, se poate folosi conversia de tip explicită prin operatorul cast. În acest caz, însă, există pericolul ca valoarea să se altereze prin conversie.

Operaţii de atribuire compusăUrmând tradiţia limbajului C, în limbajul Java există şi operatori de atribuire compusă, în care operaţia de atribuire este combinată cu una din operaţiile aritmetice.

Operatorii de atribuire compusă sunt următorii: +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=, >>>=. Se observă că fiecare din aceşti operatori are forma op=  în care op este un operator aritmetic binar. Expresia     variabila op= operand în care op este un operator aritmetic binar, este echivalentă cu expresia     variabila = variabila op operand şi se evaluează astfel:     - se calculează mai întâi 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 stânga. Aceasta nouaă valoare este, totodată, şi valoare a expresiei.

Operaţia de comparareComparaţiile sunt operaţii binare fără efect lateral , în care se compară două numere, obţinându-se ca rezultat o valoare de tip boolean. Operatorii prin care se efectuează comparaţia a două numere se numesc operatori relaţionali şi sunt daţi în tabela de mai jos.  

Operator Semnificatie

< mai mic decât

<= mai mic decât sau egal cu

> mai mare decât

>= mai mare decât sau egal cu

== este egal cu

!= este diferit de

Operaţii aritmeticeOperaţiile aritmetice sunt cele care se aplică unor operanzi numerici, având ca rezultate tot numere. După numărul de operanzi, ele pot fi unare sau binare. Unele operaţii aritmetice unare au şi efect lateral. Tipul rezultatului operaţiilor aritmetice depinde de tipul operanzilor şi va fi discutat la fiecare din tipurile numerice în parte. În exemplele de expresii din această secţiune, vom considera că a şi b sunt doi operanzi   numerici . În limbajul Java există următorii operatori aritmetici:

7

Operatori unari fără efect lateral:  

Operator Exemplu de expresie Valoarea expresiei

+ +a aceeaşi cu valoarea operandului

- -a 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 creşterea cu o unitate a valorii variabilei-operand, iar operatorul de decrementare -- are ca efect lateral micşorarea cu o unitate a acestei valori. Acest efect are loc indiferent dacă operatorul este plasat înaintea operandului sau după acesta. În schimb, poziţia operatorului faţă de operand are importanţă la stabilirea valorii expresiei rspective. Daca operatorul este plasat în fata operandului, operaţia de incrementare sau decremantare are loc înainte de a se stabili valoarea expresiei; dacă, însă, operatorul este plasat dupa operand, valoarea expresiei se stabileşte înainte de a se face incrementarea sau decrementarea. Efectul operaţiilor este prezentat în tabelul de mai jos.  

Operator Expresie Operatie Valoarea expresiei Efect lateral

++ ++a preincrementare a+1 valoarea variabilei a creste cu 1

++ a++ postincrementare a valoarea variabilei a creste cu 1

-- --a predecrementare a-1 valoarea variabilei a scade cu 1

-- a-- postdecrementare a valoarea variabilei a scade cu 1

Operatorii logici binari

Operatorii binari nu au efect lateral - deci nu modifică valorile operanzilor -   şi sunt daţi în tabela de mai jos.  

Operator Expresie Operatie Valoarea expresiei

+ a+b adunare suma valorilor operanzilor

- a-b scadere diferenta valorilor operanzilor

* a*b inmultire produsul valorilor operanzilor

/ a/b impartire catul (rezultatul impartirii) primului operand la al doilea

% a%b modulo restul impartirii intregi a primului operand la al doilea

Prin împărţire întreagă înţelegem împărţirea făcută astfel, încât câtul sa fie un număr întreg (fără extragerea părţii fracţionare (situate dupa virgulă).

Operatorii logici binari

Operatorii logici binari sunt operatori fără efect lateral, prin care se realizează operaţiile 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 (adevărat) dacă şi numai dacă atât a cât şi b au valoarea true. În celelalte cazuri expresia are valoarea false.    - Operatorii | si || realizează operaţia logică SAU. Expresiile a|b şi a||b , în care a şi b sunt operanzi de tip

8

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 adevărat, iar celălalt fals). Dacă cei doi operanzi au valori identice, valoarea expresiei este false.

Operatii de deplasare binaraUrmând "tradiţia" limbajului C, limbajul Java conţine şi operatori de deplasare binară. Aceştia sunt operatori binari (cu doi operanzi) fără efect lateral. Tipul rezultatului operaţiei se stabileşte la fel ca în cazul operaţiilor aritmetice cu numere întregi. Valoarea rezultată se stabileşte astfel: se ia reprezentarea internă a primului operand şi se deplasează la stânga sau la dreapta cu un numar de poziţii 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 aparţin unor tipuri întregi.  

Operator Expresie Efect

<< a<<s deplasare la stânga cu s poziţii binare

>> a>>s deplasare la dreapta cu s poziţii binare, cu conservarea semnului

>>> a>>>s deplasare la dreapta fără semn, cu s poziţii binare

Expresii cu date primitiveÎn programare, expresia este o combinaţie permisă ("legală", corectă) de simboluri, care reprezintă o valoare. Tipul expresiei este acelaşi 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 stabileşte ce expresii sunt permise sau nepermise. În limbajul Java, expresia poate conţine literali, variabile, operatori, operanzi, funcţii şi paranteze şi trebuie să poată fi evaluată (calculată), astfel încât să se obţină o valoare.

Precedenta operatorilor

La evaluarea unei expresii, prezinta o importanţă deosebită ordinea în care se aplică operatorii pe care îi conţine, 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 cărora se stabileşte ordinea de evaluare.

Fiecărui 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 precedenţa superioară. În consecinţă, aceasta expresie se va calcula ca şi când ar fi scrisă sub forma a+(b*c).

În limbajul Java, la stabilirea ordinii operaţiilor se aplica următoarele reguli:

    - operatorii unari se aplică înaintea celor binari;     - expresiile din interiorul parantezelor se evaluează înaintea celor din exterior;     - dacă, într-o expresie, toţi operatorii au acelaşi nivel de precedenţă, ei se aplică de la stânga la dreapta;     - operanzii unui operator se evalueaza înainte de a se aplica operatorul respectiv (deci operatorul se aplică întotdeauna asupra valorilor operanzilor săi); dacă operaţia este binară, operandul din partea stângă se evaluează înaintea celui din partea dreaptă;     - nivelul de precedenţă al operatorilor se stabileşte conform cu tabela de mai jos, în care:

toţi operatorii din aceeaşi celulă a tabelei au acelaşi nivel de precedenţă; operatorii de pe un nivel superior se aplică înaintea celor de pe nivelurile inferioare.

9

Expresia conditionalaUrmând "tradiţia" limbajului C, în limbajul Java există operatorul ternar (cu trei operanzi) ?:   numit operatorul condiţional, care este utilizat în cadrul următoarei expresii condiţionale:     operand1 ? operand2 : operand3 unde:     operand1  - expresie booleană;     operand2 şi operand3 - 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 obţinându-se o valoare booleană;    - dacă operand1 are valoarea true, atunci valoarea expresiei condiţionale este cea care se obţine evaluând operand2; altfel, este cea care se obţine evaluând operand3.

InstrucţiuneaÎn limbajul Java, procesul de calcul este controlat de instrucţiuni (enunţuri). Fiecare instrucţiune indică una sau mai multe acţiuni pe care trebuie să le execute calculatorul. Corpul oricărei metode este constituit dintr-o succesiune de instrucţiuni. Executarea metodei constă în executarea acestor instrucţiuni într-o ordine determinată. Instrucţiunile pot fi grupate în blocuri.

După structura lor, instrucţiunile pot fi simple sau structurate.

Instrucţiunile simple nu conţin în interiorul lor alte instrucţiuni. Există trei categorii principale de instrucţiuni (enunţuri) simple: declaraţiile de variabile locale, instrucţiunile-expresie şi instrucţiunea vidă. La scrierea lor se respectă următoarele reguli:

toate instrucţiunile simple se termină cu caracterul ';' (punct şi virgulă). Instrucţiunea vidă este formată numai din acest caracter;

declaraţiile de variabile locale servesc pentru a specifica tipul, numele şi (opţional) valoarea iniţială a variabilelor. Forma sintactică şi utilizarea declaraţiilor au fost prezentate anterior;

instrucţiunile-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, declaraţiile de variabile locale sunt considerate instrucţiuni executabile, deci ele au efect la executarea programului.  În majoritatea limbajelor compilate, declaraţiile de variabile locale sunt luate în consideraţie numai la compilare, deci sunt considerate instrucţiuni neexecutabile. În limbajul Java declaraţiile sunt, de asemenea, luate în consideraţie de compilator, care verifică dacă declaraţia este corectă sintactic şi, de asemenea, verifică la fiecare apariţie 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.

Principiile programării structurateProgramarea structurată este o orientare în conceperea şi alcătuirea programelor, având ca obiectiv o mai bună gestionare a complexităţii acestora, ţinând cont de particularităţile gândirii umane. Conform metodei programării structurate, la conceperea unui program, este recomandabil să se respecte următoarele principii:     1. Teorema de structură : orice program poate fi întocmit folosind numai trei structuri de control fundamentale: structura secvenţială, structura alternativă şi structura repetitivă.     2. La conceperea programelor se recomandă să se aplice tehnica de elaborare descendentă (în

10

engleză Top-Down), numită şi tehnica rafinărilor succesive.     3. Domeniile de valabilitate (de vizibilitate) ale variabilelor şi structurilor de date trebuie să fie limitate. În limbajul Java, pentru rezolvarea problemei realizării creşterii eficienţei muncii programatorilor s-a adoptat concepţia modernă a programării orientate pe obiecte. In consecinţă, modulele de program sunt mici şi rolul programării structurate este sensibil redus. Totuşi, fiecare metodă din limbajul Java este un mic program, la elaborarea căruia se aplică principiile programării structurate , ceeace s-a avut în vedere şi la adoptarea instrucţiunilor de bază oferite de acest limbaj. Este deci util ca şi programatorii în Java sa cunoască principiile fundamentale ale programării structurate.

Structura secvenţialaBlocul este o secvenţă de instrucţiuni cuprinsă între acolade. Forma sintactică a blocului este, deci, următoarea:     {         secvenţă_de_instrucţiuni     } unde secvenţă_de_instrucţiuniconstă dintr-un număr oarecare de instrucţiuni succesive, putând fi şi vidă. Instrucţiunile din această secvenţă pot fi atât simple, cât şi structurate, inclusiv alte blocuri. Din punct de vedere al programării structurate, blocul este realizarea structurii de control secvenţiale. Aceasta inseamnă că instrucţiunile dintr-un bloc se execută una dupa alta, în ordinea în care ele sunt scrise în program. Tocmai de aceea se şi foloseşte termenul secvenţă de instrucţiuni pentru a indica ce conţine blocul.

Instrucţiunea if

Instrucţiunea if serveşte pentru realizarea structurii alternative din programarea structurată. Sub forma ei cea mai simplă, această instrucţiune se scrie astfel:     if(expresie_booleană) instrucţiune unde instrucţiune poate fi orice instrucţiune valabilă în limbajul Java: instrucţiune simplă sau structurată, inclusiv un bloc sau un alt if. Remarcăm că în forma generală de mai sus nu am pus la sfârşit caracterul ';' (punct şi virgulă). Dacă instrucţiune este o instrucţiune simplă, ea include şi acest simbol.

Semnificaţia instrucţiunii if este următoarea: dacă valoarea expresiei booleene din paranteză este true, atunci se execută instrucţiune, iar altfel nu se execută nimic, continuându-se programul.

Instructiunea if .. elseInstrucţiunea if .. else realizează ambele ramuri ale structurii alternative şi are forma     if(expresie_booleană)         instrucţiune_1     else         instrucţiune_2 în care instrucţiune_1 şi instrucţiune_2 pot fi instrucţiuni simple sau structurate. Interpretarea acestui if..else este următoarea: dacă expresie_logică are valoarea true, atunci se execută instrucţiune_1, iar altfel se execută instrucţiune_2.

Instructiunea switch

În limbajul Java, structura de comutare se realizează prin instrucţiunea switch, care are următoarea formă generală:     switch (expresie) {       case valoare_1: secvenţă_1

11

                    [break;]       case valoare_2: secvenţă_2                     [break;]       ..........................       case valoare_N: secvenţă_N      [default: secvenţă ]     } î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 conţine numai literali sau variabile finale din tipurile menţionate;    - secvenţa este o secvenţă de instrucţiuni simple sau structurate;    - parantezele drepte roşii []nu apar în program, ci indică faptul că conţinutul lor este opţional (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 cărei valoare serveşte drept "comutator". Se deschide apoi acolada corpului instrucţiunii, î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 instrucţiuni (simple sau compuse) şi opţional intrucţiunea   break. După ce s-au epuizat toate cazurile, opţional se poate scrie cuvântul cheie  default urmat de una sau mai multe instrucţiuni. La sfârşit,  se închide acolada corpului instrucţiunii switch. Executarea instrucţiunii  switch decurge astfel: se evaluează mai întâi expresie şi se obţine o valoare de tip întreg, care serveşte drept comutator. Această valoare se compară, pe rând de sus în jos, cu fiecare din valorile indicate după cuvintele cheie  case, până când se găseşte prima  valoare care coincide cu cea a comutatorului. Dacă s-a găsit o astfel de valoare, se execută toate instrucţiunile care încep de la cazul respectiv, până la prima instrucţiune  break întalnită sau, în lipsa acesteia, până la acolada de închidere a corpului instrucţiunii  switch.  Dacă însă nici unul din cazuri nu conţine valoarea potrivită a comutatorului, atunci se execută instrucţiunile care urmează după cuvântul cheie default sau, în lipsa acestuia, nu se execută nimic.

Instrucţiunea  while (ciclul cu test initial)Această instrucţiune are forma generală     while (condiţie)         instrucţiune în care     condiţie - este o expresie de tip  boolean;     instrucţiune - poate fi orice instrucţiune (simplă sau structurată) a limbajului Java, inclusiv altă instrucţiune  while. Executarea acestei instrucţiuni se face astfel: se evaluează expresia booleană condiţie şi - dacă valoarea acesteia este  true, deci condiţia este satisfacută - se execută  instrucţiune,după care se revine la evaluarea condiţiei. acest ciclu se repetă cât timp este satisfacută condiţia.

Instructiunea do..while (ciclul cu test final)Forma generală a instrucţiunii de control, prin care se realizează în limbajul Java ciclul cu test final este următoarea:     do         instrucţiune     while (condiţie); unde, la fel ca în cazul instrucţiunii  while, condiţie este o expresie de tip boolean, iar instrucţiune este orice instrucţiune (simplă sau structurată) din limbajul Java. Remarcăm că la sfârşitul acestei instrucţiuni (după condiţie) se pune obligatoriu ';' (punct şi virgulă).

12

 Principala  deosebire faţă de instrucţiunea  while pentru ciclul cu test iniţial  este că testarea condiţiei se face după ce a fost executată instrucţiunea din corpul ciclului. În consecinţă, corpul ciclului va fi executat cel puţin o dată.

Instructiunea for (ciclul cu contor generalizat)

În unele limbaje de programare, pentru realizarea ciclurilor la care numărul de paşi este dinainte cunoscut, se foloseşte o instrucţiune de control specială, numită "ciclu cu contor". În pseudocod, această instrucţiune poate fi scrisă în modul următor:     pentru variabila de_la val_init la val_fin [cu_pasul pas] execută         <instrucţiune sau secvenţă de instrucţiuni>     sfârşit_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 iniţială şi finală ale acestei variabile, iar pas este pasul de variaţie la fiecare parcurgere a ciclului. Pasul implicit este 1.

Tratarea excepţiilor

În limbajul Java, există posibilitatea de a se trata prin program diferitele excepţii care apar în timpul execuţiei. În acest fel, programatorul poate să prevadă căi alternative de continuare a executării programului, fără a mai fi necesară oprirea executării lui. În mediul de lucru Java, la apariţia unei excepţii se generează un obiect special numit excepţie, care conţine informaţia despre excepţia respectivă. Acest obiect poate fi captat prin program, iar informaţia conţinută în el poate fi utilizată pentru a decide calea pe care se va merge în continuare în derularea programului. Toate obiectele de excepţie care se referă la acelaşi tip de incident formează o clasă de excepţii.

Tratarea prin program a excepţiilor se face, în limbajul Java, folosind instrucţiunea   try urmată de una sau mai multe clauze  catch şi, opţional, de o clauză  finally sub forma urmatoare:     try {            secventa         }         catch (ClasaExceptie1variabila1) {           secventa1         }         catch (ClasaExceptie2 variabila2) {           secventa2         }        ...............         catch (ClasaExceptieN variabilaN) {           secventaN         }        [finally {            secventa_finalizatoare        }]

Instrucţiuni etichetateÎn principiu, orice instrucţiune în limbajul Java poate purta o etichetă. Instrucţiunile etichetate au forma

        etichetă : instrucţiune unde    etichetă este un identificator;    instrucţiune este o instrucţiune simplă sau structurată.

13

Exemplu     alpha: x=2*a+b; Se permite să se folosească drept etichete chiar şi identificatori care mai sunt folosiţi în acelasi program ca nume de variabile, clase, metode etc., fară a se crea prin aceasta confuzii, deoarece compilatorul face distincţie între etichete şi nume în funcţie de contextul în care acestea sunt utilizate.

Instrucţiunea break

Instructiunea break se poate folosi în corpul  unei instrucţiuni  switch, while, do..while sau for şi are ca efect ieşirea forţată (abruptă)   din structura de control în care se găseşte instrucţiunea respectivă.

Instrucţiunea continue

Instrucţiunea continue se poate folosi numai în corpul ciclurilor (while, do..while, for). Dacă instrucţiunea continue nu are etichetă, efectul este că se trece peste restul instrucţiunilor din corpul ciclului, începând din punctul în care se găseşte instrucţiunea  continue până la sfârşitul acestuia, dar se continuă executarea ciclului, adică se reia executarea corpului acestuia cât timp este satisfacută condiţia de continuare.

Tipul referinţă

În memoria maşinii 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 însuşi, ci o referinţă la acest obiect. Din această cauză, se consideră că variabilele referintă aparţin unui tip de date numit tip referinţă. Mulţimea de valori a acestui tip este mulţimea referinţelor, adică mulţimea locaţiilor (adreselor) din memoria dinamică. Operaţiile permise asupra datelor de tip referinţa sunt cele date de operatorii de atribuire (=), egalitate (==) şi inegalitate (!=) care au aceleaşi semnificaţii şi mod de utilizare ca pentru toate celelalte tipuri de date.

Clase, campuri, metodeClasa este o structură de date, asociată cu o colecţie de proceduri sau funcţii, metode, care utilizează datele din această structură. Datele unei clase se numesc câmpuri, sau variabile membre. Câmpurile pot fi statice (ale clasei) sau nestatice (ale instanţei). Când clasa este instanţiată, în memoria maşinii virtuale Java se construieşte un obiect (o instanţă a clasei respective). Obiectul conţine numai câmpuri nestatice.  Câmpurile statice se păstreaza în memorie într-un singur loc, care este rezervat clasei respective. Metoda este o funcţie, care întoarce o valoare şi poate avea, de asemenea, efect lateral. Ca şi câmpurile, metodele pot fi statice (ale clasei) şi nestatice (ale instanţei). Metodele statice pot invocă numai câmpurile statice ale clasei respective, în timp ce metodele nestatice pot invoca atât câmpurile statice, cât şi pe cele nestatice (ale unei instanţe 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 cărei valoare este valoarea întoarsă de funcţia respectivă. O astfel de invocare de funcţie poate fi deci folosită ca o componentă într-o altă expresie. De exemplu, expresia Math.sqrt(a) serveste pentru a calcula rădăcina patrată a lui a, în care scop este invocată funcţia sqrt, care este o metodă statică a clasei Math (clasa funcţiilor 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 instanţei) se face sub forma     referinţa_la_obiect.nume_metodă(parametri_efectivi)

14

deci numele metodei nu mai este calificat prin (însoţit 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 căreia îi aparţine 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 atât câmpurile (nestatice ale) obiectului indicat de referinţa r1, cât şi câmpurile (statice ale) clasei căreia îi aparţine acest obiect. Dacă o metoda are efect lateral, ea poate fi invocată şi sub forma de instrucţiune. Această instrucţiune 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 efectul lateral al metodei respective. Un exemplu cunoscut deja este instrucţiunea     System.out.println(sir);

Moştenirea şi polimorfismulMoştenirea este una din proprietăţile 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.

Fiecare clasă derivata moşteneşte câmpurile şi metodele superclasei. Aceasta înseamnă că toate câmpurile şi metodele existente în superclasă sunt utilizabile şi în subclasă, dar în aceasta din urmă pot exista, de asemenea, câmpuri ş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ă acelaşi nume şi aceeasi lista de parametri şi acelaşi tip de valoare întoarsă ca în superclasă, dar va avea un comportament diferit.

ConstructoriConstructorul este o procedură specială, prin care se construiesc obiecte dintr-o anumită clasă. Constructorul are întotdeauna acelaşi nume cu clasa . În schimb, o clasă poate avea mai mulţi constructori, care pot să difere între ei prin numărul şi/sau tipul argumentelor. Constructorul alocă în memoria dinamică spaţiul necesar pentru un obiect din clasa căreia îi aparţine şi iniţializează câmpurile acestui obiect cu valori care depind de argumentele sale.

Ierarhia de clase JavaÎn general, în programarea orientată pe obiecte este permisă moştenirea multiplă, adică o clasă poate avea mai multe superclase. În limbajul Java este permisă numai moştenirea 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 excepţie o constituie clasa Object, care este rădăcina  ierarhiei de clase Java şi nu are superclasă.

Pachetele de clasePrincipalele pachete de clase sunt:     java.lang - conţine clasele de bază necesare programării în limbajul Java;     java.io    - conţine clasele necesare pentru programarea operaţiilor de intrare/ieşire;     java.util  - conţine clase pentru anumite structuri de date tipice (listă, stivă etc) şi alte clase utile;     java.awt si javax.swing - conţin clase necesare pentru realizarea interfeţelor grafice;     java.applet - pentru programarea appleturilor.

Declaraţia import Pentru a putea utiliza într-un fişier-sursa Java un anumit pachet (subpachet) de clase, la începutul

fişierului respectiv trebuie pusă declaraţia     import nume_pachet.*; în care nume_pachet este numele calificat al pachetului respectiv. De exemplu, pentru a utiliza orice clase din pachetul java.io se pune declaraţia     import java.io.*;

15

Pentru clasele din pachetul java.lang nu este necesară o declaraţie de import , acestea fiind importate implicit. Pentru a importa numai o anumita clasă dintr-un pachet, se foloseste declaraţia     import nume_pachet.NumeClasa;

Pachetul java.lang

Pachetul java.lang conţine clasele fundamentale şi există pe orice platformă Java. Pentru acest pachet nu este necesară declaraţia import, clasele sale fiind importate implicit. Lista completă a claselor din pachetul java.lang şi descrierea lor se găsesc în documentaţia Java API de pe Internet.

Clasa ObjectClasa Object este rădăcina 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, instanţele clasei Object sunt obiecte oarecare, fără atribute precizate. Variabilele referinţă la Object se folosesc atunci când, la elaborarea programului, se consideră că lor li se pot da ca valori referinţe la orice fel de obiecte, indiferent de clasa căreia îi aparţin.

Î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 acţiuni specifice acestor clase.

Metodele clasei ObjectClasa Object nu are date membre. În consecinţă, obiectele acestei clase nu au stare (cu excepţia faptului ce ele există sau nu). Clasa are un singur constructor, Object(), care nu are parametri. Obiectele acestei clase nu conţin date. În schimb, clasa dispune de un set de metode. Conform cu principiul moştenirii, 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)

Clase de exceptiiÎn pachetul java.lang există şi numeroase clase de excepţii. Instanţele acestor clase sunt creeate de către maşina virtuală Java atunci când se produce o excepţie, adică o situaţie anormală în procesul de calcul. Toate aceste clase sunt descrise în documentatia Java API. Vom menţiona aici numai două dintre ele, celelalte urmând să fie indicate la descrierea claselor care conţin metode care pot genera excepţii.  

În limbajul Java se face distincţie între excepţie şi eroare. Se consideră ca excepţiile 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 executării acestuia.

16

Clasa ExceptionAceastă clasă este rădăcina ierarhiei claselor de excepţii. În consecinţă, atunci când dorim ca in clauza catch sa fie captată orice fel de excepţie, scriem această clauză sub forma     catch(Exception e) {        instructiuni_de_tratare_a_exceptiei e     } unde e este numele simbolic (identificatorul) dat excepţiei captate. Clasa are doi constructori: public Exception()     creează un obiect din clasa Exception (deci "o excepţie") care nu conţine nici un mesaj. public Exception(String s)     creează un obiect din clasa Exception, care conţine un mesaj sub forma şirului s. Prin acest mesaj se indică, de regulă, ce incident a condus la generarea excepţiei respective.

Clasa Class

O caracteristică importantă a limbajului şi platformei Java este că clasele şi interfeţele utilizate în program sunt prezente în memoria maşinii virtuale Java în timpul executării programului, sub forma de instanţe ale clasei Class. În consecinţă, se pot obţine în timpul executării unui program informaţii despre clasele cărora le aparţin obiectele din memorie. Clasa Class nu are un constructor public. În schimb, putem obţine un obiect din această clasă folosind metoda getClass() a clasei Object. Există şi instanţe ale clasei Class pentru tipurile de date primitive. Acestea sunt conţinute sub forma de câmpuri statice în clasele acoperitoare ale tipurilor primitive respective.

Clasa system

Clasa System conţine câmpuri şi metode utile pentru realizarea legăturii dintre aplicaţie şi sistemul de execuţie Java (cel care implementează maşina virtuală Java). Această clasă nu poate fi instanţiată.

Câmpuri statice: Clasa System are trei câmpuri statice care reprezintă unităţile standard de intrare/ieşire 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 ieşirea standard a sistemului. De regulă este unitatea de afişare standard (ecranul) dar poate fi şi alt dispozitiv indicat de utilizator. Afişarea 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 ieşire pentru erori. De regulă este aceeaşi ca pentru obiectul out, dar poate fi şi alt dispozitiv indicat de utilizator.

Tablouri (Arrays)

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 colecţie indexată de variabile de acelaşi tip.

Tablouri cu un singur indiceAceste tablouri corespund conceptului matematic de vector. Nu le vom numi totuşi astfel, pentru a nu face confuzie cu obiectele clasei Vector din pachetul java.util.

17

Tabloul unidimensional este constituit dintr-un ansamblu de componente indexate (cu un singur indice), căruia i se asociază şi o variabila de tip int numita  length, care reprezintă lungimea tabloului (numărul de componente). Indicii elementelor de tablou sunt cuprinşi în intervalul  [0, length-1]. Utilizarea unui indice situat în afara acestui interval generează o excepţie.

Întrucât tablourile sunt obiecte, pentru indicarea lor în program  se folosesc variabile referinţă.

Tablouri cu doi indici

Tablourile bidimensionale din limbajul Java sunt o generalizare a conceptului de matrice,  În matematică, toate liniile unei matrice au acelaşi număr de componente, în timp ce în Java numărul 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 cărui componente sunt referinţe la tablouri cu câte un singur indice. Putem, deci, să ne imaginăm un "tablou coloană" care conţine în fiecare componentă o referinţă către 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ă numărul de linii. "Tipul tabloului" este, de fapt, tipul componentelor "liniilor" acestuia.

Tablouri cu mai multi indici

Modul de tratare al tablourilor cu doi indici poate fi extins şi la tablouri cu mai mulţi indici (tablouri multidimensionale). Se are în vedere ca tabloul cu  N indici conţine referinţe la tablouri cu N-1 indici. De exemplu un tablou cu trei indici (tridimensional) poate fi considerat că conţine 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 găseşte o anumită componentă. Un tablou cu patru indici poate fi asemănat 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 semnificaţii ale unor tablouri cu mai mult de patru indici. Totuşi, în practică, cele mai frecvent folosite tablouri au cel mult trei indici.

Declararea claselorPână în prezent, s-a arătat 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 declaraţii de clasă este următoarea:

   class NumeClasa {        declaratii_de_membri     } Observăm că declaraţia începe cu cuvântul-cheie class, urmat de numele clasei şi de corpul clasei, cuprins între acolade. Numele clasei este un identificator. Se obisnuieşte ca numele clasei sa înceapă cu literă majusculă. Dacă numele este compus din mai multe cuvinte, fiecaredin acestea începe cu majusculă. Corpul clasei cuprinde declaraţii de membri ai clasei respective. Acestea pot fi:     - declaraţii de câmpuri;     - declaraţii de constructori;     - declaraţii de metode. Nu este obligatoriu ca într-o clasă să existe toate aceste categorii de declaraţii. Pot exista, de exemplu, clase în care apar numai declaraţii de metode. În principiu, pot exista şi clase care conţin numai câmpuri şi nu conţin metode, deşi astfel de situaţii apar foarte rar în practică.

Declararea campurilor (variabile membre) Declaraţiile de câmpuri servesc pentru a descrie structura de date specifică clasei respective.

Câmpurile se mai numesc şi variabile membre şi pot fi ale clasei sau ale instanţei (ale obiectului). Se preferă denumirea de câmpuri, pentru a le deosebi de variabilele locale ale metodelor.

18

Câmpurile instanţei se declară la fel ca variabilele locale ale metodelor, numai că declaraţia respectivă nu apare în blocul unei metode, ci în corpul clasei.   De exemplu:     int m=172, n=2*m-4, r; Aceste câmpuri pot avea valori diferite pentru fiecare instanţă a clasei respective. În consecinţă, câmpurile instanţei sunt plasate în zona de memorie rezervată instanţei respective , astfel că ele sunt distincte pentru fiecare instanţă. Câmpurile clasei se numesc şi câmpuri statice. Declararea unor astfel de câmpuri se face asemănător cu cea a câmpurilor de instanţă, dar declaraţia are în faţă, în acest caz, modificatorul static. De exemplu:     static double u=3.65, v=2.87*u-3.1, x; La iniţializarea câmpurilor de instanţă se pot folosi atât valori ale câmpurilor statice, cât şi ale altor câmpuri de instanţă. În schimb, la iniţializarea câmpurilor statice se pot folosi numai valori ale altor câmpuri statice.

Declararea metodelorÎn programarea orientată pe obiecte, clasa conţine, în mod normal, nu numai câmpuri de date, ci şi metodele prin care se tratează aceste câmpuri. Sub aspect conceptual, metoda este o funcţie sau o procedură, care foloseşte drept date atât valorile argumentelor sale, cât şi câmpurile clasei căreia îi aparţine metoda respectivă.  

În principiu, deosebirea dintre funcţie şi procedură este că funcţia "întoarce" o valoare, în timp ce metoda nu întoarce o valoare, ci are numai efect lateral. O funcţie fără efect lateral este realizarea în program a conceptului matematic de funcţie ş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 funcţiile, dar se consideră că ele intorc o valoare specială numită void. Acesta este un artificiu pentru a indica faptul că o asemenea "funcţie" nu întoarce o valoare.

În limbajele de programare tradiţionale, o funcţie (sau procedura) foloseşte ca date argumentele sale şi variabilele globale. În limbajul Java nu există variabile globale şi nici funcţii independente (care să nu fie metode ale unor clase). În schimb, fiecare metodă poate folosi ca date atât argumentele saleşi variabilele locale, cât şi câmpurile clasei căreia îi aparţine metoda respectivă.

Cea mai simplă formă sintactică a declaraţiei de metodă este următoarea:     tip_valoare_intoarsa nume_metoda(declaratii_de_argumente) {        corpul_metodei     }

Instructiunea return

Dacă funcţia întoarce o valoare (diferită de void), aceasta se indică prin instrucţiunea     return expresie; Efectul acestei instrucţiuni este următorul: se evalueaza expresia expresie şi se încheie executarea funcţiei respective, întorcând valoarea astfel obţinută. În consecinţă, chiar dacă după instrucţiunea return mai apar în corpul funcţiei respective şi alte instrucţiuni, acestea nu vor mai fi executate. Dacă metoda nu întoarce o valoare (întoarce void), folosirea instrucţiunii return nu este absolut necesară, încheierea execuţiei făcându-se când se ajunge la acolada prin care se sfârseşte blocul funcţiei. Totuşi, dacă este necesar să se încheie în mod abrupt executarea corpului funcţiei, se poate folosi instrucţiunea return fără expresie.

Metode statice

19

La declararea metodelor statice, în faţa tipului valorii întoarse se pune modificatorul static. Metodele care conţin în declaraţie acest modificator se numesc statice sau ale clasei, spre deosebire de metodele obişnuite care sunt ale instanţei. În corpul metodelor statice se pot folosi numai câmpurile statice ale clasei respective şi se pot invoca numai alte metode statice ale acestei clase.

Metode cu acelasi nume. Signatura metodeiÎn aceeaşi clasă pot exista mai multe metode cu acelaşi nume, cu condiţia ca ele să difere prin numărul şi/sau tipul argumentelor. Pentru a deosebi între ele astfel de metode, s-a introdus conceptul de signatură. Signatura metodei constă din numele acesteia, însoţit de lista de argumente. În consecinţă, două metode pot avea acelaşi nume, dacă diferă între ele prin signatură

Transferul de parametri catre metodeLa invocarea unei metode, este necesar să se transmită de la metoda care invocă la metoda invocată parametrii (argumentele) acesteia. De exemplu, la executarea invocării Math.sin(a), este necesar să se transmită către metoda sin argumentul acesteia, a.  

În teoria şi practica programării se cunosc diferite moduri în car se poate face transmiterea argumentelor către o funcţie sau procedură:    - transmitere prin valoare: de la programul apelant către funcţie (procedură) se transmit valorile argumentelor;    - transmitere prin adresa: de la programul apelant către funcţie (procedură) se transmit adresele la care se găsesc în memorie valorile argumentelor;    - transmitere prin nume: de la programul apelant către funcţie (procedură) se transmit numele argumentelor;    - transmitere prin referinţă: de la programul apelant la funcţie (procedură) se transmit referinţe către argumente.

În limbajul Java, transmiterea parametrilor (argumentelor) metodelor se face prin valoare . Aceasta înseamnă că:     - dacă argumentul aparţine unui tip de date primitiv, se transmite chiar valoarea primitivă a argumentului respectiv;     - dacă argumentul aparţine unui tip-referinţă (este instanţă a unei clase), se transmite - de fapt - o referinţă către un obiect din clasa respectiva sau dintr-o clasa derivată din aceasta.

Consecinţa faptului că parametrii metodelor se transmit prin valoare este următoarea: chiar dacă în corpul unei metode se atribuie unui argument formal al acesteia o nouă valoare, această atribuire nu modifică valoarea argumentului efectiv corespunzător din programul apelant. Daca însă, în cazul unui argument-referinţă, nu se modifica referinţa însăşi, ci valorile câmpurilor obiectului indicat de către aceasta , modificarea respectivă se va transmite şi la programul apelant, constituind efectul lateral al metodei respective.

Metode recursiveO metodă (funcţie sau procedură) care se invocă pe sine însăşi se numeşte 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 arăta, de asemenea că, de regulă, aceleaşi funcţii pot fi calculate atât recursiv, cât şi iterativ (folosind cicluri). În general, în limbajele funcţionale se utilizează predominant funcţiile recursive, în timp ce în limbajele procedurale se prefera iteraţia, deşi în unele dintre ele (cum este şi limbajul Java) se pot folosi atât iteraţia, cât şi recursia. Remarcam că, la fel ca în cazul ciclurilor iterative, în metodele recursive trebuie să existe o condiţie de oprire a repetării. În caz contrar recursia ar continua până la depăşirea spaţiului de memorie alocat pentru memorarea datelor intermediare (numit stivă).

20

Comparând metodele recursive cu cele iterative se constată că:     - metodele recursive sunt "mai elegante", fiind şi mai uşor de inţeles de către om decât cele iterative;

    - din punct de vedere computaţional, metodele iterative sunt mai eficiente, deoarece solicită mai puţină memorie şi sunt mai rapide decât cele recursive. Deosebirea este cu atât mai mare, cu cât numărul de invocari succesive, respectiv de repetări, este mai mare.

Instructiunea throwCunoaştem deja că, la apariţia anumitor anomalii în executarea programului, maşina virtuală Java generează excepţii. Excepţiile 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 excepţii, folosind în acest scop instrucţiunea throw, care are forma următoare:     throw new ConstructorExceptie(lista_argumente); În limba engleză, throw este imperativul de la "a arunca".  În această instrucţiune, se foloseşte operatorul new pentru a genera un obiect al clasei de excepţii căreia îi aparţine 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 maşina virtuală Java care, în acest caz, opreşte execuţia programului.

Clauza throws

În mod normal, excepţiile 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 excepţiile generate în corpul ei. Pentru a indica această proprietate, la declararea metodei, după paranteza care conţine lista declaraţiilor argumentelor formale se pune clauza throws ClasaDeExceptii, în care se indică numele clasei excepţiei care este "aruncată" către metoda invocatoare (Cuvantul throws este persoana a treia singular a verbului to throw, "a arunca").

Clase publiceClasele publice sunt clase care pot fi utilizate şi în alte pachete, decât cel din care fac parte. Fiecare clasă publică se declară într-un fişier separat, care are obligatoriu acelaşi nume cu cel al clasei şi extensia java. În declaraţia de clasă, în faţa numelui clasei se pune modificatorul public.

Colectorul de reziduuri

Dacă un obiect nu mai este necesar, el poate fi distrus, adică eliminat din memorie. În maşina virtuală Java, există un colector de reziduuri de memorie  (engleză: garbage collector) care eliberează automat spaţiul de memorie ocupat de obiectele către care nu mai există nici o referinţă. în consecinţă, programatorul nu mai este pus în situaţia să prevadă explicit în program distrugerea obiectelor şi, deci clasele nu mai conţin destructori, ca în alte limbaje de POO.

Metoda finalize din clasa ObjectÎn clasa Object exista metoda     protected void finalize() throws Throwable Aceasta metodă este invocată de colectorul de reziduuri, atunci când acesta determină că nu mai există referinţe către 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 acţiuni necesare înainte de distrugerea obiectului respectiv. De exemplu, dacă obiectul respectiv a deschis anumite fişiere sau conexiuni externe, în metoda finalize se poate efectua închiderea lor.

21

Metoda finalize nu este  apelată explicit în programul de aplicaţie. Apelarea metodei finalize se face numai de către colectorul de reziduuri (garbage collector), dar nu imdeiat ce un obiect a rămas fără referinţă, ci abia atinci când acest obiect a "intrat în atenţia" colectorului. Este posibil ca executarea aplicaţiei să se incheie înainte ca "finalizarea" unor obiecte să aibă loc.

Caracteristicile obiectelor şi claselor: Încapsularea (encapsulation)

Î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 imaginăm obiectul ca fiind format din două straturi, ca în Figura 1.

Obiectul se comportă ca şi când ar avea doua "învelişuri": 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 atât de datele publice, cât ş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 atât 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 obţinute numai utilizand metode publice ale obiectului respectiv.

Încapsularea obiectelor prezintă avantaje importante în programare, deoarece măreşte siguranţa şi fiabilitatea programelor, prin eliminarea posibilităţii modificării 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 interfaţa acestuia cu "lumea exterioară". Este posibil ca două obiecte diferite să aibă interfeţe identice, adică să prezinte în exterior aceleaşi date şi metode. Datorită faptului că partea încapsulată diferă, astfel de obiecte pot avea comportament diferit.

Modificatori de acces pentru campuri si metode

În limbajul Java există trei modificatori de acces pentru câmpuri şi metode:   - private - pentru a specifica câmpuri sau metode private;   - public - pentru a specifica câmpuri sau metode publice;   - protected - pentru a specifica câmpuri sau metode protejate (care vor fi prezentate în secţiunea despre moştenire). Membrii privati ai claselor (câmpuri 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 câmpurilor sau metodelor nu se folosesc modificatori de acces, acestea sunt considerate vizibile numai din clasele care sunt situate în acelaşi pachet cu clasa căreia îi aparţin. În particular, pentru clasele declarate de către noi, aceste câmpuri şi metode sunt vizibile numai din clasele situate pe disc în acelaşi director. Se spune, în astfel de cazuri, că modul de acces este prietenos (engleză: friendly) sau de pachet (engleză: package).

Caracteristicile obiectelor şi claselor: Mostenirea

Moştenirea este o trăsătură fundamentală a programării orientate pe obiecte, conform căreia:     - dintr-o clasă se pot deriva alte clase. Dacă din clasa A este derivată clasa B, atunci A se numeşte clasă de bază, sau superclasă, iar B se numeşte clasă derivată, sau subclasă;     - subclasa mosteneste câmpurile şi metodele superclasei;

22

    - metodele superclasei pot fi redefinite în subclasă prin alte metode cu aceeaşi signatură;     - metodele statice ale superclasei pot fi ascunse în subclasă;     - câmpurile superclasei pot fi ascunse în subclasă prin câmpuri cu acelaşi nume dar care pot avea, eventual, alt tip.     - câmpurile unei clase pot fi ascunse chiar şi în metodele clasei respective, dacă aceste metode au argumente sau variabile locale cu acelaşi nume.

Caracteristicile obiectelor şi claselor: Polimorfismul

Polimorfismul (engleză: polymorphism) permite ca aceeaşi operaţie să se realizeze în mod diferit în clase diferite. Să considerăm, 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 moşteni, deci, de la aceasta metoda arie(). Este însă evident că aria cercului se calculează în alt mod decât aria patratului sau cea a triunghiului. Pentru fiecare din instanţele acestor clase, la calcularea ariei se va aplica metoda specifică clasei respective.

Caracteristicile obiectelor şi claselor: IdentitateaIdentitatea (engleză: Identity) se referă la faptul că datele sunt grupate în entităţi discrete, numite obiecte. Fiecare obiect din POO modelează starea şi comportamentul unui anumit 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 distincţie, 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 aceeaşi referinţă.

Agregarea (engleză: aggregation) este proprietatea obiectelor de a putea încorpora alte obiecte. Aşa dar, "datele" conţinute î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.

Caracteristicile obiectelor şi claselor: Clasificarea

Clasificarea (engleză: classification) este proprietatea obiectelor care au aceeaşi structură de date şi acelaşi comportament (aceleaşi metode) de a putea fi grupate într-o clasă. Clasa este o abstractizare, care conţine acele proprietăţi ale obiectelor, care sunt importante într-o aplicaţie sau într-o categorie de aplicaţii, şi le ignoră pe celelalte. De exemplu, în aplicaţii privind situaţia profesională a studenţilor, clasa Student conţine astfel de atribute ca numele şi prenumele studentului, facultatea, anul de studii, examenele promovate şi notele obţinute, dar ignoră atribute ca înălţimea, culoarea ochilor sau a părului, greutatea etc., care nu sunt necesare în aplicaţia respectivă. Spre deosebire de agregare, care este o relaţie între obiecte, clasificarea este o relaţie î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 însăşi o clasă. O astfel de ierarhie de clase este reprezentată în Figura 2.

Referintele this si super

În orice clasă pot fi utilizate două referinţe predefinite:     this - este o referinţă la "această" instanţă, adică la instanţa (obiectul) din care se face referinţa

23

respectivă;     super - este o referinţă la superclasă.

Declararea claselor derivate. Clauza extendsÎn declaraţia 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     } Amintim că în limbajul Java orice clasă are o superclasă şi numai una . Excepţie face clasa Object, care este rădăcina ierarhiei de clase. Daca lipseşte clauza extends, superclasa implicită este Object.

Declararea constructorului clasei derivatePentru a se da valori iniţiale câmpurilor superclasei, în declaraţia constructorului subclasei poate fi invocat constructorul superclasei prin instrucţiunea     super(lista_parametri_efectivi); unde lista parametrilor efectivi este cea a constructorului superclasei. Aceasta instrucţiune, dacă există, trebuie să fie prima instrucţiune din corpul constructorului clasei derivate. În lipsa ei, va fi invocat constructorul fără parametri al superclasei. Este posibil, de asemenea, ca într-un constructor să se invoce alt constructor al aceleeaşi clase, sub forma     this(lista_parametri_efectivi);

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ă. Când declarăm propriile noastre clase, avem şi noi posibilitatea să declarăm că unele din metodele lor sunt finale.

Clase finale

Dacă se doreşte ca o clasă să nu poată avea subclase, la declararea acesteia se foloseşte 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

Redefinirea metodelor nestaticeMetodele de instanţă (nestatice) ale unei clase pot fi redefinite în subclasele acesteia. Redefinirea unei metode se face declarând în subclasă o metodă având aceeaşi signatură cu una din superclasă. Atunci când se redefineşte o metoda protejată, modificatorul de acces al acesteia poate fi menţinut, sau poate fi transformat în public. În subclasă pot fi folosite, totuşi, şi metodele superclasei care au fost redefinite, dacă la invocarea acestor metode se foloseste referinţa super.

24

Ascunderea metodelor statice

Metodele statice nu aparţin instanţelor, ci clasei. Din această cauză, dacă într-o subclasă se declara o metoda statică cu aceeaşi signatură ca o metodă a superclasei, atunci se spune că metoda din subclasă o ascunde pe cea din superclasă (nu o redefineşte). Modul de lucru cu metodele ascunse este similar cu cel în care se lucrează cu câmpurile ascunse. Vom înţelege mai bine deosebirea dintre redefinire şi ascundere când vom studia polimorfismul

Ascunderea campurilor

Câmpurile declarate într-o clasă pot fi ascunse prin câmpuri cu acelaşi nume declarate în subclasă, chiar dacă acestea au tipuri diferite. Aceasta înseamna că, în mod normal, în metodele clasei se folosesc câmpurile declarate în clasa respectivă, şi nu cele cu acelaşi nume ale superclasei. În subclasă pot fi, totuşi, folosite şi câmpurile superclasei, dacă sunt calificate cu referinţa super.

Instanţierea clasei care conţine metoda main

Clasa care conţine metoda main este clasa principală a unei aplicaţii, deci este prima clasă care se încarcă în maşina virtuală Java la punerea în execuţie a aplicaţiei respective. În acelaşi timp, ea este o clasă ca oricare alta, care poate avea şi instanţe. Metoda main(), fiind statică, nu poate utiliza direct decât câmpurile statice şi metodele statice ale acestei clase. Totuşi, în metoda main() sau în alte metode, pot fi create instanţe ale acestei clase, putându-se astfel utiliza şi câmpurile şi metodele de instanţă ale acestora.

Clase abstracteClasele abstracte conţin în declaraţia lor modificatorul  abstract.  Clasele abstracte nu pot fi instanţiate. Remarcăm însa că pot exista clase care nu pot fi instanţiate deşi nu sunt abstracte, cum sunt, de exemplu, clasele care nu au decât constructori privaţi. Cu toate că clasa abstractă nu poate fi instanţiată, se pot declara variabile aparţinând unor clase abstracte. Acestor variabile li se pot da însa ca valori numai referinţe către instanţe ale unor subclase concrete. De exemplu, daca A este o clasă abstracta, iar B este o subclasă concreta a clasei A, atunci este corectă declaraţia     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 rândul lor, abstracte sau concrete. De exemplu, clasa abstractă FiguraPlana poate avea ca subclase clasele Cerc, Elipsa, Poligon etc.  

Din punct de vedere al progrămarii, clasa abstractă conţine cel puţin o metodă abstractă, adică o metodă pentru care s-a declarat numai antetul, fără să i se definească şi corpul. O clasă poate să conţină o metodă abstractă în mai multe moduri:      a/ în corpul clasei este declarată explicit o metodă abstractă;       b/ clasa mosteneşte de la superclasa ei o metodă abstractă, care nu este definita nici în corpul clasei curente;      c/ clasa implementeaza o interfaţă, dar nu defineşte una sau mai multe din metodele acesteia.  

Dacă apare o astfel de situaţie, iar clasa nu este declarată în mod explicit abstractă, se genereaza o eroare la compilare. 

25

Declararea unei metode abstracte:     - antetul metodei trebuie sa conţina modificatorul  abstract;     - corpul metodei se înlocuieşte prin caracterul ';' (punct şi virgulă).

Interfete

Interfaţa este o specificaţie care descrie metodele publice şi variabilele finale publice pe care trebuie sa le aibă o clasă care implementeaza interfaţa respectivă. Dacă o clasă implementează mai multe interfeţe, ea conţine toate metodele publice şi variabilele finale publice ale acestora.

Interfaţa nu este o clasă, dar poate fi utilizată de programator ca şi când ar fi o clasă abstractă. Se pot declara variabile referinţă la o interfaţă în mod asemănător cu declararea variabilelor referinţa la obiecte aparţinând unei clase, adică sub forma:     interfaţa nume_variabila1[=initializare1], ..., nume_variabilaN[=initializareN];

Declararea interfetelorO declaraţie de interfaţă introduce un nou tip referinţă, ai cărui membri sunt câmpuri statice finale şi metode abstracte. În consecinţă, interfaţa se aseamănă cu o clasa abstractă pură, care nu conţine decât metode abstracte şi câmpuri 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 conţine şi câmpuri de date şi metode concrete şi este descendentă a clasei Object). Deşi nu se încadrează în ierarhia claselor, interfeţele se pot constitui in diverse ierarhii de interfeţe, aplicându-li-se principiul mostenirii. O clasă poate implementa mai multe interfeţe. Cel mai important avantaj al folosirii interfeţelor este că mai multe clase, de pe diferite ramuri ale arborelui ierarhic al claselor, pot fi "văzute" printr-o singură interfaţă. Se pot declara variabile referinţă la interfaţă la fel cum se pot declara variabile referinţă la clasă. Interfaţa este abstractă şi deci nu poate fi instanţiată. În schimb, unei variabile referinţă la interfaţă i se pot atribui ca valori referinţe la obiecte din orice clasă care implementează interfaţa respectivă . Declaraţia de interfaţă are forma generală următoare:  [public] interface NumeInterfata [extends lista_superinterfete] {            declaratii_de_membri_ai_interfetei           }

Clase imbricate si 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 ceilalţi 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 când utilizarea unei clase are sens numai în cadrul altei clase. Aşadar, prin imbricare se creează o legatură strânsa între două clase . Este posibil, desigur, ca o clasa să conţină mai multe clase imbricate. Remarcăm că declaraţia clasei imbricate este tratata ca oricare alta declaraţie de membru al clasei, putând avea şi modificatori de câmp (de exemplu static). Fiind membru al clasei, clasa imbricată are acces la toţi membrii clasei care o conţine, chiar şi la cei privaţi. Dacă clasa imbricată este statică, ea nu poate referi direct decât membrii statici ai clasei care o conţine. Clasa imbricată statică există, la fel ca şi câmpurile sau metodele statice, numai în cadrul

26

clasei care o conţine, nu şi în instanţele acesteia. În consecinţă, pentru a referi membrii acestei clase, se foloseşte pentru calificare numele clasei. Clasa interioară (clasa imbricată nestatică) are câte o instanţă în interiorul fiecărei instanţe a clasei care o conţine. În consecinţă, accesul la membrii ei se poate face folosind drept calificator referinţa la o instanţă. Clasa interioară are acces la toţi membrii clasei care o conţine, atât la cei statici, cât şi la cei de instanţă (nestatici).

Clasa java.awt.Component

Clasa Component este o clasă abstractă, derivată direct din clasa Object.  

Dintre numeroasele metode ale acestei clase, prezentăm aici numai câteva mai frecvent folosite:

    public boolean isVisible() - testează dacă această componentă este vizibilă, atunci când este vizibil şi containerul în care se găseşte;     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 afişată pe ecran;     public Point getLocation() - întoarce locaţia componentei (poziţia colţului din stânga sus în containerul-părinte) sub forma unei instanţe a clasei Point;     public void setLocation(Point location) - setează noua poziţie a componentei în cadrul containerului părinte;     public Dimension getSize() - întoarce dimensiunea componentei;     public void setSize(int latime, int inaltime) - setează noile dimensiuni ale componentei.

În aceste metode se utilizează şi clasele auxiliare Point şi Dimension din pachetul java.awt. Instanţele clasei Point conţin coordonatele unui punct. Se consideră că originea sistemului de coordonate se află în colţul din stânga sus, axa Ox este orientată către dreapta, iar axa Oy este orientata în jos. Instanţele clasei Dimension conţin dimensiunile componentei: lăţimea şi înălţimea.

Clasa JFrame

are o structură destul de complicată şi este descrisă complet în documentaţia Java.API. Pentru a nu intra de la început în detalii, vom da, deocamdată, numai cateva informaţii strict necesare pentru folosirea acestei clase, urmând să revenim ulterior cu indicaţii suplimentare.

Principalul constructor este:     JFrame(String titlu) unde titlu este titlul ferestrei.

Clasa JFrame are numeroase metode, atât proprii, cât şi moştenite de la superclasele ei. În afară de metodele moştenite de la clasa Component, deocamdată,  vom mai menţiona aici numai două, care sunt  moştenite 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, instanţa clasei JFrame nu este vizibilă. Pentru a o face vizibilă se foloseşte metoda public void setVisible(boolean visible) a clasei Component.

27

Clase de evenimenteClasele de evenimente se găsesc î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 rândul ei, extinde clasa java.util.EventObject din pachetul java.util. Orice eveniment conţine următoarele metodele declarate în clasa java.util.EventObject:     public Object getSource() - care întoarce o referinţă către obiectul care a generat evenimentul respectiv;     public String toString() - care întoarce o reprezentare sub forma de şir a obiectului. Orice eveniment AWT (generat de componente AWT sau JFC/Swing) conţine un câmp protejat de tip int numit id, a cărui valoare indică tipul evenimentului. Toate clasele de evenimente conţin câmpuri statice finale de tip int, al căror nume indică tipul de eveniment şi a căror valoare este valoarea corespunzătoare a câmpului id. Valoarea acestui câmp se poate obţine prin metoda     public int getId() Evenimentele pot fi de nivel coborât (low level event) sau semantice. Numele claselor de evenimente de nivel coborât indică fie componenta, fie dispozitivul de intrare care le-a generat, de exemplu: ComponentEvent, WindowEvent, MouseEvent, KeyEvent. Numele claselor de evenimente semantice indică mai curând tipul de eveniment, decât sursa acestuia, de exemplu: ActionEvent, TextEvent.

Interfete si clase adaptoare pentru ascultatori de evenimenteEvenimentele generate de surse, sunt captate şi tratate de ascultători. Sursele sunt componente ale interfeţei grafice care, de regulă, sunt preluate din pachetele de clase ale platformei Java 2, deci nu sunt programate de către programatorul de aplicaţie, ci doar utilizate de acesta. În schimb, programatorul de aplicaţie trebuie să creeze clasele de ascultători de evenimente specifice aplicaţiei pe care o dezvoltă. Metodele acestor clase trebuie sa reacţioneze la apariţia evenimentelor şi să execute acţiunile corespunzătoare, conform cu obiectivele aplicaţiei. În consecinţă, platforma Java 2 nu pune la dispoziţie clase ascultătoare predefinite, ci doar interfeţele pe care trebuie să le implementeze aceste clase, pentru a putea trata evenimentele pe care le recepţionează. Există câte o interfaţă de ascultător pentru fiecare clasă de eveniment. De exemplu, pentru ComponentEvent există interfaţa ComponentListener, pentru WindowEvent exista intefaţa WindowListener etc. Pentru a se uşura munca programatorilor, pentru unele interfeţe care conţin mai multe metode, se oferă şi prototipuri de clase care implementează interfaţa respectivă , numite adaptoare. De exemplu, clasa WindowAdapter implementează interfaţa WindowListener, clasa MouseAdapter implementează interfaţa MouseListener etc. Adăugarea ascultătoarelor la sursele de evenimente se face prin metode de adăugare corespunzătoare, existente în clasele de surse. De exemplu, pentru a se adăuga la o instanţă a clasei Window sau a subclaselor acesteia (de exemplu JFrame) un ascultător de evenimente de fereastră, în clasa Window există metoda   public void addWindowListener(WindowListener l)

Evenimente generate de o fereastraPentru a ne familiariza cu modelul de evenimente al platformei Java 2,   vom urmări 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 rândul ei, este derivată din clasa java.awt.Window. Evenimentele prezentate în această secţiune sunt generate de orice instanţă a clasei Window şi ale subclaselor sale. Evenimentele generate de fereastră sunt instanţe ale clasei WindowEvent şi sunt ascultate de instanţe ale unor clase care implementează interfaţa WindowListener sau extind clasa WindowAdapter. Toate aceste clase şi interfeţe se găsesc în pachetul java.awt.event.  

28

Metodele interfeţei WindowListener sunt următoarele:   public void windowOpened(WindowEvent e)- fereastra a fost deschisă   public void windowClosing(WindowEvent e)- fereastra se închide   public void windowClosed(WindowEvent e)- fereastra a fost inchisă   public void windowIconified(WindowEvent e)- fereastra a fost iconificată   public void windowDeiconified(WindowEvent e)- fereastra a fost deiconificată   public void windowActivated(WindowEvent e)- fereastra a fost activată   public void windowDeactivated(WindowEvent e)- fereastra a fost dezactivată

Terminarea aplicatiei la inchiderea ferestrei

Pentru ca la acţionarea butonului de închidere din colţul din dreapta-sus al ferestrei să se închidă nu numai fereastra respectivă, ci si aplicaţia, este necesar ca metoda windowClosing() a ascultătorului de fereastră să conţină 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.

Evenimente de mouseEvenimentele de mouse sunt instanţe ale clasei java.awt.event.MouseEvent şi sunt generate de către orice componentă a interfeţei grafice, atunci când asupra ei se acţioneaza cu mouse-ul.   Clasa MouseEvent este derivată din clasa java.awt.event.InputEvent. Evenimentele de mouse sunt intrarea cursorului de mouse într-o componentă sau ieşirea din aceasta, apăsarea unui buton de mouse sau eliberarea lui, efectuarea unui click de mouse (simplu sau multiplu) pe suprafaţa componentei, mişcarea mouse-ului. Pentru ascultarea evenimentelor de mouse se folosesc interfeţele java.awt.event.MouseListener, java.awt.event.MouseMotionListener şi javax.swing.event.MouseInputListener. Ascultătoarele de mouse se pot obţine, de asemenea, prin extinderea claselor java.awt.event.MouseAdapter, java.awt.event.MouseMotionAdapter şi javax.swing.event.MouseInputAdapter.  

În AWT se face distincţie între evenimentele de mouse discrete şi evenimentele care caracterizează mişcarea continuă a mouse-lui.     a/ Evenimente de mouse         - a fost apăsat un buton al mouse-ului (MOUSE_PRESSED);         - a fost eliberat un buton al mouse-ului (MOUSE_RELEASED);         - s-a făcut click de mouse, adică un buton al acestuia a fost apăsat şi eliberat imediat (MOUSE_CLICKED);         - cursorul mouse-ului a intrat într-o componentă (MOUSE_ENTERED);         - cursorul mouse-ului a ieşit din componentă (MOUSE_EXITED). Ascultarea acestor evenimente se face cu instanţe ale claselor care implementeaza interfaţa java.awt.event.MouseListener.     b/ Evenimente de mişcare a mouse-ului         - mouse-ul s-a mişcat pe suprafaţa componentei (MOUSE_MOVED);         - mouse-ul a fost "tras" pe suprafaţa componentei, adică a fost mişcat ţinând un buton apăsat (MOUSE_DRAGGED). Aceste evenimente sunt ascultate cu instanţe ale claselor care implementează interfaţa java.awt.event.MouseMotionListener.

29

Evenimente de tastatura

De câte ori se apasă sau se eliberează o tastă, componenta activă a interfeţei grafice generează un eveniment de tastă din clasa java.awt.event.KeyEvent. Acesta poate fi tratat cu un "ascultător de taste" care implementează interfaţa java.awt.event.KeyListener sau care extinde clasa java.awt.event.KeyAdapter.  

Se disting următoarele evenimente generate la acţionarea tastelor:   - a fost apasată o tastă (KEY_PRESSED);   - a fost eliberată o tastă (KEY_RELEASED);   - a fost "tipărit" un caracter, adică a fost apasată şi eliberată o tastă care transmite un caracter tipăribil (KEY_TYPED). Aceste situaţii pot fi detectate cu metodele corespunzătoare ale interfeţei KeyListener.

Evenimentul generat de tastă conţine, în afară de codul tastei acţionate, şi informaţii privind starea tastelor auxiliare Ctrl, Alt şi Shift în momentul producerii evenimentului respectiv. Aceste stări pot fi detectate cu metodele corespunzătoare ale interfeţei superclasei java.awt.event.InputEvent.

Adaugarea unei componente la fereastra principala a aplicatieiPână în prezent, am arătat că, atunci când folosim JFC/Swing, fereastra principală a aplicaţiei 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, câmpuri de text etc., sau pot fi containere, care conţin - la rândul lor - alte componente. Pentru realizarea acestor componente simple şi containere se folosesc clasele din pachetele java.awt şi javax.swing, care sunt descrise în documentaţia Java API. Adăugarea de componente nu se face direct la instanţele clasei JFrame. În JFrame există un Container (un obiect dintr-o subclasă a clasei Container) numit contentPane, la care se pot adăuga componente. O referinţă la acest Container se obţine prin metoda public Container getContentPane(), existentă în clasa JFrame. Adăugarea 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 conţinut în JFrame.

Managementul poziţiei componentelor (Layout Manager).

Gestionarul de poziţionare este o clasă care asigură poziţionarea şi redimensionarea automată a componentelor situate într-un container, atât la crearea containerului, cât şi la modificarea dimensiunilor acestuia. Orice gestionar de poziţionare implementează interfaţa java.awt.LayoutManager sau subinterfaţa acesteia java.awt.LauoutManager2. În cele ce urmează, vom studia cele mai larg utilizate clase de gestionare a poziţionării, existente în pachetele java.awt şi javax.swing.

30

Clasa BorderLayout

Începem cu această clasă, deoarece este gestionarul de poziţionare implicit pentru conţinutul instanţelor clasei JFrame. În acest caz, se consideră că suprafaţa containerului este imparţită î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 însăşi un container. Adăugarea de componente la container se face, în acest caz, folosind metoda add(componenta, BorderLayout.ZONA), unde componenta este referinţa la componenta adaugată, iar ZONA este una din cele cinci zone menţionate mai sus. Dacă se foloseşte metoda add(componenta), fără a indica zona, componenta respectivă este plasată implicit în zona CENTER, aşa cum s-a procedat în secţiunea precedenta, în exemplul din fişierul AdComp.java.

Clasa FlowLayout

Gestionarul de poziţionare java.awt.FlowLayout plasează componentele pe suprafaţa containerului una după alta, în ordinea în care acestea sunt adăugate, de la stânga la dreapta şi de sus în jos. Când s-a terminat o linie, se trece la linia următoare. Numărul de componente pe o linie depinde de lăţimea componentelor şi de lăţimea containerului în care sunt acestea plasate.

Este posibil să se specifice modul de aliniere a componentelor: la stânga, la dreapta sau la centru. Aceasta se face fie specificând alinierea ca argument al constructorului, fie invocând metoda     public void setAlignement(int align) în care argumentul align poate fi FlowLayout.LEFT, FlowLayout.RIGHT sau FlowLayout.CENTER.

Clasa java.awt.GridLayoutGestionarele de poziţionare din clasa java.awt.GridLayout plasează componentele în celulele unei grile rectangulare. În consecinţă, toate componentele de pe aceeaşi coloană sunt aliniate vertical. Clasa are doi constructori:     public GridLayout(int rows, int cols) - are ca argumente numărul de linii şi de coloane al grilei;     public GridLayout(int rows, int cols, int hgap, int vgap) - are în plus ca argumente spaţiul orizontal şi, respectiv, vertical între componente. Deşi în constructor se indică atât numărul de linii, cât şi cel de coloane ale grilei, în realitate numai numărul de linii este respectat, în timp ce numărul de coloane este practic ignorat. La stabilirea amplasării componentelor în container, dacă numarul lor total este mai mic sau egal cu cel de linii, toate componentele vor fi aşezate vertical, una sub alta. Dacă numărul de componente este mai mare decât numărul de linii, numărul de coloane se stabileşte automat, prin împărţirea numărului de componente la cel de linii, cu rotunjire în plus. Plasarea efectivă a componentelor în celulele grilei astfel creeate se face apoi de la stânga la dreapta şi de sus in jos, la fel ca în cazul gestionarului FlowLayout, dar respectând alinierea verticală şi orizontală impusă de grilă.

Clasa javax.swing.BoxLayoutGestionarul de poziţionare javax.swing.BoxLayout plasează toate componentele containerului pe o singură direcţie, care poate fi orizontală sau verticală. Constructorul clasei este     public BoxLayout(Container target, int axis) în care target este o referinţa la containerul ţintă (al cărui gestionar de poziţionare este creat), iar axis poate fi BoxLayout.X_AXIS sau BoxLayout.Y_AXIS şi indică direcţia (axa) după care vor fi plasate componentele.

Pozitionarea absoluta a componentelor in container

În general, este recomandabil ca pentru amplasarea componentelor în containere să se folosească gestionari de poziţionare. În acest fel se asigură modificarea automată a poziţiei şi dimensiunilor componentelor, atunci

31

când se modifică dimensiunile containerului. Există totuşi situaţii, în care se preferă ca poziţiile ş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 poziţionării, este posibil să se proiecteze şi interfeţe grafice în care poziţionarea componentelor se face folosind coordonatele şi dimensiunile absolute ale acestora. În acest scop:     a/ pentru a se indica faptul că nu se foloseşte un gestionar de poziţionare, se recurge la instrucţiunea:     setLayout(null);     b/ pentru stabilirea coordonatelor colţului din stânga sus şi dimensiunilor fiecărei componente se foloseşte metoda     public void setBounds(int x, int y, int width, int height); din clasa java.awt.Component. În acest mod, fiecare componentă este plasată în container cu colţul stânga-sus în punctul de coordonate (x,y)şi are dimensiunile date prin lăţimea width şi înălţimea 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 poziţiei şi dimensiunilor componentelor.

Poziţia şi dimensiunile astfel stabilite ale componentelor rămân neschimbate, chiar dacă se modifică dimensiunile containerului care le conţine.

Clasele Panel si JPanelPentru a poziţiona componentele în structuri mai complicate decât cele oferite de clasele de gestionare a poziţiei 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 instanţe ale claselor java.awt.Panel, javax.swing.JPanel şi javax.swing.Box.

Clasele Panel si JPanelClasa java.awt.Panel (panou) reprezinta cel mai simplu container, care este o suprafaţă dreptunghiulară fără bordură. Gestionarul de poziţionare implicit este FlowLayout, dar se poate pune oricare altul. Panourile sunt frecvent folosite pentru a plasa pe ele diferite componente, formând 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.  

Clasa BoxClasa javax.swing.Box are ca instanţe containere speciale, care nu pot folosi decât gestionarul de poziţionare javax.swing.BoxLayout. Orice incercare de a-i pune alt gestionar produce o eroare de execuţie din clasa AWTError. Într-un container din clasa Box, componentele pot fi amplasate numai pe o singură direcţie: orizontală sau verticală.  

Clasa dispune de metode statice pentru crearea de "casete" (instanţe 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 distanţarea 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 lăţime fixă, dar de înălţime variabilă;     public static Component createVerticalStrut(int height) - creeaza o "componentă ascunsă" de înalţime fixă, dar de lăţime variabilă;

32

    public static Component createGlue() - creaza o "componentă ascunsă" cu ambele dimensiuni variabile;

Combinarea adecvată de containere din clasa Box şi folosirea în acestea a diferitelor componente vizibile şi ascunse permite crearea de interfeţe grafice cu aspecte foarte diversificate.

Componentele din JFC/SwingPentru a realiza interfaţa utilizator grafică a unei aplicaţii folosind JFC/Swing, este necesar ca la fereastra aplicaţiei (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, câmpuri de text.   2. Componente de afişare needitabile: etichete, indicatoare, etc.   3. Componente de afişare editabile: zone de text, tabele editabile, selectoare de culori, selectoare de fişiere, arbori.   4. Containere: panouri, panouri glisante, etc

Clasa javax.swing.JComponentClasa abstracta javax.swing.JComponent extinde clasa java.awt.Container. In consecinţă, orice componenta Swing are şi caracteristici de container.  

Iată, ca exemplu, câteva facilităţi pe care le ofera orice JComponentă:   - posibilitatea de a-i ataşa componentei o "inscripţie volanta" (engleză: ToolTip), adică o inscripţie explicativă care apare când punem cursorul de mouse pe componenta respectivă, fără să apăsăm butonul. O astfel de inscripţie se ataşează 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);

Caracteristicile componentelor JFC/SwingFiecare componentă a interfeţei 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 instanţelor sale. În JFC/Swing programatorului i se pun însa la dispoziţie metode şi clase prin care poate modifica aspectul componentelor. Starea se poate modifica fie datorită acţiunilor utilizatorului, fie datorită invocării prin program a unor metode ale acesteia. În general, la modificarea stării componenta generează un eveniment, iar uneori   îşi schimbă şi aspectul. Comportamentul componentei este modul în care aceasta reacţionează atunci cînd se acţionează asupra ei de către utilizator sau când este invocată o metodă şi constă în modificarea stării şi a aspectului şi în generarea de evenimente. Componentele din JFC/Swing oferă programatorului unele facilităţi 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 adăuga la fiecare componentă a unui text explicativ volant (engleză: Tool Tip), care conţine indicaţii care apar când se pune cursorul mouse-ului pe componenta respectivă, fără a apăsa 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 supraînălţare, bordură care dă aspect de scufundare;

33

    - posibilitatea de a alege aspectul general al tuturor componentelor interfeţei grafice (engleză: Look and Feel).

Componente de control

Componentele de control sunt dispozitive de intrare virtuale, uşor de utilizat, prin intermediul cărora utilizatorul poate introduce anumite comenzi. Din această categorie fac parte butoanele, riglele ajustabile, listele, listele ascunse, meniurile şi câmpurile de text.

Butoane

Butoanele sunt obiecte grafice, al căror aspect este similar celor al butoanelor folosite în aparatura electronică şi electrică. Acţionarea butonului se face punând deasupra lui cursorul mouse-ului şi apasând 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.

Butonul obişnuit (cu o singură stare stabilă)

Butoanele obişnuite se realizează folosind clasa javax.swing.JButton, derivată din clasa javax.swing.AbstractButton, aşa cum am arătat în exemplele date în capitolul precedent. Butonul obişnuit are o singură stare stabilă, în care ajunge când este eliberat. Cât timp se ţine butonul de mouse apăsat deasupra lui, butonul se află în starea "apăsat" ("acţionat"). De fiecare dată când este acţionat, butonul generează un AcţionEvent şi un ChangeEvent. Când este eliberat, generează numai un ChangeEvent. Butonul generează de asemenea, ca orice altă componentă, evenimente de componentă, de mouse şi de tastă. Totuşi, în cazul butoanelor obişnuite, cel mai frecvent se folosesc evenimentele de acţiune (ActionEvent), care sunt ascultate de un ascultător de acţiune (ActionListener). Clasele Button şi JButton sunt specificate mai detaliat în Indexul de clase.

Butonul cu două stări stabile

Clasa javax.swing.JToggleButton este derivata din javax.swing.AbstractButton şi reprezintă butoane cu două stări 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.

Caseta de validare

Caseta de validare este un obiect de control cu două stări stabile. La fiecare click de mouse pe suprafata casetei de validare, aceasta trece dintr-o stare în cealaltă. În mod obişnuit, 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, când caseta se găseşte în starea "selectat". În starea opusă (deselectat), caseta este vidă. Imaginea casetei este insoţită şi de un text explicativ.

Butonul radioButonul radio este un buton cu două stări 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 ("apăsat") un buton al grupului, se deselectează automat cel care era selectat anterior.

34

În JFC/Swing, butoanele radio sunt realizate ca instanţe ale clasei javax.swing.JRadioButton,  care este derivată din clasa javax.swing.JToggleButton. Gruparea butoanelor se face folosind clasa javax.swing.ButtonGroup.

ListeÎn cazul interfeţelor utilizator grafice, se numeşte listă o componentă care conţine articole selectabile. Selectarea lor se face de către utilizator, prin click de mouse pe articolul respectiv. Lista poate fi cu selecţie simplă sau cu selecţie multiplă, după cum pot fi selectate simultan unul sau mai multe articole.

În JFC/Swing, listele se realizează ca instanţe ale clasei javax.swing.JList. Articolele din listă pot fi, în principiu, orice obiecte afişabile. La crearea listei, constructorului i se dă ca argument tabloul obiectelor pe care le va conţine lista. Ulterior este posibil să se adauge articole la listă, sau să se elimine.

Daca lista este mai lunga decât spaţiul de afişare disponibil, ea poate fi pusă pe un panou glisant, din clasa javax.swing.JScrollPane.  

Liste ascunseLista ascunsă este o listă din care se vede un singur articol (cel care este selectat), deci ocupa pe ecran spaţiu mult mai putin decât una obişnuită. 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 (rămâne vizibil), iar celelalte dispar. Într-o listă ascunsă nu este posibilă selecţia multiplă.

În JFC/Swing, pentru realizarea listelor ascunse se foloseşte clasa javax.swing.JComboBox

Rigla ajustabilăClasa javax.swing.JSlider oferă o componentă care are aspectul unei rigle prevăzute 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 asemănat cu cel al unui dispozitiv de ajustare continuă, cum este potenţiometrul din aparatura electronică.

La deplasarea cursorului, rigla generează evenimente din clasa javax.swing.event.ChangeEvent, care sunt ascultate cu o clasă care implementează interfaţa javax.swing.event.ChangeListener.

MeniuriLa fel ca listele sau butoanele radio, meniurile permit utilizatorului să aleagă una din mai multe opţiuni posibile. În JFC/Swing se disting două categorii de meniuri:   - meniuri cu bară, care pornesc dintr-o bară situată la partea superioară a ferestrei aplicaţiei;   - meniuri derulante (pop-up), care apar în poziţia în care se găseşte 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 conţină unul sau mai multe meniuri, care se realizează ca instanţe ale clasei javax.swing.JMenu. La rândul său, fiecare meniu poate conţine unul sau mai multe articole, care sunt instanţe ale claselor javax.swing.JMenuItem sau javax.swing.JCheckBoxMenuItem. Este însă posibil ca

35

un articol de meniu să fie el însuşi un meniu (din clasa JMenu). Dacă utilizatorul alege cu mouse-ul un aricol de meniu, sunt posibile deci două situaţii:   - acesta este un articol propriu-zis (un JMenuItem), în care caz opţiunea respectivă este selectată;   - articolul ales este el însuşi un meniu (un JMenu), în care caz noul (sub)meniu se desfăşoară şi căutarea continuă.

Meniuri derulante (pop-up)

Spre deosebire de meniurile cu bară, meniurile derulante sunt tratate ca nişte componente obişnuite, care pot să fie afişate prin program, atunci când este necesar. În JFC/Swing, meniurile derulante se realizează ca instanţe ale clasei javax.swing.JPopupMenu. În rest, meniul pop-up se comportă la fel ca un meniu cu bară.

Componente de afişare needitabile

Componentele de afişare needitabile sunt realizate ca instanţe ale următoarelor clase:

  - javax.swing.JLabel - pentru realizarea unor "etichete" în care pot fi afişate texte sau imagini, fără a putea fi editate de utilizator;   - javax.swing.JTooltip - pentru afişarea de "inscripţii volante", când 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 activităţi (de la 0% la 100%).

Componente de afişare editabile

Componentele de afişare editabile permit utilizatorului operaţii de editare în timpul executării programului. În JFC/Swing există un număr 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 aceeaşi 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 fişiere), 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 recomandăm folosirea documentaţiei indicate.

Utilizarea ferestrelor de dialogFerestrele de dialog sunt ferestre care se afişează 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 când sunt necesare şi nu încarcă fereastra principală a aplicaţiei cu elemente care nu sunt necesare în permanenţă.  

În JFC/Swing, ferestrele de dialog se realizează folosind clasa javax.swing.JDialog. Instanţele acestei clase se comportă asemanator cu cele ale clasei JFrame, permiţând adăugarea oricăror componente. La fel ca la JFrame, aceste componente nu se adaugă direct la fereastră, ci la panoul contentPane conţinut în aceasta şi obţinut 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

36

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 afişarea 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, eliberând toate resursele pe care le foloseşte, se invocă metoda public void dispose(). Aceste trei metode sunt moştenite de JDialog de la superclasa java.awt.Dialog. Când 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. Când este afişată pe ecran o fereastră modală, toate celelalte ferestre existente pe ecran sunt blocate (nu se poate acţiona asupra lor), până când se încheie lucrul cu fereastra de dialog modală respectivă.

Clasa Color

Clasa Color încapsulează informaţiile despre culoare. În Java AWT se foloseşte modelul de culori RGB (engleză: red, green, blue) în care fiecare culoare este considerată ca fiind compusă din trei culori fundamentale: roşu, verde şi albastru. În consecinţă, culoarea este dată prin trei numere cuprinse în intervalul [0, 255], reprezentând ponderile celor trei culori fundamentale. În figura de mai jos este reprezentată schema de combinare a acestor trei culori fundamentale.

Prin modificarea ponderilor celor trei culori se pot obţine, î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 obţin diferite nuanţe 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 conţine şi un al patrulea câmp, 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 opacităţi intermediare, cuprinse intre 0 si 255.

Alegerea culorii folosind clasa JColorChooser

Pentru a alege culoarea în mod interactiv, în JFC/Swing este prevazută clasa javax.swing.JColorChooser. Instanţele acestei clase sunt panouri de selectare a culorii, care pot fi folosite atât prin încorporarea lor într-o fereastră obişnuită, cât şi sub forma unei ferestre de dialog.  

Pentru a creea o fereastră de dialog, care conţine î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 instanţa clasei JColorChooser care se întroduce în fereastra de dialog;   - okListener si cancelListener sunt ascultătoarele de acţiune care reacţioneaza la apăsarea butonului OK, respectiv Cancel al selectorului de culoare.

37

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, selectând culoarea prin alegerea cu mouse-ul a punctului de pe panou care are culoarea potrivita (trei butoane alăturate, notate H, S, B, arată care din cele trei componente se menţine constantă, celelalte două fiind date de coordonatele punctului ales pe panou).

Contextul grafic

Modul de realizare a imaginilor şi desenelor este strâns dependent atât de echipament (hardware) cât şi de sistemul de operare. Pentru a se asigura independenţa 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 suprafaţa componentelor grafice realizate pe diverse dispozitive fizice. Pe fiecare platformă, în mediul de execuţie Java, trebuie să existe o implementare a contextului grafic, adică o extindere a clasei Graphics, care conţine toate câmpurile şi metodele  acestei clase, dar este specifică platformei respective.  

Un obiect din clasa Graphics încapsulează informaţia de stare a contextului grafic la care se referă şi anume:       - referinţa la obiectul din clasa Component (sau dintr-o subclasa a acesteia) pe care se desenează;       - o translaţie a originii sistemului de coordonate; toate coordonatele din desen sunt raportate la această origine;      - decupajul curent (dreptunghiul în interiorul căruia se trasează desenul);       - culoarea curentă;      - fontul curent;      - operaţia logică pe pixeli curentă (XOR sau paint);      - alternarea curentă de culori pentru operaţia pe pixeli XOR. 

Originea sistemului de axe (punctul de coordonate 0,0) se găseşte în colţul din stânga-sus al dreptunghiului de desenare. Axa 0x este îndreptată spre dreapta, iar axa 0y - in jos.  

Practic, clasa abstractă Graphics conţine acele metode, care trebuie să existe în orice context grafic. Conţinutul concret al acestor metode, deci modul efectiv în care se realizează funcţiile respective, depinde de contextul grafic real, deci de dispozitivul fizic pe care se face desenarea şi de sistemul de operare folosit. Pe programatorul de aplicaţii sau miniaplicaţii în Java nu îl interesează însă acest lucru, deoarece el foloseşte în programele sale metodele clasei abstracte Graphics, fără să se preocupe de modul în care acestea vor fi executate. 

Fluxuri de intrare/ieşire şi fişiere

Introducere

În majoritatea aplicaţiilor, este necesar să se transmită date între diferite componente cum sunt: memoria internă, tastatura, ecranul, fişierele de pe disc, reţeaua de calculatoare etc. Poate fi necesar, de asemenea, să se transmită date între două aplicaţii sau între două fire de execuţie ale aceleeaşi aplicaţii. În limbajul Java, fluxul (engleză: stream) este o cale de comunicaţie între o sursă de date şi o destinaţie (Figura 1).

38

Fluxul este un concept situat pe un nivel înalt de abstractizare, fiind privit ca o simplă succesiune de octeţi sau de caractere care se transmite între sursă şi destinaţie . Nu prezintă importanţă nici natura sursei sau a destinaţiei, nici modul în care trebuie interpretată secvenţa de octeti sau de caractere respectivă.   De exemplu, un grup de 32 de octeţi transmişi între sursă şi destinaţie 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 ieşire şi de intrare. Pentru un proces dat, toate fluxurile transmise de acesta către exterior se numesc fluxuri de ieşire, iar cele primite din exterior se numesc fluxuri de intrare. În consecinţă, acelaşi flux este de ieşire în raport cu sursa şi de intrare în raport cu destinaţia.

Principalele operaţii care au loc asupra unui flux sunt:  

La sursă (flux de ieşire) La destinaţie (flux de intrare)

- Deschiderea fluxului - cât timp (există date de transmis)         scriere în flux -Închiderea fluxului

-Deschiderea fluxului - cât timp (există date de citit)         citire din flux -Închiderea fluxului

Pachetul java.io

În Java 2 SDK se consideră că fluxurile pot fi  de caractere sau de octeţi. În primul caz, de la sursă la destinaţie se transmite o succesiune de caractere Unicode (de câte 16 biţi), iar în al doilea caz - o succesiune de octeţi (de 8 biţi). În mod corespunzător, pentru fiecare din cele două categorii de fluxuri există câte o ierarhie de clase de fluxuri de intrare şi o ierarhie de clase de fluxuri de iesire. Pentru fluxurile de caractere, rădăcinile ierarhiilor de clase sunt clasele abstracte Reader şi Writer.Pentru fluxurile de octeţi, rădăcinile 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 menţionate, î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ă operaţiile de intrare sau de ieşire propriu-zise (culoare verde) şi   modelează sursele sau destinaţiile fluxurilor (engleză: Data Sink Streams);     - clase care efectuează unele operaţii de transformare a datelor de pe flux (culoare violet) şi reprezinta "fluxuri de prelucrare" (engleză: Processing Streams).

Clasa Reader

Clasa abstractă java.io.Reader este rădăcina ierarhiei de clase de fluxuri de intrare de caractere.

Metode:

    public int read() throws IOException - citeşte din fluxul de intrare un singur caracter; întoarce caracterul citit (în domeniul 0 .. 16383) sau -1 dacă s-a ajuns la sfârşit de fişier; metoda produce blocarea procesului în care este invocată, până când apare un caracter în fluxul de intrare;     public int read(char[] cbuf) throws IOException - citeşte din flux o secvenţă de caractere şi le depune într-o zonă tampon (buffer) constituită din tabloul de caractere cbuf; întoarce numărul de caractere citite sau -1 dacă s-a atins sfârşitul de fişier; metoda produce blocarea procesului până când apar caractere în fluxul de intrare, sau se ajunge la sfârşit de fişier;     public abstract int read(char[] cbuf, int off, int len) throws IOException - acţionează asemănător cu metoda precedentă, dar depunerea caracterelor citite în zona tampon de destinaţie se face începând de la poziţia off

39

(offset), iar numărul 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ă când apare cel puţin un caracter în fluxul de intrare; dacă se întâlneşte sfârşitul de fişier, se generează o excepţie de intrare/ieşire; întoarce numărul de caractere sărite 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ă poziţia curentă în fluxul de intrare, pentru a se putea reveni la ea ulterior; argumentul readAheadLimit indică numărul de caractere care vor putea fi ulterior citite din flux,fără ca acest  marcaj să se piardă; excepţia de intrare/ieşire apare dacă fluxul nu suportă marcarea sau dacă se produce altă eroare de intrare/ieşire;     public boolean markSupported() - indică dacă fluxul suportă marcarea;     public void reset() throws IOException - dacă fluxul a fost marcat, este readus la poziţia corespunzătoare ultimului marcaj; dacă fluxul nu a fost marcat sau nu suportă resetarea, se generează o excepţie de intrare/ieşire;     public abstract void close() throws IOException - închide fluxul; din acest moment, invocarea metodelor read(), ready(), mark() sau reset pentru acest flux va genera o excepţie de intrare/ieşire.

Clasa Writer

Clasa abstractă java.io.Writer este rădăcina ierarhiei de clase pentru fluxuri de ieşire de caractere.

Metode:

    public void write(int c) throws IOException - scrie în fluxul de ieşire caracterul c;     public void write(char[] cbuf) throws IOException - scrie în fluxul de ieşire caracterele conţinute în tabloul cbuf;     public abstract void(char[] cbuf, int off, int len) throws IOException - scrie în fluxul de ieşire len caractere din tabloul cbuf, începând de la poziţia 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, începând de la poziţia off (offset);     public abstract void flush() throws IOException - "descarcă" fluxul de ieşire; dacă fluxul a salvat într-o zonă tampon anumite caractere scrise cu metodele write(), aceste caractere sunt scrise efectiv în fluxul de destinaţie; dacă această destinaţie 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 ieşire; invocarea ulterioară a metodelor write() sau flush() pentru acest flux va produce o excepţie de intrare/ieşire.

Clasa InputStream

Clasa java.io.InputStream este rădăcina ierarhiei de clase pentru fluxuri de intrare organizate pe octeţi.

Metode:

    public int read() throws IOException - citeşte din fluxul de intrare un singur octet; întoarce octetul citit (in domeniul 0 .. 255) sau -1 dacă s-a ajuns la sfârşit de fişier; metoda produce blocarea procesului în care este invocată, până când apare un octet în fluxul de intrare;     public int read(byte[] buf) throws IOException - citeşte din flux o secvenţă de octeţi şi îi depune într-o zonă tampon (buffer) constituită din tabloul de octeţi buf; întoarce numărul de octeţi citiţi sau -1 dacă s-a atins sfârşitul de fişier; metoda produce blocarea procesului până când apar octeţi în fluxul de intrare, sau se ajunge la sfârşit de fişier;     public abstract int read(byte[] buf, int off, int len) throws IOException - acţionează asemănător cu metoda precedentă, dar depunerea octeţilor citiţi în tabloul de destinaţie byte[] se face începând de la poziţia off (offset), iar numărul maxim de octeţi citiţi este len;     public long skip(long n) throws IOException - se sare peste n octeţi din fluxul de intrare, care nu vor fi

40

citiţi; procesul apelant este blocat până când apare cel puţin un octet în fluxul de intrare; dacă se întâlneşte sfârşitul de fişier se generează o eroare de intrare/ieşire; întoarce numărul de octeţi săriţi efectiv;     public int available() throws IOException - întoarce numărul de octeţi disponibili pentru citire în fluxul de intrare;     public void mark(int readAheadLimit) throws IOException - marchează poziţia curenta în fluxul de intrare, pentru a se putea reveni la ea ulterior; argumentul readAheadLimit indică numărul de octeţi care vor putea fi ulterior citiţi din flux, fără ca acest  marcaj să se piardă; excepţia de intrare/ieşire apare dacă fluxul nu suportă marcarea sau dacă se produce altă eroare de intrare/ieşire;     public boolean markSupported() - indică dacă fluxul suportă marcarea;     public void reset() throws IOException - dacă fluxul a fost marcat, este readus la poziţia corespunzătoare ultimului marcaj; dacă fluxul nu a fost marcat sau nu suporta resetarea, se generează o excepţie de intrare/ieşire;     public abstract void close() throws IOException - închide fluxul; din acest moment, invocarea metodelor read(), ready(), mark() sau reset() pentru acest flux va genera o excepţie de intrare/ieşire.

Clasa OutputStream

Clasa java.io.OutputStream este rădăcina ierarhiei de clase pentru fluxuri de iesire de octeţi.

Metode:

    public void write(int c) throws IOException - scrie în fluxul de ieşire ultimul octet al numărului   c;     public void write(byte[] buf) throws IOException - scrie în fluxul de ieşire octeţii conţinuti în tabloul buf;     public abstract void(byte[] buf, int off, int len) throws IOException - scrie în fluxul de ieşire len octeţi din tabloul buf, începând de la poziţia off (offset);     public abstract void flush() throws IOException - "descarcă" fluxul de ieşire; dacă fluxul a salvat într-o zonă tampon anumiţi octeţi scrişi cu metodele write(), aceşti octeţi sunt scrişi efectiv în fluxul de destinaţie; dacă această destinaţie 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 ieşire; invocarea ulterioară a metodelor write() sau flush() pentru acest flux va produce o excepţie de intrare/ieşire.

Clasele PrintStream şi PrintWriter

Clasele java.io.PrintStream şi java.io.PrintWriter se folosesc pentru a transmite către un flux se ieşire date formatate pentru tipărire (afişare). 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, generând reprezentările datelor respective sub forma de şiruri de octeţi (caractere în codul ASCII) sau, respectiv, de caractere Unicode. Aceste clase nu se folosesc în mod independent, ci adaugă altui flux de ieşire (de octeţi sau, respectiv, de caractere) capacitatea de formatare a datelor în vederea tipăririi.  

Clasa PrintStream

Clasa PrintStream conţine doua feluri de metode de scriere a datelor: metodele cu numele write() scriu întotdeauna octeţi (fără formatare), în timp ce cele cu numele print() sau println() formatează datele, respectând convenţia de codificare (pe octeti sau pe caractere) specifică platformei pe care ruleaza aplicaţia respectivă. Totuşi, se recomandă ca pentru a obţine fluxuri de caractere să se folosească clasa PrintWriter. Deosebirea dintre print() şi println() este că metodele cu numele println() adaugă, la sfârşitul şirului de octeţi generat, un caracter de sfârşit de linie ('\n'). În consecinţă, dacă se foloseşte metoda print(), afişarea se face fără a se trece la o linie nouă, în timp ce dacă se foloseşte metoda println(), după

41

afişare se trece la linie nouă. Dacă fluxul este cu descărcare automată, metoda println() provoacă, de asemenea, descărcarea acestuia (flush).

Clasa PrintWriter

Constructori:     public PrintWriter(Writer out) - creează un nou flux de formatare pentru afişare, fără descărcare automată, conectându-l la fluxul de ieşire pe caractere out;     public PrintWriter(Writer out, boolean autoFlush) - la fel ca şi constructorul precedent, dar al doilea argument specifică dacă are loc descărcarea automată a fluxului;     public PrintWriter(OutputStream out) - creează un nou flux de formatare pe caractere, fără descărcare automată, conectându-l la fluxul de ieşire pe octeţi out; el creează şi un OutputStreamWriter intermediar, care face conversia caracterelor pe unul sau doi octeţi, dependent de platformă;     public PrintWriter(OutputStream out, boolean autoFlush) - la fel ca şi constructorul precedent, dar al doilea argument indică dacă se face descărcare automată a fluxului.

42