Documente Academic
Documente Profesional
Documente Cultură
Java
Java
Introducere
Scurt istoric
Limbajul Java mpreun cu mediul su de dezvoltare i execuie au fost proiectate pentru a
rezolva o parte dintre problemele actuale ale programrii. Proiectul Java a pornit cu scopul declarat de
a dezvolta un software performant pentru aparatele electronice de larg consum. Aceste echipamente se
definesc ca: mici, portabile, distribuite i lucrnd n timp real. De la aceste aparate, ne-am obinuit s
cerem fiabilitate i uurin n exploatare.
Limbajul luat iniial n considerare a fost C++. Din pcate, atunci cnd s-a ncercat crearea unui
mediu de execuie care s respecte toate aceste condiii s-a observat c o serie de trsturi ale C++ sunt
incompatibile cu necesitile declarate. n principal, problema vine din faptul c C++ este prea
complicat, folosete mult prea multe convenii i are nc prea multe elemente de definiie lsate la
latitudinea celor care scriu compilatoare pentru o platform sau alta.
n aceste condiii, firma Sun a pornit proiectarea unui nou limbaj de programare asemntor cu
C++ dar mult mai flexibil, mai simplu i mai portabil. Aa s-a nscut Java. Printele noului limbaj a
fost James Gostling care este cunoscut ca autor al editorului emacs i al sistemului de ferestre grafice
NeWS. Proiectul a nceput nc din 1990 dar Sun a fcut public specificaia noului limbaj abia n 1995
la SunWorld n San Francisco.
Numele iniial al limbajului a fost Oak, numele unui copac care crete n faa biroului lui James
Gostling. Ulterior, s-a descoperit c numele fusese deja folosit n trecut pentru un alt limbaj de
programare aa c a fost abandonat i nlocuit cu Java, spre deliciul programatorilor care iubesc
cafenelele i aromele exotice.
Ce este Java?
n primul rnd, Java ncearc s rmn un limbaj simplu de folosit chiar i de ctre
programatorii neprofesioniti, programatori care doresc s se concentreze asupra aplicaiilor n
principal i abia apoi asupra tehnicilor de implementare a acestora. Aceast trstur poate fi
considerat ca o reacie direct la complexitatea considerabil a limbajului C++.
Au fost ndeprtate din Java aspectele cele mai derutante din C++ precum suprancrcarea
operatorilor i motenirea multipl. A fost introdus un colector automat de gunoaie care s rezolve
problema dealocrii memoriei n mod uniform, fr intervenia programatorului. Colectorul de gunoaie
nu este o trstur nou, dar implementarea acestuia n Java este fcut inteligent i eficient folosind un
fir separat de execuie, pentru c Java are ncorporate faciliti de execuie pe mai multe fire de
Figura 1 Modelul de reprezentare al unui obiect n memorie. Stratul exterior reprezint doar operaiile care ofer
calea de a interaciona cu proprietile obiectului i nu are corespondent direct n zona de memorie ocupat de obiect.
Clase de obiecte
n lumea real se pot identifica uor familii de obiecte. Este greu s descriem ntr-un limbaj de
programare fiecare minge din lume dar, pentru a putea folosi orice minge din lume, este suficient s
descriem o singur dat care sunt proprietile unei mingi n general, precum i operaiile care pot fi
executate cu aceasta. Aceasta nu nseamn c toate obiectele minge din lume sunt identice. Diferena
dintre ele se afl reprezentat n primul rnd n valorile proprietilor lor care difer de la un obiect de
acelai fel la altul. De exemplu, n fiecare obiect minge vom avea un numr natural care reprezint
culoarea mingii. Acest numr poate s difere de la o minge la alta exact aa cum, n realitate, culoarea
difer de la o minge la alta. La fel coordonatele poziiei mingii la un moment dat sau raza mingii
precum i materialul din care este confecionat au valori care variaz de la o minge la alta.
Cu alte cuvinte, fiecare minge din lume are acelai set de proprieti, dar valorile acestora pot s
difere de la o minge la alta. Modelul de reprezentare n memorie a unui obiect este ntotdeauna acelai,
dar valorile memorate n locaiile corespunztoare proprietilor sunt n general diferite.
n ceea ce privete operaiile, acestea sunt ntotdeauna aceleai dar rezultatul aplicrii lor poate
s difere n funcie de valorile proprietilor obiectului asupra cruia au fost aplicate. De exemplu,
atunci cnd aruncm o minge spre pmnt ea va ricoa din acesta ridicndu-se din nou n aer. nlimea
la care se va ridica ns, este dependent de dimensiunile i materialul din care a fost confecionat
mingea. Cu alte cuvinte, noua poziie n spaiu se va calcula printr-o operaie care va ine cont de
valorile memorate n interiorul obiectului. Se poate ntmpla chiar ca operaia s hotrasc faptul c
mingea va strpunge podeaua n loc s fie respins de ctre aceasta.
S mai observm c operaiile nu depind numai de proprietile obiectului ci i de unele valori
exterioare acestuia. Atunci cnd aruncm o minge spre pmnt, nlimea la care va ricoa aceasta
depinde i de viteza cu care a fost aruncat mingea. Aceast vitez este un parametru al operaiei de
aruncare. Nu are nici un rost s transmitem ca parametrii ai unei operaii valorile proprietilor unui
obiect pentru c acestea sunt ntotdeauna disponibile operaiei. Nici o operaie nu se poate aplica asupra
unui obiect fr s tim exact care este obiectul respectiv i ce proprieti are acesta. Este absurd s ne
gndim la ce nlime se va ridica o minge n general, fr s facem presupuneri asupra valorilor
proprietilor acesteia. S mai observm ns c, dac toate mingile ar avea aceleai valori pentru
proprietile implicate n operaia descris mai sus, am putea s calculm nlimea de ricoeu n
general, fr s fim dependeni de o anumit minge.
n concluzie, putem spune c obiectele cu care lucrm fac parte ntotdeauna dintr-o
familie mai mare de obiecte cu proprieti i comportament similar. Aceste familii de obiecte le
vom numi n continuare clase de obiecte sau concepte n timp ce obiectele aparinnd unei anumite
clase le vom numi instane ale clasei de obiecte respective. Putem vorbi despre clasa de obiecte minge
i despre instanele acesteia, mulimea tuturor obiectelor minge care exist n lume. Fiecare instan a
clasei minge are un loc bine precizat n spaiu i n timp, un material i o culoare. Aceste proprieti
difer de la o instan la alta, dar fiecare instan a aceleiai clase va avea ntotdeauna aceleai
proprieti i aceleai operaii vor putea fi aplicate asupra ei. n continuare vom numi variabile aceste
proprieti ale unei clase de obiecte i vom numi metode operaiile definite pentru o anumit clas de
obiecte.
Pentru a clarifica, s mai relum nc o dat: O clas de obiecte este o descriere a
proprietilor i operaiilor specifice unui nou tip de obiecte reprezentabile n memorie. O
instan a unei clase de obiecte este un obiect de memorie care respect descrierea clasei. O
Figura 2 O ierarhie de clase de obiecte n care clasele sunt reprezentate n cmpuri eliptice iar instanele acestora n
cmpuri dreptunghiulare. Clasele abstracte de obiecte au elipsa dublat.
Desigur, este foarte dificil s construim o ierarhie de clase de obiecte complet, care s conin
clase de obiecte corespunztoare fiecrui concept cunoscut. Din fericire, pentru o problem dat,
conceptele implicate n rezolvarea ei sunt relativ puine i pot fi uor izolate, simplificate i definite.
Restrngerea la minimum a arborelui de concepte necesar rezolvrii unei anumite probleme fr a se
afecta generalitatea soluiei este un talent pe care fiecare programator trebuie s i-l descopere i s i-l
cultive cu atenie. De alegerea acestor concepte depinde eficiena i flexibilitatea aplicaiei.
O clas de obiecte derivat dintr-o alt clas pstreaz toate proprietile i operaiile acesteia
din urm aducnd n plus proprieti i operaii noi. De exemplu, dac la nivelul clasei de obiecte om
am definit forma biped a acestuia i capacitatea de a vorbi i de a nelege, toate acestea vor fi
motenite i de ctre clasele derivate din clasa om, i anume clasa brbailor i cea a femeilor. Fiecare
dintre aceste clase de obiecte derivate i vor defini propriile lor proprieti i operaii pentru a descrie
diferena dintre ele i clasa original.
Unele dintre proprietile i operaiile definite n superclas pot fi redefinite n subclasele de
obiecte derivate. Vechile proprieti i operaii sunt disponibile n continuare, doar c pentru a le putea
accesa va trebui s fie specificat explicit superclasa care deine copia redefinit. Operaia de redefinire
a unor operaii sau variabile din interiorul unei clase n timpul procesului de derivare o vom numi
rescriere.
\U0045
\u6abe
n al doilea pas al citirii fiierului surs, sunt recunoscute ca i caractere de sfrit de linie
caracterele ASCII CR i ASCII LF. n acelai timp, secvena de caractere ASCII CR-ASCII LF este
tratat ca un singur sfrit de linie i nu dou. n acest mod, Java suport n comun standardele de
terminare a liniilor folosite de diferite sisteme de operare: MacOS, Unix i DOS.
Uniti lexicale
Unitile lexicale sunt elementele de baz cu care se construiete semantica programelor Java. n
irul de cuvinte de intrare, unitile lexicale sunt separate ntre ele prin comentarii i spaii. Unitile
lexicale n limbajul Java pot fi:
Cuvinte cheie
Identificatori
Literali
Separatori
Operatori
Cuvinte cheie
Cuvintele cheie sunt secvene de caractere ASCII rezervate de limbaj pentru uzul propriu. Cu
ajutorul lor, Java i definete unitile sintactice de baz. Nici un program nu poate s utilizeze aceste
secvene altfel dect n modul n care sunt definite de limbaj. Singura excepie este aceea c nu exist
nici o restricionare a apariiei cuvintelor cheie n iruri de caractere sau comentarii.
Cuvintele cheie ale limbajului Java sunt:
abstract
boolean
break
byte
case
cast
catch
char
class
const
continue
default
do
double
else
extends
final
finally
float
for
future
generic
goto
if
implements
import
inner
instanceof
intinterface
long
native
new
null
operator
outer
package
private
protected
public
rest
return
short
static
super
switch
synchronized
this
throw
throws
transient
try
var
void
volatile
while
byvalue
Identificatori
Identificatorii Java sunt secvene nelimitate de litere i cifre Unicode, ncepnd cu o liter.
Identificatorii nu au voie s fie identici cu cuvintele rezervate.
Cifrele Unicode sunt definite n urmtoarele intervale:
Reprezentare Unicode Caracter ASCII
\u0030-\u0039
0-9
Explicaie
cifre ISO-LATIN-1
\u0660-\u0669
cifre Arabic-Indic
\u06f0-\u06f9
\u0966-\u096f
cifre Devanagari
\u09e6-\u09ef
cifre Bengali
\u0a66-\ u0a6f
cifre Gurmukhi
\u0ae6-\u0aef
cifre Gujarati
\u0b66-\u0b6f
cifre Oriya
\u0be7-\u0bef
cifre Tamil
\u0c66-\u0c6f
cifre Telugu
\u0ce6-\u0cef
cifre Kannada
\u0d66-\u0d6f
cifre Malayalam
\u0e50-\u0e59
cifre Thai
\u0ed0-\u0ed9
cifre Lao
\u1040-\u1049
cifre Tibetan
Tabelul 1 Cifrele Unicode.
Un caracter Unicode este o liter dac este n urmtoarele intervale i nu este cifr:
Reprezentare Unicode Caracter ASCII
Explicaie
\u0024
\u0041-\u005a
A-Z
\u0061-\u007a
a-z
\u00c0-\u00d6
\u00d8-\u00f6
\u00f8-\u00ff
\u0100-\u1fff
\u3040-\u318f
\u3300-\u337f
\u3400-\u3d2d
\u4e00-\u9fff
\uf900-\ufaff
compatibilitate Han
Tabelul 2. Literele Unicode.
Literali
Un literal este modalitatea de baz de exprimare n fiierul surs a valorilor pe care le pot lua
tipurile primitive i tipul ir de caractere. Cu ajutorul literalilor putem introduce valori constante n
variabilele de tip primitiv sau n variabilele de tip ir de caractere.
n limbajul Java exist urmtoarele tipuri de literali:
literali ntregi
literali flotani
literali booleeni
literali caracter
literali ir de caractere
Literali ntregi
Literalii ntregi pot fi reprezentai n baza 10, 16 sau 8. Toate caracterele care se folosesc pentru
scrierea literalilor ntregi fac parte din subsetul ASCII al setului Unicode.
Literalii ntregi pot fi ntregi normali sau lungi. Literalii lungi se recunosc prin faptul c se
termin cu sufixul l sau L. Un literal ntreg este reprezentat pe 32 de bii iar unul lung pe 64 de bii.
Un literal ntreg n baza 10 ncepe cu o cifr de la 1 la 9 i se continu cu un ir de cifre de la 0
la 9. Un literal ntreg n baza 10 nu poate s nceap cu cifra 0, pentru c acesta este semnul folosit
pentru a semnaliza literalii scrii n baza 8.
Exemple de literali ntregi n baza 10:
234871
2345678908
13 - d, D
14 - e, E
15 - f, F
n plus, pentru c un literal ntreg n baza 16 poate ncepe cu o liter, vom aduga prefixul 0x
sau 0X. Dac nu am aduga acest sufix, compilatorul ar considera c este vorba despre un identificator.
Exemple de literali ntregi n baza 16:
0xa34 0X123
0x2c45L
0xde123abccdL
Valoarea maxim a unui literal ntreg normal este de 2147483647 (231-1), scris n baza 10. n
baza 16, cel mai mare literal pozitiv se scrie ca 0x7fffffff iar n baza 8 ca 017777777777. Toate trei
scrierile reprezint de fapt aceeai valoare, doar c aceasta este exprimat n baze diferite.
Cea mai mic valoare a unui literal ntreg normal este -2147483648 (-231), respectiv 0x80000000 i
020000000000. Valorile 0xffffffff i 037777777777 reprezint amndou valoarea -1.
Specificarea n surs a unui literal ntreg normal care depete aceste limite reprezint o eroare de
compilare. Cu alte cuvinte, dac folosim n surs numrul: 21474836470 de exemplu, fr s punem
sufixul de numr lung dup el, compilatorul va genera o eroare la analiza sursei.
Valoarea maxim a unui literal ntreg lung este, n baza 10, 9223372036854775807L (2 63-1). n
octal, asta nseamn 0777777777777777777777L iar n baza 16 0x7fffffffffffffffL. n mod asemntor,
valoarea minim a unui literal ntreg lung este -9223372036854775808L (-263-1), n octal aceast
valoare este 0400000000000000000000L iar n baza 16 este 0x8000000000000000L.
La fel ca i la literalii ntregi normali, depirea acestor limite este o eroare de compilare.
Literali flotani
Literalii flotani reprezint numere reale. Ei sunt formai dintr-o parte ntreag, o parte
fracionar, un exponent i un sufix de tip. Exponentul, dac exist, este introdus de litera e sau E
urmat opional de un semn al exponentului.
Este obligatoriu s existe mcar o cifr fie n partea ntreag fie n partea zecimal i punctul
zecimal sau litera e pentru exponent.
Sufixul care indic tipul flotantului poate fi f sau F n cazul n care avem o valoare flotant
normal i d sau D dac avem o valoare flotant dubl. Dac nu este specificat nici un sufix, valoarea
este implicit dubl.
Valoarea maxim a unui literal flotant normal este 3.40282347e+38f iar valoarea cea mai mic
reprezentabil este 1.40239846e-45f, ambele reprezentate pe 32 de bii.
Valoarea
maxim
reprezentabil
a
unui
literal
flotant
dublu
este
de
1.79769313486231570e+308 iar valoarea cea mai mic reprezentabil este 4.94065645841246544e324, ambele reprezentate pe 64 de bii.
-3.456f
0.
.01e-3
Primele dou exemple reprezint literali flotani normali, iar celelalte literali flotani dubli.
Literali booleeni
Literalii booleeni nu pot fi dect true sau false, primul reprezentnd valoarea boolean de
adevr iar cellalt valoarea boolean de fals. True i false nu sunt cuvinte rezervate ale limbajului Java,
dar nu vei putea folosi aceste cuvinte ca identificatori.
Literali caracter
Un literal de tip caracter este utilizat pentru a exprima caracterele codului Unicode.
Reprezentarea se face fie folosind o liter, fie o secven escape. Secvenele escape ne permit
reprezentarea caracterelor care nu au reprezentare grafic i reprezentarea unor caractere speciale
precum backslash i nsi caracterul apostrof.
Caracterele care au reprezentare grafic pot fi reprezentate ntre apostrofe, ca n exemplele:
'a' '' ','
Pentru restul caracterelor Unicode trebuie s folosim secvene escape. Dintre acestea, cteva sunt
predefinite n Java, i anume:
Secven escape
Caracterul reprezentat
'\b'
'\t'
'\n'
'\f'
'\r'
'\"'
'\''
'\\'
'\oo' '\too'
'\34'
Dac irul de caractere este prea lung, putem s-l spargem n buci mai mici pe care s le concatenm
cu operatorul +.
Fiecare ir de caractere este n fapt o instan a clasei de obiecte String declarat standard n
pachetul java.lang.
Exemple de iruri de caractere:
""
"\"""ir de caractere"
"unu" + "doi"
Primul ir de caractere din exemplu nu conine nici un caracter i se numete irul vid. Ultimul
exemplu este format din dou iruri distincte concatenate.
Separatori
Un separator este un caracter care indic sfritul unei uniti lexicale i nceputul alteia.
Separatorii sunt necesari atunci cnd uniti lexicale diferite sunt scrise fr spaii ntre ele. Acestea se
pot totui separa dac unele dintre ele conin caractere separatori. n Java separatorii sunt urmtorii:
(){}[];,.
Exemple de separare:
a[i]
sin(56)
Operatori
Operatorii reprezint simboluri grafice pentru operaiile elementare definite de limbajul Java.
Lista tuturor operatorilor limbajului Java este:
= > < ! ~ ?:
= = <= >= != && || ++ -+ - * / & | ^ % << >> >>>
+= -= *= /= &= |= ^= %= <<= >>= >>>=
S mai precizm deocamdat c toi operatorii joac i rol de separatori. Cu alte cuvinte, din secvena
de caractere:
vasile+gheorghe
Comentarii
Un comentariu este o secven de caractere existent n fiierul surs dar care servete doar
pentru explicarea sau documentarea sursei i nu afecteaz n nici un fel semantica programelor.
n Java exist trei feluri de comentarii:
Comentarii pe mai multe linii, nchise ntre /* i */. Toate caracterele dintre cele dou secvene
sunt ignorate.
Comentarii pe mai multe linii care in de documentaie, nchise ntre /** i */. Textul dintre cele
dou secvene este automat mutat n documentaia aplicaiei de ctre generatorul automat de
documentaie.
Comentarii pe o singur linie care ncep cu //. Toate caracterele care urmeaz acestei secvene
pn la primul caracter sfrit de linie sunt ignorate.
n Java, nu putem s scriem comentarii n interiorul altor comentarii. La fel, nu putem introduce
comentarii n interiorul literalilor caracter sau ir de caractere. Secvenele /* i */ pot s apar pe o linie
dup secvena // dar i pierd semnificaia. La fel se ntmpl cu secvena // n comentarii care ncep
cu /* sau /**.
Ca urmare, urmtoarea secven de caractere formeaz un singur comentariu:
/* acest comentariu /* // /* se termin abia aici: */
Variabile
Declaraii de variabile
O variabil n limbajul Java este o locaie de memorie care poate pstra o valoare de un anumit
tip. n ciuda denumirii, exist variabile care i pot modifica valoarea i variabile care nu i-o pot
modifica, numite n Java variabile finale. Orice variabil trebuie s fie declarat pentru a putea fi
folosit. Aceast declaraie trebuie s conin un tip de valori care pot fi memorate n locaia rezervat
variabilei i un nume pentru variabila declarat. n funcie de locul n sursa programului n care a fost
declarat variabila, aceasta primete o clas de memorare local sau static. Aceast clas de memorare
definete intervalul de existen al variabilei n timpul execuiei.
n forma cea mai simpl, declaraia unei variabile arat n felul urmtor:
Tip NumeVariabil [, NumeVariabil];
Iniializarea variabilelor
Limbajul Java permite iniializarea valorilor variabilelor chiar n momentul declarrii acestora.
Sintaxa este urmtoarea:
Tip NumeVariabil = ValoareIniial;
Desigur, valoarea iniial trebuie s fie de acelai tip cu tipul variabilei sau s poat fi
convertit ntr-o valoare de acest tip.
Dei limbajul Java ne asigur c toate variabilele au o valoare iniial bine precizat, este
preferabil s executm aceast iniializare n mod explicit pentru fiecare declaraie. n acest fel
mrim claritatea propriului cod.
Regula ar fi deci urmtoarea: nici o declaraie fr iniializare.
Tipuri primitive
Tipul boolean
Tipul boolean este folosit pentru memorarea unei valori de adevr. Pentru acest scop, sunt
suficiente doar dou valori: adevrat i fals. n Java aceste dou valori le vom nota prin literalii true
i respectiv false. Aceste valori pot fi reprezentate n memorie folosindu-ne de o singur cifr binar,
adic pe un bit.
Valorile booleene sunt foarte importante n limbajul Java pentru c ele sunt valorile care se
folosesc n condiiile care controleaz instruciunile repetitive sau cele condiionale. Pentru a
exprima o condiie este suficient s scriem o expresie al crui rezultat este o valoare boolean,
adevrat sau fals.
Valorile de tip boolean nu se pot transforma n valori de alt tip n mod nativ. La fel, nu
exist transformare nativ dinspre celelalte valori nspre tipul boolean. Cu alte cuvinte, avnd o
variabil de tip boolean nu putem memora n interiorul acesteia o valoare ntreag pentru c
limbajul Java nu face pentru noi nici un fel de presupunere legat de ce nseamn o anumit valoare
ntreag din punctul de vedere al valorii de adevr. La fel, dac avem o variabil ntreag, nu i
putem atribui o valoare de tip boolean.
Orice variabil boolean nou creat primete automat valoarea implicit false. Putem
modifica aceast comportare specificnd n mod explicit o valoare iniial true.
Pentru a declara o variabil de tip boolean, n Java vom folosi cuvntul rezervat boolean ca n
exemplele de mai jos:
boolean terminat;
boolean areDreptate;
Rndurile de mai sus reprezint declaraia a dou variabile de tip boolean numite terminat
respectiv areDreptate. Cele dou variabile au, dup declaraie, valoarea false.
Tipul caracter
Orice limbaj de programare ne ofer ntr-un fel sau altul posibilitatea de a lucra cu caractere
grafice care s reprezinte litere, cifre, semne de punctuaie, etc. n cazul limbajului Java acest lucru
se poate face folosind tipul primitiv numit tip caracter.
O variabil de tip caracter poate avea ca valoare coduri Unicode reprezentate pe 16 bii,
adic doi octei. Codurile reprezentabile astfel sunt foarte multe, putnd acoperi caracterele de baz
din toate limbile scrise existente.
n Java putem combina mai multe caractere pentru a forma cuvinte sau iruri de caractere
mai lungi. Totui, trebuie s precizm c aceste iruri de caractere nu trebuiesc confundate cu
tablourile de caractere pentru c ele conin n plus informaii legate de lungimea irului.
Codul nu este altceva dect o coresponden ntre numere i caractere fapt care permite
conversii ntre variabile ntregi i caractere n ambele sensuri. O parte din aceste transformri pot s
altereze valoarea original din cauza dimensiunilor diferite ale zonelor n care sunt memorate cele
dou tipuri de valori. Convertirea caracterelor n numere i invers poate s fie util la prelucrarea n
bloc a caracterelor, cum ar fi trecerea tuturor literelor minuscule n majuscule i invers.
Atunci cnd declarm un caracter fr s specificm o valoare iniial, el va primi automat
ca valoare implicit caracterul null al codului Unicode, \u0000.
Pentru a declara o variabil de tip caracter folosim cuvntul rezervat char ca n exemplele
urmtoare:
char primaLiter;
char prima, ultima;
n cele dou linii de cod am declarat trei variabile de tip caracter care au fost automat iniializate cu
caracterul null.
Tipuri ntregi
Tipul octet
ntre tipurile ntregi, acest tip ocup un singur octet de memorie, adic opt cifre binare. ntro variabil de tip octet sunt reprezentate ntotdeauna valori cu semn, ca de altfel n toate variabilele
de tip ntreg definite n limbajul Java. Aceast convenie simplific schema de tipuri primitive care,
n cazul altor limbaje include separat tipuri ntregi cu semn i fr.
Fiind vorba de numere cu semn, este nevoie de o convenie de reprezentare a semnului.
Convenia folosit de Java este reprezentarea n complement fa de doi. Aceast reprezentare este
de altfel folosit de majoritatea limbajelor actuale i permite memorarea, pe 8 bii a 256 de numere
ncepnd de la -128 pn la 127. Dac avei nevoie de numere mai mari n valoare absolut, apelai la
alte tipuri ntregi.
Valoarea implicit pentru o variabil neiniializat de tip octet este valoarea 0 reprezentat pe un
octet.
Iat i cteva exemple de declaraii care folosesc cuvntul Java rezervat byte:
byte octet;
byte eleviPeClasa;
Tipul ntreg scurt
Tipul ntreg scurt este similar cu tipul octet dar valorile sunt reprezentate pe doi octei, adic
16 bii. La fel ca i la tipul octet, valorile sunt ntotdeauna cu semn i se folosete reprezentarea n
complement fa de doi. Valorile de ntregi scuri reprezentabile sunt de la -32768 la 32767 iar
valoarea implicit este 0 reprezentat pe doi octei.
Pentru declararea variabilelor de tip ntreg scurt n Java se folosete cuvntul rezervat short,
ca n exemplele urmtoare:
short i, j;
short valoareNuPreaMare;
Tipul ntreg
Singura diferen dintre tipul ntreg i tipurile precedente este faptul c valorile sunt
reprezentate pe patru octei adic 32 bii. Valorile reprezentabile sunt de la -2147483648 la 2147483647
valoarea implicit fiind 0. Cuvntul rezervat este int ca n:
int salariu;
Tipul ntreg lung
n fine, pentru cei care vor s reprezinte numerele ntregi cu semn pe 8 octei, 64 de bii,
tipul ntreg lung. Valorile reprezentabile sunt de la -9223372036854775808 la
9223372036854775807 iar valoarea implicit este 0L.
Pentru cei care nu au calculatoare care lucreaz pe 64 de bii este bine de precizat faptul c
folosirea acestui tip duce la operaii lente pentru c nu exist operaii native ale procesorului care s
lucreze cu numere aa de mari.
Declaraia se face cu cuvntul rezervat long.
exist
Tipuri flotante
Acest tip este folosit pentru reprezentarea numerelor reale sub form de exponent i cifre
semnificative. Reprezentarea se face pe patru octei, 32 bii, aa cum specific standardul IEEE
Tipul flotant
unde s este semnul +1 sau -1, m este partea care specific cifrele reprezentative ale numrului,
numit i mantis, un ntreg pozitiv mai mic dect 224 iar e este un exponent ntreg ntre -149 i 104.
Valoarea implicit pentru variabilele flotante este 0.0f. Pentru declararea unui numr flotant, Java
definete cuvntul rezervat float. Declaraiile se fac ca n exemplele urmtoare:
float procent;
float x,y;
Tipul flotant dublu
Dac valorile reprezentabile n variabile flotante nu sunt destul de precise sau destul de
mari, putei folosi tipul flotant dublu care folosete opt octei pentru reprezentare, urmnd acelai
standard IEEE
Valorile finite reprezentabile cu flotani dubli sunt de forma:
sm2e
unde s este semnul +1 sau -1, m este mantisa, un ntreg pozitiv mai mic dect 253 iar e este un
exponent ntreg ntre -1045 i 1000. Valoarea implicit n acest caz este 0.0d.
Pentru a declara flotani dubli, Java definete cuvntul rezervat double ca n:
double distanaPnLaLun;
n afar de valorile definite pn acum, standardul IEEE definete cteva valori speciale
reprezentabile pe un flotant sau un flotant dublu.
Reali speciali definii de IEEE
Prima dintre acestea este NaN (Not a Number), valoare care se obine atunci cnd efectum
o operaie a crei rezultat nu este definit, de exemplu 0.0 / 0.0.
n plus, standardul IEEE definete dou valori pe care le putem folosi pe post de infinit pozitiv i
negativ. i aceste valori pot rezulta n urma unor calcule.
Aceste valori sunt definite sub form de constante i n ierarhia standard Java, mai precis n clasa
java.lang.Float i respectiv n java.lang.Double. Numele constantelor este POSITIVE_INFINITY,
NEGATIVE_INFINITY, NaN.
n plus, pentru tipurile ntregi i ntregi lungi i pentru tipurile flotante exist definite clase
n ierarhia standard Java care se numesc respectiv java.lang.Integer, java.lang.Long, java.lang.Float
i java.lang.Double. n fiecare dintre aceste clase numerice sunt definite dou constante care
reprezint valorile minime i maxime care se pot reprezenta n tipurile respective. Aceste dou
constante se numesc n mod uniform MIN_VALUE i MAX_VALUE.
Tipuri referin
Tipurile referin sunt folosite pentru a referi un obiect din interiorul unui alt obiect. n acest
mod putem nlnui informaiile aflate n memorie.
Tipurile referin au, la fel ca i toate celelalte tipuri o valoare implicit care este atribuit
automat oricrei variabile de tip referin care nu a fost iniializat. Aceast valoare implicit este
definit de ctre limbajul Java prin cuvntul rezervat null.
Putei nelege semnificaia referinei nule ca o referin care nu trimite nicieri, a crei
destinaie nu a fost nc fixat.
Simpla declaraie a unei referine nu duce automat la rezervarea spaiului de memorie pentru
obiectul referit. Singura rezervare care se face este aceea a spaiului necesar memorrii referinei n
sine. Rezervarea obiectului trebuie fcut explicit n program printr-o expresie de alocare care
folosete cuvntul rezervat new.
O variabil de tip referin nu trebuie s trimit pe tot timpul existenei sale ctre acelai
obiect n memorie. Cu alte cuvinte, variabila i poate schimba locaia referit n timpul execuiei.
Tipul referin ctre o clas
Tipul referin ctre o clas este un tip referin care trimite ctre o instan a unei clase de
obiecte. Clasa instanei referite poate fi oricare clas valid definit de limbaj sau de utilizator.
Clasa de obiecte care pot fi referite de o anumit variabil de tip referin la clas trebuie
declarat explicit. De exemplu, pentru a declara o referin ctre o instan a clasei Minge, trebuie s
folosim urmtoarea sintax:
Minge mingeaMea;
Din acest moment, variabila referin de clas numit mingeaMea va putea pstra doar
referine ctre obiecte de tip Minge sau ctre obiecte aparinnd unor clase derivate din clasa Minge.
De exemplu, dac avem o alt clas, derivat din Minge, numit MingeDeBaschet, putem memora n
referina mingeaMea i o trimitere ctre o instan a clasei MingeDeBaschet.
n mod general ns, nu se pot pstra n variabila mingeaMea referine ctre alte clase de
obiecte. Dac se ncerc acest lucru, eroarea va fi semnalat chiar n momentul compilrii, atunci
cnd sursa programului este examinat pentru a fi transformat n instruciuni ale mainii virtuale
Java.
Tipul referin ctre o interfa
Tipul referin ctre o interfa permite pstrarea unor referine ctre obiecte care respect o
anumit interfa. Clasa obiectelor referite poate fi oricare, atta timp ct clasa respectiv
implementeaz interfaa cerut.
Declaraia se face cu urmtoarea sintax:
ObiectSpaioTemporal mingeaLuiVasile;
n care tipul este chiar numele interfeei cerute. Dac clasa de obiecte Minge declar c
implementeaz aceast interfa, atunci variabila referin mingeaLuiVasile poate lua ca valoare
referina ctre o instan a clasei Minge sau a clasei MingeDeBaschet.
Prin intermediul unei variabile referin ctre o interfa nu se poate apela dect la
funcionalitatea cerut n interfaa respectiv, chiar dac obiectele reale ofer i alte faciliti, ele
aparinnd unor clase mai bogate n metode.
Tipul referin ctre un tablou
Tipul referin ctre un tablou este un tip referin care poate pstra o trimitere ctre locaia
din memorie a unui tablou de elemente. Prin intermediul acestei referine putem accesa elementele
tabloului furniznd indexul elementului dorit.
Tablourile de elemente nu exist n general ci ele sunt tablouri formate din elemente de un
tip bine precizat. Din aceast cauz, atunci cnd declarm o referin ctre un tablou, trebuie s
precizm i de ce tip sunt elementele din tabloul respectiv.
La declaraia referinei ctre tablou nu trebuie s precizm i numrul de elemente din
tablou.
Iat cum se declar o referin ctre un tablou de ntregi lungi:
long numere[];
Numele variabilei este numere. Un alt exemplu de declaraie de referin ctre un tablou:
Minge echipament[];
Declaraia de mai sus construiete o referin ctre un tablou care pstreaz elemente de tip referin
ctre o instan a clasei Minge. Numele variabilei referin este echipament. Parantezele drepte de
dup numele variabilei specific faptul c este vorba despre un tablou.
Clasa de memorare
Fiecare variabil trebuie s aib o anumit clas de memorare. Aceast clas ne permite s
aflm care este intervalul de existen i vizibilitatea unei variabile n contextul execuiei unui
program.
Este important s nelegem exact aceast noiune pentru c altfel vom ncerca s referim variabile
nainte ca acestea s fi fost create sau dup ce au fost distruse sau s referim variabile care nu sunt
vizibile din zona de program n care le apelm.
Variabile locale
Aceste variabile nu au importan prea mare n contextul ntregii aplicaii, ele servind la
rezolvarea unor probleme locale. Variabilele locale sunt declarate, rezervate n memorie i utilizate
doar n interiorul unor blocuri de instruciuni, fiind distruse automat la ieirea din aceste blocuri.
Aceste variabile sunt vizibile doar n interiorul blocului n care au fost create i n subblocurile
acestuia.
Variabile statice
Variabilele statice sunt n general legate de funcionalitatea anumitor clase de obiecte ale
cror instane folosesc n comun aceste variabile. Variabilele statice sunt create atunci cnd codul
specific clasei n care au fost declarate este ncrcat n memorie i nu sunt distruse dect atunci cnd
acest cod este eliminat din memorie.
Valorile memorate n variabile statice au importan mult mai mare n aplicaie dect cele
locale, ele pstrnd informaii care nu trebuie s se piard la dispariia unei instane a clasei. De
exemplu, variabila n care este memorat numrul de picioare al obiectelor din clasa Om nu trebuie
s fie distrus la dispariia unei instane din aceast clas. Aceasta din cauz c i celelalte instane
ale clasei folosesc aceeai valoare. i chiar dac la un moment dat nu mai exist nici o instan a
acestei clase, numrul de picioare ale unui Om trebuie s fie accesibil n continuare pentru
interogare de ctre celelalte clase.
Variabilele statice nu se pot declara dect ca variabile ale unor clase i conin n declaraie
cuvntul rezervat static. Din cauza faptului c ele aparin clasei i nu unei anumite instane a clasei,
variabilele statice se mai numesc uneori i variabile de clas.
Variabile dinamice
Un alt tip de variabile sunt variabilele a cror perioad de existen este stabilit de ctre
programator. Aceste variabile pot fi alocate la cerere, dinamic, n orice moment al execuiei
programului. Ele vor fi distruse doar atunci cnd nu mai sunt referite de nicieri.
La alocarea unei variabile dinamice, este obligatoriu s pstrm o referin ctre ea ntr-o
variabil de tip referin. Altfel, nu vom putea accesa n viitor variabila dinamic. n momentul n
care nici o referin nu mai trimite ctre variabila dinamic, de exemplu pentru c referina a fost o
variabil local i blocul n care a fost declarat i-a terminat execuia, variabila dinamic este
distrus automat de ctre sistem printr-un mecanism numit colector de gunoaie.
Colectorul de gunoaie poate porni din iniiativa sistemului sau din iniiativa programatorului
la momente bine precizate ale execuiei.
Pentru a rezerva spaiu pentru o variabil dinamic este nevoie s apelm la o expresie de
alocare care folosete cuvntul rezervat new. Aceast expresie aloc spaiul necesar pentru un
anumit tip de valoare. De exemplu, pentru a rezerva spaiul necesar unui obiect de tip Minge, putem
apela la sintaxa:
Minge mingeaMea = new Minge( );
iar pentru a rezerva spaiul necesar unui tablou de referine ctre obiecte de tip Minge putem folosi
declaraia:
Minge echipament[] = new Minge[5];
Am alocat astfel spaiu pentru un tablou care conine 5 referine ctre obiecte de tip Minge. Pentru
alocarea tablourilor coninnd tipuri primitive se folosete aceeai sintax. De exemplu, urmtoarea
linie de program aloc spaiul necesar unui tablou cu 10 ntregi, crend n acelai timp i o variabil
referin spre acest tablou, numit numere:
int numere[] = new int[10];
Tablouri de variabile
Tablourile servesc, dup cum s-a vzut, la memorarea secvenelor de elemente de acelai tip.
Tablourile unidimensionale au semnificaia vectorilor de elemente. Se poate ntmpla s lucrm i
cu tablouri de referine ctre tablouri, n acest caz modelul fiind acela al unei matrici
bidimensionale, sau putem extinde definiia i pentru mai mult de dou dimensiuni.
Declaraia variabilelor de tip tablou
Pentru a declara variabile de tip tablou, trebuie s specificm tipul elementelor care vor
umple tabloul i un nume pentru variabila referin care va pstra trimiterea ctre zona de memorie
n care sunt memorate elementele tabloului.
Dei putem declara variabile referin ctre tablou i separat, de obicei declaraia este fcut
n acelai timp cu alocarea spaiului ca n exemplele din paragraful anterior.
Sintaxa Java permite plasarea parantezelor drepte care specific tipul tablou nainte sau dup
numele variabilei. Astfel, urmtoarele dou declaraii sunt echivalente:
int[ ] numere;
int numere[ ];
Dac dorii s folosii tablouri cu dou dimensiuni ca matricile, putei s declarai un tablou de
referine ctre tablouri cu una dintre urmtoarele trei sintaxe echivalente:
float [ ][ ] matrice;
float[ ] matrice[];
float matrice[][];
De precizat c i n cazul dimensiunilor multiple, declaraiile de mai sus nu fac nimic altceva
dect s rezerve loc pentru o referin i s precizeze numrul de dimensiuni. Alocarea spaiului
pentru elementele tabloului trebuie fcut explicit.
Pentru tablourile cu mai multe dimensiuni, rezervarea spaiului se poate face cu urmtoarea sintax:
byte [][]octeti = new byte[23][5];
n expresia de alocare sunt specificate n clar numrul elementelor pentru fiecare dimensiune a
tabloului.
Iniializarea tablourilor.
Limbajul Java permite i o sintax pentru iniializarea elementelor unui tablou. ntr-un astfel
de caz este rezervat automat i spaiul de memorie necesar memorrii valorilor iniiale. Sintaxa
folosit n astfel de cazuri este urmtoarea:
char []caractere = { a, b , c , d };
Acest prim exemplu aloc spaiu pentru patru elemente de tip caracter i iniializeaz aceste
elemente cu valorile dintre acolade. Dup aceea, creeaz variabila de tip referin numit caractere
i o iniializeaz cu referina la zona de memorie care pstreaz cele patru valori.
Iniializarea funcioneaz i la tablouri cu mai multe dimensiuni ca n exemplele urmtoare:
int [][]numere = {
{ 1, 3, 4, 5 },
{ 2, 4, 5 },
{ 1, 2, 3, 4, 5 }
};
double [][][]reali = {
{ { 0.0, -1.0 }, { 4.5 } },
{ { 2.5, 3.0 } }
};
Dup cum observai numrul iniializatorilor nu trebuie s fie acelai pentru fiecare element.
Lungimea tablourilor
Tablourile Java sunt alocate dinamic, ceea ce nseamn c ele i pot schimba dimensiunile pe
parcursul execuiei. Pentru a afla numrul de elemente dintr-un tablou, putem apela la urmtoarea
sintax:
float []tablou = new float[25];
int dimensiune = tablou.length;
sau
float [][]multiTablou = new float[3][4];
int dimensiune1 = multiTablou[2].length;
int dimensiune2 = multiTablou.length;
n cazul tablourilor cu mai multe dimensiuni, avem n realitate tablouri de referine la tablouri. Asta
nseamn c dac considerm urmtoarea declaraie:
char [][]caractere = new char [5][];
Noile tablouri sunt referite din interiorul tabloului original. Elementele noilor tablouri sunt caractere.
Variabilele de tip referin caractere[0] i tablouDeCaractere trimit spre acelai tablou rezervat n memorie.
Conversii
Operaiile definite n limbajul Java au un tip bine precizat de argumente. Din pcate, exist
situaii n care nu putem transmite la apelul acestora exact tipul pe care compilatorul Java l
ateapt. n asemenea situaii, compilatorul are dou alternative: fie respinge orice operaie cu
argumente greite, fie ncearc s converteasc argumentele ctre tipurile necesare. Desigur, n
cazul n care conversia nu este posibil, singura alternativ rmne prima.
n multe situaii ns, conversia este posibil. S lum de exemplu tipurile ntregi. Putem s
convertim ntotdeauna un ntreg scurt la un ntreg. Valoarea rezultat va fi exact aceeai. Conversia
invers ns, poate pune probleme dac valoarea memorat n ntreg depete capacitatea de
memorare a unui ntreg scurt.
n afar de conversiile implicite, pe care compilatorul le hotrte, exist i conversii
explicite, pe care programatorul le poate fora la nevoie. Aceste conversii efectueaz de obicei
operaii n care exist pericolul s se piard o parte din informaii. Compilatorul nu poate hotr de
unul singur n aceste situaii.
Conversiile implicite pot fi un pericol pentru stabilitatea aplicaiei dac pot s duc la
pierderi de informaii fr avertizarea programatorului. Aceste erori sunt de obicei extrem de greu
de depistat.
n fiecare limbaj care lucreaz cu tipuri fixe pentru datele sale exist conversii imposibile,
conversii periculoase i conversii sigure. Conversiile imposibile sunt conversiile pe care limbajul nu
le permite pentru c nu tie cum s le execute sau pentru c operaia este prea periculoas. De
exemplu, Java refuz s converteasc un tip primitiv ctre un tip referin. Dei s-ar putea imagina o
astfel de conversie bazat pe faptul c o adres este n cele din urm un numr natural, acest tip de
conversii sunt extrem de periculoase, chiar i atunci cnd programatorul cere explicit aceast
conversie.
Conversii de extindere a valorii
n aceste conversii valoarea se reprezint ntr-o zon mai mare fr s se piard nici un fel de
informaii. Iat conversiile de extindere pe tipuri primitive:
S mai precizm totui c, ntr-o parte din aceste cazuri, putem pierde din precizie. Aceast
situaie apare de exemplu la conversia unui long ntr-un float, caz n care se pierd o parte din cifrele
semnificative pstrndu-se ns ordinul de mrime. De altfel aceast observaie este evident dac
inem cont de faptul c un long este reprezentat pe 64 de bii n timp ce un float este reprezentat doar
pe 32 de bii.
Precizia se pierde chiar i n cazul conversiei long la double sau int la float pentru c, dei
dimensiunea zonei alocat pentru cele dou tipuri este aceeai, numerele flotante au nevoie de o
parte din aceast zon pentru a reprezenta exponentul.
n aceste situaii, se va produce o rotunjire a numerelor reprezentate.
Conversii de trunchiere a valorii
Conveniile de trunchiere a valorii pot produce pierderi de informaie pentru c ele convertesc
tipuri mai bogate n informaii ctre tipuri mai srace. Conversiile de trunchiere pe tipurile
elementare sunt urmtoarele:
byte la char
short la byte sau char
char la byte sau short
int la byte, short sau char
long la byte, short char, sau int
float la byte, short, char, int sau long
double la byte, short, char, int, long sau float.
O referin ctre un obiect aparinnd unei clase C poate fi convertit la o referin ctre un
obiect aparinnd clasei S doar n cazul n care C este chiar S sau C este derivat direct sau
indirect din S.
O referin ctre un obiect aparinnd unei clase C poate fi convertit ctre o referin de
interfa I numai dac clasa C implementeaz interfaa I.
O referin ctre un tablou poate fi convertit la o referin ctre o clas numai dac clasa
respectiv este clasa Object.
O referin ctre un tablou de elemente ale crui elemente sunt de tipul T1 poate fi
convertit la o referin ctre un tablou de elemente de tip T2 numai dac T1 i T2 reprezint
acelai tip primitiv sau T2 este un tip referin i T1 poate fi convertit ctre T2.
Conversii la operaia de atribuire
Conversiile pe care limbajul Java le execut implicit la atribuire sunt foarte puine. Mai
exact, sunt executate doar acele conversii care nu necesit validare n timpul execuiei i care nu pot
pierde informaii n cazul tipurilor primitive.
n cazul valorilor aparinnd tipurilor primitive, urmtorul tabel arat conversiile posibile. Pe
coloane avem tipul de valoare care se atribuie iar pe linii avem tipurile de variabile la care se
atribuie:
boolean char byte short int long float double
boolean
Da
Nu
Nu
Nu
Nu Nu
Nu
Nu
char
Nu
Da
Da
Da
Nu Nu
Nu
Nu
byte
Nu
Da
Da
Nu
Nu Nu
Nu
Nu
short
Nu
Da
Da
Da
Nu Nu
Nu
Nu
int
Nu
Da
Da
Da
Da Nu
Nu
Nu
long
Nu
Da
Da
Da
Da Da
Nu
Nu
float
Nu
Da
Da
Da
Da Da
Da
Nu
double
Nu
Da
Da
Da
Da Da
Da
Da
Conversiile posibile ntr-o operaie de atribuire cu tipuri primitive. Coloanele reprezint tipurile care se atribuie
iar liniile reprezint tipul de variabil ctre care se face atribuirea.
Dup cum se observ, tipul boolean nu poate fi atribuit la o variabil de alt tip.
Valorile de tip primitiv nu pot fi atribuite variabilelor de tip referin. La fel, valorile de tip
referin nu pot fi memorate n variabile de tip primitiv. n ceea ce privete tipurile referin ntre
ele, urmtorul tabel definete situaiile n care conversiile sunt posibile la atribuirea unei valori de
tipul T la o variabil de tipul S: S=T
T este o interfa
T trebuie s fie
subclas a lui S
T trebuie s fie o
subclas a lui S
eroare la
compilare
eroare la
compilare
eroare la compilare
T trebuie s
implementeze
interfaa S
T trebuie s
implementeze
interfaa S
T trebuie s fie o
subinterfa a lui
S
eroare la compilare
S = A[] este un
tablou cu
elemente de tipul
A
eroare la compilare
eroare la compilare
eroare la
compilare
Conversii explicite
Conversiile de tip cast, sau casturile, sunt apelate de ctre programator n mod explicit.
Sintaxa pentru construcia unui cast este scrierea tipului ctre care dorim s convertim n paranteze
n faa valorii pe care dorim s o convertim. Forma general este:
( Tip ) Valoare
Conversiile posibile n acest caz sunt mai multe dect conversiile implicite la atribuire pentru c n
acest caz programatorul este prevenit de eventuale pierderi de date el trebuind s apeleze conversia
explicit. Dar, continu s existe conversii care nu se pot apela nici mcar n mod explicit.
n cazul conversiilor de tip cast, orice valoare numeric poate fi convertit la orice valoare
numeric.
n continuare, valorile de tip boolean nu pot fi convertite la nici un alt tip.
Nu exist conversii ntre valorile de tip referin i valorile de tip primitiv.
n cazul conversiilor dintr-un tip referin ntr-altul putem separa dou cazuri. Dac compilatorul
poate decide n timpul compilrii dac conversia este corect sau nu, o va decide. n cazul n care
compilatorul nu poate decide pe loc, se va efectua o verificare a conversiei n timpul execuiei. Dac
conversia se dovedete greit, va apare o eroare de execuie i programul va fi ntrerupt.
Iat un exemplu de situaie n care compilatorul nu poate decide dac conversia este posibil sau nu:
Minge mingeaMea;
....
MingeDeBaschet mingeaMeaDeBaschet;
// MingeDeBaschet este o clas derivat din clasa
Minge
mingeaMeaDeBaschet=(MingeDeBaschet)mingeaMea;
n acest caz, compilatorul nu poate fi sigur dac referina memorat n variabila mingeaMea este de
tip MingeDeBaschet sau nu pentru c variabilei de tip Minge i se pot atribui i referine ctre instane de
tip Minge n general, care nu respect ntru totul definiia clasei MingeDeBaschet sau chiar referin
ctre alte tipuri de minge derivate din clasa Minge, de exemplu MingeDePolo care implementeaz
proprieti i operaii diferite fa de clasa MingeDeBaschet.
Iat i un exemplu de conversie care poate fi decis n timpul compilrii:
Minge mingeaMea;
MingeDeBaschet mingeaMeaDeBaschet;
....
mingeaMea = ( Minge ) mingeaMeaDeBaschet;
n fine, tabelul urmtor arat conversiile de tip cast a cror corectitudine poate fi stabilit n timpul
compilrii. Conversia ncearc s transforme printr-un cast o referin de tip T ntr-o referin de tip
S.
T este o interfa
T trebuie s fie
subclas a lui S
T trebuie s fie o
subclas a lui S
Totdeauna corect
la compilare
S trebuie s fie
subclas a lui T
T trebuie s fie
aceeai clas ca i
S
S trebuie s
implementeze
interfaa T
eroare la compilare
S este o interfa
Totdeauna corect
la compilare
T trebuie s
implementeze
interfaa S
Totdeauna corect
la compilare
eroare la compilare
S = A[] este un
tablou cu
elemente de tipul
A
T trebuie s fie
Object
eroare la
compilare
eroare la compilare
De exemplu, n urmtoarea operaie amndoi operanzii vor fi convertii la double prin promovare
aritmetic binar:
float f;
double i = f + 3;
Obiecte Java
n primul rnd s observm c, atunci cnd scriem programe n Java nu facem altceva dect s
definim noi i noi clase de obiecte. Dintre acestea, unele vor reprezenta nsi aplicaia noastr n
timp ce altele vor fi necesare pentru rezolvarea problemei la care lucrm. Ulterior, atunci cnd dorim
s lansm aplicaia n execuie nu va trebui dect s instaniem un obiect reprezentnd aplicaia n
sine i s apelm o metod de pornire definit de ctre aplicaie, metod care de obicei are un nume
i un set de parametri bine fixate. Totui, numele acestei metode depinde de contextul n care este
lansat aplicaia noastr.
Aceast abordare a construciei unei aplicaii ne spune printre altele c vom putea lansa oricte
instane ale aplicaiei noastre dorim, pentru c fiecare dintre acestea va reprezenta un obiect n memorie
avnd propriile lui valori pentru variabile. Execuia instanelor diferite ale aplicaiei va urma desigur
ci diferite n funcie de interaciunea fiecreia cu un utilizator, eventual acelai, i n funcie de unii
parametri pe care i putem defini n momentul crerii fiecrei instane.
Modificatori
Modificatorii sunt cuvinte rezervate Java care precizeaz sensul unei declaraii. Iat lista acestora:
static
final
transient
volatile
Dintre acetia, transient nu este utilizat n versiunea curent a limbajului Java. Pe viitor
va fi folosit pentru a specifica variabile care nu conin informaii care trebuie s rmn persistente
la terminarea programului.
Modificatorul volatile specific faptul c variabila respectiv poate fi modificat
asincron cu rularea aplicaiei. n aceste cazuri, compilatorul trebuie s-i ia msuri suplimentare n
cazul generrii i optimizrii codului care se adreseaz acestei variabile.
Modificatorul final este folosit pentru a specifica o variabil a crei valoare nu poate fi
modificat. Variabila respectiv trebuie s primeasc o valoare de iniializare chiar n momentul
declaraiei. Altfel, ea nu va mai putea fi iniializat n viitor. Orice ncercare ulterioar de a seta
valori la aceast variabil va fi semnalat ca eroare de compilare.
Modificatorul static este folosit pentru a specifica faptul c variabila are o singur
valoare comun tuturor instanelor clasei n care este declarat. Modificarea valorii acestei variabile
din interiorul unui obiect face ca modificarea s fie vizibil din celelalte obiecte. Variabilele statice
sunt iniializate la ncrcarea codului specific unei clase i exist chiar i dac nu exist nici o
instan a clasei respective. Din aceast cauz, ele pot fi folosite de metodele statice.
Protecie
n Java exist patru grade de protecie pentru o variabil aparinnd unei clase:
privat
protejat
public
prietenoas
O variabil public este accesibil oriunde este accesibil numele clasei. Cuvntul rezervat
este public.
O variabil protejat este accesibil n orice clas din pachetul creia i aparine clasa n
care este declarat. n acelai timp, variabila este accesibil n toate subclasele clasei date, chiar
dac ele aparin altor pachete. Cuvntul rezervat este protected.
O variabil privat este accesibil doar n interiorul clasei n care a fost declarat. Cuvntul
rezervat este private.
O variabil care nu are nici o declaraie relativ la gradul de protecie este automat o
variabil prietenoas. O variabil prietenoas este accesibil n pachetul din care face parte clasa n
interiorul creia a fost declarat, la fel ca i o variabil protejat. Dar, spre deosebire de variabilele
protejate, o variabil prietenoas nu este accesibil n subclasele clasei date dac aceste sunt
declarate ca aparinnd unui alt pachet. Nu exist un cuvnt rezervat pentru specificarea explicit a
variabilelor prietenoase.
O variabil nu poate avea declarate mai multe grade de protecie n acelai timp. O astfel de
declaraie este semnalat ca eroare de compilare.
Vizibilitate
O variabil poate fi ascuns de declaraia unei alte variabile cu acelai nume. De exemplu,
dac ntr-o clas avem declarat o variabil cu numele unu i ntr-o subclas a acesteia avem
declarat o variabil cu acelai nume, atunci variabila din superclas este ascuns de cea din clas.
Totui, variabila din superclas exist nc i poate fi accesat n mod explicit. Expresia de referire
este, n acest caz:
NumeSuperClas.NumeVariabil
sau
super.NumeVariabil
Declararea metodelor
Pentru a declara o metod, este necesar s declarm numele acesteia, tipul de valoare pe care
o ntoarce, parametrii metodei precum i un bloc n care s descriem instruciunile care trebuiesc
executate atunci cnd metoda este apelat. n plus, orice metod are un numr de modificatori care
descriu proprietile metodei i modul de lucru al acesteia.
Declararea precum i implementarea metodelor se face ntotdeauna n interiorul declaraiei
de clas. Nu exist nici o cale prin care s putem scrie o parte dintre metodele unei clase ntr-un
fiier separat care s fac referin apoi la declaraia clasei.
n form general, declaraia unei metode arat n felul urmtor:
[Modificator] TipRezultat Declaraie [ClauzeThrows] CorpulMetodei
Modificatorii precum i clauzele throws pot s lipseasc.
Numele i parametrii metodelor
Recunoaterea unei anumite metode se face dup numele i tipul parametrilor si. Pot exista
metode cu acelai nume dar avnd parametri diferii. Acest fenomen poart numele de
suprancrcarea numelui unei metode.
Numele metodei este un identificator Java. Avem toat libertatea n a alege numele pe care l
dorim pentru metodele noastre, dar n general este preferabil s alegem nume care sugereaz
utilizarea metodei.
Numele unei metode ncepe de obicei cu liter mic. Dac acesta este format din mai multe
cuvinte, litera de nceput a fiecrui cuvnt va fi majuscul. n acest mod numele unei metode este
foarte uor de citit i de depistat n surs.
Parametrii metodei sunt n realitate nite variabile care sunt iniializate n momentul apelului
cu valori care controleaz modul ulterior de execuie. Aceste variabile exist pe toat perioada
execuiei metodei. Se pot scrie metode care s nu aib nici un parametru.
Fiind o variabil, fiecare parametru are un tip i un nume. Numele trebuie s fie un
identificator Java. Dei avem libertatea s alegem orice nume dorim, din nou este preferabil s
alegem nume care s sugereze scopul la care va fi utilizat parametrul respectiv.
Tipul unui parametru este oricare dintre tipurile valide n Java. Acestea poate fi fie un tip
primitiv, fie un tip referin ctre obiect, interfa sau tablou.
n momentul apelului unei metode, compilatorul ncearc s gseasc o metod n interiorul
clasei care s aib acelai nume cu cel apelat i acelai numr de parametri ca i apelul. Mai mult,
tipurile parametrilor de apel trebuie s corespund cu tipurile parametrilor declarai ai metodei
gsite sau s poat fi convertii la acetia.
Dac o astfel de metod este gsit n declaraia clasei sau n superclasele acesteia,
parametrii de apel sunt convertii ctre tipurile declarate i se genereaz apelul ctre metoda
respectiv.
Este o eroare de compilare s declarm dou metode cu acelai nume, acelai numr de
parametri i acelai tip pentru parametrii corespunztori. ntr-o asemenea situaie, compilatorul n-ar
mai ti care metod trebuie apelat la un moment dat.
De asemenea, este o eroare de compilare s existe dou metode care se potrivesc la acelai
apel. Acest lucru se ntmpl cnd nici una dintre metodele existente nu se potrivete exact i cnd
exist dou metode cu acelai nume i acelai numr de parametri i, n plus, parametrii de apel se
pot converti ctre parametrii declarai ai ambelor metode.
Rezolvarea unei astfel de probleme se face prin conversia explicit (cast) de ctre
programator a valorilor de apel spre tipurile exacte ale parametrilor metodei pe care dorim s o
apelm n realitate.
n fine, forma general de declaraie a numelui i parametrilor unei metode este:
NumeMetod( [TipParametru NumeParametru] [,TipParametru NumeParametru] )
Modificatori de metode
Modificatorii sunt cuvinte cheie ale limbajului Java care specific proprieti suplimentare
pentru o metod. Iat lista complet a acestora n cazul metodelor:
static - pentru metodele statice
abstract - pentru metodele abstracte
final - pentru metodele finale
native - pentru metodele native
synchronized - pentru metodele sincronizate
Metode statice
n mod normal, o metod a unei clase se poate apela numai printr-o instan a clasei
respective sau printr-o instan a unei subclase. Acest lucru se datoreaz faptului c metoda face
apel la o serie de variabile ale clasei care sunt memorate n interiorul instanei i care au valori
diferite n instane diferite. Astfel de metode se numesc metode ale instanelor clasei.
Dup cum tim deja, exist i un alt tip de variabile, i anume variabilele de clas sau
variabilele statice care sunt comune tuturor instanelor clasei respective i exist pe toat perioada
de timp n care clasa este ncrcat n memorie. Aceste variabile pot fi accesate fr s avem nevoie
de o instan a clasei respective.
n mod similar exist i metode statice. Aceste metode nu au nevoie de o instan a clasei
sau a unei subclase pentru a putea fi apelate pentru c ele nu au voie s foloseasc variabile care
sunt memorate n interiorul instanelor. n schimb, aceste metode pot s foloseasc variabilele
statice declarate n interiorul clasei.
Orice metod static este implicit i final.
Metode abstracte
Metodele abstracte sunt metode care nu au corp de implementare. Ele sunt declarate numai
pentru a fora subclasele care vor s aib instane s implementeze metodele respective.
Metodele abstracte trebuie declarate numai n interiorul claselor care au fost declarate
abstracte. Altfel compilatorul va semnala o eroare de compilare. Orice subclas a claselor abstracte
care nu este declarat abstract trebuie s ofere o implementare a acestor metode, altfel va fi
generat o eroare de compilare.
Prin acest mecanism ne asigurm c toate instanele care pot fi convertite ctre clasa care
conine definiia unei metode abstracte au implementat metoda respectiv dar, n acelai timp, nu
este nevoie s implementm n nici un fel metoda chiar n clasa care o declar pentru c nu tim pe
moment cum va fi implementat.
O metod static nu poate fi declarat i abstract pentru c o metod static este implicit
final i nu poate fi rescris.
Metode finale
O metod final este o metod care nu poate fi rescris n subclasele clasei n care a fost
declarat. O metod este rescris ntr-o subclas dac aceasta implementeaz o metod cu acelai
nume i acelai numr i tip de parametri ca i metoda din superclas.
Declararea metodelor finale este util n primul rnd compilatorului care poate genera
metodele respective direct n codul rezultat fiind sigur c metoda nu va avea nici o alt
implementare n subclase.
Metode native
Metodele native sunt metode care sunt implementate pe o cale specific unei anumite
platforme. De obicei aceste metode sunt implementate n C sau n limbaj de asamblare. Metoda
propriu-zis nu poate avea corp de implementare pentru c implementarea nu este fcut n Java.
n rest, metodele native sunt exact ca orice alt metod Java. Ele pot fi motenite, pot fi
statice sau nu, pot fi finale sau nu, pot s rescrie o metod din superclas i pot fi la rndul lor
rescrise n subclase.
Metode sincronizate
O metod sincronizat este o metod care conine cod critic pentru un anumit obiect sau
clas i nu poate fi rulat n paralel cu nici o alt metod critic sau cu o instruciune
synchronized referitoare la acelai obiect sau clas.
nainte de execuia metodei, obiectul sau clasa respectiv sunt blocate. La terminarea
metodei, acestea sunt deblocate.
Dac metoda este static atunci este blocat o ntreag clas, clasa din care face parte
metoda. Altfel, este blocat doar instana n contextul creia este apelat metoda.
Protejarea metodelor
Accesul la metodele unei clase este protejat n acelai fel ca i accesul la variabilele clasei.
n Java exist patru grade de protecie pentru o metod aparinnd unei clase:
privat
protejat
public
prietenoas
O metod declarat public este accesibil oriunde este accesibil numele clasei. Cuvntul
rezervat este public.
O metod declarat protejat este accesibil n orice clas din pachetul creia i aparine
clasa n care este declarat. n acelai timp, metoda este accesibil n toate subclasele clasei date,
chiar dac ele aparin altor pachete. Cuvntul rezervat este protected.
O metod declarat privat este accesibil doar n interiorul clasei n care a fost declarat.
Cuvntul rezervat este private.
O metod care nu are nici o declaraie relativ la gradul de protecie este automat o metod
prietenoas. O metod prietenoas este accesibil n pachetul din care face parte clasa n interiorul
creia a fost declarat la fel ca i o metod protejat. Dar, spre deosebire de metodele protejate, o
metod prietenoas nu este accesibil n subclasele clasei date dac aceste sunt declarate ca
aparinnd unui alt pachet. Nu exist un cuvnt rezervat pentru specificarea explicit a metodelor
prietenoase.
O metod nu poate avea declarate mai multe grade de protecie n acelai timp. O astfel de
declaraie este semnalat ca eroare de compilare.
Apelul metodelor
Pentru a apela o metod a unei clase este necesar s dispunem de o cale de acces la metoda
respectiv. n plus, trebuie s dispunem de drepturile necesare apelului metodei.
Sintaxa efectiv de acces este urmtoarea:
CaleDeAcces.Metod( Parametri )
n cazul n care metoda este static, pentru a specifica o cale de acces este suficient s
furnizm numele clasei n care a fost declarat metoda. Accesul la numele clasei se poate obine fie
importnd clasa sau ntreg pachetul din care face parte clasa fie specificnd n clar numele clasei i
drumul de acces ctre aceasta.
De exemplu, pentru a accesa metoda random definit static n clasa Math aparinnd pachetului
java.lang putem scrie:
double aleator = Math.random();
sau, alternativ:
double aleator = java.lang.Math.random();
n cazul claselor definite n pachetul java.lang nu este necesar nici un import pentru c
acestea sunt implicit importate de ctre compilator.
Cea de-a doua cale de acces este existena unei instane a clasei respective. Prin aceast
instan putem accesa metodele care nu sunt declarate statice, numite uneori i metode ale
instanelor clasei. Aceste metode au nevoie de o instan a clasei pentru a putea lucra, pentru c
folosesc variabile non-statice ale clasei sau apeleaz alte metode non-statice. Metodele primesc
acest obiect ca pe un parametru ascuns.
De exemplu, avnd o instan a clasei Object sau a unei subclase a acesteia, putem obine o
reprezentare sub form de ir de caractere prin:
Object obiect = new Object();
String sir = obiect.toString();
n cazul n care apelm o metod a clasei din care face parte i metoda apelant putem s
renunm la calea de acces n cazul metodelor statice, scriind doar numele metodei i parametrii.
Pentru metodele specifice instanelor, putem renuna la calea de acces, dar n acest caz metoda
acceseaz aceeai instan ca i metoda apelant. n cazul n care metoda apelant este static,
specificarea unei instane este obligatorie n cazul metodelor de instan.
Parametrii de apel servesc mpreun cu numele la identificarea metodei pe care dorim s o
apelm. nainte de a fi transmii, acetia sunt convertii ctre tipurile declarate de parametri ai
metodei, dup cum este descris mai sus.
Specificarea parametrilor de apel se face separndu-i prin virgul. Dup ultimul parametru nu se
mai pune virgul. Dac metoda nu are nici un parametru, parantezele rotunde sunt n continuare
necesare. Exemple de apel de metode cu parametri:
String numar = String.valueOf( 12 );
// 12 -> String
double valoare = Math.abs( 12.54 );
// valoare absolut
String prima = numar.substring( 0, 1 );
// prima litera
void a() { }
n caz general, o metod ntoarce o valoare primitiv sau un tip referin. Putem declara acest tip ca
n:
long abs( int valoare ) { }
Pentru a returna o valoare ca rezultat al execuiei unei metode, trebuie s folosim instruciunea
return, aa cum s-a artat n seciunea dedicat instruciunilor. Instruciunea return trebuie s
conin o expresie a crei valoare s poat fi convertit la tipul declarat al valorii de retur a metodei.
De exemplu:
long abs( int valoare ) {
return Math.abs( valoare );
}
Metoda static abs din clasa Math care primete un parametru ntreg returneaz tot un ntreg. n
exemplul nostru, instruciunea return este corect pentru c exist o cale de conversie de la ntreg
la ntreg lung, conversie care este apelat automat de compilator nainte de ieirea din metod.
n schimb, n exemplul urmtor:
int abs( long valoare ) {
return Math.abs( valoare );
}
compilatorul va genera o eroare de compilare pentru c metoda static abs din clasa Math care
primete ca parametru un ntreg lung ntoarce tot un ntreg lung, iar un ntreg lung nu poate fi
convertit sigur la un ntreg normal pentru c exist riscul deteriorrii valorii, la fel ca la atribuire.
Rezolvarea trebuie s conin un cast explicit:
int abs( long valoare ) {
return ( int )Math.abs( valoare );
}
n cazul n care o metod este declarat void, putem s ne ntoarcem din ea folosind instruciunea
return fr nici o expresie. De exemplu:
void metoda() {
if( )
return;
Specificarea unei expresii n acest caz duce la o eroare de compilare. La fel i n cazul n care
folosim instruciunea return fr nici o expresie n interiorul unei metode care nu este declarat
void.
Vizibilitate
O metod este vizibil dac este declarat n clasa prin care este apelat sau ntr-una din
superclasele acesteia. De exemplu, dac avem urmtoarea declaraie:
class A {
void a() { }
}
class B extends A {
void b() {
a();
c();
}
void c() { .. }
Apelul metodei a n interiorul metodei b din clasa B este permis pentru c metoda a este declarat n
interiorul clasei A care este superclas pentru clasa B. Apelul metodei c n aceeai metod b este
permis pentru c metoda c este declarat n aceeai clas ca i metoda b.
Uneori, o subclas rescrie o metod dintr-o superclas a sa. n acest caz, apelul metodei
respective n interiorul subclasei duce automat la apelul metodei din subclas. Dac totui dorim s
apelm metoda aa cum a fost ea definit n superclas, putem prefixa apelul cu numele superclasei.
De exemplu:
class A {
void a() { }
}
class B extends A {
void a() { .. }
void c() {
a();// metoda a din clasa B
A.a();// metoda a din clasa A
Iniializatori statici
La ncrcarea unei clase sunt automat iniializate toate variabilele statice declarate n
interiorul clasei. n plus, sunt apelai toi iniializatorii statici ai clasei.
Un iniializator static are urmtoarea sintax:
static
BlocDeInstruciuni
Blocul de instruciuni este executat automat la ncrcarea clasei. De exemplu, putem defini
un iniializator static n felul urmtor:
class A {
static double a;
static int b;
static {
a = Math.random();
// numr dublu ntre 0.0 i 1.0
b = ( int )( a * 500 );
// numr ntreg ntre 0 i 500
}
Declaraiile de variabile statice i iniializatorii statici sunt executate n ordinea n care apar n clas.
De exemplu, dac avem urmtoarea declaraie de clas:
class A {
static int i = 11;
static {
i += 100;
i %= 55;
}
static int j = i + 1;
}
Constructori i finalizatori
constructori
La crearea unei noi instane a unei clase sistemul aloc automat memoria necesar instanei
i o iniializeaz cu valorile iniiale specificate sau implicite. Dac dorim s facem iniializri
suplimentare n interiorul acestei memorii sau n alt parte putem descrie metode speciale numite
constructori ai clasei.
Putem avea mai muli constructori pentru aceeai clas, acetia diferind doar prin parametrii
pe care i primesc. Numele tuturor constructorilor este acelai i este identic cu numele clasei.
Declaraia unui constructor este asemntoare cu declaraia unei metode oarecare, cu
diferena c nu putem specifica o valoare de retur i nu putem specifica nici un fel de modificatori.
Dac dorim s returnm dintr-un constructor, trebuie s folosim instruciunea return fr nici o
expresie. Putem ns s specificm gradul de protecie al unui constructor ca fiind public, privat,
protejat sau prietenos.
Constructorii pot avea clauze throws.
Dac o clas nu are constructori, compilatorul va crea automat un constructor implicit care
nu ia nici un parametru i care iniializeaz toate variabilele clasei i apeleaz constructorul
superclasei fr argumente prin super( ). Dac superclasa nu are un constructor care ia zero
argumente, se va genera o eroare de compilare.
Dac o clas are cel puin un constructor, constructorul implicit nu mai este creat de ctre
compilator.
Cnd construim corpul unui constructor avem posibilitatea de a apela, pe prima linie a
blocului de instruciuni care reprezint corpul constructorului, un constructor explicit. Constructorul
explicit poate avea dou forme:
this(
[Parametri] );
super(
[Parametri] );
Cu aceast sintax apelm unul dintre constructorii superclasei sau unul dintre ceilali constructori
din aceeai clas. Aceste linii nu pot aprea dect pe prima poziie n corpul constructorului. Dac
nu apar acolo, compilatorul consider implicit c prima instruciune din corpul constructorului este:
super();
Finalizatori
n Java nu este nevoie s apelm n mod explicit distrugerea unei instane atunci cnd nu
mai este nevoie de ea. Sistemul ofer un mecanism de colectare a gunoaielor care recunoate
situaia n care o instan de obiect sau un tablou nu mai sunt referite de nimeni i le distruge n mod
automat.
Acest mecanism de colectare a gunoaielor ruleaz pe un fir de execuie separat, de prioritate
mic. Nu avem nici o posibilitate s aflm exact care este momentul n care va fi distrus o instan.
Totui, putem specifica o funcie care s fie apelat automat n momentul n care colectorul de
gunoaie ncearc s distrug obiectul.
Aceast funcie are nume, numr de parametri i tip de valoare de retur fixe:
void
finalize()
Crearea instanelor
O instan este creat folosind o expresie de alocare care folosete cuvntul rezervat new. Iat care
sunt paii care sunt executai la apelul acestei expresii:
Se creeaz o nou instan de tipul specificat. Toate variabilele instanei sunt iniializate pe
valorile lor implicite.
Se apeleaz constructorul corespunztor n funcie de parametrii care sunt transmii n
expresia de alocare. Dac instana este creat prin apelul metodei newInstance, se
apeleaz constructorul care nu ia nici un argument.
Dup creare, expresia de alocare returneaz o referin ctre instana nou creat.
Exemple de creare:
A o1 = new A();
B o2 = new B();
class C extends B {
String valoare;
C( String val ) {
// aici exist apel implicit
// al lui super(), adic B()
valoare = val;
}
C( int val ) {
this( String.valueOf( val ) );
}
}
C o3 = new C( "Vasile" );
C o4 = new C( 13 );
O alt cale de creare a unui obiect este apelul metodei newInstance declarate n clasa Class.
Iat paii de creare n acest caz:
Se creeaz o nou instan de acelai tip cu tipul clasei pentru care a fost apelat metoda
newInstance. Toate variabilele instanei sunt iniializate pe valorile lor implicite.
Este apelat constructorul obiectului care nu ia nici un argument.
Dup creare referina ctre obiectul nou creat este returnat ca valoare a metodei
newInstance. Tipul acestei referine va fi Object n timpul compilrii i tipul clasei reale n
timpul execuiei.
Derivarea claselor
O clas poate fi derivat dintr-alta prin folosirea n declaraia clasei derivate a clauzei
extends. Clasa din care se deriv noua clas se numete superclas imediat a clasei derivate.
Toate clasele care sunt superclase ale superclasei imediate ale unei clase sunt superclase i pentru
clasa dat. Clasa nou derivat se numete subclas a clasei din care este derivat.
Sintaxa general este:
class
O clas poate fi derivat dintr-o singur alt clas, cu alte cuvinte o clas poate avea o singur
superclas imediat.
Clasa derivat motenete toate variabilele i metodele superclasei sale. Totui, ea nu poate accesa
dect acele variabile i metode care nu sunt declarate private.
Putem rescrie o metod a superclasei declarnd o metod n noua clas avnd acelai nume i
aceiai parametri. La fel, putem declara o variabil care are acelai nume cu o variabil din
superclas. n acest caz, noul nume ascunde vechea variabil, substituindu-i-se. Putem n continuare
s ne referim la variabila ascuns din superclas specificnd numele superclasei sau folosindu-ne de
variabila super.
Exemplu:
class A {
int a = 1;
void unu() {
System.out.println( a );
}
}
class B extends A {
double a = Math.PI;
void unu() {
System.out.println( a );
}
void doi() {
System.out.println( A.a );
}
void trei() {
unu();
super.unu();
}
}
Dac apelm metoda unu din clasa A, aceasta va afia la consol numrul 1.
Dac apelm metoda unu din clasa B, aceasta va afia la consol numrul PI. Apelul l putem face
de exemplu cu instruciunea:
B obiect = new B();
obiect.unu();
Observai c n metoda unu din clasa B, variabila referit este variabila a din clasa B. Variabila a
din clasa A este ascuns. Putem ns s o referim prin sintaxa A.a ca n metoda doi din clasa B.
n interiorul clasei B, apelul metodei unu fr nici o alt specificaie duce automat la apelul metodei
unu definite n interiorul clasei B. Metoda unu din clasa B rescrie metoda unu din clasa A. Vechea
metod este accesibil pentru a o referi n mod explicit ca n metoda trei din clasa B. Apelul acestei
metode va afia mai nti numrul PI i apoi numrul 1.
Dac avem declarat o variabil de tip referin ctre o instan a clasei A, aceast variabil poate s
conin n timpul execuiei i o referin ctre o instan a clasei B. Invers, afirmaia nu este
valabil.
n clipa n care apelm metoda unu pentru o variabil referin ctre clasa A, sistemul va apela
metoda unu a clasei A sau B n funcie de adevratul tip al referinei din timpul execuiei. Cu alte
cuvinte, urmtoarea secven de instruciuni:
A tablou[] = new A[2];
tablou[0] = new A();
tablou[1] = new B();
for( int i = 0; i < 2; i++ ) {
tablou[i].unu();
}
va afia dou numere diferite, mai nti 1 i apoi PI. Aceasta din cauz c cel de-al doilea element
din tablou este, n timpul execuiei, de tip referin la o instan a clasei B chiar dac la compilare
este de tipul referin la o instan a clasei A.
Acest mecanism se numete legare trzie, i nseamn c metoda care va fi efectiv apelat este
stabilit doar n timpul execuiei i nu la compilare.
Dac nu declarm nici o superclas n definiia unei clase, atunci se consider automat c noua clas
deriv direct din clasa Object, motenind toate metodele i variabilele acesteia.
Interfee
O interfa este n esen o declaraie de tip ce const dintr-un set de metode i constante
pentru care nu s-a specificat nici o implementare. Programele Java folosesc interfeele pentru a
suplini lipsa motenirii multiple, adic a claselor de obiecte care deriv din dou sau mai multe alte
clase.
Sintaxa de declaraie a unei interfee este urmtoarea:
Modificatori interface NumeInterf [ extends [Interfa][, Interfa]]
Corp
Modificatorii unei interfee pot fi doar cuvintele rezervate public i abstract. O
interfa care este public poate fi accesat i de ctre alte pachete dect cel care o definete. n
plus, fiecare interfa este n mod implicit abstract. Modificatorul abstract este permis dar nu
obligatoriu.
Numele interfeelor trebuie s fie identificatori Java. Conveniile de numire a interfeelor le urmeaz
n general pe cele de numire a claselor de obiecte.
Interfeele, la fel ca i clasele de obiecte, pot avea subinterfee. Subinterfeele motenesc toate
constantele i declaraiile de metode ale interfeei din care deriv i pot defini n plus noi elemente.
Pentru a defini o subinterfa, folosim o clauz extends. Aceste clauze specific superinterfaa
unei interfee. O interfa poate avea mai multe superinterfee care se declar separate prin virgul
dup cuvntul rezervat extends. Circularitatea definiiei subinterfeelor nu este permis.
n cazul interfeelor nu exist o rdcin comun a arborelui de derivare aa cum exist pentru
arborele de clase, clasa Object.
n corpul unei declaraii de interfa pot s apar declaraii de variabile i declaraii de
metode. Variabilele sunt implicit statice i finale. Din cauza faptului c variabilele sunt finale, este
obligatoriu s fie specificat o valoare iniial pentru aceste variabile. n plus, aceast valoare
iniial trebuie s fie constant (s nu depind de alte variabile).
Dac interfaa este declarat public, toate variabilele din corpul su sunt implicit declarate
publice.
n ceea ce privete metodele declarate n interiorul corpului unei interfee, acestea sunt
implicit declarate abstracte. n plus, dac interfaa este declarat public, metodele din interior sunt
implicit declarate publice.
Iat un exemplu de declaraii de interfee:
public interface ObiectSpatial {
final int CUB = 0;
final int SFERA = 1;
double greutate();
double volum();
double raza();
int tip();
}
public interface ObiectSpatioTemporal extends ObiectSpatial {
void centrulDeGreutate( long moment, double coordonate[] );
long momentInitial();
long momentFinal();
}
Cele dou interfee definesc comportamentul unui obiect spaial respectiv al unui obiect
spaio-temporal. Un obiect spaial are o greutate, un volum i o raz a sferei minime n care se poate
nscrie.
n plus, putem defini tipul unui obiect folosindu-ne de o serie de valori constante
predefinite precum ar fi SFERA sau CUB.
Un obiect spaio-temporal este un obiect spaial care are n plus o poziie pe axa timpului.
Pentru un astfel de obiect, n afar de proprietile deja descrise pentru obiectele spaiale, trebuie s
avem n plus un moment iniial, de apariie, pe axa timpului i un moment final. Obiectul nostru nu
exist n afara acestui interval de timp. n plus, pentru un astfel de obiect putem afla poziia
centrului su de greutate n fiecare moment aflat n intervalul de existen.
Pentru a putea lucra cu obiecte spaiale i spaio-temporale este nevoie s definim diverse
clase care s implementeze aceste interfee. Acest lucru se face specificnd clauza implements n
declaraia de clas. O clas poate implementa mai multe interfee. Dac o clas declar c
implementeaz o anumit interfa, ea este obligatoriu s implementeze toate metodele declarate n
interfaa respectiv.
De exemplu, putem spune c o minge este un obiect spaial de tip sfer. n plus, mingea are
o poziie n funcie de timp i un interval de existen. Cu alte cuvinte, mingea este chiar un obiect
spaio-temporal. Desigur, n afar de proprietile spaio-temporale mingea mai are i alte
proprieti precum culoarea, proprietarul sau preul de cumprare.
Iat cum ar putea arta definiia clasei de obiecte de tip minge:
import java.awt.Color;
class Minge extends Jucarie implements ObiectSpatioTemporal
int culoare = Color.red;
double pret = 10000.0;
double raza = 0.25;
long nastere;
long moarte;
// metodele din ObiectSpatial
double greutate() {
return raza * 0.5;
}
double raza() {
return raza;
}
double volum() {
return ( 4.0 / 3.0 ) * Math.PI * raza * raza * raza;
}
int tip() {
return SFERA;
}
coordonate[0] = x;
coordonate[1] = y;
coordonate[2] = z;
return true;
}
long momentInitial() {
return nastere;
}
long momentFinal() {
return moarte;
}
int ceCuloare() {
return culoare;
}
double cePret() {
return pret;
}
}
Desigur, toate metodele din interfeele de mai sus trebuiesc implementate, plus alte metode
specifice.
S mai observm c cele dou obiecte deriv din clase diferite: Mingea din Jucrii iar Rezervorul
din Construcii. Dac am putea deriva o clas din dou alte clase, am putea deriva Minge din
Jucarie i ObiectSpatioTemporal iar Rezervor din Constructie i
ObiectSpaioTemporal. ntr-o astfel de situaie, nu ar mai fi necesar ca
ObiectSpaioTemporal s fie o interfa, ci ar fi suficient ca acesta s fie o alt clas.
Din pcate, n Java, o clas nu poate deriva dect dintr-o singur alt clas, aa c este obligatoriu n
astfel de situaii s folosim interfeele. Dac ObiectSpaioTemporal ar fi putut fi o clas, am
fi avut avantajul c puteam implementa acolo metodele cu funcionare identic din cele dou clase
discutate, acestea fiind automat motenite fr a mai fi nevoie de definirea lor de dou ori n fiecare
clas n parte.
Putem crea n continuare metode care s lucreze cu obiecte spaio-temporale, de exemplu o metod
care s afle distana unui corp spaio-temporal fa de un punct dat la momentul su iniial. O astfel
de metod se poate scrie o singur dat, i poate lucra cu toate clasele care implementeaz interfaa
noastr. De exemplu:
return Math.sqrt( x * x + y * y + z * z );
}
Putem apela metoda att cu un obiect din clasa Minge ct i cu un obiect din clasa Rezervor.
Compilatorul nu se va plnge pentru c el tie c ambele clase implementeaz interfaa
ObiectSpaioTemporal, aa c metodele apelate n interiorul calculului distanei
(momentInitial i centruDeGreutate) sunt cu siguran implementate n ambele clase. Deci, putem
scrie:
Minge minge;
Rezervor rezervor;
double punct[] = { 10.0, 45.0, 23.0 };
distana( punct, minge );
distana( punct, rezervor );
Desigur, n mod normal ar fi trebuit s proiectm i un constructor sau mai muli care s iniializeze
obiectele noastre cu valori rezonabile. Aceti constructori ar fi stat cu siguran n definiia claselor
i nu n definiia interfeelor. Nu avem aici nici o cale de a fora definirea unui anumit constructor
cu ajutorul interfeei.
Modele de programare
Un nou limbaj de programare nu are anse s se impun fr s ofere, pe lng sintaxa propriu-zis
un set de biblioteci sau o ierarhie de clase coerent i ct mai general. Atunci cnd limbajul C a fost
prezentat pentru prima dat, mpreun cu el a fost prezentat i biblioteca standard de intrare ieire. Primul
program C pe care l-am nvat coninea deja apelul:
printf( "hello, world!" );
Limbajul Java nu face excepie de la aceast regul. Interfaa Java pentru programarea aplicaiilor
(API) ofer o ierarhie de clase care include funcionalitate pentru lucrul cu mai multe fire de execuie,
lucrul n reea, crearea interfeelor utilizator complexe, grafic, etc.
Exist mai multe moduri de a aborda scrierea unui program. Unul dintre acestea este scrierea unui
program care are iniiativa pe toat perioada rulrii. Acest tip de programe execut n permanen o
secven de cod, fie i numai o bucl de ateptare a crei condiie depinde de elemente exterioare precum ar
fi o apsare de tast sau sosirea unui pachet de date din reea.
Alternativa este aceea de a scrie programe care intr n execuie doar atunci cnd sunt generate
anumite evenimente n sistem. n clipa n care apar aceste evenimente, programul le analizeaz i execut o
secven de cod specific evenimentului respectiv. Dup execuia codului, programul se oprete din nou
pn la apariia unui nou eveniment.
Aceste dou alternative diferite de a aborda scrierea unui program i au rdcinile n moduri
diferite de lucru ale sistemelor de operare i n moduri diferite de a gndi interfaa cu utilizatorul.
Java implementeaz ambele stiluri de programe discutate mai sus. n primul caz, avem o clas de
pornire care conine o funcie public principal i care va fi lansat n execuie la apelarea programului. n
acest caz programul i controleaz complet execuia ulterioar. n termenii limbajului Java, aceasta este o
aplicaie.
n al doilea caz, codul ruleaz n interiorul unui navigator Internet. Clasa de pornire trebuie s aib
implementate metode de rspuns la anumite evenimente pe care le genereaz navigatorul, precum ar fi
iniializare, pornire, oprire, desenare, etc. Acest al doilea tip de programe Java le vom numi apleturi.
Distincia dintre cele dou moduri de organizare a codului este destul de vag, din cauz c cele
dou moduri de lucru se pot amesteca n realitate, un obiect aplet putnd fi n acelai timp lansat ca
aplicaie independent i invers. Totul depinde de metodele care au fost definite n interiorul clasei de
pornire a programului.
Aplicaii Java
Cea mai simpl aplicaie Java este declaraia unei clase de pornire coninnd o singur metod,
main, ca n exemplul urmtor:
Acest exemplu definete o funcie principal care afieaz un simplu mesaj pe consola aplicaiei.
Afiarea este lsat n sarcina clasei java.lang.System care conine n interior implementarea ieirii i intrrii
standard precum i a ieirii standard de eroare sub forma unor referine ctre obiecte de tip InputStream
pentru in (intrarea standard) respectiv PrintStream pentru out i err (ieirea standard i ieirea standard de
eroare).
Numele metodei main este obligatoriu, la fel i parametrul acesteia. Atunci cnd lansm
interpretorul Java mpreun cu numele unei clase care reprezint clasa de pornire, interpretorul
caut n interiorul acestei clase definiia unei metode numite main . Aceast metod trebuie s fie
obligatoriu public i static. n acelai timp, metoda main trebuie s nu ntoarc nici un rezultat i
s accepte un singur parametru de tip tablou de iruri de caractere.
Dac interpretorul gsete aceast metod n interiorul clasei apelate, el lanseaz n execuie
metoda main. Atenie, metoda main fiind de tip static, nu poate apela dect variabile statice. De
obicei ns, metoda main nu face nimic altceva dect s-i prelucreze parametrul dup care s creeze
o serie de obiecte care vor controla execuia ulterioar a aplicaiei.
Singurul parametru al metodei main este un tablou care conine argumentele aflate pe linia
de comand n momentul apelului. Nu este necesar transmiterea numrului de argumente care au
fost gsite pe linia de comand pentru c tablourile Java conin n interior informaii relative la
numrul de elemente. Acest numr de elemente se poate obine prin accesarea variabilei length din
interiorul tabloului ca n exemplul urmtor care listeaz parametrii de pe linia de comand la
lansarea unei clase:
public class Arguments {
public static void main( String args[ ] ) {
for( int i = 0; i < args.length; i++ ) {
System.out.println( args[i] );
}
}
}
Iat un exemplu de rulare a acestei aplicaii:
>java Arguments unu doi trei
unu
doi
trei
>
Apleturi Java
Apleturile Java ruleaz ntr-un document HTML. n acest document, fiecare aplet are
rezervat o fereastr dreptunghiular prin care comunic cu utilizatorul. Dreptunghiul de ncadrare
al ferestrei este definit ntr-un tag HTML numit APPLET. Aceast fereastr este n exclusivitate la
dispoziia apletului care este responsabil de desenarea ei i de tratarea eventualelor evenimente care
se refer la ea.
mpreun cu definirea interfeei dintre apleturi i navigator, Sun a definit i o sintax
specific noului tag HTML care permite poziionarea i dimensionarea ferestrei apletului n
document precum i specificarea unor parametri care s poat altera modul de lucru al apletului.
Iat un prim exemplu de aplet:
import java.awt.Graphics;
public class HelloWorldApplet extends java.applet.Applet {
public void init() {
resize( 150,25 );
}
public void paint( Graphics g ) {
g.drawString( "Hello world!", 50, 25 );
}
}
n mod minimal, apletul nu definete dect dou metode i anume una de iniializare,
necesar pentru organizarea mediului n care ruleaz apletul i una de desenare a spaiului destinat
apletului n interiorul documentului HTML. Metoda de iniializare nu face n acest caz dect s
redimensioneze spaiul alocat n mod corespunztor necesitilor sale n timp ce metoda de desenare
afieaz n acest spaiu un mesaj de salut.
Pentru a vedea rezultatele rulrii acestui aplet trebuie s construim un document minimal HTML,
care poate s arate n felul urmtor:
<HTML>
<HEAD>
<TITLE> Hello World Applet </TITLE>
</HEAD>
<BODY>
<APPLET CODE="HelloWorldApplet.class" WIDTH=150 HEIGHT=25>
....
</APPLET>
</BODY>
</HTML>
Spre deosebire de o aplicaie normal Java, apleturile nu pot primi parametri pe linia de
comand pentru c nu exist linie de comand. Din acest motiv, trebuie s introducem parametrii
apletului n fiierul HTML. De exemplu am putea introduce, imediat dup linia de declaraie a
apletului o linie de forma:
<PARAM NAME=mesaj VALUE="Salutare, lume!">
n acest mod putem s controlm la lansare iniializarea apletului. n definiia clasei Applet
exist i dou funcii care permit navigatorului regsirea unui minim de informaii despre aplet.
Aceste informaii reprezint descrierea apletului i a parametrilor acestuia. Funciile care trebuiesc
definite n noua clas derivat din Applet sunt getAppletInfo i getParameterInfo. De exemplu, putem
introduce n clasa HelloWorldApplet dou noi funcii:
public String getAppletInfo() {
return "Applet scris de XXX ";
}
public String [ ][ ] getParameterInfo( ) {
String info[ ][ ] = {
{ "Parametru", "String", "Textul de afisat" }
};
return info;
}
Execuia unui aplet este marcat de cteva evenimente importante generate de ctre
navigator. Atunci cnd navigatorul ntlnete o etichet APPLET, pornete n primul rnd
ncrcarea codului necesar rulrii apletului. Pn cnd acest cod nu a ajuns pe calculatorul client,
apletul nu poate fi pornit.
Dup ncrcarea codului, apletul este apelat pentru iniializare. Acesta este momentul n care
apletul i pregtete parametrii i obine de la sistem resursele necesare rulrii. Dup ce
iniializarea a fost terminat, navigatorul trimite ctre aplet o comand de pornire. Aceasta este
comanda care pune efectiv apletul n funciune deschiznd interaciunea cu utilizatorul.
Un aplet ruleaz atta timp ct navigatorul este activ. La schimbarea paginii curente,
apleturile din vechea pagin nu sunt distruse, dar primesc o comand de oprire temporar (pe care
de altfel pot s o ignore). La rencrcarea paginii, o alt comand de pornire este lansat spre aplet
i acest ciclu se poate relua. n sfrit, la oprirea navigatorului, apletul primete o comand de oprire
definitiv, caz n care el trebuie s elibereze toate resursele pe care le blocheaz.
Orice aplet Java reprezint, din punctul de vedere al limbajului un nou tip de obiect, derivat
din obiectul standard Applet. Atunci cnd navigatorul lanseaz un nou aplet el nu face altceva dect
s instanieze un nou obiect din aceast clas. Subrutinele care trateaz evenimentele descrise
anterior trebuiesc definite ca metode n interiorul acestui nou tip de obiecte.
n continuare, ntre dou evenimente de pornire i respectiv de oprire temporar a apletului
navigatorul transmite ctre aplet evenimente specifice oricrei interfee grafice cum ar fi
evenimentul care provoac redesenarea spaiului destinat apletului, evenimente legate de apsarea
unor taste sau a unor butoane ale mausului, etc. Ca rspuns la aceste evenimente, apletul trebuie s
reacioneze schimbnd coninutul ferestrei, lansnd mesaje sonore, etc. Iat i un exemplu de aplet
care ne arat fazele prin care trece un aplet n timpul existenei sale:
import java.applet.Applet;
import java.awt.*;
public class Evenimente extends Applet {
public void init() {
// metoda de iniializare
// este apelat la construcia noii instane de aplet
System.out.println("init");
}
public void paint(Graphics g) {
// metoda de desenare
// este apelat ori de cte ori este necesar
// redesenarea ferestrei apletului
System.out.println("paint");
}
public void start() {
// metoda de lansare in execuie
// este apelat la pornire
//sau la rentoarcerea n pagina apletului
System.out.println("start");
}
public void stop() {
// metoda de oprire temporar a execuiei
System.out.println( "stop" );
}
public void destroy() {
// metoda de oprire definitiv
System.out.println("destroy");
}
public void update(Graphics g) {
// metoda de actualizare a ferestrei apletului
// este apelata atunci cnd nu este necesar redesenarea
// ntregii ferestre. n mod implicit,
// metoda apeleaz metoda paint.
System.out.println("update");
}
public boolean mouseUp(Event e, int x, int y) {
Putei rula apletul de mai sus pentru a vedea care este ordinea n care sunt apelate aceste
metode de ctre navigator. Apletul de mai sus produce ieiri la consol (o fereastr text) i nu n
fereastra apletului. Dac nu vedei consola, ncercai s cutai prin meniurile navigatorului opiunea
de afiare a consolei Java.
Din cele spuse pn acum se poate deduce c apleturile Java nu au o via proprie, ele fiind
doar apelate din cnd n cnd de navigator. Ceea ce nu este ntocmai adevrat pentru c biblioteca
standard de clase Java ofer suport pentru aplicaii care folosesc mai multe fire de execuie.
Apleturile pot astfel crea fire de execuie care s lucreze independent fa de navigator.
CODEBASE = codebaseURL
Acest atribut opional specific URL-ul de baz al appletului directorul (folderul) care
conine codul apletului. Dac acest atribut nu este utilizat atunci se consider directorul
curent al documentului html.
CODE = appletFile
Acest atribut este obligatoriu i specific numele fiierului care conine forma compilat a
appletului (clasa). Acest atribut este relative la URL ul de baz.
Dac codul clasei este n acelai director cu documentul HTML este suficient s fie
specificat atributul CODE cu numele fiierului unde este acesta memorat. Dac este nevoie de un
director diferit, trebuie completat i atributul CODEBASE n care se menioneaz directorul. De
exemplu, dac fiierele .class sunt ntr-un subdirector numit /clase al directorului care conine
documentul HTML, atunci exemplul de mai sus devine:
<APPLET CODE="HelloWorldApplet.class" CODEBASE="clase"
WIDTH=200 HEIGHT=150>
Text care apare dac navigatorul nu tie Java
</APPLET>
ALT = alternateText
Acest atribut opional specific un text care trebuie s fie afiat dac browserul nelege
atributul APPLET dar nu tie s execute appleturi Java.
NAME = appletInstanceName
Este un atribut opional care specific un nume pentru instana apletului, care face posibil
comunicarea ntre apleturile din aceeai pagin.
WIDTH = pixels
HEIGHT = pixels
Aceste dou attribute opionale specific dimensiunile (n pixeli) ale ferestrei (zonei de
afiare) ale appletului.
ALIGN = alignment
Atributul ALIGN specific modul n care fereastra destinat apletului va fi aliniat n pagin.
Valorile sale posibile sunt: LEFT, RIGHT, TOP, TEXTTOP, MIDDLE, ABSMIDDLE,
BASELINE, BOTTOM i ABSBOTTOM. Valoarea implicit este BASELINE.
VSPACE = pixels
HSPACE = pixels
Atributele VSPACE i HSPACE specific, n pixeli, spaiul care desparte apletul de textul care l
nconjoar. Sunt atribute opionale.
< PARAM NAME = appletParameter1 VALUE = value >
Eticheta <PARAM> este singura modalitate prin care unui applet i se pot transmite
parametrii. Appletul preia aceti parametrii cu ajutorul metodei getParameter(), aa cum
s-a artat mai sus.
alternateHTML
Dac pagina html care conine eticheta APPLET este vizualizat cu ajutorul unui browser
care nu nelege aceast etichet, atunci browserul va ignora cele dou etichete APPLET i
TAG . Browserele compatibile Java vor ignora acest cod.
Atributele obligatorii ale acestei definiii sunt numele fiierului n care este memorat codul
i dimensiunea spaiului rezervat apletului. Minimal, tag APPLET arat n felul urmtor:
<APPLET CODE="HelloWorldApplet.class" WIDTH=200 HEIGHT=150>
Text care apare dac navigatorul nu tie Java
</APPLET>
Atributele opionale ale tagului descriu locaia de baz a codului apletului, modul de aliniere
n pagin, spaierea i eventualii parametrii care pot fi transmii apletului din interiorul
documentului HTML.
Structura programelor
Pachete de clase
Clasele Java sunt organizate pe pachete. Aceste pachete pot avea nume ierarhice. Numele de
pachete au forma urmtoare:
[NumePachet.] NumeComponentPachet
Numele de pachete i de componente ale acestora sunt identificatori Java. De obicei, aceste
nume urmeaz structura de directoare n care sunt memorate clasele compilate. Rdcina arborelui
de directoare n care sunt memorate clasele este indicat de o variabil sistem CLASSPATH. n
DOS aceasta se seteaz n felul urmtor:
set CLASSPATH=.;c:\java\lib
Din aceast rdcin, fiecare pachet are propriul director. n director exist codul binar pentru
componentele pachetului respectiv. Dac pachetul conine subpachete, atunci acestea sunt
memorate ntr-un subdirector n interiorul directorului pachetului.
Creatorii Java recomand folosirea unei reguli unice de numire a pachetelor, astfel nct s nu apar
conflicte. Convenia recomandat de ei este aceea de a folosi numele domeniului Internet aparinnd
productorului claselor. Astfel, numele de pachete ar putea arta ca n:
COM.Microsoft.OLE
COM.Apple.quicktime.v2
i aa mai departe.
Importul claselor
Este nevoie ca o clas s poat folosi obiecte aparinnd unei alte clase. Pentru aceasta,
definiia clasei respective trebuie s importe codul binar al celeilalte clase pentru a ti care sunt
variabilele i metodele clasei respective.
Importul se face cu o instruciune special:
import
numeClas ;
unde numele clasei include i pachetul din care aceasta face parte. De exemplu:
import java.awt.Graphics;
import java.applet.Applet;
Se poate importa i un pachet ntreg, adic toate clasele aparinnd acelui pachet, printr-o
instruciune de forma:
import
numePachet.*;
De exemplu:
import java.awt.*;
Fiiere surs
Codul surs Java trebuie introdus cu un editor ntr-un fiier text pe care l vom numi n
continuare fiier surs. Un fiier surs poate s conin declaraia mai multor clase i interfee, dar
doar una dintre acestea poate fi declarat public. Utilizarea celorlalte clase este limitat la fiierul
respectiv. Mai mult, nu putem avea n acelai timp o interfa public i o clas public declarate n
acelai fiier surs.
Dac dorim s nregistrm codul clasei ntr-un anumit pachet, putem s includem la nceputul
fiierului surs o declaraie de forma:
package
numePachet;
dac aceast declaraie lipsete, clasa va fi plasat n pachetul implicit, care nu are nume.
Structura general a unui fiier surs este urmtoarea:
[ DeclaraiePachet ][ InstruciuneImport ][ DeclaraieDeTip ]
unde declaraia de tip poate fi o declaraie de clas sau de interfa.
Compilare i execuie
Fiierele surs Java au obligatoriu extensia .java. Numele lor este identic cu numele clasei
sau interfeei publice declarate n interior. n urma compilrii rezult fiiere cu nume identice cu
numele claselor dar cu extensia .class indiferent dac este vorba de o clas sau o interfa. Fiierul
.class este generat n directorul local i nu direct la locaia pachetului.
Compilarea se face cu o comand de forma:
javac FiierSurs.java
unde numele clasei este numele aplicaiei care conine metoda main . Interpretorul va cuta un fiier
cu numele NumeClas.class i va ncerca s instanieze clasa respectiv.
Pentru lansarea unui aplet vei avea nevoie de un document HTML care conine tagul APPLET i
ca parametru al acesteia
name=NumeClas.class
La lansarea unui aplet, clasele care sunt apelate de clasa principal sunt mai nti cutate pe
sistemul pe care ruleaz navigatorul. Dac nu sunt acolo, ele vor fi transferate n reea. Asta
nseamn c transferul de cod este relativ mic, trebuie transferat doar codul specific aplicaiei.
Eticheta <OBJECT>
Eticheta <APPLET> este o extensie HTML introdus special pentru a insera programe Java n
paginile Web. In prezent exist i alte tipuri de programe care ruleaz interactiv ntr-o pagin, cum
ar fi controale ActiveX. Pentru a trata toate aceste tipuri de programe fr a fi nevoie de cte o
etichet explicit pentru fiecare, specificaia HTML a introdus i eticheta <OBJECT>.
Eticheta <OBJECT> este folosit pentru toate obiectele - programe interactive sau alte elemente
externe - care pot fi prezentate drept parte a paginii Web. Aceast etichet este suportat ncepnd
de la versiunile 4.0 ale Netscape Navigator sau Microsoft Internet Explorer. Browserele mai vechi
nu suport aceast nou etichet, aa nct n multe cazuri va trebui s folosii tot eticheta <APPLET>.
Eticheta <OBJECT> are urmtoarea form:
<OBJECT CLASSID="java:Bix.class" CODEBASE="javaclasses* HEIGHT=40 WIDTH=400>
</OBJECT>
Trecerea de la eticheta <APPLET> la <OBJECT> presupune urmtoarele modificri:
Eticheta <OBJECT> trebuie folosit n loc de <APPLET>
Atributul CODE trebuie nlocuit de CLASSID. n plus, nainte de numele clasei applet-ului
trebuie specificat "java:". De exemplu, dac applet-ul are clasa AppletJoc.class, atunci
atributul CLASSID trebuie s fie java: AppletJoc.class.
n rest, atributele (CODEBASE, HEIGHT, WIDTH, ALIGN) rmn aceleai. <OBJECT> poate folosi
i etichetele opionale <PARAM>.
Arhive Java
Modalitatea standard de amplasare a unui applet Java ntr-o pagin Web este de a folosi
etichetele <APPLET> sau <OBJECT> pentru a indica numele clasei primare a applet-ului. Se folosete
apoi un browser compatibil Java, care transfer i execut applet-ul. Orice alte clase sau fiiere
folosite de applet sunt transferate de pe serverul Web.
Problema cu rularea n acest fel a applet-urilor este c fiecare fiier de care are nevoie applet-ul - fie
acesta o alt clas extern, un fiier imagine, audio, text sau orice altceva -necesit o conexiune
separat de la browserul Web la serverul care conine fiierul. Deoarece intervalul de timp necesar
pentru a stabili conexiunea nu este neglijabil, acest lucru poate mri timpul total pentru transferul
applet-ului i al celorlalte fiiere necesare pentru rulare.
Soluia acestei probleme este crearea unui arhive Java, adic un fiier JAR. 0 arhiv Java reprezint
o colecie de clase Java i alte fiiere, mpachetat ntr-un singur fiier. Folosind o arhiv Java,
browserului i este suficient o singur conexiune la serverul Web. Reducnd numrul de fiiere
transferate de pe server, applet-ul poate fi ncrcat i rulat mai rapid. Arhivele Java pot fi i
comprimate, sczndu-le astfel dimensiunea i micorndu-se timpul de transfer - chiar dac va mai
dura puin din partea browserului s le decomprime nainte de a le rula.
Versiunile de Netscape Navigator i Microsoft Internet Explorer ncepnd cu 4.0 conin suport
pentru fiiere JAR. Pentru a crea aceste arhive, JDK conine un utilitar denumit jar, care poate
mpacheta sau despacheta fiierele n/din arhive Java. Fiierele JAR pot fi comprimate n format Zip
sau mpachetate fr a folosi comprimarea. Urmtoarea comand mpacheteaz toate clasele i
imaginile GIF dintr-un director ntr-o singur arhiv Java, denumit Animat.jar:
jar cf Animat.jar *.class *.gif
Argumentul cf specific dou opiuni n linie de comanda, care sunt folosite de programul jar.
Opiunea c indic faptul c arhiva Java trebuie creat, iar f arat c unul dintre urmtoarele
argumente din linia de comand reprezint numele fiierului arhiv.
Putei, de asemenea, aduga ntr-o arhiv Java alte fiiere, folosind o comand de genul:
jar cf Smiley.jar ShowSmiley.class ShowSmiley.html spinhead.gif
Aceasta creeaz o arhiv Java cu numele Smiley.jar, care conine trei fiiere:
ShowSmiley.class, ShowSmiley.html i spinhead.gif.
Rulnd utilitarul jar fr argumente, vei obine lista de opiuni care pot fi folosite.
Dup ce ai creat arhiva Java, n eticheta <APPLET> se folosete atributul ARCHIVE pentru a indica locul
unde se gsete arhiva. Putei folosi arhiva Java n felul urmtor:
<APPLET CODE="ShowSmiley.class" ARCHIVE="Smiley.jar" WIDTH=45 HEIGHT =42>
</APPLET>
Aceast etichet specific faptul c arhiva numit Smiley.jar conine fiierele folosite de applet.
Browserele i utilitarele de navigare care suport fiiere JAR tiu s caute n interiorul arhivelor
fiierele necesare pe timpul rulrii applet-ului.
Atenie
Cu toate c o arhiv Java poate conine fiiere clas, atributul ARCHIVE nu presupune eliminarea
atributului CODE. Pentru a o ncrca, browserul trebuie totui s tie numele clasei principale a
applet-ului.
if (numeleFontului == null)
numeleFontului = "Courier";
inei minte ca metoda getParameter () returneaz iruri; dac dorii ca parametrul sa fie alt tip de
obiect sau de data, trebuie sa l convertii singur. De exemplu, sa luam fiierul HTML pentru appletul Exemplu. Pentru a trata parametrul dim si a-l atribui unei variabile ntregi, numit dimensiunea,
ai putea folosi urmtorul cod:
int dimensiunea;
String s = getParameter("dim");
if (s == null)
dimensiunea = 12;
else dimensiunea = Integer.parseInt(s);
S cream un exemplu de applet care folosete aceast tehnic. Vom crea un applet Palindrom
pentru a afia alte texte, cum ar fi ,,Dennis and Edna sinned" sau ,,No, sir, prefer prison". Numele
este transmis applet-ului printr-un parametru HTML. Proiectul va primi numele Palindrom.
import java.awt.Graphics;
import java.awt.Font;
import java.awt.Color;
public class Palindrom extends java.applet.Applet {
Font f = new Font ("TimesRoman", Font.BOLD, 36);
String palindrom;
public void paint(Graphics ecran) {
ecran.setFont(f);
ecran.setColor(Color.red);
ecran.drawString(palindrom, 5, 40);
}
public void init() {
palindrom = getParameter("palindrom");
if (palindrom == null)
palindrom = "Dennis and Edna sinned";
}
}
Remarcai eticheta <APPLET>, care desemneaz fiierul clas pentru applet i valorile pentru
lime i nlime (600, respectiv 100 de pixeli). Imediat sub aceast linie (n linia 8) se afl eticheta
<PARAM>, care este folosit pentru a transmite parametrul applet-ului. n acest exemplu, numele
parametrului este palindrom, iar valoarea sa este irul No, sir, prefer prison".
Dac nu este specificat nici o valoare pentru parametrul palindrom, textul implicit este Dennis
and Edna sinned".
Urmtorul fiier HTML nu conine nici o etichet de parametru
<HTML>
<HEAD>
<TITLE>Noua pagina cu palindrom</TITLE>
</HEAD>
<BODY>
<P>
<APPLET CODE="PalindromNou.class" WIDTH=600 HIGHT=100>
Browserul dumneavoastr nu suporta Java!
</APPLET>
</BODY>
</HTML>
Deoarece aici nu a fost specificat nici un parametru, applet-ul va folosi valoarea implicit.
Clasa Graphics
Putei s v imaginai applet-ul drept o pnz pe care se vor desfura operaii grafice. Ai
folosit deja metoda drawString () pentru a desena text ntr-un applet. Fontul i culoarea textului
au fost alese anterior desenrii textului, n acelai fel n care un artist i alege culoarea i pensula
nainte de a picta.
Textul nu este singurul lucru pe care l putei desena n fereastra unui applet. Putei desena
i linii, ovale, cercuri, arcuri, dreptunghiuri i alte poligoane.
Majoritatea principalelor operaii de desenare sunt metode definite n clasa Graphics.
ntr-un applet nu este nevoie s creai un obiect Graphics pentru a putea desena ceva aa
cum poate v mai amintii, unul dintre argumentele metodei paint () este un obiect Graphics.
Acest obiect reprezint fereastra applet-ului, iar metodele sale sunt folosite pentru a desena n
applet.
Clasa Graphics este parte a pachetului java.awt, deci toate applet-urile care deseneaz ceva
trebuie s foloseasc instruciunea import pentru a putea folosi aceast clas.
Desenarea i umplerea
Pentru majoritatea formelor pe care le desenai ntr-un applet sunt disponibile dou tipuri de metode: metode
de desenare, care deseneaz conturul formei, i metode de umplere, care umplu forma cu culoarea curent. n fiecare
tip de metod, conturul obiectului este, de asemenea, desenat cu culoarea curent.
Linii
Metoda drawLine este folosit pentru a desena o linie ntre dou puncte. Metoda primete patru
argumente: coordonatele x,y ale punctului de nceput i coordonatele x, y ale punctului final.
drawLine(x1, y1, x2, y2) ;
Aceast metod deseneaz o linie ncepnd cu punctul de coordonate (x1, y1) i pn la punctul de
coordonate (x2, y2). Grosimea liniei este de un pixel.
Dreptunghiuri
Clasa Graphics conine metode pentru dou tipuri de dreptunghiuri: dreptunghiuri normale i
dreptunghiuri cu coluri .
Ambele tipuri de dreptunghiuri pot fi desenate sub form de contur sau umplute cu culoarea curent.
Pentru a desena un dreptunghi normal se folosete metoda drawRect() pentru contururi sau
metoda fillRect() pentru forme umplute. Ambele metode preiau patru argumente:
Coordonatele x i y ale colului din stnga - sus al dreptunghiului
Limea dreptunghiului
nlimea dreptunghiului
drawRect(x,y,l,h)
Poligoane
Poligoanele pot fi desenate folosind metodele drawPolygon() i fillPolygon().
Pentru a desena un poligon avei nevoie de coordonatele x,y ale fiecrui punct care definete colurile
poligonului. Poligoanele pot fi definite drept o serie de linii conectate una cu cealalt - se deseneaz o linie de la un
punct iniial la un punct final, apoi punctul final este folosit ca punct iniial pentru o alt linie i aa mai departe.
valori pentru coordonata x, tabloul cu valori pentru coordonata y i numrul de puncte (coluri). Iat
un exemplu de folosire a acestui constructor:
int x[] = { 10, 20, 30, 40, 50 };
int y[] = { 15, 25, 35, 45, 55 };
int puncte = x.length;
Polygon polig = new Polygon(x, y, puncte);
Dup ce se creeaz obiectul Polygon, se pot aduga puncte folosind metoda addpoint().
Aceasta preia ca argumente coordonatele x, y i adaug punctul n poligon. lat un exemplu:
polig.addPoint(60, 65);
Atunci cnd obiectul Polygon are toate punctele necesare, el poate fi desenat folosind una
dintre metodele drawPolygon() sau fillPolygon() . Aceste metode au drept unic argument obiectul
Polygon, ca n exemplul urmtor:
ecran.drawPolygon(polig) ;
Dac folosii metoda drawPolygon() n Java 1.02, putei nchide poligonul stabilind pentru
ultimele coordonate x,y valori identice cu primele. Altfel, poligonul va rmne deschis pe una
dintre laturi.
Metoda fillPolygon() nchide automat forma poligonal, fr a mai fi nevoie de stabilirea
coordonatelor finale.
Ovale
Metodele drawOval() i fillOval() sunt folosite pentru a desena cercuri i ovale (elipse).
Metodele preiau patru argumente:
coordonatele x, y ale ovalului
limea i nlimea ovalului, care n cazul cercurilor iau valori egale
Ovalele sunt tratate n acelai mod ca i colurile dreptunghiurilor rotunjite. Coordonata x,y va reprezenta
colul din stnga - sus al zonei n care va fi desenat ovalul, aflndu-se de fapt la stnga i mai sus dect forma oval
propriu-zis.
Arce
Un arc este o parte a unui oval, fiind implementat n Java ca o form eliptic parial desenat.
Arcele sunt desenate folosind metodele drawArc() i fillArc(), care preiau ase argumente:
coordonatele x, y ale ovalului din care face parte arcul;
limea i nlimea ovalului;
unghiul de unde se ncepe trasarea arcului;
numrul de grade al arcului. Primele patru argumente sunt aceleai ca n cazul ovalului i se
comport identic.
Unghiul de nceput al arcului ia valori ntre 0 i 359 de grade i crete n sens trigonometric (invers
acelor de ceasornic).
Copierea i tergerea
Clasa Graphics conine i cteva funcii de gen decupeaz-i-lipete (cut-and-paste),
Text i fonturi
Obiectele clasei java.awt.Font sunt folosite pentru a putea utiliza metoda drawString() cu diferite fonturi.
Obiectele Font conin numele, stilul i dimensiunea n puncte a unui font. O alt clas, FontMetrics, ofer metode
pentru determinarea dimensiunilor i a caracterelor afiabile cu un anumit font, care pot fi folosite pentru lucruri cum ar
fi formatarea i centrarea textului.
Pot fi selectate trei stiluri de fonturi, folosind constantele Font. PLAIN, Font. BOLD i Font.
ITALIC. Aceste constante sunt ntregi i pot fi nsumate pentru a obine o combinaie de efecte.
Ultimul argument al constructorului Font () este dimensiunea fontului. Urmtoarea
instruciune creeaz un font Dialog de 24 de puncte, cu aldine cursive.
Font f = new Font("Dialog", Font.BOLD + Font.ITALIC, 24);
Desenarea caracterelor i a irurilor
Pentru a seta fontul curent se folosete metoda setFont() a clasei Graphics, mpreun cu un
obiect Font. Urmtoarea instruciune folosete un obiect Font denumit ft:
ecran.setFont(ft);
Textul poate fi afiat ntr-o fereastr Applet folosind metoda drawString(). Aceast metod folosete fontul
curent selectat; dac nu a fost selectat nici un font, este folosit unul implicit. Poate fi selectat oricnd un nou font cu
ajutorul metodei setFont ().
Urmtoarea metod paint () creeaz un nou obiect Font, stabilete fontul curent la acest
obiect, dup care afieaz irul Acesta este un font. la coordonatele 10,100.
public void paint(Graphics ecran) {
Font f = new Font("TimesRoman", Font.PLAIN, 72);
ecran.setFont(f);
ecran.drawString(Acesta este un font.", 10, 100);
}
Ultimele dou argumente ale metodei drawString () sunt coordonatele x, y. Valoarea x reprezint locul de
nceput al marginii din stnga a textului, iar y este valoarea la care se afieaz linia de baz a irului de text.
Aciune
stringWidth (String)
charWidth (char)
getHeight ()
Culori
Clasele Color i ColorSpace din pachetul java.awt pot fi folosite pentru a aduce puin
culoare n applet-urile i aplicaiile dumneavoastr. Cu ajutorul acestor clase putei stabili culorile
curente folosite n operaiile de desenare, ca i culoarea de fundal pentru un applet sau alte ferestre.
De asemenea, putei translata o culoare dintr-un sistem de descriere n altul.
n mod prestabilit, Java folosete culorile conform unui sistem de descriere denumit sRGB. n acest sistem, o
culoare este descris prin cantitatea de rou, verde i albastru pe care o conine - de aici i iniialele R(ed), G(reen) i
B(lue). Fiecare dintre aceste trei componente poate fi reprezentat ca un ntreg din gama 0-255. Negrul este 0, 0, 0 lipsa complet a tuturor componentelor rou, verde, albastru. Albul este 255, 255, 255 - valoarea maxim a tuturor
componentelor. Mai putei reprezenta valori sRGB folosind trei numere n virgul mobil, n domeniul dintre 0 i 1,0.
Folosind sRGB, Java poate reprezenta milioane de culori aflate ntre cele dou extreme.
Un sistem de descriere a culorilor mai este numit i palet sau spaiu de culori (color space),
iar sRGB este doar unul dintre acestea. Exist i CMYK, un sistem folosit de imprimante i care
descrie culorile prin procentul de Cyan (azuriu), Magenta (purpuriu), Yellow (galben) i Black
(negru) pe care l conin. Java 2 suport folosirea oricrui spaiu de culori dorii, att timp ct
folosii un obiect ColorSystem care definete respectivul sistem de descriere a culorilor. De
asemenea, putei converti culorile din sRGB n alt spaiu de culori i invers.
Reprezentarea intern a culorilor n Java folosind sRGB reprezint numai spaiul de culoare folosit n program.
Dispozitivele de ieire, cum ar fi monitoarele sau imprimantele, pot avea i ele propriile spaii de culoare.
Atunci cnd afiai sau tiprii ceva cu o anumit culoare, dispozitivul de ieire s-ar putea s nu
suporte culoarea respectiv. n acest caz, culoarea va fi nlocuit cu o alta sau cu o culoare impur
(dithered), folosit pentru a aproxima culoarea care nu este disponibil. Acest lucru se ntmpl
frecvent pe World Wide Web, cnd o culoare indisponibil este nlocuit cu una impur, care
aproximeaz culoarea lips.
Practic, culorile definite conform modelului sRGB nu vor putea fi reprezentate pe orice
dispozitiv de ieire. Dac avei nevoie de un control mai precis al culorii, putei folosi ColorSpace
sau alte clase din pachetul java.awt. color, introdus o dat cu Java 2.
Pentru majoritatea programelor, folosirea sRGB, sistemul intern de reprezentare a culorilor, va fi suficient.
darkGray(gri nchis)(64,64,64)
gray (gri) (128,128,128)
green (verde) (0,255,0)
lightGray(gri deschis)(192,192,192)
Urmtoarea instruciune stabilete culoarea curent pentru obiectul ecran folosind una dintre
variabilele de clas standard:
ecran.setColor(Color.pink) ;
Dac ai creat un obiect Color, el poate fi setat ntr-un mod asemntor:
O aplicaie Java se termin atunci cnd se termin toate firele de execuie din interiorul ei
sau cnd nu mai exist dect fire demon. Terminarea firului principal de execuie nu duce la
terminarea automat a aplicaiei.
Metoda start, predefinit n obiectul Thread lanseaz execuia propriu-zis a firului. Desigur
exist i ci de a opri execuia la nesfrit a firului creat fie prin apelul metodei stop , prezentat mai
jos, fie prin rescrierea funciei run n aa fel nct execuia sa s se termine dup un interval finit de
timp.
A doua cale de definiie a unui fir de execuie este implementarea interfeei Runnable ntr-o
anumit clas de obiecte. Aceast cale este cea care trebuie aleas atunci cnd clasa pe care o crem
nu se poate deriva din clasa Thread pentru c este important s fie derivat din alt clas. Desigur,
motenirea multipl ar rezolva aceast problem, dar Java nu are motenire multipl.
}
class FirNou extends Oclasa implements Runnable {
public void run() {
for( int i = 0; i < 100; i++ ) {
System.out.println( "pasul " + i );
}
}
}
public class TestFirNou {
public static void main( String argumente[ ] ) {
new Thread( new FirNou() ).start();
// Obiectele sunt create i folosite imediat
// La terminarea instruciunii, ele sunt automat
// eliberate nefiind referite de nimic
}
}
Dup se observ, clasa Thread are i un constructor care primete ca argument o instan a
unei clase care implementeaz interfaa Runnable. n acest caz, la lansarea n execuie a noului fir, cu
metoda start , se apeleaz metoda run din acest obiect i nu din instana a clasei Thread .
Atunci cnd dorim s crem un aplet care s ruleze pe un fir de execuie separat fa de
pagina de navigator n care ruleaz pentru a putea executa operaii n fereastra apletului i n acelai
timp s putem folosi n continuare navigatorul, suntem obligai s alegem cea de-a doua cale de
implementare. Aceasta pentru c apletul nostru trebuie s fie derivat din clasa standard Applet .
Singura alternativ care ne rmne este aceea de a implementa n aplet interfaa Runnable .
try {
sleep( 1000 ); // o secund
} catch( InterruptedException ) {
Dac dorim oprirea firului de execuie pe timp nedefinit, putem apela metoda suspend.
Aceasta trece firul de execuie ntr-o nou stare, numit Nu Ruleaz. Aceeai stare este folosit i
pentru oprirea temporar cu sleep. n cazul apelului suspend ns, execuia nu va putea fi reluat
dect printr-un apel al metodei resume. Dup acest apel, firul va intra din nou n starea Ruleaz .
Pe timpul n care firul de execuie se gsete n starea Nu Ruleaz , acesta nu este planificat
niciodat la controlul unitii centrale, aceasta fiind cedat celorlalte fire de execuie din aplicaie.
Firul de execuie poate intra n starea Nu Ruleaz i din alte motive. De exemplu se poate
ntmpla ca firul s atepte pentru terminarea unei operaii de intrare/ieire de lung durat caz n
care firul va intra din nou n starea Ruleaz doar dup terminarea operaiei.
O alt cale de a ajunge n starea Nu Ruleaz este aceea de a apela o metod sau o secven de
instruciuni sincronizat dup un obiect. n acest caz, dac obiectul este deja blocat, firul de execuie
va fi oprit pn n clipa n care obiectul cu pricina apeleaz metoda notify sau notifyAll .
Atunci cnd metoda run i-a terminat execuia, obiectul intr n starea Mort. Aceast stare
este pstrat pn n clipa n care obiectul este eliminat din memorie de mecanismul de colectare a
gunoaielor. O alt posibilitate de a intra n starea Mort este aceea de a apela metoda stop .
Desigur, firul de execuie poate fi terminat i pe alte ci, caz n care metoda stop nu este
apelat. n aceste situaii este preferabil s ne folosim de o clauz finally ca n exemplul urmtor:
try {
firDeExecutie.start( );
} finally {
..// curenie
}
n fine, dac nu se mai poate face nimic pentru c firul de execuie nu mai rspunde la
comenzi, putei apela la calea disperat a metodei destroy. Din pcate, metoda destroy termin firul
de execuie fr a proceda la curirile necesare n memorie.
Atunci cnd un fir de execuie este oprit cu comanda stop, mai este nevoie de un timp pn
cnd sistemul efectueaz toate operaiile necesare opririi. Din aceast cauz, este preferabil s
ateptm n mod explicit terminarea firului prin apelul metodei join:
firDeExecutie.stop( )
try {
firDeExecutie.join( );
} catch( InterruptedException e ) {
Excepia de ntrerupere trebuie interceptat obligatoriu. Dac nu apelm metoda join pentru
a atepta terminarea i metoda stop este de exemplu apelat pe ultima linie a funciei main , exist
ansa ca sistemul s cread c firul auxiliar de execuie este nc n via i aplicaia Java s nu se
mai termine rmnnd ntr-o stare de ateptare. O putei desigur termina tastnd ^C.
Prioritatea unui fir de execuie se poate interoga cu metoda getPriority care ntoarce un
numr ntreg care reprezint prioritatea curent a firului de execuie. Pentru a seta prioritatea, se
folosete metoda setPriority care primete ca parametru un numr ntreg care reprezint prioritatea
dorit.
Schimbarea prioritii unui fir de execuie este o treab periculoas dac metoda cu
prioritate mare nu se termin foarte repede sau dac nu are opriri dese. n caz contrar, celelalte
metode nu vor mai putea primi controlul unitii centrale.
Exist ns situaii n care putem schimba aceast prioritate fr pericol, de exemplu cnd
avem un fir de execuie care nu face altceva dect s citeasc caractere de la utilizator i s le
memoreze ntr-o zon temporar. n acest caz, firul de execuie este n cea mai mare parte a
timpului n starea Nu Ruleaz din cauz c ateapt terminarea unei operaii de intrare/ieire. n clipa
n care utilizatorul tasteaz un caracter, firul va iei din starea de ateptare i va fi primul planificat
la execuie din cauza prioritii sale ridicate. n acest fel utilizatorul are senzaia c aplicaia
rspunde foarte repede la comenzile sale.
n alte situaii, avem de executat o sarcin cu prioritate mic. n aceste cazuri, putem seta
pentru firul de execuie care execut aceste sarcini o prioritate redus.
Alternativ, putem defini firul respectiv de execuie ca un demon. Dezavantajul n aceast
situaie este faptul c aplicaia va fi terminat atunci cnd exist doar demoni n lucru i exist
posibilitatea pierderii de date. Pentru a declara un fir de execuie ca demon, putem apela metoda
setDaemon. Aceast metod primete ca parametru o valoare boolean care dac este true firul este
fcut demon i dac nu este adus napoi la starea normal. Putem testa faptul c un fir de execuie
este demon sau nu cu metoda isDemon.
Acest nou fir de execuie va face parte dintr-un alt grup de fire dect firul principal. Putem
afla grupul de fire de execuie din care face parte un anumit fir apelnd metoda getThreadGroup , ca
n secvena:
Thread t = new Thread( "Firul de Executie" );
ThreadGroup tg = t.getThreadGroup();
Operaiile definite pentru un grup de fire de execuie sunt clasificabile n operaii care
acioneaz la nivelul grupului, cum ar fi aflarea numelui, setarea unei prioriti maxime, etc., i
operaii care acioneaz asupra fiecrui fir de execuie din grup, cum ar fi stop, suspend sau resume.
Metoda enumerate ntoarce numrul de fire memorate n tablou, care este identic cu numrul de fire
active.
Sincronizare
n unele situaii se poate ntmpla ca mai multe fire de execuie s vrea s acceseze aceeai
variabil. n astfel de situaii, se pot produce ncurcturi dac n timpul unuia dintre accese un alt fir
de execuie modific valoarea variabilei.
Limbajul Java ofer n mod nativ suport pentru protejarea acestor variabile. Suportul este
construit de fapt cu granulaie mai mare dect o singur variabil, protecia fcndu-se la nivelul
obiectelor. Putem defini metode, n cadrul claselor, care sunt sincronizate.
Pe o instan de clas, la un moment dat, poate lucra o singur metod sincronizat. Dac un
alt fir de execuie ncearc s apeleze aceeai metod pe aceeai instan sau o alt metod a clasei
de asemenea declarat sincronizat, acest al doilea apel va trebui s atepte nainte de execuie
eliberarea instanei de ctre cealalt metod.
n afar de sincronizarea metodelor, se pot sincroniza i doar blocuri de instruciuni. Aceste
sincronizri se fac tot n legtur cu o anumit instan a unei clase. Aceste blocuri de instruciuni
sincronizate se pot executa doar cnd instana este liber. Se poate ntmpla ca cele dou tipuri de
sincronizri s se amestece, n sensul c obiectul poate fi blocat de un bloc de instruciuni i toate
metodele sincronizate s atepte, sau invers.
Declararea unui bloc de instruciuni sincronizate se face prin:
synchronize ( Instan ) {
Instruciuni
}
iar declararea unei metode sincronizate se face prin folosirea modificatorului synchronize la
implementarea metodei.
Un exemplu
Exemplul urmtor implementeaz soluia urmtoarei probleme: ntr-o ar foarte ndeprtat
triau trei nelepi filozofi. Aceti trei nelepi i pierdeau o mare parte din energie certndu-se
ntre ei pentru a afla care este cel mai nelept. Pentru a trana problema o dat pentru totdeauna, cei
trei nelepi au pornit la drum ctre un al patrulea nelept pe care cu toii l recunoteau c ar fi mai
bun dect ei.
Cnd au ajuns la acesta, cei trei i-au cerut s le spun care dintre ei este cel mai nelept.
Acesta, a scos cinci plrii, trei negre i dou albe, i li le-a artat explicndu-le c i va lega la ochi
i le va pune n cap cte o plrie, cele dou rmase ascunzndu-le. Dup aceea, le va dezlega ochii,
i fiecare dintre ei va vedea culoarea plriei celorlali dar nu i-o va putea vedea pe a sa. Cel care
i va da primul seama ce culoare are propria plrie, acela va fi cel mai nelept.
Dup explicaie, neleptul i-a legat la ochi, le-a pus la fiecare cte o plrie neagr i le-a
ascuns pe celelalte dou. Problema este aceea de a descoperi care a fost raionamentul celui care a
ghicit primul c plria lui este neagr.
Programul urmtor rezolv problema dat n felul urmtor: Fiecare nelept privete plriile
celorlali doi. Dac ambele sunt albe, problema este rezolvat, a lui nu poate fi dect neagr. Dac
vede o plrie alb i una neagr, atunci el va trebui s atepte puin s vad ce spune cel cu plria
neagr. Dac acesta nu gsete soluia, nseamn c el nu vede dou plrii albe, altfel ar fi gsit
imediat rspunsul. Dup un scurt timp de ateptare, neleptul poate s fie sigur c plria lui este
neagr.
n fine, dac ambele plrii pe care le vede sunt negre, va trebui s atepte un timp ceva mai
lung pentru a vedea dac unul dintre concurenii si nu ghicete plria. Dac dup scurgerea
timpului nici unul nu spune nimic, nseamn c nici unul nu vede o plrie alb i una neagr.
nseamn c propria plrie este neagr.
Desigur, raionamentul pleac de la ideea c ne putem baza pe faptul c toi nelepii
gndesc i pot rezolva probleme uoare. Cel care ctig a gndit doar un pic mai repede. Putem
simula viteza de gndire cu un interval aleator de ateptare pn la luarea deciziilor. n realitate,
intervalul nu este aleator ci dictat de viteza de gndire a fiecrui nelept.
Cei trei nelepi sunt implementai identic sub form de fire de execuie. Nu ctig la
fiecare rulare acelai din cauza caracterului aleator al implementrii. neleptul cel mare este firul de
execuie principal care controleaz activitatea celorlalte fire i le servete cu date, culoarea
plriilor, doar n msura n care aceste date trebuie s fie accesibile. Adic nu se poate cere propria
culoare de plrie.
Culoarea iniial a plriilor se poate rescrie din linia de comand.
import java.awt.Color;
// clasa Filozof implementeaza comportamentul unui concurent
class Filozof extends Thread {
// parerea concurentului despre culoarea palariei sale.
// Null daca nca nu si-a format o parere.
Color parere = null;
Filozof( String nume ) {
super( nume );
}
public void run() {
// concurentii firului curent
Filozof concurenti[] = new Filozof[2];
// temporar
Thread fire[] = new Thread[10];
int numarFire = enumerate( fire );
for( int i = 0, j = 0; i < numarFire && j < 2; i++ ) {
if( fire[i] instanceof Filozof && fire[i] != this ) {
concurenti[j++] = (Filozof)fire[i];
}
}
while( true ) {
Color primaCuloare = Concurs.culoare( this, concurenti[0] );
Color adouaCuloare = Concurs.culoare( this, concurenti[1] );
if( primaCuloare == Color.white && adouaCuloare == Color.white ) {
synchronized( this ) {
parere = Color.black;
}
import java.awt.Color;
public class Concurs {
private static Color palarii[] = {
Color.black, Color.black, Color.white
};
private static Filozof filozofi[] = new Filozof[3];
public static void main( String args[] ) {
for( int i = 0; i < args.length && i < 3; i++ ) {
if( args[i].equalsIgnoreCase( "alb" ) ) {
palarii[i] = Color.white;
} else if(args[i].equalsIgnoreCase("negru")) {
palarii[i] = Color.black;
}
}
for( int i = 0; i < 3; i++ ) {
filozofi[i] = new Filozof( "Filozoful " + ( i + 1 ) );
}
Abstract Windowing Toolkit, pe scurt AWT, este un set de clase cu ajutorul crora putei
crea o interfa grafic utilizator care s reacioneze la datele de intrare primite de la mouse i
tastatur.
Deoarece Java este un limbaj independent de platform, AWT ofer o modalitate de
proiectare a unei interfee care s prezinte aceeai nfiare i aceleai caracteristici pe orice sistem
pe care ar fi rulat.
Folosind AWT, o interfa este compus din urmtoarele:
Componente. Orice poate fi plasat pe o interfa utilizator, cum ar fi butoane, liste derulante,
meniuri pop-up, casete de validare sau cmpuri de text.
Containere. Acestea sunt componente care pot conine alte componente. Ai folosit deja un
astfel de container - fereastra Applet; alte exemple ar fi panouri, casete de dialog sau ferestre
independente.
Administratori de dispunere. Obiecte care definesc modul cum sunt aranjate (dispuse)
componentele ntr-un container. Administratorul de dispunere nu este vizibil ntr-o interfa,
ns sunt vizibile rezultatele muncii" sale.
Toate clasele AWT fac parte din pachetul java.awt. Pentru a face toate aceste clase
disponibile ntr-un program, poate fi folosit urmtoarea instruciune de import, introdus la
nceputul codului surs:
import java.awt.*;
Aceast instruciune are ca rezultat importarea tuturor componentelor, containerelor i
administratorilor de dispunere pe care i vei folosi la proiectarea unei interfee. Putei folosi i
instruciuni import individuale, numai pentru clasele care vor fi utilizate ntr-un program.
Clasele AWT, ca oricare alte pri ale unei biblioteci de clase Java, sunt aranjate ierarhic.
Cea mai uoar modalitate de a demonstra cum se proiecteaz o interfa este folosirea
containerului cu care ai lucrat pn acum - clasa Applet.
Clasa Button reprezint butoanele din cadrul unei interfee (suprafee pe care se poate executa
clic). Un buton se creeaz specificnd eticheta sa n metoda constructorului, ca n urmtorul
exemplu:
Button atentie = new Button(Atenie!) ;
Aceast instruciune creeaz un buton etichetat cu textul Atenie!.
O dat creat o component, cea mai simpl metod de a o aduga ntr-un container este de
a apela metoda add () a containerului, avnd ca argument componenta respectiv.
Deoarece un applet este un container, putei folosi urmtoarea instruciune pentru a aduga
obiectul atenie ntr-o fereastr Applet:
add(atentie) ;
Adugarea unei componente nu duce imediat la afiarea acesteia. De fapt, aceasta va fi
afiat numai la apelarea metodei paint() a containerului. De acest lucru se ocup n culise" Java,
ns putei fora un apel al metodei paint() a applet-ului folosind metoda repaint() a acestuia.
Atunci cnd adugai o component ntr-un container, nu se specific coordonatele x,y ale
locului unde va fi plasat aceasta. De aranjamentul componentelor se ocup administratorul de
dispunere (layout manager) care aparine containerului respectiv.
Etichete
Cea mai simpl component a unei interfee utilizator este eticheta, care este creat din clasa
Label. Etichetele se folosesc de obicei pentru a identifica rolul celorlalte componente aflate pe
interfa; acestea nu pot fi modificate direct de utilizator.
Folosirea unei etichete pentru text este preferabil folosirii metodei drawString(), din
urmtoarele motive:
Etichetele sunt desenate automat dup creare i nu trebuie s fie tratate explicit de metoda
paint().
Etichetele vor fi aranjate corespunztor administratorului de dispunere curent i nu la o
anumit coordonat x,y cum este cazul irului.
Pentru a crea o etichet folosii unul dintre urmtorii constructori:
Label() creeaz o etichet goal (vid), cu textul aliniat la stnga.
Label (String) creeaz o etichet cu irul de text dat, aliniat, de asemenea, la stnga.
Label (String, int) creeaz o etichet cu irul de text dat i alinierea indicat de argumentul
ntreg. Pentru stabilirea alinierii se folosesc urmtoarele variabile de clas: Label.RIGHT,
Label.LEFT, Label.CENTER.
Butoane
Butoanele (zone pe care se poate efectua clic) pot fi create folosind clasa Button. Butoanele
sunt folosite ntr-o interfa pentru a declana o aciune, cum este butonul Quit (Terminare) folosit
pentru a prsi un program.
Pentru a crea un buton, folosii unul dintre constructorii:
Button() creeaz un buton care nu conine nici un text pentru explicarea funciei sale.
Button(String) creeaz un buton pe care este afiat irul de text primit ca argument.
Dup crearea unui buton, putei s i modificai eticheta folosind metoda setLabel (String) sau
putei afla textul scris folosind metoda getLabel()
Casete de validare
Casetele de validare (check boxes) sunt mici casete, etichetate sau nu, care pot fi validate
(bifate") sau goale. Acestea sunt, de obicei, folosite pentru a selecta sau deselecta anumite opiuni
ntr-un program, cum ar fi opiunile Disable Sound (Dezactivare sunet) sau Password Protected
(Protecie cu parol) dintr-o protecie de ecran (screen saver) Windows.
n mod normal, casetele de validare sunt neexclusive, ceea ce nseamn c, dac avei cinci
casete de validare ntr-un container, toate cinci pot fi validate sau nu simultan.
Aceste componente pot fi organizate i n grupuri de validare, care mai sunt denumite i
butoane radio (radio buttons). Ele i-au luat numele de la vechile aparate de radio, la care apsarea
unui buton ducea la ridicarea altuia care era apsat pn atunci.
Ambele tipuri de casete de validare sunt create folosind clasa Checkbox. Putei crea o caset de
validare neexclusiv folosind unul din urmtorii constructori:
Checkbox() creeaz o caset de validare neetichetat, care nu este validat.
Checkbox(String) creeaz o caset de validare nevalidat i care are ca etichet irul
dat.
Dup ce ai creat un obiect Checkbox, putei folosi metoda setState (boolean) pentru a
modifica starea acestuia, astfel: valoarea true pentru a valida caseta i valoarea false pentru a o
anula. Metoda getState() returneaz o valoare Boolean care indic starea de validare a casetei.
Pentru a organiza mai multe casete de validare ntr-un grup, cu scopul de a nu permite dect
validarea unei singure opiuni la un moment dat, se creeaz un obiect CheckboxGroup, printr-o
instruciune de genul:
CheckboxGroup radio = new CheckboxGroup();
Obiectul CheckboxGroup pstreaz starea tuturor casetelor de validare din grupul su.
Acest obiect va fi folosit ca argument suplimentar pentru constructorul Checkbox.
Checkbox (String, GrupCaseteValidare, boolean) creeaz o caset de validare etichetat cu
irul dat de primul argument i care aparine grupului indicat de cel de-al doilea argument. Cel de-al
treilea argument trebuie setat pe true dac se dorete validarea casetei de dialog i false n caz
contrar.
Liste de opiuni
Listele de opiuni (choice lists), create din clasa Choice, sunt componente care permit
alegerea unei singure opiuni dintr-o list derulant (pull-down list). Vei ntlni de multe ori acest
tip de liste atunci cnd completai un formular dintr-o pagin World Wide Web.
Primul pas n crearea unei liste de opiuni const n crearea obiectului Choice care va pstra
lista, ca n exemplul urmtor:
Choice sex = new Choice();
Elementele se adaug ntr-o list de opiuni folosind metoda addItem(String) a obiectului.
Urmtoarele instruciuni adaug dou elemente n lista de opiuni sex:
sex.addItem("Masculin");
sex.addItem("Feminin");
Putei continua s folosii metoda addItem() pentru a aduga opiuni n list chiar i dup ce lista a
fost introdus ntr-un container.
Cmpuri de text
Cmpurile de text (text fields) sunt folosite pentru a crea componente n care textul poate fi
modificat de utilizator. Aceste componente sunt create din clasa TextField.
Pentru a crea un cmp de text, folosii unul din urmtorii constructori:
TextField (String, int) creeaz cmp completat cu irul dat i cu limea specificata de
argumentul ntreg.
Atributul responsabil cu limea cmpului are relevan doar n cazul folosirii unor
administratori de dispunere (layout managers) care nu redimensioneaz componentele, cum ar fi
administratorul FlowLayout.
Urmtoarea instruciune creeaz un cmp de text gol, care ofer suficient spaiu pentru 30 de
caractere:
TextField nume = new TextField(30) ;
Urmtoarea instruciune poate fi folosit dac dorii s iniializai cmpul cu irul de text
"Ion I. Ionescu":
TextField nume = new TextField("Ion I. Ionescu", 30);
Putei crea i un cmp de text care s ascund caracterele tastate, afind n locul lor un
caracter oarecare. Aceast facilitate se folosete de obicei n cmpurile de introducere a parolelor,
pentru a ascunde parola de priviri indiscrete.
Pentru a defini un astfel de caracter de mascare, n Java 1.02 se folosete metoda
setEchoCharacter(char), iar n versiunile urmtoare, metoda setEchoChar(char). Dac se
folosete un literal, acesta trebuie ncadrat ntre ghilimele simple, ca de exemplu '*'. Java
interpreteaz orice literal ncadrat de ghilimele duble ca fiind un obiect de tip String (ir).
Zone de text
Zonele de text (text areas), create din clasa textArea, sunt cmpuri de text modificabile
care pot conine mai multe linii de text. Zonele de text posed bare de defilare orizontale i
verticale, care permit utilizatorului s parcurg ntreg textul coninut n component.
Pentru a crea o zon de text putei folosi unul din urmtorii constructori:
TextArea() creeaz o zon de text goal, cu nlime i lime nespecificate.
TextArea (int, int) creeaz o zon goal, care conine numrul de rnduri dat de primul
argument i are limea n caractere dat de al doilea argument.
TextArea (String) creeaz o zon de text care conine irul specificat i are limea i
nlimea nespecificate.
TextArea(String, int, int) creeaz o zon de text care conine irul specificat, numrul de
rnduri fiind dat de primul argument, iar limea n caractere de al doilea argument.
Liste de derulare
Listele de derulare (scrolling lists), create din clasa List, sunt asemntoare listelor de
opiuni, cu dou diferene semnificative:
Lista de derulare poate fi configurat aa nct s poat fi selectate mai multe opiuni la un
moment dat.
Listele de derulare se prezint asemntor unei zone de text n care sunt afiate mai multe
opiuni. Dac lista conine mai multe opiuni dect pot fi afiate, se folosete o bar de
derulare pentru a se parcurge ntreaga list.
O list de derulare este definit prin crearea unui obiect List i adugarea n list a unor
elemente. Clasa List posed urmtorii constructori:
List() creeaz o list de parcurgere vid care permite selectarea unui singur element la un
moment dat.
List(int, boolean) creeaz o list de derulare care posed numrul de elemente vizibile
indicat de primul argument (numr care poate fi mai mic dect numrul total de elemente).
Argumentul boolean indic dac pot fi selectate mai multe elemente (true) sau nu (false).
Dup crearea unui obiect List se folosete metoda addItem(String) pentru a aduga
elemente n list. (Nota: ncepnd cu Java 2, metoda nu se mai recomand i a fost nlocuit de
metoda add(String)).
Suprafee de desenare
Suprafeele de desenare (canvas) sunt componente folosite, n principal, drept loc de afiare
pentru imagini sau animaie. Putei desena i pe alte componente, ns obiectele Canvas sunt cele
mai simplu de folosit n acest scop.
Pentru a folosi o suprafa de desenare trebuie s creai o subclas a clasei Canvas. Aceast
subclas se poate ocupa de toate operaiunile de desenare care trebuie s aib loc, n metoda sa
paint().
O dat creat o subclas Canvas, aceasta poate fi folosit n program prin apelarea
constructorului su i prin adugarea noului obiect Canvas ntr-un container.
Dispunerea secvenial
FlowLayout este cea mai simpl clas de administrare a dispunerii. Ea aranjeaz
componentele ntr-o manier asemntoare dispunerii cuvintelor ntr-o pagin - de la stnga la
dreapta pn la captul rndului, apoi n continuare pe rndul urmtor.
n mod prestabilit, dac folosii constructorul FlowLayout() fr argumente, componentele
de pe fiecare rnd vor fi centrate. Dac dorii ca acestea s fie aliniate la marginea din stnga sau
din dreapta a containerului, trebuie folosite drept argument pentru constructor variabilele de clas
FlowLayout.LEFT sau FlowLayout.RIGHT:
FlowLayout dreapta = new FlowLayout(FlowLayout.RIGHT);
Variabila de clas FlowLayout.CENTER este folosit pentru dispunerea pe centru a
componentelor.
Dispunerea tabelar
Administratori de dispunere tabelar (grid) aranjeaz componentele ntr-un caroiaj (tabel)
format din rnduri i coloane.
Componentele sunt adugate ncepnd cu celula aflat cel mai n stnga pe primul rnd al
tabelului i continund spre dreapta. Dup completarea tuturor celulelor de pe primul rnd se
continua cu cel de-al doilea rnd, de la stnga la dreapta, i aa mai departe.
Dispunerea tabelar este stabilit pornind de la clasa GridLayout. Constructorul
GridLayout primete dou argumente - numrul de rnduri i numrul de coloane din tabel.
Urmtoarea instruciune creeaz un administrator de dispunere tabelar pentru 10 rnduri i 3
coloane:
GridLayout gr = new GridLayout(10,3);
Ca i n cazul dispunerii secveniale, dac se folosesc dou argumente suplimentare, putei
specifica spaiul pe orizontal i pe vertical care trebuie lsat ntre componente. Urmtoarea
instruciune creeaz un tabel cu 10 rnduri, 3 coloane, un spaiu pe orizontal de 5 pixeli i un
spaiu pe vertical de 8 pixeli:
GridLayout gr2 = new GridLayout(10, 3, 5, 8);
Spaiul ntre componentele dispunerii tabelare este implicit 0 pixeli, att pe orizontal ct si pe
vertical.
Dispunerea marginal
Dispunerile marginale (border layouts), create pornind de la clasa BorderLayout, mpart un
container n cinci seciuni: nord, sud, est, vest i centru.
Folosind dispunerea marginal, componentele din cele patru puncte cardinale vor ocupa
spaiul de care au nevoie, iar centrul obine spaiul rmas disponibil. De obicei, acest aranjament are
ca rezultat o component central de dimensiuni mari, nconjurat de patru componente mai
subiri".
Dispunerea marginal se obine folosind unul dintre constructorii Borderlayout() sau
BorderLayout(int, int). Primul constructor creeaz o dispunere marginal fr nici un spaiu ntre
componente. Al doilea constructor specific spaiul pe orizontal, respectiv pe vertical.
Dispuneri complexe
Dispunerea n stiv
O dispunere n stiv (card layout) difer de celelalte deoarece ascunde vederii unele
componente. O dispunere n stiv este un grup de containere sau de componente afiate cte unul o
dat. Fiecare container din grup este denumit card (cartel).
n mod normal, dispunerea n stiv folosete un panou pentru fiecare cartel. Mai nti se introduc
componente n panouri, dup care acestea se introduc n containerul pe care s-a stabilit o dispunere
n stiv.
O dispunere n stiv se creeaz cu ajutorul clasei CardLayout, apelnd constructorul acesteia:
CardLayout cc=new CardLayout();
Pentru a stabili administratorul de dispunere pentru un container se folosete metoda
setLayout(). Dup ce ai stabilit un container se folosete metoda add(String, container). Al doilea
argument specific containerul sau componenta care reprezint cartela. Dac este vorba de un
container acesta trebuie s conin deja toate componentele necesare. Primul argument este un ir
care reprezint numele cartelei. Acesta poate fi oricare, ca n exemplul:
add(Cartela de optiuni, optiuni)
prin care se adaug n container un panou numit optiuni i i se atribuie numele Cartela de optiuni.
Dup ce s-a adugat cartela n containerul principal al programului, se poate folosi metoda show() a
administratorului de dispunere n stiv, metod ce primete dou argumente:
Containerul n care au fost adugate cartelele. Dac containerul este chiar fereastra
principal se poate folosi this.
Numele cartelei
Urmtorul exemplu apeleaz metoda show() a administratorului de dispunere n stiv denumir cc:
cc.show(this,Cartela de date)
restrictii.gridwidth=1;
restrictii.gridheight=1;
restrictii.weightx=30;
restrictii.weighty=30;
restrictii.fill= GridBagConstraints.NONE;
restrictii.anchor= GridBagConstraints.CENTER;
tabel.setConstraints(b,restrictii);
add(b);
Etapele care trebuie parcurse la dispunerea tabelara neproporional
Etapa 1. Proiectarea tabelului
O variant ar fi s se creeze o metod ajuttoare, care preia mai multe valori i stabilete
restriciile pentru acestea. Asftel metoda definireRestrictii() preia apte argumente: un obiect
GridBagConstraints i ase valori ntregi, care reprezint variabilele de instan gridx, gridy,
gridwidth, gridheight, weightx i weighty. Metoda definireRestrictii este urmtoarea:
void definireRestrictii(GridBagConstraints gbc, int gx, int gy, int gw, int
gh, int wx, int wy) {
gbc.gridx=gx;
gbc.gridy=gy;
gbc.gridwidth=gw;
gbc.gridheight=gh;
gbc.weightx=wx;
gbc.weighty=wy;
}
Se creeaz apoi metoda init() , n care se creeaz de fapt dispunerea.
public void init()
{GridBagLayout tabel=new GridBagLayout();
GridBagConstraints restrictii =new GridBagConstraints();
SetLayout(tabel);
restrictii.fill=GridBagConstraints.BOTH;
}
Se vor defini apoi restrictii corespunztoare fiecrei componente din interfa, ca n
exemplul urmtor:
definireRestrictii(restrictii, 0,0,1,1,100,100);
Button eticheta1=new Button(nume);
tabel.setConstraints(eticheta1,restrictii);
add(eticheta1);
Aceste linii vor stabili restriciile pentru un obiect, vor crea un buton, vor asocia acestuia restriciile
i l vor aduga n panou.
Primele dou argumente reprezint valorile gridx i gridy ale restriciilor. Acestea
reprezint chiar coordonatele celulei ce conine componenta. Dac o component ocup mai multe
celule se vor introduce coordonatele componentei cea mai din stnga-sus. Urmtoarele argumente
reprezint gridwidth i gridheight. Ele nu reprezint laimea i nlimea n pixeli, ci reprezint
numrul de celule pe care le ocup componenta. Ultimele dou argumente sunt proporiile weightx
i weighty, folosite pentru a stabili proporiile rndurilor i a coloanelor, adic modul de distribuire
al spaiului suplimentar care rmne neutilizat dup amplasarea componentei. Dup stabilirea
proporiilor ele pot fi atribuite unui obiect folosind metoda GridBagConstraints().
La determinarea proporiilor se ine cont de obiectele care se extind pe mai multe celule.
Acestea trebuie s primeasc valoarea 0 n direcia n care se extind.
Etapa a patra. Adugarea i aranjarea componentelor
n aceast etap se stabilesc restriciile care arajeaz componentele n cadrul celulei. Exist
dou astfel de restricii: fill (umplere) i anchor (ancorare).
Restricia fill determin pentru componentele care se pot extinde n orice direcie n ce direcie
se face aceast extindere i poate avea una dintre urmtoarele valori:
GridBagConstraints.BOTH, care extinde componenta pentru a umple celula n ambele direcii
GridBagConstraints.NONE, care determin componenta s fie afiat la cea mai mic dimensiune
a sa
GridBagConstraints.HORIZONTAL, care extinde componenta pe direcie orizontal
GridBagConstraints.VERTICAL, care extinde componenta pe direcie vertical.
Implicit restricia fill este NONE.
A doua restricie care afecteaz modul n care apare o component ntr-o celul este anchor
(ancorare) i ea se aplic doar componentelor care nu umplu ntreaga celul, indicnd funciilor
AWT unde s plaseze componenta n cadrul celulei. Valori posibile:
GridBagConstraints.NORTH, GridBagConstraints.SOUTH, GridBagConstraints.NORTHEAST,
GridBagConstraints.SOUTHWEST, GridBagConstraints.EAST, GridBagConstraints.WEST,
GridBagConstraints.SOUTHEAST, GridBagConstraintsNORTHWEST, GridBagConstraints.CENTER.
Tratarea evenimentelor
Unul dintre lucrurile pe care le-ai nvat atunci cnd ai creat pentru prima dat un applet
este c, atunci cnd acesta ruleaz, n fundal se desfoar o mulime de activiti. Sistemul de
ferestre al Java apeleaz automat metode cum ar fi paint(), init() sau start(), atunci cnd este nevoie,
fr nici o intervenie din partea dumneavoastr.
Ca i programarea applet-urilor, tratarea evenimentelor presupune apelarea automat a unor
metode atunci cnd aciunea unui utilizator duce la apariia unui eveniment.
Tipuri de evenimente
Un eveniment este generat ca rspuns la aproape orice aciune pe care o poate ntreprinde un
utilizator pe parcursul ciclului de via al unui program Java. O micare a mouse-ului, un clic
executat pe un buton, o apsare de tast, toate genereaz un eveniment.
n programele dumneavoastr nu trebuie s tratai toate evenimentele ce por aprea. De fapt,
v vei ocupa de acele evenimente la care vrei s rspund programul dumneavoastr; restul vor fi
ignorate. De exemplu, dac utilizatorul execut un clic cu mouse-ul sau apas o tast, putei face ca
programul s rspund la aceste evenimente.
Iat cteva dintre evenimentele care pot fi tratate n programele dumneavoastr:
Clicuri cu mouse-ul. Apsarea butonului mouse-ului (mouse down), eliberarea acestuia
(mouse up) sau apsarea i eliberarea butonului pe aceeai poziie (mouse clic).
Micri ale mouse-ului. Cursorul mouse-ului care prsete sau ptrunde pe suprafaa
ocupat de o component a interfeei sau tragerea cu mouse-ul (drag - micrile efectuate de
cursor atunci cnd butonul mouse-ului este apsat).
Apsri de taste. Apsarea tastei, eliberarea tastei, tastarea (apsarea i eliberarea unei
taste).
Evenimente ale interfeei utilizator. Execuia de clicuri pe butoane, derularea listelor,
afiarea meniurilor derulante i aa mai departe.
Metoda handleEvent ()
Tratarea evenimentelor reprezint domeniul n care au aprut cele mai multe modificri n
trecerea de la Java 1.02 la Java 2. Evenimentele sunt generate i executate aproximativ n acelai
mod, indiferent de versiunea de limbaj pe care o folosii; diferena const n modul cum acestea sunt
recepionate i procesate.
n Java 1.02, toate evenimentele care apar n ciclul de via al unui program sunt tratate de o
metod denumit handleEvent(). Aceasta este definit n clasa Component, care este motenit de
java.applet.Applet, devenind astfel disponibil tuturor applet-urilor.
Atunci cnd un eveniment este transmis metodei handleEvent (), aceasta apeleaz apoi o
metod specific de tratare a evenimentului, n funcie de tipul acestuia. Exemple de astfel de
metode specifice sunt mouseDown(), mouseUp() sau keyDown().
Pentru a trata un eveniment n programele dumneavoastr, va trebui s suprascriei una
dintre aceste metode specifice. Apoi, la apariia evenimentului respectiv, metoda respectiv va fi
apelat. De exemplu, putei suprascrie metoda mouseDown() pentru a afia un mesaj n fereastra
Applet. Atunci cnd apare un eveniment de acest tip (apsarea butonului mouse-ului), mesajul va fi
afiat.
Tratarea clicurilor de mouse
Unul dintre cele mai des ntlnite evenimente care v-ar putea interesa este efectuarea unui
clic cu mouse-ul. Evenimentele de acest tip apar atunci cnd utilizatorul execut un clic cu mouseul undeva, pe interfaa programului.
Putei intercepta clicurile mouse-ului pentru diferite lucruri simple - de exemplu, pentru a
activa sau dezactiva sunetul ntr-un applet, pentru a trece la urmtoarea plan a unei prezentri sau
pentru a terge ecranul. De asemenea, clicurile cu mouse-ul pot fi folosite mpreun cu deplasrile
acestuia pentru a realiza o form de interaciune mai complex cu utilizatorul.
Evenimentele mouse down i mouse up
Atunci cnd utilizatorul execut un clic cu mouse-ul, se genereaz dou evenimente: un
eveniment mouse down, atunci cnd se apas butonul mouse-ului, i un eveniment mouse up, atunci
cnd acesta este eliberat. Aceast divizare permite executarea unor aciuni diferite n cele dou
etape ale clicului.
Tratarea evenimentelor mouse-ului n applet-ul dumneavoastr este simpl; se suprascrie
metoda corespunztoare, care va fi apelat la apariia respectivului eveniment. Iat un exemplu de
semntur de metod pentru un eveniment mouse down:
public boolean mouseDown(Event evt, int x, int y) {
//. . .
}
Metoda mouseDown() (ca i metoda mouseUp()) primete trei parametri: evenimentul n
sine i coordonatele x i y unde a aprut evenimentul respectiv.
Argumentul evt reprezint o instan a clasei Event. Toate evenimentele genereaz o
instan a clasei Event, care conine informaii privind locul i perioada cnd a avut loc
evenimentul, tipul lui, precum i alte informaii. Uneori, existena unui astfel de pointer ctre un
obiect Event este folositoare, aa cum vei descoperi mai trziu n aceast seciune.
Coordonatele x i y ale evenimentului, aa cum au fost ele transmise prin argumentele x i y
ale metodei mouseDown(), v permit s determinai cu precizie locul unde s-a efectuat , clicul. Deci
de exemplu, dac evenimentul mouse down a aprut n zona unui buton grafic, putei activa acel
buton. Reinei c putei obine coordonatele x i y i din cadrul obiectului Event; n aceast metod,
ele au fost transmise ca argumente separate pentru a se lucra mai uor cu ele.
alfanumerice, taste funcionale, tabulatori, tasta return (retur de car) i aa mai departe. Pentru a le
folosi drept caractere (de exemplu, pentru a le tipri) trebuie s le convertii n caractere, astfel:
caracterCrt = (char)tasta;
Iat un exemplu simplu de metod keyDown(), care nu face altceva dect s afieze tasta pe
care ai apsat-o, att ca valoare Unicode, ct i drept caracter :
public boolean keyDown(Event evt, int tasta) {
System.out.println("Valoare UNICODE: " + tasta) ;
System.out.println("Caracter: " + (char) tasta) ;
return true;
}
Ca i n cazul clicurilor de mouse, fiecare eveniment key down are i corespondentul key up
tast ridicat. Pentru a intercepta evenimentele key up se folosete metoda keyUp():
public boolean keyUp(Event evt, int tasta) {
// ...
}
Taste prestabilite
Clasa Event ofer un set de variabile de clas care reprezint cteva taste standard nealfanumerice, cum ar fi tastele funcionale sau tastele direcionale (cu sgei). Dac interfaa appletului dumneavoastr folosete aceste taste, putei crea un cod mai lizibil prin testarea acestora n
metoda keyDown(), n loc s testai valorile numerice echivalente (de asemenea, dac folosii aceste
variabile, codul dumneavoastr va funciona cu mai mare probabilitate pe alte platforme). De
exemplu, cnd dorii s testai dac a fost apsat tasta direcional cu sgeata n sus (up arrow),
putei folosi urmtoarea secven de cod:
if (tasta = Event.UP) {
// ...
}
Deoarece valorile acestor variabile de clas sunt ntregi, putei folosi pentru testarea lor
instruciunea switch.
n tabelul urmtor se prezint variabilele de clas Event pentru diferite taste, precum i semnificaia
acestora.
Tastele standard definite n clasa Event.
Variabila de clas
Tasta reprezentat
Event.HOME
Event.END
Event.PGUP
Event.PGDN
Event.UP
Event.DOWN
Tasta Home
Tasta End
Tasta Page Up
Tasta Page Down
Tasta Up
Tasta Down
Event.LEFT
TastaLeft
Event.RIGHT
Event.F1
Event.F2
Event.P3
Event.F4
Event.F5
Event.F6
Event.F7
Event.F8
Event.F9
Event.F10
Event.F11
Event.F12
Tasta Right
Tasta F1
Tasta F2
Tasta F3
Tasta F4
TastaF5
Tasta F6
Tasta F7
Tasta F8
Tasta F9
Tasta F10
TastaF11
TastaF12
Tip de argument
String
Boolean
Boolean
Ce conine
Eticheta butonului
ntotdeauna true
ntordeauna true
Meniuri de opiuni
Cmpuri de text
String
String
n cadrul metodei action(), primul lucru care trebuie fcut este s testai care component a
generat aciunea (spre deosebire de evenimentele de mouse sau de tastatur, n care aceasta nu
conta, deoarece toate componentele puteau genera aciuni). Din fericire, obiectul Event pe care l
primii ca argument n apelul metodei action() conine o variabil de instan denumit target (int),
care conine o referin ctre obiectul ce a generat evenimentul. Putei folosi operatorul instanceof
pentru a afla ce component a generat evenimentul, ca n urmtorul exemplu:
public boolean action(Event evt, Object arg) {
if (evt.target instanceof textField)
return handleText(evt.target);
else if (evt.target instanceof Choice);
return handleChoice(arg);
// ...
return false;
}
n acest exemplu, metoda action() putea fi generat fie de o component TextField (cmp de
text), fie de un meniu cu opiuni; instruciunea if determin care dintre acestea dou a generat
evenimentul i apeleaz o alt metod (aici, handleText() sau handlechoice()), care trateaz, de fapt,
evenimentul respectiv. (Nici handleText() i nici handleChoice() nu sunt metode AWT; sunt doar
exemple de nume ce pot fi folosite drept metode ajuttoare. Se obinuiete s se creeze astfel de
metode ajuttoare - helper - aa nct metoda action() s nu devin prea ncrcat cu cod.)
Ca i n cazul altor metode de tratare a evenimentelor, action() returneaz o valoare Boolean.
La fel, trebuie s returneze true dac va trata evenimentul respectiv i false dac acesta va fi ignorat
sau tratat n alt parte. n acest exemplu ai transferat controlul metodelor handleText() sau
handleChoice(), care vor returna true sau false, aa ca putei returna false (reinei, vei returna true
numai daca metoda proceseaz evenimentul).
Pot aprea complicaii dac avei mai multe componente aparinnd toate aceleiai clase - de
exemplu, o mulime de butoane. Toate genereaz aciuni i toate sunt instane ale clasei Button. Aici
intervine argumentul suplimentar: folosind cteva comparaii simple de iruri, putei folosi
etichetele, elementele sau coninutul componentei pentru a determina care dintre ele a generat
evenimentul. (Nu uitai s convertii prin cast argumentul n obiectul corespunztor.)
public boolean action(Event evt, Object arg) {
if (evt.target instanceof Button) {
String eticheta = (String)arg;
if (eticheta.equals("OK"))
// trateaza butonul OK
else if (eticheta.equals ("Anulare"))
// trateaza butonul Anulare
else if (eticheta.equals("Navigare"))
// trateaza butonul Navigare
// ...
}
}
Listele derulante genereaz trei tipuri de evenimente diferite; selectarea sau deselectarea
unui element individual al listei are ca efect un eveniment de selectare/deselectare list, iar dublul
clic executat pe un element al listei are ca efect un eveniment de aciune.
Putei suprascrie metoda action() pentru a trata elementul din list pe care s-a efectuat dubluclic. Pentru seleciile i deseleciile din list, putei s suprascriei metoda handleEvent() i s testai
identificatorii de eveniment LIST_SELECT i LIST_DESELECT.
Clasele Window
Clasele AWT care produc ferestre sau casete de dialog motenesc o clas comun, Window. Clasa Window
motenete clasa Container, ca i componentele panou i applet, i ofer un comportament generic pentru toate
elementele derivate din ferestre.
De obicei nu se folosesc instane ale clasei Window, ci ale celor dou subclase principale
ale sale: Frame i Dialog.
Clasa Frame (cadru) ofer o fereastr care conine o bar de titlu, butoane de
nchidere i alte elemente specifice unei ferestre pentru un anumit sistem. De asemenea,
cadrele permit adugarea unor bare de meniuri. Clasa Dialog este o variant mai limitat
a clasei Frame, care, de obicei, nu are un titlu. FileDialog, o subclas a clasei Dialog,
ofer o caset de dialog standard pentru alegerea unui fiier (de obicei, aceasta poate fi
folosit doar n cadrul aplicaiilor Java, deoarece applet-urile impun restricii de securitate).
Pentru a aduga o fereastr sau o caset de dialog n applet-ul sau aplicaia dumneavoastr
trebuie s creai subclase ale claselor Frame sau Dialog.
Cadre
Cadrele (frames) sunt ferestre independente de fereastra applet-ului sau a browserului care
conine applet-ul; ele sunt ferestre separate, care conin titluri proprii, butoane de redimensionare
sau de nchidere i bare de meniuri. Putei crea cadre, n applet-uri, pentru a produce ferestre sau le
putei folosi n aplicaii pentru a pstra coninutul acestora.
Un cadru reprezint o fereastr specific unei anumite platforme, care conine un titlu, o
bar de meniuri, butoane de nchidere i de redimensionare i alte elemente specifice unei ferestre.
Pentru a crea un cadru se folosete unul din urmtorii constructori:
este BorderLayout. Iat un exemplu care creeaz un cadru, stabilete dispunerea componentelor n
acesta i adaug dou butoane:
win = new Frame("Fereastra mea") ;
win.setLayout(new BorderLayout(10, 20));
win.add("North", new Button("Start")) ;
win.add("Center", new Button("Mutare"));
Pentru a stabili dimensiunea noului cadru se folosete metoda resize (), care primete ca
argumente limea i nlimea acesteia. De exemplu, aceast linie de cod redimensioneaz fereastra
la dimensiunile de 100 pixeli lime i 200 pixeli nlime:
win.resize(100, 200);
Deoarece n sisteme diferite se calculeaz n mod diferit reprezentrile pixelilor i exist
rezoluii diferite, este dificil crearea unui cadru de dimensiuni bune" pentru oricare platform.
Ferestrele care sunt potrivite ntr-un sistem pot fi prea mici sau prea mari ntr-un altul.
O metod de evitare a acestei probleme este folosirea metodei pack() n locul metodei
resize(). Metoda pack(), care nu primete argumente, creeaz o fereastr de cea mai mic
dimensiune posibil, date fiind dimensiunile curente ale componentelor pe care le conine,
administratorul de dispunere i inseriile folosite. Urmtorul exemplu creeaz dou butoane i le
adaug ntr-o fereastr. Dup aceasta, fereastra este adus la cele mai mici dimensiuni posibile cnd
conine aceste dou butoane.
FlowLayout flo = new FlowLayout() ;
Button ok = new Button("OK");
Button anulare = new Button("Anulare");
win.setLayout(flo);
win.add(ok) ;
win.add(anulare);
win.pack() ;
Atunci cnd creai o fereastr, aceasta este invizibil. Pentru a fi afiat pe ecran trebuie s
folosii metoda show(). Pentru a o ascunde din nou putei folosi metoda hide(). Exemplu:
win.show() ;
Reinei c atunci cnd o fereastr este afiat de un applet, browserul v atrage atenia c
aceasta nu este o fereastr a sa, de obicei, printr-un mesaj n cadrul ferestrei.
Casete de dialog
Casetele de dialog, din punct de vedere funcional, sunt asemntoare cadrelor prin faptul c afieaz ferestre
pe ecran. Totui, ele sunt destinate pentru a fi folosite drept ferestre temporare adic pentru a v prezenta mesaje de
avertizare, pentru a v cere anumite informaii i aa mai departe.
Casetele de dialog nu au, de obicei, bare de titlu sau alte elemente caracteristice unei ferestre
(cu toate c putei crea i casete de dialog cu bare de titlu). Ele pot fi definite aa nct s nu fie
redimensionabile sau pot fi definite drept modale. (Casetele de dialog modale mpiedic accesarea
altor ferestre pn n momentul cnd se renun la ele.)
Casetele de dialog sunt ferestre temporare avnd rolul de a alerta utilizatorul cu privire la un anumit eveniment
sau de a prelua date de la utilizator. Spre deosebire de cadre, casetele de dialog nu posed, de obicei, bare de titlu sau
butoane de nchidere.
O caset de dialog modal nu permite introducerea de date n alte ferestre pn cnd nu este
nchis. Nu vei putea aduce n prim plan o alt fereastr i nici minimiza caseta de dialog modal;
aceasta trebuie nchis explicit pentru a se putea continua lucrul n sistem. De obicei, avertismentele
sunt casete de dialog modale.
AWT ofer dou tipuri de casete de dialog: clasa Dialog, care produce o caset de dialog
generic, i FileDialog, care produce o caset de dialog pentru cutarea de fiiere, specific
platformei respective.
Obiecte dialog
Casetele de dialog se creeaz i se folosesc asemntor ferestrelor. Pentru crearea unei casete de dialog
generice se folosete unul din urmtorii constructori:
Dialog (Frame, boolean) creeaz o caset de dialog invizibil, ataat cadrului curent, fie
Codul care face acest lucru folosete metoda getParent(), definit pentru toate
componentele AWT. Metoda getParent() returneaz obiectul care conine obiectul curent. Deci
printele tuturor aplicaiilor AWT trebuie s fie un cadru. Applet-urile se comport n acelai mod.
Prin apelarea n mod repetat a metodei getParent() vei ajunge, pn la urm, s obinei o instan
a clasei Frame. lat codul pe care trebuie s l introducei n applet-ul dumneavoastr:
Object ancora = getParent();
while (! (ancora instanceof Frame))
ancora = ((Component)ancora).getParent();
n prima linie a codului se creeaz o variabil local, denumit ancora, care va memora n final
cadrul acestui applet. Obiectul atribuit variabilei poate fi de mai multe tipuri, aa nct va fi
declarat de tip Object.
Urmtoarele dou linii de cod definesc un ciclu while care apeleaz metoda getParent() n
lan, pentru fiecare obiect, pn cnd ajunge la un obiect de tip Frame. Se observ aici c, deoarece
metoda getParent() este definit doar pentru obiectele care motenesc clasa Component, trebuie s
convertii prin cast valoarea ancora la tipul Component de fiecare dat cnd apelai metoda
getParent().
Dup ncheierea ciclului, obiectul coninut de variabila ancora va fi o instan a clasei Frame
(sau a uneia dintre subclasele acesteia). Putei crea un obiect Dialog ataat acestui cadru convertind
prin cast variabila ancora, pentru a v asigura c obinei un obiect Frame:
TextDialog dl = new TextDialog((Frame)ancora, "Enter Text",true);
Folosirea de instane ale clasei FileDialog n applet-uri depinde de browser. Din cauza
restriciilor de securitate existente n applet-uri, majoritatea browserelor produc o excepie de
securitate atunci cnd ncercai acest lucru. Obiectele FileDialog sunt mai folositoare n aplicaiile
independente.
Pentru a crea o caset de dialog pentru fiiere, folosii unul din urmtorii constructori:
FileDialog(Frame, String) creeaz o caset de dialog ataat unui cadru dat i cu un titlu
dat, pentru ncrcarea unui fiier.
FileDialog(Frame, String, int) creeaz tot o caset de dialog, ns argumentul ntreg este
folosit pentru a stabili dac este vorba despre o caset de dialog pentru ncrcarea sau pentru
salvarea unui fiier. (Singura diferen este eticheta butoanelor; de fapt, aceast caset de
dialog nu deschide sau nu salveaz nimic.) Opiunile pentru acest argument sunt
FileDialog.LOAD sau FileDialog.SAVE.
Dup crearea unei instane a clasei FileDialog se folosete metoda show() pentru a o afia:
FileDialog fd = new FileDialog(this, "FileDialog=) ;
fd.show() ;
Atunci cnd utilizatorul alege un fiier i nchide caseta de dialog, el poate accesa numele fiierului
ales folosind metodele getDirectory() i getFile(). Ambele metode returneaz un ir care conine
valorile alese de utilizator. Dup aceasta, putei deschide fiierul folosind metodele de lucru cu
fiiere i fluxuri (streams) de date, apoi putei citi sau scrie din/n acest fiier.
Evenimente de fereastr
Ai ajuns acum la ultimul tip de evenimente pe care le putei trata n AWT: evenimentele pentru ferestre i
casete de dialog. (n ceea ce privete evenimentele, caseta de dialog este tot un tip de fereastr.) Evenimentele de
fereastr apar atunci cnd starea unei ferestre se modific: de exemplu, cnd este mutat, redimensionat, minimizat,
restabilit, mutat n prim-plan sau nchis. ntr-o aplicaie ngrijit programat, aceste evenimente trebuie tratate - de
exemplu, pentru a opri firele aflate n execuie atunci cnd o fereastr este minimizat sau pentru a face curenie" la
nchiderea ferestrei.
Cnd apare
Generat atunci cnd o fereastr este nchis folosind butonul Close sau
opiunea de meniu Close
Generat atunci cnd fereastra este adus n prim-plan din spatele altor ferestre
Generat atunci cnd fereastra este minimizat (redus la dimensiunea unei
pictograme)
Generat atunci cnd fereastra este restabilit (cnd se revine de la starea de
pictogram)
Generat atunci cnd fereastra este mutat
Meniuri
O bar de meniuri (menu bar) este o colecie de meniuri. Un meniu, n schimb, conine o
colecie de opiuni, care pot avea denumiri i, opional, prescurtri (shortcuts). Biblioteca AWT
ofer clase pentru toate aceste elemente de meniu, cum ar fi MenuBar, Menu i MenuItem.
Elemente de meniu
n meniurile individuale putei aduga patru tipuri de elemente (opiuni):
Instane ale clasei MenuItem, pentru elemente de meniu obinuite
Instane ale clasei CheckBoxMenuItem, pentru elemente de meniu care au strile
activat/dezactivat
Evenimente de meniu
Aciunea de selectare a unui meniu cu ajutorul mouse-ului sau a comenzii rapide asociate
genereaz un eveniment. Putei trata acest eveniment folosind metoda action(), aa cum ai procedat
i n aplicatiile anterioare.
n afar de evenimente de aciune, elementele de tip checkBoxMenuItem genereaz
evenimente de selectare i deselectare a listelor, care pot fi tratate cu ajutorul metodei
handleEvent().
Atunci cnd procesai evenimentele generate de elementele de meniu simple sau cele cu
casete de validare, inei cont de faptul c deoarece CheckBoxMenuItem este o subclas a
MenuItem, nu trebuie s tratai acel element de meniu drept un caz special. Vei trata aciunea sa n
acelai mod ca pe alte aciuni.
Pentru crearea unei aplicaii Java clasa aplicaiei principale trebuie s moteneasc clasa
Frame. Dac folosete fire de execuie (pentru animaie sau alte procesri), trebuie s
implementeze, de asemenea, clasa Runnable:
class AplicatieAWT extends Frame implements Runnable {
//...
}
Pentru aplicaia dumneavoastr vei crea n metoda main() o nou instan a clasei; deoarece
clasa motenete clasa Frame, vei obine o nou fereastr AWT, pe care apoi o putei
redimensiona i afia ca pe orice fereastr AWT.
Caracteristicile AWT normale pentru o fereastr, care se declarau de obicei n cadrul
metodei init() a unui applet, se realizeaz aici n cadrul metodei constructor a clasei: se stabilete
titlul, se declar un administrator de dispunere, se creeaz i adaug componente cum ar fi bara de
meniuri sau alte elemente de interfa, se lanseaz fire de execuie i aa mai departe.
Un exemplu de aplicaie simpl:
import java.awt.* ;
class AplicatieAWT extends Frame {
AplicatieAWT(String titlu) {
super(titlu) ;
setLayout(new FlowLayout()) ;
add(new Button("OK") ;
add (new Button("Reset");
add( new Button("Cancel) ;
}
public static void main(String args[ ]) {
AplicatieAWT apl = new AplicatieAWT("Prima aplicatie") ;
apl.resize(300, 300);
apl.show() ;
}
}
Pentru controlul i administrarea unei aplicaii putei folosi aproape oricare dintre metodele
nvate. Singurele metode care nu pot fi folosite sunt cele specifice applet-urilor (adic cele
definite n java.applet.Applet, cum ar fi cele pentru apelarea informaiilor de la diferite adrese
URL).
Este bine de cunoscut nc o diferen ntre aplicaii i applet-uri: atunci cnd tratai un
eveniment de nchidere a unei ferestre, n afar de ascunderea sau distrugerea ferestrei trebuie s
mai apelai i metoda System.exit(0), care indic sistemului c aplicaia dumneavoastr s-a
terminat.
public void nchidereFereastra(WindowEvent e) {
fr.hide() ;
fr.destroy() ;
System.exit(0) ;
numete ncapsulare (encapsulation): un obiect poate controla modul cum este vzut i cum se poate
interaciona cu el din exterior.
ncapsularea este procesul de prevenire a citirii sau a modificrii unor variabile aparinnd
unei clase de ctre alte clase. Singura metoda de folosire a acestor variabile este prin apelarea
metodelor clasei, dac acestea sunt disponibile. Limbajul Java ofer patru niveluri de control al
accesului: public, private, protected i un nivel special, care este specificat prin absena
modificatorului.
Accesul prestabilit
Pentru majoritatea exemplelor de pn acum nu s-a specificat nici un tip de control al
accesului. Variabilele sau metodele au fost declarate prin instruciuni de genul:
String nume = "Popescu Ion";
boolean este ( ) {
return true;
}
O variabil sau o metod declarat fr nici un modificator al accesului este disponibil
tuturor celorlalte clase dintr-un acelai pachet. Mai nainte ai putut vedea cum clasele i bibliotecile
Java sunt organizate n pachete (packages). Pachetul java. awt este unul dintre ele - un set de clase
cu comportament asemntor, care alctuiesc Abstract Windowing Toolkit.
Orice variabil declarat fr modificator poate fi citit sau modificat de orice clas care
face parte din acelai pachet. Orice metod declarat astfel poate fi apelat de orice clas din acelai
pachet. Alte clase nu pot accesa aceste elemente n nici un mod.
Acest nivel de control de fapt nu controleaz prea mult accesul. Atunci cnd vei analiza mai
bine modul cum vor fi folosite clasele dumneavoastr de alte clase, vei folosi n locul controlului
prestabilit al accesului unul dintre cei trei modificatori specializai.
Accesul privat
Pentru a ascunde complet o metod sau o variabil, n scopul de a nu fi folosit de nici o alt
clas, se folosete modificatorul private. In acest fel, metodele sau variabilele nu pot fi accesate
dect din clasa curent, unde sunt definite.
De exemplu, o variabil de instan privat poate fi utilizat de metodele din aceeai clas,
ns nu i de obiectele din alte clase. n acelai fel, metodele private pot fi accesate din clasa unde
sunt definite, ns nu i din altele. Aceast restricie afecteaz i motenirea: nici variabilele private
i nici metodele private nu pot fi motenite de subclase.
Variabilele private sunt foarte folositoare n dou cazuri:
Atunci cnd alte clase nu au nici un motiv s foloseasc variabila respectiv
Atunci cnd alt clasa poate produce dezastre dac variabila respectiv este folosit
necorespunztor.
De exemplu, s considerm o clas Java, denumit Bingo, care genereaz numere de bingo
pentru un site Internet de jocuri. Aceast clas conine o variabil denumit rataCastiguri, prin care
se poare controla numrul de ctiguri i de pierderi generate. Aceast variabil are un impact
deosebit asupra jocului. Dac ea ar putea fi modificat de alte clase, performana jocului s-ar putea
modifica substanial. Pentru a v proteja mpotriva unui astfel de scenariu, putei declara variabila
rataCastiguri drept private.
Folosirea modificatorului private reprezint principala metod pentru ncapsularea unui
obiect. Fr utilizarea acestuia pentru a ascunde variabile i metode, nu putei limita modul n care
este folosit o clas; accesul este liber la toate variabilele i metodele din cadrul clasei.
Accesul public
n unele cazuri vei avea nevoie ca o metod sau o variabil a clasei s fie disponibil complet
oricrei alte clase care dorete s o foloseasc. O astfel de variabil este variabila de clas black a
clasei Color. Aceast variabil este folosit atunci cnd o clas dorete s foloseasc culoarea
neagr, deci nu trebuie s existe nici o restricie de acces.
De obicei, variabilele de clas sunt declarate publice.
Modificatorul public face ca o metod sau o variabil s fie complet disponibil unei alte clase. Ai
folosit acest modificator n toate aplicaiile pe care le-ai scris pn acum, ca n instruciunea
urmtoare:
public static void main(String[ ] argumente) {
// ...
}
Metoda main ( ) a unei aplicaii trebuie s fie public. Altfel, ea nu poate fi apelat de
interpretorul java pentru a lansa n execuie clasa.
Datorit motenirii, toate variabilele i metodele publice ale unei clase sunt preluate i de
subclasele sale.
Accesul protejat
Al treilea nivel de control al accesului este limitarea vizibilitii unei metode sau variabile doar
pentru urmtoarele dou grupuri:
Subclasele unei clase
Alte clase din acelai pachet
Putei realiza acest lucru folosind modificatorul protected, ca n urmtorul exemplu:
protected boolean avemNevoieDeMaiMultaOdihna = true;
Acest nivel de control al accesului este folositor dac dorii implementarea unei subclase. Clasa
dumneavoastr poate conine o metod sau o variabil care s ajute i la realizarea sarcinilor
subclasei.
Deoarece o subclas motenete cea mai mare parte a comportamentului i atributelor, ea sar putea s aib cam aceleai sarcini de realizat.
Accesul protejat ofer subclasei ansa de a apela metoda sau variabila ajuttoare i, n acelai timp,
nu permite folosirea acestora de alte clase cu care nu are relaii de rudenie".
Compararea nivelurilor de control al accesului
Diferena dintre diferitele tipuri de protecii poate deveni puin neclar, mai ales n cazul
metodelor i variabilelor protejate. Tabelul urmtor, care prezint n rezumat ceea ce este permis i
unde, v ajut s v dai seama de diferenele existente ntre cea mai puin restrictiv form de
protecie (public) i cea mai restrictiv (private).
Vizibilitate
Din aceeai clas
Din orice clas care aparine aceluiai
pachet
Din orice clasa din afara pachetului
Dintr-o subclas a aceluiai pachet
Dintr-o subclas din afara pachetului
public
da
protected
da
default
da
private
da
da
da
da
nu
da
da
da
nu
da
da
nu
da
nu
nu
nu
nu
viteza de execuie. Aceast abordare elimin posibilitatea de a deriva mai trziu subclase, aa c
trebuie s v gndii bine nainte de a face aceast schimbare.
Biblioteca de clase Java declar multe dintre metodele mai des folosite drept final, aa nct
acestea pot fi executate rapid atunci cnd sunt apelate din programe.
Clase finale
Clasele sunt finalizate prin introducerea modificatorului final n declaraia acestora, ca n
exemplul:
public final class OAltaProblema {
// ...
}
Dintr-o clas final nu se pot deriva subclase. Ca i n cazul metodelor, acest proces aduce
unele avantaje legate de viteza de execuie.
Majoritatea claselor mai des folosite sunt finale, cum ar fi java. lang.String, java.lang.Math,
java.net. InetAddress. Dac dorii s creai o clas care s se comporte ca un ir, dar s aib unele
modificri, nu vei putea s o derivai din clasa String i s definii doar comportamentul diferit; va
trebui s o scriei de la zero.
Toate metodele dintr-o clas final sunt automat finale, deci nu va mai trebui s folosii acest
modificator n declaraiile lor.
Nu avei prea multe motive s v declarai propriile clase drept finale, deoarece clasele care
pot s-i pun la dispoziie metodele i atributele unor subclase sunt mult mai folositoare.
Pachete
Folosirea pachetelor
Ai folosit pachetele pe tot cuprinsul acestui curs: ori de cte ori ai folosit instruciunea
import sau ori de cte ori ai referit o clas prin denumirea sa complet (de exemplu,
java.awt.Color).
Pentru a folosi o clas coninut ntr-un pachet, putei folosi unul dintre urmtoarele trei
mecanisme:
Cnd clasa pe care dorii s o folosii se afl n pachetul java. lang (de exemplu, System
sau Date), o putei referi pur i simplu prin numele ei. Clasele din java. lang sunt automat
disponibile n toate programele.
Cnd clasa pe care dorii s o folosii se afla ntr-un alt pachet, putei sa o referii
folosindu-i numele complet, adic inclusiv pe cel al pachetului (de exemplu, java. awt. Font).
Pentru clasele pe care le folosii frecvent din alte pachete, putei importa clasele
individuale sau ntregul pachet de clase. Dup ce clasa sau pachetul au fost importate, putei s
referii clasa doar prin numele su.
Clasele care nu sunt declarate ca fcnd parte dintr-un anumit pachet sunt automat incluse
ntr-un pachet prestabilit. Aceste clase pot fi referite prin numele lor, de oriunde din cod.
Pentru a referi o clas dintr-un alt pachet, putei folosi numele ei complet: numele clasei,
precedat de toate numele pachetului. Pentru aceasta nu este nevoie s importai clasa sau pachetul:
java.awt.Font f = new java.awt.Font( );
Are sens sa folosii denumirea complet doar pentru clasele pe care le folosii o dat sau de
dou ori n cadrul programului. Dac folosii aceste clase de mai multe ori sau dac numele
pachetului este prea lung i conine mai multe subpachete, este mai bine s importai clasa
respectiv, pentru a economisi timpul pe care l-ai pierde cu tastarea.
Comanda import
Pentru a importa clasele dintr-un pachet se folosete comanda import, aa cum ai vzut n
toate exemplele prezentate n aceast carte. Putei importa o anumit clas, ca n exemplul urmtor:
import java.util.Vector;
Sau putei importa un ntreg pachet de clase, folosind simbolul asterisc (*) n locul numelor de
clas, astfel:
import java.awt .*;
Instruciunea import trebuie folosit n prima parte a definiiei clasei, nainte de orice alte
definiii (ns dup definiia pachetului).
Importarea unui grup de clase nu ncetinete programul i nici nu i mrete dimensiunile;
vor fi ncrcate doar clasele de care avei nevoie n codul dumneavoastr. Ins importarea unui
pachet ntreg face ca lucrurile s fie mai neclare pentru cei care citesc codul dumneavoastr, pentru
c nu se va ti de unde provin clasele folosite. Opiunea pentru importuri individuale sau n grup
depinde de stilul dumneavoastr de programare.
Conflicte de nume
Dup ce ai importat o clas sau un pachet de clase, putei s v referii la clas doar prin
numele sau, fr identificatorul de pachet. ntr-un singur caz va trebui s fii mai explicit: atunci
cnd avei mai multe clase cu acelai nume, care provin din pachete diferite.
Iat un exemplu: S presupunem c importai clase provenite din dou pachete diferite, aparinnd
unor programatori diferii :
import claseMihai.*;
import claseMarcel.*;
n cadrul pachetului lui Mihai se afl o clas denumit Vector. i n pachetul lui Marcel exist o
clas cu acelai nume, dar cu implementare i definiie total diferite. V vei ntreba acum care
dintre versiunile clasei este folosit atunci cnd facei n programul dumneavoastr o referire la
clasa Vector:
Vector vect = new Vector(10) ;
Rspunsul este nici una"; compilatorul Java va semnala un conflict de nume i va refuza s
compileze programul. In acest caz, chiar dac ai importat ambele clase, va trebui totui s v
referii la clasa dorit prin numele su complet, ca n exemplul:
claseMihai.Vector vect = new claseMihai.Vector(10);
folosete dou elemente: numele pachetului i directoarele referite de variabila de mediu CLASSPATH
(dac folosii un sistem Windows).
Numele pachetelor corespund unor nume de directoare ale sistemului de fiiere, deci clasa
java.applet.Applet se va gsi n directorul applet, care face parte i el din directorul java (este vorba
de java\applet\Applet. class).
Java caut aceste directoare, pe rnd, n cadrul directoarelor referite de variabila CLASSPATH,
dac aceasta este definit. Dac nu este configurat nici o variabil CLASSPATH, Java caut n
directorul prestabilit, java/lib, aflat n directorul cu versiunea JDK pe care o folosii, precum i n
directorul curent. Java caut n aceste directoare clasa referit n sursa dumneavoastr folosindu-se
de numele pachetului i al clasei, iar dac nu o gsete returneaz un mesaj de eroare. Majoritatea
erorilorde tip 'class not found' (clas inexistent) sunt cauzate de o configurare greit a variabilei
de mediu CLASSPATH .
15:
16:
17:
18:
19:
20:
21:
Nod(0bject o, Nod n)
continut = o;
urmatorul = n;
}
// ...
Clasa public ListaInlantuita ofer un set de metode publice (cum ar fi add ( ) ) altor clase
care ar avea nevoie s le foloseasc. Celelalte clase nu trebuie s tie de alte clase pe care
ListaInlantuita le folosete pentru a-i ndeplini sarcinile. Nod, una dintre aceste clase ajuttoare,
este declarata din acest motiv fr modificatorul public i deci nu va face parte din interfaa public
a pachetului colecie.
Faptul c Nod nu este o clas public nu nseamn c Listalnlantuita nu va mai avea acces la
ea dup ce este importat ntr-o alt clas. Atunci cnd importai i folosii clasa Listalnlantuita,
clasa Nod va fi, de asemenea, ncrcat n sistem, ns doar instanele clasei Listalnlantuita vor avea
permisiunea s o foloseasc.
Crearea unui pachet bine proiectat presupune definirea unui set mic de clase publice i de
metode care pot fi folosite de alte clase i implementarea lor folosind un numr de clase ajuttoare,
invizibile n exterior.
Interfee
Interfeele, ca i clasele sau metodele abstracte, ofer un model de comportament care se
presupune c va fi implementat de alte clase. Totui, interfeele ofer posibiliti mult mai mari
dect clasele i metodele abstracte, att pentru Java, ct i pentru proiectarea obiectelor i a claselor,
n general.
Problema unicei moteniri
Dup ce vei ctiga ceva mai mult experien n proiectare, va vei da seama c simplitatea
ierarhiei de clase Java este oarecum restrictiv, mai ales atunci cnd dorii s folosii unele metode
din clase aflate pe diferite ramuri" ale aceleiai ierarhii.
S lum un exemplu care va clarifica aceast problem. S presupunem c avei o ierarhie
de clase referitoare la biologie, pe primul nivel aflndu-se clasa Animal, iar mai jos, clasele
Mamifer i Pasare. Printre atributele clasei Mamifer se numr naterea de pui vii i existena
blnii. Clasa Pasare conine atribute cum ar fi depunerea de ou i existena ciocului. Dar cum vei
defini o clas pentru ornitorinc, care, se tie, are blan, cioc i depune ou? Pentru crearea clasei
Ornitorinc va trebui s combinai atributele din cele dou clase. Dar, deoarece clasele pot avea n
Java o singur superclas, acest tip de problem nu poate fi rezolvat prea elegant.
Alte limbaje OOP (orientate obiect) conin conceptul de motenire multipl, care rezolv
aceast problem. Dac se folosete motenirea multipl, o clas poate avea mai multe superclase,
mprumutnd atribute de la toate. Una dintre problemele motenirii multiple este aceea c limbajul
de programare devine mai dificil de nvat, de folosit i de implementat. Problemele legate de
apelarea metodelor i de modul de organizare a ierarhiei de clase devin mult mai complicate i este
mult mai probabil s produc ambiguiti i confuzii. Deoarece unul din scopurile limbajului Java
este simplitatea, s-a renunat la motenirea multipl n favoarea mai simplei moteniri unice.
Pentru rezolvarea acestor probleme Java conine o alt ierarhie, total separat de ierarhia principal,
care conine clase cu comportament combinat. Astfel, atunci cnd creai o nou clas, aceasta are o
singur superclas primar, ns poate alege i alte comportamente din cealalt ierarhie. Aceast
nou ierarhie se numete ierarhie de interfee. O interfa Java este o colecie de comportamente
abstracte, care pot fi combinate n orice clas pentru a introduce n acea clas comportamente care
nu pot fi motenite de la superclas. Tehnic, o interfa Java nu conine nimic altceva dect definiii
de metode abstracte i constante - fr variabile de instan sau implementri de metode.
Interfeele sunt implementate i folosite n biblioteca de clase Java ori de cte ori este nevoie
ca un anumit comportament s fie implementat n alte clase. Ierarhia de clase Java, de exemplu,
definete i folosete interfeele java.lang.Runnable, java.awt.image.ImageConsumer i java. awt.
image.ImageProducer.
Interfeele i clasele
Clasele i interfeele, chiar dac au definiii diferite, au foarte multe n comun. Interfeele, ca
i clasele, sunt declarate n fiiere surs, cte un fiier pentru fiecare interfa. Ca i clasele, acestea
sunt compilate n fiiere .class folosind compilatorul Java. i, n majoritatea cazurilor, oriunde se
poate folosi o clas (ca tip de dat pentru variabile, ca rezultat al unei conversii prin cast i aa mai
departe) se poate folosi i o interfa. Programatorii Java folosesc termenul clas" pentru a se referi
att la clase, ct i la interfee. Interfeele completeaz i extind puterea claselor i de aceea pot fi
tratate aproape n acelai fel. Una dintre puinele diferene existente ntre clase i interfee este aceea
c nu se poate obine o instan a unei interfee: operatorul new se folosete doar pentru crearea
de instane ale unei clase.
Implementarea i folosirea interfeelor
Cu interfeele putei face dou lucruri: s le folosii n clasele dumneavoastr sau s definii
unele proprii. S ncepem cu primul caz.
Pentru a folosi o interfa, trebuie folosit cuvntul cheie implements ca parte a definiiei clasei. Un
astfel de exemplu este cel care a fost prezentat ntr-unul dintre capitolele anterioare:
public class Neko extends java.applet.Applet implements Runnable
{
// . . .
}
n acest exemplu, java.applet.Applet este superclasa, ns interfaa Runnable extinde
comportamentul implementat de aceasta.
Deoarece interfeele nu ofer nimic altceva dect definiii abstracte de metode, va trebui s
implementai aceste metode n clasele dumneavoastr folosind semnturile de metode provenite din
interfa. Reinei c o dat inclus o interfa, va trebui s implementai toate metodele acesteia; nu
putei s alegei doar metodele de care avei nevoie. Prin implementarea unei interfee, nseamn c
declarai utilizatorilor clasei c vei suporta toate metodele acesteia. (Aceasta este o alt diferen
ntre interfee i clasele abstracte; subclasele claselor abstracte pot alege care dintre metode s fie
implementate sau suprascrise i s le ignore pe celelalte.)
Dup ce clasa pe care ai scris-o implementeaz o interfa, subclasele acesteia vor moteni
toate noile metode (care pot fi suprascrise sau suprancrcate) ca i cnd acestea ar fi fost definite n
superclas. Cnd o clas motenete o superclas care implementeaz o anumit interfa, nu mai
trebuie s folosii cuvntul cheie implements n definiia clasei respective.
S lum un exemplu simplu - crearea unei noi clase, denumit Portocala. S presupunem c
posedai deja o implementare bun a clasei Fruct i o interfa, ModelFruct, care reprezint ceea ce
un Fruct este capabil s fac. Dorii ca portocala s fie un fruct, ns dorii s fie i un obiect sferic
care s poate fi aruncat, rotit i aa mai departe. Iat cum se pot defini toate acestea:
interface ModelFruct {
void stricare ( );
void stoarcere ( );
// ...
}
class Fruct implements ModelFruct {
private Color culoareaMea;
private int zilePanaLaStricare;
//...
}
interface ModelSfera {
void aruncare ( );
void rotire ( );
// ...
}
class Portocala extends Fruct implements ModelSfera {
// aruncare ( ) poate sa provoace stoarcere ( )
// (caracteristici unice pentru clasa Portocala)
}
Remarcai c n clasa Portocala nu este nevoie s se implementeze interfaa ModelFruct, deoarece,
prin motenirea clasei Fruct, deja o implementeaz! Unul dintre avantajele acestei structuri este
acela c v putei rzgndi n privina clasei de unde se deriv clasa Portocala (de exemplu, dac
este implementat o clas mai bun, denumit Sfera) i totui clasa Portocala va nelege aceleai
dou interfee:
class Sfera implements ModelSfera {
// derivata direct din clasa Object
private float raza;
// .. .
}
class Portocala extends Sfera implements ModelFruct {
// ...utilizatorii clasei Portocala nu vor remarca aceasta
// modificare!
}
Implementarea unor interfee multiple
Spre deosebire de ierarhia de clase cu motenire unic n clasele dumneavoastr putei folosi oricte
interfee dorii; clasa rezultat va implementa comportamentul combinat: al tuturor interfeelor
incluse. Pentru a include mai multe interfee ntr-o clas, separai numele acestora prin virgule:
public class Neko extends java. applet. Applet
implements Runnable, Comestibil, Sortabil, Observable {
// ...
}
Reinei totui c folosirea unor interfee multiple poate da natere la complicaii. Ce se ntmpl
dac dou interfee definesc aceeai metod? Putei rezolva aceast problem n trei moduri:
Dac metoda are aceeai semntur n ambele interfee, implementai n clasa dumneavoastr o
metod a crei definiie satisface ambele interfee.
Dac metodele au liste de parametri diferite, vei avea o situaie de suprancrcare a metodelor;
implementai ambele metode, fiecare dintre definiii satisfcnd interfaa respectiv.
Dac ambele metode au aceeai list de parametri, ns returneaz tipuri diferite, nu vei putea
crea o metod care s le satisfac pe amndou (deoarece suprancrcarea metodelor ine cont doar
de lista de parametri, nu de tipul de retur). n acest caz, ncercarea de compilare a unei clase care
implementeaz ambele interfee va produce o eroare. Dac ajungei n aceast situaie, nseamn c
interfeele dumneavoastr au erori de proiectare i trebuie reanalizate.
Alte utilizri ale interfeelor
Aproape oriunde putei folosi o clas, putei folosi i o interfa. De exemplu, s declarm o variabil de tip
interfa:
S lum, de exemplu, interfaa ModelFruct, care definete metodele (fr parametri) stricare ( ) i
stoarcere ( ). Mai putei avea o metod, germinareSeminte ( ), care are un singur argument: fructul
nsui. De ce tip urmeaz s fie acest argument? Nu poate fi de tip Fruct, deoarece putei avea o
clas derivat din ModelFruct (deci care implementeaz interfaa ModelFruct) i care s nu fie, de
fapt, un fruct. Soluia este de a declara n interfa argumentul de tip ModelFruct:
public interface ModelFruct {
public germinareSeminte (ModelFruct fr) {
//
}
}
Apoi, n implementarea acestei metode ntr-o clas, putei converti prin cast argumentul
genericModelFruct n obiectul corespunztor:
public class Portocala extends Fruct {
public germinareSeminte(ModelFruct fr) {
Portocala oPortocala = (Portocala)fr;
// . . .
}
}
Derivarea interfeelor
Ca i n cazul claselor, interfeele pot fi organizate ntr-o ierarhie. Atunci cnd o interfa
motenete o alt interfa, subinterfaa" primete toate metodele i constantele definite n
superinterfa". Pentru a deriva (extinde) o interfa vei folosi cuvntul cheie extends, la fel ca n
cazul definiiilor claselor:
public interface ModelFruct extends ModelMancare {
// ...
}
Totui, spre deosebire de clase, ierarhia de interfee nu posed echivalentul unei clase Object;
aceast ierarhie nu are un vrf". Interfeele pot exista independent sau pot moteni o alt interfa.
De asemenea, spre deosebire de ierarhia de clase, ierarhia de interfee este una cu motenire
multipl. De exemplu, o singur interfa poate moteni oricte clase are nevoie (separate prin
virgul, n acea parte a definiiei care folosete cuvntul cheie extends); noua interfa va conine o
combinaie de metode i constante motenite de la prini". Iat definiia unei interfee care
motenete mai multe interfee:
public interface InterfataAglomerata extends Runnable, Crescator, ModelFruct, Observable {
// ...
}
n interfeele cu motenire multipl, regulile de gestionare a conflictelor ntre numele metodelor
sunt aceleai ca pentru clasele care folosesc mai multe interfee; metodele care difer numai prin
tipul de retur vor genera o eroare de compilare.
Clase interioare
Clasele cu care ai lucrat pn acum sunt toate membre ale unui pachet, fie c ai folosit
instruciunea package, urmat de numele unui pachet, fie c a fost folosit pachetul prestabilit.
Clasele care aparin unui pachet sunt cunoscute drept clase de nivel nalt (top-level classes). La
introducerea Java, acestea erau singurele clase suportate de limbaj.
ncepnd cu Java 1.1, putei defini o clasa n interiorul altei clase, ca i cnd ar fi o metod sau o
variabil. Astfel de clase se numesc clase interioare (inner classes). Listingul urmtor prezint
applet-ul Interior, care folosete o clas interioar, denumit ButonAlbastru pentru a reprezenta
butoanele care au culoarea de fundal albastr.
Textul complet al programului Interior.java.
1: import java.awt.Button;
2: import java.awt.Color;
3:
4: public class Interior extends java.applet.Applet {
5:
Button b1 = new Button ("0ne");
6:
ButonAlbastru b2 = new ButonAlbastru("Two");
7:
8:
public void init ( ) {
9:
add(b1);
10:
add(b2);
}
11:
12:
class ButonAlbastru extends Button {
13:
ButonAlbastru (String eticheta) {
14:
super(eticheta) {
15:
this .setBackground(Color.blue) ;
16:
}
17:
}
18: }
n acest exemplu, clasa ButonAlbastru nu este dect o clas ajuttoare inclus n acelai fiier surs
ca i clasa principal a programului. Singura diferen este c aceast clas ajuttoare este definit
n cadrul fiierului clas, ceea ce aduce cteva avantaje:
Clasele interioare sunt invizibile pentru alte clase, ceea ce nseamn c nu trebuie s v facei
probleme privind conflictele de nume cu alte clase.
Clasele interioare pot avea acces la variabilele i metodele din domeniul de vizibilitate al
clasei de nivel superior, lucru care nu ar fi fost valabil dac ar fi fost separate.
n majoritatea cazurilor, o clas interioar este o clas de dimensiuni reduse i cu un scop limitat. n
applet-ul Interior, deoarece clasa ButonAlbastru nu conine atribute sau metode complexe, este
indicat pentru a fi implementat drept clas interioar.
Numele clasei interioare este asociat cu numele clasei care o conine i este atribuit automat la
compilarea programului. n exemplul clasei ButonAlbastru, JDK i va atribui numele
Interior$ButonAlbastru.class.
Clasele interioare, chiar dac par c aduc mbuntiri minore limbajului Java, reprezint, de fapt, o
modificare semnificativ a limbajului.
Regulile care guverneaz domeniul de vizibilitate al unei clase interioare sunt aceleai care se aplic
i variabilelor. Numele unei clase interioare nu este vizibil n afara domeniului su, exceptnd cazul
cnd se folosete numele complet, lucru care ajut la structurarea claselor n cadrul pachetului.
Codul unei clase interioare poate folosi nume simple, din domeniile de vizibilitate pe care le
cuprinde, cum ar fi variabilele de clas i de instan ale claselor pe care le conine, precum i
variabilele locale din blocurile incluse.
n plus, putei defini o clas de nivel nalt ca membru static al unei alte clase de nivel nalt. Spre
deosebire de o clas interioar, o clas de nivel nalt nu poate folosi direct variabilele de instan ale
unei alte clase. Posibilitatea de a imbrica n acest fel clasele permite oricrei clase de nivel nalt s
ofere o organizare de tipul pachetelor pentru un grup de clase de nivel mai sczut, nrudite din punct
de vedere logic.
Exceptii Java
Pn n acest moment, este mai mult ca sigur c ai ntlnit cel puin o situaie de excepie Java - probabil
atunci cnd ai introdus greit numele unei metode sau ai fcut o greeal n cod care a dus la apariia unei probleme.
Error
Exception
IOException
RuntimeException
ClassNotFoundE
xception
AWTException
FileNotFound
Exception
EOFException
MalFormedURL
Exception
SocketException
Clasa Throwable are dou subclase: Error i Exception. Instanele clasei Error reprezint
erori interne ale mediului de lucru Java (maina virtual). Aceste erori sunt rare i, de obicei, fatale;
nu putei face mare lucru cu ele (nici s le interceptai i nici s le semnalai), exist pentru ca Java
s le poat folosi dac are nevoie de ele.
Subclasele Exception se mpart n dou grupuri:
Excepii de execuie (runtime), care sunt subclase ale clasei RuntimeException, cum ar fi
ArrayIndexOutofBounds, SecurityException sau NullPointerException
Alte excepii, cum ar fi EOFException sau MalformedURLException
Majoritatea claselor de excepie fac parte din pachetul java.lang (cum ar fi Throwable,
Exception sau RuntimeException). Celelalte pachete definesc i ele excepii, care pot fi folosite n
toat biblioteca de clase. De exemplu, pachetul java.io definete o clas de excepie generic,
denumit IOException, care nu este folosit doar n pachetul java.io, pentru excepiile de
intrare/ieire (EOFException, FileNotFoundException), ci i n clasele pachetului java.net, pentru
excepii de reea cum ar fi MalformedURLException.
Gestionarea excepiilor
Cu ct lucrai mai mult cu biblioteci Java, cu att mai mult crete posibilitatea de a ntlni o
eroare (o excepie!) de compilare, asemntoare acesteia:
Program.java:32: Exception java.lang.InterruptedException must be
caught or it must be declared in the throws clause of this method.
(Program.java:32: Excepia java.lang.InterruptedException trebuie interceptat sau trebuie declarat
n clauza throws a acestei metode.)
n Java, o metod poate indica tipurile de erori pe care le poate semnala. De exemplu,
metodele care citesc din fiiere pot semnala excepii IOException, deci aceste metode sunt
declarate cu un modificator special care indic potenialele erori. Atunci cnd folosii aceste metode
n programele dumneavoastr Java, trebuie s v protejai codul mpotriva acestor excepii. Aceast
regul este verificat chiar de compilator, n acelai fel n care verific i dac ai apelat metodele
cu numrul corespunztor de argumente sau dac ai atribuit variabilelor tipurile de date declarate.
De ce se face aceast verificare? Deoarece astfel programele dumneavoastr sunt mai puin
expuse erorilor fatale i terminrii anormale, pentru c tii dinainte ce tipuri de excepii pot fi
semnalate de metodele folosite n program. Nu trebuie s mai citii cu atenie documentaia sau
codul unui obiect pentru a v asigura c ai tratat toate potenialele probleme - Java face aceste
verificri n locul dumneavoastr. Pe de alt parte, dac definii metodele astfel nct s indice
excepiile pe care le pot semnala, Java poate avertiza utilizatorii acestor obiecte c trebuie s trateze
erorile respective.
Clauza finally
S presupunem c n codul dumneavoastr exist o anumit aciune care trebuie neaprat
executat, indiferent ce se ntmpl, indiferent dac excepia este semnalat sau nu. Acest lucru se
face, de obicei, pentru a elibera anumite resurse dup folosire, pentru a nchide un fiier dup
deschidere sau ceva de acest gen. Chiar dac putei introduce aceste aciuni att n cadrul unui bloc
catch, ct i n afara sa, aceasta nseamn o duplicare a codului n dou locuri diferite. n loc s
procedai astfel, introducei o copie a codului ntr-o poriune special a blocului try. . .catch,
denumit finally.
Urmtorul exemplu prezint modul cum este structurat un bloc try. . .catch . . . finally:
try {
citesteFisierText();
} catch (IOException e) {
// tratati erorile de intrare/iesire
} finally {
inchideFisierText() ;
}
Instruciunea finally este folositoare, de fapt, n afara excepiilor; putei, de asemenea, s o
folosii pentru executarea unui cod de reiniializare dup o instruciune return, break sau continue
din cadrul unui ciclu. n ultimul caz putei folosi o instruciune try doar cu blocul finally, fr
blocul catch.
Pentru a indica faptul c o metod poate semnala o excepie, vei folosi n definiia sa o
clauz special, denumit throws.
Clauza throws
Pentru a indica faptul c o poriune a unei metode poate semnala o excepie, este suficient s
adugai cuvntul cheie throws dup semntura metodei (nainte de acolada deschis) i s
specificai numele excepiilor pe care le poate semnala metoda dumneavoastr:
public boolean metodaMea(int x, int y) throws oExceptie {
// ...
}
Dac metoda dumneavoastr poate semnala mai multe tipuri de excepii, putei s le
specificai pe toate n clauza throws, separate prin virgule:
public boolean oAltaMetodaAMea(int x, int y)
throws oExceptie, oADouaExceptie, oATreiaExceptie {
// ...
}
La fel ca n cazul catch, putei folosi o superclas a unui grup de excepii pentru a indica faptul c metoda
dumneavoastr poate semnala oricare dintre subclasele acelei excepii:
}
Specificarea clauzei throws n definiia metodei dumneavoastr nu nseamn dect c
metoda poate semnala o excepie dac ceva merge prost, nu i c va face acest lucru. Clauza throws
ofer doar o informaie suplimentar referitoare la potenialele excepii i permite compilatorului
Java s se asigure c metoda este corect folosit de utilizatori.
Toate datele din Java sunt scrise sau citite folosind fluxuri. Fluxurile, aa cum le arat i denumirea, transport
ceva dintr-un loc n altul.
Un flux (stream) reprezint calea pe care o urmeaz datele ntr-un program. Un flux de
intrare transport datele de la surs la program, iar un flux de ieire transport datele din program
ctre o destinaie.
Exist dou tipuri de fluxuri: fluxuri de octei i fluxuri de caractere. Octeii pot pstra
valori ntregi din domeniul 0. . . 255. n acest format pot fi reprezentate o multitudine de date, cum
ar fi date numerice, programe executabile, comunicaii Internet sau cod Java (bytecode) - adic
fiierele clas care sunt executate pe o main virtual Java. De fapt, orice tip de date poate fi
reprezentat printr-o serie de octei.
Fluxurile de caractere reprezint un tip special de fluxuri de octei, care se folosesc numai
pentru datele de tip text (tipribile). Ele difer de fluxurile de octei prin faptul c setul de caractere
Java suport codificarea Unicode, un standard prin care se pot reprezenta mai multe caractere dect
dac s-ar folosi octei.
Toate datele de tip text, cum ar fi fiierele text, paginile Web sau alte formate de text,
trebuie s foloseasc fluxuri de caractere.
Folosirea unui flux
Indiferent dac folosii fluxuri de octei sau de caractere, procedura este asemntoare.
n cazul irurilor de intrare, prima etap const n crearea unui obiect asociat cu sursa de
date. De exemplu, dac sursa este un fiier de pe hard discul dumneavoastr, acestuia trebuie s i se
asocieze un obiect de tip FileInputStream.
Odat obinut obiectul asociat fluxului, putei citi informaii din acest flux folosind una
dintre metodele obiectului. Clasa FileInputStream posed o metod read(), care returneaz un
octet citit din fiier.
Atunci cnd ai terminat de citit informaia din flux, trebuie s apelai metoda close(), pentru
a indica faptul c ai terminat de folosit fluxul.
n cazul fluxurilor de ieire, vei ncepe prin a crea un obiect asociat cu destinaia datelor.
Un astfel de obiect poate fi creat pornind de la clasa BufferedReader, care constituie o metod
eficient de creare a fiierelor text.
Metoda write() reprezint cea mai simpl metod de a transmite informaii ctre destinaia
unui flux. De exemplu, metoda write() aparinnd dasei BufferedReader poate transmite caractere
individuale unui flux de ieire.
Ca i n cazul fluxurilor de intrare, pentru un flux de ieire trebuie apelat metoda close ()
atunci cnd nu mai exist date de transmis.
Filtrarea unui flux
Cea mai simpl metod de a folosi un flux este de a l crea i de a-i apela metodele de
transmitere sau de recepie a datelor, n funcie de rolul lui (flux de intrare sau flux de ieire).
Majoritatea claselor folosite n prezent permit obinerea unor rezultate mai sofisticate prin
asocierea fluxului cu un filtru, nainte de a citi sau scrie date.
Un filtru este un tip de flux care schimb modul n care se lucreaz cu un flux existent.
Procedura de folosire a unui filtru pentru un flux presupune urmtoarele:
Crearea unui flux asociat cu sursa de date sau cu destinaia datelor.
Asocierea unui filtru cu acest flux.
Citirea i scrierea datelor de la/n filtru, i nu direct n flux.
Metodele pe care le apelai n cazul filtrelor sunt aceleai cu cele pe care le apelai n cadrul
fluxurilor: exist metodele read () i write (), asemntoare celor ale unui flux nefiltrat.
Putei chiar s asociai un filtru unui alt filtru, crend situaii de genul: un flux de intrare este
asociat unui fiier text, este trecut printr-un filtru de traducere romno-englez i, n final, este trimis
la destinaie - o persoan care dorete s l citeasc.
Fluxuri de octei
Toate fluxurile de octei sunt subclase ale InputStream sau OutputStream. Aceste clase
sunt abstracte, deci nu putei obine un flux prin crearea de obiecte direct din aceste clase. n
schimb, putei crea fluxuri prin folosirea unor subclase ale acestora, cum ar fi:
FileInputStream i FileOutputStream-Octei stocai n fiiere pe disc, pe CD-ROM sau pe
alte dispozitive de stocare.
DataInputStream i DataOutputStream - Un flux de octei filtrat, din care pot fi citite date
de tip ntreg sau n virgul mobil (float). InputStream este superclasa tuturor fluxurilor de intrare.
Fluxuri de fiiere
Fluxurile de octei cu care vei lucra de obicei sunt fluxuri de fiiere folosite pentru
transferul de date ntre program i fiierele aflate pe hard discuri, pe CD-ROM sau pe alte
dispozitive de stocare ce pot fi referite printr-o cale de director i un nume.
Putei transmite octei unui flux de ieire i putei citi octei dintr-un flux de intrare.
Fluxuri de intrare din fiiere
Spre deosebire de alte metode read (), aceasta nu retumeaz date din flux, ci un ntreg care
reprezint numrul de octei citii sau -1 dac nu s-au citit octei i s-a ajuns la sfritul fluxului.
Urmtoarele instruciuni folosesc un ciclu while pentru a citi datele din obiectul df de tip
FileInputStream:
int octetNou = 0;
while (octetNou != -1) {
octetNou = df.read();
System.out.println(octetNou +" );
}
Aceast bucl citete ntregul fiier referit de obiectul df, cte un octet o dat, i afieaz valoarea
fiecrui octet, urmat de un spaiu. De asemenea, cnd se ajunge la sfritul fiierului va fi afiat
valoarea -1, lucru pe care l putei evita folosind un test if.
Fluxuri de ieire n fiiere
Un flux de ieire n fiier poate fi creat folosind constructorul FileOutputStream (String).
Utilizarea sa este identic cu cea a constructorului FileInputStream (String), deci putei specifica
i calea pn la fiier, nu numai numele acestuia.
Trebuie s avei grij atunci cnd specificai fiierul n care scriei. Dac folosii numele unui fiier deja existent, o dat
cu nceperea scrierii datelor, acesta va fi ters definitiv.
Putei crea un flux de ieire n fiier care s adauge date (append) la sfritul unui fiier existent
folosind constructorul FileOutputStream(String, boolean). irul specific numele fiierului, iar
argumentul boolean, dac are valoarea true, va aduga datele la sfritul fiierului, n loc s
suprascrie datele existente.
Pentru a scrie octei ntr-un fiier se folosete metoda write ( int) a fluxului de ieire. Dup ce s-a
scris ultimul octet, fluxul trebuie nchis folosind metoda close ().
Pentru a scrie mai muli octei se poate folosi metoda write(byte[], int, int), care funcioneaz
similar metodei read (byte[], int, int) descris anterior. Argumentele acestei metode sunt tabloul
care conine octeii ce vor fi scrii, poziia de nceput din tablou i numrul de octei ce trebuie
scrii.
Filtrarea fluxurilor
Fluxurile filtrate sunt fluxuri care modific informaia trimis printr-un flux existent.
Acestea sunt create folosind subclase ale FilterInputStream sau FilterOutputStream.
Aceste filtre nu realizeaz singure nici un fel de operaie de filtrare. De fapt, ele posed subclase, cum ar fi
BufferInputStream sau DataOutputStream, care sunt folosite pentru anumite tipuri de filtrri.
Filtre de octeti
Informaia este furnizat mai rapid dac poate fi transmis n blocuri de date mai mari, chiar
dac aceste blocuri sunt recepionate mai repede dect pot fi procesate.
Un tampon (buffer) reprezint o zon n care se pot pstra date nainte de a fi nevoie s fie
citite sau scrise de un program. Prin folosirea unui tampon putei avea acces la date fr s accesai
din nou sursa original de date.
Fluxuri cu tampon
Un flux de intrare cu tampon umple un tampon cu date care nu au fost nc procesate; cnd
programul are nevoie de aceste date, le caut n zona tampon nainte de a apela fluxul surs original.
Aceast tehnic este mai eficient. Aceast descongestionare a fluxului nu face altceva dect s
Putei, de asemenea, folosi metoda read(byte [] , int, int), care este disponibil i pentru alte fluxuri
de intrare, caz n care datele sunt ncrcate ntr-un tablou de octei.
Un flux de ieire cu tampon este creat prin folosirea urmtorilor constructori:
Dac trebuie s lucrai cu date care nu sunt reprezentate drept octei sau caractere, putei
folosi fluxuri de date de intrare i de ieire. Aceste fluxuri filtreaz un flux de octei existent astfel
nct urmtoarele tipuri de date s poat fi citite direct din flux: boolean, byte, double, float, int,
long i short.
Un flux de date de intrare este creat folosind constructorul DataInputStream (InputStream).
Argumentul trebuie s fie un flux de intrare existent, de exemplu, un flux de intrare cu tampon sau
un flux de intrare din fiier. Reciproc, un flux de date de ieire necesit utilizarea constructorului
DataOutputStream (OutputStream), care folosete ca argument fluxul de ieire asociat.
Urmtoarea list prezint metodele de citire i de scriere ce pot fi folosite pentru fluxurile de date de
intrare, respectiv de ieire:
readBoolean(), writeBoolean(boolean)
readByte(), writeByte (int)
readDouble(), writeDouble(double)
:
readFloat(), writeFloat(float)
readInt(), writeInt(int)
readLong(), writeLong(long)
readShort(), writeShort(int)
Fiecare dintre metodele de intrare returneaz tipul de dat primitiv indicat de numele metodei. De
exemplu, metoda readFloat () retumeaz o valoare float.
Exist i metodele readUnsignedByte () i readUnsignedShort (), care pot citi valori de tip octet
sau ntregi scuri fr semn. Aceste tipuri de date nu sunt suportate n Java, deci vor fi retumate ca
valori ntregi.
Octeii fr semn iau valori de la 0 la 255. Aceasta difer de tipul de variabil byte din Java, care ia valori ntre -128 i
127. n acelai fel, o variabil ntreag scurt fr semn ia valori ntre 0 i 65535, n loc de domeniul -32768 i 32767,
suportat de tipul short n Java.
Nu toate metodele de citire dintr-un flux de date de intrare retumeaz o valoare ce poate indica
faptul c s-a ajuns la sfritul fluxului. V mai putei atepta la apariia excepiei EOFException
care este semnalat la atingerea sfritului unui flux. Ciclul n care se citesc date poate fi ncadrat
ntr-un bloc try, iar instruciunea catch asociat trebuie s trateze doar excepiile EOFException.
In cadrul blocului catch putei s apelai i metoda close () i s efectuai alte aciuni de
reiniializare.
Fluxuri de caractere
Aceste fluxuri se folosesc pentru lucrul cu orice text reprezentat n format ASCII sau
Unicode .
Clasele folosite pentru a citi i scrie aceste fluxuri sunt subclase ale daselor Reader i
Writer. Este indicat s folosii aceste clase pentru lucrul cu text, i nu fluxuri de octei.
Tehnicile pentru lucrul cu fluxuri de caractere s-au mbuntit considerabil n versiunile
ulterioare Java 1.02, o dat cu introducerea claselor Reader i Writer i a subclaselor acestora; ele
ofer suport pentru setul de caractere Unicode i permit o manevrare mai uoar a textelor. Un
applet java compatibil cu versiunea 1.02 poate citi caracterele folosind clasele pentru fluxuri de
octei descrise anterior.
Citirea fiierelor text
Principala clas folosit pentru citirea de fluxuri de caractere dintr-un fiier este FileReader.
Aceast clas motenete clasa InputStreamReader, care citete un flux de octei i i convertete
n valorile ntregi corespunztoare caracterelor Unicode.
Un flux de intrare de caractere este asociat unui fiier folosind constructorul FileReader (String).
irul reprezint numele fiierului i poate conine i calea pn la acesta.
Urmtoarea instruciune creeaz un obiect FileReader denumit web i l asociaz cu fiierul text
denumit index. html:
FileReader web = new FileReader("index.html);
Dup ce ai obinut un obiect de acest tip, putei s apelai urmtoarele metode de citire a
caracterelor din fiier:
read () returneaz urmtorul caracter din flux, ca valoare ntreag
read (char [ ], int, int) citete caractere ntr-un tablou i primete ca argumente tabloul de
caractere, poziia de ncepere i numrul de caractere de citit. A doua metod funcioneaz
asemntor echivalentului su din clasele de fluxuri de intrare de octei. n loc s returneze
caracterul urmtor din flux, aceasta returneaz fie numrul de caractere citite, fie -1 dac s-a ajuns
la sfritul fluxului i nu s-a citit nimic.
Urmtoarea metod ncarc un fiier text folosind obiectul FileReader i afieaz caracterele
coninute de acesta:
FileReader text = new FileReader("readme.txt");
int octetCitit;
do {
octetCitit = text.read();
if (octetCitit != -1)
System.out.print( (char)octetCitit) ;
} while (octetCitit != -1) ;
System.out.println(" ");
text.close() ;
Deoarece metoda read () a unui flux de caractere returneaz o valoare ntreag, trebuie s convertii
prin cast aceast valoare nainte de a o afia, de a o salva ntr-un tablou sau de a o folosi ntr-un ir.
Fiecare caracter posed un cod numeric care reprezint poziia sa n setul de caractere Unicode.
Valoarea ntreag citit din flux reprezint chiar acest cod numeric. Dac dorii s citii din fiier o
ntreag linie de text, i nu caracter cu caracter, putei folosi o combinaie a daselor FileReader i
BufferedReader.
Clasa BufferedReader citete un caracter din fluxul de intrare i l memoreaz ntr-o zon tampon,
pentru mai mult eficien. Pentru a crea o versiune care folosete tampon, trebuie s existe un
obiect de tip Reader. Pentru crearea obiectului BufferedReader se pot folosi urmtorii
constructori:
BufferedReader(Reader)
Creeaz un flux de caractere cu zon tampon, asociat obiectului
Reader specificat (de exemplu FileReader).
BufferedReader (Reader, int) Creeaz un flux de caractere asodat obiectului Reader, cu o zon
tampon de dimensiunea specificat de argumentul ntreg.
Dintr-un flux de caractere cu tampon se poate citi folosind metodele read () i read(char[ ] , int,
int), asemntoare celor descrise pentru FileReader. Putei citi o ntreag linie de text folosind
metoda readLine ().
Metoda readLine () returneaz un obiect String care conine urmtoarea linie de text din flux, fr a
include i caracterul (sau caracterele) care reprezint sfritul de linie. Dac se ajunge la sfritul
fluxului, valoarea irului returnat va fi null.
Sfritul de linie este indicat astfel:
Clasa FileWriter este folosit pentru scrierea unui flux de caractere ntr-un fiier. Aceasta
este o subclas a OutputStreamWriter, care are rolul de a converti codurile caracterelor Unicode
n octei.
Exist doi constructori FileWriter: FileWriter (String) i FileWriter (String, boolean).
irul din primul argument reprezint numele fiierului ctre care va fi direcionat fluxul de caractere
i poate conine i calea. Argumentul opional de tip boolean trebuie s ia valoarea true dac se
dorete ca datele s fie adugate la sfritul unui fiier existent. Ca i n cazul altor clase de scriere
n fluxuri, trebuie s avei grij s nu suprascriei accidental un fiier existent.
Clasa FileWriter conine trei metode ce pot fi folosite pentru a scrie date ntr-un flux:
write(int)
Scrie un caracter.
write(char [], int, int)
Scrie caracterele din tabloul specificat, ncepnd de la poziia dat i
avnd numrul de caractere dat.
write(String, int, int)
Scrie caractere din irul specificat, ncepnd de la poziia dat i avnd
numrul de caractere dat.
Urmtorul exemplu scrie un flux de caractere ntr-un fiier folosind clasa FileWriter i metoda
write (int):
FileWriter litere = new FileWriter("alfabet.txt");
for (int i = 65; i < 91; i++) litere.write((char)i) ;
litere.close() ;
Metoda close () este folosit pentru nchiderea fluxului, dup ce toate caracterele au fost trimise n
fiierul destinaie. lat coninutul fiierului alfabet.txt produs de acest cod:
ABCDEFGHIJKLMNOPQRSTUVXYZ
Clasa BufferedWriter poate fi folosit pentru scrierea ntr-un flux de caractere cu zon tampon.
Obiectele acestei clase sunt create folosind constructorul BufferedWriter (Writer) sau
BufferedWriter (Writer, int). Argumentul Writer poate fi oricare dintre clasele de fluxuri de
caractere de ieire, cum ar fi FileWriter. Al doilea argument, opional, este o valoare ntreag ce
indic dimensiunea zonei tampon care va fi folosit.
BufferedWriter posed aceleai trei metode de ieire ca i FileWriter: write(int),
write(char[], int, int) i write(String, int, int).
0 alt metod folositoare este newLine (), care trimite caracterul (sau caracterele) ce specific
sfritul liniei pe platforma folosit pentru rularea programului.
Diferitele caractere de sfrit de linie pot crea neplceri la transferul unui fiier de pe un sistem de
operare pe altul, cum ar fi cazul cnd un utilizator Windows 95 copiaz un fiier pe un server Web
care folosete sistemul de operare Linux. Folosind metoda newLine() n loc de un literal (cum ar fi
'\n'), putei utiliza programul dumneavoastr pe diferite platforme.
Metoda close () este apelat pentru a nchide fluxul de caractere de ieire i pentru a asigura c toate
datele memorate n zona tampon au fost trimise ctre destinaia fluxului.
Fiecare dintre aceste metode va semnala o excepie SecurityException dac programul nu are
permisiunile necesare pentru executarea operaiilor respective, deci trebuie folosite blocuri try. . .
catch sau clauze throws pentru a trata aceste excepii.
Swing, care face parte din biblioteca JFC (Java Foundation Classes), reprezint o extensie
a pachetului AWT (Abstract Windowing Toolkit), care a fost integrat ncepnd cu versiunea 2 a
Java.
Swing ofer o funcionare mbuntit fa de predecesorul sau - noi componente, funcii
avansate ale acestora, o mai bun tratare a evenimentelor, precum i un aspect adaptabil.
Toate elementele Swing fac parte din pachetul javax.swing. Pentru a folosi o clas Swing,
trebuie s folosii fie o instruciune import explicit, fie una general, cum ar fi urmtoarea:
import javax.swing.* ;
Procesul de folosire a unei componente Swing nu este diferit de cel al folosiri
componentelor AWT. Vei crea componenta apelnd constructorul su, apelnd, dac este nevoie,
metodele componentei i apoi adugnd componenta ntr-un container.
Toate componentele Swing sunt subclase ale clasei JComponent.
Lucrul cu Swing
Exist componente Swing echivalente pentru toate componentele AWT pe care le-ai
nvat pn acum. n majoritatea cazurilor, constructorii componentelor Swing sunt similari
Etichete
Etichetele sunt implementate n Swing folosind clasa JLabel.
Caracteristicile sunt asemntoare cu ale etichetelor AWT, ns acum putei include i
pictograme. n plus, alinierea unei etichete poate fi specificat folosind una din cele trei variabile
ale clasei
SwingConstants: LEFT, CENTER sau RIGHT.
Iat cteva metode constructor ce pot fi folosite:
JLabel(String,int)
Creeaz o etichet cu irul i alinierea specificate.
JLabel(String,Icon,int)
Creeaz o etichet cu textul, pictograma i alinierea
specificate.
Butoane
Butoanele Swing sunt descrise n clasa JButton. Ele pot folosi o etichet de text (la fel ca
butoanele AWT), o etichet pictogram sau o combinaie a acestora.
lat cteva dintre metodele constructor ce pot fi folosite:
JButton (String)
Creeaz un buton cu textul specificat.
JButton (Icon)
Creeaz un buton cu pictograma specificat.
JButton (String, Icon)
Creeaz un buton cu textul i pictograma specificate.
Cmpuri de text
Cmpurile de text sunt implementate n Swing folosind clasa JTextField. Diferena dintre
aceste cmpuri text i echivalentul lor AWT este c metoda setEchoChar(char) nu mai este
suportat de JTextField pentru mascarea textului introdus.
lat ce metode constructor putei folosi:
JTextField(int)
Creeaz un cmp de text cu limea specificat.
JTextField(String, int)
Creeaz un cmp de text cu textul i limea specificate.
Pentru crearea unui cmp de text care folosete caractere de mascare se folosete clasa
JPasswordField. Aceast clas posed aceleai metode constructor ca i JTextField:
JPasswordField(int) i JPasswordField(String, int).
O dat creat cmpul de text pentru parole, putei folosi metoda setEchoChar(char) pentru a masca
datele de intrare cu caracterul specificat.
Zone de text
Zonele de text sunt implementate n Swing folosind clasa JTextArea. Aceasta folosete
urmtoarele metode constructor;
JTextArea (int, int) Creeaz o zona de text cu numrul de rnduri i de coloane specificat.
JTextArea (String, int, int) Creeaz o zon de text cu textul, numrul de rnduri i de
coloane specificate.
Liste de opiuni
Listele de opiuni, care n AWT erau create folosind clasa Choice, sunt disponibile acum
prin intermediul clasei JComboBox.
O list de opiuni este creat parcurgnd urmtoarele etape:
1. Se folosete constructorul JComboBox() fr nici un argument.
2. Se folosete metoda addItem(Obiect) a casetei combo pentru a aduga elemente n list.
3. Se folosete metoda setEditable(boolean) a casetei combo, cu argumentul avnd
valoarea false.
Aceast ultim metod transform caseta combo ntr-o list de opiuni - singurele opiuni
disponibile pentru utilizator sunt elementele coninute de list.
Cnd caseta combo este editabil permite introducerea de text din partea utilizatorului, n locul
alegerii unei opiuni din list. De la aceast combinaie provine i numele casetei (combo).
Bare de derulare
Barele de derulare sunt implementate n Swing folosind clasa JScrollBar. Funcionarea
acestora este identic cu cea a barelor de derulare AWT; putei folosi urmtoarele metode
constructor:
JScrollBar(int)
Creeaz o bar de derulare cu orientarea specificat.
JScrollBar(int, int, int, int, int) Creeaz o bar de derulare cu orientarea, valoarea
iniial, dimensiunea casetei de derulare, valoarea minim i valoarea maxim specificate.
Orientarea este specificat prin variabilele clasei SwingConstants, HORIZONTAL sau
VERTICAL.
Stabilirea aspectului
Swing posed un administrator de interfa care controleaz aspectul componentelor - modul
n care butoanele, etichetele i celelalte elemente sunt reprezentate pe ecran.
Administrarea aspectului este sarcina clasei UIManager, care face parte din pachetul
javax.swing.*. Opiunile pentru aspect difer n funcie de mediul de dezvoltare folosit. In Java 2
sunt disponibile urmtoarele opiuni:
Un aspect caracteristic Windows 95 sau Windows NT
Un aspect caracteristic sistemului Motif X-Window
Metal, un nou aspect Swing, independent de platform
Clasa UIManager posed metoda setLookAndFeel(LookAndFeel), care este folosit
pentru alegerea aspectului unui program.
Pentru a obine un obiect LookAndFeel care poate fi transmis ca argument metodei
setLookAndFeel() putei folosi una dintre metodele UIManager:
getCrossPlatformLookAndFeelClassName()
Aceast metod returneaz un obiect
LookAndFeel care reprezint aspectul Metal, independent de platform.
getSystemLookAndFeelClassName()
Aceast metod returneaz un obiect
LookAndFeel care reprezint un obiect caracteristic sistemului.
Daca nu poate stabili aspectul interfeei, metoda setLookAndFeel() semnaleaz o excepie
UnsupportedLookAndFeel.
Urmtoarele instruciuni pot fi folosite pentru a stabili un aspect Metal n orice program:
try {
UIManager.setLookAndFeel(
UIManager.getCrossPlatformLookAndFeelClassName ()) ;
} catch (Exception e) {
O alt metod de a face mai accesibil o interfa este de a oferi o descriere text pentru
componentele Swing. Aceast tehnic presupune dou etape:
ConfirmDialog
O caset de dialog care pune o ntrebare i posed trei
butoane, corespunztoare rspunsurilor Yes, No i Cancel.
InputDialog
O caset de dialog care ateapt introducerea unui text.
MessageDialog
O caset de dialog care afieaz un mesaj.
OptionDialog
O caset de dialog care cuprinde toate celelalte trei tipuri.
Fiecare dintre aceste casete de dialog posed propria metod n cadrul clasei
JOptionPane.
Al doilea argument poate fi un ir, o component sau o pictogram. Dac este un ir de text,
acesta va fi afiat n cadrul casetei de dialog. Dac este o alt component sau o pictograma, n locul
mesajului text va fi afiat obiectul respectiv.
Aceast metod returneaz una dintre cele trei valori posibile, reprezentate prin ntregi, care
sunt variabile de clas ale JOptionPane: YES_OPTION, NO_OPTION sau CANCEL_OPTION.
n continuare se prezint un exemplu care folosete o caset de dialog de confirmare cu un
mesaj text i memoreaz rspunsul n variabila raspuns:
int raspuns;
raspuns = JOptionPane.showConfirmDialog(null, "Pot sa sterg
toate fisierele dumneavoastra personale confidentiale?);
Exist o alt metod ce ofer mai multe opiuni pentru dialogul de confirmare:
showConfirmDialog(Component, Object, String, int, int). Primele dou argumente sunt
aceleai ca pentru cealalt metod, iar ultimele trei sunt urmtoarele:
Un ntreg care indic ce butoane vor fi afiate. Acesta trebuie s aib valoarea egal
cu una dintre variabilele de clas YES_NO_CANCEL_OPTION sau YES_NO_OPTION.
Una din cele cinci variabile de clas care descriu tipul casetei de dialog:
ERROR_MESSAGE, INFORMATION_MESSAGE, PLAIN_MESSAGE,
QUESTION_MESSAGE sau WARNING_MESSAGE.
Urmtoarea instruciune creeaz o caseta de dialog de intrare folosind aceast metod:
String raspuns=JOptionPane.showInputDialog(null, "Care este codul
dunineavoastra postal?", "Introduceti codul postal,
JOptionPane.QUESTION_MESSAGE);
Swing trateaz evenimentele n mod diferit, folosind un set de clase denumite interceptoare
de evenimente (event listeners).
Evenimentul principal
n sistemul de tratare a evenimentelor, evenimentele erau prelucrate prin intermediul unui
set de metode disponibile tuturor componentelor. Metode cum ar fi mouseDown(), keyDown() sau
action() puteau fi suprascrise de orice program AWT care dorea s trateze aceste evenimente.
Aceste sistem de tratare a evenimentelor este caracteristic doar Java 1.02, deoarece n urmtoarele
versiuni ale limbajului a fost introdus o versiune mult mbuntit a acestuia.
Interceptoare de evenimente
Dac o clas dorete s rspund unui eveniment utilizator conform sistemului Java 2 de
tratare a evenimentelor, ea trebuie s implementeze o interfa care s prelucreze evenimentele.
Aceste interfee se numesc interceptoare de evenimente (event listeners).
Fiecare interceptor trateaz un anumit tip de eveniment, iar o clas poate implementa oricte
evenimente are nevoie.
Sunt disponibile urmtoarele interceptoare de evenimente:
ActionListener
Trateaz evenimente de aciune, care sunt generate de aciunea unui
utilizator asupra unei componente cum ar fi execuia unui clic pe un buton.
AdjustmentListener
Trateaz evenimente de modificare, care sunt generate de
modificarea unei componente, cum ar fi deplasarea unei bare de derulare,
FocusListener
Trateaz evenimente de selecionare, care sunt generate atunci cnd o
component, cum ar fi un cmp de text, devine selectat sau pierde acest atribut.
ItemListener
Trateaz evenimente de element, care sunt generate atund cnd este
modificat starea unui element cum ar fi o caset de validare.
KeyListener Trateaz evenimente de tastatur, care apar atunci cnd un utilizator
introduce date prin intermediul tastaturii.
MouseListener
Trateaz evenimente de mouse, care sunt generate de clicuri cu
mouse-ul, de ptrunderea indicatorului mouse-ului pe suprafaa unei componente sau de prsirea
acesteia.
MouseMotionListener
Trateaz evenimente de deplasare a mouse-ului, care sunt
folosite pentru a memora toate micarile mouse-ului pe o componenta.
WindowListener Trateaz evenimente de ferestre, care sunt generate de maximizarea,
minimizarea, mutarea sau nchiderea ferestrelor.
Urmtoarea clas este declarat astfel nct s poat trata att evenimentele de aciune, ct i
pe cele de text;
public class Test extends JFrame implements ActionListener,
TextListener {
// . . .
}
Pacherul java.awt.event conine toate interceptoarele principale de evenimente, precum i
pe cele asociate unor evenimente specifice. Pentru a folosi aceste clase n programele
dumneavoastr putei s le importai individual sau s folosii o instruciune de tipul:
import java.awt.event.*;
Configurarea componentelor
Prin definirea unei clase ca interceptor de evenimente ai stabilit faptul c aceasta poate asculta"
(intercepta) un anumit tip de eveniment. Totui nu se va ntmpla nimic dac nu continuai cu un al doilea
pas: trebuie s asociai componentei un interceptor de acelai tip; la folosirea componentei, acesta va
genera evenimentele respective.
Dup crearea unei componente, pentru a o asocia cu un anumit tip de interceptor putei apela
una din urmtoarele metode:
addActionListener() Pentru componente JButton, JCheckBox, JComboBox,
JTextField i JRadioButton
addAdjustmentListener() Pentru componente JScrollBar
addFocusListener() Pentru toate componentele Swing
addItemListener() Pentru componente JButton, JCheckBox, JComboBox i
JRadioButton
addKeyListener() Pentru toate componentele Swing
addMouseListener()
Pentru toate componentele Swing
addMouseMotionListener()
Pentru toate componentele Swing
addWindowListener()
Pentru toate componentele JWindow i JFrame
O greeal des ntlnit n programele Java o constituie modificarea unei componente dup
introducerea acesteia ntr-un container. Metodele de interceptare i celelalte configurri trebuie
stabilite pentru o component nainte de a o aduga ntr-un container; altfel toate acestea vor fi
ignorate la execuia programului.
Urmtorul exemplu creeaz un obiect JButton i i asociaz un interceptor de evenimente de
aciune:
sorteazaInregistrari() ;
Acest exemplu apeleaz metoda terminareProgram() n cazul cnd evenimentul a fost
generat de obiectul butonTerminare sau metoda sortareInregistrari() dac evenimentul a fost
generat de obiectul sortareInregistrari.
Multe metode de tratare a evenimentelor apeleaz metode diferite pentru fiecare tip de
eveniment sau de component. Aceasta face ca metoda de tratare a evenimentelor s fie uor de
citit. n plus, dac o clas conine mai multe metode de tratare a evenimentelor, fiecare poate apela
aceleai metode pentru realizarea sarcinii dorite.
O alt tehnic util n cadrul unei metode de tratare a evenimentelor o constituie folosirea
operatorului instanceof, care permite testarea fiecrui tip de component care putea genera
evenimentul. Urmtorul exemplu poate fi folosit ntr-un program care conine un buton i un cmp
de text, fiecare dintre acestea genernd evenimente de aciune:
void actionPerformed(ActionEvent evt) {
Object sursa = evt.getSource() ;
if (sursa instanceof JTextField)
calculeazaScor() ;
else if (sursa instanceof JButton)
terminaProgram() ;
}
Evenimente de actiune
Evenimentele de aciune apar atunci cnd utilizatorul realizeaz o aciune asupra unui obiect
de tip JButton, JCheckBox, JTextField sau JRadioButton.
Pentru a trata aceste evenimente, o clas trebuie s implementeze interfaa ActionListener.
n plus, trebuie apelat metoda addActionListener() pentru fiecare component care urmeaz s
genereze evenimente de aciune, cu excepia cazurilor n care dorii s ignorai evenimentele de
aciune ale unei componente.
Interfaa ActionListener conine o singur metod: actionPerformed(ActionEvent) care
are urmtoarea form:
public void actionPerformed(ActionEvent evt) {
// ...
}
n afar de metoda getSource(), putei folosi metoda getActionCommand() cu argumentul
ActionEvent, pentru a afla mai multe informaii despre sursa evenimentului.
Evenimente de modificare
Evenimentele de modificare (ajustare) apar atund cnd o component JScrollBar este
deplasat folosind sgeile, caseta de derulare sau printr-un clic undeva pe bar. Pentru a trata aceste
evenimente, o clas trebuie s implementeze interfaa AdjustmentListener.
Interfaa AdjustmentListener conine o singur metod, care are urmtoarea form:
adjustmentValueChanged(AdjustmentEvent evt) {
// ...
}
Pentru a obine valoarea curent a obiectului JScrollBar putei folosi metoda getValue()
avnd ca argument obiectul AdjustmentEvent. Aceast metod returneaz o valoare ntreag care
reprezint valoarea barei de derulare..
Putei determina i modul cum a fost deplasat bara de derulare dac folosii metoda
getAdjustmentType() a obiectului AdjustmentEvent. Aceasta returneaz una din urmtoarele
cinci valori, care sunt variabile de clas ale clasei Adjustment:
UNIT_INCREMENT
O cretere cu 1 a valorii, produs de executarea unui clic pe
sgeata de deplasare a barei sau pe o tast cu sgeat
UNIT_DECREMENT
O descretere a valorii cu 1
BLOCK_INCREMENT
O cretere mai mare a valorii, cauzat de un clic pe bara de
derulare, n zona dintre caset i sgeat
BLOCK_DECREMENT O descretere mai mare a valorii
TRACK
O modificare produs de deplasarea casetei de derulare
Evenimente de selecionare
Evenimentele de selecionare (focus events) apar atunci cnd o component primete sau
pierde dreptul de a primi datele de intrare n cadrul interfeei grafice utilizator. Starea de
selecionare determin componenta care este activat la un moment dat pentru a primi date de
intrare de la tastatur. Dac unul din cmpurile de text este selecionat (ntr-o interfa utilizator cu
mai multe cmpuri de text editabile), n acesta se va vedea un cursor care plpie. Orice text
introdus de la tastatura este memorat n componenta selecionat.
Starea de selecionare (focus) se aplic tuturor componentelor care pot primi date de intrare
de la tastarur. n cazul unui obiect JButton selecionat, pe suprafaa acestuia va fi reprezentat un
contur cu linie ntrerupt.
Evenimente de element
Evenimentele de element (item events) apar atunci cnd se selecteaz sau se deselecteaz un
element de tip JButton, JCheckBox, JComboBox sau JRadioButton. Pentru a trata aceste
evenimente, o clas trebuie s implementeze interfaa ItemListener.
Aceast interfa conine o singur metod: itemStateChanged (ItemEvent), care are
urmtoarea form:
void itemStateChanged(ItemEvent evt) {
// ...
}
Pentru a determina elementul care a produs evenimentul se poate folosi metoda getItem(),
care primete ca argument obiectul ItemEvent.
De asemenea, putei determina dac elementul a fost selectat sau deselectat folosind metoda
getStateChange(). Aceasta returneaz o valoare ntreag, egal cu una dintre variabilele de clas
ItemEvent. DESELECTED sau ItemEvent.SELECTED.
Evenimente de tastatur
Evenimentele de tastatur (key events) sunt generate atunci cnd se apas o tast. Orice
component poate genera aceste evenimente, iar pentru a fi suportate ntr-o clas, aceasta trebuie s
implementeze interfaa KeyListener.
Aceast interfa conine trei metode: keyPressed(KeyEvent), keyReleased(KeyEvent) i
keyTyped(KeyEvent), care au urmtoarea form:
public void keyPressed(KeyEvent evt) {
//...
}
public void keyReleased(KeyEvent evt) {
// ...
}
public void keyTyped(KeyEvent evt) {
// ...
}
Evenimente de mouse
Evenimentele de mouse sunt generate, de obicei, de mai multe tipuri de interaciuni:
Clic de mouse
Indicatorul mouse-ului ptrunde pe suprafaa componentei
Indicatorul mouse-ului prsete suprafaa componentei
Orice component poate genera aceste evenimente, care sunt implementate de o clas prin
intermediul interfeei MouseListener. Aceast interfa posed cinci metode:
mouseClicked(MouseEvent)
mouseEntered(MouseEvent)
mouseExited(Mouse.Event)
mousePressed(Mouse.Event)
mouseReleased(MouseEvent)
Fiecare dintre acestea are forma generic prezentat mai jos pentru mouseReleased
(MouseEvent):
mouseReleased(MouseEvent evt) {
// ...
}
Pentru obiectele MouseEvent pot fi folosite unntoarele metode:
getClickCount() Returneaz o valoare ntreag ce reprezint de cte ori s-a executat clic
getPoint() Returneaz coordonatele x,y ale punctului unde s-a executat clic pe
component, sub forma unui obiect Point.
getX()
Returneaz poziia x
getY()
Returneaz poziia y
Evenimente de fereastr
Evenimentele de fereastr apar atunci cnd utilizatorul deschide sau nchide un obiect
fereastr, cum ar fi JFrame sau JWindow. Orice componenta poate genera aceste evenimente, iar
pentru a le trata, o clas trebuie s implementeze interfaa windowListener.
Interfaa WindowListener conine apte metode:
windowActivated(WindowEvent)
windowClosed(WindowEvent)
windowClosing(WindowEvent)
windowDeactivated(WindowEvent)
windowDeiconified(WindowEvent)
windowIconified(WindowEvent)
windowOpened(WindowEvent)
Toate acestea au urmtoarea form, prezentat aici pentru metoda
windowOpened(WindowEvent):
public void windowOpened(WindowEvent evt) {
// . . .
}
Metodele windowClosing() i windowClosed() sunt asemntoare, ns una este apelat o
dat cu nchiderea ferestrei, iar cealalt - dup nchiderea acesteia. Dac dorii, este posibil ca n
cadrul metodei windowClosing() s decidei anularea nchiderii ferestrei.
Restriciile de securitate schimb modul de scriere i testare a applet-urilor care ncarc fiiere pe
baza adreselor lor URL. Deoarece pn acum nu ai folosit conexiuni de reea, ai putut testa appleturile pe sistemul local prin simpla ncrcare a fiierelor HTML ntr-un browser sau n utilitarul
appletviewer. Acest lucru nu poate fi fcut n cazul applet-urilor care deschid conexiuni de reea.
Pentru ca aceste applet-uri s funcioneze corect trebuie s procedai ntr-unul din urmtoarele
moduri:
Rulai browserul pe aceeai main pe care ruleaz i serverul Web. Dac nu avei acces la
un server Web, putei instala i rula unul pe propria dumneavoastr main.
Copiai clasa i fiierul HTML pe serverul Web ori de cte ori dorii s le testai, apoi rulai
applet-ul din pagina Web, nu de pe sistemul local.
n acest mod v vei da seama dac applet-ul i conexiunea deschis de acesta se afl pe
aceeai main. Dac ncercai s ncrcai un applet sau un fiier de pe alte servere, vei obine o
excepie de securitate, mpreun cu o mulime de alte mesaje de eroare afiate pe ecran sau pe
consola Java.
Din aceste motive, acunci cnd v conectai la Internet pentru a-i folosi resursele, este
bine s folosii aplicaii, care nu sufer de aceste restricii.
java.awt.*;
java.awt.event.*;
java.net.*;
java.io.*;
Thread executabil;
URL page;
TextArea box = new TextArea("Transfer text ...");
public CitireFisier() {
super("Transfer fisier");
add(box);
try {
page = new URL("http://www.masini.ro//masini.html");
}
catch (MalformedURLException e) {
System.out.println("URL gresit: " + page);
}
}
public static void main(String[] arguments) {
CitireFisier cadru = new CitireFisier();
WindowListener l = new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
};
cadru.addWindowListener(l);
cadru.pack();
cadru.setVisible(true);
if (cadru.executabil == null) {
cadru.executabil = new Thread(cadru);
cadru.executabil.start();
}
}
public void run() {
URLConnection conn = null;
InputStreamReader in;
BufferedReader data;
String line;
StringBuffer buf = new StringBuffer();
try {
conn = this.page.openConnection();
conn.connect();
box.setText("Conexiune deschisa ...");
in = new InputStreamReader(conn.getInputStream());
data = new BufferedReader(in);
box.setText("Citeste date ...");
while ((line = data.readLine()) != null) {
buf.append(line + "\n");
}
box.setText(buf.toString());
}
catch (IOException e) {
System.out.println("Eroare ! :" + e.getMessage());
}
}
}
Socluri
Pentru aplicaiile de reea unde folosirea claselor URL sau URLConnection nu este
suficient (cum ar fi cazurile cnd se folosesc alte protocoale sau pentru comunicaii n reea
generice), Java ofer clasele Socket i ServerSocket drept o metod proprie, echivalent tehnicilor
de programare cu socluri TCP standard (sockets).
Clasa Socket ofer o interfa soclu client asemntoare soclurilor UNIX. Crearea unei noi instane
a clasei Socket, prin care se deschide o conexiune, se face astfel (numeGazda este numele mainii gazd,
iar numarPort este numrul portului):
Dac folosii socluri ntr-un applet, nu uitai c v aflai sub incidena restriciilor de
securitate proprii unui applet, care v interzic s v conectai la un alt sistem dect la cel de unde
provine applet-ul.
O dat soclul deschis, putei folosi fluxuri de intrare sau de ieire pentru a citi din acesta:
BufferedInputStream bis =
new BufferedInputStream(conexiune.getInputStream());
DataInputStream intrare = new DataInputStream(bis);
BufferedOutputStream bos =
new BufferedOutputStream(conexiune.getOutputStream() ) ;
DataOutputStream iesire = new DataOutputStream(bos);
Dup ce ai terminat de lucrat cu un soclu, nu uitai s l nchidei. (Acest lucru va nchide, de
asemenea, fluxurile de intrare sau de ieire pe care le-ai atribuit soclului.)
conexiune.close() ;
Soclurile server funcioneaz asemntor, cu excepia metodei accept(). Un soclu server ascult pe
un port TCP pentru a intercepta o cerere de conexiune din partea unui client; atund cnd clientul se
conecteaz la un port, metoda accept() accept conexiunea de la acesta. Prin folosirea soclurilor client i
server putei crea aplicaii care comunic prin reea.
Pentru a crea un soclu server ataat unui port, se instaniaz clasa ServerSocket, specificnd
numrul portului:
ServerSocket sConexiune = new ServerSocket(8888);
Folosii metoda accept() pentru a asculta portul respectiv i pentru a accepta eventualele
conexiuni ale clienilor:
sConexiune.accept();
O dat conexiunea efectuat, putei folosi fluxuri de intrare i de ieire pentru a citi sau scrie
de la, ctre un client.
Pentru a prezenta comunicaia n reea prin Java, este prezentat aici un program Banal,
care folosete clasele Socket pentru implementarea unei aplicaii client server de reea.
Exemplul funcioneaz n felul urmtor: programul server ateapt conectarea unui client.
La conectarea unui client, serverul pune o ntrebare i ateapt un rspuns. La cellalt capt clientul
recepioneaz ntrebarea, o afieaz ctre utilizator i ateapt un rspuns de la acesta. Utilizatorul
introduce rspunsul, care este trimis napoi ctre server. Serverul verific dac rspunsul este corect
i anun rezultatul. Dup aceasta, serverul ntreab clientul dac dorete s i se pun alt ntrebare;
dac rspunsul este afirmativ, procesul se repet.
Aplicaia are nevoie de 2 pri: pe partea de server este necesar un program care s
monitorizeze un anumit port al calculatorului gazd, acolo unde urmeaz s se conecteze clientul.
La detectarea unui client, serverul alege o ntrebare i o trimite clientului pe portul respectiv. Dup
aceasta, serverul intr ntr-o stare de ateptare pn ce recepioneaz rspunsul de la client. Dup
primirea rspunsului, serverul verific corectitudinea acestuia i anun clientul rezultatul obinut.
Apoi clientul este ntrebat dac dorete o nou ntrebare, .a.m.d. Pe scurt serverul realizeaz
urmtoarele aciuni:
1. Ateapt conectarea unui client
2. Accept conectarea unui client
3. Transmite clientului o ntrebare aleatoare
4. Ateapt rspunsul de la client
5. Verific rspunsul i anun clientul rezultatul
6. ntreab clientul dac dorete o alt ntrebare
7. Ateapt un rspuns (y/n) de la client
8. Dac este cazul revine la pasul 3
Pe partea de client este o aplicaie care ruleaz n linia de comand. Clientul se conecteaz la server
i ateapt o ntrebare. Atunci cnd primete o ntrebare de la server, clientul o afieaz
utilizatorului i ateapt introducerea unui rspuns. Acest rspuns este trimis napoi ctre server,
dup care se ateapt rspunsul acestuia. Clientul afieaz rspunsul de la server i permite
utilizatorului s opteze pentru continuarea programului (dac mai dorete o nou ntrebare). Clientul
trimite apoi rspunsul utilizatorului i i termin execuia, n cazul acesta nu dorete continuarea
conversaiei. Principalele activiti ale clientului sunt urmtoarele:
1. Se conecteaz la server
2. Ateapt trimiterea unei ntrebri
3. Afieaz ntrebarea i primete rspunsul introdus de utilizator
4. Trimite rspunsul ctre server
5. Ateapt un rspuns de la server
6. Afieaz rspunsul i l ntreab pe utilizator dac doret o nou ntrebare
7. Trimite serverului rspunsul utilizatorului
8. Dac este cazul, revine la pasul 2.
Textul surs al aplicaiei este prezentat n continuare.
import java.io.*;
import java.net.*;
import java.util.Random;
public class ServerBanal extends Thread {
private static final int NRPORT = 1234;
private static final int ASTEAPTACLIENT = 0;
private static final int ASTEAPTARASPUNS = 1;
private static final int ASTEAPTACONFIRMARE = 2;
private String[] intrebari;
private String[] raspunsuri;
private ServerSocket serverSocket;
private int nrIntrebari;
private int crt = 0;
private int stare = ASTEAPTACLIENT;
private Random aleator = new Random();
public ServerBanal() {
super("ServerBanal");
try {
serverSocket = new ServerSocket(NRPORT);
System.out.println("ServerBanal este in executie ...");
}
catch (IOException e) {
System.err.println("Exception: nu se poate crea soclul");
System.exit(1);
}
}
public static void main(String[] arguments) {
ServerBanal server = new ServerBanal();
server.start();
}
public void run() {
Socket clientSocket = null;
// Initializare vectori cu intrebari si raspunsuri
if (!initIntRasp()) {
System.err.println("Error: nu se pot initializa intrebarile
si raspunsurile");
return;
}
// Asteapta clientul si pune intrebari banale
while (true) {
// Asteapta un client
if (serverSocket == null)
return;
try {
clientSocket = serverSocket.accept();
}
catch (IOException e) {
System.err.println("Exceptie: nu se poate face
conectarea la soclul client");
System.exit(1);
}
// Se poarta dialogul intrebare/raspuns
try {
InputStreamReader isr = new
InputStreamReader(clientSocket.getInputStream());
BufferedReader is = new BufferedReader(isr);
PrintWriter os = new PrintWriter(new
BufferedOutputStream(clientSocket.getOutputStream()), false);
String linieIesire;
//Transmite cererea serverului
linieIesire = citireIntrari(null);
os.println(linieIesire);
os.flush();
// Citeste si afiseaza intrarile utilizator
while (true) {
String linieIntrare = is.readLine();
if (linieIntrare.length() > 0) {
linieIesire = citireIntrari(linieIntrare);
os.println(linieIesire);
os.flush();
if (linieIesire.equals("La revedere!."))
break;
}
}
// Inchidere fluxuri
os.close();
is.close();
clientSocket.close();
}
catch (Exception e) {
System.err.println("Exception: " + e);
e.printStackTrace();
}
}
}
private boolean initIntRasp() {
try {
File fisierIntrare = new File("intrebari.txt");
FileInputStream inStream = new FileInputStream(fisierIntrare);
byte[] data = new byte[(int)fisierIntrare.length()];
// Se citesc intrebarile si raspunsurile
if (inStream.read(data) <= 0) {
System.err.println("Error: nu se pot citi intrebarile si rasp");
return false;
}
// Numarare intrebari si raspunsuri
for (int i = 0; i < data.length; i++)
if (data[i] == (byte)'\n') nrIntrebari++;
nrIntrebari /= 2;
intrebari = new String[nrIntrebari];
raspunsuri = new String[nrIntrebari];
// Se introduc intrebarile si raspunsurile in tablouri separate
int start = 0, nr = 0;
boolean esteIntr = true;
for (int i = 0; i < data.length; i++)
if (data[i] == (byte)'\n') {
if (esteIntr) {
intrebari[nr] = new String(data, start, i - start - 1);
esteIntr = false;
}
else {
raspunsuri[nr] = new String(data, start, i - start - 1);
esteIntr = true;
nr++;
}
start = i + 1;
}
}
catch (FileNotFoundException e) {
System.err.println("Exceptie: nu se gaseste fisierul cu
intrebari si raspunsuri");
return false;
}
catch (IOException e) {
System.err.println("Exceptie: eroare la citire intrebari");
return false;
}
return true;
}
String citireIntrari(String inStr) {
String outStr = null;
switch (stare) {
case ASTEAPTACLIENT:
// Pune o intrebare
outStr = intrebari[crt];
stare = ASTEAPTARASPUNS;
break;
case ASTEAPTARASPUNS:
// Verifica raspunsul
if (inStr.equalsIgnoreCase(raspunsuri[crt]))
outStr = "Raspuns corect! Doriti o noua intrebare? (y/n)";
else
outStr = "Raspuns gresit! Raspunsul corect este " +
raspunsuri[crt] + ". Doriti alta intrebare? (y/n)";
stare = ASTEAPTACONFIRMARE;
break;
case ASTEAPTACONFIRMARE:
// Se asteapta confirmarea continuarii dialogului
if (inStr.equalsIgnoreCase("Y")) {
crt = Math.abs(aleator.nextInt()) % intrebari.length;
outStr = intrebari[crt];
stare = ASTEAPTARASPUNS;
}
else {
outStr = "La revedere!.";
stare = ASTEAPTACLIENT;
}
break;
}
return outStr;
}
}
import java.io.*;
import java.net.*;
public class Banal {
private static final int NRPORT = 1234;
public static void main(String[] arguments) {
Socket socket = null;
InputStreamReader isr = null;
BufferedReader in = null;
PrintWriter out = null;
String adresa;
// Cauta adresa in argumentele liniei de comanda
if (arguments.length != 1) {
System.out.println("Mod de utilizare: java Banal <adresa>");
return; }
else
adresa = arguments[0];
// Initializare soclu si fluxuri
try {
socket = new Socket(adresa, NRPORT);
isr = new InputStreamReader(socket.getInputStream());
in = new BufferedReader(isr);
out = new PrintWriter(socket.getOutputStream(),true);
}
catch (IOException e) {
System.err.println("Err: nu se poate crea soclul fluxului"
+ e.getMessage());
System.exit(1);
}
// Citeste datele de intrare si raspunsurile serverului si le prelucreaza
try {
StringBuffer str = new StringBuffer(128);
String inStr;
int c;
while ((inStr = in.readLine()) != null) {
System.out.println("Server: " + inStr);
if (inStr.equals("La revedere")) break;
Artificii cu applet-uri
Metoda showStatus()
Metoda showStatus() a clasei Applet v permite s afiai un ir n bara de stare a browserului care
ruleaz applet-ul. Putei folosi aceast metod pentru afiarea mesajelor de eroare, a legturilor, pentru
indicaii sau pentru alte mesaje de stare.
URL (URL, String) creeaz un obiect URL avnd o adres de baz provenit din
obiectul URL specificat i o cale relativ provenit din irul transmis ca argument secund. Putei
folosi getDocumentBase() pentru adresa URL a paginii care conine applet-ul sau getCodebase()
pentru adresa URL a clasei applet-ului. Calea relativ va fi concatenat cu adresa de baz.
URL (String, String, int, String) creeaz un obiect URL pornind de la protocol
(cum ar fi http sau ftp), numele mainii (www.prefect.com, ftp.netcom.com etc.), numrul de port
(80 pentru http)i un nume de fiier sau de director.
} catch (MalformedURLException e) {
System.out.println("Adresa URL incorecta: " + unURL) ;
}
O dat obinut obiectul URL, tot ceea ce mai trebuie s facei este s l transmitei
browserului; drept urmare, acesta va ncarca adresa respectiv:
getAppletContext().showDocument(unURL);
Browserul ce conine un applet Java cu codul prezentat mai sus va ncrca i va afia
documentul de la adresa URL respectiv.
Aplicaia urmtoare prezint dou clase: ButonLink i o clas ajuttoare Marcaj. Appletul
ButonLink afieaz trei butoane care indic trei locaii Web diferite; dac se execut clic pe aceste
butoane, va fi ncrcat documentul de la locaia respectiv.
Textul surs al aplicaiei este prezentat n continuare:
import java.awt.*;
import java.net.*;
public class ButonLink extends java.applet.Applet {
Marcaj ListaMarcaje[] = new Marcaj[3];
public void init() {
ListaMarcaje[0] = new Marcaj("Catalog auto",
"http://www.masini.ro");
ListaMarcaje[1] = new Marcaj("Macmillan Computer Publishing",
"http://www.mcp.com");
ListaMarcaje[2]= new Marcaj("JavaSoft",
"http://java.sun.com");
GridLayout gl = new GridLayout(ListaMarcaje.length, 1, 10, 10);
setLayout(gl);
for (int i = 0; i < ListaMarcaje.length; i++) {
add(new Button(ListaMarcaje[i].name));
}
}
public boolean action(Event evt, Object arg) {
if (evt.target instanceof Button) {
saltLa( (String)arg );
return true;
}
else return false;
}
void saltLa(String name) {
URL theURL = null;
for (int i = 0; i < ListaMarcaje.length; i++) {
if (name.equals(ListaMarcaje[i].name))
theURL = ListaMarcaje[i].url;
}
if (theURL != null)
getAppletContext().showDocument(theURL);
}
}
class Marcaj {
String name;
URL url;
Marcaj(String name, String theURL) {
this.name = name;
try {
this.url = new URL(theURL);
} catch (MalformedURLException e) {
System.out.println("URL inexistent: " + theURL);
}
}
}
Un context reprezint un mijloc prin care se poate descrie mediul din care face parte ceva.
n acest caz, contextul applet-ului este definit n clasa AppletContext i este folosit pentru
comunicaia ntre applet-uri.
Pentru a obine o instan a acestei clase pentru applet-ul dumneavoastr, vei folosi metoda
getAppletContext(), i nu un anumit constructor.
De exemplu, apelarea metodei trimiteMesaj() pentru toate applet-urile dintr-o pagin,
inclusiv cel curent, folosete metoda getApplets() i un ciclu for de genul:
for (Enumeration e = getAppletContext().getApplets();
e.hasMoreElements();) {
Applet curent = (SubclasaMeaApplet) (e.nextElement());
curent.trimiteMesaj ();
}
Metoda getApplets() returneaz un obiect de tip Enumeration care conine o list a appleturilor din pagin. Parcurgerea acestei liste v permite s accesai pe rnd fiecare element. Reinei
c fiecare element al obiectului Enumeration este o instan a clasei Object; pentru ca applet-ul s se
comporte n modul dorit (i s accepte mesaje de la alte applet-uri) trebuie s l convertii prin cast
la o instan a subclasei applet-ului dumneavoastr (n acest caz, clasa SubclasaMeaApplet).
Apelarea unei metode ntr-un anumit applet este ceva mai complicat. Pentru aceasta,
trebuie s asociai fiecrui applet un nume i s facei referirea prin numele respectiv.
Pentru a asocia unui applet un nume se folosete atributul NAME al etichetei <APPLET>:
<P>Acest applet trimite informatii:
<APPLET CODE=AppletulMeu.class" WIDTH=100 HEIGHT=150 NAME=Expeditor>
</APPLET>
<P>Acest applet primeste informatii de la expeditor:
<APPLET CODE="AppletulMeu.class" WIDTH=100 HEIGHT=150 NAME=Destinatar>
</APPLET>
Pentru a obine o referin la un alt applet din aceeai pagin se folosete metoda
getApplet() pentru contextul applet-ului cu acel nume. Aceasta va avea ca rezultat obinerea unei
referine la applet-ul cu numele respectiv. Dup aceasta, v putei referi la acest applet ca la oricare
alt obiect: apelai metode, modificai variabilele de instan i aa mai departe. Iat codul care
realizeaz acest lucru:
// accesati applet-ul destinatar
Applet destinatar = (SubclasaMeaApplet)getAppletContext().
getApplet("Destinatar);
// comandati-i sa se actualizeze
destinatar.actualizare(text, valoare);
n acest exemplu s-a folosit metoda getApplet() pentru a se obine o referin ctre applet-ul
cu numele "Destinatar". Observai c obiectul returnat de getApplet() este o instan a clasei
generice Applet; vei dori, probabil, s l convertii prin cast ctre o instan a subclasei
dumneavoastr. O dat obinut referina ctre applet, putei apela apoi metodele sale ca i cnd ar fi
orice alt obiect din mediul dumneavoastr de execuie. Aici, de exemplu, dac ambele applet-uri
conin o metod denumit actualizare(), putei comanda applet-ului destinatar s se actualizeze
singur folosind informaiile din applet-ul curent.
Denumirea applet-urilor i referirea lor prin metodele prezentate n aceast seciune permit
comunicarea i sincronizarea applet-urilor, obinndu-se astfel un comportament uniform pentru
toate applet-urile din pagin.
Aspectele datelor sunt descrise folosind tipurile MIME, adic mecanismul de negociere a
coninutului care este folosit de programele de pot electronic sau de World Wide Web. n afar
de numele logic al aspectului, acesta mai posed i un nume descriptiv, care poate fi tradus n
diferite limbaje internaionale. Aspectele de date pot avea, de asemenea. o clas reprezentativ - de
exemplu, dac datele sunt un ir Unicode, acesta este reprezentat de clasa String. Dac aspectul de
date nu este reprezentat de nici o clas, va fi folosit implicit clasa InputStream.
Pentru a crea un nou aspect de date trebuie creat o instan a clasei DataFlavor folosind
unul din urmtorii constructori:
DataFlavor (String, String) creeaz un aspect de date care reprezint un tip MIME,
unde primul argument este tipul MIME, iar al doilea reprezint numele descriptiv. Clasa care
reprezint acest aspect de date va fi InputStream.
Dup ce ai obinut acest obiect cu aspectul de date, putei interoga valorile sale sau putei
compara tipurile sale MIME cu cele ale altor obiecte aspect de date pentru a negocia modul cum vor
fi transferate datele.
Aspectele de date sunt folosite de obiectele transferabile, care sunt definite folosind interfaa
Transferable. Un obiect transferabil va conine datele ce urmeaz a fi transferate, precum i
instane pentru fiecare dintre aspectele de date care reprezint obiectul respectiv. Pentru ca obiectul
dumneavoastr transferabil s poat fi ntr-adevr negociat i transferat, trebuie s implementai i
metodele getTransferDataFlavors(), isDataFlavorSupported() i getTransferData(). (Pentru
detalii, consultai documentaia interfeei Transferable.)
Clasa StringSelection implementeaz un obiect transferabil simplu, pentru transferul
irurilor de text, folosind obiecte DataFlavor i interfaa Transferable.
Reinei c obiectele transferabile sunt folosite pentru ncapsularea datelor i pentru
descrierea formatului (aspectului) acestora; ele nu au nici un rol n formatarea datelor, la nici una
dintre prile implicate n transfer. Aceasta este responsabilitatea programului dumneavoastr atunci
cnd folosii zona Clipboard pentru a obine date de la o surs.
Transferable contents) {
}
}