Sunteți pe pagina 1din 65

Cuprins

Cuprins ....................................................................................................................................... 1
INTRODUCERE........................................................................................................................ 2
Capitolul 1. Elementele de bază ale limbajului Java.................................................................. 8
1.1 Comentariile ..................................................................................................................... 8
1.2 Identificatori ..................................................................................................................... 9
1.3 Cuvinte cheie.................................................................................................................. 10
1.4 Literalii ........................................................................................................................... 11
1.5 Operatori......................................................................................................................... 13
1.6 Separatori ....................................................................................................................... 14
1.7 Tipuri şi variabile ........................................................................................................... 14
1.8 Declararea de variabile................................................................................................... 16
1.9 Folosirea tablourilor ....................................................................................................... 16
Capitolul 2 ................................................................................................................................ 19
2.1 Crearea unei aplicatii simple .......................................................................................... 19
2.1 Crearea unui applet......................................................................................................... 20
Capitolul 3 ................................................................................................................................ 21
3.1 Controlul executiei ......................................................................................................... 21
3.2 Siruri de caractere........................................................................................................... 23
3.3. Folosirea argumentelor de la linia de comanda............................................................. 24
Capitolul 4 ................................................................................................................................ 25
Obiecte si clase in Java............................................................................................................. 25
4.1 Crearea obiectelor .......................................................................................................... 25
4.2. Crearea claselor ............................................................................................................. 28
4.4 Membri de instanta si membri de clasa .......................................................................... 36
4.5 Clase imbricate............................................................................................................... 39
Capitolul 5 ................................................................................................................................ 47
Interfete .................................................................................................................................... 47
5.1. Ce este o interfata ? ....................................................................................................... 47
5.2. Implementarea unei interfete......................................................................................... 48
Diferente între o interfata si o clasa abstracta ...................................................................... 49
5.3 Mostenire multipla prin intermediul interfetelor............................................................ 49
5.4 Utilitatea interfetelor ...................................................................................................... 50
5.5 Crearea grupurilor de constante ..................................................................................... 51
5.6 Transmiterea metodelor ca parametri (call-back) .......................................................... 51
Capitolul 6 ................................................................................................................................ 52
Exceptii..................................................................................................................................... 52
6.1 Ce sunt exceptiile? ......................................................................................................... 52
6.2 "Prinderea" si tratarea exceptiilor................................................................................... 56
6.3 "Aruncarea" exceptiilor.................................................................................................. 58
6.4 Ierarhia claselor ce descriu exceptii ............................................................................... 59
6.5 Exceptii la executie (RuntimeException)....................................................................... 59
6.6 Crearea propriilor exceptii ............................................................................................. 60
Capitolul 7 ................................................................................................................................ 62
Pachete ..................................................................................................................................... 62
7.1 Crearea unui pachet ........................................................................................................ 62
7.2 Pachetele JDK ................................................................................................................ 64

1
INTRODUCERE
Java este un limbaj orientat pe obiecte. Trecerea de la alte paradigme de programare la
programarea orientata pe obiecte poate să fie dificilă. Java se bazează pe crearea de obiecte
care pot fi construite şi manipulate de către program. Ca şi alte limbaje , Java oferă suport
pentru scrierea şi citirea datelor de la diferite echipamente de intrare / ieşire. Java foloseşte
procese care măresc eficienţa intrărilor si ieşirilor, facilitează internaţionalizarea . Java are
posibilitatea de a lucra automat cu dealocarea memoriei adică nu este nevoie să urmăreşti
pointerii în memorie şi să faci dealocare manuală a memoriei. Această facilitate înseamnă că
un program este mai puţin vulnerabil sa se blocheze şi memoria nu poate fi intenţionat
gestionată necorespunzător.
În doar câteva luni , Java s-a mutat de la laboratoarele Sun Microsystems in centrul
scenei Word Wide Web. Niciodată înainte un limbaj de programare aşa de simplu nu a
generat intr-un timp foarte scurt aşa multă atenţie şi a captivat imaginaţia a aşa multor
programatori şi a utilizatori de calculatoare. Experţii in programarea Web consideră că Java
este cel mai semnificativ lucru care s-a dezvoltat pentru Web.
De ce Java a făcut senzaţie aşa repede ? Un răspuns ar fi că Java este independentă de
platformă şi are potenţialul să transforme Web-ul într-un mediu mult mai interactiv şi
dinamic. Alte motive ar fi că Java seamănă cu C şi C++ şi suporta populara programare
orientată pe obiecte , astfel muţi programatori cunoscători de C şi C++ au reuşit rapid să
stăpânească facilităţile puternice din Java
În continuare se vor pune bazele limbajului Java şi se arată de unde a apărut acest
limbaj şi încotro se îndreaptă. Este important de studiat Java prin prisma unui programator
C++ deoarece sintaxa şi facilităţile orientate pe obiecte sunt foarte asemănătoare.
Înainte de Java programele erau construite să ruleze sub un singur sistem de operare şi
provocarea era să se creeze programe care rulau cât mai rapid posibil. Aproape peste noapte
Java şi World Wide Web –ul au schimbat această noţiune de sisteme de operare – limbaje
bazate pe un mediu în noţiunea de platformă independentă şi limbaje pentru reţea şi sisteme.
Java reprezintă schimbarea majoră care a avut loc în industria de calculatoare. Limbaje
ca Java au mutat radical graniţa de la computere locale la servere care furnizează programe
utilizatorului.
Programatorii au acceptat aşa rapid Java deoarece oferă tot cea ce este necesar la un
limbaj modern si anume :
- facilităţi orientate pe obiect
- execuţie concurentă a proceselor (multithreadhing)
- managementul automat al memoriei
- facilităţi de lucru în reţea şi securitate
- independenţa de platformă (arhitectura neutră)
- facilităţi de lucru în Intenet / Web

Limbajele populare ca C++ şi Smalltalk au împins de ani de zile programatori departe


de programarea structurată top-down spre programarea orientată spre obiect mult mai flexibilă
şi adaptabilă. Java contribuie mult la această evoluţie şi chiar îmbunătăţeşte câteva neajunsuri
ale limbajului C++.
Ceea ce este remarcabil la Java este faptul că pentru prima oare se poate realiza soft de
reţea robust inter-platforme pentru Internet.
Se poate observa limbajul Java în acţiune în paginile din Web browsere care conţin
applet-uri Java. Limbajul Java poate fi folosit şi pentru a scrie aplicaţii. Applet-urile sunt
incorporate in pagini Web folosind un tag HTML special <APPLET> şi sunt descărcate şi
rulate automat când sunt afişate paginile de către un browser cu Java . Acest proces este

2
similar cu afişarea a altor elemente cum ar fi grafica şi text dar diferenţa constă că un applet
procesează un conţinut executat dinamic in loc de date statice.
O aplicaţie Java în schimb arată asemănător cu un program în C++. Poate să ruleze
singură şi realizează diverse sarcini. Singura problemă este că la momentul actual Java este un
limbaj interpretat , şi de aceea programele scrise în Java necesită o Maşină Virtuală Java
pentru a fi executate. În viitor se preconizează dezvoltarea unor compilatoare care vor
permite ca aplicaţiile Java să ruleze mai rapid şi mai independent.

Platforma de dezvoltare Java

Pentru a rula applet-uri este nevoie după cum am spus de un Web browser care permite Java
sau se poate folosi utilitarul appletviewer distribuit cu Java Development Kit (JDK) de la
Sun. Pentru orice program scris în Java este nevoie de JDK deoarece oferă compilatorul
pentru compilarea applet-urilor Java o aplicaţie (javac) şi un interpretor (java) pentru a rula
aplicaţiile Java şi un debugger (jdbg). Majoritatea acestor programe rulează în linie de
comandă si sunt oarecum primitive.
Instrumentele din JDK cuprind :
- un compilator pentru limbajul Java care generează cod binar neutru arhitectural
- Maşina Virtuala Java care interpretează codul binar la rulare
- Un set de biblioteci de clase pentru a ajuta programatori Java să dezvolte aplicaţii.
Câteva din aceste biblioteci includ instrumente pentru interfaţă, I/O, crearea de
applet-uri, lucru în reţea, etc
- Un mediu Java pentru execuţie care suportă verificarea codului binar ,
multithreading şi dealocarea memoriei
- Un debugger generator de documentaţie , etc

Puterea softului distribuit

Înaintea de Java , majoritatea inter –activităţii în Web se realiza folosind modelul


Common Gateway Interface ( CGI ) . Cel mai bun limbaj pentru realizarea de scripturi pentru
CGI a fost Perl . Modelul de lucru al CGI este complet unul client /server. De exemplu un
utilizator pe un computer client rulează un Web browser ca Firefox şi completează un
formular cu date şi trimite aceste date la server.. Severul citeşte si procesează aceste date şi
trimite un răspuns înapoi la client. Dezavantajul acestui mod de lucru este că cele mai multe
sarcini cheie sunt realizate de către un computer central – serverul. Si dacă serverul este
ocupat (ceea ce se întâmplă des in lumea Web), clientul trebuie să aştepte .
În lumea software -ului distribuit , reţelele sunt folosite pentru a trimite cod executabil la
computere client care sunt capabile să ruleze soft-ul local. Dea lungul anilor multe companii
de software de vârf au încercat să creeze un standard pentru a distribui conţinutul executabil.
Cele mi notabile încercări includ ShockWave de la Macromedia, WebObject de la NEXT şi
controale Microsoft ActiveX
Deci cu ajutorul applet - urilor se rulează cod distribuit prin reţea , descărcat şi
executat local. Se doreşte realizarea de aplicaţii are rulează în reţea deschizându-se astfel noi
posibilităţi atât pentru îmbunătăţirea divertismentului şi a softului de afaceri . Si cea mia buna
parte este că programatorii nu trebuie să mai scrie programe pentru mai multe platforme.
Acelaşi program scris în Java poate rula pe mai multe platforme care se pot conecta la reţea şi
au o Maşină Virtuală Java

3
Cele mai mari beneficii pe care software- ul distribuit le oferă faţă de abordarea client
server CGI sunt :
Realizarea de Interfaţă Web Interactivă . Cu applet-uri Java se pot crea pagini Web care
permit mutarea obiectelor pe ecran , vizualizare de animaţii , facilităţi multimedia ca sunetul
şi muzica .
Utilizarea resurselor Locale. Cu modelul CGI , serverul este limitat la procesarea datelor
care ii sunt transmise. Cu Java se pot scrie aplicaţii care pot cu adevărat să profite de resursele
dintr-un sistem local.
Acces îmbunătăţit la Internet. Una dintre problemele Web-ului şi a Internet-ului este că
informaţiile sunt depozitate într-un mod haotic peste tot în lume. Folosind Java se pot scrie
programe de interfaţă cu Web-ul mult mai bune , cum ar fi motoare de căutare şi se poate
îmbunătăţii accesul la Web.
Reducerea costului şi distribuirii de software. Industria soft-ului s-a transformat într-o
afacerea în care computerele rulează doar programe majore de la companii gigant . Unul
dintre motivele pentru care s-a produs acest lucru este că dea lungul anilor a crescut riscul şi
costul de producere şi distribuţie a soft-ului. Cu softul distribuit , utilizatorii pot să obţină şi
să descarce softul de care au nevoie nu fiind necesar să îl cumperi de la magazin

Securitatea în Java
Cu oportunităţile şi promisiunile software - ului distribuit vine şi riscul securităţii.
Programele care rulează pe calculatoare locale sunt acele pe care utilizatorul a decis sa le
cumpere sau să le descarce . Odată instalate pot fi verificate de viruşi şi şterse daca cauzează
probleme sistemului. Programele distribuite cum sunt şi applet - urile Java se află pe
calculatorul altuia. Când sunt rulate de fapt se descarcă cod din alt calculator la care nu ai nici
un control. Din fericire filozofia avută în vedere la proiectarea Java este securitatea. Codul
binar (bytecode) care este descărcat din reţea este trimis unui verificator de cod binar care
încearcă să elimine codul defectuos care ar putea afecta un calculator local. Deoarece Java nu
foloseşte pointerii sau rutine programabile de alocare a memorie codul Java este puţin
probabil să blocheze un calculator datorită unei operaţii de alocare greşită a memoriei.
Pentru a mări securitatea Java dispune de clase care verifică conflictele legate de
securitate. Ca măsură finală Java permite utilizatorului configurarea detaliată a securităţii. De
exemplu un utilizator poate să specifice exact ce directoare poate sa scrie sau să citească un
applet.

Java şi C++

Java este foarte asemănătoare cu limbajul C++. Dacă se dispune de cunoştinţe de C++
migrarea spre Java va fi uşoară. Dacă există cunoştinţe de începător atât pentru C++ şi Java
trebuie să ajungi să înţelegi natura orientată pe obiecte a limbajului Java.

Sumar la orientarea pe obiecte

Pentru început să vedem câteva probleme cheie a programării orientată pe obiecte. În primul
rând , C++ nu este un limbaj orientat pe obiecte (OO) „adevărat “ dar Java este mult mai
aproape de acest lucru. Aceasta deoarece totul în Java este o clasă şi toate apelurile de metode
sunt făcute prin invocarea unei metode a unui obiect dintr-o clasă Java. În C++ se pot folosi
funcţii de sine – stătătoare , fişiere header, variabile globale etc. Singurul lucru care nu se
găseşte în clasă în Java este interfaţa . Oricum interfeţele sunt folosite ca şi clasele dar fără
implementare.

4
Această natură strictă a OO înseamnă că nu se poate converti cod C++ foarte uşor.

Ce lipseşte ?

Unul din scopurile creatorilor Java a fost să studieze toate celelalte limbaje de
programare şi să scoată cele mai bune facilităţi din fiecare. Sintaxa adoptată pentru limbajul
Java este importată din limbajul C/C++ . Multe din facilităţile limbajului C++ nu au fost
implementate din motive de securitate deoarece limbajul Java este destinat Web-ului Alte
facilităţi au fost omise deoarece erau prea dificil de utilizat sau erau nefolositoare.

Cele mai importante facilităţi omise sunt :

Eliminarea pointerilor

Aritmetica pointerilor este cel mai mare blestem pentru cei care urăsc C++. Pentru cei puţin
dintre programatori care stăpânesc pointerii, vă salutăm. Pentru restul dintre noi, bine c-am
scăpat. Principalul motiv pentru care pointeri nu sunt folosiţi în Java este securitatea. Dacă
applet-urile Java au posibilitatea să acceseze memoria direct , ar putea să cauzeze foarte uşor
probleme grave. Sunt câteva sarcini care necesită pointeri . Dar datorită faptului că în Java nu
există trebuie găsite posibilităţi de a trata aceste lucruri. În Java obiectele sunt transmise ca
argumente direct in loc să se folosească transmiterea unui pointer la obiect . Trebuie de
asemenea să foloseşti indici ca să utilizezi tablouri decât să acceseze valori direct.

Eliminarea fişierelor header

Utilizatorii de C++ consideră că fişierele header sunt foarte folositoare. Cu toate acestea dacă
se observă mai îndeaproape la modul cum folosesc majoritatea programatorilor fişierele
header se va observa că cea mai mare utilizare a fişierelor header este pentru documentare şi
prototipare. Pentru a examina interfaţa unei funcţii se examinează fişierul header. Prin simpla
examinare a hederului unei clase din C++ se poate distinge mult despre cea ce face o clasă
fără să se vadă nimic din implementare.
În Java nu se poate realiza acest lucru din vreme ce implementarea pentru clasă şi
metode trebuie să se realizez în acelaşi loc. În Java implementarea întotdeauna urmează după
declaraţie. Bineînţeles că se poate documenta codul cu comentarii dar codul poate să fie pe
mai multe pagini. Nu este întotdeauna uşor să te uiţi la codul unei clase Java şi să înţelegi ce
face . Se pune întrebarea de ce Java nu foloseşte headere . În primul rând nu este posibil să
foloseşti o bibliotecă care declară o metodă dar care nu o implementează. În al doilea rând
este mult mai dificil să programezi cu fişiere care nu sunt sincronizate cu implementarea

Eliminarea moştenirii multiple

Adesea în programarea orientată pe obiecte , un obiect are nevoie să moştenească


