Documente Academic
Documente Profesional
Documente Cultură
FACULTATEA DE INFORMATIC
PROGRAMARE N JAVA
- 2016 -
Introducere
Acest curs se adreseaz studenilor anului II, specializarea Informatic, forma de nvmnt la
distan. Modul de prezentare ine cont de particularitile nvmntului la distan, la care studiul
individual este determinant..
Competenele dobndite de ctre studeni prin nsuirea coninutului cursului sunt folosite la
disciplinele de specialitate precum Tehnici avansate de programare, Proiectarea interfeelor
grafice etc. O nenelegere a noiunilor fundamentale prezentate n acest curs poate genera
dificulti n asimilarea conceptelor mai complexe ce vor fi introduse n aceste cursuri de
specialitate.
2
Pachet software recomandat:
Orice mediu de lucru pentru limbajul Java poate fi folosit, dar pentru a face o alegere mai puin
costisitoare, de altfel gratuit, v sugerm mediul de lucru NetBeans care se poate descrca de pe
site-ul https://netbeans.org/downloads/
Coordonator de disciplin
Conf. univ. dr. Ana Cristina Dsclescu
3
Unitatea de nvare nr. 1
Obiective:
ncepnd cu anul 1998, cnd a aprut versiunea 2 a limbajului (Java 2 Platform), Java a fost extins,
acoperind i mai multe direcii de dezvoltare: programarea aplicaiilor enterprise (aplicaii de tip
server) precum i a celor adresate dispozitivelor cu resurse limitate, cum ar fi telefoanele mobile,
pager-e sau PDA-uri (mici dispozitive de calcul, de dimensiuni puin mai mari dect ale unui
telefon mobil, cu faciliti de agend i capabile s execute aplicaii ntr-un mod relativ asemntor
cu cel al unui PC).
4
Platforme de lucru Java
Tehnologiile Java sunt grupate n aa numitele platforme de lucru. Acestea reprezint seturi de
librarii scrise n limbajul Java, precum i diverse programe utilitare, utilizate pentru dezvoltarea de
aplicaii sau componente destinate unei anume categorii de utilizatori.
1. Programe Java care se execut individual prin intermediul unui interpretor Java. Acestea se
ncadreaz n programele clasice scrise n diverse limbaje de programare, cum ar
fi:C/C++, Pascal etc. Acest tip de programe Java sunt denumite aplicaii de sine stttoare.
2. Programe Java care se execut n interiorul unui navigator Internet, dintr-un document
HTML. Acest tip de programe Java sunt denumite applet-uri.
O aplicaie de sine stttoare este un program Java care se execut n afara browser-ului Web .
Principala caracteristic a acestui tip de aplicaie este ncapsularea n cadrul unei clase principale a
unei funcii main() asemntoare cu cea folosita n limbajul C, cu urmtoarea signatura:
Aplicaiile care se execut pe partea de client sunt cele ncrcate de pe un server i apoi executate
de programe speciale cum ar fi navigatoarele Web.
Un applet este un program Java care respecta o mulime de reguli astfel nct s poat rula n cadrul
unui navigator Web.
O aplicaie care se execut pe partea de server este o aplicaie care este rulat de server ca urmare a
unei cereri primite de acesta, iar rezultatul este trimis programului solicitant.
Un servlet este o component Web, scris n Java, i care poate interaciona cu diferii clieni
folosind o implementare a paradigmei cerere/rspuns bazata pe protocolul HTTP. Servlet-urile
extind funcionalitatea unui server, de obicei a unui server HTTP.
5
Etapele dezvoltrii unei aplicaii Java
1.Editarea setului de instruciuni de programare cu ajutorul unui editor de texte. n acest fel este
creat un fiier surs, care are extensia .java.
O aplicaie Java este compus din una sau mai multe clase care interacioneaz ntre ele prin
intermediul metodelor. n grupul de clase, care formeaz o aplicaie Java, trebuie sa existe o clas
care s conin o metoda statica avnd numele main. Atunci cnd se execut o aplicaie Java,
maina virtual va cuta i invoca automat metoda static avnd numele main.
Observaie: Metoda main poate fi considerat ca fiind echivalentul Java al funciei main din
C/C++.
class aplicatie
{
public static void main (String [ ] args)
{
System.out.println(Primul program Java);
}
}
Observaie: Tipul parametrilor metodei (funciei) main ct i tipul metodei, static void, sunt
obligatorii.
Elemente de baz
Caractere
Limbajele de programare "clasice" utilizeaz setul de caractere ASCII. Limbajul Java folosete
setul de caractere Unicode, care este reprezentabil pe 16 bii, deci are 65 536 caractere, cuprinznd
caractere i simboluri proprii aproape tuturor limbilor existente.
Primele 256 caractere din Unicode sunt cele din setul de caractere Latin-1, dintre care primele 128
sunt cele din codul ASCII.
Un caracter poate fi reprezentat oriunde n textul surs i prntr-o aa numit "secven Escape",
avnd forma \uhhhh sau \Uhhhh, unde am notat prin h o cifr hexazecimal (cifrele hexazecimale
corespunztoare lui 10-15 sunt identificate prin a-f sau A-F). O secven Escape poate s apar deci
6
nu numai n caractere i iruri de caractere, dar i n identificatori. Numrul hexazecimal dntr-o
astfel de secven corespunde numrului de ordine al caracterului n setul Unicode.
Ne mrginim la a indica secvenele Escape pentru semnele diacritice din limba romn:
= \u00c3 = \u00e3
= \u00c2 = \u00e2
= \u00aa = \u00ca
= \u00de = \u00fe
= \u00ce = \u00ee
n continuare vom nelege prin spaii albe caracterele blanc, tab, form-feed, precum i terminatorii
de linie: return, line-feed (linie nou) i return + line-feed.
Motivaia utilizrii setului Unicode este integrarea n limbaje de tip HTML care s permit
circulaia pe Internet.
Identificatori
n Java identificatorii ncep cu o liter (inclusiv '_' i '$') i pot continua cu litere sau / i cifre; este
totui indicat s nu includem n identificatori caracterul '$', deoarece el este folosit de compilatorul
Java pentru a genera identificatori interni, despre care nu vom vorbi aici. Prin "litere" nelegem att
pe cele obinuite (literele mici i mari din alfabetul englez), ct i pe cele din alte limbi. Un
identificator poate avea orice lungime; de aceea este indicat s folosim identificatori ct mai
sugestivi pentru rolul pe care l joac, timpul "pierdut" la scrierea programului fiind recuperat din
plin atunci cnd revedem programul peste cteva luni sau cnd trebuie ca el s fie neles de alte
persoane.
Aa cum am precizat n capitolul anterior, n programe sau secvene de cod aceste cuvinte cheie vor
aprea ngroate pentru a veni n ajutorul cititorilor.
7
Constante
n limbajul Java, constantele mai poart i numele de literali. Vom prezenta doar o parte a acestor
constante (de exemplu nu vom vorbi de literali ntregi octali i hexazecimali):
4) Literalii de tip caracter au forma 'c', unde c este un caracter sau o secven Escape; aceste
secvene au fost prezentate mai sus.
Comentarii
Comentariile sunt folosite n principal pentru explicitarea aciunilor ntreprinse de cod; ele sunt
ignorate de compilator.
Variabile
Modificatorii pot nsoi nu numai cmpurile, ci i clasele i metodele, dar despre acest aspect vom
vorbi ntr-un capitol urmtor.
La declararea cmpurilor unei clase se recomand precizarea modificatorilor n ordinea de mai sus.
Aa cum am menionat n capitolul anterior, modificatorul static specific faptul c respectivul
cmp este unic pe clas, deci comun tuturor obiectelor ce sunt instane ale clasei (joac rolul de
memorie comun pentru toate obiectele ce instaniaz clasa); cmpul static poate fi referit din afara
clasei ca orice cmp, dar i prin precalificare cu numele clasei.
O declarare poate s apar oriunde n cadrul unei clase, metode sau a unui bloc de iniializare, deci
nu neaprat la nceputul lor.
Limbajul Java atribuie valori iniiale implicite cmpurilor claselor. Ele sunt:
false (pentru boolean) ; 'u0000' (pentru char) ; null (pentru referine)
0 (pentru orice tip ntreg) ; +0.0f sau +0.0d (pentru float i double) ,
unde tipurile menionate sunt descrise n continuare. n schimb nu este atribuit vreo valoare iniial
prin lips variabilelor locale din metode, constructori i blocuri de iniializare i de aceea aceste
variabile trebuie s primeasc valori nainte de a fi utilizate; nerespectarea acestei reguli conduce la
semnalarea unei erori.
O variabil declarat cu modificatorul final este iniializat implicit sau explicit prin declararea sa;
aceast valoare nu mai poate fi schimbat ulterior.
O variabil are un nume (care este un identificator) i un tip, despre care tim c este un tip primitiv
sau un tip referin. Enumerm n continuare tipurile primitive (de baz).
1) Tipul boolean. Variabilele de acest tip pot lua doar valorile true i false.
2) Tipul char. Variabilele de acest tip sunt reprezentate pe 16 bii i pot primi ca valoare orice
simbol din codul Unicode. O variabil de tip caracter poate fi folosit oriunde poate aprea o
valoare ntreag: este considerat numrul su de ordine n setul de caractere Unicode.
9
Precizm c n calcule tipurile byte i short sunt convertite la int.
Fiecrui tip primitiv din Java i corespunde o clas definit standard n Java: Boolean, Character,
Byte, Short, Integer, Long, Float i Double. n aceste clase apar constante i metode utile. Am
prezentat deja cteva constante din aceste clase n discuia asupra literalilor n virgul mobil. Mai
menionm metoda isNaN din clasele Float i Double: metoda primete o valoare de tipul
corespunztor i ntoarce o valoare boolean, care este true dac i numai dac argumentul nu este o
valoare numeric valid.
Operatori
Menionm c Java pune la dispoziia utilizatorului aproximativ 40 de operatori, dintre care unii
sunt descrii n continuare. Trebuie precizat c programatorul poate defini metode noi, dar nu i
operatori noi.
Operatori aritmetici
Aceti operatori sunt urmtorii:
+ - * / %
De asemenea este folosit operatorul unar - pentru schimbarea semnului, precum i operatorul unar +
(introdus pentru simetrie).
n aritmetica ntreag trebuie s inem cont de urmtoarele reguli:
- orice valoare ce depete limita admis este redus modulo aceast limit; de aceea nu exist
depiri (overflow i underflow);
- mprirea ntreag se face prin trunchiere; de exemplu -8/3==-2, iar 8/3==2 ;
- operatorul % este definit prin:
(x/y)*y+x%y==x
De exemplu 8%3==2, iar -8%3==-2.
Diferena ntre x++ i ++x const n faptul c incrementarea este realizat dup, respectiv nainte de
utilizarea lui x n contextul n care apare. Astfel, dac valoarea curent a lui x este 4, atunci:
- evaluarea expresiei 2 * ++x conduce la rezultatul 10,
- evaluarea expresiei 2 * x++ conduce la rezultatul 8,
dup care valoarea lui x va fi n ambele cazuri 5.
Evident, operatorul -- se supune unor reguli analoage.
10
O construcie de tipurile x++,x--,++x,--x reprezint o expresie aritmetic, dar i o instruciune
(valoarea expresiei nu este folosit, ns x este incrementat sau decrementat).
Operatorii de mai sus pot fi aplicai i pentru tipul char, semnificnd trecerea la precedentul,
respectiv urmtorul caracter din setul de caractere Unicode.
Operatorii de atribuire
Pe lng operatorul = folosit standard pentru atribuire, mai pot fi folosii i operatorii:
+= -= /= *= %=
care reprezint scrieri prescurtate. Astfel x+=y este echivalent cu x=x+y, cu excepia faptului c
evaluarea adresei lui x se face o singur dat (vezi paragraful precedent). Desigur, operatorul %= va
fi folosit doar pentru aritmetica ntreag.
Operatorii relaionali
Este vorba de urmtorii operatori:
> (mai mare ca) >= (mai mare sau egal cu) == (egal cu)
< (mai mic ca) <= (mai mic sau egal cu) != (diferit de)
Operatori booleeni
Este vorba de urmtorii operatori:
(disjuncia logic, sau) && (conjuncia logic, i) ! (negaie)
cu meniunea c la evaluare se face scurtcircuitare (pe scurt, dac la evaluarea unei expresii
booleene devine la un moment dat clar valoarea ei, nu se mai continu n mod inutil evaluarea; de
exemplu dac expresia este disjuncia logic a trei termeni i valoarea primului este true, nu se mai
evalueaz ceilali termeni).
Operatori pe bii
Este vorba de operatorii binari i & care realizeaz disjuncia logic i conjuncia logic la nivel de
bit, pentru fiecare pereche de bii de pe aceeai poziie din reprezentarea operanzilor.
Operatorul condiional ?:
Acest operator se utilizeaz n expresii sub forma:
( cond ? e1 : e2 )
a crei valoare este e1 dac cond este true, respectiv e2 dac cond este false; cond trebuie s fie
o expresie de tip boolean. Pentru a nu intra n amnunte, vom impune deocamdat regula ca e1 i
e2 s aib acelai tip.
Operatori postfixai
Includem aici:
- cuprinderea ntre paranteze a indicilor (cu []);
- operatorul de calificare (.) folosit pentru accesarea membrilor claselor;
- parantezele rotunde folosite pentru specificarea listei de parametri din invocri;
- operatorii postfixai de incrementare/decrementare ++ i -- de mai sus.
11
Operatorul de conversie a tipurilor
Ne mrginim la a preciza c o conversie explicit de tip are forma:
(tip) expresie
urmnd s discutm ulterior condiiile n care poate avea loc o astfel de conversie.
Precedena operatorilor
Ordinea n care are loc efectuarea prelucrrilor determinate de operatori este dat n urmtorul tabel
de prioriti ale operatorilor (de la prioritate maxim la prioritate minim):
- operatorii postfix
- operatorii unari de incrementare/decrementare, operatorii + i - unari, operatorul de negaie !
- operatorul new de creare de obiecte i cel de conversie: (tip) expresie
- operatorii multiplicativi: * / %
- operatorii aditivi: + -
- operatorii relaionali i instanceof
- operatorii de egalitate: == !=
- operatorul &
- operatorul
- conjuncia logic &&
- disjuncia logic
- operatorul condiional ( ? : )
- operatorii de atribuire.
Observaii:
- la prioritate egal, operatorii "vecini" acioneaz conform regulilor de asociativitate prezentate n
continuare;
- utilizarea parantezelor este mai puternic dect prioritatea operatorilor. Astfel, spre deosebire de
x+y*z, n (x+y)*z prima operaie care va fi executat este adunarea.
12
Asociativitate
Regula general o constituie asociativitatea la stnga. Fac excepie urmtorii operatori, pentru care
este folosit asociativitatea la dreapta:
- operatorii unari;
- operatorii de atribuire.
- operatorul ( ? : ).
Exemple :
Controlul execuiei
- Instruciunea de declarare asociaz unei variabile un anumit tip i eventual i atribuie o valoare
iniial; variabila devine local celui mai interior bloc care o conine, n sensul c exist atta timp
ct se execut instruciuni ale blocului. O instruciune de declarare poate s apar oriunde n
interiorul unui bloc. nainte de utilizarea lor, variabilele locale trebuie s fi primit valori fie prin
iniializare la declarare, fie printr-o instruciune de atribuire (n caz contrar va fi semnalat o eroare
la compilare).
- Instruciunea vid este format numai din ; i care nu prevede vreo prelucrare.
- Instruciunea prin care este creat un obiect folosete n acest scop operatorul new.
- Instruciunile ce controleaz ordinea de executare, ca de exemplu: if-else, for, while etc. Ele vor
fi prezentate detaliat n continuare.
13
- Instruciunea if-else. Ea are una dintre formele:
if (expresie_boolean) instr1
sau
if (expresie_boolean) instr1
else instr2
Este evaluat expresia boolean. Dac rezultatul este true, atunci se execut instr1, iar n caz contrar
se execut instr2 (sau nimic pentru forma scurt).
Clauza else este asociat celui mai recent if cruia nu i s-a asociat un else. Astfel n :
if (a==0) b=1; if (c==1) b=2; else b=3;
clauza else este asociat celui de al doilea if. Pentru a face lucrurile clare, este indicat ca fiecare if
s fie nsoit de un else (urmat eventual de instruciunea vid).
- expresia boolean poate i ea lipsi, caz n care se presupune c ea are implicit valoarea true.
Cadrul tipic de utilizare este n iteraii. De exemplu, suma primelor n numere naturale poate fi
obinut astfel:
s=0;
for (i=0;i<n;i++) s+=i;
Mai prezentm nc un exemplu: dei n-am vorbit nc despre tablouri, menionm c pentru
inversarea ordinii elementelor unui tablou (unidimensional) a este suficient o instruciune for
(indexarea elementelor tablourilor ncepe cu 0):
for(i=0,j=a.length-1; i<j; i++,j--)
{ b=a[i];a[i]=a[j];a[j]=b;}
14
care desemneaz repetarea "la infinit" a executrii lui instr. Evident, n cazul folosirii acestei forme,
asigurarea ieirii din ciclu cade n sarcina instruciunii instr.
n iniializrile din for este permis s facem declarri, ca de exemplu:
for(int i=1;i<=n;i++) s+=i;
dar numai dac i nu este deja declarat; precizm c n aceast situaie variabila i este local
instruciunii for.
- Instruciunea break este folosit pentru a iei dintr-un bloc. O prim form este:
break;
prin care se iese din cea mai interioar instruciune for, while, do sau switch, sau bloc ce conine
aceast instruciune.
Forma:
break eticheta;
unde eticheta este eticheta unui bloc sau a uneia dintre cele 4 tipuri de instruciuni menionate, ce
conine instruciunea break. Ca efect, controlul este transferat la instruciunea cu eticheta
respectiv. Se poate astfel iei de exemplu din dou instruciuni for imbricate. S remarcm faptul
c nu este posibil s trecem controlul oricrei alte instruciuni (ca pentru goto din alte limbaje), deci
transferul este controlat i respect structurarea programului.
- Instruciunea switch evalueaz o expresie ntreag, a crei valoare este folosit pentru a detecta o
secven de instruciuni ce urmeaz a fi executat. O prim form a ei este:
switch (expresie) {
case val1 : secven_instruciuni1
...
case valk : secven_instruciunik
default : secven_instruciuni
}
unde:
- tipul expresiei poate fi numai char, byte, short sau int;
- val1, ..., valk sunt constante (literali sau cmpuri statice finale iniializate cu expresii constante) de
acelai tip cu al expresiei;
- alternativa default este opional.
Executarea instruciunii are loc dup cum urmeaz. Este calculat valoarea expresiei, care este apoi
comparat pe rnd cu val1, ..., valk, pn cnd se detecteaz prima dat egalitate. Urmeaz
executarea secvenei de instruciuni corespunztoare, dar i a celor care urmeaz; executarea
acestora poate fi limitat prin folosirea instruciunii break. Dac nu se detecteaz nici o egalitate,
atunci se execut secvena de instruciuni corespunztoare lui default (dac aceast alternativ este
prezent) sau nu se execut nimic (n caz contrar).
15
Mai general, o alternativ poate avea mai multe valori, ca n exemplul urmtor:
case 1 : case 3 : case 5 : a = b; b = c; c = a;
Exemplul 2
Programul urmtor:
class Switch {
static void numara(int i) {
switch (i) {
case 1 : System.out.print("unu ");
case 2 : System.out.print("doi ");
case 3 : System.out.println("trei");
}
}
n limbajul Java nu exista instruciuni specializate pentru citirea/scrierea datelor. Aceste operaii se
realizeaz prin intermediul unor metode existente n pachetele API ale limbajului. Intrarea i ieirea
n Java se realizeaz cu ajutorul claselor de obiecte din pachetul predefinit java.io. Orice program
care folosete rutinele de intrare/ieire trebuie sa cuprind instruciunea:
import java.io.*
Conceptul fundamental n operaiile de intrare/ieire n limbajul Java este fluxul de intrare/ieire
(stream).
Daca stream-ul este de intrare, succesiunea de bii curge dinspre exterior (n acest caz, de la
tastatur) ctre memoria calculatorului.
Daca stream-ul este de ieire, secvena de bii curge dinspre memoria calculatorului ctre exterior
(n acest caz, ctre ecran).
Java ofer trei fluxuri predefinite pentru operaii I/O standard:
- System.n pentru intrarea standard de la tastatura;
- System.out pentru ieirea standard la ecranul calculatorului;
- System.err pentru fluxul de erori.
Pentru afiarea datelor la ecranul calculatorului se folosesc metodele print i println. Spre
deosebire de limbajul C/C++ care dispune de un numr foarte mare de opiuni de formatare,
afiarea n Java se face exclusiv prin concatenarea de String-uri fr nici o opiune de formatare.
16
Observaie: String-urile sunt obiecte Java care descriu irurile de caractere i le vom studia separat
ntr-o lecie viitoare. S reinem c prin concatenarea a dou iruri se obine un nou sir de caractere
care unete cele doua iruri iniiale. Operatorul de concatenare a doua iruri de caractere folosit de
Java este semnul + (plus).
Sintaxa folosita la apelul metodei print este:
System.out.print (<expresie>);
unde:
- <expresie> - este numele unei variabile de un tip de data sau este o expresie care folosete
operatorul de concatenare pentru iruri de caractere; daca nu toi operanzii din expresie sunt iruri
de caractere, ci alte tipuri primitive de date atunci Java face o conversie temporar la tipul String.
Efectul apelului metodei print este acela ca se realizeaz afiarea pe ecran a variabilei dat ca
parametru i nu se face salt la o linie nou.
Sintaxa folosita la apelul metodei println este:
System.out.println (<expresie>);
unde:
- <expresie> - este numele unei variabile de un tip de data sau este o expresie care folosete
operatorul de concatenare pentru iruri de caractere.
Efectul apelului metodei println este acela ca se realizeaz afiarea pe ecran a variabilei dat ca
parametru i se face salt la o linie noua.
Metoda println se poate apela i fr parametrii, adic n forma:
System.out.println( ); caz n care se face numai un salt la o linie nou fr sa se afieze
nimic.
Aplicaia 1
Scriei o surs Java care calculeaz masa ideal pentru brbai i femei n funcie de vrsta i
nlimea lor. Citirea datelor de intrare (nlimea i vrsta) se va realiza de la tastatur folosind
clasa Scanner.
Pentru a citi de la tastatur se poate folosi clasa Scanner, din pachetul java.util.
Consultai documentaia i observai metodele puse la dispoziie.
Scanner sc = new Scanner(System.n);
int n = sc.nextInt(); //citirea unui numr ntreg
package curs_1;
import java.util.Scanner;
17
masaidealab=masa;
masaidealaf=masa*0.9F;
}
}
Aplicaia 2
Scriei o surs Java care simuleaz n aruncri a dou zaruri. Afiai pe ecran numrul aruncrilor
ctigtoare. O aruncare se consider ctigtoare dac cele zaruri au acelai numr.
package curs_1;
import java.util.Scanner;
import java.util.Random;
18
Tem de autoinstruire
Consultai bibliografia pentru a afla :
3. Alte exemple de programe pentru a nelege mai bine structura programelor n Java, diferena
ntre programarea procedural i programarea orientat pe obiecte, modalitile de transmitere a
parametrilor n Java.
Teste de control
1. Fie urmtoarea declaraie Java:
int x=1;
String []names={"Andreea","Matei","Ana"};
names[--x]+=".";
for(int i=0;i<names.length;i++)
System.out.println(names[i]);
19
case 4:case5: System.out.print("26 ");
}}
public static void main(String []args){
for(int i=0;i<6;i++)
f(i);
}}
Care afirmaii sunt false?
A. Eroare la compilare;
B. Programul se compileaz i la execuie afieaz i 1 21 21 26 26 ;
C. Programul se compileaz i la execuie afieaz i 1 21 26 ;
D. Programul se compileaz i la execuie afieaz i 1 21 21 26 26 i;
Ce se poate spune despre acest cod, daca este integrat intr-un program Java?
A. Va produce eroare la compilare;
B. Va produce eroare la execuie;
C. Programul se compileaz i la execuie afieaz -3;
D. Programul se compileaz i la execuie afieaz -4.
20
Unitatea de nvare nr. 2
Definiie, declarare
Un tablou este o secven de componente de acelai tip. Acest tip poate fi un tip primitiv sau un tip
referin (deci putem lucra cu tablouri de obiecte).
Un tablou a poate fi declarat folosind una dintre urmtoarele modaliti:
tip[] a;
tip a[];
unde tip este tipul componentelor tabloului. n continuare vom folosi numai prima form.
Declararea unui tablou nu are drept consecin crearea sa. Crearea tabloului a declarat mai sus
trebuie fcut explicit, prin:
a = new tip[n];
unde n este o constant sau o variabil ntreag ce a primit o valoare strict pozitiv.
Cele de mai sus devin clare dac specificm faptul (menionat i n primul capitol) c un tablou este
un tip referin. Prin creare se obine un obiect de tip tablou (obiect numit prin abuz de limbaj tot
tablou).
Componentele tabloului pot fi referite prin a[i], cu i lund valori n intervalul 0..n-1; dac i nu
este n acest interval, va fi semnalat o eroare la executare. Lungimea tabloului poate fi referit prin
a.length.
21
Cmpul length al unui (obiect de tip) tablou este un cmp constant (cu modificatorii public i
final) de tip int; deci, odat creat, un obiect tablou nu i poate schimba dimensiunea (numrul
de componente). Pe de alt parte, variabilei referin la tablou i se poate asocia o referin la un
tablou de acelai tip.
Exemple:
tip[] a ;
a = new tip[10]; ...
a = new tip[20]; ...
este corect. Evident, noul tablou nu are nici o legtur cu cel vechi (n particular
nu se pstreaz valoarea nici unei componente a tabloului vechi).
Pentru interschimbarea coninutului a dou tablouri se poate proceda la fel ca
Exemplul 2
pentru interschimbarea valorilor a dou variabile primitive:
int[] a = {1,2,3,4}, b = {11,12,13}, c;
c=a; a=b; b=c;
deci practic se interschimb referinele la cele dou tablouri.
Tablouri multidimensionale
Limbajul Java permite lucrul cu tablouri multidimensionale. De exemplu expresia C[][] este un
tip ce reprezint tablouri bidimensionale ale cror componente au tipul C.
Tablourile multidimensionale trebuie gndite ca tablouri unidimensionale ale cror elemente sunt
tablouri unidimensionale etc. De aceea referirea la un element al unui tablou multidimensional a se
face prin:
a[indice1]...[indicen].
22
Este suficient s reducem discuia la tablouri bidimensionale, generalizarea fiind imediat. S
considerm urmtorul exemplu:
int[][] a = new int[3][];
a[0] = new int[3];
a[1] = new int[4];
a[2] = new int[2];
ceea ce arat c n Java tablourile nu sunt neaprat dreptunghiulare; aceasta conduce desigur la
economie de spaiu.
Evident, a[1].length=4.
La aceeai structur se poate ajunge i prntr-o iniializare efectiv:
int[][] a = { {0,1,2}, {1,2,3,4}, {2,3} };
care n plus atribuie valori elementelor tabloului.
Dac n referirea la un element al unui tablou unul dintre indici nu este n intervalul corespunztor,
va aprea eroarea (numit n Java excepie) cu numele:
IndexOutOfBoundsException
Reamintim c unei referine la un tablou i se poate asocia o referin la un alt tablou. Astfel, pentru
exemplul de mai sus poate apare n continuare:
a[1] = new int[7];
ceea ce permite s schimbm "o parte" dintr-un tablou fr a defini un altul i a copia prile
comune. De asemenea putem de exemplu s interschimbm dou "linii" ale tabloului de mai sus
prin:
int[] temp;
temp = a[0]; a[0] = a[2]; a[2]= temp;
Aplicaia 1
Scriei o surs Java care aloc un n memorie un tablou bidimensional cu n linii de forma:
1
1 2
1 2 3
. . .
1 2 3 . . . n
package Aplicatii;
import java.util.Scanner;
public class Tablou {
public static void main(String args[])
{
int n, i, j;
Scanner tas=new Scanner(System.n);
System.out.print("n= ");
n=tas.nextInt();
23
{
a[i]=new int[i+1];
for(j=0;j<i+1;j++)
a[i][j]=j+1;
}
for(i=0;i<n;i++)
{
for(j=0;j<i+1;j++)
System.out.print(a[i][j]+" ");
System.out.println();
}
}
}
Aplicaii propuse
1. Scriei o surs Java care interclaseaz doi vectori cu elemente ntregi citite de la tastatur.
2. Fie a un tablou de lungime n. Scriei o metod care deplaseaz elementele vectorului cu p poziii
spre dreapta, unde p este un numr dat de la tastatur.
24
Unitatea de nvare nr. 3
CLASE I OBIECTE
Obiective:
Clase
Un tip de date primitiv poate fi privit ca o reprezentare a unui concept. De exemplu, tipul
primitiv float, mpreun cu operaiile definite asupra acestuia (+, -, *, etc.) reprezint o
versiune a conceptului matematic de numere cu virgul. Pentru alte concepte, care nu au o
reprezentare direct prin tipurile primitive cunoscute de ctre maina virtuala Java, se pot
defini noi tipuri de date care s specifice aceste concepte. De asemenea, aceste tipuri de date
nu au ntotdeauna o reprezentare unitar. Spre exemplu, o aplicaie pentru realizarea
recensmntului persoanelor ar putea necesita un tip de date Persoana, care s includ
numele persoanei, vrsta, localitatea etc. O alt aplicaie poate necesita tipul de date Persoana
pentru calculul ntreinerii, caz n care se vor lua n calcul pentru acest concept alte
caracteristici, cum ar fi suprafaa locuit, numrul persoanelor aflate n ntreinere etc.
Definirea un nou tip de dat care s modeleze un anumit concept se poate realiza prin
definirea unui tip de dat compus, distinct, care s fie cunoscut mainii virtuale Java. Astfel
de tipuri de date compuse apar prin alturarea de variabile cu tipuri de date deja existente;
spre exemplu, pentru a reprezenta o dat calendaristica, ar putea fi suficient s cream un tip de
date care ncapsuleaz 3 variabile de tip int - pentru zi, luna i an. n schimb, pentru tipul de
date Persoana, este nevoie de o variabila de tip String pentru numele persoanei, una de tip int
pentru vrst etc. Desigur, nu este suficient doar s definim tipul de date abstract prin
compunerea mai multor date de tip primitiv, ci este necesar s se stabileasc i care setul de
operaii ce se va executa asupra datelor componente, precum i care sunt restriciile pentru
fiecare n parte.
O clas reprezint structura unui nou tip de date definit de ctre programator, spre deosebire
de primitive a cror structura este deja cunoscuta compilatorului i mainii virtuale. Pe baza
clasei putem construi obiecte, care sunt date de acel nou tip; crearea de obiecte ale unei clase
25
poarta numele de instaniere a clasei n cauz. Fiecare obiect este o instan (ncarnare) a
clasei, aa cum mai multe aparate de acelai fel pot fi construite pornind de la aceeai schem
electronic. La clase diferite vor corespunde tipuri de obiecte diferite, aa cum din doua
scheme electronice distincte obinem doua tipuri de aparate distincte.
Clasele reprezint o modalitate de a introduce noi tipuri de date ntr-o aplicaie Java, cealalt
modalitate fiind prin intermediul interfeelor.
26
Modificatorii de acces
n cazul n care declaram o clasa de obiecte ca fiind publica, atunci aceasta clasa poate fi
folosit (accesat) i din exteriorul pachetului din care face parte.
Daca o clasa nu este declarata ca fiind de tip public atunci ea va putea fi folosit (accesat)
doar de clasele din cadrul aceluiai pachet. Acest tip de acces la o clasa se numete package-
friendly i este implicit n Java.
Nota: Toate clasele care nu fac parte din nici un pachet, sunt considerate automat ca fcnd
parte din acelai pachet implicit. Ca o consecina, accesul de tip friendly se aplica pentru toate
aceste clase. Acesta este motivul pentru care vizibilitatea nu este afectata daca se omite
modificatorul public pentru clasele care nu fac parte dintr-un pachet. Totui, aceasta
modalitate de folosire a accesului de tip friendly nu este recomandat.
class A {
void metoda1(){
// Implementare
}
void metoda2(){
// Implementare
}
}
class NumeClasa {
[modificatori] NumeClasa([argumente]) { // Constructor}}
O clas poate avea unul sau mai muli constructori care trebuie ns s difere prin lista de
argumente primite. n felul acesta sunt permise diverse tipuri de iniializri ale obiectelor la
crearea lor, n funcie de numrul parametrilor cu care este apelat constructorul.
Exemplul 1
27
class Dreptunghi {
double x, y, w, h;
Dreptunghi(double x1, double y1, double w1, double h1) {
// Constructor general
x=x1; y=y1; w=w1; h=h1;
System.out.println("Instantiere dreptunghi");
}
Dreptunghi(double w1, double h1) {
// Constructor cu doua argumente
x=0; y=0; w=w1; h=h1;
System.out.println("Instantiere dreptunghi");
}
Dreptunghi() {
// Constructor fr argumente
x=0; y=0; w=0; h=0;
System.out.println("Instantiere dreptunghi");
}
}
Constructorii sunt apelai automat la instanierea unui obiect. n cazul n care dorim sa
apelam explicit constructorul unei clase folosim expresia
this( argumente )
Exemplul 2
class Dreptunghi {
double x, y, w, h;
Dreptunghi(double x1, double y1, double w1, double h1) {
// Implementam doar constructorul general
x=x1; y=y1; w=w1; h=h1;
System.out.println("Instantiere dreptunghi");
}
Dreptunghi(double w1, double h1) {
this(0, 0, w1, h1);
// Apelm constructorul cu 4 argumente
}
Dreptunghi() {
this(0, 0);
// Apelm constructorul cu 2 argumente
}
}
Constructorul implicit
Constructorii sunt apelati automat la instantierea unui obiect. n cazul n care scriem o
clasa care nu are declarat nici un constructor, sistemul ii creeaza automat un constructor
28
implicit, care nu primeste nici un argument i care nu face nimic. Deci prezenta
constructorilor n corpul unei clase nu este obligatorie. Daca insa scriem 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 ctre sistem. Sa consideram, ca exemplu,
urmatoarele declaratii de clase:
class Dreptunghi {
double x, y, w, h;
// Nici un constructor
}
class Cerc {
double x, y, r;
// Constructor cu 3 argumente
Cerc(double x, double y, double r) { ... };
}
Exemplu 3
Sa consideram acum doua instantieri ale claselor de mai sus:
Variabilele membre ale unei clase se declara de obicei inaintea metodelor, desi acest
lucru nu este impus de ctre compilator.
class NumeClasa {
// Declararea variabilelor
// Declararea metodelor
}
Variabilele membre ale unei clase se declara n corpul clasei i nu n corpul unei
metode, fiind vizibile n toate metodele respectivei clase. Variabilele declarate n cadrul
unei metode sunt locale metodei respective.
29
daca este constanta sau nu
daca este variabila de instanta sau de clasa
alti modificatori
Modificatori:
static
Prezenta lui declara ca o variabila este variabila de clasa i nu de instanta.
int variabilaInstanta ;
static int variabilaClasa;
final
Indica faptul ca valoarea variabilei nu mai poate fi schimbata, cu alte cuvinte este folosit
pentru declararea 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 i ulterior intr-un constructor, dupa care ea nu va mai putea fi modificata.
class Test {
final int MAX;
Test() {
MAX = 100; // Corect
MAX = 200; // Eroare la compilare !
}
}
30
Implementarea metodelor
Metodele sunt responsabile cu descrierea comportamentului unui obiect. Intrucat Java este un
limbaj de programare complet orientat-obiect, metodele se pot gasi doar n cadrul claselor.
Generic, o metoda se declara astfel:
[modificatori] TipReturnat numeMetoda ( [argumente] )
[throws TipExceptie1, TipExceptie2, ...]
{
// Corpul metodei
}
unde un modificator poate fi :
un specificator de acces : public, protected, private
unul din cuvintele rezervate: static, abstract, final, native, synchronized;
abstract
Permite declararea metodelor abstracte. O metoda abstracta este o metoda care nu are
implementare i trebuie obligatoriu sa faca parte dntr-o clasa abstracta.
final
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 consistent starii unui obiect. De exemplu, studentilor unei universitati trebuie sa
li se calculeze media finala, n functie de notele obtinute la examene, n aceiai maniera,
indiferent de facultatea la care sunt.
class Student {
...
final float calcMedie(float note[], float ponderi[]) {
...
}
...
}
class StudentInformatica extends Student {
float calcMedie(float note[], float ponderi[]) {
return 10.00;
}
}// Eroare la compilare !
Apelul metodelor
Apelul unei metode definita ntr-o clasa de obiecte se realizeaza n mai multe moduri:
- prin crearea i utilizarea unei instante a clasei n care a fost definita metoda sau a unei
subclase a clasei respective (ca regula generala de invocare a unei metode); n acest caz se
31
foloseste operatorul punct ( . ), n stinga acestuia punandu-se numele instantei, iar n dreapa
acestuia punandu-se numele metodei;
- prin simpla folosire a numelui sau, n cazul n care clasa n care este apelata metoda este
aceiai cu clasa n care a fost definita; aceasta modalitate este folosita daca atat metoda
apelanta ct i metoda apelata sunt fie numai metode de instanta, fie numai metode de clasa;
- prin folosirea operatorului punct ( . ), n stanga acestuia punandu-se numele clasei n care a
fost definita, iar n dreapta acestuia punandu-se numele metodei; aceasta modalitate este
folosita numai daca metoda este definita ca metoda de clasa.
Exemplu 4
Varianta de apel a unei metode prin simpla folosire a numelui metodei, deoarece metoda este
definita i apelata n aceiai clasa. Totusi metoda creareTablou trebuie sa fie declarata ca
metoda de clasa (modificatorul static) pentru a putea fi apelata dntr-o alta metoda de clasa.
public class ClasaTablou2 {
static int [] creareTablou(int inf, int sup){
int [] tabl = new int[(sup - inf) +1];
for (int i = 0 ; i < tabl.length; i++)
tabl[i] = inf++;
return tabl;
}
public static void main(String args[])
{
int [] tablou = creareTablou(1,10);
System.out.print("Tabloul: [ ");
for (int i = 0; i < tablou.length; i++)
System.out.print(tablou[i] + " ");
System.out.println("]");
}
}
32
Metode de instanta
Ca regula generala, o metoda definita ntr-o clasa se poate apela prin crearea unei
instante a clasei respective sau a unei subclase a clasei respective. Aceasta se datoreaza
faptului ca metoda lucreaza cu o serie de variabile ale clasei care sunt memorate n
interiorul instantei i care au valori diferite n instante diferite (numite variabile de
instanta). Astfel de metode se numesc metode ale instantelor clasei.
Metodele de instanta sunt aplicate unui anume obiect, nu unei clase intregi. Majoritatea
metodelor definite ntr-o clasa sunt metode de instanta.
Metode de clasa
Dupa cum stim deja, exista i un alt tip de variabile i anume variabilele de clasa sau
variabilele statice care sunt comune tuturor instantelor clasei respective. Aceste
variabile pot fi accesate fara a avea nevoie de o instanta a clasei n care au fost
declarate.
n mod similar exista i metode de clasa sau metode statice. Pentru a fi apelate, aceste
metode, definite ntr-o clasa, nu au nevoie sa fie creata o instanta a clasei respective sau
a subclasei derivata din clasa respectiva. Metodele de clasa sunt disponibile oricarei
instante a clasei.
O metoda este accesibila (apelabila) daca este definita n clasa din care este apelata sau
intr-una din subclasele acesteia. Atunci cand se apeleaza metoda unui obiect, Java cauta
definitia metodei respective n clasa obiectului. Daca nu o gaseste, cauta mai sus n
ierarhia de clase pana cand gaseste o definitie.
n acelasi timp pentru a vedea o metoda i pentru a o putea apela, este nevoie sa avem
drepturile de acces necesare (date de modificatorii de acces).
Modificatorul public face ca metoda respectiva sa fie accesibila oriunde este accesibila
clasa din care face parte metoda.
Modificatorul protected face ca metoda respectiva sa fie accesibila n orice clasa din
pachetul careia ii apartine clasa n care a fost definita. n acelasi timp, metoda este
accesibila n toate subclasele clasei date, chiar daca ele apartin altor pachete.
Modificatorul private face ca metoda respectiva sa fie accesibila doar n interiorul clasei
n care a fost definita.
Daca pentru o metoda a unei clase nu se precizeaza nici un modificator de acces din cei
descrisi mai sus, atunci metoda respectiva devine package-friendly. O metoda
friendly este accesibila n pachetul din care face parte clasa n interiorul careia a fost
definita, dar nu este accesibila n subclasele clasei date daca acestea apartin altor
pachete.
33
Nota: Modificatorii de acces (public, protected, private) sunt plasati primii n definitia
metodei, urmeaza apoi modificatorii care determina felul metodei (static, abstract,
final) i apoi semnatura metodei.
class Cerc
{
private double raza;
public void setRaza(double r) {
raza = r; }
public double getRaza() {
return raza; }
public double arie() {
return Math.PI * raza * raza; }
public double lungime() {
return 2 * Math.PI * raza; }
}
public class TestCerc
{
public static void main(String[] args) {
Cerc cerculMeu = new Cerc();
cerculMeu.setRaza(10);
System.out.println("Raza=" + cerculMeu.getRaza());
System.out.println("Aria=" + cerculMeu.arie());
System.out.println("Lungimea=" +
cerculMeu.lungime());
}
}
Observatie: Deoarece fisierul-sursa TestCerc.java contine o clasa publica, TestCerc,
numele fisierului trebuie sa fie identic cu numele clasei publice, altfel compilarea nu se
va face cu succes. Intr-un fisier-sursa nu se poate defini decat o singura clasa publica.
Referinta this
Cuvantul-cheie this se refera la obiectul curent, adica obiectul a carei metoda a fost
apelata. Metoda poate folosi variabilele de instanta ale obiectului curent sau poate
transmite obiectul curent ca parametru unei alte metode. Iata cateva exemple de folosire
a cuvantului this:
t = this.x; // variabila de instanta x pentru acest obiect
this.resetRaza(this); // apeleaza metoda resetRaza, definita n clasa
curenta i
// transmite obiectul curent
return this; // returneaza obiectul curent
n cele mai multe cazuri nu este nevoie sa se foloseasca explicit cuvantul-cheie this,
deoarece este presupus. De exemplu, ne putem referi atat la variabilele de instanta, ct i
34
la apelurile de metode definite n clasa curenta prin simpla folosire a numelui lor,
deoarece this este implicit folosit de aceste referinte.
De aceea, primele doua exemple se pot rescrie astfel:
t = x; // variabila de instanta x pentru acest obiect
resetRaza(this); // apeleaza metoda resetRaza, definita n clasa curenta
Crearea obiectelor
n Java, ca n orice limbaj de programare orientat-obiect, crearea obiectelor se
realizeaza prin instantierea unei clase i implica urmatoarele etape:
Declararea
Presupune specificarea tipului acelui obiect, cu alte cuvinte specificarea clasei acestuia
NumeClasa numeObiect;
Instantiere
Initializarea
Sa consideram urmatorul exemplu, n care declaram i instantiem doua obiecte din clasa
Rectangle, clasa ce descrie suprafete grafice rectangulare, definite de coordonatele
coltului stanga sus (originea) i latimea, respective inaltimea.
n primul caz Rectangle() este un apel ctre constructorul clasei Rectangle care este
responsabil cu initializarea obiectului cu valorile implicite. Dupa cum observam n al
doilea caz, initializarea se poate face i cu anumiti parametri, cu conditia sa existe un
constructor al clasei respective care sa accepte parametrii respectivi.
35
Fiecare clasa are un set de constructori care se ocupa cu initializare obiectelor nou
create. De exemplu, clasa Rectangle are urmatorii constructori:
public Rectangle()
public Rectangle(int latime, int inaltime)
public Rectangle(int x, int y, int latime, int inaltime)
public Rectangle(Point origine)
public Rectangle(Point origine, int latime, int inaltime)
public Rectangle(Point origine, Dimension dimensiune)
Declararea, instantierea i initializarea obiectului pot aparea pe aceiai linie (cazul cel
mai uzual):
Rectangle patrat = new Rectangle(0, 0, 100, 100);
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, respectiv prin 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
patrat.x = 10;
patrat.y = 20; //schimba originea
patrat.origin = new Point(10, 20); //schimba originea
36
Rolul operatorului new
La folosirea operatorului new se execut urmatoarele:
- se creaza o noua instanta a clasei date;
- se aloca memorie pentru aceasta instanta;
- se apeleaza o metoda speciala a clasei numita constructor.
Distrugerea obiectelor
Aplicaie 1 Construii un proiect Java care cuprinde ntr-un pachet Clase o clas care
modeleaz noiunea student. Clasa conine date membre precum: nume,
medie. ntr-un pachet de aplicaii, scriei o surs Java care n care definii un
obiect de tip Student. n acelai pachet de aplicaii scriei o surs Java care
definete un tablou de obiecte de tip Student i afieaz n fereastra System
numrul obiectelor instantiate.
package Clase;
public Student() {
this.nume="####";
this.medie=0.0;
37
nrObiecte++;
}
public String getNume() {
return nume;
}
Sursa Java
package Clase;
import Clase.Student;
Aplicatie propus
Construii un proiect Java care cuprinde ntr-un pachet Surse o clas care modeleaz noiunea de
angajat al firmei BestIT. Clasa conine date membre precum: nume, varsta, firma, salariu. ntr-un
pachet de aplicaii, scriei o surs Java care n care definii un obiect de tip Angajat. Testai pentru
obiectul creat metodele motenite din clasa Object. n acelai pachet de aplicaii scriei o surs Java
care definete un tablou de obiecte de tip Angajat i afieaz n fereastra System ci angajai sunt
ntr-un stagiu de internship. Un angajat se consider a fi ntr-un stagiu de internship dac are vrsta
mai mica dect 25.
38
Tema de autoinstruire
2. Dac C este o clas fr un constructor definit, avnd un cmp x de tip ntreg, scriei
instruciunile prin care se creeaz un obiect ob de tip C i se afieaz valoarea cmpului
x al obiectului ob.
3. Cum se numete posibilitatea de a exista mai muli constructori, respectiv mai multe
metode cu acelai nume, dar cu signaturi diferite? Exemplificai.
class Doi{
void modific(int x){x=2;}
void modific(Pereche c){c.im=2;}
}
class M {
public static void main(String sir[]){
Doi d=new Doi();
Pereche c=new Pereche(5,6); c.afis();
d.modific(c.re); c.afis();
d.modific(c);c.afis();
}
}
Teste de control
1. Declararea constructorilor trebuie sa tina cont de:
A. relatia de motenire dintre clase;
B. numele constructorului, care trebuie sa fi identic cu numele clasei;
C. comportamentul obiectelor pe care le instantiaza;
D. o metoda prin care poate fi accesat de toate tipurile din Java sau de tipuri mostenite
din tipul care contine membrul n discutie;
39
this.x=x;
}
int getX_C1(){
Return x;}}
Class C2 extens C1{
float x=5.0f;
int f(int x){
super.f((int)x);}
float getX_C2(){
return x;}}
public class Subiect9{
public static void main(String []args){
C2 obiect = new C2();
obiect.f(4);
System.out.print(obiect.getX_C2() + " ");
System.out.println(obiect.getX_C1());}}
A. Programul este corect i va afisa la executie 5 4;
B. Programul este corect i va afisa la executie 4.0 4;
C. Va aparea eroare la compilare deoarece n clasa C2 s-a suprascris gresit atributul x
din clasa C1;
D. Va aparea eroare la compilare deoarece metoda suprascrisa f() din clasa C2 intoarce
un tip diferit de void;
41
Unitatea de nvare nr. 4
Obiective:
irurile (de caractere) din Java sunt obiecte standard. Orice ir este un obiect al clasei String, ce
apare n pachetul java.lang:
public final class String extends Object
S observm diferenele fa de lucrul cu tablouri. Dac s este un ir, iar a un tablou, atunci:
- s.length() este lungimea irului, iar a.length este lungimea tabloului;
- s.charAt(i) este caracterul de pe poziia i din ir, iar a[i] este elementul de pe
poziia i din tablou.
42
Invocarea metodei charAt cu un indice n afara irului lanseaz excepia:
IndexOutOfBoundsException. Aceast excepie mai poate fi lansat i de alte metode
prezentate n continuare (identificarea lor se face cu uurin).
Urmtoarele metode ale clasei String ntorc un rezultat de tipul int, ce reprezint o poziie cu o
anumit proprietate din irul s prin care au fost invocate (dac o astfel de poziie nu exist, este
ntoars valoarea 1).
Exemplul 1
Urmtorul program citete dou iruri i determin numrul de apariii al celui de al doilea n
primul. irurile sunt introduse la executare din linia de comand.
class nr_apar {
static int nrapar(String s, String subs) {
int nr=0, indice, poz=0;
indice = s.indexOf(subs,poz);
while (indice>=0 && indice<s.length()) {
nr++; poz++;
indice = s.indexOf(subs,poz);
}
return nr;
}
43
Compararea irurilor
Clasa String prevede metode pentru compararea coninutului irului care invoc metoda cu
coninutul unui ir transmis ca argument. Vom presupune c irul care invoc metodele este s.
Compararea se refer la iruri n totalitatea lor sau la subsecvene ale lor.
Metodele clasei String ce se ncadreaz aici sunt urmtoarele (vom presupunde din nou c irul care
invoc metoda este notat prin s):
String substring(int p) :
este ntors subirul lui s ce ncepe de pe poziia p;
String substring(int p, int u) :
este ntors subirul lui s ce ncepe de pe poziia p i se termin pe poziia u-1;
String replace(char c1, char c2) :
este ntors irul obinut din s prin nlocuirea tuturor caracterelor c1 prin caracterul c2;
String toUpperCase() :
fiecare caracter este nlocuit cu echivalentul su majuscul, dac acesta exist;
String toLowerCase() :
fiecare "liter mic" este nlocuit cu "liter mare", dac aceast coresponden exist;
String trim() :
ntoarce irul obinut din s prin eliminarea spaiilor albe de la nceputul i sfritul su;
String concat(String s1) :
ntoarce irul s+s1.
44
iruri i tablouri de caractere
Clasa String prevede metode pentru transformarea irurilor n tablouri de caractere, precum i
pentru transformarea invers:
Exemplu 2
Pentru a determina irul obinut din irul s prin considerarea elementelor sale n ordine invers,
putem scrie urmtoarea metod:
Conversii
n multe cazuri suntem pui n situaia de a converti valori numerice n iruri sau de a trebui s
lucrm cu o valoare numeric memorat ntr-un ir.
irul ce corespunde unei valori numerice sau booleene x se obine simplu prin:
String.valueOf(x)
Metoda valueOf a clasei String mai poate fi invocat i pentru un caracter: va fi ntors irul
format din acel unic caracter.
Transformarea invers (de la un ir ce conine un literal boolean sau numeric) la acel literal se poate
realiza folosind metodele puse la dispoziie de clasele nfurtoare.
45
Aplicaii propuse
1. Scriei o surs Java care citete un ir de caractere de la tastatur i care realizeaz urmtoarele
cerine:
a. Afiez pe ecran numrul cuvintelor (acestea pot fi separate prin diferite semne de
punctuaie)
b. Sorteaz n ordine descresctoare cuvintele irului.
c. nlocuiete toate cuvintele de lugime maxim cu cele de lungime minima
2. Scriei o surs Java care citete dntr-o fereastr de dialog CNP-ul unei persoane i afieaz
vrsta acesteia.
3. Scriei o aplicaie Java care, pentru un cuvnt dat de la tastatur afieaz numrul de vocale din
cuvnt i cea mai lung subsecven de consoane (consecutive) din cuvnt.
4. Scriei o surs Java care verific dac dou iruri sunt anagrame
46
Unitatea de nvare nr. 5
EXTINDEREA CLASELOR
Aa cum am menionat de la nceput, limbajul Java a fost conceput ca un limbaj orientat pe obiecte.
Am prezentat deja una dintre caracteristicile orientrii spre obiecte i anume ncapsularea (datele
mpreun cu operaiile asupra lor sunt "puse la un loc" i anume ntr-o clas).
Vom studia acum modul n care Java trateaz alte aspecte ale programrii orientate pe obiecte:
extinderea claselor, polimorfismul i legarea dinamic.
La prima vedere, rezolvarea problemelor de mai sus se poate face simplu: modificm clasa,
introducnd sau/i modificnd cmpurile i metodele clasei. n practica programrii, aceast soluie
este de neconceput. Pe de o parte se pot introduce erori, iar pe de alt parte utilizatorii clasei vechi
nu vor mai putea folosi clasa aa cum o fceau nainte i cum vor n continuare s o fac, nefiind
interesai de noile faciliti; clasa (firma care a elaborat-o) i va pierde astfel vechii clieni. De
aceea vechea clas trebuie s rmn nemodificat, iar actualizarea ei trebuie fcut prin
mecanismul de extindere a claselor, prezentat n continuare.
S reinem deci ca o regul general de programare faptul c nu trebuie modificat o clas testat i
deja folosit de muli utilizatori; cu alte cuvinte, nu trebuie modificat "contractul" ce a dus la
scrierea clasei.
47
Un prim exemplu
Exemplul 1 S presupunem c dorim s urmrim micarea unui punct n plan. Vom ncepe
prin a considera clasa:
class Punct {
int x,y; Punct urm;
Punct(int x, int y) { this.x=x; this.y=y; }
void Origine() { x=0; y=0; }
Punct Miscare(int x, int y) {
Punct p = new Punct(x,y); urm=p; return p;
}
}
Este adoptat urmtoarea terminologie: clasa Punct este superclas a lui Pixel, iar Pixel este
subclas (clas extins) a lui Punct.
n Java, clasele formeaz o structur de arbore n care rdcina este clasa Object, a crei definiie
apare n pachetul java.lang. Orice clas extinde direct (implicit sau explicit) sau indirect clasa
Object. tim c n informatic arborii "cresc n jos", deci rdcina (clasa Object) se afl pe cel
mai de sus nivel.
Termenii de superclas i subclas se refer exclusiv la relaia tat fiu, conform relaiei de
extindere, n arborele de clase. Este incorect de a interpreta aceti termeni n sensul de incluziune!
O metod declarat ntr-o clas poate fi rescris ntr-o subclas prin declararea ei n subclas cu
acelai nume, aceeai signatur i acelai tip al valorii ntoarse. n metoda rescris putem schimba
modificatorul de acces, cu condiia ca dreptul de acces s creasc; reamintim c modificatorii de
acces, n ordine de la cel mai restrictiv la cel mai permisiv, sunt: private, protected, cel
implicit (package) i public.
Spunem c metodele rescrise sunt ascunse (dac e vorba de metode statice) sau redefinite (n cazul
metodelor nestatice). Nu este vorba numai de o diferen de terminologie, deoarece metodele statice
pot fi rescrise (ascunse) numai de metode statice, iar metodele nestatice pot fi rescrise (redefinite)
numai de metode nestatice. Alte precizri vor fi fcute n continuare.
Fie A o clas i fie B o subclas a sa. S considerm urmtoarele patru aciuni echivalente din
punctul de vedere al obiectului a ce ia natere:
1) A a; a = new B(...);
2) A a = new B(...);
3) A a; B b; b = new B(...); a = b;
4) A a; B b; b = new B(...); a = (A) b;
S observm c este vorba de o conversie de la o subclas la o superclas, conversie numit
upcasting; ea poate fi implicit (ca n primele trei aciuni) sau explicit (ca n cea de a patra
aciune).
49
Vom spune c obiectul a are tipul declarat A i tipul real B, ceea ce pune n eviden noiunea de
polimorfism.
Tipul real al unui obiect coincide cu tipul su declarat (este cazul obiectului b) sau este o subclas a
tipului declarat (vezi obiectul a).
Fie camp un cmp al clasei A, ce este redeclarat (ascuns) n subclasa B. Dac obiectul a face
referire la cmpul camp, atunci este vorba de cmpul declarat n clasa A, adic este folosit tipul
declarat al obiectului.
Fie met o metod a clasei A, care este rescris n subclasa B. La invocarea metodei met de ctre
obiectul a, este folosit fie implementarea corespunztoare metodei ascunse (dac este static), fie
cea corespunztoare metodei redefinite (dac este nestatic). Cu alte cuvinte, pentru metode statice
este folosit tipul declarat (la fel ca pentru cmpuri), iar pentru metode nestatice este folosit tipul real
al obiectului. n ambele cazuri, se pleac de la tipul indicat mai sus i se merge n sus spre rdcin
(clasa Object) n arborele de clase pn cnd se ajunge la primul tip n care apare metoda
respectiv (evident cu signatura corespunztoare); inexistena unui astfel de tip este semnalat chiar
n faza de compilare.
class Super {
static void met1() {
System.out.println("static_Super"); }
void met2() { System.out.println("Super"); }
}
class Test1 {
public static void main(String[] s) {
Super Ob = new Sub(); Ob.met1(); Ob.met2();
}
}
produce la ieire:
static_Super
Sub
class A {
int va=1, v;
A() { v=va; System.out.print(""+met()); }
int met() { return va; }
}
class B extends A {
50
int vb=2, v;
B() { v=va+vb; }
int met() { return vb; }
}
class Constr {
public static void main (String[] s) {
A a = new B(); System.out.println("\t"+a.met());
}
}
- invocarea metodei met n metoda principal, realizat de obiectul a, se va referi tot la metoda
met din clasa B.
class A {
String s="Super";
void scrie() { System.out.println("A : "+s); }
}
class B extends A {
String s="Sub";
void scrie() { System.out.println("B : "+s); }
}
class AB1 {
public static void main(String[] s) {
B b = new B(); A a = b;
a.scrie(); b.scrie();
System.out.println(a.s + "\t" + b.s);
}
}
La executare sunt tiprite urmtoarele:
B : Sub
B : Sub
Super Sub
adic rezultatele ateptate, innd cont c:
- pentru obiectul b: tipul declarat coincide cu cel real i este B;
- pentru obiectul a: tipul declarat este A, iar tipul real este B.
51
S considerm o clas C i dou subclase X i Y ale sale, precum i urmtoarea secven de
instruciuni:
C Ob;
. . . Ob = new X(...);
. . . Ob = new C(...);
. . . Ob = new Y(...);
. . .
n care Ob are mai nti tipul real X, apoi tipul real C, apoi tipul real Y. Spunem c Ob este o
variabil polimorfic, deoarece are pe rnd forma (comportamentul) a mai multor clase.
Din exemplul de mai sus rezult clar c doar la momentul executrii putem determina necesarul de
memorie pentru obiectul Ob, ceea ce justific de ce la creare obiectele sunt "stocate" n heap-ul
memoriei. Mai precis, la crearea unui obiect este alocat spaiu pentru toate cmpurile nestatice din
clas, inclusiv pentru cele ascunse.
Putem folosi cuvntul cheie super n orice metod nestatic a unei clase extinse, i anume sub una
dintre formele:
- super(...) : pentru a invoca un constructor al superclasei clasei curente;
- super.met(...) : pentru a invoca o metod a superclasei, metod ce a fost redefinit n clasa
curent;
- super.c : pentru a accesa un cmp c al superclasei, cmp ce a fost ascuns n clasa curent prin
redefinirea sa.
Observm c la accesarea unui cmp sau a unei metode, super acioneaz ca referin la obiectul
curent ca instaniere a superclasei sale.
class A {
String s="Super";
void scrie() { System.out.println("A : "+s); }
void metoda() { System.out.println("A:"); }
}
class B extends A {
String s="Sub";
void scrie() { System.out.println("B : "+s+"
"+super.s); }
void metoda() { scrie(); super.scrie();
super.metoda(); }
}
class AB2 {
public static void main(String[] x) {
B b = new B(); b.metoda(); System.out.println(b.s);
System.out.println("****************");
A a; a = b; a.metoda(); System.out.println(a.s);
52
System.out.println("****************");
A c = new A(); c.metoda(); System.out.println(c.s);
}
}
Sunt incorecte, nencadrndu-se n formele prezentate mai sus de folosire a lui super, construcii
de forma b.super.metoda() (care ar inteniona ca pentru obiectul b s invocm metoda
metoda din superclasa clasei de tipul creia este) sau urcarea mai multor niveluri n arborele de
clase prin super.super. Pentru a avea acces la un cmp ascuns aflat cu dou niveluri mai sus n
arborele de clase putem proceda de pild ca n exemplul urmtor.
class A {
int x=1;
void met() { System.out.print("\t"+x); }
}
class B extends A {
boolean x=false;
void met() { System.out.print("\t"+x); super.met(); }
}
class C extends B {
double x=3.14;
void met() { System.out.print("\t"+x); super.met(); }
}
class SubSup {
public static void main (String[] s) {
C Ob = new C(); Ob.met();
}
}
produce la ieire:
3.14 false 1
53
Motenire, polimorfism i legare dinamic
Reamintim urmtoarele:
- orice obiect care instaniaz o clas poate fi folosit n orice cod menit s lucreze cu instanieri ale
superclaselor sale;
- orice obiect care instaniaz o clas poate folosi (n modurile descrise mai sus) codul supraclasei.
La aceste dou caracteristici legate de motenire (extinderea claselor), Java adaug polimorfismul i
legarea dinamic, ntre care exist o strns relaie.
Aa cum am precizat n subcapitolul precedent, fiecare obiect are un tip declarat i un tip real; tipul
real coincide cu cel declarat sau este un subtip al acestuia. La invocarea metodelor nestatice se
folosete tipul real, iar la invocarea metodelor statice i la referirea cmpurilor se folosete tipul
declarat. Menionm c n literatura consacrat programrii orientate pe obiecte nu este agreat
opiunea Java de a folosi pentru cmpuri tipul declarat i nu pe cel real.
Pentru metode nestatice se folosete tipul real al obiectelor care le invoc deoarece:
- cronologic, superclasa a fost scris naintea clasei i este de presupus c a fost folosit de mai
muli utilizatori, care vor n continuare s lucreze cu ea;
- n metodele noii clase se pot face referiri la cmpuri nou definite, ceea ce nu este posibil pentru
metodele superclasei.
Utilizarea tipului declarat pentru metodele statice se datoreaz urmtorului fapt: compilatorul "face
tot ce poate" pentru a detecta metoda ce trebuie invocat.
Java folosete legarea dinamic, adic identificarea metodei nestatice concrete care este folosit la
o invocare se face la executare i nu la compilare. De aceea legarea dinamic se mai numete legare
trzie.
Exemplul 7 Fie A o clas n care este definit o metod met, iar B o subclas a sa n care
metoda met este redefinit. Secvena de instruciuni
A Ob;
citete d
if (d>0) Ob = new A(...);
else Ob = new B(...);
Ob.met(...);
arat c doar la momentul invocrii metodei devine clar care dintre cele dou
metode met va fi invocat.
54
Aplicatie 1
Se definete o clas Persoana cu datele membre nume,varsta. Clasa Angajat extinde clasa
Persoana.
package extinderi;
class Persoana
{
String nume;
int varsta;
56
Tem de autoinstruire
Teste de control
1. Care este clasa motenit direct sau indirect de orice clasa n Java?
class Unu{
int x;
Unu(int x){this.x=x; afis();}
void afis(){ System.out.println(x);}
void dublu(){x*=2;}
static void nume(){System.out.println("Unu");}
}
class Doi extends Unu{
int y;
Doi(int x,int y){
super(x); this.y=y; afis();
}
void afis(){ System.out.println(x+" "+y);}
void dublu(){
super.dublu();
y*=2;
}
static void nume(){System.out.println("Doi");}
}
class Test{
public static void main(String sir[]){
Doi d=new Doi(4,5);
d.dublu(); d.afis();
Unu u=(Unu)d;
u.dublu(); u.afis();
d.afis();
u.nume();d.nume();
}
}
57
Unitatea de nvare nr. 6
Nu este posibil s crem obiecte ca instane ale unei clase abstracte. Pe de alt parte, ntr-o subclas
putem s redefinim o metod a superclasei transformnd-o ntr-o metod abstract; aceasta are sens
de exemplu dac n subarborele avnd ca rdcin subclasa, comportamentul materializat prin acea
clas nu mai este valabil n subarbore i este specific fiecrei extensii a subclasei.
Un prim exemplu
Exemplul 1 Urmtoarea clas are ca scop s msoare timpul necesitat de executarea unei
metode oarecare fr parametri i care nu ntoarce vreun rezultat:
abstract class C {
abstract void met();
public long timp() {
long t0 = System.currentTimeMillis();
met();
return System.currentTimeMillis()-t0;
}
}
58
clase, putem apela metoda timp pentru a determina timpul de executare a metodei
met, ce are acum o implementare precis:
class C1 extends C {
void met () {
int x=0;
for (int i=0; i<1000000; i++) x=x+1-1;
}
}
class Abstr {
public static void main(String[] s) {
C1 Ob = new C1();
System.out.println( "durata="+Ob.timp() );
}
}
Legat de exemplul de mai sus, nu trebuie s ne mire c e posibil ca la executri diferite s obinem
timpi diferii: aceasta este o consecin a faptului c pe perioada executrii programului nostru
sistemul gazd "mai face i altceva", sau c a intervenit colectorul de reziduuri.
Noiunea de interfa
Aa cum s-a menionat anterior, este posibil s declarm clase abstracte n care toate metodele sunt
abstracte. Acest lucru poate fi realizat i prin intermediul interfeelor. n plus, aa cum vom vedea n
continuare, ele reprezint mecanismul propus de Java pentru tratarea problemelor ridicate de
motenirea multipl.
Motenirea multipl este facilitatea oferit de unele limbaje de programare ca o clas s
moteneasc (prin extindere) membri ai mai multor clase. Evident, aceast caracteristic important
a programrii orientate pe obiecte nu este neglijat n Java. Modul n care aceast facilitate poate fi
implementat n Java va fi tratat n continuare.
Interfeele reprezint o modalitate de a declara un tip constnd numai din constante i din metode
abstracte. Ca sintax, o interfa este asemntoare unei clase, cu deosebire c n loc de class
trebuie precizat interface, iar metodele nu au corp, acesta fiind nlocuit cu ';'.
Putem spune c interfeele reprezint numai proiecte, pe cnd clasele sunt o combinaie de proiecte
i implementri. Ca i n cazul claselor abstracte, este evident c nu pot fi create obiecte de tipul
unei interfee.
Cmpurile unei interfee au n mod implicit modificatorii static i final, deci sunt constante.
Metodele interfeelor sunt totdeauna publice i au n mod implicit modificatorul abstract. n
plus ele nu pot fi statice, deoarece fiind abstracte, nu pot fi specifice claselor.
Orice interfa este gndit pentru a fi ulterior implementat de o clas, n care metodele interfeei
s fie redefinite, adic s fie specificate aciunile ce trebuie ntreprinse. Faptul c o clas C
implementeaz o interfa I trebuie specificat prin inserarea informaiei implements I n
antetul clasei.
59
Exemplul 2 Prezentm un prim exemplu de implementare a unei interfee.
interface I {
char c=a; int i=0;
void scrie();
}
class C implements I {
public void scrie() { System.out.println(c+" "+i); }
}
Precizm urmtoarele:
- o interfa poate extinde oricte interfee. n acest mod interfeele permit motenirea unor
"contracte" (numele i signaturile unor metode) fr motenirea implementrii;
- dac o clas implementeaz doar unele din metodele unei interfee, atunci ea trebuie declarat cu
abstract;
- spre deosebire de interfee (care sunt limitate la constante i anunuri de metode), clasele abstracte
pot avea implementri pariale, metode statice, membri cu modificatorul protected, cmpuri
care nu sunt finale etc.;
- o clas poate implementa oricte interfee, dar poate extinde o singur clas.
Dac o clas extinde o alt clas i implementeaz una sau mai multe interfee, atunci trebuie
anunat nti extinderea i apoi implementarea, ca n exemplul urmtor:
Aa cum vom vedea n continuare, facilitatea ca interfeele i clasele s poat extinde oricte
interfee reprezint modalitatea prin care Java rezolv problema motenirii multiple.
Dac s-ar permite ca o clas s extind mai multe clase, ar aprea neclariti legate de semnificaia
numelor. Astfel, dac ar fi posibil urmtoarea structur de clase extinse:
W
X Y
Mai menionm c putem declara variabile avnd ca tip numele unei interfee. Unei astfel de
variabile i poate fi atribuit un obiect care implementeaz interfaa (are ca tip real o clas ce
implementeaz interfaa).
60
Un exemplu ce ilustreaz aceste elemente va fi prezentat n paragraful destinat implementrii
interfeelor.
ntrebare: Se tie c o clas poate avea un singur printe. Este valabil aceast afirmaie i in
cazul interfeelor, in sensul ca o interfa poate implementa o singur interfa?
Rspuns: Nu. O interfa poate implementa oricte interfee. De asemenea o clas poate
implementa oricte interfee.
Extinderea interfeelor
Ca i clasele, interfeele pot fi extinse. O interfa I poate extinde oricte interfee, n acest mod
adugndu-se la I noi constante i (anunuri de) metode.
Este permis ca o interfa ce extinde alt interfa s conin o constant cu acelai nume. De
exemplu pentru urmtoarea structur de interfee:
W
X Y
este posibil ca n una sau mai multe dintre interfee s fie declarat o constant c. Deosebim dou
cazuri:
1) Constanta c este redeclarat n interfaa Z : o referire la c constituie o referire la constanta c
din Z. Putem face ns referire i la constantele din celelalte interfee prin X.c, Y.c i W.c.
2) Constanta c nu este redeclarat n interfaa Z : o referire la c este corect dac exist un
unic drum de interfee ce "coboar" n Z, drum n care c poate fi declarat de mai multe ori; n acest
caz referirea are ca obiect cea mai "recent" declarare a cmpului, adic cea din interfaa cea mai
apropiat de Z. Dac c este declarat pe mai multe drumuri de interfee ce "coboar" n Z,
compilatorul va semnala c este vorba de o referire ambigu. Dac n Z constanta c nu poate fi
regsit pe nici un drum de interfee ce ajunge n Z, atunci va fi semnalat din nou eroare.
Este posibil ca de exemplu n X i n Z (sau, mai general, ntr-un drum de interfee extinse) s
anunm cte o metod cu acelai nume i aceeai signatur. Atunci o clas care implementeaz
interfaa Z va implementa ambele metode.
61
Exemplul 3 Programul urmtor:
class C implements X {
public void met() { System.out.println("++++++");
}
}
class D implements Z {
public void met() { System.out.println("******");
}
}
produce la ieire:
+++++
*****
-88 a 1 true 99
Implementarea interfeelor
n subcapitolul de fa prezentm modul n care sunt rezolvate conflictele de nume ce pot aprea la
implementarea interfeelor.
Fie C o clas care implementeaz una sau mai multe interfee i extinde eventual o clas.
62
Presupunem mai nti c n unul sau mai multe dintre aceste tipuri apare un cmp (constant n
cazul interfeelor) cu acelai nume c. Atunci discuia este analoag cu cea referitoare la extinderea
interfeelor, cu urmtoarea adugire: dac c este declarat att n Z, ct i n clasa pe care o extinde,
va trebui s specificm super.c pentru cmpul din superclas.
Trecem acum la cazul metodelor. Motenirea metodelor interfeelor are loc n modul descris la
extinderea interfeelor. Drept urmare, toate metodele motenite din interfee trebuie implementate.
Dac o metod cu acelai nume i aceeai signatur apare n superclas i n interfeele
implementate, atunci:
- dac precizm n C o implementare a metodei, ea va constitui o redefinire a metodei din
superclas; la aceasta din urm putem face ns apel prin super;
- dac n C nu este precizat o implementare a metodei, atunci metoda (motenit) din superclas
constituie implementarea metodei din interfee, cu condiia ca ea s aib modificatorul public.
interface A {
int x=1; void scrie(); A B C
}
interface B {
D
int x=2; void scrie();
}
class C {
int x=3;
public void scrie() {
System.out.print(A.x+" "+B.x+" "+x);
}
}
class D extends C implements A,B {
int x=4;
}
class Interfete2 {
public static void main(String[] w) {
D Ob = new D(); Ob.scrie();
System.out.println(" "+Ob.x);
A Ob1 = new D(); Ob1.scrie();
System.out.println(" "+Ob1.x);
}
}
produce la ieire:
1 2 3 4
1 2 3 1
Sunt necesare explicaii doar referitor la obiectul Ob1. El are tipul declarat A
i tipul real D, ceea ce face ca invocarea metodei scrie prin intermediul acestui
obiect s se refere la metoda scrie din clasa C, iar referina Ob1.x s se
adreseze constantei x din interfaa A.
63
Clase interne
Pn acum am lucrat sub restricia c o clas nu poate conine o alt clas. Dar Java permite s
definim clase nu numai ca membri ai pachetelor, dar i ca membri ai unei clase, n interiorul unei
metode sau a unui bloc. Mai mult, aa cum vom vedea mai jos, pot aprea clase fr nume.
Clasele care sunt membrii unui pachet sunt considerate clase de nivel superior.
Clasele declarate ntr-o clas se mpart n dou categorii:
- clase de nivel superior: este vorba de membrii statici ai unei clase de nivel superior; aceste clase
au deci acelai statut cu clasele membre ale unui pachet;
- clase interne: clasele care nu sunt de nivel superior.
Instanierea unei clase interne este asociat instanierii curente a clasei care o conine; drept urmare
clasa intern poate accesa direct cmpurile clasei ce o cuprinde.
Cele de mai sus nu mai rmn valabile pentru clasele de nivel superior: o clas care este membru
static al unei clase nu poate folosi direct cmpurile clasei ce o cuprinde (dar putem realiza acest
lucru n mod indirect, prin crearea unui obiect ce instaniaz clasa al crui membru este).
O clas intern nu poate fi folosit direct dect n clasa n care a fost declarat i n descendenii (n
arborele de clase ai) acesteia. Domeniul ei de vizibilitate este cel al unui cmp, respectiv al unei
variabile locale.
Avantajul utilizrii claselor locale const n primul rnd n faptul c permite includerea lor exact
acolo unde trebuie s apar din punct de vedere logic, dar i n uurina folosirii lor (reamintim c
din interiorul unei clase interne putem s ne referim direct la cmpurile clasei ce o conine).
Observaie. Crearea de clase anonime permite extinderea implicit a unei clase i implementarea
implicit a unei interfee (fr a folosi extends sau implements). Drept urmare codul devine
mai scurt i mecanismul este folosit "la locul potrivit". Aceast tehnic este larg folosit de exemplu
n lucrul cu interfee grafice.
abstract class A {
A(int i) { System.out.println(i); }
void met() { };
}
class A_C {
static A ObA;
public static void main(String[] s) {
ObA = new A(3) {
void met() { System.out.println("O.K."); }
};
ObA.met();
}
}
64
Clasa abstract A are un constructor i o metod care nu prevede nici o aciune. Pare ciudat faptul c
dei metoda nu este abstract, clasa a fost declarat ca fiind abstract; acest "artificiu" este de fapt o
invitaie la a extinde clasa i a preciza aciuni specifice pentru metode.
n clasa A_C apare metoda principal, n care obiectul ObA (avnd tipul declarat A) este creat ca
avnd ca tip real o clas anonim care extinde clasa abstract A. Clasa anonim este o clas intern.
Dup invocarea constructorului este invocat metoda met; este vorba bineneles de metoda met
redefinit n clasa anonim. Drept urmare la ieire va aprea:
3
O.K.
O interfa nu poate avea constructori explicii. Exist ns constructorul implicit cu aciune nul;
acest constructor a fost folosit n exemplul de mai sus.
Este interesant de subliniat nc un aspect. Clasa I_C are modificatorul de acces implicit, dar n
interiorul ei apare o metod cu modificatorul (mai permisiv) public. Acesta se datoreaz faptului
c metoda redefinete o metod (public) dintr-o interfa.
Clasele interne se dovedesc un instrument foarte util i uor de mnuit i se va face apel la ele n
continuare. Clasele anonime apar iniial ca fiind mai puin "naturale", dar avantajele (menionate
mai sus) ale acestei tehnici fac ca ea s fie foarte util i deci folosit, aa cum vom face n lucrul cu
interfee grafice.
Aplicatie 1
Scriei o surs Java definete o interfa ConstateMatematice cu urmtoarele constate matematice:
double PI = 3.14159265358979323846;
double SQRT_2 = 1.41421356237;
double SQRT_3 = 1.73205080757;
double LN_2 = 0.69314718056;
Definii clasele TriunghiEchilateral i Cerc care sunt extinse din clasa abstract
FiguraGeometricaPlan i implementeaz interfaa ConstanteMatematice. n fiecare din clasele
concrete se ncapsulez cte o metod de calcul a ariei.
package Interfete;
package Interfete;
package Interfete;
package Interfete;
66
public double arie()
{
return (dim1*dim2*ConstanteMatematice.SQRT_3)/4;
}
package Instantieri;
import Interfete.*;
import java.util.Scanner;
for(int i=0;i<n;i++)
{
System.out.print("optiune: 1(tr)/2(cerc)?");
x=in.nextInt();
if(x==1)
{
System.out.print("Lat tr: ");
dim=in.nextInt();
tab[i]=new TrEchilateral(dim, dim);
}
else
if(x==2)
{
System.out.print("Raza cerc: ");
dim=in.nextInt();
tab[i]=new Cerc(dim, dim);
}
for(int i=0;i<n;i++)
System.out.println(tab[i]+" "+tab[i].arie());
}
67
Tem de autoinstruire
Consultai bibliografia pentru :
1. A vedea alte exemple care utilizeaz clase abstracte, interfee i clase interne.
Teste de control
1. Pot exista metode implementate (cu corp) ntr-o clas abstract? Dar ntr-o interfa?
2. ntr-o clas care implementeaz o interfa se poate modifica valoarea unui cmp din aceast
interfa?
interface I1{
int a=5;
int f(int x);
}
interface I2 extends I1{
float b=10;
float f(float x);}
class C implements I2{
public int f(int x){return x+a;}
public float f(float x){return x/b;}}
class Test{
public static void main(String sir[]){
I2 ob=new C();
System.out.print(ob.f(1)+" "+ob.f(1.5f)); }}
5. Scriei un program care s conin o clas abstract cu o metoda abstract sort care primete
ca parametru un vector de ntregi, precum i o metod implementat care msoar timpul de
execuie a metodei sort; dou clase care extind aceast clas abstract, fiecare dintre aceste
clase implementnd metoda sort prin modaliti diferite de a sorta un vector de ntregi.
Afiai timpul necesar pentru ca metodele din cele dou clase s sorteze un vector dat (folosind
metoda motenit de la clasa abstract).
68
Unitatea de nvare nr. 7
EXCEPII I CONVERSII
Excepii
Un aspect important de care trebuie inut cont ori de cte ori scriem un program este de a asigura
robusteea sa. Prin aceasta nelegem identificarea situaiilor nedorite (de exemplu introducerea unor
date eronate, eecul la ncercarea de a avea acces la Internet etc.) i specificarea aciunile
corespunztoare.
Exist ns i reversul aspectului descris mai sus. Introducerea de verificri prin instruciuni de
control face programul greu de citit i afecteaz buna sa structurare.
69
program detecteaz o condiie care cere ca o excepie s fie raportat, el creeaz un obiect
corespunztor excepiei, care poate fi folosit pentru a invoca metode ale a clasei respective.
Trebuie subliniat c o excepie poate fi o eroare, dar i orice situaie pentru care vrem s
ntreprindem aciuni specifice. Pentru situaiile n care consider c este vorba de o eroare, Java
lanseaz automat o excepie care, dac nu este captat de un handler de eroare, conduce la tiprirea
unui mesaj, dup care programul se termin; este ns posibil s captm excepia i s ntreprindem
ce aciune dorim.
Un prim exemplu
Exemplul se refer la metoda System.in.read() care lanseaz, atunci cnd are
Exemplul 1 loc o eroare la citire (nu poate fi citit un caracter), o excepie de tipul
IOException. Exist dou posibiliti de a trata aceast situaie:
n aceast a doua variant nu mai este necesar s declarm clauza throws IOException n
antetul metodei. De asemenea trebuie observat c nu mai este ntreprins o aciune implicit,
deoarece este prevzut explicit un cod ce trebuie executat (cel din handlerul de excepie). De
exemplu aciunea poate fi:
System.out.println("Eroare : " + e);
prin care este tiprit mesajul "Eroare" urmat de numele excepiei.
Clasa Exception are un constructor implicit cu zero argumente, un constructor cu un argument de
tip String i o metod fr nume care se execut implicit la lansarea unei excepii i care const n
tiprirea unui mesaj de eroare specific (la care se poate aduga irul transmis constructorului, n
cazul n care a fost folosit acest constructor).
70
prin care are loc terminarea programului pentru toate excepiile prevzute de Java. Nu este ns
indicat s procedm n acest mod, deoarece n general nu vom obine suficiente informaii pentru
depanarea programului.
De obicei, lansarea ntr-o metod a unei excepii se face din cadrul unei instruciuni if sau a unei
instruciuni switch, ca de exemplu n:
tip Met(...)throws Exceptie {
...
if(...) throw new Exceptie(...);
...
}
unde Exceptie este o clas ce extinde clasa Exception. Dac este ndeplinit condiia din if,
atunci este creat, folosind un constructor, un obiect avnd tipul (de excepie) Exceptie. Observm
c n antetul metodei Met de mai sus apare clauza "throws Exceptie".
class ... {
tip Met(...) {
...
if(...) Exceptie Ob = new Exceptie(...);
...
}
}
Lucrurile nu sunt ns identice: nu exist constructorii de care am vorbit mai sus i nu au loc
automat tiprirea unui mesaj de excepie i terminarea programului.
71
Construcia try
Mecanismul incipient descris mai sus permite crearea unei excepii i invocarea unui constructor al
su. Dar o excepie lansat n corpul unei metode trebuie s aib drept consecin executarea unor
aciuni cuprinse ntr-un handler de excepie prezent tot n corpul metodei. Tipul de excepie
respectiv este ns o clas, care poate avea i metode. n handlerul de excepie este posibil
invocarea unor metode ale clasei a crei instaniere este obiectul n discuie. Toate aceste aspecte
sunt rezolvate de construcia try.
Construcia try are forma:
try bloc
catch(E_1 e_1) bloc1
catch(E_2 e_2) bloc2
...
finally bloc_final
unde:
- E_1, E_2, ... sunt tipuri de excepie (clase ce extind Exception);
- e_1, e_2, ... sunt identificatori;
- clauza finally este opional;
- blocurile reprezint tocmai handlerele de excepie.
Dac n blocul bloc asociat lui try nu este lansat nici o excepie, atunci se trece de ultimul
catch. S presupunem acum c din bloc este lansat o excepie; fie E tipul su. Se ncearc pe
rnd, n ordinea n care apar clauzele catch, asocierea ei cu una dintre ele. Dac E coincide cu E_1
sau este derivat din (extinde pe) E_1, atunci se execut blocul bloc_1, dup care se trece de
ultima clauz catch. n caz contrar se ncearc pe rnd asocierea excepiei cu E_2, E_3 etc. Dac
nu s-a reuit o asociere, se merge "la un nivel superior" ntr-o construcie try care o cuprinde pe
cea n discuie etc. Dac nici n acest mod nu s-a identificat o asociere, se trece n codul care a
invocat metoda curent etc. n final se va reui o asociere, deoarece altfel ar apare o eroare chiar n
faza de compilare.
Tot o eroare la compilare va apare i dac de exemplu E_2 este derivat din E_1; explicaia const
n faptul c lansarea unei excepii de tipul E_2 nu va putea conduce la captarea ei de ctre clauza
identificat prin E_2 (excepia va fi captat de clauza catch precedent). Conform celor de mai
sus, este posibil ca o construcie try s nu aib ataat nici o clauz catch.
S mai observm c la lansarea unor excepii din bloc (vezi forma general a construciei try),
instruciunile care i urmeaz n acest bloc nu vor mai fi executate. Mai este clar i c o construcie
try poate fi utilizat pentru captarea mai multor excepii.
Aa cum am anunat anterior, o construcie try poate avea i o clauz finally. Aceasta permite
executarea unei secvene de instruciuni indiferent dac din blocul bloc este lansat sau nu o
excepie. Odat inclus, clauza finally nu poate fi n nici un fel ocolit i blocul bloc_final
este totdeauna executat. Un caz limit este de exemplu urmtorul:
try { ... return 0; ... }
finally { return 1; }
pentru care valoarea ntoars este totdeauna 1.
De obicei clauza finally este folosit pentru a elibera anumite resurse, ca de exemplu resurse
grafice sau fiiere (prin nchiderea lor).
72
Tratarea excepiilor
Descriem n continuare modul tipic de utilizare a excepiilor. Pentru simplificare vom considera un
singur tip de excepie cu un unic constructor i o unic metod.
class Clasa {
Clasa(..) {..}
.. Met(..)throws Exceptie {
...
if(..) throw new Exceptie(..)
..
}
}
programatorul a identificat n metoda Met o condiie deosebit care ar putea interveni i de aceea a
conceput i clasa Exceptie pentru a putea prevedea aciunile ce trebuie ntreprinse la ndeplinirea
condiiei:
class Exceptie extends Exception {
Exceptie(...) {...}
... MetExc(...) {...}
}
n mod normal, aceste activiti sunt ntreprinse o singur dat, n vederea unor aplicaii ce urmeaz
a fi dezvoltate. Pe de alt parte, clasa Exceptie poate fi folosit i de alt clas dect Clasa; de
exemplu att pentru lucrul cu stive, ct i pentru cel cu cozi, prelucrrile prevzute pentru o
ncercare de adugare a unui element n stiva/coada plin pot fi aceeai. De aceea de multe ori este
natural ca cele dou clase s se afle n uniti de compilare separate.
Ulterior, programatorul scrie un program care cuprinde o clas C, din care este invocat metoda Met
a clasei Clasa, ceea ce poate conduce la lansarea excepiei respective. Este clar c aici este locul
cel mai potrivit pentru a specifica aciunea ce trebuie ntreprins la lansarea excepiei. Pentru
aceasta este folosit construcia try, care capteaz obiectul excepie i prin intermediul lui invoc
metoda MetExc a clasei Exceptie:
class C {
Clasa Ob = new Clasa(...);
...
try {
....
Ob.Met(...);
....
}
catch (Exceptie e){
... e.MetExc(...); ...
}
.....
}
S-a prevzut invocarea metodei Met a clasei Clasa din interiorul construciei try. n cazul n care
apare condiia n discuie, este creat un obiect de tipul Exceptie prin invocarea constructorului
su. Apoi controlul este trecut clauzei catch care capteaz (primete n parametrul su) obiectul
creat, ceea ce permite invocarea metodei MetExc din Exceptie.
73
Acum discuia de la nceputul capitolului capt consisten: o excepie de tipul Exceptie este
lansat din clasa Clasa i este captat n clasa C.
Un exemplu
Vom aplica cele de mai sus la rezolvarea urmtoarei
Exemplulprobleme:
2
Un vector a de lungime n conine n caractere. Ele trebuie mutate ntr-o ordine oarecare n vectorul
b, prin intermediul unui vector auxiliar stack de lungime lung, care implementeaz o stiv.
Operaiile permise sunt:
- mutarea unui element din a n vectorul stack : elementul curent (cel cu numrul de ordine cel
mai mic) din a este mutat dup elementele deja existente n stiv;
- extragerea (inclusiv tergerea) unui element din vrful stivei i nscrierea sa n b, dup ultimul
element nscris n b.
Dificultatea problemei const n tratarea cazului n care se ncearc extragerea unui element din
stiva vid i a cazului n care se ncearc introducerea unui element n stiva plin.
74
Unitatea de compilare Stiva.java :
import java.util.*;
class Stiva {
public static void main(String[] sir) {
int n=10,na,nb,i; char[] a,b; char c;
a = new char[n]; b = new char[n];
Random R = new Random();
for (c='a',i=0; i<n; i++,c++) a[i]=c;
na=0; nb=0; S Ob = new S(3);
while (nb!=n) {
try {
if (R.nextInt()<0 && na<n) { Ob.pune(a[na]); na++;
}
else { b[nb] = Ob.ia(); nb++;} }
catch (Vida e) {e.print(" ~I");}
catch (Plina e) {e.print(" ~P");}
}
System.out.println();
for (i=0; i<n; i++) System.out.print(b[i]+" ");
System.out.println();
}
}
Explicaii Clasa principal este Stiva. Metoda sa main folosete, n afar de vectorii a i b,
urmtoarele:
Metoda main din Stiva repet, atta timp ct n b nu au fost nscrise n caractere, urmtoarele
aciuni:
- este generat aleator un nou numr ntreg;
- dac valoarea sa este negativ i mai exist elemente n a, este invocat metoda pune din clasa S
cu intenia de a muta un element din a n stiv; invocarea este urmat de mrirea lui na cu o unitate.
n caz contrar este invocat metoda ia cu intenia de a obine un element din stiv i de a-l muta n
vectorul b;
- n final sunt listate elementele lui b.
Observm c nu sunt tratate aici cazurile de excepie (adugare la stiv plin sau extragere din stiva
vid), aceste verificri cznd n sarcina clasei S. Utilizarea clasei Random permite un
nedeterminism n succesiunea de operaii asupra stivei, ceea ce va conduce la vectori b diferii de la
o executare la alta.
n clasa S este folosit vectorul stack de lungime lung pentru implementarea stivei. n ns este
memorat numrul de elemente din stiv. n antetul metodei pune este declarat tipul de excepie
plina, cruia i corespunde clasa plina ce extinde clasa Exception. Deosebim dou situaii:
75
- dac stiva este plin (ns=lung), atunci prin throw este creat o excepie (un obiect de tip
Plina). Controlul este trecut acelei clauze catch din Stiva care este identificat prin tipul Plina
al excepiei. Obiectul creat este transmis n e. Prin invocarea e.print(...) este apelat metoda
print a clasei Plina care tiprete mesajul primit la invocare. S observm c n acest mod se
evit incrementarea lui na;
- dac stiva nu este plin, atunci este nscris un nou element n stiv.
Este uor de observat c s-a folosit exact schema descris anterior, cu clasele Plina i Vida n
rolul clasei Exceptie, cu S n postura clasei Clasa i cu Stiva n locul clasei C.
76
Tem de autoinstruire
Teste de control
import java.util.*;
import java.io.*;
class Fisier{
void afisFisier(String numeFisier)
throws FileNotFoundException,IOException{
Scanner sc=new Scanner(new File(numeFisier));
while(sc.hasNextLine())
System.out.println(sc.nextLine());
sc.close();
}}
5. Scriei o clas care s implementeze o coad de numere strict pozitive, innd cont de
urmtoarele precizri:
- coada va avea o capacitate maxim;
- clasa va conine metode de adugare a unui element, interogare i tergere a unui element,
afiare a cozii. Metoda de adugare a unui numr va lansa excepie dac se ncearc adugarea
unui numr care nu este strict pozitiv sau dac numrul de elemente din coad este deja egal cu
capacitatea cozii. Metoda de eliminare va lansa excepie dac nu exist nici un element n
coad;
- folosii aceast clas pentru numere citite de la tastatur utiliznd metoda nextInt a clasei
Scanner, tratnd excepiile pe care le pot lansa operaiile asupra cozii, dar i excepia
InputMismatchException din pachetul java.util lansat de metoda nextInt a clasei
Scanner dac nu este introdus un ntreg corect.
77
Unitatea de nvare nr. 8
FLUXURI DE INTRARE/IEIRE
Suprapunerea obiectelor
Fie clasa:
class A {
... met(...) { ... }
}
Dorim ca o clas B s poat utiliza metoda met.O modalitate este oferit de mecanismul de
extindere a claselor: declarm o clas B care extinde A, construim un obiect b de tipul B i putem
invoca b.met().
Exist ns limitri de aplicare, innd de context sau de limbaj, dintre care menionm:
- de multe ori invocarea lui met trebuie fcut ntr-un anumit context, de exemplu printr-un
anumit obiect de tipul A, cu anumite cmpuri;
- este posibil s dorim ca din clasa B s utilizm i metode din alte clase; dar o clas poate
extinde o singur clas.
O alt modalitate, folosit n lucrul cu fluxuri, o constituie cea de suprapunere de obiecte (n cazul
fluxurilor va fi numit suprapunere de fluxuri).
Pentru simplificare, ilustrm aceast variant pentru cazul unei singure metode:
class B {
A a;
B(A a) { this.a = a; }
... met(...) { ...; a.met(); ... }
}
situaie n care procedm astfel:
B b = new B(new A()); b.met(...).
Spunem c obiectul b suprapune obiectul a, respectiv c (prin suprapunere) clasa B adaug noi
faciliti clasei A.
78
Schema general
Clasele ce ofer faciliti de intrare/ieire se gsesc n pachetul java.io.
Facilitile de intrare/ieire din Java au la baz noiunea de flux. Un flux este un obiect asociat unei
succesiuni de elemente (octei sau caractere), citite i scrise secvenial.
Pentru un flux de intrare sursa datelor poate fi un fiier, dar i un ir sau tablou de octei, respectiv
caractere. Pentru un flux de ieire, datele transmise sunt stocate ntr-un fiier sau ntr-un tablou de
octei, respectiv caractere.
Dac la citire nu sunt nc date disponibile n flux i nu s-a detectat sfritul datelor, atunci firul de
executare care realizeaz citirea va fi blocat pn cnd vor exista date disponibile.
O prim clasificare a fluxurilor are n vedere elementele de baz care sunt transmise: caractere sau
octei.
Object
InputStream (clas abstract pt. citire la nivel de octet)
OutputStream (clas abstract pt. scriere la nivel de octet)
Reader (clas abstract pentru citire la nivel de caracter)
Writer (clas abstract pt. scriere la nivel de caracter)
Toate clasele, interfeele i metodele din pachetul java.io au modificatorul public, iar n plus
aproape toate metodele conin clauza throws IOException.
Object
DataInput (interfa)
InputStream (clas abstract)
FileInputStream
FilterInputStream
DataInputStream implements DataInput
DataOutput (interfa)
OuputStream (clas abstract)
FileOutputStream
FilterOutputStream
DataOutputStream implements DataOutput
Observaie. Vom restrnge n continuare discuia la a prezenta cele mai simple faciliti pentru a
scrie n fiiere, respectiv de a citi din fiiere:
- octei : clasele FileOutputStream i FileInputStream ;
- date de tipuri primitive i iruri de caractere : clasele DataOutputStream i
DataInputStream;
- obiecte : vezi "Serializarea obiectelor".
79
Scrierea i citirea de octei
Clasele FileInputStream i FileOutputStream permit crearea unui flux de intrare, respectiv
ieire, asociat unui fiier cu un nume dat. Ele permit, printre altele, citirea i scrierea de octei.
Exemplul 1
Este apoi citit numele noului fiier i acesta este creat, tergnd eventuala versiune anterioar. Apoi
din primul fiier este citit consecutiv cte un octet (prin invocarea metodei read), care este copiat
n al doilea fiier. Sfritul fiierului este atins atunci cnd metoda read ntoarce valoarea -1.
import java.io.*;
import java.util.*;
class Copiere {
public static void main(String[] args) throws IOException {
Scanner sc = new Scanner(System.in);
System.out.print("Fisier cerut: ");
String fisier = sc.next();
InputStream is = null;
try { is = new FileInputStream(fisier); }
catch(FileNotFoundException e) {
System.out.println("Fisier inexistent");
System.exit(0);
}
System.out.print("Numele copiei : ");
fisier = sc.next();
OutputStream os = new FileOutputStream(fisier);
int c = 123;
while( (c=is.read()) != -1) os.write(c);
System.out.println("\nFisier copiat!");
is.close(); os.close();
}
}
Interfaa DataOutput
Conine metode menite a scrie, ntr-un flux de ieire neprecizat, date de tipuri primitive, precum i
iruri de caractere.
void write(int b)
void write(byte[] b) throws NullPointerException
void write(byte[] b, int init, int lung)
throws NullPointerException, IndexOutOfBoundsException
void writeBytes(String s) throws NullPointerException
void writeChars(String s) throws NullPointerException
void writeUTF(String s) void writeBoolean(boolean v)
void writeByte(int v) void writeShort(int v)
void writeChar(int v) void writeInt(int v)
80
void writeLong(long v) void writeFloat(float v)
void writeDouble(double v)
Interfaa DataInput
Este "complementara" interfeei DataOutput. Metodele citesc octei din fluxul de intrare; pe baza
acestor octei sunt reconstituite date de tipuri primitive sau iruri de caractere.
int skipBytes(int n) boolean readBoolean()
byte readByte() short readShort()
char readChar() int readInt()
long readLong() float readFloat()
double readDouble() String readLine()
String readUTF()
Observaie. Dac s-a ajuns la sfritul fluxului de intrare nainte de a se fi citit numrul dorit de
octei, va fi lansat excepia EOFException.
Se presupune c datele citite au fost scrise n fiier cu metodele complementare anunate n
interfaa DataOutput.
81
redefiniri ale metodelor clasei InputStream
}
Dac dorim s scriem/citim tipuri primitive sau iruri de caractere, vom folosi clasele
DataOutputStream i DataInputStream.
Exemplul 2
ntr-o prim etap vom citi de la intrarea standard un numr natural n i apoi n numere reale; vom
crea n directorul curent un fiier cu numele out.dat n care vom scrie datele citite. ntr-o a doua
etap vom citi din fiierul out.dat valoarea n i cele n numere i le vom tipri la ieirea standard.
Prima etap este realizat de urmtorul program:
import java.io.*;
import java.util.*;
class Unu {
public static void main(String[] sir) throws Exception {
int n;
Scanner sc = new Scanner(System.in);
DataOutputStream dos = new DataOutputStream(
new FileOutputStream("out.dat"));
System.out.println("n= "); n = sc.nextInt();
dos.writeInt(n);
82
System.out.println("Introduceti " +n+ " numere reale:");
for(int i=0; i<n; i++) dos.writeInt(sc.nextInt());
dos.close();
}
}
unde:
- prin new FileOutputStream("out.dat") este creat fiierul out.dat;
- fluxul dos de tipul DataOutputStream folosete metodele writeInt i writeDouble
(anunate n interfaa DataOutput i implementate n clasa DataOutputStream) pentru a scrie n
fiierul out.dat;
- pentru nchiderea fiierului este invocat metoda close a clasei FilterInputStream
(motenit din DataOutputStream).
A doua etap este realizat de urmtorul program:
import java.io.*;
class Doi {
public static void main(String[] ss) throws Exception {
double d; int n;
DataInputStream dis = new DataInputStream(
new FileInputStream("out.dat") );
n = dis.readInt();
for (int i=0; i<n; i++)
System.out.print(dis.readInt() + "\t" );
System.out.println(); dis.close();
}
}
unde:
- prin new FileInputStream("out.dat") este deschis fiierul out.dat;
- fluxul dis de tipul DataInputStream folosete metodele readInt i readDouble
(anunate n interfaa DataInput i implementate n clasa DataInputStream) pentru a citi din
fiierul out.dat;
- pentru nchiderea fiierului este invocat metoda close a clasei FilterInputStream
(motenit din DataInputStream).
83
implements DataInput {
DataInputStream(InputStream in)
implementarea metodelor read i skipBytes din interfaa DataOutput
}
din care vom folosi numai clasa PrintWriter, care ofer facilitatea de a scrie date n fluxul de
ieire ntr-un mod formatat, specific metodelor toString. Nu este lansat niciodat excepia
IOException.
import java.io.*;
class Print {
public static void main(String[] args) throws IOException {
84
FileOutputStream fos = new FileOutputStream("out");
PrintWriter out = new PrintWriter(fos);
PrintWriter stdout = new PrintWriter(System.out);
out.println("Cifrele zecimale sunt:");
for(int i=0; i<10; i++) out.print(i + "\t");
out.println();
stdout.println("Cifrele zecimale sunt:");
for(int i=0; i<10; i++) stdout.print(i + "\t");
stdout.println();
out.close(); // stdout.close();
}
}
Facem observaia c nenchiderea explicit a unui flux poate conduce la nenregistrarea n fiier a
tuturor datelor prevzute a fi scrise n el prin program.
85
Tem de autoinstruire
86
Unitatea de nvare nr. 9
87
Crearea bazei de date cu Microsoft Access
Fie Agenda numele bazei de date, n care folosim tabelul Persoane. Secvena standard de
aciuni ce trebuie ntreprins este urmtoarea:
se deschide Microsoft Access;
Blank Access Database;
se selecteaz directorul de lucru;
File Name: Agenda;
Create;
se selecteaz Create Table in Design view i Tables;
Open;
se introduc numele cmpurilor + tipul lor;
se nchide;
se salveaz sub numele Persoane;
nu se alege cheie primar;
se selecteaz Persoane: se introduc nregistrri;
se nchid toate ferestrele.
89
Executarea de instruciuni SQL
Pentru executarea de instruciuni SQL trebuie mai nti creat un "obiect instruciune", adic un
obiect de tipul interfeei Statement:
Statement stmt = con.createStatement();
unde createStatement este o metod a interfeei Connection. Pe baza acestui obiect este posibil
executarea de instruciuni SQL, cu primirea rezultatelor cutrii.
n continuare trebuie creat un ir de caractere care s reprezinte o comand SQL valid:
String sql = "...";
Urmeaz transmiterea cererii i obinerea rezultatului interogrii folosind una dintre metodele:
public ResultSet executeQuery(String sql) throws
SQLException
unde sql reprezint o instruciune SQL de tip SELECT. Este ntors un obiect de tipul
ResultSet care permite regsirea rezultatelor cererii;
public int executeUpdate(String sql) throws SQLException
unde sql reprezint o instruciune SQL de unul dintre tipurile INSERT, UPDATE, sau DELETE.
Este ntors numrul liniei (nregistrrii) afectate.
Interfaa:
public interface ResultSet
permite regsirea, sub forma unui tabel, a rezultatelor cutrii la executarea unei metode
executeQuery. Un obiect de acest tip menine un cursor la linia curent din tabel, iniial la prima
linie a acestuia. Dintre metodele interfeei ResultSet descriem deocamdat numai urmtoarele:
public boolean next()
ntoarce true dac i numai dac mai exist linii n rs, caz n care se trece la urmtoarea nregistrare;
public gettip(String s)
ntoarce coninutul cmpului cu numele s din nregistrarea curent ca o valoare de tipul tip din Java;
tip poate fi String, Int etc.
Observaie Obiectele con i stmt trebuie "nchise" n final prin invocarea metodei
close().
class Persoana {
private String nume,prenume,localitate;
private int salariu;
public Persoana(String n, String p, String l, int s)
{
nume=n; prenume=p; localitate=l; salariu=s;
}
public String rNume() { return nume; }
90
public String rPrenume() { return prenume; }
public String rLocalitate() { return localitate; }
public int rSalariu() { return salariu; }
public String toString() {
return "\t"+ nume+"\t"+prenume+"\t"+
localitate+"\t"+salariu;
}
}
import java.sql.*;
class BD {
Statement stmt;
BD(Statement s) { stmt = s; }
91
Clasa Agenda de mai jos conine numai metoda principal. Aceast metod prevede crearea unei
conexiuni con la baza de date, a unui "obiect instruciune" stmt i a unui obiect bd de tipul BD. n
continuare sunt citite de la intrare iruri de caractere i se ntreprind urmtoarele aciuni:
dac primul ir de caractere citit este "INSERT", mai sunt citite 3 iruri de caractere i un numr
ntreg;
dac primul ir de caractere citit este "SELECT", atunci mai sunt citite dou iruri de caractere
nume i loc;
import java.sql.*;
class Agenda {
public static void main(String[] args) throws Exception {
String id,nume,prenume,loc; int sal; Persoana P;
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
String url = "jdbc:odbc:AgendaODBC";
Connection con =
DriverManager.getConnection(url,"Vasile","Sile");
Statement stmt = con.createStatement();
BD bd = new BD(stmt);
Scanner sc = new Scanner(System.in);
for ( ; ; ) {
System.out.println("*** Comanda noua : ***");
id = sc.next();
if (id.equals("STOP")) break;
else if (id.equals("SELECT")) {
nume = sc.next(); loc = IO.readString();
bd.cauta(nume,loc);
}
else if (id.equals("INSERT")) {
nume = sc.next(); prenume = sc.next();
loc = sc.next(); sal = sc.next();
P = new Persoana(nume,prenume,loc,sal);
bd.adauga(P);
}
else System.out.println("Comanda incorecta");
}
con.close(); stmt.close();
}
}
92
Tem de autoinstruire
1. Consultai bibliografia pentru a afla cum se lucreaz cu toate clasele i interfeele pentru funcii
folosite n manipularea bazelor de date SQL.
Teste de control
1. Scriei un program pentru interogarea unei baze de date care ine evidena produselor unui
magazin sportiv. Baza de date conine urmtoarele informaii: nume produs, tip produs, nr
buci, pre, disponibil n stoc. S se introduc produse noi n baza de date i s se verifice
adugarea lor ca noi nregistrri n baza de date. S se afieze toate produsele de tipul
nclminte disponibile n stoc.
93
Unitatea de nvare nr. 10
SERVLET-URI
Despre servlet-uri
Servlet-urile sunt aplicaii Java aflate pe server i executate de ctre acesta. Serverul de Web, la
executarea servlet-ului, trimite napoi browser-ului un fiier HTML, pe care acesta n afieaz
corespunztor; n particular, browser-ul nu trebuie s tie nici mcar ce nseamn un servlet.
Partea din serverul de Web care ateapt cereri (n cazul nostru cereri de executare a unui servlet)
este numit demon HTTP, deoarece are caracteristicile unui fir de executare demon. Serverul poate
efectua "simultan" tranzacii cu mai muli clieni, pornind pentru fiecare un fir de executare. Mai
menionm c schimbul de informaii ntre server i fiecare client se face n esen prin socket-uri,
dar la un nivel superior i n mod transparent pentru utilizator.
Servlet-urile nu sunt subiectul unor restricii. Servlet-urile creaz documente HTML dinamice prin
succesiunea de tranzacii descrise mai sus. Independena de platform a limbajului Java se extinde
n mod natural i logic asupra servlet-urilor (spre deosebire de script-urile CGI care sunt
independente de platform i care sunt n plus mult mai lente).
94
Gestionarea servlet-urilor
Reamintim c am creat directorului nostru propriu myapp de aplicaii C:\Tomcat3\jakarta-
tomcat-3.3.2\webapps cu urmtoarea structur:
myapp
WEB-INF (*)
classes (**)
i c n (*) am copiat fiierul web.xml din
C:\Tomcat3\jakarta-tomcat-3.3.2\webapps\examples\WEB-INF
Aplicaiile noastre (servlet-urile) vor fi plasate n (**).
Mai sunt necesare urmtoarele:
Dac vrem s executm C.class obinut prin compilarea unui servlet aflat n directorul
myapp, deschidem Internet Explorer i specificm:
http://localhost:8080/myapp/servlet/C (***)
cu observaia c servlet nu este director, ci informaie c lucrm cu servlet-uri.
Un prim exemplu
Prezentm n continuare un prim exemplu, cu cteva explicaii necesare, urmnd ca unele interfee,
clasele i metode referitoare la servlet-uri s fie descrise n continuare n detaliu.
95
out.println("</head>");
out.println("<body>");
out.println("<h1>Salutare!</h1>");
s += " Vasilica" + " " + val;
out.println(s);
out.println("</body>"); out.println("</html>");
System.out.println("O.K.");
}
}
Servlet-ul Salut conine metoda doGet care este invocat la o cerere HTTP de tipul GET.
Variabilele resp i req sunt obiecte de tipul indicat, care corespund cererii primite de la client,
respectiv rspunsului care va fi transmis clientului.
Prin invocarea metodei getWriter obiectul resp creeaz un flux de ieire out n care va fi
introdus documentul HTML.
n continuare obiectul req invoc metoda getParameter pentru a capta n variabilele locale s i
val valorile parametrilor din cererea HTTP care au numele nume i val. Apoi n fluxul out este
introdus un ir de caractere ce reprezint documentul HTML ce va fi transmis clientului.
96
Formulare n HTML
n exemplul de mai sus, clientul a trimis (prin intermediul browser-ului) o cerere severului de Web,
care a rspuns cu un document HTML, pagina Web respectiv fiind afiat de browser. Dorim ns
mai mult i anume s realizm un dialog "continuu" ntre client i server. O posibilitate const n a
folosi formularele din HTML, variant studiat n acest paragraf. O alt posibilitate, dezvoltat ntr-
un paragraf ulterior, const n a folosi applet-uri pe partea de client.
Formulare
Formularele stau la baza crerii, cu ajutorul servlet-urilor, a paginilor HTML dinamice i a
procesrii de ctre server a datelor transmise de client prin intermediul lor. Pot fi create formulare
multiple, dar independente. Ele au forma:
ariile de text:
< textarea name=nume cols=m rows=n >
butoane de validare:
<input name=nume type=checkbox value=val checked >
permit alegerea multipl (a mai multor opiuni), care sunt iruri de caractere. Toate opiunile trebuie
s aib acelai nume nume i pentru fiecare poate fi precizat, prin prezena lui checked, dac este
selectat.
butoane radio:
<input name=nume type=radio value=val checked >
difer de butoanele de validare prin aceea c exact o opiune poate fi aleas.
butoane de comand:
<input name=nume type=tip value=val >
unde tip poate fi:
reset : cmpurile formularului revin la valorile iniiale;
submit : cmpurile formularului sunt trimise ctre server (vom reveni);
push : este ntreprins aciunea definit de autorul formularului.
97
nume de fiier:
<input type=file name=nume >
unde nume este numele unui fiier care este transmis; va aprea i un buton Browse a crui
acionare va permite selctarea fiierului prin navigare n structura de directoare.
<html>
<head> <title> Formular </title> </head>
<body>
<form method=GET action=???>
<p> Numele <input type=text name="Nume">
<p>
Ai studiat Informatica in liceu?
<input type=radio name="radio" value="Da" checked>
Da    
<input type=radio name="radio" value="Nu"> Nu
<p>
Selecteaza cursurile favorite <br>
<input type=checkbox value="1"> Programare <br>
<input type=checkbox value="2" checked> Algoritmi <br>
<input type=checkbox value="3" checked>
Baze de date <br>
<p>
Forma de invatamant:
<Select name="valuta">
<option value="Inf"> Informatica </option>
<option selected value="MI"> Mat-Inf </option>
<option value="Col"> Colegiu </option>
</Select>
<p> Fisier catre server:<br>
<input type=file value="fisier" size=30>
<p>
Butoane:<br>
<input type=reset name="Exit" value="Iesire">
<input type=submit name="Cerere" value="Cerere">
</form>
</body>
</html>
Browser-ul va afia:
98
Trimiterea de date ctre server
Exist dou modaliti de trimitere (corespunztoare celor dou tipuri de cereri HTTP), dup cum
metoda este:
GET : datele din formular sunt adugate n URL-ul trimis, sub forma de perechi
(nume,valoare). Ele vor fi accesibile servlet-ului prin metodele:
getQueryString, getParameter i getParameterValues;
POST : datele sunt nglobate n antetele cererii. Ele vor fi accesibile servlet-ului prin
metoda getParameterValues sau prin citire din ServletInputStream.
n funcie de metoda aleas, servlet-ul specificat prin clasa va executa metoda doGet sau metoda
doPost. Alte detalii despre cele dou tipuri de cereri HTML, respectiv despre metodele doGet i
doPost, vor fi furnizate ulterior.
Dorim s trimitem iruri de caractere ctre server. Vom folosi un formular care conine doar un
cmp de text i un buton submit. La completarea cmpului de text i apsarea butonului, va fi
ntors mesajul transmis.
import java.io.*;
import java.awt.*; import java.awt.event.*;
import javax.servlet.*; import javax.servlet.http.*;
99
Observaie. O alternativ la executarea servlet-ului TF n modul precizat este de folosi urmtorul
document HTML:
<html>
<head><title>Camp de text</title>
</head>
<body>
<form method=GET
action=http://localhost:8080/myapp/servlet/TF>
<p><input type=text name=tf maxlength=20>
<p><input type=submit name=Buton value=Apasa>
</form>
</body>
</html>
Reamintim c acest document (fie D.html numele su) va fi plasat n mod tipic pe serverul de
Web n directorul myapp, iar el va fi cerut de client prin:
http://adresa_server:8080/myapp/D.html.
100
Clase i interfee folosite n lucrul cu servlet-uri
Clasele i interfeele pe care le-am ales pentru a fi prezentate apar n urmtoarele dou pachete:
- Pachetul javax.servlet
Interfee:
public interface Servlet
public interface ServletRequest
public interface ServletResponse
Clase:
public abstract class ServletInputStream
public abstract class ServletOutputStream
public abstract class GenericServlet
implements Servlet, Serializable
- Pachetul javax.servlet.http
Interfee:
public interface HttpServletRequest extends ServletRequest
public interface HttpServletResponse extends ServletResponse
Clase:
public abstract class HttpServlet extends GenericServlet
Servlet-uri
Aceast metod este invocat de server n momentul n care primete o comand HTTP de tip
GET. n mod normal, metoda trebuie ca, folosind informaia din parametrul req, s ntreprind
aciunile corespunztoare i s plaseze rezultatele n fluxul de ieire creat pe baza parametrului
resp.
Aceast metod difer de doGet prin aceea c este invocat de server n momentul n care
primete o comand HTTP de tip POST. Alte diferene vor fi prezentate n continuare.
101
Ciclul de via al unui servlet
Servlet-ul este un program Java care ruleaz n cadrul unui server de Web. De fapt serverul de Web
creaz un container n cadrul cruia este executat servlet-ul. Pentru simplificare, vom considera c
acest container este chiar serverul de Web.
n literatura de specialitate apare afirmaia "servlet-ul este un applet pe partea de server". Afirmaia
se bazeaz pe analogia ntre ciclul de via al unui applet i ciclul de via al unui servlet.
Metoda init()
este declarat n clasa GenericServlet prin:
public void init() throws ServletException
Metoda este invocat numai la crearea servlet-ului. Un servlet este creat prima dat cnd un
utilizator invoc URL-ul corespunztor servlet-ului. n concluzie, la invocri ulterioare
metoda init() nu mai intr n aciune. Prin aceast metod putem face diverse iniializri,
ca de exemplu stabilirea unei conexiuni la o baz de date.
Observaie. Din momentul executrii metodei init, modificrile fcute pe server asupra
servlet-ului nu sunt efective dect dup oprirea i repornirea serverului de Web.
Metoda service()
este declarat n clasa GenericServlet prin:
public abstract void service(ServletRequest req,
ServletResponse resp)
throws ServletException, java.io.IOException
De fiecare dat cnd serverul de Web primete o cerere pentru un servlet, lanseaz un nou
fir de executare i invoc metoda service. Metoda detecteaz tipul cererii HTTP i
invoc n mod corespunztor una dintre metodele de serviciu doGet i doPost. Posibila
existen mai multor fire de executare care folosesc servletul ridic probleme de concuren,
a cror rezolvare cade n sarcina programatorului.
Putem evita metoda service furniznd implementri pentru metodele doGet i doPost,
aa cum vom proceda de obicei n continuare. Totui metoda service i gsete utilitatea
n situaia existenei unei condiii n funcie de care se invoc doGet sau doPost. Dac
dorim ca ambele tipuri de cerere s fie tratate identic, specificm n doGet aciunea
corespunztoare i introducem metoda doPost urmtoare:
Metoda destroy()
este declarat n clasa GenericServlet prin:
public void destroy()
Aceast metod este invocat de serverul de Web la cererea administratorului sau n cazul n
care servlet-ul nu primete cereri o perioad ndelungat de timp. n metod sunt precizate
de obicei eliberri de resurse alocate prin init(), ca de exemplu ntreruperea unei
conexiuni cu o baz de date. Instana servlet creat prin init() este distrus.
102
Recapitulnd, ciclul de via al unui servlet poate fi figurat astfel:
Prima init
cerere
Cerere
service
Rspuns
destroy
Cereri
103
Urmtoarele dou metode permit accesarea parametrilor din irul de parametri adugai comenzii
HTTP, de exemplu prin acionarea unui buton de tip submit.
import java.io.*;
import javax.servlet.*; import javax.servlet.http.*;
public class Ex1 extends HttpServlet {
public void doGet(HttpServletRequest req,
HttpServletResponse resp)
throws ServletException,IOException {
resp.setContentType("text/html");
ServletOutputStream out = resp.getOutputStream();
String RemoteAddr = req.getRemoteAddr();
String Method = req.getMethod();
String ServerName = req.getServerName();
int ServerPort = req.getServerPort();
String RequestURI = req.getRequestURI();
String ContextPath = req.getContextPath();
String ServletPath = req.getServletPath();
out.println(
"<html><head><title>Info_Client</title></head>" +
"<body> <p> RemoteAddr : " + RemoteAddr +
"<br> Method : " + Method +
"<br> ServerName : " + ServerName +
"<br> ServerPort : " + ServerPort +
"<br> RequestURI : " + RequestURI +
"<br> ContextPath : " + ContextPath +
"<br> ServletPath : " + ServletPath +
"</body></html>");
}}
104
Rspuns
Interfeele:
definesc un obiect prin intermediul cruia servlet-ul transmite un rspuns clientului, rspuns dirijat
ctre fluxul de ieire ataat acestui obiect. HttpServletResponse furnizeaz n plus
funcionalitate HTTP.
Dintre metode menionm doar urmtoare;e:
public void setContentType(String tip)
n care tip precizeaz versiunea protocolului MIME (de exemplu "text/html") folosit la
transmiterea rspunsului;
public void addHeader(String s1, String s2)
prin care se adaug antetul (header-ul) cu numele s1 i cu valoarea s2. Un exemplu va fi
prezentat n capitolul referitor la transmiterea de fiiere.
Fluxuri
Pentru fluxurile de intrare este folosit clasa:
Un flux de intrare poate citi date la nivel de octet, furniznd n plus metoda readLine pentru
citirea de linii:
public int readLine(byte[] octeti, int depl, int nr)
citete n octeti cte o linie din fluxul de intrare, plecnd de la poziia curent, cu deplasarea
depl. Metoda se termin fie la detectarea sfritului de linie dup citirea a maximum nr octei
(caz n care rezultatul ntors este numrul de octei citii), fie la citirea a nr octei fr detectarea
sfritului de linie (caz n care ntoarce valoarea -1).
105
public PrintWriter getWriter()
din interfaa HttpServletResponse. Este folosit dac dorim ca transmiterea s se fac la
nivel de octet. Invocarea metodei flush() ncheie acest rspuns. Setarea versiunii MIME (prin
setContentType) trebuie fcut nainte de a folosi acest flux de ieire.
<html>
<head> <title> Formular </title> </head>
<body>
<form method=POST
action=http://adresa_server:8080/myapp/servlet/File>
<p> Fisier catre server:<br>
<input type=file name=fisier >
<p>
Buton:<br>
<input type=submit name=Buton value=Apasa>
</form>
</body>
</html>
Vor aprea un cmp de text, un buton cu eticheta Browse i un al doilea buton cu eticheta Apasa.
Acionarea butonului Browse permite alegerea unui fiier al crui nume (cu calea complet) este
nscris n cmpul de text. Acionarea butonului Apasa transmite serverului aceste informaii, care
le prelucreaz prin urmtorul servlet:
Sunt necesare mai multe observaii. Am citit, informaia din fluxul de intrare. Aceat informaie
este prelucrat cu StringTokenizer, pentru care am prevzut delimitatorul '&'.
Presupunnd c am ales s trimitem numele de fiier autoexec.bat din C:, informaia afiat
de server n fereastra Tomcat va avea forma:
fisier=C%3A%5CAUTOEXEC.BAT
Buton=Apasa
null
deoarece :
- la transmiterea informaiei, caracterul ':' este nlocuit prin irul de caractere "%3A", iar
caracterul '\' este nlocuit prin irul de caractere "%5C", conform schemei de codare implicite;
- metoda getParameter ntoarce null pentru c am ales s citim din fluxul de intrare; altfel
spus, metodele getInputStream i getParameter sunt incompatibile.
107
Tem de autoinstruire
Teste de control
1. Fiierul text agenda.txt conine numerele de telefon ale mai multor persoane. Fiecare linie din
agend este de forma nume prenume,telefon. Realizai un servlet care s primeasc, prin
intermediul unui parametru transmis folosind metoda GET, un prenume i s genereze o pagin
HTML care s conin numele i numerele de telefon ale tuturor persoanelor din agend care au
prenumele respectiv, precum i numrul lor. Coninutul agendei telefonice se va ncrca din
fiierul text ntr-o structur de date adecvat o singur dat, n momentul iniializrii servlet-
ului.
2. Fiierul text dictionar.txt conine traducerile unor cuvinte din limba romn n limba englez.
Prima linie din fiier conine numrul cuvintelor din dicionar, iar pe fiecare din urmtoarele
linii sunt perechi de forma nume cuvnt romn,cuvnt englez. Scriei un servlet care s
primeasc, prin intermediul unui parametru transmis folosind metoda GET, un cuvnt n limba
romn i s genereze o pagin HTML care s conin traducerea cuvntului respectiv n limba
englez sau un mesaj corespunztor dac respectivul cuvnt nu se gsete n dicionar.
Coninutul dicionarului se va ncrca din fiierul text ntr-o structur de date adecvat o singur
dat, n momentul iniializrii servlet-ului.
108
Bibliografie
[1] Georgescu Horia, Introducere n universul Java, Editura Tehnic,
Bucureti, 2002
[2] Georgescu Horia, Boriga Radu, Programare distribuit n Java, Editura
Universitii din Bucureti, 2008
[3] Mahmoud Qusay, Distributed Programming with Java, Manning, 2000
[4] Tanas tefan, Andrei tefan, Olaru Cristian, Java de la 0 la expert (ediia
a II-a), Editura Polirom, 2007
[5] Arnold K., Gosling J., The Java Programming Language. Second Edition,
Addison - Wesley, 1997
109