funcţionalitatea a una sau mai multe clase . În C++ acest lucru este realizat cu ajutorul
moştenirii multiple , o tehnică care permite unei clase să moştenească atâtea clase de câte are
nevoie. Moştenirea multiplă poate fi extrem de complicată şi este una din cauzele erorilor în
programele C++ (şi a sinuciderii programatorilor ) . Răspunsul la moştenirea multiplă în cazul
Java sunt interfeţele . Interfeţele sunt singurele chestiuni din Java care nu sunt clase . Sunt

5
simple şabloane pentru o clasă să le urmeze. Ele conţin declaraţii metodelor fără
implementare . orice clasă care implementează o interfaţă trebuie să folosească metodele
declarate în interfaţă.
Interfeţele funcţionează bine, dar au câteva limitări. Cel mai mare neajuns este ca
trebuie să scrie cod pentru fiecare metodă pe care interfaţa o declară. Moştenirea multiplă în
C++ permitea să se suprascrie metodele pe care le doreşti şi apoi poţi să foloseşti
implementarea părinte pentru alte scopuri . Interfeţele sunt mult mai uşor de înţeles şi folosi
decât moştenirea multiplă. Cu o strategie de programare corectă se poate obţine aproape toată
funcţionalitatea moştenirii multiple . Şi cu speranţa că nu vor fi toate problemele.

Ce este nou ?

De vreme ce Java se presupune că este următorul pas în evoluţia limbajelor de


programare, se aşteaptă câteva avantaje. Majoritatea noilor facilităţi se axează pe securitate şi
realizarea programării cât mai uşor

Colectarea informaţiei inutile

Atunci când se termină folosirea unei resurse în C++, trebuie explicit să ii spui la calculator
când să elibereze memoria care o foloseşte. Acest lucru se realizează cu pointeri. Din
moment ce Java nu foloseşte pointeri din motive de securitate , are nevoie de un mod de a
curăţa resursele când nu mai sunt necesare . Aici intervine colectarea informaţiei inutile.
Colectarea informaţiei inutile este un mediu fir de execuţie (thread ) în momentul
rulării (run -time) care menţine o evidenţă a toate părţile programului şi automat dealocă
memoria folosită când aceasta nu mai este necesară . De exemplu atunci când se declară o
variabilă memoria este alocată pentru a putea stoca valoare ei. Motorul colectării de
informaţie inutilă observă cu ce scop este folosită variabila de către program. Când programul
nu mai foloseşte variabila este ştearsă.
De exemplu avem următoarea secvenţă :
for (int x; x < 10; ++x)
System.out.println(x);

Întregul pe care îl folosim să număram până la 10 este de fapt declarat în interiorul buclei .
După ce bucla se termină spaţiul de memorie a variabilei x este curăţat şi se poate folosi de
câtre altcineva. Aceasta idee funcţionează la toate nivelele din cadrul mediului Java.

Securitatea

Securitatea era o problemă cu care creatorii limbajului C++ nu trebuia să o rezolve – ei au


lăsato la îndemâna programatorilor individuali. Din moment ce Java este proiectată să fie un
limba de programare distribuit , securitatea este un principal interes. Java include multe
facilităţi pentru a ajuta în prevenirea problemelor de securitate. Eliminarea pointerilor a fost o
probleme cheie care a redus riscul securităţii. Funcţionalitatea care se pierde este recuperată
prin robusteţea aplicaţiilor şi a applet-urilor.

Excepţiile

6
Excepţiile nu sunt chiar noi – sunt folosite în C++. Oricum folosirea lor este dificilă în C++.
În java excepţiile sunt mult folosite. Excepţiile sunt condiţii de eroare care nu sunt aşteptate
de lungul cursului unei rulări standard a programului. Situaţii ca lipsa unui fişier va rezulta în
excepţii în Java. În Java, excepţiile sunt de fapt parte a limbajului; ele au clasele lor , interfeţe
, etc. În C++ excepţiile au fost o adăugare (add-on) care nu a fost niciodată pe deplin
implementată.

Siruri contra Tablori de caractere

În C++ şirurile sunt simple tablouri de caractere . În Java şirurile pot fi mânuite ca şiruri . Nu
sunt tipuri primitive de date dar este de fapt o clasă şi deci şirul este instanţiat ca un obiect.
Dece atunci când se mânuiesc şirurile de fapt se manevrează cu un obiect String care are
propriile metode. În loc să se apeleze metodele care acţionează asupra şirului (C++) . de fapt
sunt apelate metodele obiectului şir care acţionează asupra lui. Dacă se doreşte se poate folosi
un tablou de caractere ca un şir dar se va pierde facilităţile uşor de folosit construite n clasa
String.

Clasa Super

Daca a-ţi folosit C++ sunteţi familiari cu cuvântul chei this care este folosit pentru a face
referire la obiectul curent. Java implementează de asemenea operatorul this , dar mai adaugă
şi operatorul super, care ii spune la Java să găsească clasa care este extinsă de clasa noastră
curentă . Se poate folosi super pentru a face un apel explicit la superclasa clasei curente.

Modificatori noi

În C++ modificatorii sunt folosiţi foarte frecvent. Java prei mulţi din modificatorii
C++ şi adaugă alţii noi. Mulţi dintre noii modificatori sunt pentru a ajuta în problemele de
securitate.
Câţiva dintre modificatorii noi :

abstract - folosiţi pentru a definii clase şi metode care trebuie sa fie moştenite (subclasate)
syncronized – spune la Java că o metodă poate fi apelată de un obiect pe rând.
native – folosit pentru a crea apeluri câtre limbaje ca C
final – spune la Java că o clasă nu pot fi moştenită .

Operatorul instanceof

Operatorul instanceof este foarte folositor atunci când ai de-a face cu obiecte şi nu eşti sigur
de tipul lor.

7
Capitolul 1. Elementele de bază ale limbajului Java
În această parte se vor evidenţia conceptele fundamentale despre elementele
fundamentale de programare în Java.

Comentarii
Identificatori
Cuvinte cheie
Declaraţii de variabile

1.1 Comentariile
Comentariile sunt utile deoarece contribuie la realizarea uni program uşor de intreţinut,
modificat şi folosit. Dar adăugarea de comentarii unei aplicaţii după ce este gata nu este o
bună practică. Mai des decât se crede , după o perioadă de timp departe de program nu iţi vei
aminti ce face acel cod pe care chiar tu l- ai scris . Din nefericire mulţi programatori urmează
această tradiţie. De aceea se sugerează să se scrie comentarii în timp ce se realizează
programul.
Java suportă 3 tipuri de stiluri de comentarii. Primele două sunt preluate din C++. AL
treilea tip de comentariu este folosit pentru a crea automat clase şi metode de documentaţie.

Stilul de comentariu numărul 1


/* aici comentariu */

Acest stil de comentariu este folosit atunci când este nevoie de explicaţii pe mai multe linii .
Pentru a realiza acest lucru este nevoie de următorul set de simboluri /* şi */.

Exemplu :

/*
Acest program este scris de Vasi
Este cel mai deosibit program scris !
*/
while (i <= /* comentariul poate sa fie aici */ 10)
{
total += i;
i++;
}

Stilul de comentariu numărul 2

// aici comentariu

Acest tip de comentariu este terminat de sfârşitul liniei, nu se pot folosi linii multiple
doar dacă fiecare linie începe cu un dublu slash (/)

Exemplu :
// Acest program este scris de Vasi
// Este cel mai deosibit program scris !
while (i <= 10) // comentariu aici
{

8
total += i;
i++;
}
Stilul de comentariu numarul 2
/** comentariu documentaţie aici... */

Acest stil de comentariu este asemănător cu cel de la stilul 1 cu excepţia uni asterisc în
plus la început. Compilatorul Java ignoră şi acest tip de comentariu dar un program denumit
JAVADOC:EXE care vine odată cu pachetul Java Development Kit foloseşte aceste
comentarii pentru a construi documentaţie HTML care descriu funcţiile , clasele şi pachetele .

Exemplu
/**
* Welcome to HelloWorld
* @author Anthony Potts
* @version 1.1
* @see java.lang.System
*/
class helloworld {
/**
* Main method of helloworld
*/
public static void main(String args[]) {
System.out.println("Hello World!");
}
}

În fig se poate observa cum arată un fişier de documentaţie realizat cu JAVADOC al


programului de mai sus.

1.2 Identificatori

Identificatorul este numele pe care dvs preferaţi să denumiţi un element ( ca de exemplu


variabilă sau o metodã). Java va accepta oricare nume simbolic valabil, dar din motive
practice , este cel mai bine să se folosească un termen specific aplicaţiei şi nu litere sau
numere la întâmplare. Aceşti identificatori trebuie să încapă cu o literă a alfabetului sau cu
simbolul _ şi simbolul $. După primul caracter se pot folosi numere şi caractere. De
asemenea numele identificatorilor trebuie să fie diferite de cele ale cuvintelor cheie folosite în
limbajul JAVA

Câteva exemplu de nume de identificatori corecte :


Var1 $Dolari nrSuma _SALut2 Capitolul3 ABC123

Şi câteva exemple de identificatori invalizi :


3Pag #Buna -Principal

9
1.3 Cuvinte cheie

În Java există cuvinte cheie care sunt rezervate şi alcătuiesc vocabularul limbajului. . Aceste
cuvinte nu pot fi folosite ca nume de identificatori pentru clase, variabile, pachete etc.
Tabelul 1.1. conţine lista completă a cuvintelor cheie din Java

Tabelul 1.1 Cuvintele cheie din Java


Cuvînt cheie Descriere
abstract Modificator de clasă
boolean Tip de dată boolean
break Folosit pentru a întrupe bucle
byte Tipul de dată byte
cast Folosit pentru a converti tipurile de date
catch Folosit în mecanismul de detectare a erorilor
char Tipul de date caracter (16-bit)
class Folosit pentru a crea o structură de clasă
continue Folosit pentru a continua o operaţie
default Folosit cu instrucţiunea switch
do Folosit pentru a crea o structură de control do loop
Double Folosit pentru a defini tipul real in vigulă mobilă (64-bit)
else Folosit pentru a implementa ramura de elese dintr-o
instrucţiune if
extends Folosit pentru moştenire
final Folosit pentru a impiedica ca o clasă sa fie moştenită
Finally Folosit cu excepţiile ca ultima posibilitate înainte de ieşire
that Codul va fi executat dacă o excepţie apare sau nu
float Folosit pentru a defini tipul real in virgulă mobilă (32-bit)
for Folosit pentru a crea structura repetitivă for
if Folosit pentru a crea o structură de decizie if -then
implements Folosit pentru a asocia o interfaţă unei clase
import Folosit pentru a include pachete Java
inner Folosit pentru a crea blocuri de control
instanceof Folosit pentru a determina tipul unui obiect
int Tipul de date întreg (32-bit)
interface Folosit pentru a crea o structură de interfaţă
long Tipul de date întreg (64-bit)
Native Folosit pentru a executa cod extern
new Operator folosit la declararea unui obiect
null Referinţă la o valoare nulă
outer Folosit pentru a crea blocuri de control
package Folosit pentru a arata pachetele care sunt utilizate in
program

10
private Modificator pentru clase, metode şi variabile
protected Modificator pentru clase, metode şi variabile
Public Modificator pentru clase, metode şi variabile
Return Folosit pentru a seta valoare returnată pentru o metoda
short Tipul de date intreg (16-bit values)
static Modificator pentru clase, metode şi variabile
super Folosit pentru a face referire la clasa parinte
Switch Instrucţiune folosite pentru a alege dintr-o listă de opţiuni
synchronized Modificator pentru o metodă care arată că acea metodă
poate fi executată o singur dată la un moment dat
Împiedică mediul Java să apeleze metoda a doua oară
până când prima nu s-a terminat.
this Folosit pentru a indica (a referi ) obiectul curent
throw Instrucţiune care arată mediului Java ce excepţie să
apeleze în cazul unei erori
transient Modificator care accesează cod Java nou
try Operator folosit pentru a testa excepţii n cod
void Modificator folosit pentru a desemna metodele fără tip de
date pentru revenire.
volatile Modificator de variabilă
while Folosit pentru a crea o structură repetitiva while

1.4 Literalii

Simbolurile literale sunt valori care sunt atribuite atunci când se introduc valori explicite . De
exemplu la o atribuire ca aceasta :
i = 10;

valoarea 10 este un simbol literal.

Aceste simboluri sunt de trei tipuri: numerice , caractere, boolean. Simbolurile boolean sunt
doar True şi False.

Literali numerici

Numerele pot fi întregi sau reale în virgulă mobilă. Numerele întregi sunt reprezentate de
obicei în format zecimal dar se pot introduce şi numere în format hexazecimal. . Pentru a
putea introduce un număr hexazecimal trebuie să înceapă cu simbolul 0x sai 0X. Numerele
întregi sunt stocate diferit în funcţie de mărimea lor. Tipul int este folosit pentru stocarea a
numere întregi pe 32 de biţi cu valori între -2,147,483,648 şi 2,147,483,648. Dacă se doreşte
folosirea de numere mai mari există în Java tipul long care stochează valori pe 64 de biţi în
domeniul
- 9.223372036855e+18 la 9.223372036855e+18.
Pentru a specific ca un număr este de tipul long se adaugă la sfârşitul numărului litera “l” sau
“L”

11
Se dau câteva exemple cum se pot folosi simbolurile literale intregi pentru a atribui valori
instrucţiunilor Java :

int i;
i = 1;
i= -9;

i = 1203131;

i = 0xA11; // literal hexazecimal


i = 4.5; // ilegal deoarece un numar real nu poate fi atribuit unei
variabile de tip întreg

long lg;

lg = 1L; // număr întreg lung

lg = -9e15;
lg = 7e12;

Alt tip de simboluri literale numerice sunt numerele reale în virgulă mobilă. La fel ca şi
numerele întregi , valorile reale sunt reprezentate pe 32 de biţi şi 4 de biţi .

Exemple :

float f;

f = 1.3; // tipul float (32-bit)


f = -9.0;
f = 1203131.1241234;

double d;
d = 1.0D; // valoare stocată pe 65 de biti -
d = -9.3645e235;
d = 7.0001e52D;

Literali caractere

Al doilea tip de literali de care este nevoie sunt literalii caractere. Literalii caractere includ
caractere individuale si şiruri.
Caracterele individuale sunt delimitate de apostrof în timp ce şirurile de caractere sunt
delimitate de ghilimele . Caracterele individuale pot fi orice caracter din setul de caractere
Unicode. De asemenea mai exisă câteva combinaţii speciale de două caractere care nu se
afişează dar au un rol important. Tabelul 1.2. arată aceste combinaţii speciale . Aceste
combinaţii sunt valabile şi pentru şiruri

Tabelul 1.2. Combinaţii de caractere speciale ăn Java

Combinaţie Utilizare Descriere


specială standard

\ <linie nouă> continuare


\n NL or LF linie nouă

12
\b BS Backspace
\r CR Carriage Return
\t HT Horizontal Tab
\\ \ Backslash
\’ ‘ apostrof
\” “ ghilimele
\xdd 0xdd Numar hexa
\ddd 0ddd Numar octal
\uddd 0xdddd Caracter Unicode

Exemple :
char ch;

ch = 'a';
ch = \n;
ch = \';
ch = \x30;

String str;
str = "Java string";

1.5 Operatori
Operatorii sunt folosiţi pentru a realiza calcule cu una sau mai multe variabile sau obiecte.
Operatori sunt folosiţi pentru a aduna variabile , compararea a două numere, atribuirea valori
unei variabile, incrementarea valori unei variabile, etc.
Tabelul 1.3. arată operatori folosiţi în Java .

Tabel 1.3 Operatori folosiţi în Java


Operator Descriere
+ Adunare
- Scadere
* Înmulţire
/ Impărţire
% Rest
++ Incremetare
— Decrementare
> Mai mare
>= Mai mare si egal
< Mai mic
<= Mai mic şi egal
== Egal
!= Diferit
! NU logic
&& SI logic
|| SAU logic
& SI pe bit

13
^ SAU Exclusiv pe bit
| SAU pe bit
~ Complement pe bit
<< Deplasare stanga
>> Deplasare dreapta
>>> Deplasare dreapta si inlocuieşte cifrele deplasate cu zero
= Atribuire
+= Atribuire cu adunare
-= Atribuire cu scadere
*= Atribuire cu înmulţire
/= Atribuire cu împărţire
%= Atribuire cu rest
&= Atribuire cu SI pe bit
|= Atribuire cu SAU pe bit
^= Atribuire cu SAU Exclusiv pe bit
<<= Atribuire cu deplasare stanga
>>= Atribuire cu deplasare dreapta
>>>= Atribuire cu deplasare dreapta si inlocuite cifrele deplasate cu zero

1.6 Separatori

Separatorii în Java sunt foloiţo pentru a delimit blocuri de cod. De e4xmplu acoladele
sunt folosite pentru a delimita implemntarea unei metode. Şi se utilizează parantezele pentru
a cuprinde lista de parametrii a unei metode.

Tabelul 1.4. Separatori folosiţi ăn Java


Separator Descriere
() Folosit pentru a defini blocuri de
argumente
[] Folosit pentru a defini tablouri
{} Definit pentru a cuprinde blocuri de cod
, Folosit pentru a separa argumente într-o
declaraţie
; Folosit pentru a termina o instrucţiune

1.7 Tipuri şi variabile

Variabilele sunt elemente care conţin informaţie în timp ce tipurile de date descriu ce
tip de informaţie este conţinut în element.
O variabilă trebuie să aibă un tip şi un identificator. Tipurile de date sunt byte, short,
int, long, float, şi double— apoi char şi boolean. Mai există şi tipul string care este de fapt
o clasă nu un tip de date.

14
Byte
Tipul byte poate fi folosit de variabilele care au nevoie de valori între-256 şi 255. Tipul byte
are lungimea de 8 biţi. Exemple de valori de tipul byte : -7 5 238

short
Tipul numeric short poate să stocheze valori între -32768 şi 32767. Are lungimea de 16 biţi.
Câteva exemple de valori : -7 256 -29524

Tabel Tipuri de date Java


1.1.
Tip de
Minimum negativ Maximum pozitiv
date
byte -256 255
short -32768 32767
int -2147483648 2147483647
long -9223372036854775808 9223372036854775807
float 1.40239846e-45 3.40282347e38
4.94065645841246544e-
double 1.79769313486231570e308
324
boolean False True

int
Tipul de date int foloseşte valori întregi cu semn pe 32 de biţi cu valori maxime şi minime de
până la 2 miliarde. Având această plajă de valori este cel mai folosit tip de date pentru întregi.
De obicei , acest tip se foloseşte abuziv chiar dacă programul nu are nevoie de întreaga
rezoluţie a tipului. Dacă se folosesc numere întregi mici este indicat să se folosească tipul de
date short . Regula de bază ar fi dacă se cunoaşte exact domeniul de valori a unei variabile se
va folosi cel mai mic tip de date posibil. Aceasta va permite programului să folosească mai
puţină memorie şi astfel va rula mai rapid, în special la maşinile cu RAM limitat. Câteva
exemple de valori de tip int : -7 256 -29523234 1321412422

long
Tipul de date log este cel mai puternic tip de date întreg. Foloseşte 64 de biţi de informaţie
pentru a stoca valori ajungând până la 9 milioane de trilioane. Dacă se începe să se utilizeze
multe asemenea variabile , sau doamne fereşte un tablou de tip long , se poate consuma o tonă
de resurse. Câteva exemple de valori long : -7 256 -29523234 1.835412e15 -3e18
float
Tipul float este unul din cele două tipuri de date folosite pentru a stoca valori în virgulă
mobilă.
Tipurile în virgulă mobilă din Java pot stoca numere gigantice.
Exemple
-7F 256.0 -23e34 23e100
double
Ca şi cum tipul float nu ar conţine destule valori , tipul double suportă un spaţiu de stocare şi
mai mare. Definiţia SUN a valorilor posibile pentru un double : “Valoarea finită diferită de
zero de tipul double este de forma s * m * 2e, unde s este +1 sau -1, m este un întreg pozitiv

15
mai mic decât 2^53 şi e este un întreg între -1045 şi 1000 inclusiv ”. Din nou, avem aici
numere cu adevărat monstruoase . Dar atunci când ai dea face cu programarea dură , acest tip
de date devine necesar din când în când, deci este necesar să îi înţelegem domeniul. Aici
avem câteva exemple :

-7.0D 256.0D -23e424 23e1000

boolean
Tipul boolean are propriile lui valori True şi False, şi nu corespund altor valori. Java nu
permite conversie între tipul boolean şi ale tipuri. Această limitare nu este absolută, există
metode de conversie pentru a elimina acest neajuns.

char
Tipul char este folosit pentru a stoca caractere individuale. Deoarece Java foloseşte setul de
caractere Unicode, tipul caracter trebuie să fie capabil să stocheze mii de caractere, de aceea
se folosesc întregi pe 16 biţi cu semn. Tipul caracter are posibilitatea să fie convertit la
aproape toate tipurile.

string
Tipul şir este de fapt o clasă de sine stătătoare şi nu este un tip primitiv de date. N acest fel
şirurile nu sunt limitate ele pot să se modifice în timpul programului acest lucru realizându-se
în interiorul clasei şi nu ne interesează cum este implementat.

1.8 Declararea de variabile

Declararea de variabile este asemănătoare cu declararea variabilelor în C/C++ atunci


când se folosesc tipuri de date primitive. Aproape orie în Java este o clasă - cu excepţia
tipurilor primitive de date. Aici avem o declaraţie standard pentru o variabile primitivă :

int i;

Tocmai am declarat o variabilă “i” să fie un întreg. Alte câteva exemple :


byte i, j;
int a=7, b = a;
float f = 1.06;
String name = "Tony";

1.9 Folosirea tablourilor


Este dificil de imaginat crearea unei aplicaţii mari fără să avem unu sau două tablouri. Java
foloseşte tablourile într-o manieră diferită de celelalte limbaje.
În loc să fie o structură care reţine variabile , tablourile în Java sunt de fapt obiecte
care pot fi tratate ca şi orice alt obiect din Java.
Cel mai puternic avantaj aici este ca deoarece tablourile sunt obiecte deci derivă dintr-
o clasă , ele au metode şi se pot apela pentru a primi informaţii despre tablou sau să
manipulăm tabloul.

16
Unul din neajunsurile la modul cum implementează Java tablourile este acela că există
doar tablouri de o singură dimensiune. Pentru a folosi tablouri cu mai multe dimensiuni este
nevoie să se creeze tablouri de tablouri. Acest lucru se realizează însă uşor şi lipsa suportului
pentru tablouri multidimensionale nu ar trebuie sa ne împiedice cu nimic.

1.9.1 Declararea tablourilor


Din moment ce tablourile sunt de fapt instanţe de clase (obiecte), noi avem nevoie să folosim
constructorii pentru a crea tablourile noastre. De reţinut că un tablou poate dor să stocheze un
singur tipe de date – nu se poate amesteca şiruri cu întregi într-un singur tablou. Aici avem
câteva exemple de cum se declară variabilele tablou.
int intArray[];
String Names[];

După cum se observă , acestea arată foarte asemănător cu declararea standard de


variabile , cu excepţia parantezelor drepte după numele variabilei. Se pot pune parantezele
drepte şi după numele tipului de date dacă în felul cesta declaraţia devine mai citeaţă

int[] intArray;
String[] Names;

1.9.2 Redimensionarea tablourilor

Există trei tipuri pentru a seta dimensiunea unui tablou. Două dintre ele folosesc operatorul
new. Folosirea operatorului new va iniţializa toate elementele tabloului la o valoare implicită.
A treia metodă implică umplerea elementelor tabloului cu valori în timp ce este declarat
tabloul.
Prima metodă implică preluarea uni variabile declarate anterior şi setarea dimensiunii
tabloului . Aici avem câteva exemple :

int intArray[]; // declară tablou


String Names[];
intArray[] = new int[10]; // dimnsionează tablou
Names[] = new String[100];

Sau se poate dimsniona atunci când se declară tabloul :


int intArray[] = new int[10];
String Names[] = new String[100];
În fine , se poate umple tabloul cu valori atunci când este declarat:
String Names[] = {"Tony", "Dave", "Jon", "Ricardo"};
int[] intArray = {1, 2, 3, 4, 5};

1.9.3 Accesul elementelor tabloului

Acum că şti, cum să iniţializăm tabloul , avem nevoie să învăţăm cum să umplem tabloul cu
date şi să accesăm elementele tabloului pentru a obţine date. Am arătat o modalitate foarte
simplă de a adăuga date la tablou când l-am iniţializat , dar de obicei aceasta nu este îndeajuns
de flexibilă pentru sarcini din lumea reală. Pentru a accesa o valoare a unui tablou trebuie să
cunoaştem poziţia acestuia. Sistemul de indexare folosit pentru a accesa elementele
tablourilor începe de la zero , ceea ce înseamnă că prim valoare este întotdeauna pe poziţia 0.
Să ne uităm la un mic program care prima data umple un tablou cu valori şi apoi le afişează.

17
public class powersOf2 {

public static void main(String args[]) {


int intArray[] = new int[10];
for (int i = 0; i < intArray.length; i++) {
intArray[i] = 1;
for(int p = 0; p < i; p++) intArray[i] *= 2 ;
}
for (int i = 0; i < intArray.length; i++)
System.out.println("2 to the power of " + i + " is " +
intArray[i]);
}
}

Ieşirea programului arată ca aceasta :


2 to the power of 0 is 1
2 to the power of 1 is 2
2 to the power of 2 is 4
2 to the power of 3 is 8
2 to the power of 4 is 16
2 to the power of 5 is 32
2 to the power of 6 is 64
2 to the power of 7 is 128
2 to the power of 8 is 256
2 to the power of 9 is 512
2 to the power of 10 is 1024

Aici avem structura unui apel de index :


arrayName[index];

Foarte simplu . Dacă se încearcă şi se foloseşte un index care depăşeşte limita tabloului , va
apărea o eroare la execuţie.

1.9.4 Tablouri multidimensionale

Tablourile multidimensionale sunt create în Java folosind tablouri de tablouri.. aici avem
câteva exemple de cum putem implementa tablourile multidimensionale .
int intArray[][];
String Names[][];

Putem să facem aceleaşi lucruri care le-am făcut şi cu tablourile cu o singură dimensiune.

int intArray[][] = new int[10][5];


String Names[][] = new String[25][3];
int intArray[][] = {{2, 3, 4} {1, 2, 3}};
String Names[][] = {{"Jon", "Smith"}{"Tony", "Potts"}{"Dave", "Friedel"}};

Putem să realizăm tablouri care nu sunt neapărat dreptunghiulare. Adică fiecare tablou din
tabloul principal poate să aibă un număr diferit de elemente

int intArray[][] = {{1, 2} {1, 2, 3} {1, 2, 3, 4}};


String Names[][] = {{"Jon", "Smith"} {"Tony","A", "Potts"} {"Dave", "H",
"Friedel", "Jr."}};

18
Accesul datelor într-un tablou multidimensional nu este foarte mult diferit de accesul datelor
unui tablou cu o dimensiune .

int intArray[][] = new int[10][5]; // Declare the arrays


String Names[][] = new String[25][3];
intArray[0][0] = 5; // Assign values
intArray[7][2] = 37;
intArray[7][9] = 37; // This will cause an out of bounds error!
Names[0][0] = "Bill Gates";
// Access an array element in a Java statement
System.out.println(Names[0][0]);

Copierea vectorilor
Copierea unui vector în alt vector se face cu ajutorul metodei System.arraycopy:

int x[] = {1, 2, 3, 4};


int y[] = new int[4];
System.arraycopy(x,0,y,0,x.length);

Vectori cu dimensiune variabila


Implementarea vectorilor cu numar variabil de elemente este oferita de clasa Vector din
pachetul java.util. Un obiect de tip Vector contine numai elemente de tip Object.

Capitolul 2

2.1 Crearea unei aplicatii simple


1. Scriererea codului sursa

19
class FirstApp {
public static void main( String args[]) {
System.out.println("Hello world");
}
}

Toate aplicatiile Java contin o clasa principala(primara) în care trebuie sa se gaseasca


metoda main. Clasele aplicatiei se pot gasi fie într-un singur fisier, fie în mai multe.

2. Salvarea fisierelor sursa

Se va face în fisiere cu extensia .java


Fiserul care contine codul sursa al clasei primare trebuie sa aiba acelasi nume cu clasa
primara a aplicatiei (clasa care contine metoda main)
Obs: Java face distinctie între literele mari si mici.

C:/java/FirstApp.java

3. Compilarea aplicatiei

Se foloseste compilatorul Java, javac


Apelul compilatorului se face pentru fisierul ce contine clasa principala a aplicatiei.
Compilatorul creeaza câte un fisier separat pentru fiecare clasa a programului; acestea au
extensia .class si sunt plasate în acelasi director cu fisierele sursa.

javac FirstApp.java -> FirstApp.class

4. Rularea aplicatiei

Se face cu interpretorul java, apelat pentru unitatea de compilare corespunzatoare clasei


principale, fiind însa omisa extensia .class asociata acesteia.

java FirstApp

Rularea unei aplicatii care nu foloseate interfata grafica, se va face într-o fereastra sistem.

2.1 Crearea unui applet


Crearea structurii de fisere si compilarea applet-urilor sunt identice ca în cazul aplicatiilor.
Difera în schimb structura programului si modul de rulare al acestuia.

1. Scrierea codului sursa si salvarea în fisier

import java.awt.* ;
import java.applet.* ;
public class FirstApplet extends Applet {
Image img;
public void init() {
img = getImage(getCodeBase(), "taz.gif");
}
public void paint (Graphics g) {
g.drawImage(img, 0, 0, this);

20
g.drawOval(100,0,150,50);
g.drawString("Hello! My name is Taz!", 110, 25);
}
}

Salvarea se va face în fisierul FirstApplet.java

2. Compilarea applet-ului

javac FirstApplet.java -> FirstApplet.class

Rularea applet-ului

Applet-urile nu ruleaza independent. Ele pot fi rulate doar prin intermediul unui
browser : Internet Explorer, Netscape sau printr-un program special cum ar fi
appletviewer-ul din setul JDK.

1. Creearea unui fisier HTML pentru miniaplicatie (exemplu.html)

<html>
<head>
<title>First Java Applet</title>
</head>
<body>
<applet code=FirstApplet.class width=400
height=400>
</applet>
</body>
</html>

2. Vizualizarea appletului

appletviewer exemplu.html

Capitolul 3

3.1 Controlul executiei


Instructiunile Java pentru controlul executiei sunt asemanatoare celor din C. Sumarul
instrucţiunilor din Java este :

21
1. Instructiuni de decizie
if-else, switch-case
2. Instructiuni de salt
for, while, do-while
3. Instructiuni pt. tratarea exceptiilor
try-catch-finally, throw
4. Alte instructiuni
break, continue, label: , return

3.1.1 Instructiuni de decizie

a) if-else
if (exp_booleana)
{ /*...*/}

if (exp_booleana)
{ /*...*/}
else
{ /*...*/}

b) switch-case

switch (variabila) {
case val1 : /* ... */ break;
case val2 : /* ... */ break;
/*...*/
default : /*...*/
}

3.1. 2. Instructiuni de salt

a) for

for (initializare; exp_booleana; pas_iteratie)

Ex: for(int i=0, j=100 ; i<100 && j>0; i++, j--)


{/* ... /*}
Obs: atât la initializare cât si în pasul de iteratie pot fi mai multe instructiuni despartite prin
virgula.

b)while

while (exp_booleana) {
/*...*/
}

c)do-while

22
do {
/*...*/
}while (exp_booleana) ;

3.1.3. Instructiuni pentru tratarea exceptiilor

try-catch-finally, throw (vezi "Tratarea exceptiilor")

3.1.4. Alte instructiuni

break - paraseste fortat corpul iteratiei curente

continue - termina fortat iteratia curenta

return -termina o metoda

return [valoare];

label: Defineste o eticheta

Atentie: In Java nu exista goto. Se pot însa defini etichete de forma nume_eticheta:, folosite
în expresii de genul: break nume_eticheta sau continue nume_eticheta

Exemplu:
i=0;
eticheta:
while (i<10) {
System.out.println("i="+i);
j=0;
while (j<10) {
j++;
if (j==5) continue eticheta;
if (j==7) break eticheta;
System.out.println("j="+j);
}
i++;
}

3.2 Siruri de caractere


In Java, un sir de caractere poate fi reprezentat printr-un vector format din elemente de tip
char, un obiect de tip String sau un obiect de tip StringBuffer.

Declararea unui sir


Daca un sir de caractere este constant atunci el va fi declarat de tipul String, altfel va fi

23
declarat cu StringBuffer. (vezi "Clasele String, StringBuffer") Exemple echivalente de
declarare a unui sir:

String str = "abc";


char data[] = {'a', 'b', 'c'};
String str = new String(data);
String str = new String("abc");

Concatenarea sirurilor
Concatenarea sirurilor de caractere se face prin intermediul operatorului +.

String str1 = "abc" + "xyz";


String str2 = "123";
String str3 = str1 + str2;
In Java, operatorul de concatenare + este extrem de flexibil în sensul ca permite concatenarea
sirurilor cu obiecte de orice tip care au o reprezentare de tip sir de caractere.
System.out.print("Vectorul v are" + v.length + " elemente")

3.3. Folosirea argumentelor de la linia de comanda


O aplicatie Java poate primi oricâte argumente de la linia de comanda în momentul lansarii ei.
Aceste argumente sunt utile pentru a permite utilizatorului sa specifice diverse optiuni legate
de functionarea aplicatiei sau sa furnizeze anumite date initiale programului.

Atentie: Programele care folosesc argumente de la linia de comanda nu sunt 100% pure Java
deoarece unele sisteme de operare cum ar fi Mac OS nu au în mod normal linie de comanda.
Argumentele de la linia de comanda sunt introduse la lansarea unei aplicatii, fiind specificate
dupa numele aplicatiei si separate prin spatiu. De exemplu, sa presupunem ca aplicatia Sort
ordoneaza lexicografic liniile unui fisier si primeste ca argument numele fisierului pe care sa
îl sorteze. Pentru a ordona fisierul "persoane.txt" lansarea aplicatiei se va face astfel:
java Sort persoane.txt
Asadar, formatul general pentru lansarea unei aplicatii care primeste argumente de la linia de
comanda este:
java NumeAplicatie [arg1 arg2 . . . argn]
In cazul în care sunt mai multe, argumentele trebuie separate prin spatii iar daca unul dintre
argumente contine spatii, atunci el trebuie pus între ghilimele. Evident, o aplicatie poate sa nu
primeasca nici un argument sau poate sa ignore argumentele primite de la linia de comanda.
In momentul lansarii unei aplicatii interpretorul parcurge linia de comanda cu care a fost
lansata aplicatia si, în cazul în care exista, transmite aplicatiei argumentele specificate sub
forma unui vector de siruri. Acesta este primit de aplicatie ca parametru al metodei main.
Reamintim ca formatul metodei main din clasa principala este:
public static void main ( String args[])
Vectorul primit ca parametru de metoda main va contine toate argumentele transmise
programului de la linia de comanda. In cazul apelului java Sort persoane.txt vectorul
args va contine un singur element args[0]="persoane.txt".
Numarul argumentelor primite de un program este dat deci de dimensiunea vectorului args si
acesta poate fi aflat prin intermediul atributului length al vectorilor:
numarArgumente = args.length ;
Spre deosebire ce C/C++ vectorul primit de metoda main nu contine pe prima pozitie numele
aplicatiei, întrucât în Java numele aplicatiei este numele clasei principale, adica a clasei în
care se gaseste metoda main.
Exemplu: afisarea argumentelor primite la linia de comanda

24
public class Echo {
public static void main (String[] args) {
for (int i = 0; i < args.length; i++)
System.out.println(args[i]);
}
}
Un apel de genul java Echo Drink Hot Java va produce urmatorul rezultat:
Drink
Hot
Java
(aplicatia Echo a primit 3 argumente).
Una apel de genul java Echo "Drink Hot Java" va produce urmatorul rezultat:
Drink Hot Java
(aplicatia Echo a primit un singur argument).

Argumente numerice la linia de comanda


Argumentele de la linia de comanda sunt primite sub forma unui vector de siruri (obiecte de
tip String). In cazul în care unele dintre acestea reprezinta valori numerice ele vor trebui
convertite din siruri în numere. Acest lucru se realizeaza cu metode de tipul parseXXX aflate
în clasa corespunzatoare tipului în care vrem sa facem conversia: Integer, Float, Double,
etc.
Sa consideram, de exemplu, ca aplicatia Power ridica un numar real la o putere întreaga,
argumentele fiind trimise de la linia de comanda:

java Power "12.1" "3" //ridica 12.1 la puterea 3


Conversia celor doua argumente în numere se va face astfel:
double numar;
int putere;
numar = Double.parseDouble(args[0]);
putere = Integer.parseInt(args[1]);
Metodele de tipul parseXXX pot produce exceptii (erori) de tipul NumberFormatException în
cazul în care sirul primit ca parametru nu reprezinta un numar de tipul respectiv.

Capitolul 4
Obiecte si clase in Java

4.1 Crearea obiectelor


In Java obiectele sunt create prin instantierea unei clase, cu alte cuvinte prin crearea unei
instante a unei clase.Crearea unui obiect presupune trei lucruri:

25
1. Declararea obiectului

NumeClasa numeObiect;
Ex: Rectangle patrat;

2. Instantierea
Se realizeaza prin intermediul operatorului new si are ca efect crearea efectiva a
obiectului cu alocarea spatiului de memorie corespunzator.

patrat = new Rectangle();

3. Initializarea
Se realizeaza prin intermediul constructorilor clasei respective. Rectangle() este un
apel catre constructorul clasei Rectangle care este responsabil cu initializarea
obiectului. Initializarea se poate face si cu anumiti parametri, cu conditia sa existe un
constructor al clasei respective care sa accepte parametrii respectivi;

patrat = new Rectangle(0, 0, 100, 200);

Fiecare clasa are un set de constructori care se ocupa cu initializare obiectelor nou create.
De exemplu clasa Rectangle are urmatorii constructori:
public Rectangle(Point p)
public Rectangle(int w, int h)
public Rectangle(Point p, int w, int h)
public Rectangle()
Declararea, instantierea si initializarea obiectului pot aparea pe aceesi linie (cazul cel mai
uzual):
Rectangle patrat = new Rectangle(0, 0, 100, 200);
Este posibila si crearea unor obiecte anonime care servesc doar pentru initializarea altor
obiecte, caz în care etapa de declarare a obiectului nu mai este prezenta:
patrat.origin = new Point(0, 0);
//se creeaza un obiect anonim de tip Point care,
//dupa executarea atribuirii este automat distrus de catre sistem
Atentie
Spatiul de memorie nu este pre-alocat
Declararea unui obiect nu implica alocarea de spatiu de memorie pentru acel obiect.
Rectangle patrat;
patrat.x = 10; //EROARE!
Alocarea memoriei se face doar la apelul instructiunii new !

4.1.1 Folosirea obiectelor


Odata un obiect creat, el poate fi folosit în urmatoarele sensuri: aflarea unor informatii despre
obiect, schimbarea starii sale sau executarea unor actiuni. Aceste lucruri se realizeaza prin:

• aflarea sau schimbarea valorilor variabilelor sale


• apelarea metodelor sale.

Referirea valorii unei variabile se face prin obiect.variabila


De exemplu clasa Rectangle are variabilele publice x, y, width, height, origin.
Aflarea valorilor acestor variabile sau schimbarea lor se face prin constructii de genul:
Rectangle patrat = new Rectangle(0, 0, 100, 200);
System.out.println(patrat.width); //afiseaza 100

26
patrat.x = 10;
patrat.y = 20; //schimba originea
patrat.origin = new Point(10, 20); //schimba originea
Obs: Accesul la variabilele unui obiect se face în conformitate cu drepturile de acces pe care
le ofera variabilele respective celorlalte clase. Apelul unei metode se face prin
obiect.metoda([parametri])
Rectangle patrat = new Rectangle(0, 0, 100, 200);
patrat.setLocation(10, 20); //schimba originea
patrat.setSize(200, 300); //schimba dimensiunea
Se observa ca valorile variabilelor pot fi modificate indirect prin intermediul metodelor.
Programarea orientata obiect descurajeaza folosirea directa a variabilelor unui obiect deoarece
acesta poate fi adus în stari inconsistente (ireale). In schimb, pentru fiecare variabila a
obiectului trebui sa existe metode care sa permita aflarea/schimbarea valorilor variabilelor
sale.
patrat.width = -100; //stare inconsistenta
patrat.setSize(-100, -200)
//metoda setSize poate sa testeze daca valorile sunt corecte si sa
//valideze sau nu schimbarea lor

4.1.2 Distrugerea obiectelor


Multe limbaje de programare impun ca programatorul sa tina evidenta obiectelor create si sa
le distruga în mod explicit atunci când nu mai este nevoie de ele, cu alte cuvinte sa
administreze singur memoria ocupata de obiectele sale. Practica a demonstart ca aceasta
tehnica este una din principala furnizoare de erori ce duc la functionarea defectuoasa a
programelor.
In Java programatorul nu mai are responsabilitatea distrugerii obiectelor sale întrucât, în
momentul rularii unui program, simultan cu interpretorul Java ruleaza si un proces care se
ocupa cu distrugerea obiectelor care nu mai sunt folosite. Acest proces pus la dispozitie de
platforma Java de lucru se numeste garbage collector (colector de gunoi), prescurtat gc.
Un obiect este elimnat din memorie de procesul de colectare atunci când nu mai exista nici o
referinta la acesta. Referintele (care sun de fapt variabile) sunt distruse în mod :

• natural, atunci când variabila respectiva iese din domeniul sau, de exemplu la
terminarea unei metode
• explicit, daca atribuim variabilei respective valoare null.

Cum functioneaza colectorul de gunoaie ?


GC este un proces de prioritate scazuta care se executa periodic si care scaneaza dinamic
memoria ocupata de programul Java aflat în executie si marcheaza acele obiecte care au
referinte directe sau indirecte. Dupa ce toate obiectele au fost parcurse cele care au ramas
nemarcate sunt eliminate din memorie.
Procesul gc poate fi fortat sa se execute prin metoda gc a clasei System.

Finalizare
Inainte ca un obiect sa fie eliminat din memorie, procesul gc da acelui obiect posibilitatea "sa
curete dupa el", apelând metoda de finalizare a obiectului respectiv. Uzual, în timpul
finalizarii un obiect îsi închide fisierele si socket-urile folosite, distruge referintele catre alte
obiecte (pentru a usura sarcina colectorului de gunoaie), etc. Codul pentru finalizare unui
obiect trebuie scris într-o metoda speciala numita finalize a clasei ce descrie obiectul
respectiv.
De exemplu, clasa Rectangle are urmatorul cod pentru finalizarea obiectelor sale:
class Rectangle {

27
...
protected void finalize() throws Throwable {
origin = null;
super.finalize();
}
}

4.2. Crearea claselor


4.2.1 Declararea claselor

Declararea unei clase

[public][abstract][final] class NumeClasa


[extends NumeSuperclasa]
[implements Interfata1 [, Interfata2 ... ]]
{
//corpul clasei
}

Asadar, prima parte a declaratie o ocupa modificatorii clasei. Acestia sunt:

Modificatorii unei clase


public Implicit, o clasa poate fi folosita doar de clasele aflate în acelasi pachet cu clasa
respectiva (daca nu se specifica un anume pachet, toate clasele din directorul
curent sunt considerate a fi în acelasi pachet).
O class declarata cu public poate fi folosita de orice clasa, indiferent de pachetul
în care se gaseste.
abstract Declara o clasa abstracta (sablon). O clasa abstracta nu poate fi instantiata, fiind
folosita doar pentru a crea un model comun pentru o serie de subclase
final Declara ca respectiva clasa nu poate avea subclase. Declarare claselor finale are
doua scopuri:

• securitate : unele metode pot astepta ca parametru un obiect al unei


anumite clase si nu al unei subclasei, dar tipul exact al unui obiect nu
poate fi aflat cu exactitate decât în momentul executiei; în felul acesta nu
s-ar mai putea realiza obiectivul limbajului Java ca un program care a
trecut compilarea nu mai este susceptibil de nici o eroare (nu "crapa
sistemul").
• programare în spririt orientat-obiect : "O clasa perfecta nu trebuie sa mai
aiba subclase"

Dupa numele clasei putem specifica, daca este cazul, faptul ca respectiva clasa este subclasa a
unei alte clase cu numele NumeSuperclasa sau/si ca implementeaza una sau mai multe
interfete, ale caror nume trebuie separate prin virgula.
Se observa ca, spre deosebire de C++, Java permite doar mostenirea simpla, asadar o clasa

28
poate avea un singur un singur parinte (superclasa). Evident o clasa poate avea oricâti
mostenitori (subclase). Extinderea unei clase se realizeaza deci astfel:
class B extends A {...} //A este superclasa clasei B

4.2.2 Corpul unei clase


Urmeaza declararea clasei si este cuprins între acolade. Contine:

• declararea variabilelor de instanta si de clasa (cunoscute împreuna ca variabile


membre)
• declararea si implementarea metodelor de instanta si de clasa (cunoscute împreuna ca
metode membre)

Spre deosebire de C++, nu este permisa doar declararea metodei în corpul clasei, urmând ca
implementare sa fie facuta în afara ei. Implementarea metodelor unei clase trebuie sa se faca
"inline" in corpul clasei.
In C++ In Java
class A { class A {
void metoda1(); void metoda(){
int metoda2() { //implementare
//implementare }
} }
}
A::metoda1() {
//implementare
}

Obs: variabilele unei clase pot avea acelasi nume cu metodele clasei.

4.2.3 Constructorii unei clase


Constructorii unei clase sunt metode speciale care au acelasi nume cu cel al clasei, nu
returneaza nici o valoare si sunt folositi pentru initializarea obiectelor acelei clase în
momentul instantierii lor.
class Dreptunghi {
Dreptunghi() {
//constructor
}
}
O clasa poate avea unul sau mai multi constructori care trebuie însa sa difere prin lista de
argumente primite. In felul acesta sunt permise diverse tipuri de initializari ale obiectului la
crearea sa, în functie de numarul parametrilor cu care este apelat constructorul.
class Dreptunghi {
double x, y, w, h;
Dreptunghi(double x0, double y0, double wo, double h0) {
x=x0; y=y0; w=w0; h=h0;
}
Dreptunghi(double x0, double y0) {
this(x0, y0, 0, 0);
}
Dreptunghi() {
//initializare implicita
this(0, 0, 100, 100);
}
}

29
Constructorii sunt apelati automat la instantierea unui obiect. In cazul în care dorim sa apelam
explicit constructorul unei clase folosim metoda this( argumente ), care apeleaza
constructorul corespunzator (ca argumente) al clasei respective. Aceasta metoda este folosita
atunci când sunt implementati mai multi constructori pentru o clasa pentru a nu repeta
secventele de cod scrise la constructorii cu mai putine argumente.
Dintr-o subclasa putem apela si constructorii superclasei cu metoda super( argumente ).
class Patrat extends Dreptunghi {
double size;
Patrat(double x0, double y0, double s0) {
super(x0, y0, s0, s0); //se apeleaza constructorul
superclasei
size = s0;
}
}
Constructorii sunt apelati automat la instantierea unui obiect.
In cazul în care scrieti o clasa care nu are declarat nici un constructor, sistemul îi creeaza
automat un constructor implicit care nu primeste nici un argument si care nu face nimic. Deci
prezenta constructorilor în corpul unei clase nu este obligatorie. Daca însa ati scris un
constructor pentru o clasa care are mai mult de un argument, atunci constructorul implicit
(fara nici un argument) nu va mai fi furnizat implicit de catre sistem.
class Dreptunghi {
//nici un constructor
}
...
Dreptunghi d;
d=new Dreptunghi(); -> OK (a fost generat constructorul implicit)

class Dreptunghi {
double x, y, w, h;
Dreptunghi(double x0, double y0, double wo, double h0) {
x=x0; y=y0; w=w0; h=h0;
}
}
...
Dreptunghi d;
d=new Dreptunghi(); -> Eroare la compilare
Constructorii unei clase pot avea urmatorii specificatori de acces:

Specificatorii de acces ai constructorilor


private Nici o alta clasa nu poate instantia obiecte ale acestei clase. O astfel de clasa
poate contine metode publice (numite "factory methods") care sa-si creeze
propriile obiecte si sa le returneze altor clase, controlând în felul acesta diversi
parametri legati de creare obiectelor sale.
protected Doar subclasele pot crea obiecte de tipul clasei respective.
public Orice clasa poate crea instante ale clasei respective
implicit Doar clasele din acelasi pachet pot crea instante ale clasei respective

30
4.2.4 Declararea variabilelor membre
Variabilele se declara de obicei înaintea metodelor, desi acest lucru nu este impus de
compilator.
class NumeClasa {
//declararea variabilelor
//declararea metodelor
}
Variabilele unei clase se declara în corpul clasei dar nu în corpul unei metode. Variabilele
declarate în cadrul unei metode sunt locale metodei respective.
Declararea unei variabile presupune specificarea urmatoarelor lucruri:

• numele variabilei
• tipul de date
• nivelul de acces la acea variabila de catre alte clase
• daca este constanta sau nu
• daca este variabila de instanta sau de clasa

Generic, o variabila se declara astfel:


Declararea variabilelor membre
[modificatori] TipDeDate numeVariabila [ = valoareInitiala ] ;
unde un modificator poate fi :

• un specificator de acces : public, protected, private


• unul din cuvintele rezervate: static, final, transient, volatile

Ex: double x;
protected static int n;
public String s = "abcd";
private Point p = new Point(10, 10);
final long MAX = 100000L;

static Prezenta lui declara ca o variabila este variabila de clasa si nu de instanta:


Declararea int x ; //variabila de instanta
variabilelor de static int nrDeObiecteCreate; //variabila de clasa
clasa
final Indica faptul ca valoarea variabilei nu mai poate fi schimbata, cu alte
Declararea cuvinte este folosit pentru declararea constantelor.
constantelor final double PI = 3.14 ;
...
PI = 3.141 -> eroare la compilare
Prin conventie numele variabilelor finale se scriu cu litere mari. Folosirea
lui final aduce o flexibilitate sporita în lucrul cu constante, în sensul ca
valoarea unei variabile nu trebuie specificata neaparat la declararea ei (ca în
exemplul de mai sus), ci poate fi specificata si ulterior, dupa care ea nu va
mai putea fi modificata.
class Test {
final int MAX;
Test() {
MAX = 100; // legal
MAX = 200; // ilegal -> eroare la
compilare
}
}

31
transient Este folosit la serializarea obiectelor, pentru a specifica ce variabile membre
ale unui obiect nu participa la serializare (vezi "Serializarea obiectelor")
volatile Este folosit pentru a semnala compilatorului sa nu execute anumite
optimizari asupra membrilor unei clase. Este o facilitate avansata a
limbajului Java.

4.2.5 Implementarea metodelor


Metodele sunt responsabile cu descrierea comportamentului unui obiect. Generic, o metoda se
declara astfel:
Declararea metodelor membre
[modificatori] TipReturnat numeMetoda ( [argumente] )
[throws TipExceptie]
{
//corpul metodei
}
unde un modificator poate fi :

• un specificator de acces : public, protected, private


• unul din cuvintele rezervate: static, abstract, final, native, synchronized

static Prezenta lui declara ca o metoda este metoda de clasa si nu de instanta:


Declararea void metoda1() ; //metoda de instanta
metodelor de static void metoda2(); //metoda de clasa
clasa
abstract O metoda abstracta este o metoda care nu are implementare si trebuie sa
Declararea faca parte dintr-o clasa abstracta.
metodelor
abstracte
final Specifica faptul ca acea metoda nu mai poate fi supradefinita în
subclasele clasei în care ea este definita ca fiind finala.
native In cazul în care aveti o librarie însemnata de functii scrise în alt limaj de
programare decât Java (C de exemplu), acestea pot fi refolosite din
programele Java.
synchronized Este folosit în cazul în care se lucreaza cu mai multe fire de executie iar
metoda respectiva se ocupa cu partajarea unei resurse comune. Are ca
efect construirea unui semafor care nu permite executarea metodei la un
moment dat decât unui singur fir de executie. (vezi "Fire de executie")

Tipul returnat de o metoda


Metodele pot sau nu sa returneze o valoare (un obiect) la terminarea lor. Tipul returnat poate
fi atât un tip primitiv de date (int, double, etc.) sau o referinta la un obiect al unei clase. In
cazul în care o metoda nu returneaza nimic atunci la rubrica TipReturnat trebuie obligatoriu sa
apara cuvântul cheie void. (Ex: void afisareRezultat() )
Daca o metoda trebuie sa returneze o valoare acest lucru se realizeaza prin intermediul
instructiunii return, care trebuie sa apara în toate situatiile de terminare a functiei.
double radical(double x) {
if (radical >= 0)
return Math.sqrt(x);
else

32
System.out.println("Eroare - numar negativ!");
//Eroare la compilare - lipseste return pe aceasta
ramura
}
In cazul în care în declaratia functiei tipul returnat este un tip primitiv de date, valoarea
returnata la terminarea functiei trebuie sa aiba obligatoriu acel tip, altfel va fi furnizata o
eroare la compilare.
Daca valoarea returnata este o referinta la un obiect al unei clase, atunci clasa obiectului
returnat rebuie sa coincida sau sa fie o subclasa a clasei specificate la declararea metodei. De
exemplu, fie clasa Poligon si subclasa acesteia Patrat.
Poligon metoda1( ) {
Poligon p = new Poligon();
Patrat t = new Patrat();
if (...)
return p; // legal
else
return t; // legal
}
Patrat metoda2( ) {
Poligon p = new Poligon();
Patrat t = new Patrat();
if (...)
return p; // ilegal
else
return t; // legal
}

Trimiterea parametrilor catre o metoda


Signatura unei metode este data de numarul si tipul argumentelor primite de acea metoda:
metoda([tip1 argument1] [, tip2 argument2] ... )

Tipul de date al unui argument poate fi orice tip valid al limbajului, atât tip primitiv de date
cât si referinta la un obiect.
Ex: adaugarePersoana(String nume, int varsta, float salariu)
String este tip referinta, int si float sunt tipuri primitive
Spre deosebire de alte limbaje, în Java nu pot fi trimise ca parametri ai unei metode referinte
la alte metode (functii), însa pot fi trimise obiecte care sa contina implementarea acelor
metode, pentru a fi apelate. De asemenea, în Java o metoda nu poat primi un numar variabil
de argumente, ceea ce înseamna ca apelul unei metode trebuie sa se faca cu specificarea
exacta a numarului si tipurilor argumentelor.
Numele argumentelor primite trebuie sa difere între ele si nu trebuie sa coincida cu numele
nici uneia din variabilele locale ale metodei. Pot însa sa coincida cu numele variabilelor
membre ale clasei caz în care diferentierea se va face prin intermediul variabile this.
class Cerc {
int x, y, raza;
public Cerc(int x, int y, int raza) {
this.x = x;
this.y = y;
this.raza = raza;
}
}
Atentie: In Java argumentele sunt trimise doar prin valoare (pass-by-value)
Acest lucru însemna ca metoda receptioneaza doar valorile variabilelor primite ca parametri.
Când argumentul are tip primitiv de date metoda nu-i poate schimba valoarea decât local (în
cadrul metodei); la revenirea din metoda variabila are aceeasi valoare ca la apelul initial al

33
metodei (modificarile facute în cadrul metodei sunt pierdute).
Când argumentul este de tip referinta metoda nu poate schimba referinta obiectului însa poate
apela metodele acelui obiect si poate modifica orice variabila membra accesibila.
Asadar, daca dorim ca o metoda sa schimbe starea(valoarea) unui argument primit, atunci el
trebuie sa fie neaparat de tip referinta (trebuie sa fie un obiect!). De exemplu, sa consideram
clasa Cerc descrisa anterior si dorim sa implementam o metoda care sa returneze parametrii
cercului:

Varianta incorecta

...
int x = -1, y = -1, r = -1;
cerc.aflaParametri(x, y, r);
System.out.println("x = " + x + ", y = " + y + ", raza = " + r);
. . .
In acesct scop în clasa Cerc ar trebui sa avem o metoda de genul:
class Cerc {
int x, y, raza;
...
public void aflaParametri(int valx, int valy, int valr) {
//metoda nu functioneaza cum ar trebui!
valx = x;
valy = y;
valr = raza;
}
}
Aceasta metoda însa nu va realiza lucrul propul întrucât ea primeste doar valorile variabilelor
x, y si r adica (-1, -1, -1) si nu referinte la ele (adresele lor de memorie) astfel încât sa
le poata modifica valoarea. In concluzie, metoda nu realizeaza nimic pentru ca nu poate
schimba valorile unor variabile aflate în afara corpului ei.

Varianta corecta
Definim o clasa suplimentara care descrie parametrii pe care dorim sa-i aflam:

class CParam {
public int x, y, raza;
}

class Cerc {
int x, y, raza;
public void aflaParametri(CParam param) {
param.x = x;
param.y = y;
param.raza = raza;
}
}

...
CParam p = new CParam();
cerc.aflaParametri(p);
System.out.println("x = " + p.x + ", y = " + p.y + ", raza = " + p.raza);

4.3 Supraîncarcarea si supradefinirea metodelor


Sunt doua concepte extrem de utile ale POO si se refera la:

34
• supraîncarcarea (overloading) : în cadrul unei clase pot exista metode cu acelasi
nume cu conditia ca signaturile lor sa fie diferite (lista de argumente primite sa difere
fie prin numarul argumentelor, fie prin tipul lor) astfel încât la apelul functiei cu acel
nume sa se poata stabili în mod unic care dintre ele se executa. Fenomenul de
supradefinire a metodelor se mai numeste si polimorfism.
• supradefinirea (overriding): o subclasa a unei clase poate rescrie o metoda a clasei
parinte, prin implementarea unei metode cu acelasi nume si aceeasi signatura ca ale
superclasei.

Exemplificare:
class A {
void metoda() {
System.out.println("A: metoda fara parametru");
}

//supraincarcare - polimorfism
void metoda(int arg) {
System.out.println("A: metoda cu un parametru");
}
}

class B extends A {
//supradefinire
void metoda() {
System.out.println("B: metoda fara parametru");
}
}
O metoda supradefinita poate sa:

• ignore complet codul metodei corespunzatoare din superclasa (cazul de mai sus)
• B b = new B();
• b.metoda(); -> afiseaza "B: metoda fara parametru"

• sa extinda codul metodei parinte, executând înainte de codul propriu si functia parinte.

• class B extends A {
• //supradefinire prin extensie
• void metoda() {
• super.metoda();
• System.out.println("B: metoda fara
parametru");
• }
• }
• . . .
• B b = new B();
• b.metoda(); -> afiseaza :
• "A: metoda fara parametru"
• "B: metoda fara parametru"

Metode finale
Specifica faptul ca acea metoda nu mai poate fi supradefinita în subclasele clasei în care ea
este definita ca fiind finala. Acest lucru este util daca respectiva metoda are o implementare
care nu trebuie schimbata sub nici o forma în subclasele ei, fiind critica pentru consistenta

35
starii unui obiect. De exemplu studentilor unei universitati trebuie sa li se calculeze media
finala în functie de notele obtinute la examene în aceeasi maniera, indiferent de facultatea la
care sunt.
class Student {
. . .
final float calcMedie(int nrExamene, float note[], float ponderi[])
{
...
}
. . .
}
class StudentInformatica extends Student{
float calcMedie(int nrExamene, float note[], float ponderi[]) {
return 10.00;
}
}//eroare la compilare!

Specificatori de acces pentru membrii unei clase

Sunt cuvinte rezervate ce controleaza accesul celorlate clase la membrii unei clasei.
Specificatorii de acces pentru variabilele si metodele unei clase sunt: public, protected,
private si cel implicit (package), iar nivelul lor de acces este dat în tabelul de mai jos:
Specificator Clasa Subclasa Pachet Toti
private X
protected X X** X
public X X X X
package* X X
Exemple de declaratii:
private int secretPersonal;
proteceted String secretDeFamilie;
public Vector elemente;
long doarIntrePrieteni ; -> package

private void metodaInterna();


public double calculeazaRezultat();
Obs1(*): Daca nu este specificat nici un modificator de acces, implicit nivelul de acces este la
nivelul pachetului (package). Asadar, modificatorul "package" nu apare explicit în declararea
unei variabile/metode (în cazul în care apare, compilatorul va furniza o eroare).
Obs2(**): In cazul în care declaram un membru "protected" atunci accesul la acel membru
din subclasele clasei în care a fost declarata variabila depinde si de pachetul în care se gaseste
subclasa: daca sunt în acelasi pachet accesul este permis, daca nu sunt în acelasi pachet
accesul nu este permis decât pentru obiecte de tipul subclasei.

4.4 Membri de instanta si membri de clasa


O clasa Java poate contine doua tipuri de variabile si metode :

• de instanta: declarate fara modificatorul static, specifice fiecarei instante si


• de clasa: declarate cu modificatorul static, specifice clasei

36
Variabile
Când declarati o variabila membra cum ar fi x în exemplul de mai jos:
class MyClass {
int x ; //variabila de instanta
}
se declara de fapt o variabila de instanta, cee ce însemna ca la fiecare creare a unei instante a
clasei MyClass sistemul aloca o zona de memorie separata pentru memorarea valorii lui x.
MyClass o1 = new MyClass();
o1.x = 100;
MyClass o2 = new MyClass();
o2.x = 200;
System.out.println(o1.x) -> afiseaza 100
System.out.println(o2.x) -> afiseaza 200
Asadar, fiecare obiect nou creat va putea memora valori diferite pentru variabilele sale de
instanta.
Pentru variabilele de clasa (statice) sistemul aloca o singura zona de memorie la care au acces
toate instantele clasei respective, ceea ce înseamna ca daca un obiect modifica valoarea unei
variabile statice ea se va modifica si pentru toate celelate obiecte.
class MyClass {
int x ; //variabila de instanta
static long n; //variabila de clasa
}
. . .
MyClass o1 = new MyClass();
MyClass o2 = new MyClass();
o1.n = 100;
System.out.println(o2.n) -> afiseaza 100
o2.n = 200;
System.out.println(o1.n) -> afiseaza 200

Metode
Similar ca la variabile, metodele declarate fara modificatorul static sunt metode de instanta
iar cele declarate cu static sunt metode de clasa (statice). Diferenta între cele doua metode
este urmatoarea:

• metodele de instanta opereaza atât pe variabilele de instanta cât si pe cele statice ale
clasei
• metodele de clasa opereaza doar pe variabilele statice ale clasei
• class MyClass {
• int x ; //variabila de instanta
• static long n; //variabila de clasa
• void metodaDeInstanta() {
• n ++; //legal
• x --; //legal
• static void metodaStatica() {
• n ++; //legal
• x --; //ilegal
• }

Intrucât metodele de clasa nu depind de starea obiectelor clasei respective, apelul lor se poate
face astfel:
MyClass.metodaStatica(); //legal, echivalent cu
MyClass obj = new MyClass();
obj.metodaStatica(); //legal

37
spre deosebire de metodele de instanta care nu pot fi apelate decât unei instante a clasei
respective:
MyClass.metodaDeInstanta(), //ilegal
MyClass obj = new MyClass();
obj.metodaDeInstanta(); //legal

Utilitatea membrilor de clasa (statici)


Sunt folositi pentru a pune la dispozitie valori si metode independente de starea obiectelor
dintr-o anumita clasa.

1. Declararea constantelor
2. class MyClass {
3. final double PI = 3.14; //variabila finala de
instanta
4. }

La fiecare instantiere a clasei MyClass va fi rezervata zona de memorie pentru


variabilele finale ale obiectului respectiv, ceea ce este o risipa întrucât aceste constante
au aceleasi valori pentru toate instantele clasei. Declararea corecta a constantelor
trebuie asadar facuta cu modificatorii static si final, pentru a le rezerva o singura
zona de memorie, comuna tuturor obiectelor:

class MyClass {
static final double PI = 3.14; //variabila finala de clasa
}

5. Numararea obiectelor unei clase


6. class MyClass {
7. static long nrInstante = 0;
8. MyClass() { //constructorul este apelat la
fiecare instantiere
9. nrInstante ++;
10. }
11. }

Folosind variabile statice putem controla diversi parametri legati de crearea obiectelor
unei clase

12. Implementarea functiilor globale


Spre deosebire de C++, în Java nu putem avea functii globale definite ca atare, întrucât
"orice este un obiect". Din acest motiv si metodele care au o functionalitate globala
trebuie implementate în cadrul unei clase. Acest lucru se va face prin intermediul
metodelor de clasa (globale), deoarece acestea nu depind de starea particulara a
obiectelor din clasa respectiva. De exemplu, sa consideram functia globala sqrt care

38
extrage radicalul unui numar si care se gaseste în clasa Math. Daca nu ar fi fost functie
de clasa, apelul ei ar fi trebuit facut astfel (incorect, de altfel):
13. Math obj = new Math();
14. double rad121 = obj.sqrt(121);

ceea ce ar fi fost extrem de neplacut pentru programatori. Fiind însa functie statica ea
poate fi apelata prin: Math.sqrt(121) .

Initializarea variabilelor de clasa

Se poate face în momentul declararii lor :

class MyClass {
static final double PI = 3.14;
static long nrInstante = 0;
static final double EPS = 0.01;
}

sau prin intermediul unui bloc static de initializare:

class MyClass {
static {
final double PI = 3.14;
long nrInstante = 0;
final double EPS = 0.01;
}
}

4.5 Clase imbricate


O clasa imbricata este, prin definitie, o clasa membra a unei alte clase

class ClasaDeAcoperire{
. . .
class ClasaImbricata {
. . .
}
}

Folosirea claselor imbricate se face atunci când o alta clasa are nevoie în
implementarea ei de o alta clasa si nu exista nici un motiv pentru care clasa imbricata
sa fie declarata de sine statatoare (nu mai este folosita nicaieri).

public class Pachet { //clasa de acoperire


class Continut { //clasa imbricata
private String marfa;
private float cantitate;
Continut (String marfa, float cantitate) {
this.marfa = marfa;
this.cantitate = cantitate;
}
}

39
class Destinatie { //clasa imbricata
private String dest;
private int termen;
Destinatie(String undePleaca, int inCateZile) {
dest = undePleaca;
termen = inCateZile;
}
}

public void trimite(String marfa, float cant, String dest,


Continut c = new Continut(marfa, cant);
Destinatie d = new Destinatie(dest, termen);
}

public static void main(String[] args) {


Pachet p = new Pachet();

p.trimite("banane", 100, "Romania", 7);


}
}

Ca membra a unei clase, o clasa imbricata are un privilegiu special fata de celelalte
clase: acces nelimitat la variabilele clasei de acoperire, chiar daca acestea sunt private.

Clase interne

Ca orice alta clasa o clasa imbricata poate fi declarata statica sau nu. O clasa imbricata
nestatica se numeste clasa interna.

class ClasaDeAcoperire{
. . .
static class ClasaImbricataStatica {
. . .
}
class ClasaInterna {
. . .
}
}

Diferentierea acestor denumiri se face deoarece:

o o "clasa imbricata" reflecta relatia sintactica a doua clase; codul unei clase
apare în interiorul dodului altei clase;
o o "clasa interna" reflecta relatia dintre instantele a doua clase, în sensul ca o
instanta a unei clase interne nu poate exista decât în cadrul unei instante a
clasei de acoperire.

In general cele mai folosite clase imbricate sunt clasele interne


Asadar, o clasa interna este o clasa imbricata ale carei instante nu pot exista decât în
cadrul instantelor clasei de acoperire si care are acces direct la toti membrii clasei sale
de acoperire.

40
Identificarea claselor imbricate

Dupa cum stim orice clasa produce la compilare asa numitele "unitati de compilare",
care sunt fisiere având numele clasei respective si extensia .class, si care contin toate
informatiile despre clasa respectiva.
Pentru clasele imbricate aceste unitati de compilare sunt denumite astfel: numele
clasei de acoperire, urmat de simbolul '$' apoi de numele clasei imbricate.

class ClasaDeAcoperire{
class ClasaInterna1 {}
class ClasaInterna2 {}
}

Pentru exemplul de mai sus vor fi generate trei fisiere:

ClasaDeAcoperire.class
ClasaDeAcoperire$ClasaInterna1.class
ClasaDeAcoperire$ClasaInterna2.class
In cazul în care clasele imbricate au la rândul lor alte clase imbricate (situatie mai
putin uzuala) denumirea lor se face dupa aceeasi metoda : adaugarea unui '$' si apoi
numele clasei imbricate.
4.6 Clase si metode abstracte
Uneori în proiectarea unei aplicatii este necesar sa reprezentam cu ajutorul claselor
concepte abstracte care sa nu poata fi instantiate si care sa foloseasca doar la
dezvoltarea ulterioara a unor clase ce descriu obiecte concrete. De exemplu în pachetul
java.lang exista clasa abstracta Number care modeleaza conceptul generic de
"numar". Intr-un program nu avem însa nevoie de numere generice ci de numere
întregi, reale, etc. Clasa Number serveste ca superclasa pentru clase cum ar fi Byte,
Double, Float, Integer, Long si Short ce implementeaza obiecte pentru
descrierea numerelor de un anumit tip. Asadar clasa Number reprezinta un concept
abstract si nu vom putea instantia obiecte de acest tip:
Number numarGeneric = new Number(); //eroare

Declararea unei clase abstracte

Se face folosind cuvântul rezervat abstract în declaratia clasei:

abstract class ClasaAbstracta {


. . .
}

Daca vom încerca sa instantiem un obiect al clasei ClasaAbstracta vom obtine o


eroare la compilarea programului de genul:class ClasaAbstracta is an
abstract class. It can't be instantiated.

41
Metode abstracte

Spre deosebire de clasele obisnuite care trebuie sa furnizeze implementari pentru toate
metodele declarate o clasa abstracta poate contine metode fara nici o implementare.
Metodele fara nici o implementare se numesc metode abstracte si pot aparea doar în
clase abstracte.
In fata unei metode abstracte trebuie sa apara cuvântul cheie abstract, altfel va fi
furnizata o eroare de compilare.

abstract void metodaAbstracta(); //corect


void metoda(); //incorect
(Method metoda requires a method body; otherwisw declare it
abstract)

In felul acesta o clasa abstracta poate pune la dispozitia subclaselor sale un model
complet pe care trebuie sa-l implementeze, furnizând chiar implementarea unor
metode comune tuturor claselor sau lasând explicitarea unor metode fiecarei subclase
în parte.
Un exemplu elocvent de folosire a claselor si metodelor abstracte este descrierea
obiectelor grafice într-o maniera orientata-obiect.

o Obiecte grafice : linii, dreptunghiuri, cercuri, curbe Bezier, etc


o Stari comune : pozitia(originea), dimensiunea, culoarea, etc
o Comportament : mutare, redimensionare, desenare, colorare, etc.

Pentru a folosi starile si comportamentele comune acestor obiecte în avantajul nostru


putem declara o clasa generica GraphicObject care sa fie superclasa pentru celelalte
clase.

Metodele abstracte vor fi folosite pentru implementarea comportamentului specific


fiecarui obiect, cum ar fi desenarea iar cele obisnuite pentru comportamentul comun
tuturor, cum ar fi schimbarea originii.
Implementarea clasei abstracte GraphicObject:

42
abstract class GraphicObject {
int x, y;
. . .
void moveTo(int newX, int newY) { //metoda normala
. . .
}
abstract void draw(); //metoda abstracta
} //nici
o implementare

Atentie: Orice subclasa non-abstracta a unei clase abstracte trebui sa furnizeze


implementari ale metodelor abstracte din superclasa.
Implementarea claselor pentru obiecte grafice ar fi:

class Circle extends GraphicObject {


void draw() {
. . . //obligatoriu implementarea
}
}
class Rectangle extends GraphicObject {
void draw() {
. . . //obligatoriu implementarea
}
}

Observatii:
O clasa abstracta poate sa nu aiba nici o metoda abstracta.
O metoda abstracta nu poate aparea decât într-o clasa abstracta.
Orice clasa care are o metoda abstracta trebuie declarata ca fiind abstracta.
4.7 Clasa Object

Orice clasa are o superclasa

Dupa cum am vazut la crearea unei clase clauza "extends" specifica faptul ca acea
clasa este o subclasa a altei clase, numita superclasa. O clasa poate avea o singura
superclasa (Java nu suporta mostenirea multipla) si chiar daca nu specificati clauza
"extends" la crearea unei clase ea totusi va avea o superclasa. Cu alte cuvinte, in Java
orice clasa are o superclasa si numai una.

43
Superclasa tuturor celorlalte clase este clasa Object, care este radacina ierarhiei de
clase în Java. Clasa Object este si superclasa implicita a claselor care nu specifica o
alta superclasa. Declaratia class MyClass {} este echivalenta cu class MyClass
extends Object {}.

Clasa Object

Este cea mai generala dintre clase, orice obiect fiind, direct sau indirect, descendent al
acestei clase. Defineste si implementeaza comportamentul comun al tuturor claselor
Java cum ar fi:

o posibilitatea compararii obiectelor între ele


o specificarea unei reprezentari ca sir de caractere a unui obiect
o returnarea clasei din care face parte un obiect
o notificarea altor obiecte ca o variabila de conditie s-a schimbat, etc

Fiind sublcasa a lui Object, orice clasa poate supradefini metodele clasei Object care
nu sunt finale. Metode care pot fi supradefinite sunt: clone, equals/hashCode,
finalize ,toString

clone Acesasta metoda este folosita pentru duplicarea obiectelor (creearea unor clone).
Clonarea unui obiect presupune crearea unui nou obiect de acelasi tip si care sa
aiba aceeassi stare (aceleasi valori pentru variabilele sale)
equals, Aceste metode trebuie supradefinite împreuna. In metoda equals este scris
hashCode
codul pentru compararea a doua obiecte. Implicit (implementarea din clasa
Object) aceasta metoda compara referintele obiectelor. Uzual este redefinita
pentru a testa daca starile obiectelor coincid sau daca doar o parte din variabilele
lor coincid.
Metoda hashCode returneaza un cod întreg pentru fiecare obiect pentru a testa
consistenta obiectelor: acelasi obiect trebuie sa returneze acelasi cod pe durata
executiei programului. Daca doua obiecte sunt egale conform metodei equals
atunci apelul metodei hashCode pentru fiecare din cele doua obiecte trebuie sa
returneze acelasi întreg.
finalize In aceasta metoda se scrie codul care "curata dupa un obiect" înainte de a fi
eliminat din memorie de colectorul de gunoaie.
toString Este folosita pentru a returna o reprezentare ca sir de caractere a unui obiect.

44
Este utila pentru concatenarea sirurilor cu diverse obiecte în vederea tiparirii.
MyObject obj = new MyObject();
System.ot.println("Obiect=" + obj); //echivalent cu
System.ot.println("Obiect=" + obj.toString());

Exemplu de supradefinire a metodelor clasei Object


class MyObject extends Object {
//clasa in care este supradefinita metoda equals
public int x;
public boolean equals(Object obj) {
if (obj == null) return false;
if (!(obj instanceof MyObject)) return false;
if ( ((MyObject) obj).x == x)
return true;
else
return false;
}
public synchronized Object clone() {
MyObject m = new MyObject();
m.x = x;
return m;
}
public final synchronized String toString() {
return "[" + x + "]";
}
public void finalize() {
System.out.println("Finalizare");
x = -1;
}
}

class OtherObject {
public int x;
//clasa in care NU este supradefinita metoda equals
}

class TestObject { //clasa principala - contine metoda main


public static void main(String args[]) {
OtherObject o1 = new OtherObject();
OtherObject o2 = new OtherObject();
o1.x = 1;
o2.x = 1;
if (o1.equals(o2))
System.out.println("test1: o1 == o2");
else
System.out.println("test1: o1 != o2"); //corect
//Desi x=1 pt ambele obiecte egalitatea se obtine doar cand
//adresele lor de memorie coincid deoarece nu este
implementata
//metoda equals

o2 = o1;
if (o1.equals(o2))
System.out.println("test2: o1 == o2"); //corect
else
System.out.println("test2: o1 != o2");

//////////////////////////////////////////////
MyObject m1 = new MyObject();
MyObject m2 = new MyObject();

45
m1.x = 1;
m2.x = 1;
if (m1.equals(m2))
System.out.println("test3: m1 == m2"); //corect
else
System.out.println("test3: m1 != m2");
//x=1 pt ambele obiecte -> metoda equals returneaza true

MyObject m3;
m3 = (MyObject) m1.clone();
System.out.println("Obiectul clonat: " + m3); //echivalent
cu
System.out.println("Obiectul clonat: " + m3.toString());
//Se tipareste: Obiectul clonat: [1]
}
}

46
Capitolul 5
Interfete

5.1. Ce este o interfata ?


Interfetele duc conceptul de clasa abstracta cu un pas înainte prin eliminarea oricarei
implementari a metodelor, punând în practica unul din conceptele POO de separare a
modelului unui obiect (interfata) de implementarea sa. Asadar, o interfata poate fi privita ca
un protocol de comunicare între obiecte.
O interfata Java defineste un set de metode dar nu specifica nici o implementare pentru ele. O
clasa care implementeaza o interfata trebuie obligatoriu sa specifice implementari pentru toate
metodele interfetei, supunându-se asadar unui anumit comportament.
Definitie
O interfata este o colectie de metode fara implementare si declaratii de constante

Definirea unei interfete


Definirea unei interfete se face prin intermediul cuvântului cheie interface:
[public] interface NumeInterfata
[extends SuperInterfata1 [,extends
SuperInterfata2...]]
{
//corpul interfetei:constane si metode abstracte
}
O interfata poate avea un singur modificator: public. O interfata publica este accesibila
tuturor claselor indiferent de pachetul din care fac parte. O interfata care nu este publica este
accesibila doar claselor din pachetul din care face parte interfata.
O clasa poate extinde oricâte interfete. Acestea se numesc superinterfete si sunt separate prin
virgula
Corpul unei interfete contine:

• constante: acestea pot fi sau nu declarate cu modificatorii public, static si final


care sunt impliciti; nici un alt modificator nu poate aparea în declaratia unei variabile a
unei interfete Constantele dintr-o interfata trebuie obligatoriu initializate.
• interface NumeInterfata {
• int MAX = 100; //echivalent cu
• public static final MAX = 100;
• int MAX; //ilegal - fara
initializare
• private int x = 1; //ilegal
• }

• metode fara implementare: acestea pot fi sau nu declarate cu modificatorul public


care este implicit; nici un alt modificator nu poate aparea în declaratia unei metode a
unei interfete.
• interface NumeInterfata {
• void metoda(); //echivalent cu
• public void metoda();
• protected void metoda2(); //ilegal

47
Atentie
Variabilele unei interfete sunt implicit publice chiar daca nu sunt declarate cu
modificatorul public.
Variabilele unei interfete sunt implicit constante chiar daca nu sunt declarate cu
modificatorii static si final.
Metodele unei interfete sunt implicit publice chiar daca nu sunt declarate cu
modificatorul public.
In variantele mai vechi de Java era permis si modificatorul abstract în declaratia
interfetei si în declaratia metodelor, însa a fost eliminat deoarece atât interfata cât si
metodele sale sunt implicit abstracte.

5.2. Implementarea unei interfete


Se face prin intermediul cuvântului cheie implements:

class NumeClasa implements NumeInterfata sau


class NumeClasa implements Interfata1, Interfata2...

O clasa poate implementa oricâte interfete. O clasa care implementeaza o interfata


trebuie obligatoriu sa specifice cod pentru toate metodele interfetei. Din acest motiv,
odata creata si folosita la implementarea unor clase, o interfata nu mai trebuie
modificata , în sensul ca adaugarea unor metode noi sau schimbarea signaturii
metodelor existente va duce la erori în compilarea claselor care o implementeaza.
Modificarea unei interfete implica modificarea tuturor claselor care implementeaza
acea interfata!
Implementarea unei interfete poate sa fie si o clasa abstracta.
Exemplu de interfata

interface Instrument {
//defineste o metoda fara implementare
void play();
}

class Pian implements Instrument {


//clasa care implementeaza interfata
//trebuie obligatoriu sa implementeze metoda play
public void play() {
System.out.println("Pian.play()");
}
}

class Vioara implements Instrument {


//clasa care implementeaza interfata
//trebuie obligatoriu sa implementeze metoda play

48
public void play() {
System.out.println("Vioara.play()");
}
}

public class Muzica { //clasa principala


static void play(Instrument i) {
//metoda statica care porneste un instrument generic
//ce implementeaza interfata Instrument
i.play();
}
static void playAll(Instrument[] e) {
for(int i = 0; i < e.length; i++)
play(e[i]);
}
public static void main(String[] args) {
Instrument[] orchestra = new Instrument[2];
int i = 0;
orchestra[i++] = new Pian();
orchestra[i++] = new Vioara();
playAll(orchestra);
}
}
Se observa ca folosind interfata Instrument putem adauga noi clase de instrumente
fara a schimba codul metodelor play si playAll din clasa principala întrucât acestea
primesc ca parametru un instrument generic.
Atentie
O interfata nu este o clasa, dar orice referinta la un obiect de tip interfata poate primi
ca valoare o referinta la un obiect al unei clase ce implementeaza interfata respectiva
(upcast). Din acest motiv interfetele pot fi privite ca tipuri de date.

Diferente între o interfata si o clasa abstracta


La prima vedere o interfata nu este altceva decât o clasa abstacta în care toate
metodele sunt abstracte (nu au nici o implementare). Asadar o clasa abstracta nu ar
putea înlocui o interfata ?
Raspunsul la intrebare este Nu. Deosebirea consta în faptul ca unele clase sunt fortate
sa extinda o anumita clasa (de exemplu orice applet trebuie sa fie subclasa a clasei
Applet) si nu ar mai putea sa extinda o clasa abstracta deoarece în Java nu exista decât
mostenire simpla. Fara folosirea interfetelor nu am putea forta clasa respectiva sa
respecte un anumit protocol.
La nivel conceptual diferenta consta în:

o extinderea unei clase abstracte forteaza o relatie între clase


o implementarea unei interfete specifica doar necesitatea implementarii unor
anumie metode

5.3 Mostenire multipla prin intermediul interfetelor


Interfetele nu au nici o implementare si nu ocupa spatiu de memorie la instantierea lor.
Din acest motiv nu reprezinta nici o problema ca anumite clase sa implementeze mai
multe interfete sau ca o interfata sa extinda mai multe interfete (sa aiba mai multe
superinterfete)

49
class NumeClasa implements Interfata1, Interfata2, ...
interface NumeInterfata extends Interfata1, Interfata2, ...

O interfata mosteneste atât constantele cât si declaratiile de metode de la


superinterfetele sale. O clasa mosteneste doar constantele unei interfete.
Exemplu de clasa care implementeaza mai multe interfete:

interface Inotator {
void inoata();
}
interface Zburator {
void zboara();
}
class Luptator {
public void lupta() {}
}
class Erou extends Luptator implements Inotator, Zburator {
public void inoata() {}
public void zboara() {}
}

Exemplu de interfata care extinde mai multe interfete :

interface Monstru {
void ameninta();
}
interface MonstruPericulos extends Monstru {
void distruge();
}
interface Mortal {
void omoara();
}
interface Vampir extends MonstruPericulos, Mortal {
void beaSange();
}
class Dracula implements Vampir {
public void ameninta() {}
public void distruge() {}
public void omoara();
public void beaSange() {}
}
Atentie
O clasa nu poate avea decât o superclasa
O clasa poate implementa oricâte interfete
O clasa mosteneste doar constantele unei interfete
O clasa nu poate mosteni implementari de metode dintr-o interfata
Ierarhia interfetelor este independenta de ierarhia claselor care le implementeaza

5.4 Utilitatea interfetelor


O interfata defineste un protocol ce poate fi implementat de orice clasa, indiferent de
ierarhia de clase din care face parte. Interfetele sunt utile pentru:

50
o definirea unor similaritati între clase independente fara a forta artificial o
legatura între ele.
o asigura ca toate clasele care implementeaza o interfata pun la dipozitie
metodele specificate în interfata; de aici rezulta posibilitatea implementarii
unitare a unor clase prin mai multe modalitati.
o specificarea metodelor unui obiect fara a deconspira implementarea lor (aceste
obiecte se numesc anonime si sunt folosite la livrarea unor pachete cu clase
catre alti programatori: acestia pot folosi clasele respective dar nu pot vedea
implementarile lor efective)
o definirea unor grupuri de constante
o transmiterea metodelor ca parametri (tehnica Call-Back) (vezi "Transmiterea
metodelor ca parametri").

5.5 Crearea grupurilor de constante


Deoarece orice variabila a unei interfete este implicit declarata cu public, static si
final interfetele reprezinta o metoda convenabila de creare a unor grupuri de
constante, similar cu enum din C++.

public interface Luni {


int IAN=1, FEB=2, ..., DEC=12;
}

Folosirea acestor constante se face prin expresii de genul NumeInterfata.constanta


:

if (luna < Luni.DEC)


luna ++
else
luna = Luni.IAN;

5.6 Transmiterea metodelor ca parametri (call-back)


Transmiterea metodelor ca parametri se face în C++ cu ajutorul pointerilor. In Java
aceasta tehnica este implementata prin intermediul interfetelor. Vom ilustra acest lucru
prin intermediul unui exemplu.

Explorarea unui graf


In fiecare nod trebuie sa se execute prelucrarea informatiei din el prin intermediul unei
functii primite ca parametru.

interface functie {
public int executie(int arg);
}

class Graf {
//...
void explorare(functie f) {
//...
if explorarea a ajuns in nodul v
f.executie(v.valoare);
//...

51
}
}

//Definim doua functii


class f1 implements functie {
public int executie(int arg) {
return arg+1;
}
}
class f2 implements functie {
public int executie(int arg) {
return arg*arg;
}
}

public class TestCallBack {


public static void main(String args[]) {
Graf G = new Graf();
G.explorare(new f1());
G.explorare(new f2());
}
}

Capitolul 6
Exceptii

6.1 Ce sunt exceptiile?


Termenul exceptie este o prescurtare pentru "eveniment exceptional" si poate fi definit astfel:
Definitie
O exceptie este un eveniment ce se produce în timpul executiei unui program si care
provoaca întreruperea cursului normal al executiei.
Exceptiile pot aparea din diverse cauze si pot avea nivele diferite de gravitate: de la erori
fatale cauzate de echipamentul hardware pâna la erori ce tin strict de codul programului, cum
ar fi accesarea unui element din afara spatiului alocat unui vector. In momentul când o
asemenea eroare se produce în timpul executiei sistemul genereaza automat un obiect de tip
exceptie ce contine:

• informatii despre exceptia respectiva


• starea programului în momentul producerii acelei exceptii

public class Exceptii {


public static void main(String argsst) {
int v[] = new int[10];
v[10] = 0; //exceptie, vectorul are elementele
v[0]...v[9]
System.out.println("Aici nu se mai ajunge...");
}
}
La rularea programului va fi generata o exceptie si se va afisa mesajul :
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException :10
at Exceptii.main (Exceptii.java:4)

52
Crearea unui obiect de tip exceptie se numeste aruncarea unei exceptii ("throwing an
exception"). In momentul în care o metoda genereaza o exceptie (arunca o exceptie) sistemul
de executie este responsabil cu gasirea unei secvente de cod dintr-o metoda care sa trateze
acea exceptie. Cautarea se face recursiv, începând cu metoda care a generat exceptia si
mergând înapoi pe linia apelurilor catre acea metoda.
Secventa de cod dintr-o metoda care trateaza o anumita exceptie se numeste analizor de
exceptie ("exception handler") iar interceptarea si tratarea exceptie se numeste prinderea
exceptiei ("catch the exception").
Cu alte cuvinte la aparitia unei erori este "aruncata" o exceptie iar cineva trebuie sa o "prinda"
pentru a o trata. Daca sistemul nu gaseste nici un analizor pentru o anumita exceptie atunci
programul Java se opreste cu un mesaj de eroare (în cazul exemplului de mai sus mesajul
"Aici nu se mai ajunge..." nu va fi tiparit).
Atentie: In Java tratarea erorilor nu mai este o optiune ci o constrângere. Orice cod care poate
provoca exceptii trebui sa specfice modalitatea de tratare a acestora.

Avantajele exceptiilor
Prin modalitatea sa de tratare a exceptiilor Java are urmatoarele avantaje fata de mecanismul
traditional de tratare a erorilor:

1. Separarea codului pentru tratarea unei erori de codul în care ea poate sa apara
2. Propagarea unei erori pâna la un analizor de exceptii corespunzator
3. Gruparea erorilor dupa tipul lor

Separarea codului pentru tratarea unei erori de codul în care ea poate sa


apara
In programarea traditionala tratarea erorilor se combina cu codul ce poate produce aparitia lor
conducând la ada numitul "cod spaghetti". Sa consideram urmatorul exemplu: o functie care
încarca un fisier în memorie:
citesteFisier {
deschide fisierul;
determina dimensiunea fisierului;
aloca memorie;
citeste fisierul in memorie;
inchide fisierul;
}
Problemele care pot aparea la aceasta functie, aparent simpla sunt de genul: "Ce se întâmpla
daca: ... ?"

• fisierul nu poate fi deschis


• nu se poate determina dimensiunea fisierului
• nu poate fi alocata suficienta memorie
• nu se poate face citirea din fisier
• fisierul nu poate fi închis

Un cod traditional care sa trateze aceste erori ar arata astfel:


int citesteFisier {
int codEroare = 0;
deschide fisier;
if (fisierul s-a deschis) {
determina dimensiunea fisierului;
if (s-a determinat dimensiunea) {

53
aloca memorie;
if (s-a alocat memorie) {
citeste fisierul in memorie;
if (nu se poate citi din fisier) {
codEroare = -1;
}
} else {
codEroare = -2;
}
} else {
codEroare = -3;
}
inchide fisierul;
if (fisierul nu s-a inchis && codEroare == 0) {
codEroare = -4;
} else {
codEroare = codEroare & -4;
}
} else {
codEroare = -5;
}
return codEroare;
}//cod "spaghetti"
Acest stil de progamare este extrem de susceptibil la erori si îngreuneaza extrem de mult
întelegerea sa.
In Java, folosind mecansimul exceptiilor, codul ar arata astfel:
int citesteFisier {
try {
deschide fisierul;
determina dimensiunea fisierului;
aloca memorie;
citeste fisierul in memorie;
inchide fisierul;
}
catch (fisierul nu s-a deschis) {trateaza eroarea;}
catch (nu s-a determinat dimensiunea) {trateaza eroarea;}
catch (nu s-a alocat memorie) {trateaza eroarea }
catch (nu se poate citi dun fisier) {trateaza eroarea;}
catch (nu se poate inchide fisierul) {trateaza eroarea;}
}

Propagarea unei erori pâna la un analizor de exceptii corespunzator


Sa presupunem ca apelul la metoda citesteFisier este consecinta unor apeluri imbricate de
metode:
int metoda1 {
apel metoda2;
. . .
}
int metoda2 {
apel metoda3;
. . .
}
int metoda3 {
apel citesteFisier;
. . .
}
Sa presupunem de asemenea ca dorim sa facem tratarea erorilor doar în metoda1. Traditional,
acest lucru ar trebui facut prin propagarea erorii întoarse de metoda citesteFisier pâna la
metoda1.

54
int metoda1 {
int codEroare = apel metoda2;
if (codEroare != 0)
proceseazaEroare;
. . .
}
int metoda2 {
int codEroare = apel metoda3;
if (codEroare != 0)
return codEroare;
. . .
}
int metoda3 {
int codEroare = apel citesteFisier;
if (codEroare != 0)
return codEroare;
. . .
}
Java permite unei metode sa arunce exceptiile aparute în cadrul ei la un nivel superior, adica
functiilor care o apeleaza sau sistemului. Cu alte cuvinte o metoda poate sa nu îsi asume
responsabilitatea tratarii exceptiilor aparute în cadrul ei:
metoda1 {
try {
apel metoda2;
}
catch (exceptie) {
proceseazaEroare;
}
. . .
}
metoda2 throws exceptie{
apel metoda3;
. . .
}
metoda3 throws exceptie{
apel citesteFisier;
. . .
}

Gruparea erorilor dupa tipul lor


In Java exista clase corespunzatoare tuturor exceptiilor care pot aparea la executia unui
program. Acestea sunt grupate în functie de similaritatile lor într-o ierarhie de clase. De
exemplu, clasa IOException se ocupa cu exceptiile ce pot aparea la operatii de intrare/iesire
si diferentiaza la rândul ei alte tipuri de exceptii, cum ar fi FileNotFoundException,
EOFException, etc.
La rândul ei clasa IOException se încadreaza într-o categorie mai larga de exceptii si anume
clasa Exception. Radacina acestei ierarhii este clasa Throwable (vezi "Ierarhia claselor ce
descriu exceptii").
Interceptarea unei exceptii se poate face fie la nivelul clasei specifice pentru acea exceptie fie
la nivelul uneia din superclasele sale, în functie de necesitatile programului:
try {
FileReader f = new FileReader("input.dat");
//acest apel poate genera exceptie de tipul
FileNotFoundException
//tratarea ei poate fi facuta in unul din modurile
de mai jos
}
catch (FileNotFoundException e) {

55
//exceptie specifica provocata de absenta fisierului
'input.dat'
} //sau
catch (IOException e) {
//exceptie generica provocata de o operatie de
intrare/iesire
} //sau
catch (Exception e) {
//cea mai generica exceptie - NERECOMANDATA!
}

6.2 "Prinderea" si tratarea exceptiilor


Tratarea exceptiilor se realizeaza prin intermediul blocurilor de instructiuni try, catch si
finally. O secventa de cod care trateaza anumite exceptii trebuie sa arate astfel:
try {
Instructiuni care pot genera o exceptie
}
catch (TipExceptie1 ) {
Prelucrarea exceptiei de tipul 1
}
catch (TipExceptie2 ) {
Prelucrarea exceptiei de tipul 2
}
. . .
finally {
Cod care se executa indiferent daca apar sau nu exceptii
}
Sa consideram urmatorul exemplu : citirea unui fisier si afisarea lui pe ecran. Fara a folosi
tratarea exceptiilor codul programului ar arata astfel:
//ERONAT!
import java.io.*;
public class CitireFisier {

public static void citesteFisier() {


FileInputStream sursa = null; //s este flux de intrare
int octet;
sursa = new FileInputStream("fisier.txt");
octet = 0;
//citesc fisierul caracter cu caracter
while (octet != -1) {
octet = sursa.read();
System.out.print((char)octet);
}
sursa.close();
}

public static void main(String args[]) {


citesteFisier();
}
}
Acest cod va furniza erori la compilare deoarece în Java tratarea erorilor este obligatorie.
Folosind mecanismul exceptiilor metoda citesteFisier îsi poate trata singura erorile pe
care le poate provoca:
//CORECT
import java.io.*;
public class CitireFisier {

public static void citesteFisier() {

56
FileInputStream sursa = null; //s este flux de intrare
int octet;
try {
sursa = new FileInputStream("fisier.txt");
octet = 0;
//citesc fisierul caracter cu caracter
while (octet != -1) {
octet = sursa.read();
System.out.print((char)octet);
}

catch (FileNotFoundException e) {
System.out.println("Fisierul nu a fost gasit !");
System.out.println("Exceptie: " + e.getMessage());
System.exit(1);
}
catch (IOException e) {
System.out.println("Eroare de intrare/iesire");
System.out.println("Exceptie: " + e.getMessage());
System.exit(2);
}
finally {
if (sursa != null) {
System.out.println("Inchidem fisierul...");
try {
sursa.close();
}
catch (IOException e) {
System.out.println("Fisierul poate fi
inchis!");
System.out.println("Exceptie: " +
e.getMessage());
System.exit(3);
}
}
}
}

public static void main(String args[]) {


citesteFisier();
}
}
Blocul "try" contine instructiunile de deschidere a unui fisier si de citire dintr-un fisier ambele
putând produce exceptii. Exceptiile provocate de aceste instructiuni sunt tratate în cele doua
blocuri "catch", câte unul pentru fiecare tip de exceptie.
Inchiderea fisierului se face în blocul "finally", deoarece acesta este sigur ca se va executa.
Fara a folosi blocul "finally" închiderea fisierului ar fi trebuit facuta în fiecare situatie în care
fisierul ar fi fost deschis, ceea ce ar fi dus la scrierea de cod redundant:
try {
. . .
sursa.close();
}
. . .
catch (IOException e) {
. . .
sursa.close(); //cod redundant
}

57
Atentie: Obligatoriu un bloc de instructiuni "try" trebuie sa fie urmat de unul sau mai multe
blocuri "catch", în functie de exceptiile provocate de acele instructiuni sau (optional) de un
bloc "finally"

6.3 "Aruncarea" exceptiilor


In cazul în care o metoda nu îsi asuma responsabilitatea tratarii uneia sau mai multor exceptii
pe care le pot provoca anumite instructiuni din codul sau atunci ea poate sa "arunce" aceste
exceptii catre metodele care o apeleaza, urmând ca acestea sa implementeze tratarea lor sau,
la rândul lor, sa "arunce" mai departe exceptiile respective.
Acet lucru se realizeaza prin specificarea în declaratia metodei a clauzei throws:
metoda throws TipExceptie1, TipExceptie2, ... {
. . .
}
Atentie: O metoda care nu trateaza o anumita exceptie trebuie obligatoriu sa o "arunce". In
exemplul de mai sus daca nu facem tratarea exceptiilor în cadrul metodei citesteFisier
atunci metoda apelanta (main) va trebui sa faca acest lucru:
import java.io.*;
public class CitireFisier {
public static void citesteFisier() throws FileNotFoundException,
IOException {
FileInputStream sursa = null; //s este flux de intrare
int octet;
sursa = new FileInputStream("fisier.txt");
octet = 0;
//citesc fisierul caracter cu caracter
while (octet != -1) {
octet = sursa.read();
System.out.print((char)octet);
}
sursa.close();
}
public static void main(String args[]) {
try {
citesteFisier();
}
catch (FileNotFoundException e) {
System.out.println("Fisierul nu a fost gasit !");
System.out.println("Exceptie: " + e.getMessage());
System.exit(1);
}
catch (IOException e) {
System.out.println("Eroare de intrare/iesire");
System.out.println("Exceptie: " + e.getMessage());
System.exit(2);
}
}
}
Observati ca, în acest caz, nu mai putem diferentia exceptiile provocate de citirea din fisier si
de închiderea fisierului ambele fiind de tipul IOException.
Aruncarea unei exceptii se poate face si implicit prin instructiunea throw ce are formatul:
throw obiect_de_tip_Exceptie .
Exemple:
throw new IOException();
if (index >= vector.length)
throw new ArrayIndexOutOfBoundsException();
catch(Exception e) {

58
System.out.println("A aparut o exceptie);
throw e;
}
Aceasta instructune este folosita mai ales la aruncarea exceptiilor proprii care, evident, nu
sunt detectate de catre mediul de executie. (vezi "Crearea propriilor exceptii")

6.4 Ierarhia claselor ce descriu exceptii


Radacina claselor ce descriu exceptii este clasa Thowable iar cele mai importante subclase ale
sale sunt Error, Exception si RuntimeException, care sunt la rândul lor superclase
pentru o serie întreaga de tipuri de exceptii.

Clasa Error
Erorile (obiecte de tip Error) sunt cazuri speciale de exceptii generate de functionarea
anormala a echipamentului hard pe care ruleaza un program Java si sunt invizibile
programatorilor. Un program Java nu trebuie sa trateze aparitia acestor erori si este
improbabil ca o metoda Java sa provoace asemenea erori.
Clasa Exception
Obiectele de acest tip sunt exceptiile standard care trebuie tratate de catre programele Java. In
Java, tratarea exceptiilor nu este o optiune ci o constrângere.
Exceptiile care pot "scapa" netratate sunt încadrate în subclasa RuntimeException si se
numesc exceptii la executie.

In general metodele care pot fi apelate pentru un obiect exceptie sunt definite în clasa
Throwable si sunt publice, astfel încât pot fi apelate pentru orice tip de exceptie. Cele mai
uzuale sunt:
String getMessage( ) tipareste detaliul unei exceptii
void printStackTrace(
) tipareste informatii despre localizarea exceptiei

String toString( )
metoda din clasa Object, da reprezentarea ca sir de caractere a
exceptiei

6.5 Exceptii la executie (RuntimeException)

59
In general tratarea exceptiilor este obligatorie în Java. De la acest principu se sustrag însa asa
numitele exceptii la executie sau, cu alte cuvinte, exceptiile care pot proveni strict din vina
programatorului si nu generate de o cauza externa.
Aceste exceptii au o superclasa comuna si anume RuntimeException si în acesata categorie
sunt incluse:

• operatii aritmetice (împartire la zero)


• accesarea membrilor unui obiect ce are valoarea null
• operatii cu elementele unui vector (accesare unui index din afara domeniului,etc)

Aceste exceptii pot aparea uriunde în program si pot fi extrem de numeroare iar încercarea de
"prindere" a lor ar fi extrem de anevoioasa. Din acest motiv compilatorul permite ca aceste
exceptii sa ramâna netratate, tratarea lor nefiind însa ilegala.
int v[] = new int[10];
try {
v[10] = 0;
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("Atentie la indecsi!");
e.printStackTrace();
}//legal

6.6 Crearea propriilor exceptii


Adeseori poate aparea necesitatea crearii unor exceptii proprii pentru a pune în evidenta
cazuri speciale de erori provocate de clasele unei librarii, cazuri care nu au fost prevazute în
ierarhia exceptiilor standard Java.
O exceptie proprie trebuie sa se încadreze în ierarhia exceptiilor Java, cu alte cuvinte clasa
care o implementeaza trebuie sa fie subclasa a unei clase deja existente în aceasta ierarhie,
preferabil una apropiata ca semnificatie sau superclasa Exception.
class MyException extends Exception {
public MyException() {}
public MyException(String msg) {
super(msg);
//apeleaza constructorul superclasei
Exception
}
}
Un exemplu de folosire a exceptiei nou create:
public class TestMyException {
public static void f() throws MyException {
System.out.println("Exceptie in f()");
throw new MyException();
}
public static void g() throws MyException {
System.out.println("Exceptie in g()");
throw new MyException("aruncata din g()");
}
public static void main(String[] args) {
try {
f();
} catch(MyException e) {e.printStackTrace();}
try {
g();
} catch(MyException e) {e.printStackTrace();}
}
}

60
Fraza cheie este extends Exception care specifica faptul ca noua clasa MyEception este
subclasa a clasei Exception si deci implementeaza obiecte ce reprezinta exceptii.
In general codul adaugat claselor pentru exceptii proprii este nesemnificativ: unul sau doi
constructori care afiseaza un mesaj de eroare la iesirea standard.
Rularea programului de mai sus va produce urmatorul rezultat:
Exceptie in f()
MyException()
at TestMyException.f(TestMyException.java:12)
at TestMyException.main(TestMyException.java:20)
Exceptie in g()
MyException(): aruncata din g
at TestMyException.g(TestMyException.java:16)
at TestMyException.main(TestMyException.java:23)
Procesul de creare a unei noi exceptii poate fi dus mai departe prin adaugarea unor noi metode
clasei ce descrie acea exceptie, însa aceasta dezvoltare nu îsi are rostul în majoritatea
cazurilor. In general, exceptiile proprii sunt descrise de clase foarte simple chiar fara nici un
cod în ele, cum ar fi:
class SimpleException extends Exception { }
Aceasta clasa se bazeaza pe constructorul implicit creat de compilator însa nu are
constructorul SimpleException(String), care în practica nici nu este prea des folosit.

61
Capitolul 7
Pachete

7.1 Crearea unui pachet


Definitie
Un pachet este o colectie de clase si interfete înrudite. Sunt folosite pentru gasirea si
utilizarea mai usoara a claselor, pentru a evita conflictele de nume si pentru a controla
accesul la anumite clase. In alte limbaje de programare pachetele se numesc librarii.
Toate clasele si interfetele Java apartin la diverse pachete, grupate dupa functionalitatea lor:
clasele de baza se gasesc în pachetul java.lang, clasele pentru intrari/iesiri sunt în java.io,
clasele pentru grafica în java.awt, cele pentru construirea applet-urile în java.applet, etc.
Crearea unui pachet se realizeaza prin scriere la începutul fisierelor sursa ce contin clasele si
interfetele pe care dorim sa le grupam într-un pachet a instructiunii: package NumePachet;
Sa consideram un exemplu: presupunem ca avem doua fisiere sursa Graf.java si
Arbore.java
Graf.java Arbore.java
package grafuri; package grafuri;
class Graf {...} class Arbore {...}
class GrafPerfect extends Graf {...} class ArboreBinar extends Arbore {...}
Clasele Graf, GrafPerfect, Arbore, ArboreBinar vor face parte din acelasi pachet
grafuri.
Instructiunea package actioneaza asupra întregului fisier sursa la începutul caruia apare. Cu
alte cuvinte nu putem specifica faptul ca anumite clase dintr-un fisier sursa apartin unui
pachet iar altele altui pachet.
Daca nu este specificat un anumit pachet, clasele unui fisier sursa vor face parte din pachetul
implicit (care nu are nici un nume). In general, pachetul implicit este format din toate clasele
si intefetele directorului curent.
Este recomandabil ca toate clasele si intefetele sa fie plasate în pachete. Pachetul implicit este
folosit doar pentru aplicatii mici sau la începutul dezvoltarii unei aplicatii.

Denumirea unui pachet


Exista posibilitatea ca doi programatori care lucreaza la un proiect comun sa foloseasca
acelasi nume pentru unele din clasele lor. De asemenea, se poate ca una din clasele unei
aplicatii sa aiba acelasi nume cu o clasa a mediului Java. Acest lucru este posibil atât timp cât
clasele cu acelasi nume se gasesc în pachte diferite, ele fiind diferentiate prin prefixarea lor cu

62
numele pachetelor. Asadar numele complet al unei clase este format din numele pachetului la
care apartine + numele sau:
numePachet.NumeClasa
Ex: java.lang.String (java.lang=pachet, String=clasa)
De exemplu sa presupunem ca în aplicatia noastra folosim o clasa numita Stack:
package my_package;
class Stack { ... }
Clasa Stack exista deja în pachetul java.util. Diferentierea între cele doua clase se va face
prin specificarea numelui complet al clasei, adica numelePachetului.NumeleClasei:
java.util.Stack s1 = new java.util.Stack();
my_package.Stack s2 = new my_package.Stack();
Ce se întâmpla însa când doi programatori care lucreaza la un proiect comun folosesc clase cu
acelasi nume ce se gasesc în pachete cu acelasi nume ? Pentru a evita acest lucru companiile
folosesc inversul domeniului lor Internet în denumirea pachetelor implementate în cadrul
companiei, cum ar fi com.company.numePachet. In cadrul unei aceeasi companii conflictele
de nume trebuie rezolvate prin diverse conventii de uz intern.De exemplu, adresa mea de e-
mail este acf@infoiasi.ro, ceea ce înseamna ca domeniul meu Internet este infoiasi.ro.
Pachetele create de mine ar trebui denumite ro.infoiasi.NumePachet. Pentru a rezolva
conflicte cu alti programatori din acelasi domeniu cu mine pachetele s-ar putea numi:
ro.infoiasi.acf.NumePachet.
Folosirea membrilor unui pachet

Conform specificatiilor de acces ale unei clase si ale membrilor ei doar clasele publice si
membrii declarati publici ai unei clase sunt accesibili în afara pachetului în care acestea se
gasesc.

Pentru a folosi o clasa publica dintr-un pachet sau pentru a apela o metoda publica a unei
clase public a unui pachet exista trei solutii:

• specificarea numelui complet al clasei


• importul clasei respective
• importul întregului pachet în care se gaseste clasa

Specificarea numelui complet al calsei se face, asa cum am vazut, prin prefixarea numelui
clasei cu numele pachetului: numePachet.NumeClasa. Aceasta metoda este recomandata doar
pentru cazul în care folosirea acelei clase se face o singura data sau foarte rar. De exemplu ar
fi extrem de neplacut sa scriem de fiecare data când vrem sa declaram un sir de caractere sau
sa folosim un obiect grafic secvete de genul;
java.lang.String s = "neplacut";
java.awt.Rectangle r = new java.awt.Rectangle();
java.awt.Circle c = new java.awt.Circle();
In aceste situatii vom importa (include) clasa respective sau întreg pachet din care face parte
in aplicatia noastra. Acest lucru se realizeaza prin instructiunea import, care trebuie sa apara
la începutul fisierelor sursa, imediat dupa instructiunea package.
Importul unei clase sau interfete

Se face printr-o instructiune import în care specificam numele clasei (interfetei) pe care dorim
sa o folosim dintr-un pachet:
import java.awt.Rectangle;
Din acest moment vom putea folosi în clasele fisierului în care am plasat instructiunea de
import numele scurt al clasei Rectangle
Rectangle r = new Rectangle(0,0,100,100);

63
Aceasta abordare este eficienta în cazul în care nu avem nevoie decât de acea clasa sau doar
de câteva clase din pachetul respectiv. Daca în exemplul nostru am avea nevoie si de clasele
Circle, Line, Point, Polygon ar trebui sa avem câte o instructiune de import pentru
fiecare dintre ele:
import java.awt.Rectangle;
import java.awt.Circle;
import java.awt.Line;
import java.awt.Point;
import java.awt.Polygon;
In aceasta situatie ar fi recomandat importul întregului pachet si nu al fiecarei clase în parte.

Importul unui pachet (importul la cerere)

Se face printr-o instructiune import în care specificam numele pachetului ale carui clase si
interfete dorim sa le folosim dintr-un pachet, urmat de simbolul '*'. Se mai numeste import la
cerere deoarece încarcarea claselor se face dinamic în momentul apelarii lor. Este cel mai
uzual tip de import.
import java.awt.*;
Din acest moment vom putea folosi în clasele fisierului în care am plasat instructiunea de
import numele scurt al tuturor claselor pachetului importat:
Rectangle r = new Rectangle();
Circle c = new Circle(); ...
Atentie
* nu are semnificatia uzuala de wildcard (masca) si nu poate fi folosit decât ca atare.
import java.awt.C*; //eroare de compilare
In cazul în care sunt importate doua pachete care contin o clasa cu acelasi nume atunci
referirea la ea trebuie facuta folosind numele complet al clasei respective.
//Stack.java
package my_package;
class Stack { ... }
//alt fisier sursa
import java.util.*;
import my_package.*;
...
Stack s = new Stack(); //ilegal -> conflict de nume
java.util.Stack s1 = new java.util.Stack(); //corect
my_package.Stack s2 = new my_package.Stack();//corect
Mediul Java importa automat trei pachete pentru toate fisierele sursa:

• pachetul java.lang
• pachetul curent
• pachetul implicit (fara nume)

7.2 Pachetele JDK


Limbajul Java se bazeaza pe o serie de biblioteci (pachete) cu ajutorul carora se pot construi
aplicatiile. Exista deci un set de clase deja implementate, ceea ce reduce timpul de dezvoltare
a unui program. Cele mai importante sunt:

java.applet suport pt scrierea de appleturi


java.awt suportul pentru grafica(Abstract Windowing Toolkit)

64
java.beans suport pentru scrierea de componente reutilizabile
java.io intrari/iesiri, acces la fisiere
java.lang clasele de baza ale limbajului
java.math operatii matematice
java.net acces la retea
java.rmi executie la distanta (Remote Message Interface)
java.security mecanisme de securitate : criptare, autentificare
java.sql interogari SQL
java.text suport pentru formatarea textelor
java.util clase utile : Vector, Stack, Random, etc

Pachetul java.lang contine elementele de baza ale limbajului si este importat automat.

65

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