Sunteți pe pagina 1din 252

Se instaleaza visual studio versiunea 2015 si j#

https://www.microsoft.com/en-eg/download/details.aspx?id=4712

1
2
Rularea unui program Java ( J# )

3
Apas pe Object
Browser ca sa pot
vedea continutul
sis a scriu sursa

scriu programul
Rularea
programului
Java

Continutul
programului

4
Structura lexicală a limbajului Java
1.3.1 Setul de caractere Sunt secvenţe nelimitate de litere şi cifre
Limbajului Java lucrează în mod nativ folosind Unicode, începând cu o literă. După
setul de caractere Unicode. cum am mai spus, identificatorii nu au voie să
Acesta este un standard internaţional care fie identici cu cuvintele rezervate.
înlocuieşte vechiul set de caractere 1.3.4 Literali
ASCII şi care foloseşte pentru reprezentarea Literalii pot fi de următoarele tipuri:
caracterelor 2 octeţi, ceea ce • Intregi
înseamnă că se pot reprezenta 65536 de semne, Sunt acceptate 3 baze de numeraţie : baza 10,
spre deosebire de ASCII, unde baza 16 (încep cu caracterele
era posibilă reprezentarea a doar 256 de 0x) şi baza 8 (încep cu cifra 0) şi pot fi de două
caractere. Primele 256 caractere tipuri:
Unicode corespund celor ASCII, referirea la – normali - se reprezintă pe 4 octeţi (32 biţi)
celelalte făcându-se prin \uxxxx, – lungi - se reprezintă pe 8 octeţi (64 biţi) şi se
unde xxxx reprezintă codul caracterului. termină cu caracterul
O altă caracteristică a setului de caractere L (sau l).
Unicode este faptul că întreg • Flotanţi
intervalul de reprezentare a simbolurilor este Pentru ca un literal să fie considerat flotant el
divizat în subintervale numite trebuie să aibă cel puţin o
blocuri, câteva exemple de blocuri fiind: Basic zecimală după virgulă, să fie în notaţie
Latin, Greek, Arabic, Gothic, exponenţială sau să aibă sufixul
Currency, Mathematical, Arrows, Musical, etc. F sau f pentru valorile normale - reprezentate
Mai jos sunt oferite câteva exemple de pe 32 biţi, respectiv D
caractere Unicode. sau d pentru valorile duble - reprezentate pe 64
• \u0030 - \u0039 : cifre ISO-Latin 0 - 9 biţi.
• \u0660 - \u0669 : cifre arabic-indic 0 - 9 Exemple: 1.0, 2e2, 3f, 4D.
• \u03B1 - \u03C9 : simboluri greceşti _ - ! • Logici
• \u2200 - \u22FF : simboluri matematice (8, 9, Sunt reprezentaţi de true - valoarea logică de
;, etc.) adevăr, respectiv false
• \u4e00 - \u9fff : litere din alfabetul Han - valoarea logică de fals.
(Chinez, Japonez, Coreean) Atenţie
Mai multe informaţii legate de reprezentarea Spre deosebire de C++, literalii întregi 1 şi 0
Unicode pot fi obţinute la nu mai au semnificaţia
adresa ”http://www.unicode.org”. de adevărat, respectiv fals.
1.3.2 Cuvinte cheie • Caracter
Cuvintele rezervate în Java sunt, cu câteva Un literal de tip caracter este utilizat pentru a
excepţii, cele din C++ şi au fost exprima caracterele codului
enumerate în tabelul de mai jos. Acestea nu pot Unicode. Reprezentarea se face fie folosind o
fi folosite ca nume de clase, literă, fie o secvenţă
interfeţe, variabile sau metode. true, false, null escape scrisă între apostrofuri. Secvenţele
nu sunt cuvinte cheie, escape permit specificarea
dar nu pot fi nici ele folosite ca nume în caracterelor care nu au reprezentare grafică şi
aplicaţii. Cuvintele marcate prin _ sunt reprezentarea unor caractere
rezervate, dar nu sunt folosite. speciale precum backslash, apostrof, etc.
abstract double int strictfp Secvenţele escape predefinite
boolean else interface super în Java sunt:
break extends long switch – ’\b’ : Backspace (BS)
byte final native synchronized – ’\t’ : Tab orizontal (HT)
case finally new this – ’\n’ : Linie nouă (LF)
catch float package throw – ’\f’ : Pagină nouă (FF)
char for private throws – ’\r’ : Inceput de rând (CR)
class goto* protected transient – ’\"’ : Ghilimele
const* if public try – ’\’’ : Apostrof
continue implements return void – ’\\’ : Backslash
default import short volatile • Şiruri de caractere
do instanceof static while Un literal şir de caractere este format din zero
Incepând cu versiunea 1.5, mai există şi sau mai multe caractere
cuvântul cheie enum. între ghilimele. Caracterele care formează şirul
1.3.3 Identificatori pot fi caractere grafice

5
sau secvenţe escape. • Comentarii pe mai multe linii, închise între /*
Dacă şirul este prea lung el poate fi scris ca o şi */.
concatenare de subşiruri • Comentarii pe mai multe linii care ţin de
de dimensiune mai mică, concatenarea şirurilor documentaţie, închise între
realizându-se cu operatorul /** şi */. Textul dintre cele două secvenţe este
+, ca în exemplul: "Ana " + " are " + " mere ". automat mutat în
Sirul vid documentaţia aplicaţiei de către generatorul
este "". automat de documentaţie
După cum vom vedea, orice şir este de fapt o javadoc.
instanţă a clasei String, • Comentarii pe o singură linie, care incep
definită în pachetul java.lang. cu //.
1.3.5 Separatori Observaţii:
Un separator este un caracter care indică • Nu putem scrie comentarii în interiorul altor
sfârşitul unei unităţi lexicale şi comentarii.
ýnceputul alteia. In Java separatorii sunt • Nu putem introduce comentarii în interiorul
următorii: ( ) [ ] ; , . . literalilor caracter sau şir
Instrucţiunile unui program se separă cu punct de caractere.
şi virgulă. • Secvenţele /* şi */ pot să apară pe o linie
1.3.6 Operatori după secvenţa // dar îşi
Operatorii Java sunt, cu mici deosebiri, cei din pierd semnificaţia. La fel se întamplă cu
C++: secvenţa // în comentarii care
• atribuirea: = incep cu /* sau */.
• operatori matematici: +, -, *, /, %, ++, -- . 1.4 Tipuri de date şi variabile
Este permisă notaţia prescurtată de forma lval 1.4.1 Tipuri de date
op= rval: x += 2 n In Java tipurile de date se impart în două
-= 3 categorii: tipuri primitive şi
Există operatori pentru autoincrementare şi tipuri referinţă. Java porneşte de la premiza că
autodecrementare (post şi ”orice este un obiect”,
pre): x++, ++x, n--, --n prin urmare tipurile de date ar trebui să fie de
Evaluarea expresiilor logice se face prin fapt definite de clase şi toate
metoda scurtcircuitului: evaluarea variabilele ar trebui să memoreze instanţe ale
se opreşte în momentul în care valoarea de acestor clase (obiecte). In
adevăr a expresiei este principiu acest lucru este adevărat, însă, pentru
sigur determinată. usurinţa programării, mai
• operatori logici: &&(and), ||(or), !(not) există şi aşa numitele tipurile primitive de date,
• operatori relaţionali: <, <=, >, <=, ==, != care sunt cele uzuale :
• operatori pe biţi: &(and), |(or), ^ (xor), ~ • aritmetice
(not) – întregi: byte (1 octet), short (2), int (4), long
• operatori de translaţie: <<, >>, >>> (shift la (8)
dreapta fără semn) – reale: float (4 octeti), double (8)
• operatorul if-else: expresie-logica ? val-true : • caracter: char (2 octeţi)
val-false • logic: boolean (true şi false)
• operatorul , (virgulă) folosit pentru evaluarea In alte limbaje de programare formatul şi
secvenţială a operaţiilor: dimensiunea tipurilor primitive de
int x=0, y=1, z=2; date pot depinde de platforma pe care rulează
• operatorul + pentru concatenarea şirurilor: programul. In Java acest lucru
String s1="Ana"; nu mai este valabil, orice dependenţă de o
String s2="mere"; anumită platformă specifică fiind
int x=10; eliminată.
System.out.println(s1 + " are " + x + " " + s2); Vectorii, clasele şi interfeţele sunt tipuri
• operatori pentru conversii (cast) : (tip-de- referinţă. Valoarea unei variabile
data) de acest tip este, spre deosebire de tipurile
int a = (int)’a’; primitive, o referinţă (adresă de
char c = (char)96; memorie) către valoarea sau mulţimea de
int i = 200; valori reprezentată de variabila
long l = (long)i; //widening conversion respectivă.
long l2 = (long)200; Există trei tipuri de date din limbajul C care nu
int i2 = (int)l2; //narrowing conversion sunt suportate de limbajul
1.3.7 Comentarii Java. Acestea sunt: pointer, struct şi union.
In Java există trei feluri de comentarii: Pointerii au fost

6
eliminaţi din cauză că erau o sursă constantă de class Exemplu {
erori, locul lor fiind luat de //Fiecare variabila corespunde situatiei data de
tipul referinţă, iar struct şi union nu îşi mai au numele ei
rostul atât timp cât tipurile //din enumerarea de mai sus
compuse de date sunt formate în Java prin int a;
intermediul claselor. public void metoda(int b) {
1.4.2 Variabile a = b;
Variabilele pot fi de tip primitiv sau referinţe la int c = 10;
obiecte (tip referinţă). Indiferent for(int d=0; d < 10; d++) {
de tipul lor, pentru a putea fi folosite c --;
variabilele trebuie declarate şi, }
eventual, iniţializate. try {
• Declararea variabilelor: Tip numeVariabila; a = b/c;
• Iniţializarea variabilelor: Tip numeVariabila } catch(ArithmeticException e) {
= valoare; System.err.println(e.getMessage());
• Declararea constantelor: final Tip }
numeVariabila; }
Evident, există posibilitatea de a declara şi }
iniţializa mai multe variabile Observatii:
sau constante de acelaşi tip într-o singură • Variabilele declarate într-un for, rămân locale
instrucţiune astfel: corpului ciclului:
Tip variabila1[=valoare1], for(int i=0; i<100; i++) {
variabila2[=valoare2],...; //domeniul de vizibilitate al lui i
Convenţia de numire a variabilelorîn Java }
include, printre altele, următoarele i = 101;//incorect
criterii: • Nu este permisă ascunderea unei variabile:
• variabilele finale (constante) se scriu cu int x=1;
majuscule; {
• variabilele care nu sunt constante se scriu int x=2; //incorect
astfel: prima literă mică iar }
dacă numele variabilei este format din mai 1.5 Controlul execuţiei
mulţi atomi lexicali, atunci Instrucţiunile Java pentru controlul execuţiei
primele litere ale celorlalţi atomi se scriu cu sunt foarte asemănătoare celor
majuscule. din limbajul C şi pot fi împărţite în următoarele
Exemple: categorii:
final double PI = 3.14; • Instrucţiuni de decizie: if-else, switch-case
final int MINIM=0, MAXIM = 10; • Instrucţiuni de salt: for, while, do-while
int valoare = 100; • Instrucţiuni pentru tratarea excepţiilor: try-
char c1=’j’, c2=’a’, c3=’v’, c4=’a’; catch-finally, throw
long numarElemente = 12345678L; • Alte instrucţiuni: break, continue, return,
String bauturaMeaPreferata = "apa"; label:
In funcţie de loculîn care sunt declarate 1.5.1 Instrucţiuni de decizie
variabilele seîmpartîn următoatele if-else
categorii: if (expresie-logica) {
a. Variabile membre, declarate în interiorul ...
unei clase, vizibile pentru }
toate metodele clasei respective cât şi pentru if (expresie-logica) {
alte clase în funcţie de ...
nivelul lor de acces (vezi ”Declararea } else {
variabilelor membre”). ...
b. Parametri metodelor, vizibili doar în metoda }
respectivă. switch-case
c. Variabile locale, declarate într-o metodă, switch (variabila) {
vizibile doar în metoda respectiv case valoare1:
ă. ...
d. Variabile locale, declarate într-un bloc de break;
cod, vizibile doar în blocul case valoare2:
respectiv. ...
e. Parametrii de la tratarea excepţiilor (vezi break;
”Tratarea excepţiilor”). ...

7
default: 1.6 Vectori
... 1.6.1 Crearea unui vector
} Crearea unui vector presupune realizarea
Variabilele care pot fi testate folosind următoarelor etape:
instrucţiunea switch nu pot fi decât • Declararea vectorului - Pentru a putea utiliza
de tipuri primitive. un vector trebuie, înainte
1.5.2 Instrucţiuni de salt de toate, sa-l declarăm. Acest lucru se face prin
for expresii de forma:
for(initializare; expresie-logica; pas-iteratie) { Tip[] numeVector; sau
//Corpul buclei Tip numeVector[];
} ca în exemplele de mai jos:
for(int i=0, j=100 ; i < 100 && j > 0; i++, j--) { int[] intregi;
... String adrese[];
} • Instanţierea
Atât la iniţializare cât şi în pasul de iteraţie pot Declararea unui vector nu implică şi alocarea
fi mai multe instrucţiuni memoriei necesare pentru
despărţite prin virgulă. reţinerea elementelor. Operaţiunea de alocare a
while memoriei, numită şi
while (expresie-logica) { instanţierea vectorului, se realizează
... întotdeauna prin intermediul operatorului
} new. Instanţierea unui vector se va face printr-
do-while o expresie de
do { genul:
... numeVector = new Tip[nrElemente];
} unde nrElemente reprezintă numărul maxim de
while (expresie-logica); elemente pe care le
1.5.3 Instrucţiuni pentru tratarea poate avea vectorul. In urma instanţierii vor fi
excepţiilor alocaţi: nrElemente _ dimensiune(Tip) octeţi
Instrucţiunile pentru tratarea excepţiilor sunt necesari memorării elementelor din vector,
try-catch-finally, respectiv unde
throw şi vor fi tratate în capitolul ”Excepţii”. prin dimensiune(Tip) am notat numărul de
1.5.4 Alte instrucţiuni octeţi pe care se reprezintă
• break: părăseşte forţat corpul unei structuri tipul respectiv.
repetitive. v = new int[10];
• continue: termina forţat iteraţia curentă a unui //aloca spatiu pentru 10 intregi: 40 octeti
ciclu şi trece la următoarea c = new char[10];
iteraţie. //aloca spatiu pentru 10 caractere: 20 octeti
• return [valoare]: termină o metodă şi, Declararea şi instanţierea unui vector pot fi
eventual, returnează o valorare. făcute simultan astfel:
• numeEticheta: : Defineşte o etichetă. Tip[] numeVector = new Tip[nrElemente];
Deşi în Java nu există goto, se pot defini totuşi • Iniţializarea (opţional) După declararea unui
etichete folosite în expresii vector, acesta poate fi
de genul: break numeEticheata sau continue iniţializat, adică elementele sale pot primi nişte
numeEticheta, utile pentru valori iniţiale, evident
a controla punctul de ieşire dintr-o structură dacă este cazul pentru aşa ceva. In acest caz
repetitivă, ca înexemplul de instanţierea nu mai trebuie
mai jos: facută explicit, alocarea memoriei făcându-se
i=0; automat în funcţie de
eticheta: numă rul de elemente cu care se iniţializează
while (i < 10) { vectorul.
System.out.println("i="+i); String culori[] = {"Rosu", "Galben", "Verde"};
j=0; int []factorial = {1, 1, 2, 6, 24, 120};
while (j < 10) { Primul indice al unui vector este 0, deci
j++; poziţiile unui vector cu n elemente
if (j==5) continue eticheta; vor fi cuprinse între 0 şi n - 1. Nu sunt permise
if (j==7) break eticheta; construcţii de genul
System.out.println("j="+j); Tip numeVector[nrElemente], alocarea
} memoriei făcându-se doar prin intermediul
i++; opearatorului new.
} int v[10]; //ilegal

8
int v[] = new int[10]; //corect // Sorteaza vectorul v
1.6.2 Tablouri multidimensionale // Acesta va deveni {1, 2, 3, 4}
In Java tablourile multidimensionale sunt de • binarySearch - căutarea binară a unei anumite
fapt vectori de vectori. De valori într-un vector
exemplu, crearea şi instanţierea unei matrici sortat;
vor fi realizate astfel: • equals - testarea egalităţii valorilor a doi
Tip matrice[][] = new Tip[nrLinii][nrColoane]; vectori (au aceleaşi număr
matrice[i] este linia i a matricii şi reprezintă un de elemente şi pentru fiecare indice valorile
vector cu nrColoane corespunzătoare din cei doi
elemente iar matrice[i][j] este elementul de pe vectori sunt egale)
linia i şi coloana j. • fill - atribuie fiecărui element din vector o
1.6.3 Dimensiunea unui vector valoare specificată.
Cu ajutorul variabilei length se poate afla 1.6.6 Vectori cu dimensiune variabilă şi
numărul de elemente al unui eterogeni
vector. Implementări ale vectorilor cu număr variabil
int []a = new int[5]; de elemente sunt oferite de
// a.length are valoarea 5 clase specializate cum ar fi Vector sau
int m[][] = new int[5][10]; ArrayList din pachetul java.util.
// m[0].length are valoarea 10 Astfel de obiecte descriu vectori eterogeni, ale
Pentru a înţelege modalitatea de folosire a lui căror elemente au tipul Object,
length trebuie menţionat că şi vor fi studiaţi în capitolul ”Colecţii”.
fiecare vector este de fapt o instanţă a unei 1.7 Şiruri de caractere
clase iar length este o variabilă In Java, un şir de caractere poate fi reprezentat
publică a acelei clase, în care este reţinut printr-un vector format
numărul maxim de elemente al din elemente de tip char, un obiect de tip String
vectorului. sau un obiect de tip
1.6.4 Copierea vectorilor StringBuffer.
Copierea elementelor unui vector a într-un alt Dacă un şir de caractere este constant (nu se
vector b se poate face, fie doreşte schimbarea conţinutului
element cu element, fie cu ajutorul metodei să pe parcursul execuţiei programului) atunci
System.arraycopy, ca în exemplele el va fi declarat de tipul String,
de mai jos. După cum vom vedea, o atribuire altfel va fi declarat de tip StringBuffer.
de genul b = a are altă Diferenţa principală între aceste
semnificaţie decât copierea elementelor lui a în clase este că StringBuffer pune la dispoziţie
b şi nu poate fi folosită în metode pentru modificarea
acest scop. conţinutului şirului, cum ar fi: append, insert,
int a[] = {1, 2, 3, 4}; delete, reverse.
int b[] = new int[4]; Uzual, cea mai folosită modalitate de a lucra
// Varianta 1 cu şiruri este prin intermediul
for(int i=0; i<a.length; i++) clasei String, care are şi unele particularităţi
b[i] = a[i]; faţă de restul claselor menite să
// Varianta 2 simplifice cât mai mult folosirea şirurilor de
System.arraycopy(a, 0, b, 0, a.length); caractere. Clasa StringBuffer
// Nu are efectul dorit va fi utilizată predominant în aplicaţii dedicate
b = a; procesării textelor cum ar fi
1.6.5 Sortarea vectorilor - clasa Arrays editoarele de texte.
In Java s-a pus un accent deosebit pe Exemple echivalente de declarare a unui şir:
implementarea unor structuri de date String s = "abc";
şi algoritmi care să simplifice proceseul de String s = new String("abc");
crearea a unui algoritm, programatorul char data[] = {’a’, ’b’, ’c’};
trebuind să se concentreze pe aspectele String s = new String(data);
specifice problemei abordate. Observaţi prima variantă de declarare a şirului
Clasa java.util.Arrays oferă diverse metode s din exemplul de mai sus
foarte utile în lucrul cu vectori - de altfel, cea mai folosită - care prezintă o
cum ar fi: particularitate a clasei String
• sort - sortează ascendent un vector, folosind faţa de restul claselor Java referitoare la
un algoritm de tip Quick- instanţierea obiectelor sale.
Sort performant, de complexitate O(n log(n)). Concatenarea şirurilor de caractere se face prin
int v[]={3, 1, 4, 2}; intermediul operatorului
java.util.Arrays.sort(v);

9
+ sau, în cazul şirurilor de tip StringBuffer, In cazul în care sunt mai multe, argumentele
folosind metoda append. trebuie separate prin spaţii
String s1 = "abc" + "xyz"; iar dacă unul dintre argumente conţine spaţii,
String s2 = "123"; atunci el trebuie pus între
String s3 = s1 + s2; ghilimele. Evident, o aplicaţie poate să nu
In Java, operatorul de concatenare + este primească nici un argument sau
extrem de flexibil, în sensul că poate să ignore argumentele primite de la linia
permite concatenarea şirurilor cu obiecte de de comandă.
orice tip care au o reprezentare 1.8.2 Primirea argumentelor
de tip şir de caractere. Mai jos, sunt câteva In momentul lansării unei aplicaţii
exemple: interpretorul parcurge linia de comandă cu
System.out.print("Vectorul v are" + v.length + care a fost lansată aplicaţtia şi, în cazul în care
" elemente"); există, transmite programului
String x = "a" + 1 + "b" argumentele specificate sub forma unui vector
Pentru a lămuri puţin lucrurile, ceea ce execută de şiruri. Acesta este primit
compilatorul atunci când de aplicaţie ca parametru al metodei main.
întâlneşte o secvenţă de genul String x = "a" + Reamintim că formatul metodei
1 + "b" este: main din clasa principală este:
String x = new public static void main (String args[])
StringBuffer().append("a").append(1). Vectorul args primit ca parametru de metoda
append("b").toString() main va conţine toate argumentele
Atenţie însă la ordinea de efectuare a transmise programului de la linia de comandă.
operaţiilor. Şirul s=1+2+"a"+1+2 In cazul apelului java Sortare persoane.txt
va avea valoarea "3a12", primul + fiind vectorul args va conţine un
operatorul matematic de adunare singur element pe prima să poziţie:
iar al doilea +, cel de concatenare a şirurilor. args[0]="persoane.txt".
1.8 Folosirea argumentelor de la linia de Vectoru args este instanţiat cu un număr de
comand elemente egal cu numărul argumentelor
ă primite de la linia de comandă. Aşadar, pentru
1.8.1 Transmiterea argumentelor a afla numărul de
O aplicaţie Java poate primi oricâte argumente argumente primite de program este suficient să
de la linia de comanda în aflăm dimensiunea vectorului
momentul lansării ei. Aceste argumente sunt args prin intermediul atributului length:
utile pentru a permite utilizatorului public static void main (String args[]) {
să specifice diverse opţiuni legate de int numarArgumente = args.length ;
funcţionarea aplicaţiei sau să }
furnizeze anumite date iniţiale programului. In cazul în care aplicaţia presupune existenţa
Atenţie unor argumente de la linia
Programele care folosesc argumente de la linia de comandă, însă acestea nu au fost transmise
de comandă nu sunt 100% programului la lansarea sa, vor
pure Java, deoarece unele sisteme de operare, apărea excepţii (erori) de tipul
cum ar fi Mac OS, nu au în ArrayIndexOutOfBoundsException. Tratarea
mod normal linie de comandă. acestor excepţii este prezentată în capitolul
Argumentele de la linia de comandă sunt ”Excepţii”.
introduse la lansarea unei aplicaţii, Din acest motiv, este necesar să testăm dacă
fiind specificate după numele aplicaţiei şi programul a primit argumentele
separate prin spaţiu. De exemplu, de la linia de comandă necesare pentru
să presupunem că aplicaţia Sortare ordonează funcţionarea sa şi, în caz contrar, să
lexicografic (alfabetic) liniile afişeze un mesaj de avertizare sau să
unui fişier şi primeşte ca argument de intrare folosească nişte valori implicite, ca în
numele fişierului pe care să exemplul de mai jos:
îl sorteze. Pentru a ordona fişierul public class Salut {
"persoane.txt", aplicaţia va fi lansată public static void main (String args[]) {
astfel: if (args.length == 0) {
java Sortare persoane.txt System.out.println("Numar insuficient de
Aşadar, formatul general pentru lansarea unei argumente!");
aplicaţii care primeşte argumente System.exit(-1); //termina aplicatia
de la linia de comandă este: }
java NumeAplicatie [arg0 arg1 . . . argn] String nume = args[0]; //exista sigur
String prenume;

10
if (args.length >= 1) Argumentele de la linia de comandă sunt
prenume = args[1]; primite sub forma unui vector de
else şiruri (obiecte de tip String). In cazul în care
prenume = ""; //valoare implicita unele dintre acestea reprezintă
System.out.println("Salut " + nume + " " + valori numerice ele vor trebui convertite din
prenume); şiruri în numere. Acest lucru
} se realizează cu metode de tipul
} parseTipNumeric aflate în clasa
Spre deosebire de limbajul C, vectorul primit corespunzatoare
de metoda main nu conţine tipului în care vrem să facem conversia:
pe prima poziţie numele aplicaţiei, întrucât în Integer, Float, Double,
Java numele aplicaţiei este etc.
chiar numele clasei principale, adică a clasei în Să considerăm, de exemplu, că aplicaţia Power
care se gaseşte metoda main. ridică un numar real la o
Să consideră în continuare un exemplu simplu putere întreagă, argumentele fiind trimise de la
în care se doreşte afişarea linia de comandă sub forma:
pe ecran a argumentelor primite de la linia de java Power "1.5" "2" //ridica 1.5 la puterea 2
comandă: Conversia celor două argumente în numere se
public class Afisare { va face astfel:
public static void main (String[] args) { public class Power {
for (int i = 0; i < args.length; i++) public static void main(String args[]) {
System.out.println(args[i]); double numar = Double.parseDouble(args[0]);
} int putere = Integer.parseInt(args[1]);
} System.out.println("Rezultat=" +
Un apel de genul java Afisare Hello Java va Math.pow(numar, putere));
produce următorul rezultat }
(aplicaţia a primit 2 argumente): }
Hello Metodele de tipul parseTipNumeric pot
Java produce excepţii (erori) de tipul
Apelul java Afisare "Hello Java" va NumberFormatExceptionîn cazulîn care şirul
produceînsă alt rezultat (aplicaţia primit ca parametru nu reprezintă
a primit un singur argument): un numar de tipul respectiv. Tratarea acestor
Hello Java excepţii este prezentată în
1.8.3 Argumente numerice capitolul ”Excepţii”.

APLICATII

//sa scrie un mesaj


package j1;

class HelloWorld
{
public static void main (String args[])
{
System.out.println("Hello World!");
}
}

//sa testeze structura IF


package j1;
class testif
{

public static void main (String args[])


{
boolean engineState = false;
if (engineState == true)
System.out.println("The engine
is already on.");

11
else
{
engineState = true;
System.out.println("The engine is now
on.");
}
}
}
//sa creeze o clasa si un obiect caruia sa i se apeleze metodele
clasei
package j1;
class Motorcycle
{

String make;
String color;
boolean engineState = false;

void startEngine()
{
if (engineState == true)
System.out.println("The engine is already on.");
else
{
engineState = true;
System.out.println("The engine is now on.");
}
}
void showAtts()
{
System.out.println("This motorcycle is a "
+ color + " " + make);
if (engineState == true)
System.out.println("The engine is on.");
else System.out.println("The engine is off.");
}

public static void main (String args[])


{
Motorcycle m = new Motorcycle();
m.make = "Yamaha RZ350";
m.color = "yellow";
System.out.println("Calling showAtts...");
m.showAtts();
System.out.println("--------");
System.out.println("Starting engine...");
m.startEngine();
System.out.println("--------");
System.out.println("Calling showAtts...");
m.showAtts();
System.out.println("--------");
System.out.println("Starting engine...");
m.startEngine();
}
};
//sa se testeze operatorii in Java
package j1;
class ArithmeticTest

12
{
public static void main (String args[])
{
short x = 6;
int y = 4;
float a = 12.5f;
float b = 7f;

System.out.println("x is " + x + ", y is


" + y);
System.out.println("x + y = " + (x + y));
System.out.println("x - y = " + (x - y));
System.out.println("x / y = " + (x / y));
System.out.println("x % y = " + (x % y));

System.out.println("a is " + a + ", b is


" + b);
System.out.println("a / b = " + (a / b));
}
}
//sa se testeze operatorii de
postdecrementare,postincrementare.preincrementare,predecrementare in
Java
package j1;
class PrePostFixTest
{

public static void main (String args[])


{
int x = 0;
int y = 0;
System.out.println("x and y are " + x + " and "
+ y );
x++;
System.out.println("x++ results in " + x);
++x;
System.out.println("++x results in " + x);
System.out.println("Resetting x back to 0.");
x = 0;
System.out.println("------------");
y = x++;
System.out.println("y = x++ (postfix) results
in:");
System.out.println("x is " + x);
System.out.println("y is " + y);
System.out.println("------------");

y = ++x;
System.out.println("y = ++x (prefix) results
in:");
System.out.println("x is " + x);
System.out.println("y is " + y);
System.out.println("------------");

}
}
//sa se testeze operatorii de rezervare de memorie si importul de
biblioteci
package j1;
import java.util.Date;

13
class CreateDates
{

public static void main(String args[])


{
Date d1, d2, d3;

d1 = new Date();
System.out.println("Date 1: " +
d1);

d2 = new Date(71, 7, 1,
7, 30);
System.out.println("Date 2: " +
d2);

d3 = new Date("April 3
1993 3:24 PM");
System.out.println("Date 3: " +
d3);
}
}
//sa se testeze operatorii de rezervare de memorie PENTRU
COORDONATELE UNOR PUNCTE si importul de biblioteci
package j1;
import java.awt.Point;

class TestPoint
{
public static void main(String args[])
{
Point thePoint = new Point(10,10);

System.out.println("X is " +
thePoint.x);
System.out.println("Y is " + thePoint.y);

System.out.println("Setting X to
5.");
thePoint.x = 5;
System.out.println("Setting Y to 15.");
thePoint.y = 15;

System.out.println("X is " +
thePoint.x);
System.out.println("Y is " + thePoint.y);

}
}
//sa se testeze METODELE care actioneaza asupra unui sir de
caractere
package j1;
class TestString
{

public static void main(String args[])


{
String str = "Now is the winter of our
discontent";

14
System.out.println("The string
is: " + str);
System.out.println("Length of this
string: "
+ str.length());
System.out.println("The character at
position 5: "
+ str.charAt(5));
System.out.println("The substring from
11 to 17: "
+ str.substring(11, 17));
System.out.println("The index of the
character d: "
+ str.indexOf('d'));
System.out.print("The index of the
beginning of the ");

System.out.println("substring \"winter\": "


+ str.indexOf("winter"));
System.out.println("The string in upper
case: "
+ str.toUpperCase());
}
}
//sa se testeze referirea la coordonatele unui obiect de tip PUNCT
package j1;
import java.awt.Point;

class ReferencesTest
{
public static void main (String args[])
{
Point pt1, pt2;
pt1 = new Point(100, 100);
pt2 = pt1;

pt1.x = 200;
pt1.y = 200;
System.out.println("Point1: " +
pt1.x + ", " + pt1.y);
System.out.println("Point2: " +
pt2.x + ", " + pt2.y);
}
}
//sa se testeze operatorul de egalitate la siruri de caractere
package j1;
class EqualsTest
{
public static void main(String args[])
{
String str1, str2;
str1 = "she sells sea shells by the sea
shore.";
str2 = str1;

System.out.println("String1: " +
str1);
System.out.println("String2: " + str2);
System.out.println("Same object? " + (str1 ==
str2));

15
str2 = new String(str1);

System.out.println("String1: " +
str1);
System.out.println("String2: " + str2);
System.out.println("Same object? " + (str1 ==
str2));
System.out.println("Same value? " +
str1.equals(str2));
}
}
//sa se testeze rolul operatorului NEW care rezerva memkorie
// la un vector de siruri de caractere
package j1;
class ArrayTest
{

String[] firstNames = { "Dennis", "Grace", "Bjarne",


"James" };
String[] lastNames = new String[firstNames.length];

void printNames()
{
int i = 0;
System.out.println(firstNames[i]
+ " " + lastNames[i]);
i++;
System.out.println(firstNames[i]
+ " " + lastNames[i]);
i++;
System.out.println(firstNames[i]
+ " " + lastNames[i]);
i++;
System.out.println(firstNames[i]
+ " " + lastNames[i]);
}

public static void main (String args[])


{
ArrayTest a = new ArrayTest();
a.printNames();
System.out.println("----------");
a.lastNames[0] = "Ritchie";
a.lastNames[1] = "Hopper";
a.lastNames[2] = "Stroustrup";
a.lastNames[3] = "Gosling";
a.printNames();
}
}
//sa se testeze structura IF

package j1;
class Peeper
{

void peepMe(int val)


{
System.out.println("Value is "
+ val + ". ");
if (val % 2 == 0)

16
System.out.println("Peep!");
}

public static void main (String args[])


{
Peeper p = new Peeper();

p.peepMe(1);
p.peepMe(2);
p.peepMe(54);
p.peepMe(77);
p.peepMe(1346);
}
}
//sa se testeze structura switch

package j1;
class NumberReader
{

String convertNum(int val)


{
switch (val)
{
case 0: return "zero ";
case 1: return "one ";
case 2: return "two ";
case 3: return "three ";
case 4: return "four ";
case 5: return "five ";
case 6: return "six ";
case 7: return "seven ";
case 8: return "eight ";
case 9: return "nine ";
default: return " ";
}
}

public static void main (String args[])


{
NumberReader n = new NumberReader();
String num = n.convertNum(4) +
n.convertNum(1) + n.convertNum(5);
System.out.println("415 converts to " +
num);
}
}
//sa se testeze structura FOR

package j1;
class ArrayTest
{

String[] firstNames = { "Dennis", "Grace", "Bjarne", "James" };


String[] lastNames = new String[firstNames.length];
void printNames()
{
for (int i = 0; i < firstNames.length; i++)
System.out.println(firstNames[i] + " " + lastNames[i]);
}

17
};
class NamesLoop
{

String[] firstNames = { "Dennis", "Grace", "Bjarne",


"James" };
String[] lastNames = new String[firstNames.length];

void printNames()
{
for (int i = 0; i < firstNames.length; i++)

System.out.println(firstNames[i] + " " + lastNames[i]);


}

public static void main (String args[])


{
ArrayTest a = new ArrayTest();
a.printNames();
System.out.println("----------");
a.lastNames[0] = "Ritchie";
a.lastNames[1] = "Hopper";
a.lastNames[2] = "Stroustrup";
a.lastNames[3] = "Gosling";

a.printNames();
}
}
//sa se testeze structura WHILE

package j1;
class ArrayTest
{

String[] firstNames = { "Dennis", "Grace", "Bjarne", "James" };


String[] lastNames = new String[firstNames.length];
void printNames()
{
for (int i = 0; i < firstNames.length; i++)
System.out.println(firstNames[i] + " " + lastNames[i]);
}
};

class CopyArrayWhile
{
public static void main (String args[])
{
int[] array1 = { 5, 7, 3, 6, 0, 3, 2, 1 };
float[] array2 = new float[array1.length];

System.out.print("array1: [ ");
for (int i = 0; i < array1.length; i++)
{

System.out.print(array1[i] + " ");


}
System.out.println("]");

System.out.print("array2: [ ");
int count = 0;

18
while ( count < array1.length &&
array1[count] != 0)
{
array2[count] =
(float) array1[count];

System.out.print(array2[count++] + " ");


}
System.out.println("]");
}
}
//sa se testeze structura DO..WHILE

package j1;
class DoTest
{
public static void main (String args[])
{
int x = 1;

do
{

System.out.println("Looping, round " + x);


x++;
} while (x <=
10);
}
}
//sa se testeze structura SALTULUI LA O ANUMITA ETICHETA

package j1;
class LabelTest
{
public static void main (String arg[])
{

foo:
for (int i = 1; i <= 5; i++)
for (int j = 1; j <= 3;
j++)
{

System.out.println("i is " + i + ", j is " + j);

if (( i + j) > 4)

break foo;
}
System.out.println("end of loops");
}
}
Capitolul 2
Obiecte şi clase
2.1 Ciclul de viaţă al unui obiect
2.1.1 Crearea obiectelor
In Java, ca în orice limbaj de programare • Declararea
orientat-obiect, crearea obiectelor Presupune specificarea tipului acelui obiect, cu
se realizează prin instanţierea unei clase şi alte cuvinte specificarea
implică următoarele lucruri:

19
clasei acestuia (vom vedea că tipul unui obiect Rectangle patrat = new Rectangle(0, 0, 100,
poate fi şi o interfaţă). 100);
NumeClasa numeObiect; Obiecte anonime
• Instanţierea Este posibilă şi crearea unor obiecte anonime
Se realizează prin intermediul operatorului care servesc doar pentru
new şi are ca efect crearea iniţializarea altor obiecte, caz în care etapa de
efectivă a obiectului cu alocarea spaţiului de declarare a referinţei obiectului
memorie corespunzător. nu mai este prezentă:
numeObiect = new NumeClasa(); Rectangle patrat = new Rectangle(new
• Iniţializarea Point(0,0),
Se realizează prin intermediul constructorilor new Dimension(100, 100));
clasei respective. Iniţializarea Spaţiul de memorie nu este pre-alocat
este de fapt parte integrantă a procesului de Declararea unui obiect nu implică sub nici o
instanţiere, în sensul că formă alocarea de spaţiu
imediat după alocarea memoriei ca efect al de memorie pentru acel obiect. Alocarea
operatorului new este apelat memoriei se face doar la apelul
constructorul specificat. Parantezele rotunde de operatorului new.
după numele clasei indic Rectangle patrat;
ă faptul că acolo este de fapt un apel la unul patrat.x = 10;
din constructorii clasei //Eroare - lipseste instantierea
şi nu simpla specificare a numelui clasei. 2.1.2 Folosirea obiectelor
Mai general, instanţierea şi iniţializarea apar Odată un obiect creat, el poate fi folosit în
sub forma: următoarele sensuri: aflarea unor
numeObiect = new NumeClasa([argumente informaţii despre obiect, schimbarea stării sale
constructor]); sau executarea unor acţiuni.
Să considerăm următorul exemplu, în care Aceste lucruri se realizeaza prin aflarea sau
declarăm şi instanţiem două schimbarea valorilor variabilelor
obiecte din clasa Rectangle, clasă ce descrie sale, respectiv prin apelarea metodelor sale.
suprafeţe grafice rectangulare, Referirea valorii unei variabile se face prin
definite de coordonatele colţului stânga sus obiect.variabila De exemplu
(originea) şi lăţimea, respectiv clasa Rectangle are variabilele publice x, y,
înălţimea. width, height, origin.
Rectangle r1, r2; Aflarea valorilor acestor variabile sau
r1 = new Rectangle(); schimbarea lor se face prin construcţii
r2 = new Rectangle(0, 0, 100, 200); de genul:
In primul caz Rectangle() este un apel către Rectangle patrat = new Rectangle(0, 0, 100,
constructorul clasei Rectangle 200);
care este responsabil cu iniţializarea obiectului System.out.println(patrat.width); //afiseaza 100
cu valorile implicite. După patrat.x = 10;
cum observăm în al doilea caz, iniţializarea se patrat.y = 20; //schimba originea
poate face şi cu anumiţi parametri, patrat.origin = new Point(10, 20); //schimba
cu condiţia să existe un constructor al clasei originea
respective care să accepte Accesul la variabilele unui obiect se face în
parametrii respectivi. conformitate cu drepturile de
Fiecare clasă are un set de constructori care se acces pe care le oferă variabilele respective
ocupă cu iniţializare celorlalte clase. (vezi ”Modificatori
obiectelor nou create. De exemplu, clasa de acces pentru membrii unei clase”)
Rectangle are următorii constructori: Apelul unei metode se face prin
public Rectangle() obiect.metoda([parametri]).
public Rectangle(int latime, int inaltime) Rectangle patrat = new Rectangle(0, 0, 100,
public Rectangle(int x, int y, int latime, int 200);
inaltime) patrat.setLocation(10, 20); //schimba originea
public Rectangle(Point origine) patrat.setSize(200, 300); //schimba
public Rectangle(Point origine, int latime, int dimensiunea
inaltime) Se observă că valorile variabilelor pot fi
public Rectangle(Point origine, Dimension modificate indirect prin intermediul
dimensiune) metodelor sale. Programarea orientată obiect
Declararea, instanţierea şi iniţializarea descurajează folosirea
obiectului pot apărea pe aceeaşi directă a variabilelor unui obiect deoarece
linie (cazul cel mai uzual): acesta poate fi adus în stări inconsistente

20
(ireale). In schimb, pentru fiecare variabilă sunt folosite, fără a forţa însă pornirea
care descrie starea procesului.
obiectului trebuie să existe metode care să Finalizare
permită schimbarea/aflarea valorilor Inainte ca un obiect să fie eliminat din
variabilelor sale. Acestea se numesc metode de memorie, procesul gc dă acelui
accesare, sau metode obiect posibilitatea ”să cureţe după el”,
setter - getter şi au numele de forma apelând metoda de finalizare a obiectului
setVariabila, respectiv getVariabila. respectiv. Uzual, în timpul finalizării un obiect
patrat.width = -100; //stare inconsistenta îşi inchide fisierele şi
patrat.setSize(-100, -200); //metoda setter socket-urile folosite, distruge referinţele către
//metoda setSize poate sa testeze daca noile alte obiecte (pentru a uşsura
valori sunt sarcina colectorului de gunoaie), etc.
//corecte si sa valideze sau nu schimbarea lor Codul pentru finalizarea unui obiect trebuie
2.1.3 Distrugerea obiectelor scris într-o metodă specială
Multe limbaje de programare impun ca numita finalize a clasei ce descrie obiectul
programatorul să ţină evidenţa obiectelor respectiv. (vezi ”Clasa Object”)
create şi să le distrugă în mod explicit atunci Atenţie
când nu mai este nevoie de ele, Nu confundati metoda finalize din Java cu
cu alte cuvinte să administreze singur memoria destructorii din C++. Metoda
ocupată de obiectele sale. finalize nu are rolul de a distruge obiectul ci
Practica a demonstrat că această tehnică este este apelată automat înainte de
una din principalele furnizoare eliminarea obiectului respectiv din memorie.
de erori ce duc la funcţionarea defectuoasă a 2.2 Crearea claselor
programelor. 2.2.1 Declararea claselor
In Java programatorul nu mai are Clasele reprezintă o modalitate de a introduce
responsabilitatea distrugerii obiectelor noi tipuri de date într-o
sale întrucât, în momentul rulării unui aplicaţie Java, cealaltă modalitate fiind prin
program, simultan cu interpretorul intermediul interfeţelor. Declararea
Java, rulează şi un proces care se ocupă cu unei clase respectă următorul format general:
distrugerea obiectelor care nu [public][abstract][final]class NumeClasa
mai sunt folosite. Acest proces pus la [extends NumeSuperclasa]
dispoziţie de platforma Java de lucru [implements Interfata1 [, Interfata2 ... ]]
se numeşte garbage collector (colector de {
gunoi), prescurtat gc. // Corpul clasei
Un obiect este eliminat din memorie de }
procesul de colectare atunci când Aşadar, prima parte a declaraţiei o ocupă
nu mai există nici o referinţă la acesta. modificatorii clasei. Aceştia
Referinţele (care sunt de fapt variabile) sunt:
sunt distruse două moduri: • public
• natural, atunci când variabila respectivă iese Implicit, o clasă poate fi folosită doar de
din domeniul său de vizibilitate, clasele aflate în acelaşi pachet(
de exemplu la terminarea metodei în care ea a librărie) cu clasa respectivă (dacă nu se
fost declarată; specifică un anume pachet,
• explicit, dacă atribuim variabilei respective toate clasele din directorul curent sunt
valoare null. considerate a fi în acelaşi
Cum funcţionează colectorul de gunoaie ? pachet). O clasă declarată cu public poate fi
Colectorul de gunoaie este un proces de folosită din orice altă
prioritate scazută care se execut clasă, indiferent de pachetul în care se găseşte.
ă periodic, scanează dinamic memoria ocupată • abstract
de programul Java aflat Declară o clasă abstractă (şablon). O clasă
în execuţie şi marchează acele obiecte care au abstractă nu poate fi
referinţe directe sau indirecte. instanţiată, fiind folosită doar pentru a crea un
După ce toate obiectele au fost parcurse, cele model comun pentru o
care au rămas nemarcate sunt serie de subclase. (vezi ”Clase şi metode
eliminate automat din memorie. abstracte”)
Apelul metodei gc din clasa System sugerează • final
maşinii virtuale Java să Declară că respectiva clasă nu poate avea
”depună eforturi” în recuperarea memoriei subclase. Declarare claselor
ocupate de obiecte care nu mai finale are două scopuri:

21
– securitate: unele metode pot aştepta ca metodelor unei clase trebuie să se facă
parametru un obiect al obligatoriu în corpul clasei.
unei anumite clase şi nu al unei subclase, dar // C++
tipul exact al unui class A {
obiect nu poate fi aflat cu exactitate decat în void metoda1();
momentul executiei; int metoda2() {
în felul acesta nu s-ar mai putea realiza // Implementare
obiectivul limbajului Java }
ca un program care a trecut compilarea să nu }
mai fie susceptibil A::metoda1() {
de nici o eroare. // Implementare
– programare în spririt orientat-obiect: O clasa }
”perfectă” nu trebuie // Java
să mai aibă subclase. class A {
După numele clasei putem specifica, dacă este void metoda1(){
cazul, faptul că respectiva // Implementare
clasă este subclasă a unei alte clase cu numele }
NumeSuperclasa sau/şi că void metoda2(){
implementează una sau mai multe interfeţe, ale // Implementare
căror nume trebuie separate }
prin virgulă. }
2.2.2 Extinderea claselor Variabilele unei clase pot avea acelaşi nume cu
Spre deosebire de alte limbaje de programare metodele clasei, care poate
orientate-obiect, Java permite fi chiar numele clasei, fără a exista
doar moştenirea simplă, ceea ce îneamnă că o posibilitatea apariţiei vreunei ambiguităţi
clasă poate avea un singur din punctul de vedere al compilatorului. Acest
părinte (superclasă). Evident, o clasă poate lucru este însă total nerecomandat
avea oricâti moştenitori (subclase), dacă ne gândim din perspectiva lizibilităţii
de unde rezultă că mulţimea tuturor claselor (clarităţii) codului,
definite în Java poate fi dovedind un stil ineficient de progamare.
vazută ca un arbore, rădăcina acestuia fiind class A {
clasa Object. Aşadar, Object int A;
este singura clasă care nu are părinte, fiind void A() {};
foarte importantă în modul de // Corect pentru compilator
lucru cu obiecte si structuri de date în Java. // Nerecomandat ca stil de programare
xtinderea unei clase se realizează folosind }
cuvântul cheie extends: Atenţie
class B extends A {...} Variabilele şi metodele nu pot avea ca nume un
// A este superclasa clasei B cuvânt cheie Java.
// B este o subclasa a clasei A 2.2.4 Constructorii unei clase
O subclasă moşteneşte de la părintele său toate Constructorii unei clase sunt metode speciale
variabilele şi metodele care au acelaşi nume cu cel
care nu sunt private. al clasei, nu returnează nici o valoare şi sunt
2.2.3 Corpul unei clase folosiţi pentru iniţializarea
Corpul unei clase urmează imediat după obiectelor acelei clase în momentul instanţierii
declararea clasei şi este cuprins între lor.
acolade. Conţinutul acestuia este format din: class NumeClasa {
• Declararea şi, eventual, iniţializarea [modificatori] NumeClasa([argumente]) {
variabilelor de instanţă şi de clasă // Constructor
(cunoscute împreună ca variabile membre). }
• Declararea şi implementarea constructorilor. }
• Declararea şi implementarea metodelor de O clasă poate avea unul sau mai mulţi
instanţa şi de clasă (cunoscute constructori care trebuie însă să
împreună ca metode membre). difere prin lista de argumente primite. In felul
• Declararea unor clase imbricate (interne). acesta sunt permise diverse
Spre deosebire de C++, nu este permisă doar tipuri de iniţializări ale obiectelor la crearea
declararea metodeiîn corpul lor, în funcţie de numărul parametrilor
clasei, urmând ca implementare să fie facută în cu care este apelat constructorul.
afara ei. Implementarea Să considerăm ca exemplu declararea unei
clase care descrie noţiunea de

22
dreptunghi şi trei posibili constructori pentru Să presupunem că dorim să creăm clasa Patrat,
aceasta clasă. derivată din clasa Dreptunghi:
class Dreptunghi { class Patrat extends Dreptunghi {
double x, y, w, h; Patrat(double x, double y, double d) {
Dreptunghi(double x1, double y1, double w1, super(x, y, d, d);
double h1) { // Apelam constructorul superclasei
// Cel mai general constructor }
x=x1; y=y1; w=w1; h=h1; }
System.out.println("Instantiere dreptunghi"); Atenţie
} Apelul explcit al unui constructor nu poate
Dreptunghi(double w1, double h1) { apărea decât într-un alt constructor
// Constructor cu doua argumente si trebuie să fie prima instrucţiune din
x=0; y=0; w=w1; h=h1; constructorul respectiv.
System.out.println("Instantiere dreptunghi"); Constructorul implicit
} Constructorii sunt apelaţi automat la
Dreptunghi() { instanţierea unui obiect. In cazul
// Constructor fara argumente în care scriem o clasă care nu are declarat nici
x=0; y=0; w=0; h=0; un constructor, sistemul îi
System.out.println("Instantiere dreptunghi"); creează automat un constructor implicit, care
} nu primeşte nici un argument
} şi care nu face nimic. Deci prezenţa
Constructorii sunt apelaţi automat la constructorilor în corpul unei clase nu
instanţierea unui obiect. In cazul este obligatorie. Dacă însă scriem un
în care dorim să apelăm explicit constructorul constructor pentru o clasă, care are mai
unei clase folosim expresia mult de un argument, atunci constructorul
this( argumente ), implicit (fără nici un argument)
care apelează constructorul corespunzător (ca nu va mai fi furnizat implicit de către sistem.
argumente) al clasei respective. Să considerăm, ca exemplu,
Această metodă este folosită atunci când sunt următoarele declaraţii de clase:
implementaţi mai mulţi class Dreptunghi {
constructori pentru o clasă, pentru a nu repeta double x, y, w, h;
secvenţele de cod scrise deja // Nici un constructor
la constructorii cu mai multe argumente (mai }
generali). Mai eficient, fără class Cerc {
a repeta aceleaşi secvenţe de cod în toţi double x, y, r;
constructorii (cum ar fi afişarea // Constructor cu 3 argumente
mesajului ”Instantiere dreptunghi”), clasa de Cerc(double x, double y, double r) { ... };
mai sus poate fi rescrisă astfel: }
class Dreptunghi { Să considerăm acum două instanţieri ale
double x, y, w, h; claselor de mai sus:
Dreptunghi(double x1, double y1, double w1, Dreptunghi d = new Dreptunghi();
double h1) { // Corect (a fost generat constructorul implicit)
// Implementam doar constructorul cel mai Cerc c;
general c = new Cerc();
x=x1; y=y1; w=w1; h=h1; // Eroare la compilare !
System.out.println("Instantiere dreptunghi"); c = new Cerc(0, 0, 100);
} // Varianta corecta
Dreptunghi(double w1, double h1) { In cazul moştenirii unei clase, instanţierea unui
this(0, 0, w1, h1); obiect din clasa extinsă
// Apelam constructorul cu 4 argumente implică instanţierea unui obiect din clasa
} părinte. Din acest motiv, fiecare
Dreptunghi() { constructor al clasei fiu va trebui să aibă un
this(0, 0); constructor cu aceeaşi signatură
// Apelam constructorul cu 2 argumente în părinte sau să apeleze explicit un constructor
} al clasei extinse folosind
} expresia super([argumente]), în caz contrar
Dintr-o subclasă putem apela explicit fiind semnalată o eroare la
constructorii superclasei cu expresia compilare.
super( argumente ). class A {
int x=1;

23
A(int x) { this.x = x;} unde un modificator poate fi :
} • un modificator de acces : public, protected,
class B extends A { private (vezi ”Modificatori
// Corect de acces pentru membrii unei clase”)
B() {super(2);} • unul din cuvintele rezervate: static, final,
B(int x) {super.x = x;} transient, volatile
} Exemple de declaraţii de variabile membre:
class C extends A { class Exemplu {
// Eroare la compilare ! double x;
C() {super.x = 2;} protected static int n;
C(int x) {super.x = x;} public String s = "abcd";
} private Point p = new Point(10, 10);
Constructorii unei clase pot avea următorii final static long MAX = 100000L;
modificatori de acces: }
public, protected, private şi cel implicit. Să analizăm modificatorii care pot fi specificaţi
• public pentru o variabilă, alţii
In orice altă clasă se pot crea instanţe ale clasei decât cei de acces care sunt tratati într-o
respective. secţiune separata: ”Specificatori
• protected de acces pentru membrii unei clase”.
Doar în subclase pot fi create obiecte de tipul • static
clasei respective. Prezenţa lui declară că o variabilă este
• private variabilă de clasă şi nu de
In nici o altă clasă nu se pot instanţia obiecte instanţă. (vezi ”Membri de instanţa şi membri
ale acestei clase. O astfel de clasă”)
de clasă poate conţine metode publice (numite int variabilaInstanta ;
”factory methods”) static int variabilaClasa;
care să fie responsabile cu crearea obiectelor, • final
controlând în felul acesta Indică faptul că valoarea variabilei nu mai
diverse aspecte legate de instanţierea clasei poate fi schimbată, cu alte
respective. cuvinte este folosit pentru declararea
• implicit constantelor.
Doar în clasele din acelaşi pachet se pot crea final double PI = 3.14 ;
instanţe ale clasei respective. ...
2.2.5 Declararea variabilelor PI = 3.141; // Eroare la compilare !
Variabilele membre ale unei clase se declară Prin convenţie, numele variabilelor finale se
de obicei înaintea metodelor, scriu cu litere mari. Folosirea
deşi acest lucru nu este impus de către lui final aduce o flexibilitate sporită în lucrul
compilator. cu constante, în sensul
class NumeClasa { că valoarea unei variabile nu trebuie
// Declararea variabilelor specificată neapărat la declararea
// Declararea metodelor ei (ca în exemplul de mai sus), ci poate fi
} specificată şi ulterior într-un
Variabilele membre ale unei clase se declară în constructor, după care ea nu va mai putea fi
corpul clasei şi nu în corpul modificată.
unei metode, fiind vizibile în toate metodele class Test {
respectivei clase. Variabilele final int MAX;
declarate în cadrul unei metode sunt locale Test() {
metodei respective. MAX = 100; // Corect
Declararea unei variabile presupune MAX = 200; // Eroare la compilare !
specificarea următoarelor lucruri: }
• numele variabilei }
• tipul de date al acesteia • transient
• nivelul de acces la acea variabila din alte Este folosit la serializarea obiectelor, pentru a
clase specifica ce variabile
• dacă este constantă sau nu membre ale unui obiect nu participă la
• dacă este variabilă de instanţă sau de clasă serializare. (vezi ”Serializarea
• alţi modificatori obiectelor”)
Generic, o variabilă se declară astfel: • volatile
[modificatori] Tip numeVariabila [ = Este folosit pentru a semnala compilatorului să
valoareInitiala ]; nu execute anumite

24
optimizări asupra membrilor unei clase. Este o synchronized
facilitate avansată a Să analizăm modificatorii care pot fi specificaţi
limbajului Java. pentru o metodă, alţii
2.2.6 this şi super decât cei de acces care sunt trataţi într-o
Sunt variabile predefinite care fac referinţa, în secţiune separată.
cadrul unui obiect, la obiectul • static
propriu-zis (this), respectiv la instanţa Prezenţa lui declară că o metodă este de clasă
părintelui (super). Sunt folosite şi nu de instanţă. (vezi
în general pentru a rezolva conflicte de nume ”Membri de instanţa şi membri de clasă”)
prin referirea explicită a unei void metodaInstanta();
variabile sau metode membre. După cum am static void metodaClasa();
văzut, utilizate sub formă de • abstract
metode au rolul de a apela constructorii Permite declararea metodelor abstracte. O
corespunzători ca argumente ai clasei metodă abstractă este o
curente, respectiv ai superclasei metodă care nu are implementare şi trebuie
class A { obligatoriu să facă parte
int x; dintr-o clasă abstractă. (vezi ”Clase şi metode
A() { abstracte”)
this(0); • final
} Specifică faptul că acea metoda nu mai poate fi
A(int x) { supradefinită în subclasele
this.x = x; clasei în care ea este definită ca fiind finală.
} Acest lucru este
void metoda() { util dacă respectiva metodă are o implementare
x ++; care nu trebuie schimbat
} ă sub nici o formă în subclasele ei, fiind critică
} pentru consistenţa
class B extends A { stării unui obiect. De exemplu, studenţilor unei
B() { universităţi trebuie să
this(0); li se calculeze media finala, în funcţie de
} notele obţinute la examene,
B(int x) { în aceeaşi manieră, indiferent de facultatea la
super(x); care sunt.
System.out.println(x); class Student {
} ...
void metoda() { final float calcMedie(float note[], float
super.metoda(); ponderi[]) {
System.out.println(x); ...
} }
} ...
2.3 Implementarea metodelor }
2.3.1 Declararea metodelor class StudentInformatica extends Student {
Metodele sunt responsabile cu descrierea float calcMedie(float note[], float ponderi[]) {
comportamentului unui obiect. Intruc return 10.00;
ât Java este un limbaj de programare complet }
orientat-obiect, metodele }// Eroare la compilare !
se pot găsi doar în cadrul claselor. Generic, o • native
metodă se declară astfel: In cazul în care avem o librărie importantă de
[modificatori] TipReturnat numeMetoda funcţii scrise în alt limbaj
( [argumente] ) de programare, cum ar fi C, C++ şi limbajul de
[throws TipExceptie1, TipExceptie2, ...] asamblare, acestea
{ pot fi refolosite din programele Java.
// Corpul metodei Tehnologia care permite acest
} lucru se numeşte JNI (Java Native Interface) şi
unde un modificator poate fi : permite asocierea dintre
• un specificator de acces : public, protected, metode Java declarate cu native şi metode
private (vezi ”Specificatori native scrise în limbajele
de acces pentru membrii unei clase”) de programare menţionate.
• unul din cuvintele rezervate: static, abstract, • synchronized
final, native,

25
Este folosit în cazul în care se lucrează cu mai specificate la declararea metodei. De exemplu,
multe fire de execuţie iar fie clasa Poligon şi subclasa
metoda respectivă gestionează resurse comune. acesteia Patrat.
Are ca efect construirea Poligon metoda1( ) {
unui monitor care nu permite executarea Poligon p = new Poligon();
metodei, la un moment dat, Patrat t = new Patrat();
decât unui singur fir de execuţie. (vezi ”Fire de if (...)
executie”) return p; // Corect
2.3.2 Tipul returnat de o metodă else
Metodele pot sau nu să returneze o valoare la return t; // Corect
terminarea lor. Tipul returnat }
poate fi atât un tip primitiv de date sau o Patrat metoda2( ) {
referinţă la un obiect al unei clase. Poligon p = new Poligon();
In cazul în care o metodă nu returnează nimic Patrat t = new Patrat();
atunci trebuie obligatoriu if (...)
specificat cuvântul cheie void ca tip returnat: return p; // Eroare
public void afisareRezultat() { else
System.out.println("rezultat"); return t; // Corect
} }
private void deseneaza(Shape s) { 2.3.3 Trimiterea parametrilor către o
... metodă
return; Signatura unei metode este dată de numarul şi
} tipul argumentelor primite
Dacă o metodă trebuie să returneze o valoare de acea metodă. Tipul de date al unui argument
acest lucru se realizează prin poate fi orice tip valid al
intermediul instrucţiunii return, care trebuie să limbajului Java, atât tip primitiv cât şi tip
apară în toate situaţiile de referinţă.
terminare a funcţiei. TipReturnat metoda([Tip1 arg1, Tip2 arg2, ...])
double radical(double x) { Exemplu:
if (x >= 0) void adaugarePersoana(String nume, int varsta,
return Math.sqrt(x); float salariu)
else { // String este tip referinta
System.out.println("Argument negativ !"); // int si float sunt tipuri primitive
// Eroare la compilare Spre deosebire de alte limbaje, în Java nu pot fi
// Lipseste return pe aceasta ramura trimise ca parametri ai
} unei metode referinţe la alte metode (funcţii),
} însă pot fi trimise referinţe la
In cazul în care în declaraţia funcţiei tipul obiecte care să conţină implementarea acelor
returnat este un tip primitiv de metode, pentru a fi apelate.
date, valoarea returnată la terminarea funcţiei Pâna la apariţia versiunii 1.5, în Java o metodă
trebuie să aibă obligatoriu acel nu putea primi un număr
tip sau un subtip al său, altfel va fi furnizată o variabil de argumente, ceea ce înseamna că
eroare la compilare. In general, apelul unei metode trebuia să se
orice atribuire care implică pierderi de date facă cu specificarea exactă a numarului şi
este tratată de compilator ca tipurilor argumentelor. Vom analiza
eroare. într-o secţiune separată modalitate de
int metoda() { specificare a unui număr variabil
return 1.2; // Eroare de argumente pentru o metodă.
} Numele argumentelor primite trebuie să difere
int metoda() { între ele şi nu trebuie să coincid
return (int)1.2; // Corect ă cu numele nici uneia din variabilele locale
} ale metodei. Pot însă să
double metoda() { coincidă cu numele variabilelor membre ale
return (float)1; // Corect clasei, caz în care diferenţierea
} dintre ele se va face prin intermediul variabile
Dacă valoarea returnată este o referinţă la un this.
obiect al unei clase, atunci class Cerc {
clasa obiectului returnat trebuie să coincidă sau int x, y, raza;
să fie o subclasă a clasei public Cerc(int x, int y, int raza) {
this.x = x;

26
this.y = y; param.x = x;
this.raza = raza; param.y = y;
} param.raza = raza;
} }
In Java argumentele sunt trimise doar prin }
valoare (pass-by-value). Argumentul param are tip referinţă şi, deşi nu
Acest lucruînseamnă că metoda recepţionează îi schimbăm valoarea (valoarea
doar valorile variabilelor primite sa este adresa de memorie la care se gaseşte şi
ca parametri. nu poate fi schimbată),
Când argumentul are tip primitiv de date, putem schimba starea obiectului, adică
metoda nu-i poate schimba valoarea informaţia propriu-zisă conţinută de
decât local (în cadrul metodei); la revenirea din acesta.
metodă variabila are Varianta de mai sus a fost dată pentru a
aceeaşi valoare ca înaintea apelului, clarifica modul de trimitere a
modificările făcute în cadrul metodei fi- argumentelor unei metode. Pentru a aflaînsă
ind pierdute. valorile variabilelor care descriu
Când argumentul este de tip referinţă, metoda starea unui obiect se folosesc metode de tip
nu poate schimba valoarea getter însoţite de metode setter
referinţei obiectului, însă poate apela metodele care să permită schimbarea stării obiectului:
acelui obiect şi poate modifica class Cerc {
orice variabilă membră accesibilă. private int x, y, raza;
Aşadar, dacă dorim ca o metodă să schimbe public int getX() {
starea (valoarea) unui argument return x;
primit, atunci el trebuie să fie neaparat de tip }
referinţă. public void setX(int x) {
De exemplu, să considerăm clasa Cerc descrisă this.x = x;
anterior în care dorim să }
implementăm o metodă care să returneze ...
parametrii cercului. }
// Varianta incorecta: 2.3.4 Metode cu număr variabil de
class Cerc { argumente
private int x, y, raza; Incepând cu versiunea 1.5 a limbajului Java,
public void aflaParametri(int valx, int valy, int există posibilitate de a declara
valr) { metode care să primească un număr variabil de
// Metoda nu are efectul dorit! argumente. Noutatea constă
valx = x; în folosirea simbolului ..., sintaxa unei astfel de
valy = y; metode fiind:
valr = raza; [modificatori] TipReturnat
} metoda(TipArgumente ... args)
} args reprezintă un vector având tipul specificat
Această metodă nu va realiza lucrul propus şi instanţiat cu un număr
întrucât ea primeşte doar variabil de argumente, în funcţie de apelul
valorile variabilelor valx, valy şi valr şi nu metodei. Tipul argumentelor
referinţe la ele (adresele lor poate fi referinţă sau primitiv. Metoda de mai
de memorie), astfel încât să le poată modifica jos afişează argumentele primite,
valorile. In concluzie, metoda care pot fi de orice tip:
nu realizează nimic pentru că nu poate schimba void metoda(Object ... args) {
valorile variabilelor primite for(int i=0; i<args.length; i++)
ca argumente. System.out.println(args[i]);
Pentru a rezolva lucrul propus trebuie să }
definim o clasă suplimentară ...
care să descrie parametrii pe care dorim să-i metoda("Hello");
aflăm: metoda("Hello", "Java", 1.5);
// Varianta corecta 2.3.5 Supraîncărcarea şi supradefinirea
class Param { metodelor
public int x, y, raza; Supraîncărcarea şi supradefinirea metodelor
} sunt două concepte extrem de
class Cerc { utile ale programării orientate obiect,
private int x, y, raza; cunoscute şi sub denumirea de polimor-
public void aflaParametri(Param param) { fism, şi se referă la:

27
• supraîncarcarea (overloading) : în cadrul unei metodele abstracte ale superclasei (dacă este
clase pot exista metode cazul). In cazul în care o clasă
cu acelaşi nume cu condiţia ca signaturile lor nu supradefineşte toate metodele abstracte ale
să fie diferite (lista de părintelui, ea însăşi este abstract
argumente primite să difere fie prin numărul ă şi va trebui declarată ca atare.
argumentelor, fie prin In Java nu este posibilă supraîncărcarea
tipul lor) astfel încât la apelul funcţiei cu acel operatorilor.
nume să se poată stabili 2.4 Modificatori de acces
în mod unic care dintre ele se execută. Modificatorii de acces sunt cuvinte rezervate
• supradefinirea (overriding): o subclasă poate ce controlează accesul celorlate
rescrie o metodă a clasei clase la membrii unei clase. Specificatorii de
părinte prin implementarea unei metode cu acces pentru variabilele
acelaşi nume şi aceeaşi şi metodele unei clase sunt: public, protected,
signatură ca ale superclasei. private şi cel implicit (la
class A { nivel de pachet), iar nivelul lor de acces este
void metoda() { dat în tabelul de mai jos:
System.out.println("A: metoda fara Specificator Clasa Sublasa Pachet Oriunde
parametru"); private X
} protected X X* X
// Supraincarcare public X X X X
void metoda(int arg) { implicit X X
System.out.println("A: metoda cu un Aşadar, dacă nu este specificat nici un
parametru"); modificator de acces, implicit
} nivelul de acces este la nivelul pachetului. In
} cazul în care declarăm un
class B extends A { membru ”protected” atunci accesul la acel
// Supradefinire membru este permis din subclasele
void metoda() { clasei în care a fost declarat dar depinde şi de
System.out.println("B: metoda fara pachetul în care se gaseşte
parametru"); subclasa: dacă sunt în acelaşi pachet accesul
} este permis, dacă nu sunt în
} acelaşi pachet accesul nu este permis decât
O metodă supradefinită poate să: pentru obiecte de tipul subclasei.
• ignore complet codul metodei Exemple de declaraţii:
corespunzătoare din superclasă (cazul private int secretPersonal;
de mai sus): protected String secretDeFamilie;
B b = new B(); public Vector pentruToti;
b.metoda(); long doarIntrePrieteni;
// Afiseaza "B: metoda fara parametru" private void metodaInterna();
• extindă codul metodei părinte, executând public String informatii();
înainte de codul propriu şi 2.5 Membri de instanţă şi membri de clasă
funcţia părintelui: O clasă Java poate conţine două tipuri de
class B extends A { variabile şi metode :
// Supradefinire prin extensie • de instanţă: declarate fără modificatorul
void metoda() { static, specifice fiecărei
super.metoda(); instanţe create dintr-o clasă şi
System.out.println("B: metoda fara • de clasă: declarate cu modificatorul static,
parametru"); specifice clasei.
} 2.5.1 Variabile de instanţă şi de clasă
} Când declarăm o variabilă membră fără
... modificatorul static, cum ar fi x în
B b = new B(); exemplul de mai jos:
b.metoda(); class Exemplu {
/* Afiseaza ambele mesaje: int x ; //variabila de instanta
"A: metoda fara parametru" }
"B: metoda fara parametru" */ se declară de fapt o variabilă de instanţă, ceea
O metodă nu poate supradefini o metodă ce înseamnă că la fiecare creare
declarată finală în clasa părinte. a unui obiect al clasei Exemplu sistemul alocă
Orice clasă care nu este abstractă trebuie o zonă de memorie separată
obligatoriu să supradefinească pentru memorarea valorii lui x.

28
Exemplu o1 = new Exemplu(); n ++; // Corect
o1.x = 100; x --; // Corect
Exemplu o2 = new Exemplu(); }
o2.x = 200; static void metodaStatica() {
System.out.println(o1.x); // Afiseaza 100 n ++; // Corect
System.out.println(o2.x); // Afiseaza 200 x --; // Eroare la compilare !
Aşadar, fiecare obiect nou creat va putea }
memora valori diferite pentru }
variabilele sale de instanţă. Intocmai ca şi la variabilele statice, întrucât
Pentru variabilele de clasă (statice) sistemul metodele de clasă nu depind
alocă o singură zonă de memorie de starea obiectelor clasei respective, apelul lor
la care au acces toate instanţele clasei se poate face şi sub forma:
respective, ceea ce înseamnă că NumeClasa.numeMetodaStatica
dacă un obiect modifică valoarea unei variabile Exemplu.metodaStatica(); // Corect, echivalent
statice ea se va modifica şi cu
pentru toate celelalte obiecte. Deoarece nu Exemplu obj = new Exemplu();
depind de o anumită instanţă a obj.metodaStatica(); // Corect, de asemenea
unei clase, variabilele statice pot fi referite şi Metodele de instanţă nu pot fi apelate decât
sub forma: pentru un obiect al clasei
NumeClasa.numeVariabilaStatica respective:
class Exemplu { Exemplu.metodaDeInstanta(); // Eroare la
int x ; // Variabila de instanta compilare !
static long n; // Variabila de clasa Exemplu obj = new Exemplu();
} obj.metodaDeInstanta(); // Corect
... 2.5.3 Utilitatea membrilor de clasă
Exemplu o1 = new Exemplu(); Membrii de clasă sunt folosiţi pentru a pune la
Exemplu o2 = new Exemplu(); dispoziţie valori şi metode
o1.n = 100; independente de starea obiectelor dintr-o
System.out.println(o2.n); // Afiseaza 100 anumita clasă.
o2.n = 200; Declararea eficientă a constantelor
System.out.println(o1.n); // Afiseaza 200 Să considerăm situaţia când dorim să declarăm
System.out.println(Exemplu.n); // Afiseaza o constantă.
200 class Exemplu {
// o1.n, o2.n si Exemplu.n sunt referinte la final double PI = 3.14;
aceeasi valoare // Variabila finala de instanta
Iniţializarea variabilelor de clasă se face o }
singură dată, la încărcarea în La fiecare instanţiere a clasei Exemplu va fi
memorie a clasei respective, şi este realizată rezervată o zonă de memorie
prin atribuiri obişnuite: pentru variabilele finale ale obiectului
class Exemplu { respectiv, ceea ce este o risipă întrucât
static final double PI = 3.14; aceste constante au aceleaşi valori pentru toate
static long nrInstante = 0; instanţele clasei. Declararea
static Point p = new Point(0,0); corectă a constantelor trebuie aşadar facută cu
} modificatorii static şi final,
2.5.2 Metode de instanţă şi de clasă pentru a le rezerva o singură zonă de memorie,
Similar ca la variabile, metodele declarate fără comună tuturor obiectelor:
modificatorul static sunt class Exemplu {
metode de instanţă iar cele declarate cu static static final double PI = 3.14;
sunt metode de clasă (statice). // Variabila finala de clasa
Diferenţa între cele două tipuri de metode este }
următoarea: Numărarea obiectelor unei clase
• metodele de instanţă operează atât pe Numărarea obiectelor unei clase poate fi făcută
variabilele de instanţă cât şi pe extrem de simplu folosind
cele statice ale clasei; o variabilă statică şi este utilă în situaţiile când
• metodele de clasă operează doar pe trebuie să controlăm diverşi
variabilele statice ale clasei. parametri legaţi de crearea obiectelor unei
class Exemplu { clase.
int x ; // Variabila de instanta class Exemplu {
static long n; // Variabila de clasa static long nrInstante = 0;
void metodaDeInstanta() { Exemplu() {

29
// Constructorul este apelat la fiecare int t=1;
instantiere y = 2;
nrInstante ++; z = x + y + t;
} }
} Test() {
Implementarea funcţiilor globale /* La executia constructorului
Spre deosebire de limbajele de programare variabilele de clasa sunt deja initializate si
procedurale, în Java nu putem toate blocurile statice de initializare au
avea funcţii globale definite ca atare, întrucât fost obligatoriu executate in prealabil.
”orice este un obiect”. Din */
acest motiv chiar şi metodele care au o ...
funcţionalitate globală trebuie implementate }
în cadrul unor clase. Acest lucru se va face }
prin intermediul 2.6 Clase imbricate
metodelor de clasă (globale), deoarece acestea 2.6.1 Definirea claselor imbricate
nu depind de starea particular O clasă imbricată este, prin definiţie, o clasă
ă a obiectelor din clasa respectivă. De membră a unei alte clase, numită
exemplu, să considerăm funcţia şi clasă de acoperire. In funcţie de situaţie,
sqrt care extrage radicalul unui număr şi care definirea unei clase interne se
se găseşte în clasa Math. Dacă poate face fie ca membru al clasei de acoperire
nu ar fi fost funcţie de clasă, apelul ei ar fi - caz în care este accesibilă
trebuit făcut astfel (incorect, de tuturor metodelor, fie local în cadrul unei
altfel): metode.
// Incorect ! class ClasaDeAcoperire{
Math obj = new Math(); class ClasaImbricata1 {
double rad = obj.sqrt(121); // Clasa membru
ceea ce ar fi fost extrem de neplăcut... Fiind }
însă metodă statică ea poate fi void metoda() {
apelată prin: Math.sqrt(121) . class ClasaImbricata2 {
Aşadar, funcţiile globale necesare unei aplicaţii // Clasa locala metodei
vor fi grupate corespunzător }
în diverse clase şi implementate ca metode }
statice. }
2.5.4 Blocuri statice de iniţializare Folosirea claselor imbricate se face atunci când
Variabilele statice ale unei clase sunt o clasă are nevoie în implementarea
iniţializate la un moment care precede ei de o altă clasă şi nu există nici un motiv
prima utilizare activă a clasei respective. pentru care aceasta
Momentul efectiv depinde de implementarea din urmă să fie declarată de sine stătătoare (nu
maşinii virtuale Java şi poartă numele de mai este folosită nicăieri).
iniţializarea clasei. Pe O clasă imbricată are un privilegiu special faţă
lângă setarea valorilor variabilelor statice, în de celelalte clase şi anume
această etapă sunt executate şi acces nerestricţionat la toate variabilele clasei
blocurile statice de iniţializare ale clasei. de acoperire, chiar dacă acestea
Acestea sunt secvenţe de cod de sunt private. O clasă declarată locală unei
forma: metode va avea acces şi la
static { variabilele finale declarate în metoda
// Bloc static de initializare; respectivă.
... class ClasaDeAcoperire{
} private int x=1;
care se comportă ca o metodă statică apelată class ClasaImbricata1 {
automat de către maşina virtual int a=x;
ă. Variabilele referite într-un bloc static de }
iniţializare trebuie să fie void metoda() {
obligatoriu de clasă sau locale blocului: final int y=2;
public class Test { int z=3;
// Declaratii de variabile statice class ClasaImbricata2 {
static int x = 0, y, z; int b=x;
// Bloc static de initializare int c=y;
static { int d=z; // Incorect
System.out.println("Initializam..."); }

30
} class ClasaDeAcoperire{
} class ClasaInterna1 {}
O clasă imbricată membră (care nu este locală class ClasaInterna2 {}
unei metode) poate fi }
referită din exteriorul clasei de acoperire Pentru exemplul de mai sus vor fi generate trei
folosind expresia fişiere:
ClasaDeAcoperire.ClasaImbricata ClasaDeAcoperire.class
Aşadar, clasele membru pot fi declarate cu ClasaDeAcoperire$ClasaInterna1.class
modificatorii public, protected, ClasaDeAcoperire$ClasaInterna2.class
private pentru a controla nivelul lor de acces In cazul în care clasele imbricate au la rândul
din exterior, întocmai ca orice lor alte clase imbricate
variabilă sau metodă mebră a clasei. Pentru (situaţie mai puţin uzuală) denumirea lor se
clasele imbricate locale unei face după aceeaşi regulă: adăugarea
metode nu sunt permişi acesţi modificatori. unui ’$’ şi apoi numele clasei imbricate.
Toate clasele imbricate pot fi declarate 2.6.4 Clase anonime
folosind modificatorii abstract şi Există posibilitatea definirii unor clase
final, semnificaţia lor fiind aceeaşi ca şi în imbricate locale, fără nume, utilizate
cazul claselor obişnuite. doar pentru instanţierea unui obiect de un
2.6.2 Clase interne anumit tip. Astfel de clase se
Spre deosebire de clasele obişnuite, o clasă numesc clase anonime şi sunt foarte utile în
imbricată poate fi declarată statică situaţii cum ar fi crearea unor
sau nu. O clasă imbricată nestatică se numeşte obiecte ce implementează o anumită interfaţă
clasa internă. sau extind o anumită clasă
class ClasaDeAcoperire{ abstractă.
... Exemple de folosire a claselor anonime vor fi
class ClasaInterna { date în capitolul ”Interfeţe”,
... precum şi extensiv în capitolul ”Interfaţa
} grafică cu utilizatorul”.
static class ClasaImbricataStatica { Fişierele rezultate în urma compilării claselor
... anonime vor avea numele
} de forma ClasaAcoperire.$1,...,
} ClasaAcoperire.$n, unde n este numărul
Diferenţierea acestor denumiri se face de clase anonime definite în clasa respectivă de
deoarece: acoperire.
• o ”clasă imbricată” reflectă relaţia sintactică a 2.7 Clase şi metode abstracte
două clase: codul unei Uneori în proiectarea unei aplicaţii este necesar
clase apare în interiorul codului altei clase; să reprezentăm cu ajutorul
• o ”clasă internă” reflectă relaţia dintre claselor concepte abstracte care să nu poată fi
instanţele a două clase, în sensul instanţiate şi care să folosească
că o instanţa a unei clase interne nu poate doar la dezvoltarea ulterioară a unor clase ce
exista decat în cadrul unei descriu obiecte concrete. De exemplu,
instanţe a clasei de acoperire. în pachetul java.lang există clasa abstractă
In general, cele mai folosite clase imbricate Number care modelează
sunt cele interne. conceptul generic de ”număr”. Intr-un program
Aşadar, o clasă internă este o clasă imbricată nu avem însă nevoie de numere
ale carei instanţe nu pot generice ci de numere de un anumit tip: întregi,
exista decât în cadrul instanţelor clasei de reale, etc. Clasa Number
acoperire şi care are acces direct serveşte ca superclasă pentru clasele concrete
la toţi membrii clasei sale de acoperire. Byte, Double, Float, Integer,
2.6.3 Identificare claselor imbricate Long şi Short, ce implementează obiecte
După cum ştim orice clasă produce la pentru descrierea numerelor de un
compilare aşa numitele ”unităţi de compilare”, anumit tip. Aşadar, clasa Number reprezintă un
care sunt fişiere având numele clasei respective concept abstract şi nu vom
şi extensia .class putea instanţia obiecte de acest tip - vom folosi
şi care conţin toate informaţiile despre clasa în schimb subclasele sale.
respectivă. Pentru clasele imbricate Number numar = new Number(); // Eroare
aceste unităţi de compilare sunt denumite Integer intreg = new Integer(10); // Corect
astfel: numele clasei de 2.7.1 Declararea unei clase abstracte
acoperire, urmat de simbolul ’$’ apoi de Declararea unei clase abstracte se face folosind
numele clasei imbricate. cuvântul rezervat abstract:

31
[public] abstract class ClasaAbstracta originii. Implementarea clasei abstracte
[extends Superclasa] GraphicObject ar putea arăta
[implements Interfata1, Interfata2, ...] { astfel:
// Declaratii uzuale abstract class GraphicObject {
// Declaratii de metode abstracte // Stari comune
} private int x, y;
O clasă abstractă poate avea modificatorul private Color color = Color.black;
public, accesul implicit fiind ...
la nivel de pachet, dar nu poate specifica // Metode comune
modificatorul final, combinaţia public void setX(int x) {
abstract final fiind semnalată ca eroare la this.x = x;
compilare - de altfel, o clasă }
declarată astfel nu ar avea nici o utilitate. public void setY(int y) {
O clasă abstractă poate conţine aceleaşi this.y = y;
elemente membre ca o clasă }
obişnuită, la care se adaugă declaraţii de public void setColor(Color color) {
metode abstracte - fără nici o implementare. this.color = color;
2.7.2 Metode abstracte }
Spre deosebire de clasele obişnuite care trebuie ...
să furnizeze implementări // Metode abstracte
pentru toate metodele declarate, o clasă abstract void draw();
abstractă poate conţine metode fără ...
nici o implementare. Metodele fara nici o }
implementare se numesc metode O subclasă care nu este abstractă a unei clase
abstracte şi pot apărea doar în clase abstracte. abstracte trebuie să furnizeze
In faţa unei metode abstracte obligatoriu implementări ale metodelor
trebuie să apară obligatoriu cuvântul cheie abstracte definite în superclasă. Implementarea
abstract, altfel va fi furnizată o claselor pentru obiecte grafice ar fi:
eroare de compilare. class Circle extends GraphicObject {
abstract class ClasaAbstracta { void draw() {
abstract void metodaAbstracta(); // Corect // Obligatoriu implementarea
void metoda(); // Eroare ...
} }
In felul acesta, o clasă abstractă poate pune la }
dispoziţia subclaselor sale class Rectangle extends GraphicObject {
un model complet pe care trebuie să-l void draw() {
implementeze, furnizând chiar implementarea // Obligatoriu implementarea
unor metode comune tuturor claselor şi lăsând ...
explicitarea altora }
fiecărei subclase în parte. }
Un exemplu elocvent de folosire a claselor şi Legat de metodele abstracte, mai trebuie
metodelor abstracte este descrierea menţionate următoarele:
obiectelor grafice într-o manieră orientată- • O clasă abstractă poate să nu aibă nici o
obiect. metodă abstractă.
• Obiecte grafice: linii, dreptunghiuri, cercuri, • O metodă abstractă nu poate apărea decât
curbe Bezier, etc într-o clasă abstractă.
• Stări comune: poziţia(originea), dimensiunea, • Orice clasă care are o metodă abstractă
culoarea, etc trebuie declarată ca fiind abstract
• Comportament: mutare, redimensionare, ă.
desenare, colorare, etc. In API-ul oferit de platforma de lucru Java
Pentru a folosi stările şi comportamentele sunt numeroase exemple de
comune acestor obiecte în avantajul ierarhii care folosesc la nivelele superioare
nostru putem declara o clasă generică clase abstracte. Dintre cele mai
GraphicObject care să fie superclas importante amintim:
ă pentru celelalte clase. Metodele abstracte vor • Number: superclasa abstractă a tipurilor
fi folosite pentru implementarea referinţă numerice
comportamentului specific fiecărui obiect, cum • Reader, Writer: superclasele abstracte ale
ar fi desenarea fluxurilor de intrare/ieşire
iar cele obişnuite pentru comportamentul pe caractere
comun tuturor, cum ar fi schimbarea

32
• InputStream, OutputStream: superclasele clone). Clonarea unui obiect presupune crearea
abstracte ale fluxurilor de unui nou obiect de
intrare/ieşire pe octeţi acelaşi tip şi care să aibă aceeaşi stare (aceleaşi
• AbstractList, AbstractSet, AbstractMap: valori pentru variabilele
superclase abstracte pentru sale).
structuri de date de tip colecţie • equals, hashCode
• Component : superclasa abstractă a Acestea sunt, de obicei, supradefinite
componentelor folosite în dezvoltarea împreună. In metoda equals este
de aplicaţii cu interfaţă grafică cu utilizatorul scris codul pentru compararea egalităţii
(GUI), cum ar conţinutului a două obiecte.
fi Frame, Button, Label, etc. Implicit (implementarea din clasa Object),
• etc. această metodă compară
2.8 Clasa Object referinţele obiectelor. Uzual este redefinită
2.8.1 Orice clasă are o superclasă pentru a testa dacă stările
După cum am văzut în secţiunea dedicată obiectelor coincid sau dacă doar o parte din
modalităţii de creare a unei clase, variabilele lor coincid.
clauza ”extends” specifică faptul că acea clasă Metoda hashCode returneaza un cod întreg
extinde (moşteneşte) o altă pentru fiecare obiect, pentru
clasă, numită superclasă. O clasă poate avea o a testa consistenţa obiectelor: acelaşi obiect
singură superclasă (Java nu trebuie să returneze
suportă moştenirea multiplă) şi chiar dacă nu acelaşi cod pe durata execuţiei programului.
specificăm clauza ”extends” la Dacă două obiecte sunt egale conform metodei
crearea unei clase ea totuşi va avea o equals, atunci apelul
superclasă. Cu alte cuvinte, în Java metodei hashCode pentru fiecare din cele două
orice clasă are o superclasă şi numai una. obiecte ar trebui să
Evident, trebuie să existe o excepţie returneze acelaşi intreg.
de la această regulă şi anume clasa care • finalize
reprezintă rădăcina ierarhiei formată In această metodă se scrie codul care ”curăţă
de relaţiile de moştenire dintre clase. Aceasta după un obiect”înainte de
este clasa Object. a fi eliminat din memorie de colectorul de
Clasa Object este şi superclasa implicită a gunoaie. (vezi ”Distrugerea
claselor care nu specifică o obiectelor”)
anumită superclasă. Declaraţiile de mai jos • toString
sunt echivalente: Este folosită pentru a returna o reprezentare ca
class Exemplu {} şir de caractere a unui
class Exemplu extends Object {} obiect. Este utilă pentru concatenarea şirurilor
2.8.2 Clasa Object cu diverse obiecte în
Clasa Object este cea mai generală dintre clase, vederea afişării, fiind apelată automat atunci
orice obiect fiind, direct când este necesară transformarea
sau indirect, descendent al acestei clase. Fiind unui obiect în şir de caractere.
părintele tuturor, Object Exemplu obj = new Exemplu();
defineşte şi implementează comportamentul System.out.println("Obiect=" + obj);
comun al tuturor celorlalte clase //echivalent cu
Java, cum ar fi: System.out.println("Obiect=" + obj.toString());
• posibilitatea testării egalităţii valorilor Să considerăm următorul exemplu, în care
obiectelor, implementăm parţial clasa
• specificarea unei reprezentări ca şir de numerelor complexe, şi în care vom
caractere a unui obiect , supradefini metode ale clasei Object.
• returnarea clasei din care face parte un obiect, De asemenea, vom scrie un mic program
• notificarea altor obiecte că o variabilă de TestComplex în care vom testa
condiţie s-a schimbat, etc. metodele clasei definite.
Fiind subclasă a lui Object, orice clasă îi poate Listing 2.1: Clasa numerelor complexe
supradefini metodele class Complex {
care nu sunt finale. Metodele cel mai uzual private double a; // partea reala
supradefinite sunt: clone, private double b; // partea imaginara
equals/hashCode, finalize, toString. public Complex ( double a, double b) {
• clone this .a = a;
Această metodă este folosită pentru duplicarea this .b = b;
obiectelor (crearea unor }
public Complex () {

33
this (1, 0); obiect având o anumită valoare primitivă şi
} metode specializate pentru conversia
public boolean equals ( Object obj) { unui obiect în tipul primitiv corespunzător, de
if (obj == null ) return false ; genul tipPrimitivValue:
if (!( obj instanceof Complex )) return false ; Integer obi = new Integer(1);
Complex comp = ( Complex ) obj; int i = obi.intValue();
return ( comp .a==a && comp .b==b); Boolean obb = new Boolean(true);
} boolean b = obb.booleanValue();
public Object clone () { Incepând cu versiunea 1.5 a limbajului Java,
return new Complex (a, b); atribuirile explicite între
} tipuri primitve şi referinţă sunt posibile, acest
public String toString () { mecanism purtând numele de
String semn = (b > 0 ? "+" : "-"); autoboxing, respectiv auto-unboxing.
return a + semn + b + "i"; Conversia explicită va fi facută de către
} compilator.
public Complex aduna ( Complex comp ) { // Doar de la versiunea 1.5 !
Complex suma = new Complex (0, 0); Integer obi = 1;
suma .a = this .a + comp .a; int i = obi;
suma .b = this .b + comp .b; Boolean obb = true;
return suma ; boolean b = obb;
} 2.10 Tipul de date enumerare
} Incepând cu versiunea 1.5 a limbajului Java,
există posibilitatea de a defini
public class TestComplex { tipuri de date enumerare prin folosirea
public static void main ( String c[]) { cuvântului cheie enum. Acestă
Complex c1 = new Complex (1 ,2); soluţie simplifică manevrarea grupurilor de
Complex c2 = new Complex (2 ,3); constante, după cum reiese din
Complex c3 = ( Complex ) c1. clone (); următorul exemplu:
System . out. println (c1. aduna (c2)); // 3.0 + public class CuloriSemafor {
5.0i public static final int ROSU = -1;
System . out. println (c1. equals (c2)); // false public static final int GALBEN = 0;
System . out. println (c1. equals (c3)); // true public static final int VERDE = 1;
} }
} ...
2.9 Conversii automate între tipuri // Exemplu de utilizare
După cum văzut tipurile Java de date pot fi if (semafor.culoare = CuloriSemafor.ROSU)
împărţie în primitive şi referinţă. semafor.culoare = CuloriSemafor.GALBEN);
Pentru fiecare tip primitiv există o clasă ...
corespunzătoare care permie lucrul Clasa de mai sus poate fi rescrisă astfel:
orientat obiect cu tipul respectiv. public enum CuloriSemafor { ROSU,
byte Byte GALBEN, VERDE };
short Short ...
int Integer // Utilizarea structurii se face la fel
long Long ...
float Float if (semafor.culoare = CuloriSemafor.ROSU)
double Double semafor.culoare = CuloriSemafor.GALBEN);
char Character ...
boolean Boolean Compilatorul este responsabil cu transformarea
Fiecare din aceste clase are un constructor ce unei astfel de structuri
permite iniţializarea unui într-o clasă corespunzătoare.

CLASE
//sa se defineasca o clasa cu o metoda specifica de initializare a
unui vector

package j1;
class RangeClass
{
int[] makeRange(int lower, int upper)

34
{
int arr[] = new int[ (upper -
lower) + 1 ];

for (int i = 0; i <


arr.length; i++)
{

arr[i] = lower++;
}
return arr;
}

public static void main(String arg[])


{
int theArray[];
RangeClass theRange = new
RangeClass();

theArray =
theRange.makeRange(1, 10);
System.out.print("The array:
[ ");
for (int i = 0; i <
theArray.length; i++)
{

System.out.print(theArray[i] + " ");


}
System.out.println("]");
}

}
//sa se defineasca o clasa cu o metoda CARE SA FIE PROCEDURA

package j1;
class ScopeTest
{
int test = 10;

void printTest ()
{
int test = 20;
System.out.println("test = " + test);
}

public static void main (String args[])


{
ScopeTest st = new ScopeTest();
st.printTest();
}
}
//sa se defineasca o clasa cu o metoda CARE sa inlocuiasca pe 1 cu 3
// intr-un vector

package j1;

class PassByReference
{
int onetoZero(int arg[])
{

35
int count = 0;

for (int i = 0; i < arg.length;


i++)
{
if
(arg[i] == 1)

count++;

arg[i] = 0;

}
}
return count;
}
public static void main (String arg[])
{
int arr[] = { 1, 3, 4, 5, 1, 1, 7 };
PassByReference test = new
PassByReference();
int numOnes;

System.out.print("Values of
the array: [ ");
for (int i = 0; i < arr.length; i++)
{

System.out.print(arr[i] + " ");


}
System.out.println("]");

numOnes =
test.onetoZero(arr);
System.out.println("Number of Ones =
" + numOnes);
System.out.print("New values of the
array: [ ");
for (int i = 0; i < arr.length; i++)
{

System.out.print(arr[i] + " ");


}
System.out.println("]");
}
}
//sa se numere numarul de instate (chemari) ale unei metode
package j1;

import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;

36
import java.awt.Image;
import java.applet.AudioClip;
import java.awt.Event;
import java.awt.Point;
import java.awt.*;
import java.net.*;
import java.net.MalformedURLException;
import java.awt.*;
import java.io.DataInputStream;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.net.MalformedURLException;

public class CountInstances


{
private static int numInstances = 0;

protected static int getNumInstances()


{
return numInstances;
}

private static void addInstance()


{
numInstances++;
}

CountInstances()
{
CountInstances.addInstance();
}

public static void main(String args[])


{
System.out.println("Starting with " +
CountInstances.getNumInstances() + " instances");
for (int i = 0; i < 10; ++i)
new CountInstances();
System.out.println("Created " +
CountInstances.getNumInstances() + " instances");
}
}

//sa se defineasca o clasa cu o metode CARE sa determine ccordonatele


unui dreptunghi

package j1;

import java.awt.Point;

class MyRect
{
int x1 = 0;
int y1 = 0;
int x2 = 0;
int y2 = 0;

MyRect buildRect(int x1, int y1, int x2, int y2)


{

37
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
return this;
}

MyRect buildRect(Point topLeft, Point bottomRight)


{
x1 = topLeft.x;
y1 = topLeft.y;
x2 = bottomRight.x;
y2 = bottomRight.y;
return this;
}

MyRect buildRect(Point topLeft, int w, int h)


{
x1 = topLeft.x;
y1 = topLeft.y;
x2 = (x1 + w);
y2 = (y1 + h);
return this;
}

void printRect()
{
System.out.print("MyRect: <" + x1 +
", " + y1);
System.out.println(", " + x2 + ", "
+ y2 + ">");
}

public static void main(String args[])


{
MyRect rect = new MyRect();

System.out.println("Calling
buildRect with coordinates 25,25,50,50:");
rect.buildRect(25, 25, 50, 50);
rect.printRect();
System.out.println("----------");

System.out.println("Calling
buildRect w/points (10,10), (20,20):");
rect.buildRect(new Point(10,10), new
Point(20,20));
rect.printRect();
System.out.println("----------");

System.out.print("Calling
buildRect w/1 point (10,10),");
System.out.println(" width (50) and
height (50):");

rect.buildRect(new
Point(10,10), 50, 50);
rect.printRect();
System.out.println("----------");
}
}

38
CONSTRUCTORI
//sa se defineasca o clasa cu o metoda si UN CONCTRUCTOR
package j1;

class Person
{
String name;
int age;

Person(String n, int a)
{
name = n;
age = a;
}

void printPerson()
{
System.out.print("Hi, my name is " +
name);
System.out.println(". I am " + age + "
years old.");
}

public static void main (String args[])


{
Person p;
p = new Person("Laura", 20);
p.printPerson();
System.out.println("--------");
p = new Person("Tommy", 3);
p.printPerson();
System.out.println("--------");
}
}
//sa se defineasca o clasa cu o metoda si UN CONCTRUCTOR
package j1;

import java.awt.Point;

class MyRect2
{
int x1 = 0;
int y1 = 0;
int x2 = 0;
int y2 = 0;

MyRect2(int x1, int y1, int x2, int y2)


{
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
}

MyRect2(Point topLeft, Point bottomRight)


{
x1 = topLeft.x;
y1 = topLeft.y;
x2 = bottomRight.x;

39
y2 = bottomRight.y;
}

MyRect2(Point topLeft, int w, int h)


{
x1 = topLeft.x;
y1 = topLeft.y;
x2 = (x1 + w);
y2 = (y1 + h);
}

void printRect()
{
System.out.print("MyRect: <" + x1
+ ", " + y1);
System.out.println(", " + x2 + ",
" + y2 + ">");
}

public static void main(String args[])


{
MyRect2 rect;

System.out.println("Calling MyRect2 with coordinates 25,25 50,50:");


rect = new MyRect2(25, 25, 50,50);
rect.printRect();
System.out.println("----------");

System.out.println("Calling MyRect2 w/points (10,10), (20,20):");


rect= new MyRect2(new
Point(10,10), new Point(20,20));
rect.printRect();
System.out.println("----------");

System.out.print("Calling MyRect2 w/1 point (10,10)");


System.out.println(" width (50) and
height (50):");
rect = new MyRect2(new
Point(10,10), 50, 50);
rect.printRect();
System.out.println("----------");

}
}
//sa se defineasca o clasa cu o metoda si O SUBCLASA
package j1;
class PrintClass
{
int x = 0;
int y = 1;

void printMe()
{
System.out.println("x is " + x + ", y
is " + y);
System.out.println("I am an instance of
the class " +
this.getClass().getName());

40
}
}

class PrintSubClass2 extends PrintClass


{
int z = 3;

void printMe()
{
System.out.println("x is " + x + ", y
is " + y +
", z is " + z);
System.out.println("I am an instance of
the class " +
this.getClass().getName());
}

public static void main(String args[])


{
PrintSubClass2 obj = new
PrintSubClass2();
obj.printMe();
}
}
//sa se defineasca o clasa cu o metoda si O SUBCLASA
package j1;
import java.awt.Point;
class NamedPoint extends Point
{
String name;

NamedPoint(int x, int y, String name)


{
super(x,y);
this.name = name;
}
public static void main (String arg[])
{
NamedPoint np = new NamedPoint(5, 5,
"SmallPoint");
System.out.println("x is " + np.x);
System.out.println("y is " + np.y);
System.out.println("Name is " +
np.name);
}
}
CREAREA UNUI APLET
Appleturi Ca orice altă aplicaţie Java, codul unui applet
3.1 Introducere poate fi format din una sau
Definiţie mai multe clase. Una dintre acestea este
Un applet reprezintă un program Java de principală şi extinde clasa Applet,
dimensiuni reduse ce gestionează aceasta fiind clasa ce trebuie specificată în
o suprafaţă de afişare (container) care poate fi documentul HTML ce descrie
inclusă într-o pagină Web. Un pagina Web în care dorim să includem
astfel de program se mai numeşte appletul.
miniaplicatie. Diferenţa fundamentală dintre un applet şi o
aplicaţie constă în faptul că

41
un applet nu poate fi executat independent, ci 3. Compilarea
va fi executat de browserul Compilarea se face la fel ca şi la aplicaţiile
în care este încărcată pagina Web ce conţine independente, folosind compilatorul
appletul respectiv. O aplicaţie javac apelat pentru fişierul ce conţine appletul.
independentă este executată prin apelul javac FirstApplet.java
interpretorului java, având ca argument In cazul în care compilarea a reuşit va fi
numele clasei principale a aplicaţiei, clasa generat fisierul FirstApplet.class.
principală fiind cea care 4. Rularea appletului
conţine metoda main. Ciclul de viată al unui Applet-urile nu ruleaza independent. Ele pot fi
applet este complet diferit, rulate doar prin intermediul
fiind dictat de evenimentele generate de către unui browser: Internet Explorer, Netscape,
browser la vizualizarea documentului Mozilla, Opera, etc. sau
HTML ce conţine appletul. printr-un program special cum ar fi
Pachetul care oferă suport pentru crearea de appletviewer din kitul de dezvoltare
appleturi este java.applet, J2SDK. Pentru a executa un applet trebuie să
cea mai importantă clasă fiind Applet. In facem două operaţii:
pachetul javax.swing există • Crearea unui fişier HTML în care vom
şi clasa JApplet, care extinde Applet, oferind include applet-ul. Să consider
suport pentru crearea de ăm fişierul simplu.html, având conţinutul de
appleturi pe arhitectura de componente mai jos:
JFC/Swing. <html>
Ierarhia claselor din care derivă appleturile este <head>
prezentata în figura de <title>Primul applet Java</title>
mai jos: </head>
Fiind derivată din clasa Container, clasa <body>
Applet descrie de fapt suprafeţe <applet code=FirstApplet.class width=400
de afişare, asemenea claselor Frame sau Panel. height=400>
3.2 Crearea unui applet simplu </applet>
Crearea structurii de fişiere şi compilarea </body>
applet-urilor sunt identice ca în </html>
cazul aplicaţiilor. Diferă în schimb structura • Vizualizarea appletului: se deschide fisierul
programului şi modul de rulare simplu.html folosind
a acestuia. Să parguream în continuare aceşti unul din browser-ele amintite sau efectuând
paşi pentru a realiza un applet apelul:
extrem de simplu, care afişează o imagine şi un appletviewer simplu.html.
şir de caractere. 3.3 Ciclul de viaţă al unui applet
1. Scrierea codului sursa Execuţia unui applet începe în momentul în
import java.awt.* ; care un browser afişează o pagină
import java.applet.* ; Web în care este inclus appletul respectiv şi
public class FirstApplet extends Applet { poate trece prin mai multe etape.
Image img; Fiecare etapă este strâns legată de un
public void init() { eveniment generat de către browser şi
img = getImage(getCodeBase(), "taz.gif"); determină apelarea unei metode specifice din
} clasa ce implementează appletul.
public void paint (Graphics g) { • Incărcarea în memorie
g.drawImage(img, 0, 0, this); Este creată o instanţa a clasei principale a
g.drawOval(100,0,150,50); appletului şi încarcată în
g.drawString("Hello! My name is Taz!", 110, memorie.
25); • Iniţializarea
} Este apelată metoda init ce permite iniţializarea
} diverselor variabile,
Pentru a putea fi executată de browser, clasa citirea unor parametri de intrare, etc.
principală a appletului trebuie • Pornirea
să fie publică. Este apelată metoda start
2. Salvarea fisierelor sursă • Execuţia propriu-zisă
Ca orice clasă publică, clasa principala a Constă în interacţiunea dintre utilizator şi
appletului va fi salvată într-un componentele afişate pe
fişier cu acelaşi nume şi extensia .java. Aşadar, suprafaţa appletului sau în executarea unui
vom salva clasa de mai sus anumit cod într-un fir de
într-un fişier FirstApplet.java.

42
execuţie. In unele situaţii întreaga execuţie a import java.awt.event.*;
appletului se consumă la public class StructuraApplet extends Applet {
etapele de iniţializare şi pornire. public void init() {
• Oprirea temporară }
In cazul în care utilizatorul părăseşte pagina public void start() {
Web în care rulează appletul }
este apelată metoda stop a acestuia, dându-i public void stop() {
astfel posibilitatea să }
opreasca temporar execuţia sa pe perioadaîn public void destroy() {
care nu este vizibil, pentru }
a nu consuma inutil din timpul procesorului. }
Acelaşi lucru se întâmplă 3.4 Interfaţa grafică cu utilizatorul
dacă fereastra browserului este minimizată. In După cum am văzut, clasa Applet este o
momentul când pagina extensie a superclasei Container,
Web ce contine appletul devine din nou activă, ceea ce înseamnă că appleturile sunt, înainte de
va fi reapelată metoda toate, suprafeţe de afişare.
start. Plasarea componentelor, gestionarea
• Oprirea definitivă poziţionării lor şi tratarea evenimentelor
La închiderea tuturor instanţelor browserului generate se realizează la fel ca şi în cazul
folosit pentru vizualizare, aplicaţiilor. Uzual, adăugarea componentelor
appletul va fi eliminat din memorie şi va fi pe suprafaţa appletului precum şi stabilirea
apelată metoda destroy a obiectelor responsabile
acestuia, pentru a-i permite să elibereze cu tratarea evenimentelor generate sunt
resursele deţinute. Apelul operaţiuni ce vor fi realizate în
metodei destroy este întotdeauna precedat de metoda init.
apelul lui stop. Gestionarul de poziţionare implicit este
Metodele specifice appleturilor FlowLayout, însă acesta poate fi
Aşadar, există o serie de metode specifice schimbat prin metoda setLayout.
appleturilor ce sunt apelate automat Desenarea pe suprafaţa unui applet
la diverse evenimente generate de către Există o categorie întreagă de appleturi ce nu
browser. Acestea sunt definite comunică cu utilizatorul
în clasa Applet şi sunt enumerate în tabelul de prin intermediul componentelor ci, execuţia lor
mai jos: se rezumă la diverse operaţiuni
Metoda Situaţia în care este apelată de desenare realizate în metoda paint.
init La iniţializarea appletului. Teoretic, Reamintim că metoda paint este responsabil
această metodă ă cu definirea aspectului grafic al oricărei
ar trebui să se apeleze o singură dată, la prima componente. Implicit,
afişare a appletului în pagină, însă, la unele metoda paint din clasa Applet nu realizează
browsere, nimic, deci, în cazul în care
este posibil ca ea să se apeleze de mai multe dorim să desenăm direct pe suprafaţa unui
ori. applet va fi nevoie să supradefinim
start Imediat după iniţializare şi de fiecare dată această metodă.
când appletul redevine activ, după o oprire public void paint(Graphics g) {
temporară. // Desenare
stop De fiecare dată când appletul nu mai este ...
vizibil }
(pagina Web nu mai este vizibilă, fereastra In cazul în care este aleasă această soluţie,
browserului evenimentele tratate uzual vor fi
este minimizată, etc) şi înainte de destroy. cele generate de mouse sau tastatură.
destroy La închiderea ultimei instanţe a 3.5 Definirea şi folosirea parametrilor
browserului Parametrii sunt pentru appleturi ceea ce
care a încărcat în memorie clasa principală a argumentele de la linia de comandă
appletului. sunt pentru aplicaţiile independente. Ei permit
Atenţie utilizatorului să personalizeze
Aceste metode sunt apelate automat de aspectul sau comportarea unui applet fără a-i
browser şi nu trebuie apelate schimba codul şi recompila
explicit din program ! clasele.
Structura generală a unui applet Definirea parametrilor se face în cadrul tagului
import java.applet.Applet; APPLET din documentul
import java.awt.*;

43
HTML ce conţine appletul şi sunt identificaţi Să scriem un applet care să afişeze un text
prin atributul PARAM. primit ca parametru, folosind
Fiecare parametru are un nume, specificat prin un font cu numele şi dimensiunea specificate
NAME şi o valoare, speci- de asemenea ca parametri.
ficată prin VALUE, ca în exemplul de mai jos: Listing 3.1: Folosirea parametrilor
<APPLET CODE="TestParametri.class" import java . applet . Applet ;
WIDTH=100 HEIGHT=50 import java . awt .*;
<PARAM NAME=textAfisat public class TestParametri extends Applet {
VALUE="Salut"> String text , numeFont ;
<PARAM NAME=numeFont int dimFont ;
VALUE="Times New Roman"> public void init () {
<PARAM NAME=dimFont VALUE=20> text = getParameter (" textAfisat ");
</APPLET> if ( text == null )
Ca şi în cazul argumentelor trimise aplicaţiilor text = " Hello "; // valoare implicita
de la linia de comandă, tipul numeFont = getParameter (" numeFont ");
parametrilor este întotdeauna şir de caractere, if ( numeFont == null )
indiferent dacă valoarea numeFont = " Arial ";
este între ghilimele sau nu. try {
Fiecare applet are şi un set de parametri dimFont = Integer . parseInt ( getParameter ("
prestabiliţi ale căror nume nu dimFont "));
vor putea fi folosite pentru definirea de noi } catch ( NumberFormatException e) {
parametri folosind metoda de dimFont = 16;
mai sus. Aceştia apar direct în corpul tagului }
APPLET şi definesc informaţii }
generale despre applet. Exemple de astfel de public void paint ( Graphics g) {
parametri sunt CODE, WIDTH sau g. setFont (new Font ( numeFont , Font .BOLD
HEIGHT. Lista lor completă va fi prezentata la , dimFont ));
descrierea tagului APPLET. g. drawString (text , 20, 20);
Folosirea parametrilor primiţi de către un }
applet se face prin intermediul public String [][] getParameterInfo () {
metodei getParameter care primeşte ca String [][] info = {
argument numele unui parametru // Nume Tip Descriere
şi returnează valoarea acestuia. In cazul în care {" textAfisat ", " String ", " Sirul ce va fi afisat
nu există nici un parametru "},
cu numele specificat, metoda întoarce null, caz {" numeFont ", " String ", " Numele fontului
în care programul trebuie "},
să atribuie o valoare implicită variabilei în care {" dimFont ", "int ", " Dimensiunea fontului "}
se dorea citirea respectivului };
parametru. return info ;
Orice applet poate pune la dispoziţie o }
”documentaţie” referitoare la parametrii }
pe care îi suportă, pentru a veni în ajutorul 3.6 Tag-ul APPLET
utilizatorilor care doresc să Sintaxa completă a tagului APPLET, cu
includă appletul într-o pagină Web. Aceasta se ajutorul căruia pot fi incluse appleturi
realizează prin supradefinirea în cadrul paginilor Web este:
metodei getParameterInfo, care returnează un <APPLET
vector format din triplete CODE = clasaApplet
de şiruri. Fiecare element al vectorului este de WIDTH = latimeInPixeli
fapt un vector cu trei elemente HEIGHT = inaltimeInPixeli
de tip String, cele trei şiruri reprezentând [ARCHIVE = arhiva.jar]
numele parametrului, tipul său şi [CODEBASE = URLApplet]
o descriere a sa. Informaţiile furnizate de un [ALT = textAlternativ]
applet pot fi citite din browserul [NAME = numeInstantaApplet]
folosit pentru vizualizare prin metode specifice [ALIGN = aliniere]
acestuia. De exemplu, în appletviewer [VSPACE = spatiuVertical]
informaţiile despre parametri pot fi vizualizate 14.6. TAG-UL APPLET 411
la rubrica Info din [HSPACE = spatiuOrizontal] >
meniul Applet, în Netscape se foloseşte [< PARAM NAME = parametru1 VALUE =
opţiunea Page info din meniul View, valoare1 >]
etc.

44
[< PARAM NAME = parametru2 VALUE = 3.7 Folosirea firelor de execuţie în appleturi
valoare2 >] La încărcarea unei pagini Web, fiecărui applet
... îi este creat automat un fir
[text HTML alternativ] de execuţie responsabil cu apelarea metodelor
</APPLET> acestuia. Acestea vor rula
Atributele puse între paranteze pătrate sunt concurent după regulile de planificare
opţionale. implementate de maşina virtuală Java
• CODE = clasaApplet a platformei folosite.
Numele fişierului ce conţine clasa principală a Din punctul de vedere al interfeţei grafice însă,
appletului. Acesta va fiecare applet aflat pe o
fi căutat în directorul specificat de paginăWeb are acces la un acelaşi fir de
CODEBASE. Nu poate fi absolut şi execuţie, creat de asemenea automat
trebuie obligatoriu specificat. Extensia ”.class” de către browser, şi care este responsabil cu
poate sau nu să apară. desenarea appletului (apelul
• WIDTH =latimeInPixeli, HEIGHT metodelor update şi paint) precum şi cu
=inaltimeInPixeli transmiterea mesajelor generate
Specifică lăţimea şi înălţimea suprafeţei în care de către componente. Intrucât toate appleturile
va fi afişat appletul. de pe pagină ”împart” acest
Sunt obligatorii. fir de execuţie, nici unul nu trebuie să îl
• ARCHIVE = arhiva.jar solicite în mod excesiv, deoarece va
Specifică arhiva în care se găsesc clasele provoca funcţionarea anormală sau chiar
appletului. blocarea celorlalte.
• CODEBASE = directorApplet In cazul în care dorim să efectuăm operaţiuni
Specifică URL-ul la care se găseşte clasa consumatoare de timp este
appletului. Uzual se exprimă recomandat să le realizăm într-un alt fir de
relativ la directorul documentului HTML. In execuţie, pentru a nu bloca
cazul în care lipseşte, se interacţiunea utilizatorului cu appletul,
consideră implicit URL-ul documentului. redesenarea acestuia sau activitatea
• ALT = textAlternativ celorlalte appleturi de pe pagină.
Specifică textul ce trebuie afişat dacă Să considermăm mai întâi două abordări
browserul înţelege tagul APPLET greşite de lucru cu appleturi.
dar nu poate rula appleturi Java. Dorim să creăm un applet care să afişeze la
• NAME =numeInstantaApplet coordonate aleatoare mesajul
Oferă posibilitatea de a da un nume respectivei ”Hello”, cu pauză de o secundă între două
instanţe a appletului, afişări. Prima variantă, greşită de
astfel încât mai multe appleturi aflate pe altfel, ar fi:
aceeaşi pagină să poată Listing 14.2: Incorect: blocarea metodei paint
comunica între ele folosindu-se de numele lor. import java . applet .*;
• ALIGN =aliniere import java . awt .*;
Semnifică modalitatea de aliniere a appletului public class AppletRau1 extends Applet {
în pagina Web. Acest public void paint ( Graphics g) {
atribut poate primi una din următoarele valori: while ( true ) {
left, right, top, int x = (int )( Math . random () * getWidth ());
texttop, middle, absmiddle, baseline, bottom, int y = (int )( Math . random () * getHeight ());
absbottom , seminificaţiile g. drawString (" Hello ", x, y);
lor fiind aceleaşi ca şi la tagul IMG. try {
• VSPACE =spatiuVertical, HSPACE = Thread . sleep (1000) ;
spatiuOrizontal } catch ( InterruptedException e) {}
Specifică numarul de pixeli dintre applet şi }
marginile suprafetei de }
afişare. }
• PARAM Motivul pentru care acest applet nu
Tag-urile PARAM sunt folosite pentru funcţionează corect şi probabil va
specificarea parametrilor unui applet duce la anomalii în funcţionarea browserului
(vezi ”Folosirea parametrilor”). este că firul de execuţie care
• text HTML alternativ se ocupă cu desenarea va rămâne blocat în
Este textul ce va fi afişat în cazul în care metoda paint, încercând să o
browserul nu întelege tagul termine. Ca regulă generală, codul metodei
APPLET. Browserele Java-enabled vor ignora paint trebuie să fie cât mai
acest text.

45
simplu de executat ceea ce, evident, nu este }
cazul în appletul de mai sus. public void paint ( Graphics g) {
O altă idee de rezolvare care ne-ar putea veni, g. drawString (" Hello ", x, y);
de asemenea greşită, este }
următoarea : }
Listing 3.3: Incorect: appletul nu termină In cazul în care firul de execuţie pornit de
iniţializarea applet efectuează operatii ce
import java . applet .*; au sens doar dacă appletul este vizibil, cum ar
import java . awt .*; fi animatie, ar fi de dorit
public class AppletRau2 extends Applet { ca acesta să se opreasca atunci când appletul
int x, y; nu mai este vizibil (la apelul
public void init () { metodei stop) şi să reporneasca atunci când
while ( true ) { appletul redevine vizibil (la
x = (int )( Math . random () * getWidth ()); apelul metodei start). Un applet este considerat
y = (int )( Math . random () * getHeight ()); activ imediat după apelul
repaint (); metodei start şi devine inactiv la apelul
try { metodei stop. Pentru a afla dacă
Thread . sleep (1000) ; un applet este activ se foloseşte metoda
} catch ( InterruptedException e) {} isActive.
} Să modificăm programul anterior, adăugând şi
} un contor care să numere
public void paint ( Graphics g) { afişările de mesaje - acesta nu va fi incrementat
g. drawString (" Hello ", x, y); pe perioada în care appletul
} nu este activ.
} Listing 3.5: Folosirea metodelor start şi stop
Pentru a putea da o soluţie corectă problemei import java . applet .*;
propuse, trebuie să folosim import java . awt .*;
un fir de execuţie propriu. Structura unui public class AppletCorect2 extends Applet
applet care doreste să lanseze un implements Runnable
fir de execuţie poate avea două forme. In prima {
situaţie appletul porneşte int x, y;
firul la iniţialzarea sa iar acesta va rula, Thread fir = null ;
indiferent dacă appletul mai este sau boolean activ = false ;
nu vizibil, până la oprirea sa naturală int n = 0;
(terminarea metodei run) sau până la public void start () {
închiderea sesiunii de lucru a browserului. if (fir == null ) {
Listing 3.4: Corect: folosirea unui fir de fir = new Thread ( this );
execuţie propriu activ = true ;
import java . applet .*; fir . start ();
import java . awt .*; }
public class AppletCorect1 extends Applet }
implements Runnable public void stop () {
{ activ = false ;
int x, y; fir = null ;
Thread fir = null ; }
public void init () { public void run () {
if (fir == null ) { while ( activ ) {
fir = new Thread ( this ); x = (int )( Math . random () * getWidth ());
fir . start (); y = (int )( Math . random () * getHeight ());
} n ++;
} repaint ();
public void run () { try {
while ( true ) { Thread . sleep (1000) ;
x = (int )( Math . random () * getWidth ()); } catch ( InterruptedException e) {}
y = (int )( Math . random () * getHeight ());
repaint (); }
try { }
Thread . sleep (1000) ; public void paint ( Graphics g) {
} catch ( InterruptedException e) {} g. drawString (" Hello " + n, x, y);
} }

46
} fie calea relativă la o anumită adresă URL,
Atenţie cum ar fi cea a directorului
Este posibil ca unele browsere să nu apele în care se găseşte documentul HTML ce
metoda stop în situaţiile conţine appletul (getDocumentBase)
prevăzute în specficiaţiile appleturilor. Din sau a directorului în care se găseşte clasa
acest motiv, corectitudinea unui appletului (getCodeBase).
applet nu trebuie să se bazeze pa acest Listing 3.6: Afişarea imaginilor
mecanism. import java . applet . Applet ;
3.8 Alte metode oferite de clasa Applet import java . awt .*;
Pe lângă metodele de bază: init, start, stop, public class Imagini extends Applet {
destroy, clasa Applet Image img = null ;
oferă metode specifice applet-urilor cum ar fi: public void init () {
Punerea la dispozitie a unor informaţii despre img = getImage ( getCodeBase () , "taz.gif");
applet }
Similară cu metoda getParameterInfo ce oferea public void paint ( Graphics g) {
o ”documentaţie” despre g. drawImage (img , 0, 0, this );
parametrii pe careîi acceptă un applet, există }
metoda getAppletInfo ce permite }
specificarea unor informaţii legate de applet Aflarea contextului de execuţie
cum ar fi numele, autorul, Contextul de execuţie al unui applet se referă
versiunea, etc. Metoda returnează un sir de la pagina în care acesta rulează,
caractere continând informaţiile eventual împreună cu alte appleturi, şi este
respective. descris de interfaţa AppletContext.
public String getAppletInfo() { Crearea unui obiect ce implementează această
return "Applet simplist, autor necunoscut, ver interfaţă se realizează de
1.0"; către browser, la apelul metodei
} getAppletContext a clasei Applet. Prin
Aflarea adreselor URL referitoare la applet intermediul acestei interfeţe un applet poate
Se realizează cu metodele: ”vedea” în jurul sau, putând
• getCodeBase - ce returnează URL-ul comunica cu alte applet-uri aflate pe aceeasi
directorului ce conţine clasa pagină sau cere browser-ului să
appletului; deschidă diverse documente.
• getDocumentBase - returnează URL-ul AppletContext contex = getAppletContext();
directorului ce conţine documentul Afişarea unor documente în browser
HTML în care este inclus appletul respectiv. Se face cu metoda showDocument ce primeşte
Aceste metode sunt foarte utile deoarece adresa URL a fişierului ce
permit specificarea relativă a unor conţine documentul pe care dorim sa-l
fişiere folosite de un applet, cum ar fi imagini deschidem (text, html, imagine, etc).
sau sunete. Această metodă este accesată prin intermediul
Afişarea unor mesaje în bara de stare a contextului de execuţie al
browserului appletului.
Acest lucru se realizează cu metoda try {
showStatus URL doc = new
public void init() { URL("http://www.infoiasi.ro");
showStatus("Initializare applet..."); getAppletContext().showDocument(doc);
} } catch(MalformedURLException e) {
Afişarea imaginilor System.err.println("URL invalid! \n" + e);
Afişarea imaginilor într-un applet se face fie }
prin intermediul unei componente Comunicarea cu alte applet-uri
ce permite acest lucru, cum ar fi o suprafaţă de Această comunicare implică de fapt
desenare de tip Canvas, identificarea unui applet aflat pe aceeaşi
fie direct în metoda paint a applet-ului, pagina şi apelarea unei metode sau setarea unei
folosind metoda drawImage a clasei variabile publice a acestuia.
Graphics. In ambele cazuri, obţinerea unei Identificarea se face prin intermediu numelui
referinţe la imaginea respectivă pe care orice instanţa a unui
se va face cu ajutorul metodei getImage din applet îl poate specifica prin atributul NAME.
clasa Applet. Aceasta poate Obţinerea unei referinţe la un applet al cărui
primi ca argument fie adresa URL absolută a nume îl cunoaştem sau
fişierului ce reprezintă imaginea, obţinerea unei enumerări a tuturor applet-urilor
din pagină se fac prin intermediul

47
contextului de execuţie, folosind metodele 3.9 Arhivarea appleturilor
getApplet, respectiv După cum am văzut, pentru ca un applet aflat
getApplets. pe o pagină Web să poată
Redarea sunetelor fi executat codul său va fi transferat de pe
Clasa Applet oferă şi posibilitatea redării de serverul care găzduieşte pagina
sunete în format .au. Acestea Web solicitată pe maşina clientului. Deoarece
sunt descrise prin intermediul unor obiecte ce transferul datelor prin reţea
implementează interfaţa AudioClip este un proces lent, cu cât dimensiunea fişierlor
din pachetul java.applet. Pentru a reda un sunet care formează appletul este
aflat într-un mai redusă, cu atâ încărcarea acestuia se va
fişier ”.au” la un anumit URL există două face mai repede. Mai mult, dacă
posibilităţi: appletul conţine şi alte clase în afară de cea
• Folosirea metodei play din clasa Applet care principală sau diverse resurse
primeşte ca argument (imagini, sunete, etc), acestea vor fi transferate
URL-ul la care se află sunetul; acesta poate fi prin reţea abia în momentul
specificat absolut sau în care va fi nevoie de ele, oprind temporar
relativ la URL-ul appletului activitatea appletului până la
• Crearea unui obiect de tip AudioClip cu încărcarea lor. Din aceste motive, cea mai
metoda getAudioClip apoi eficientă modalitate de a distribui
apelarea metodelor start, loop şi stop pentru un applet este să arhivăm toate fişierele
acesta. necesare acestuia.
Listing 3.7: Redarea sunetelor Arhivarea fişierelor unui applet se face cu
import java . applet .*; utilitarul jar, oferit în
import java . awt .*; distribuţia J2SDK.
import java . awt. event .*; // Exemplu
public class Sunete extends Applet implements jar cvf arhiva.jar ClasaPrincipala.class
ActionListener { AltaClasa.class
Button play = new Button (" Play "); imagine.jpg sunet.au
Button loop = new Button (" Loop "); // sau
Button stop = new Button (" Stop "); jar cvf arhiva.jar *.class *.jpg *.au
AudioClip clip = null ; Includerea unui applet arhivat într-o pagină
public void init () { Web se realizează specific
// Fisierul cu sunetul trebuie sa fie in acelasi ănd pe lângă numele clasei principale şi
// director cu appletul numele arhivei care o conţine:
clip = getAudioClip ( getCodeBase () , " <applet archive=arhiva.jar
sunet .au"); code=ClasaPrincipala
add ( play ); width=400 height=200 />
add ( loop ); 3.10 Restricţii de securitate
add ( stop ); Deoarece un applet se execută pe maşina
play . addActionListener ( this ); utilizatorului care a solicitat pagina
loop . addActionListener ( this ); Web ce conţine appletul respectiv, este foarte
stop . addActionListener ( this ); important să existe anumite
} restricţii de securitate care să controleze
public void actionPerformed ( ActionEvent e) activitatea acestuia, pentru a
{ preveni acţiuni rău intenţionate, cum ar fi
Object src = e. getSource (); ştergeri de fişiere, etc., care să
if (src == play ) aducă prejudicii utilizatorului. Pentru a realiza
clip . play (); acest lucru, procesul care
else if (src == loop ) rulează appleturi instalează un manager de
clip . loop (); securitate, adică un obiect de
else if (src == stop ) tip SecurityManager care va ”superviza”
clip . stop (); activitatea metodelor appletului,
} aruncând excepţii de tip Security Exception în
} cazul în care una din acestea
In cazul în care appletul foloseşte mai multe încearcă să efectueze o operaţie nepermisă.
tipuri de sunete, este recomandat Un applet nu poate să:
ca încărcarea acestora să fie făcută într-un fir • Citească sau să scrie fişiere pe calculatorul pe
de execuţie separat, care a fost încarcat
pentru a nu bloca temporar activitatea firească (client).
a programului.

48
• Deschidă conexiuni cu alte maşini în afară de • Apelăm metodele init şi start, care ar fi fost
cea de pe care provine apelate automat de
(host). către browser.
• Pornească programe pe maşina client. • Facem fereastra vizibilă.
• Citească diverse proprietăţi ale sistemului de Listing 14.8: Applet şi aplicaţie
operare al clientului. import java . applet . Applet ;
Ferestrele folosite de un applet, altele decât cea import java . awt .*;
a browserului, vor arăta public class AppletAplicatie extends Applet {
altfel decât într-o aplicaţie obişnuită, indicând public void init () {
faptul că au fost create de un add (new Label (" Applet si aplicatie "));
applet. }
3.11 Appleturi care sunt şi aplicaţii public static void main ( String args []) {
Deoarece clasa Applet este derivată din AppletAplicatie applet = new AppletAplicatie
Container, deci şi din Component, ();
ea descrie o suprafaţă de afişare care poate fi Frame f = new Frame (" Applet si aplicatie ");
inclusă ca orice altă componentă f. setSize (200 , 200) ;
într-un alt container, cum ar fi o fereastră. Un f.add(applet , BorderLayout . CENTER );
applet poate funcţiona şi ca applet . init ();
o aplicaţie independentă astfel: applet . start ();
• Adăugăm metoda main clasei care descrie f. show ();
appletul, în care vom face }
operaţiunile următoare. }
• Creăm o instanţă a appletului şi o adăugăm
pe suprafaţa unei ferestre.

1)Creez programul J# normal in calea


C:\Documents and Settings\ticatica\My Documents\Visual Studio
Projects\j1
//sa se defineasca un applet
package j1;

import java.awt.Graphics;
import java.awt.Font;
import java.awt.Color;

public class HelloAgainApplet extends java.applet.Applet


{

Font f = new Font("TimesRoman", Font.BOLD, 36);

public void paint(Graphics g)


{
g.setFont(f);
g.setColor(Color.red);
g.drawString("Hello again!", 5,
40);
}
}

2)creez documentul html in aceasi cale adica


C:\Documents and Settings\ticatica\My Documents\Visual Studio
Projects\j1
Astfel:

49
a)

b)File/new/

ok

c)sterg tot continutul sursei de acolo si-l inlocuiesc cu cel nou


adica cu:

<HTML>
<HEAD>
<TITLE>This page has an applet on it</TITLE>
</HEAD>
<BODY>
<P>My second Java applet says:
<BR><APPLET CODE="HelloAgainApplet.class" WIDTH=200 HEIGHT=50>
Hello Again!
</APPLET>
</BODY>
</HTML>

d)fac salvarea in calea:

50
e)deschid prin enter documentul nou creat la noi x11:

//sa se defineasca un aplet


package j1;

import java.awt.Graphics;
import java.awt.Font;
import java.awt.Color;

public class MoreHelloApplet extends java.applet.Applet


{

51
Font f = new Font("TimesRoman", Font.BOLD, 36);
String name;

public void init()


{
name = getParameter("name");
if (name == null)

name = "Laura";

name = "Hello " + name


+ "!";
}

public void paint(Graphics g)


{
g.setFont(f);
g.setColor(Color.red);
g.drawString(name, 5, 40);
}
}
iar sursa HTML ESTE:

<HTML>
<HEAD>
<TITLE>Hello!</TITLE>
</HEAD>
<BODY>
<P>
<APPLET CODE="MoreHelloApplet.class" WIDTH=200 HEIGHT=50>
<PARAM NAME=name VALUE="Bonzo">
Hello to whoever you are!
</APPLET>
</BODY>
</HTML>

executia cand apas enter pe documentul HTML este:

RULAREA APLETURILOR JAVA


SE mai poate face cu programul JCreator astfel:

52
1)

2)File/New/aleg Java File/si dau numele proiectului adica x11

ok
3)dublu clic pe x11.java

editez continutul java adica:


import java.awt.*;
import java.applet.*;

public class X1 extends Applet


{

53
public void init()
{

public void paint(Graphics g)


{
g.drawString("Welcome to Java!!", 50, 60 );
}

4)dublu clic pe x1.htm si-I editez continutul:

adica:
<HTML>
<HEAD>
</HEAD>
<BODY BGCOLOR="000000">
<CENTER>
<APPLET
code = " X1
.class"
width = "500"
height = "300"
>
</APPLET>
</CENTER>
</BODY>
</HTML>
4)sa fiul plasat in sursa java si sa salvez documentul in prealabil
si astept pana se confirma compilarea

5)rulez proiectul apasand tasta F5

54
OBS:
Sursa Html ramane la fel numai ca se va scimba continutul clasei si se repeat
pasul 4 si 5
De exemplu programul care face doua dreptunghiuri

import java.awt.*;
import java.applet.*;

public class X1
extends Applet
{
public void init()
{

public void paint(Graphics g)


{

g.drawRect(20,20,60,60);
g.fillRect(120,20,60,60);

}
iar sursa html este aceiasi adica

<HTML>
<HEAD>
</HEAD>
<BODY BGCOLOR="000000">
<CENTER>
<APPLET
code =" X1 .class"
width = "500"
height = "300"
>
</APPLET>
</CENTER>
</BODY>
</HTML>
executia repetand pasii 4 si 5

55
realizarea de doua dreptunghiuri rotunjite

/**************************************************************
* You can modify the template of this file in the
* directory ..\JCreator\Templates\Template_2\Project_Name.java
*
* You can also create your own project template by making a new
* folder in the directory ..\JCreator\Template\. Use the other
* templates as examples.
*
*/

import java.awt.*;
import java.applet.*;

public class X1 extends Applet


{
public void init()
{

public void paint(Graphics g)


{

g.drawRoundRect(20,20,60,60,10,10);
g.fillRoundRect(120,20,60,60,20,20);

}
Interfaţa grafică cu utilizatorul
6.1 Introducere
Interfaţa grafică cu utilizatorul (GUI), este un diverselor funcţionalitati UI, însă ne vom ocupa în
termen cu înţeles larg care continuare de cele care
se referă la toate tipurile de comunicare vizuală între permit realizarea intefeţei grafice cu utilizatorul
un program şi utilizatorii (GUI).
săi. Aceasta este o particularizare a interfeţei cu De la apariţia limbajului Java, bibliotecile de clase
utilizatorul (UI), prin care oferă servicii
care vom întelege conceptul generic de interacţiune grafice au suferit probabil cele mai mari schimbări
dintre program şi utilizatori. în trecerea de la o versiune
Limbajul Java pune la dispoziţie numeroase clase la alta. Acest lucru se datorează, pe de o parte
pentru implementarea dificultăţii legate de

56
implementarea noţiunii de portabilitate, pe de altă descind din clasa MenuComponent. Aşadar, prin
parte nevoii de a integra noţiunea de componentă
mecanismele GUI cu tehnologii apărute şi vomîntelege în continuare orice obiect care poate
dezvoltate ulterior, cum ar fi Java avea o reprezentare grafică
Beans. In momentul actual, există două modalităţi şi care poate interactiona cu utilizatorul. Exemple de
de a crea o aplicaţie cu componente sunt ferestrele,
interfaţă grafică şi anume: butoanele, listele, bare de defilare, etc. Toate
• AWT(Abstract Windowing Toolkit) - este API-ul componentele AWT sunt
iniţial pus la dispoziţie definte de clase proprii ce se gasesc în pachetul
începând cu primele versiuni de Java; java.awt, clasa Component
• Swing - parte dintr-un proiect mai amplu numit fiind superclasa abstractă a tuturor acestor clase.
JFC (Java Foundation Crearea obiectelor grafice nu realizează automat şi
Classes) creat în urma colaborării dintre Sun, afişarea lor pe ecran.
Netscape şi IBM, Maiîntâi ele trebuie aşezate pe o suprafata de
Swing se bazează pe modelul AWT, extinzând afişare, care poate fi o fereastră
funcţionalitatea acestuia sau un applet, şi vor deveni vizibileîn momentulîn
şi adăugând sau înlocuind componente pentru care suprafaţa pe care sunt
dezvoltarea aplicaţiilor afişate va fi vizibilă. O astfel de suprafaţă pe care
GUI. sunt plasate componente
Aşadar, este de preferat ca aplicaţiile Java să fie se mai numeşte container şi reprezintă o instanţă a
create folosind tehnologia unei clase derivate din
Swing, aceasta punând la dispoziţie o paletă mult Container. Clasa Container este o subclasă aparte a
mai largă de facilităţi, lui Component, fiind
însă nu vom renunţa complet la AWT deoarece aici la rândul ei superclasa tuturor suprafetelor de afişare
există clase esenţiale, Java.
reutilizate în Swing. Aşa cum am văzut, interfaţă grafică serveşte
In acest capitol vom prezenta clasele de bază şi interacţiunii cu utilizatorul.
mecanismul de tratare a De cele mai multe ori programul trebuie să facă o
evenimentelor din AWT, deoarece va fi simplificat anumită prelucrare în
procesul de înţelegere a momentul în care utilizatorul a efectuat o acţiune şi,
dezvoltării unei aplicaţii GUI, după care vom face prin urmare, componentele
trecerea la Swing. trebuie să genereze evenimente în funcţie de
In principiu, crearea unei aplicaţii grafice presupune acţiunea pe care au
următoarele lucruri: suferit-o (acţiune transmisă de la tastatură, mouse,
• Design etc.). Incepând cu versiunea
– Crearea unei suprafeţe de afişare (cum ar fi o 1.1 a limbajului Java, evenimentele sunt instanţe ale
fereastră) pe care vor claselor derivate
fi aşezate obiectele grafice (componente) care din AWTEvent.
servesc la comunicarea Aşadar, un eveniment este produs de o acţiune a
cu utilizatorul (butoane, controale pentru editarea utilizatorului asupra unui
textelor, obiect grafic, deci evenimentele nu trebuie generate
liste, etc); de programator. In
– Crearea şi aşezarea componentelor pe suprafaţa de schimb, într-un program trebuie specificat codul
afişare la poziţiile care se execută la apariţia
corespunzătoare; unui eveniment. Tratarea evenimentelor se
• Funcţionalitate realizează prin intermediul unor
– Definirea unor acţiuni care trebuie să se execute în clase de tip listener (ascultător, consumator de
momentul când evenimente), clase care sunt
utilizatorul interacţionează cu obiectele grafice ale definite în pachetul java.awt.event. In Java, orice
aplicaţiei; componentă poate ”consuma”
– ”Ascultarea” evenimentelor generate de obiecte în evenimentele generate de o altă componentă (vezi
momentul ”Tratarea evenimentelor”).
interacţiunii cu utilizatorul şi executarea acţiunilor Să considerăm un mic exemplu, în care creăm o
corespunzătoare, fereastră ce conţine două
aşa cum au fost ele definite. butoane.
6.2 Modelul AWT Listing 6.1: O fereastră cu două butoane
Pachetul care oferă componente AWT este java.awt. import java . awt .*;
Obiectele grafice sunt derivate din Component, cu public class ExempluAWT1 {
excepţia meniurilor care public static void main ( String args []) {
// Crearea ferestrei - un obiect de tip Frame

57
Frame f = new Frame ("O fereastra "); • Container - superclasa tuturor suprafeţelor de
// Setarea modului de dipunere a componentelor afişare (vezi ”Suprafeţe
f. setLayout (new FlowLayout ()); de afişare”);
// Crearea celor doua butoane • Label - etichete simple ce pot conţine o singură
Button b1 = new Button ("OK"); linie de text needitabil;
Button b2 = new Button (" Cancel "); • List - liste cu selecţie simplă sau multiplă;
// Adaugarea butoanelor • Scrollbar - bare de defilare orizontale sau
f.add(b1); verticale;
f.add(b2); • TextComponent - superclasa componentelor
f. pack (); pentru editarea textului:
// Afisarea fereastrei TextField (pe o singură linie) şi TextArea (pe mai
f. show (); multe linii).
} Mai multe informaţii legate de aceste clase vor fi
} prezentate în secţiunea
După cum veţi observa la execuţia acestui program, ”Folosirea componentelor AWT”.
atât butoanele adăugate Din cauza unor diferenţe esentiale în implementarea
de noi cât şi butonul de închidere a ferestrei sunt meniurilor pe diferite
funcţionale, adică pot fi platforme de operare, acestea nu au putut fi integrate
apasate, dar nu realizează nimic. Acest lucru se ca obiecte de tip
întâmplă deoarece nu am Component, superclasa care descrie meniuri fiind
specificat nicăieri codul care trebuie să se execute la MenuComponent (vezi
apăsarea acestor butoane. ”Meniuri”).
De asemenea, mai trebuie remarcat că nu am Componentele AWT au peste 100 de metode
specificat nicăieri dimensiunile comune, moştenite din clasa
ferestrei sau ale butoanelor şi nici pozitiile în Component. Acestea servesc uzual pentru aflarea
acestea să fie plasate. Cu sau setarea atributelor
toate acestea ele sunt plasate unul lânga celalalt, fără obiectelor, cum ar fi: dimensiune, poziţie, culoare,
să se suprapună iar font, etc. şi au formatul
suprafaţa fereastrei este suficient de mare cât să general getProprietate, respectiv setProprietate. Cele
cuprindă ambele obiecte. mai folosite, grupate
Aceste ”fenomene” sunt provocate de un obiect pe tipul proprietăţii gestionate sunt:
special de tip FlowLayout • Poziţie
pe care l-am specificat şi care se ocupă cu getLocation, getX, getY, getLocationOnScreen
gestionarea ferestrei şi cu plasarea setLocation, setX, setY
componentelor într-o anumită ordine pe suprafaţa ei. • Dimensiuni
Aşadar, modul de getSize, getHeight, getWidth
aranjare nu este o caracteristică a suprafeţei de setSize, setHeight, setWidth
afişare ci, fiecare container • Dimensiuni şi poziţie
are asociat un obiect care se ocupă cu dimensionarea getBounds
şi dispunerea componentelor setBounds
pe suprafaţa de afişare şi care se numeste gestionar • Culoare (text şi fundal)
de poziţionare getForeground, getBackground
(layout manager) (vezi ”Gestionarea poziţionării”). setForeground, setBackground
6.2.1 Componentele AWT • Font
După cum am spus deja, toate componentele AWT getFont
sunt definte de clase setFont
proprii ce se gasesc în pachetul java.awt, clasa • Vizibilitate
Component fiind superclasa setVisible
abstracta a tuturor acestor clase. isVisible
• Button - butoane cu eticheta formată dintr-un text • Interactivitate
pe o singură linie; setEnabled
• Canvas - suprafaţă pentru desenare; isEnabled
• Checkbox - componentă ce poate avea două stări; 6.2.2 Suprafeţe de afişare (Clasa Container)
mai multe obiecte Crearea obiectelor grafice nu realizează automat şi
de acest tip pot fi grupate folosind clasa afişarea lor pe ecran. Mai
CheckBoxGroup; întâi ele trebuie aşezate pe o suprafaţă, care poate fi
• Choice - liste în care doar elementul selectat este o fereastră sau suprafaţa
vizibil şi care se unui applet, şi vor deveni vizibile în momentul în
deschid la apăsarea lor; care suprafaţa respectivă

58
va fi vizibilă. O astfel de suprafaţa pe care sunt TextField text = new TextField();
plasate componentele se Panel panel = new Panel();
numeşte suprafaţă de afişare sau container şi panel.add(et);
reprezintă o instanţa a unei clase panel.add(text);
derivată din Container. O parte din clasele a căror // Adaugam panel-ul pe fereastra
părinte este Container // si, indirect, cele doua componente
este prezentată mai jos: f.add(panel);
• Window - este superclasa tututor ferestrelor. Din 6.3 Gestionarea poziţionării
această clasă sunt Să considerăm mai întâi un exemplu de program
derivate: Java care afişează 5 butoane
– Frame - ferestre standard; pe o fereastră:
– Dialog - ferestre de dialog modale sau nemodale; Listing 9.2: Poziţionarea a 5 butoane
• Panel - o suprafaţă fără reprezentare grafică import java . awt .*;
folosită pentru gruparea public class TestLayout {
altor componente. Din această clasă derivă Applet, public static void main ( String args []) {
folosită pentru Frame f = new Frame (" Grid Layout ");
crearea appleturilor. f. setLayout (new GridLayout (3, 2)); //*
• ScrollPane - container folosit pentru Button b1 = new Button (" Button 1");
implementarea automată a derulării Button b2 = new Button ("2");
pe orizontală sau verticală a unei componente. Button b3 = new Button (" Button 3");
Aşadar, un container este folosit pentru a adăuga Button b4 = new Button ("Long - Named Button
componente pe suprafaţa 4");
lui. Componentele adăugate sunt memorate într-o Button b5 = new Button (" Button 5");
listă iar poziţiile lor din f.add(b1); f.add (b2); f. add(b3); f.add(b4);
această listă vor defini ordinea de traversare ”front- f.add(b5);
to-back” a acestora în f. pack ();
cadrul containerului. Dacă nu este specificat nici un f. show ();
index la adăugarea unei }
componente, atunci ea va fi adaugată pe ultima }
poziţie a listei. Fereastra afişata de acest program va arăta astfel:
Clasa Container conţine metodele comune tututor Să modificăm acum linia marcata cu ’*’ ca mai jos,
suprafeţelor de afişare. lăsând neschimbat
Dintre cele mai folosite, amintim: restul programului:
• add - permite adăugarea unei componente pe Frame f = new Frame("Flow Layout");
suprafaţa de afişare. f.setLayout(new FlowLayout());
O componentă nu poate aparţine decât unui singur Fereastra afişată după această modificare va avea o
container, ceea ce cu totul altfel de
înseamnă că pentru a muta un obiect dintr-un dispunere a componentelor sale:
container în altul trebuie Motivul pentru care cele două ferestre arată atât de
sa-l eliminam mai întâi de pe containerul initial. diferit este că folosesc
• remove - elimină o componentă de pe container; gestionari de poziţionare diferiţi: GridLayout,
• setLayout - stabileşte gestionarul de poziţionare al respectiv FlowLayout.
containerului (vezi Definiţie
”Gestionarea poziţionării”); Un gestionar de poziţionare (layout manager) este
• getInsets - determină distanţa rezervată pentru un obiect care controleaz
marginile suprafeţei ă dimensiunea şi aranjarea (poziţia) componentelor
de afişare; unui container.
• validate - forţează containerul să reaşeze toate Aşadar, modul de aranjare a componentelor pe o
componentele sale. suprafaţa de afişare
Această metodă trebuie apelată explicit atunci când nu este o caracteristică a containerului. Fiecare
adăugăm sau eliminăm obiect de tip Container
componente pe suprafaţa de afişare după ce aceasta (Applet, Frame, Panel, etc.) are asociat un obiect
a devenit vizibilă. care se ocupă cu dispunerea
Exemplu: componentelor pe suprafaţa sa şi anume gestionarul
Frame f = new Frame("O fereastra"); său de poziţionare.
// Adaugam un buton direct pe fereastra Toate clasele care instanţiaza obiecte pentru
Button b = new Button("Hello"); gestionarea poziţionării implementeaz
f.add(b); ă interfaţă LayoutManager.
// Adaugam doua componente pe un panel La instanţierea unui container se creează implicit un
Label et = new Label("Nume:"); gestionar de poziţionare

59
asociat acestuia. De exemplu, pentru o fereastră metode pentru a calcula dimensiunea la care vor
gestionarul implict este de afişa o componentă.
tip BorderLayout, în timp ce pentru un panel este de Sunt însă situaţii când dorim să plasăm
tip FlowLayout. componentele la anumite poziţii
6.3.1 Folosirea gestionarilor de poziţionare fixe iar acestea să ramâna acolo chiar dacă
Aşa cum am văzut, orice container are un gestionar redimensionăm containerul. Folosind
implicit de poziţionare - un gestionar această poziţionare absolută a
un obiect care implemenează interfaţa componentelor nu este posibilă şi
LayoutManager, acesta fiindu-i ataşat deci trebuie cumva să renunţăm la gestionarea
automat la crearea sa. In cazul în care acesta nu automată a containerul. Acest
corespunde necesităţilor lucru se realizează prin trimitera argumentului null
noastre, el poate fi schimbat cu uşurinţă. Cei mai metodei setLayout:
utilizaţi gestionari din // pozitionare absoluta a componentelor in container
pachetul java.awt sunt: container.setLayout(null);
• FlowLayout Folosind poziţionarea absolută, nu va mai fi însă
• BorderLayout suficient să adăugam cu
• GridLayout metoda add componentele în container, ci va trebui
• CardLayout să specificăm poziţia şi
• GridBagLayout dimensiunea lor - acest lucru era făcut automat de
Pe lângă aceştia, mai există şi cei din modelul gestionarul de poziţionare.
Swing care vor fi prezentaţi container.setLayout(null);
în capitolul dedicat dezvoltării de aplicaţii GUI Button b = new Button("Buton");
folosind Swing. b.setSize(10, 10);
Ataşarea explicită a unui gestionar de poziţionare la b.setLocation (0, 0);
un container se face container.add(b);
cu metoda setLayout a clasei Container. Metoda In general, se recomandă folosirea gestionarilor de
poate primi ca parametru poziţionare în toate
orice instanţă a unei clase care implementează situaţiile când acest lucru este posibil, deoarece
interfaţă LayoutManager. permit programului să aibă
Secvenţa de ataşare a unui gestionar pentru un aceeaşi ”înfatisare” indiferent de platforma şi
container, particularizată rezoluţia pe care este rulat.
pentru FlowLayout, este: Poziţionarea absolută poate ridica diverse probleme
FlowLayout gestionar = new FlowLayout(); în acest sens.
container.setLayout(gestionar); Să analizam în continuare pe fiecare din gestionarii
// sau, mai uzual: amintiţi anterior.
container.setLayout(new FlowLayout()); 6.3.2 Gestionarul FlowLayout
Programele nu apeleazăîn general metode ale Acest gestionar aşează componentele pe suprafaţa
gestionarilor de poziţionare, de afişareîn flux liniar, mai
darîn cazul când avem nevoie de obiectul gestionarîl precis, componentele sunt adăugate una după alta pe
putem obţine cu metoda linii, în limita spaţiului
getLayout din clasa Container. disponibil. In momentul când o componentă nu
Una din facilităţile cele mai utile oferite de maiîncape pe linia curentă se
gestionarii de poziţionare trece la următoarea linie, de sus în jos. Adăugarea
este rearanjarea componentele unui container atunci componentelor se face de
când acesta este redimesionat. la stânga la dreapta pe linie, iar alinierea obiectelor
Poziţiile şi dimensiunile componentelor nu sunt în cadrul unei linii poate
fixe, ele fiind fi de trei feluri: la stânga, la dreapta şi pe centru.
ajustate automat de către gestionar la fiecare Implicit, componentele
redimensionare astfel încât să sunt centrate pe fiecare linie iar distanţa implicită
ocupe cât mai ”estetic” suprafaţa de afişare. Cum între componente este de
sunt determinate însă 5 pixeli pe verticală şi 5 pe orizontală.
dimensiunile implicite ale componentelor ? Este gestionarul implicit al containerelor derivate
Fiecare clasă derivată din Component poate din clasa Panel deci şi
implementa metodele getPreferredSize, al applet-urilor.
getMinimumSize şi getMaximumSize care să Listing 6.3: Gestionarul FlowLayout
returneze dimensiunea import java . awt .*;
implicită a componentei respective şi limitele în public class TestFlowLayout {
afara cărora componenta public static void main ( String args []) {
nu mai poate fi desenată. Gestionarii de poziţionare Frame f = new Frame (" Flow Layout ");
vor apela aceste f. setLayout (new FlowLayout ());

60
Button b1 = new Button (" Button 1"); f. show ();
Button b2 = new Button ("2"); }
Button b3 = new Button (" Button 3"); }
Button b4 = new Button ("Long - Named Button Cele cinci butoane ale ferestrei vor fi afişate astfel:
4"); La redimensionarea ferestrei se pot observa
Button b5 = new Button (" Button 5"); următoarele lucruri: nordul şi
f.add(b1); f.add (b2); f. add(b3); f.add(b4); sudul se redimensionează doar pe orizontală, estul şi
f.add(b5); vestul doar pe verticală,
f. pack (); în timp ce centrul se redimensionează atât pe
f. show (); orizontală cât şi pe verticală.
} Redimensionarea componentelor din fiecare zonă se
} face astfel încât ele ocupă
Componentele ferestrei vor fi afişate astfel: toată zona containerului din care fac parte.
Redimensionând fereastra astfel încât cele cinci 6.3.4 Gestionarul GridLayout
butoane să nu mai încapă Gestionarul GridLayout organizează containerul ca
pe o linie, ultimele dintre ele vor fi trecute pe linia un tabel cu rânduri şi
următoare: coloane, componentele fiind plasate în celulele
6.3.3 Gestionarul BorderLayout tabelului de la stânga la
Gestionarul BorderLayout împarte suprafaţa de dreapta, începând cu primul rând. Celulele tabelului
afişare în cinci regiuni, corespunz au dimensiuni egale
ătoare celor patru puncte cardinale şi centrului. O iar o componentă poate ocupa doar o singură celulă.
componentă poate fi Numărul de linii şi
plasată în oricare din aceste regiuni, dimeniunea coloane vor fi specificate în constructorul
componentei fiind calculata gestionarului, dar pot fi modificate
astfel încât să ocupe întreg spaţiul de afişare oferit şi ulterior prin metodele setRows, respectiv setCols.
de regiunea respectivă. Dacă numărul de linii
Pentru a adăuga mai multe obiecte grafice într-una sau coloane este 0 (dar nu ambele în acelaşi timp),
din cele cinci zone, ele atunci componentele vor
trebuie grupate în prealabil într-un panel, care va fi fi plasate într-o singură coloană sau linie. De
amplasat apoi în regiunea asemenea, distanţa între componente
dorită (vezi ”Gruparea componentelor - clasa pe orizontală şi distanta între rândurile tabelului pot
Panel”). fi specificate
Aşadar, la adăugarea unei componente pe o în constructor sau stabilite ulterior.
suprafaţă gestionată de BorderLayout, Listing 9.5: Gestionarul GridLayout
metoda add va mai primi pe lânga referinţa import java . awt .*;
componentei şi zona în care public class TestGridLayout {
aceasta va fi amplasată, care va fi specificată prin public static void main ( String args []) {
una din constantele clasei: Frame f = new Frame (" Grid Layout ");
NORTH, SOUTH, EAST, WEST, CENTER. f. setLayout (new GridLayout (3, 2));
BorderLayout este gestionarul implicit pentru toate f.add(new Button ("1"));
containerele care descind f.add(new Button ("2"));
din clasa Window, deci al tuturor tipurilor de f.add(new Button ("3"));
ferestre. f.add(new Button ("4"));
Listing 6.4: Gestionarul BorderLayout f.add(new Button ("5"));
import java . awt .*; f.add(new Button ("6"));
public class TestBorderLayout { f. pack ();
public static void main ( String args []) { f. show ();
Frame f = new Frame (" Border Layout "); }
// Apelul de mai jos poate sa lipseasca }
f. setLayout (new BorderLayout ()); Cele şase butoane ale ferestrei vor fi plasate pe trei
f.add(new Button (" Nord "), BorderLayout . rânduri şi două
NORTH ); coloane, astfel:
f.add(new Button (" Sud"), BorderLayout . Redimensionarea ferestrei va determina
SOUTH ); redimensionarea tuturor celulelor
f.add(new Button (" Est"), BorderLayout . EAST ); şi deci a tuturor componentelor, atât pe orizontală
f.add(new Button (" Vest "), BorderLayout . cât şi pe verticală.
WEST ); 6.3.5 Gestionarul CardLayout
f.add(new Button (" Centru "), BorderLayout . Gestionarul CardLayout tratează componentele
CENTER ); adăugate pe suprafaţa sa
f. pack ();

61
într-o manieră similară cu cea a dispunerii cărţilor 6.3.6 Gestionarul GridBagLayout
de joc într-un pachet. Este cel mai complex şi flexibil gestionar de
Suprafaţa de afişare poate fi asemănată cu pachetul poziţionare din Java. La fel ca în
de cărţi iar fiecare component cazul gestionarului GridLayout, suprafaţa de afişare
ă este o carte din pachet. La un moment dat, numai este considerată ca fiind
o singură component un tabel însă, spre deosebire de acesta, numărul de
ă este vizibilă (”cea de deasupra”). linii şi de coloane sunt
Clasa dispune de metode prin care să poată fi afişată determinate automat, în funcţie de componentele
o anumită component amplasate pe suprafaţa de
ă din pachet, sau să se poată parcurge secvenţial afişare. De asemenea, în funcţie de componentele
pachetul, ordinea gestionate, dimensiunile
componentelor fiind internă gestionarului. celulelor pot fi diferite cu singurele restricţii ca pe
Principala utilitate a acestui gestionar este utilizarea aceeaşi linie să aibă aceeaşi
mai eficientă a înalţime, iar pe coloană aibă aceeaşi lăţime. Spre
spaţiului disponibil în situaţii în care componentele deosebire de GridLayout,
pot fi grupate în aşa o componentă poate ocupa mai multe celule
fel încât utilizatorul să interacţioneze la un moment adiacente, chiar de dimensiuni
dat doar cu un anumit diferite, zona ocupată fiind referită prin ”regiunea de
grup (o carte din pachet), celelalte fiind ascunse. afişare” a componentei
O clasă Swing care implementează un mecansim respective.
similar este JTabbedPane. Pentru a specifica modul de afişare a unei
Listing 6.6: Gestionarul CardLayout componente, acesteia îi este
import java . awt .*; asociat un obiect de tip GridBagConstraints, în care
import java . awt. event .*; se specifică diferite
public class TestCardLayout extends Frame proprietăţi ale componentei referitoare la regiunea
implements să de afişare şi la modul
ActionListener { în care va fi plasată în această regiune. Legătura
Panel tab; dintre o componentă şi un
public TestCardLayout () { obiect GridBagConstraints se realizează prin metoda
super (" Test CardLayout "); setConstraints:
Button card1 = new Button (" Card 1"); GridBagLayout gridBag = new GridBagLayout();
Button card2 = new Button (" Card 2"); container.setLayout(gridBag);
Panel butoane = new Panel (); GridBagConstraints c = new GridBagConstraints();
butoane . add( card1 ); //Specificam restrictiile referitoare la afisarea
butoane . add( card2 ); componentei
tab = new Panel (); ...
tab . setLayout ( new CardLayout ()); gridBag.setConstraints(componenta, c);
TextField tf = new TextField (" Text Field "); container.add(componenta);
Button btn = new Button (" Button "); Aşadar, înainte de a adăuga o componentă pe
tab .add (" Card 1", tf); suprafaţa unui container
tab .add (" Card 2", btn); care are un gestionar de tip GridBagLayout, va
add ( butoane , BorderLayout . NORTH ); trebui să specificăm anumiţi
add (tab , BorderLayout . CENTER ); parametri (constrângeri) referitori la cum va fi
pack (); plasată componenta respectiv
show (); ă. Aceste constrângeri vor fi specificate prin
card1 . addActionListener ( this ); intermediul unui obiect de tip
card2 . addActionListener ( this ); GridBagConstraints, care poate fi refolosit pentru
} mai multe componente
public void actionPerformed ( ActionEvent e) { care au aceleaşi constrângeri de afişare:
CardLayout gestionar = ( CardLayout ) tab. gridBag.setConstraints(componenta1, c);
getLayout (); gridBag.setConstraints(componenta2, c);
gestionar . show (tab , e. getActionCommand ()); ...
} Cele mai utilizate tipuri de constrângeri pot fi
public static void main ( String args []) { specificate prin intermediul
TestCardLayout f = new TestCardLayout (); următoarelor variabile din clasa
f. show (); GridBagConstraints:
} • gridx, gridy - celula ce reprezintă colţul stânga sus
} al componentei;
Prima ”carte” este vizibilă A doua ”carte” este • gridwidth, gridheight - numărul de celule pe linie
vizibilă şi coloană pe care

62
va fi afişată componenta; adauga ( etSalariu , 0, 3, 1, 1);
• fill - folosită pentru a specifica dacă o componentă TextField nume = new TextField ("", 30) ;
va ocupa întreg gbc . fill = GridBagConstraints . HORIZONTAL ;
spaţiul pe careîl are destinat; valorile posibile sunt gbc . anchor = GridBagConstraints . CENTER ;
HORIZONTAL, VERTICAL, adauga (nume , 1, 2, 2, 1);
BOTH, NONE; TextField salariu = new TextField ("", 30) ;
• insets - distanţele dintre componentă şi marginile adauga ( salariu , 1, 3, 2, 1);
suprafeţei sale de Button adaugare = new Button (" Adaugare ");
afişare; gbc . fill = GridBagConstraints . NONE ;
• anchor - folosită atunci când componenta este mai adauga ( adaugare , 3, 2, 1, 2);
mică decât suprafaţa Button salvare = new Button (" Salvare ");
sa de afişare pentru a forţa o anumită dispunere a sa: gbc . fill = GridBagConstraints . HORIZONTAL ;
nord, sud, est, adauga ( salvare , 1, 4, 1, 1);
vest, etc. Button iesire = new Button (" Iesire ");
• weigthx, weighty - folosite pentru distribuţia adauga ( iesire , 2, 4, 1, 1);
spaţiului liber; uzual f. pack ();
au valoarea 1; f. show ();
Ca exemplu, să realizăm o fereastră ca în figura de }
mai jos. Pentru a }
simplifica codul, a fost creată o metodă responsabilă 6.3.7 Gruparea componentelor (Clasa Panel)
cu setarea valorilor Plasarea componentelor direct pe suprafaţa de
gridx, gridy, gridwidth, gridheight şi adăugarea unei afişare poate deveni incomodă
componente cu în cazul în care avem multe obiecte grafice. Din
restricţiile stabilite pe fereastră. acest motiv, se recomandă
Listing 9.7: Gestionarul GridBagLayout gruparea componentelor înrudite ca funcţii astfel
import java . awt .*; încât să putem fi siguri că,
public class TestGridBagLayout { indiferent de gestionarul de poziţionare al suprafeţei
static Frame f; de afişare, ele se vor găsi
static GridBagLayout gridBag ; împreună. Gruparea componentelor se face în panel-
static GridBagConstraints gbc ; uri.
static void adauga ( Component comp , Un panel este cel mai simplu model de container. El
int x, int y, int w, int h) { nu are o reprezentare
gbc . gridx = x; vizibilă, rolul său fiind de a oferi o suprafaţă de
gbc . gridy = y; afişare pentru componente
gbc . gridwidth = w; grafice, inclusiv pentru alte panel-uri. Clasa care
gbc . gridheight = h; instanţiaza aceste obiecte
gridBag . setConstraints (comp , gbc); este Panel, extensie a superclasei Container. Pentru
f.add( comp ); a aranja corespunzător
} componentele grupate într-un panel, acestuia i se
public static void main ( String args []) { poate specifica un gestionar
f = new Frame (" Test GridBagLayout "); de poziţionare anume, folosind metoda setLayout.
gridBag = new GridBagLayout (); Gestionarul implicit pentru
gbc = new GridBagConstraints (); containerele de tip Panel este FlowLayout.
gbc . weightx = 1.0; Aşadar, o aranjare eficientă a componentelor unei
gbc . weighty = 1.0; ferestre înseamnă:
gbc . insets = new Insets (5, 5, 5, 5); • gruparea componentelor ”înfraţite” (care nu
f. setLayout ( gridBag ); trebuie să fie desparţite
Label mesaj = new Label (" Evidenta persoane ", de gestionarul de poziţionare al ferestrei) în panel-
Label . CENTER uri;
); • aranjarea componentelor unui panel, prin
mesaj . setFont (new Font (" Arial ", Font .BOLD , specificarea unui gestionar
24)); de poziţionare corespunzător;
mesaj . setBackground ( Color . yellow ); • aranjarea panel-urilor pe suprafaţa ferestrei, prin
gbc . fill = GridBagConstraints . BOTH ; specificarea gestionarului
adauga (mesaj , 0, 0, 4, 2); de poziţionare al ferestrei.
Label etNume = new Label (" Nume :"); Listing 6.8: Gruparea componentelor
gbc . fill = GridBagConstraints . NONE ; import java . awt .*;
gbc . anchor = GridBagConstraints . EAST ; public class TestPanel {
adauga ( etNume , 0, 2, 1, 1); public static void main ( String args []) {
Label etSalariu = new Label (" Salariu :"); Frame f = new Frame (" Test Panel ");

63
Panel intro = new Panel (); le generează, mai precis în funcţie de acţiunea
intro . setLayout (new GridLayout (1, 3)); utilizatorului asupra acesteia.
intro .add(new Label (" Text :")); Pentru fiecare tip de eveniment există o clasă care
intro .add(new TextField ("", 20) ); instanţiază obiecte de
intro .add(new Button (" Adaugare ")); acel tip. De exemplu, evenimentul generat de
Panel lista = new Panel (); acţionarea unui buton este
lista . setLayout (new FlowLayout ()); descris de clasa ActionEvent, cel generat de
lista .add(new List (10) ); modificarea unui text de clasa
lista .add(new Button (" Stergere ")); TextEvent, etc. Toate aceste clase sunt derivate din
Panel control = new Panel (); superclasa AWTEvent,
control . add( new Button (" Salvare ")); lista lor completă fiind prezentată ulterior.
control . add( new Button (" Iesire ")); O clasă consumatoare de evenimente (listener) poate
f.add(intro , BorderLayout . NORTH ); fi orice clasă care
f.add(lista , BorderLayout . CENTER ); specifica în declaraţia sa că doreşte să asculte
f.add( control , BorderLayout . SOUTH ); evenimente de un anumit
f. pack (); tip. Acest lucru se realizează prin implementarea
f. show (); unei interfeţe specifice
} fiecărui tip de eveniment. Astfel, pentru ascultarea
} evenimentelor de tip
6.4 Tratarea evenimentelor ActionEvent clasa respectivă trebuie să
Un eveniment este produs de o acţiune a implementeze interfaţa ActionListener,
utilizatorului asupra unei componente pentru TextEvent interfaţă care trebuie
grafice şi reprezintă mecanismul prin care implementata este TextListener,
utilizatorul comunică efectiv etc. Toate aceste interfeţe sunt derivate din
cu programul. Exemple de evenimente sunt: EventListener.
apăsarea unui buton, modi- Fiecare interfaţă defineşte una sau mai multe
ficarea textului într-un control de editare, închiderea metode care vor fi apelate
sau redimensionarea automat la apariţia unui eveniment:
unei ferestre, etc. Componentele care generează class AscultaButoane implements ActionListener {
anumite evenimente se mai public void actionPerformed(ActionEvent e) {
numesc şi surse de evenimente. // Metoda interfetei ActionListener
Interceptarea evenimentelor generate de ...
componentele unui program se }
realizează prin intermediul unor clase de tip listener }
(ascultător, consumator class AscultaTexte implements TextListener {
de evenimente). In Java, orice obiect poate public void textValueChanged(TextEvent e) {
”consuma” evenimentele generate // Metoda interfetei TextListener
de o anumită componentă grafică. ...
Aşadar, pentru a scrie cod care să se execute în }
momentul în care utilizatorul }
interactionează cu o componentă grafică trebuie să Intrucât o clasă poate implementa oricâte interfeţe,
facem următoarele ea va putea să asculte
lucruri: evenimente de mai multe tipuri:
• să scriem o clasă de tip listener care să ”asculte” class Ascultator implements ActionListener,
evenimentele produse TextListener {
de acea componentă şi în cadrul acestei clase să public void actionPerformed(ActionEvent e) { ... }
implementăm metode public void textValueChanged(TextEvent e) { ... }
specifice pentru tratarea lor; }
• să comunicăm componentei sursă că respectiva Vom vedea în continuare metodele fiecărei interfeţe
clasa îi ”ascultă” evenimentele pentru a şti ce trebuie
pe care le generează, cu alte cuvinte să înregistrăm să implementeze o clasă consumatoare de
acea clasă evenimente.
drept ”consumator” al evenimentelor produse de Aşa cum am spus mai devreme, pentru ca
componenta respectiv evenimentele unei componente
ă. să fie interceptate de către o instanţă a unei clase
Evenimentele sunt, ca orice altceva în Java, obiecte. ascultător, această clasă
Clasele care descriu trebuie înregistrata în lista ascultătorilor
aceste obiecte se împart în mai multe tipuri în componentei respective. Am spus
funcţie de componenta care lista, deoarece evenimentele unei componente pot fi
ascultate de oricâte clase,

64
cu condiţia ca acestea să fie înregistrate la }
componenta respectivă. Inregistrarea }
unei clase în lista ascultătorilor unei componente se public class TestEvent1 {
face cu metode public static void main ( String args []) {
din clasa Component de tipul Fereastra f = new Fereastra (" Test Event ");
addTipEvenimentListener, iar eliminarea ei f. show ();
din această listă cu removeTipEvenimentListener. }
Sumarizând, tratarea evenimentelor în Java se }
desfăşoară astfel: Nu este obligatoriu să definim clase speciale pentru
• Componentele generează evenimente când ceva ascultarea evenimentelor.
”interesant” seîntâmplă; In exemplul de mai sus am definit clasa Ascultator
• Sursele evenimentelor permit oricărei clase să pentru a
”asculte” evenimentele intercepta evenimentele produse de cele două
sale prin metode de tip addXXXListener, unde XXX butoane şi din acest motiv a
este un tip de trebuit să trimitem ca parametru constructorului
eveniment; clasei o referinţa la fereastra
• O clasă care ascultă evenimente trebuie să noastră. Mai simplu ar fi fost să folosim chiar clasa
implementeze interfeţe speci- Fereastra pentru
fice fiecărui tip de eveniment - acestea descriu a trata evenimentele produse de componentele sale.
metode ce vor fi apelate Vom modifica puţin şi
automat la apariţia evenimentelor. aplicaţia pentru a pune în evidenţa o altă modalitate
6.4.1 Exemplu de tratare a evenimentelor de a determina componenta
Inainte de a detalia aspectele prezentate mai sus, să generatoare a unui eveniment - metoda getSource.
considerăm un exemplu Listing 9.10: Tratarea evenimentelor în ferestră
de tratare a evenimentelor. Vom crea o fereastră import java . awt .*;
care să conţină două butoane import java . awt. event .*;
cu numele ”OK”, repectiv ”Cancel”. La apăsarea class Fereastra extends Frame implements
fiecărui buton vom ActionListener {
scrie pe bara de titlu a ferestrei mesajul ”Ati apasat Button ok = new Button ("OK");
butonul ...”. Button exit = new Button (" Exit ");
Listing 9.9: Ascultarea evenimentelor a două int n=0;
butoane public Fereastra ( String titlu ) {
import java . awt .*; super ( titlu );
import java . awt. event .*; setLayout (new FlowLayout ());
class Fereastra extends Frame { setSize (200 , 100) ;
public Fereastra ( String titlu ) { add (ok);
super ( titlu ); add ( exit );
setLayout (new FlowLayout ()); ok. addActionListener ( this );
setSize (200 , 100) ; exit . addActionListener ( this );
Button b1 = new Button ("OK"); // Ambele butoane sunt ascultate in clasa Fereastra
Button b2 = new Button (" Cancel "); // deci ascultatorul este instanta curenta : this
add (b1); }
add (b2); // Metoda interfetei ActionListener
Ascultator listener = new Ascultator ( this ); public void actionPerformed ( ActionEvent e) {
b1. addActionListener ( listener ); if (e. getSource () == exit )
b2. addActionListener ( listener ); System . exit (0); // Terminam aplicatia
// Ambele butoane sunt ascultate de obiectul listener if (e. getSource () == ok) {
, n ++;
// instanta a clasei Ascultator , definita mai jos this . setTitle ("Ati apasat OK de " + n + " ori");
} }
} }
class Ascultator implements ActionListener { }
private Fereastra f; public class TestEvent2 {
public Ascultator ( Fereastra f) { public static void main ( String args []) {
this .f = f; Fereastra f = new Fereastra (" Test Event ");
} f. show ();
// Metoda interfetei ActionListener }
public void actionPerformed ( ActionEvent e) { }
f. setTitle ("Ati apasat " + e. getActionCommand Aşadar, orice clasă poate asculta evenimente de
()); orice tip cu condiţia să

65
implementeze interfeţele specifice acelor tipuri de CheckboxMenuItem
evenimente. Scrollbar AdjustmentListener
6.4.2 Tipuri de evenimente TextField TextListener
Evenimentele se împart în două categorii: de nivel TextArea
jos şi semantice. Observaţi că deşi există o singură clasă
Evenimentele de nivel jos reprezintă o interacţiune MouseEvent, există două interfeţe
de nivel jos cum ar asociate MouseListener şi MouseMotionListener.
fi o apăsare de tastă, mişcarea mouse-ului, sau o Acest lucru a fost făcut
operaţie asupra unei ferestre. deoarece evenimentele legate de deplasarea mouse-
In tabelul de mai jos sunt enumerate clasele ce ului sunt generate foarte
descriu aceste evenimente şi frecvent şi recepţionarea lor poate avea un impact
operaţiunile efectuate (asupra unei componente) negativ asupra vitezei de
care le generează: execuţie, în situaţia când tratarea acestora nu ne
ComponentEvent Ascundere, deplasare, interesează şi dorim să
redimensionare, afişare tratăm doar evenimente de tip click, de exemplu.
ContainerEvent Adăugare pe container, eliminare Orice clasă care tratează evenimente trebuie să
FocusEvent Obţinere, pierdere foucs implementeze obligatoriu
KeyEvent Apăsare, eliberare taste, tastare metodele interfeţelor corespunzătoare. Tabelul de
MouseEvent Operaţiuni cu mouse-ul: click, drag, mai jos prezintă, pentru
etc. fiecare interfaţă, metodele puse la dispozitie şi care
WindowEvent Operaţiuni asupra ferestrelor: trebuie implementate de
minimizare, maximizare,etc. către clasa ascultător.
O anumită acţiune a utilizatorului poate genera mai Interfaţă Metode
multe evenimente. ActionListener actionPerformed(ActionEvent e)
De exemplu, tastarea literei ’A’ va genera trei AdjustmentListener
evenimente: unul pentru adjustmentValueChanged(AdjustmentEvent e)
apăsare, unul pentru eliberare şi unul pentru tastare. componentHidden(ComponentEvent e)
In funcţie de necesit ComponentListener
ăţile aplicaţie putem scrie cod pentru tratarea componentMoved(ComponentEvent e)
fiecărui eveniment în parte. componentResized(ComponentEvent e)
Evenimentele semantice reprezintă interacţiunea cu componentShown(ComponentEvent e)
o componentă ContainerListener
GUI: apăsarea unui buton, selectarea unui articol componentAdded(ContainerEvent e)
dintr-o listă, etc. Clasele componentRemoved(ContainerEvent e)
care descriu aceste tipuri de evenimente sunt: FocusListener focusGained(FocusEvent e)
ActionEvent Acţionare focusLost(FocusEvent e)
AdjustmentEvent Ajustarea unei valori ItemListener itemStateChanged(ItemEvent e)
ItemEvent Schimbarea stării keyPressed(KeyEvent e)
TextEvent Schimbarea textului KeyListener keyReleased(KeyEvent e)
Următorul tabel prezintă componentele AWT şi keyTyped(KeyEvent e)
tipurile de evenimente mouseClicked(MouseEvent e)
generate, prezentate sub forma interfeţelor mouseEntered(MouseEvent e)
corespunzătoare. Evident, evenimentele MouseListener mouseExited(MouseEvent e)
generate de o superclasă, cum ar fi Component, se mousePressed(MouseEvent e)
vor regăsi şi pentru mouseReleased(MouseEvent e)
toate subclasele sale. MouseMotionListener mouseDragged(MouseEvent
Component ComponentListener e)
FocusListener mouseMoved(MouseEvent e)
KeyListener TextListener textValueChanged(TextEvent e)
MouseListener windowActivated(WindowEvent e)
MouseMotionListener windowClosed(WindowEvent e)
Container ContainerListener windowClosing(WindowEvent e)
Window WindowListener WindowListener windowDeactivated(WindowEvent
Button e)
List ActionListener windowDeiconified(WindowEvent e)
MenuItem windowIconified(WindowEvent e)
TextField windowOpened(WindowEvent e)
Choice In cazulîn care un obiect listener tratează
Checkbox ItemListener evenimente de acelaşi tip provocate
List

66
de componente diferite, este necesar să putem afla, Pentru a realiza acest lucru trebuie interceptat
în cadrul uneia din evenimentul de închidere a
metodele de mai sus, care este sursa evenimentului ferestrei în metoda windoClosing şi apelată metoda
pe care îl tratăm pentru dispose de închidere
a putea reacţiona în consecinţă. Toate tipurile de a ferestrei, sau System.exit pentru terminarea
evenimente moştenesc programului, în cazul când
metoda getSource care returnează obiectul este vorba de fereastra principală a aplicaţiei.
responsabil cu generarea evenimentului. Aceasta înseamnă că trebuie
In cazul în care dorim să diferenţiem doar tipul să implementăm interfaţa WindowListener care are
componentei sursă, nu mai puţin de şapte
putem folosi operatorul instanceof. metode.
public void actionPerformed(ActionEvent e) { Listing 6.11: Implementarea interfeţei
Object sursa = e.getSource(); WindowListener
if (sursa instanceof Button) { import java . awt .*;
// A fost apasat un buton import java . awt. event .*;
Button btn = (Button) sursa; class Fereastra extends Frame implements
if (btn == ok) { WindowListener {
// A fost apasat butonul ’ok’ public Fereastra ( String titlu ) {
} super ( titlu );
... this . addWindowListener ( this );
} }
if (sursa instanceof TextField) { // Metodele interfetei WindowListener
// S-a apasat Enter dupa editarea textului public void windowOpened ( WindowEvent e) {}
TextField tf = (TextField) sursa; public void windowClosing ( WindowEvent e) {
if (tf == nume) { // Terminare program
// A fost editata componenta ’nume’ System . exit (0);
} }
... public void windowClosed ( WindowEvent e) {}
} public void windowIconified ( WindowEvent e) {}
} public void windowDeiconified ( WindowEvent e)
Pe lângă getSource, obiectele ce descriu evenimente {}
pot pune la dispoziţie public void windowActivated ( WindowEvent e) {}
şi alte metode specifice care permit aflarea de public void windowDeactivated ( WindowEvent e)
informaţii legate de evenimentul {}
generat. De exemplu, ActionEvent conţine metoda }
getActionCommand public class TestWindowListener {
care, implicit, returnează eticheta butonului care a public static void main ( String args []) {
fost apăsat. Astfel de Fereastra f = new Fereastra (" Test WindowListener
particularităţi vor fi prezentate mai detaliat în ");
secţiunile dedicate fiecârei f. show ();
componente în parte. }
6.4.3 Folosirea adaptorilor şi a claselor anonime }
Am vazut că o clasă care tratează evenimente de un Observaţi că trebuie să implementăm toate metodele
anumit tip trebuie să implementeze interfeţei, chiar dacă
interfaţa corespunzătoare acelui tip. Aceasta nu scriem nici un cod pentru unele dintre ele.
înseamnă că trebuie Singura metodă care ne intereseaz
să implementeze obligatoriu toate metodele definite ă este windowClosing, în care specificăm ce trebuie
de acea interfaţă, chiar făcut atunci când
dacă nu specifică nici un cod pentru unele dintre ele. utilizatorul doreste să închidă fereastra. Pentru a
Sunt însă situaţii când evita scrierea inutilă a
acest lucru poate deveni supărator, mai ales atunci acestor metode, există o serie de clase care
când nu ne interesează implementează interfeţele de tip
decât o singura metodă a interfeţei. ”listener” fără a specifica nici un cod pentru
Un exemplu sugestiv este următorul: o fereastră care metodele lor. Aceste clase se
nu are specificat cod numesc adaptori.
pentru tratarea evenimentelor sale nu poate fi Un adaptor este o clasă abstractă care
închisă cu butonul standard implementează o anumită interfaţă
marcat cu ’x’ din colţul dreapta sus şi nici cu fără a specifica cod nici unei metode a interfeţei.
combinaţia de taste Alt+F4. Scopul unei astfel de clase este ca la crearea unui
”ascultător” de evenimente,

67
în loc să implementă o anumită interfaţă şi implicit }
toate metodele }
sale, să extindem adaptorul corespunzător interfeţei In tabelul de mai jos sunt daţi toţi adaptorii
respective (dacă are!) interfeţelor de tip ”listener”
şi să supradefinim doar metodele care ne interesează - se obervă că o interfaţă XXXListener are un
(cele în care vrem să adaptor de tipul XXXAdapter.
scriem o anumită secvenţă de cod). Interfeţele care nu au un adaptor sunt cele care
De exemplu, adaptorul interfeţei WindowListener definesc o singură metodă şi
este WindowAdapter prin urmare crearea unei clase adaptor nu îsi are
iar folosirea acestuia este dată în exemplul de mai rostul.
jos: Interfaţa Adaptor
Listing 9.12: Extinderea clasei WindowAdapter ActionListener nu are
import java . awt .*; AdjustemnrListener nu are
import java . awt. event .*; ComponentListener ComponentAdapter
class Fereastra extends Frame { ContainerListener ContainerAdapter
public Fereastra ( String titlu ) { FocusListener FocusAdapter
super ( titlu ); ItemListener nu are
this . addWindowListener (new Ascultator ()); KeyListener KeyAdapter
} MouseListener MouseAdapter
} MouseMotionListener MouseMotionAdapter
class Ascultator extends WindowAdapter { TextListener nu are
// Suprdefinim metodele care ne intereseaza WindowListener WindowAdapter
public void windowClosing ( WindowEvent e) { Ştim că o clasă internă este o clasă declarată în
System . exit (0); cadrul altei clase, iar
} clasele anonime sunt clase interne folosite pentru
} instanţierea unui singur
public class TestWindowAdapter { obiect de un anumit tip. Un exemplu tipic de
public static void main ( String args []) { folosire a lor este instanţierea
Fereastra f = new Fereastra (" Test WindowAdapter adaptorilor direct în corpul unei clase care conţine
"); componente ale căror
f. show (); evenimente trebuie tratate.
} Listing 6.13: Folosirea adaptorilor şi a claselor
} anonime
Avantajul clar al acestei modalităţi de tratare a import java . awt .*;
evenimentelor este reducerea import java . awt. event .*;
codului programului, acesta devenind mult mai class Fereastra extends Frame {
lizibil. Insă există şi public Fereastra ( String titlu ) {
două dezavantaje majore. După cum aţi observat super ( titlu );
faţăde exemplul anterior, setSize (400 , 400) ;
clasa Fereastra nu poate extinde WindowAdapter this . addWindowListener (new WindowAdapter ()
deoarece ea extinde deja {
clasa Frame şi din acest motiv am construit o nouă public void windowClosing ( WindowEvent e) {
clasă numită Ascultator. // Terminam aplicatia
Vom vedea însă că acest dezavantaj poate fi System . exit (0);
eliminat prin folosirea unei clase }
anonime. });
Un alt dezavantaj este că orice greşeală de sintaxă în final Label label = new Label ("", Label .
declararea unei metode CENTER );
a interfeţei nu va produce o eroare de compilare dar label . setBackground ( Color . yellow );
nici nu va supradefini add (label , BorderLayout . NORTH );
metoda interfeţei ci, pur şi simplu, va crea o metodă this . addMouseListener (new MouseAdapter () {
a clasei respective. public void mouseClicked ( MouseEvent e) {
class Ascultator extends WindowAdapter { // Desenam un cerc la fiecare click de mouse
// In loc de windowClosing scriem WindowClosing label . setText (" Click ... ");
// Nu supradefinim vreo metoda a clasei Graphics g = Fereastra . this . getGraphics ();
WindowAdapter g. setColor ( Color . blue );
// Nu da nici o eroare int raza = ( int )( Math . random () * 50);
// Nu face nimic ! g. fillOval (e. getX () , e. getY () , raza , raza );
public void WindowClosing(WindowEvent e) { }
System.exit(0); });

68
this . addMouseMotionListener ( new adăugarea tuturor componentelor pe suprafaţa
MouseMotionAdapter () { ferestrei.
public void mouseMoved ( MouseEvent e) { • getFocusOwner - returnează componenta ferestrei
// Desenam un punct la coordonatele mouse - ului care are focus-ul
Graphics g = Fereastra . this . getGraphics (); (dacă fereastra este activă).
g. drawOval (e. getX () , e. getY () , 1, 1); 6.5.2 Clasa Frame
} Este derivată a clasei Window şi este folosită pentru
}); crearea de ferestre independente
this . addKeyListener (new KeyAdapter () { şi funcţionale, eventual continând o bară de meniuri.
public void keyTyped ( KeyEvent e) { Orice aplicaţie
// Afisam caracterul tastat cu interfaţă grafică contţine cel puţin o fereastră, cea
label . setText ("Ati tastat : " + e. getKeyChar () + mai importantă fiind
""); numită şi fereastra principală.
} Constructorii uzuali ai clasei Frame permit crearea
}); unei ferestre cu sau
} fără titlu, iniţial invizibilă. Pentru ca o fereastră să
} devină vizibilă se va
public class TestAdapters { apela metoda show definită în superclasa Window.
public static void main ( String args []) { import java.awt.*;
Fereastra f = new Fereastra (" Test adaptori "); public class TestFrame {
f. show (); public static void main(String args[]) {
} Frame f = new Frame("Titlul ferestrei");
} f.show();
6.5 Folosirea ferestrelor }
După cum am văzut suprafeţele de afişare ale }
componentelor sunt extensii Crearea ferestrelor prin instanţierea directă a
ale clasei Container. O categorie aparte a acestor obiectelor de tip Frame este
containere o reprezintă mai puţin folosită. De obicei, ferestrele unui
ferestrele. Acestea sunt descrise de clase derivate program vor fi definite în clase
din Window, cele mai separate care extind clasa Frame, ca în exemplul de
utilizate fiind Frame şi Dialog. mai jos:
O aplicaţie Java cu intefaţă grafică va fi formată din import java.awt.*;
una sau mai multe class Fereastra extends Frame{
ferestre, una dintre ele fiind numită fereastra // Constructorul
principală. public Fereastra(String titlu) {
9.5.1 Clasa Window super(titlu);
Clasa Window este rar utilizată în mod direct ...
deoarece permite doar crearea }
unor ferestre care nu au chenar şi nici bară de }
meniuri. Este utilă atunci public class TestFrame {
când dorim să afişam ferestre care nu public static void main(String args[]) {
interacţionează cu utilizatorul ci doar Fereastra f = new Fereastra("Titlul ferestrei");
oferă anumite informaţii. f.show();
Metodele mai importante ale clasei Window, care }
sunt de altfel moştenite }
de toate subclasele sale, sunt date de mai jos: Gestionarul de poziţionare implicit al clasei Frame
• show - face vizibilă fereastra. Implicit, o fereastră este BorderLayout.
nou creată nu este Din acest motiv, în momentul în care fereastra este
vizibilă; creată dar nici o component
• hide - face fereastra invizibilă fără a o distruge ă grafică nu este adăugată, suprafaţa de afişare a
însă; pentru a redeveni feretrei va fi determinat
vizibila se poate apela metoda show; ă automota de gestionarul de pozitţionare şi va oferi
• isShowing - testează dacă fereastra este vizibilă doar spaţiul necesar
sau nu; afişării barei ferestrei şi grupului de butoane pentru
• dispose - închide) fereastra şi şi eliberează toate minimizare, maximizare
resursele acesteia; şi închidere. Acelaşi efect îl vom obţine dacă o
• pack - redimensionează automat fereastra la o redimenionam şi apelăm apoi
suprafaţa optimă care metoda pack care determină dimeniunea suprafeţei
să cuprindă toate componentele sale; trebuie apelată de afişare în funcţie de
în general după componentele adăugate.

69
Se observă de asemenea că butonul deînchidere a • setMenuBar - setează bara de meniuri a ferestrei
ferestrei nu este funcţional. (vezi ”Folosirea meniurilor”);
Tratarea evenimentelor ferestrei se face prin • setTitle - setează titlul ferestrei;
implementarea interfeţei WindowListener • setResizable - stabileşte dacă fereastra poate fi
sau, mai uzual, prin folosirea unui adaptor de tip redimenionată de utilizator;
WindowAdapter. 6.5.3 Clasa Dialog
Structura generală a unei ferestre este descrisă de Toate interfeţele grafice oferă un tip special de
clasa Fereastra din ferestre destinate preluării
exemplul de mai jos: unor informaţii sau a unor date de la utilizator.
Listing 6.14: Structura generală a unei ferestre Acestea se numesc ferestre
import java . awt .*; de dialog sau casete de dialog şi sunt implementate
import java . awt. event .*; prin intermediul clasei
class Fereastra extends Frame implements Dialog, subclasă directă a clasei Window.
ActionListener { Diferenţa majoră dintre ferestrele de dialog şi
// Constructorul ferestrele de tip Frame
public Fereastra ( String titlu ) { constă în faptul că o fereastră de dialog este
super ( titlu ); dependentă de o altă fereastra
// Tratam evenimentul de inchidere a ferestrei (normală sau tot fereastră de dialog), numită şi
this . addWindowListener (new WindowAdapter () fereastra părinte. Cu alte
{ cuvinte, ferestrele de dialog nu au o existenţă de
public void windowClosing ( WindowEvent e) { sine stătătoare. Când fereastra
dispose (); // inchidem fereastra părinte este distrusă sunt distruse şi ferestrele sale de
// sau terminam aplicatia dialog, când este
System . exit (0); minimizată ferestrele sale de dialog sunt făcute
} invizibile iar când este restaurat
}); ă acestea sunt aduse la starea în care se găseau în
// Eventual , schimbam gestionarul de pozitionare momentul minimizării
setLayout (new FlowLayout ()); ferestrei părinte.
// Adaugam componentele pe suprafata ferestrei Ferestrele de dialog pot fi de două tipuri:
Button exit = new Button (" Exit "); • modale: care blochează accesul la fereastra parinte
add ( exit ); în momentul deschiderii
// Facem inregistrarea claselor listener lor, cum ar fi ferestrele de introducere a unor date,
exit . addActionListener ( this ); de alegere
// Stabilim dimensiunile a unui fişier, de selectare a unei opţiuni, mesaje de
pack (); // implicit avertizare, etc;
// sau explicit • nemodale: care nu blochează fluxul de intrare către
// setSize (200 , 200) ; fereastra părinte
} - de exemplu, dialogul de căutare a unui cuvânt într-
// Implementam metodele interfetelor de tip listener un fişier, etc.
public void actionPerformed ( ActionEvent e) { Implicit, o fereastră de dialog este nemodală şi
System . exit (0); invizibilă, însă există constructori
} care să specifice şi aceşti parametri. Constructorii
} clasei Dialog
public class TestFrame { sunt:
public static void main ( String args []) { Dialog(Frame parinte)
// Cream fereastra Dialog(Frame parinte, String titlu)
Fereastra f = new Fereastra ("O fereastra "); Dialog(Frame parinte, String titlu, boolean modala)
// O facem vizibila Dialog(Frame parinte, boolean modala)
f. show (); Dialog(Dialog parinte)
} Dialog(Dialog parinte, String titlu)
} Dialog(Dialog parinte, String titlu, boolean modala)
Pe lângă metodele moştenite din clasa Window, Parametrul ”părinte” reprezintă referinţa la fereastra
există o serie de metode părinte, ”titlu”
specifice clasei Frame. Dintre cele mai folosite reprezintă titlul ferestrei iar prin argumentul
amintim: ”modală” specificăm dacă fereastra
• getFrames - metodă statică ce returnează lista de dialog creată va fi modală (true) sau nemodală
tuturor ferestrelor deschise (false - valoarea
ale unei aplicaţii; implicită).
• setIconImage - setează iconiţa ferestrei; Crearea unei ferestre de dialog este relativ simpla şi
se realizează prin

70
derivarea clasei Dialog. Comunicarea dintre }
fereastra de dialog şi fereastra // Fereastra de dialog
sa părinte, pentru ca aceasta din urmă să poată folosi class FerDialog extends Dialog implements
datele introduse (sau ActionListener {
opţiunea specificata) în caseta de dialog, se poate public String raspuns = null ;
realiza folosind una din private TextField text ;
următoarele abordări generale: private Button ok , cancel ;
• obiectul care reprezintă dialogul poate să trateze public FerDialog ( Frame parinte , String titlu ,
evenimentele generate boolean
de componentele de pe suprafaţa să şi să seteze modala ) {
valorile unor variabile super ( parinte , titlu , modala );
accesibile ale ferestrei părinteîn momentulîn care this . addWindowListener (new WindowAdapter ()
dialogul esteîncheiat; {
• obiectul care creează dialogul (fereastra părinte) să public void windowClosing ( WindowEvent e) {
se înregistreze ca raspuns = null ;
ascultător al evenimentelor de la butoanele care dispose ();
determină încheierea }
dialogului, iar fereastra de dialog să ofere metode });
publice prin care text = new TextField ("", 30) ;
datele introduse să fie preluate din exterior; add (text , BorderLayout . CENTER );
Să creăm, de exemplu, o fereastră de dialog modală Panel panel = new Panel ();
pentru introducerea ok = new Button ("OK");
unui şir de caractere. Fereastra principală a aplicatiei 9.5. FOLOSIREA FERESTRELOR 239
va fi părintele casetei cancel = new Button (" Cancel ");
de dialog, va primi şirul de caractere introdus şi îsi panel .add(ok);
va modifica titlul ca fiind panel .add( cancel );
acesta. Deschiderea ferestrei de dialog se va face la add (panel , BorderLayout . SOUTH );
apăsarea unui buton al pack ();
ferestrei principale numit ”Schimba titlul”. Cele text . addActionListener ( this );
două ferestre vor arăta ca ok. addActionListener ( this );
în imaginile de mai jos: cancel . addActionListener ( this );
Fereastra principală Fereastra de dialog show ();
Listing 6.15: Folosirea unei ferestre de dialog }
import java . awt .*; public void actionPerformed ( ActionEvent e) {
import java . awt. event .*; Object sursa = e. getSource ();
// Fereastra principala if ( sursa == ok || sursa == text )
class FerPrinc extends Frame implements raspuns = text . getText ();
ActionListener { else
public FerPrinc ( String titlu ) { raspuns = null ;
super ( titlu ); dispose ();
this . addWindowListener (new WindowAdapter () }
{ }
public void windowClosing ( WindowEvent e) { // Clasa principala
System . exit (0); public class TestDialog {
} public static void main ( String args []) {
}); FerPrinc f = new FerPrinc (" Fereastra principala ");
setLayout (new FlowLayout ()); f. show ();
setSize (300 , 80); }
Button b = new Button (" Schimba titlul "); }
add (b); 6.5.4 Clasa FileDialog
b. addActionListener ( this ); Pachetul java.awt pune la dispozitie şi un tip de
} fereastră de dialog folosită
public void actionPerformed ( ActionEvent e) { pentru selectarea unui nume de fişier în vederea
FerDialog d = new FerDialog (this , " Dati titlul ", încărcării sau salvării unui
true ); fişier: clasa FileDialog, derivată din Dialog.
String titlu = d. raspuns ; Instanţele acestei clase au un
if ( titlu == null ) comportament comun dialogurilor de acest tip de pe
return ; majoritatea platformelor
setTitle ( titlu ); de lucru, dar forma în care vor fi afişate este
} specifică platformei pe care

71
rulează aplicaţia. FileDialog fd = new FileDialog (this , " Alegeti un
Constructorii clasei sunt: fisier ",
FileDialog(Frame parinte) FileDialog . LOAD );
FileDialog(Frame parinte, String titlu) // Stabilim directorul curent
FileDialog(Frame parinte, String titlu, boolean mod) fd. setDirectory (".");
Parametrul ”părinte” reprezintă referinţa ferestrei // Stabilim numele implicit
părinte, ”titlu” reprezintă fd. setFile (" TestFileDialog . java ");
titlul ferestrei iar prin argumentul ”mod” specificăm // Specificam filtrul
dacă încărcăm sau fd. setFilenameFilter ( new FilenameFilter () {
salvăm un fişier; valorile pe care le poate lua acest public boolean accept ( File dir , String numeFis ) {
argument sunt: return ( numeFis . endsWith (". java "));
• FileDialog.LOAD - pentru încărcare, respectiv }
• FileDialog.SAVE - pentru salvare. });
// Dialog pentru incarcarea unui fisier // Afisam fereastra de dialog ( modala )
new FileDialog(parinte, "Alegere fisier", fd. show ();
FileDialog.LOAD); System . out. println (" Fisierul ales este :" + fd.
// Dialog pentru salvarea unui fisier getFile ());
new FileDialog(parinte, "Salvare fisier", }
FileDialog.SAVE); }
La crearea unui obiect FileDialog acesta nu este public class TestFileDialog {
implicit vizibil. Dacă public static void main ( String args []) {
afişarea sa se face cu show, caseta de dialog va fi FerPrinc f = new FerPrinc (" Fereastra principala ");
modală. Dacă afişarea f. show ();
se face cu setVisible(true), atunci va fi nemodală. }
După selectarea unui }
fişier ea va fi facută automat invizibilă. Clasa FileDialog este folosită mai rar deoarece în
Pe lângă metodele moştenite de la superclasa Dialog Swing există clasa
clasa FileDialog JFileChooser care oferă mai multe facilităţi şi prin
mai conţine metode pentru obţinerea numelui urmare va constitui
fişierului sau directorului selectat prima opţiune într-o aplicaţie cu intefaţă grafică.
getFile, getDirectory, pentru stabilirea unui criteriu 6.6 Folosirea meniurilor
de filtrare Spre deosebire de celelalte obiecte grafice care
setFilenameFilter, etc. derivă din clasa Component,
Să considerăm un exemplu în care vom alege, prin componentele unui meniu reprezintă instanţe ale
intermediul unui obiect unor clase derivate din superclasa
FileDialog, un fişier cu extensia ”java”. Directorul abstractă MenuComponent. Această excepţie este
iniţial este directorul facută deoarece
curent, iar numele implicit este TestFileDialog.java. unele platforme grafice limitează capabilităţile unui
Numele fişierului meniu.
ales va fi afişat la consolă. Meniurile pot fi grupate în două categorii:
Listing 6.16: Folosirea unei ferestre de dialog • Meniuri fixe (vizibile permanent): sunt
import java . awt .*; grupateîntr-o bară de meniuri
import java . awt. event .*; ce conţine câte un meniu pentru fiecare intrare a sa.
import java .io .*; La rândul lor,
class FerPrinc extends Frame implements aceste meniuri conţin articole ce pot fi selectate,
ActionListener { comutatoare sau alte
public FerPrinc ( String titlu ) { meniuri (submeniuri). O fereastră poate avea un
super ( titlu ); singur meniu fix.
this . addWindowListener (new WindowAdapter () • Meniuri de context (popup): sunt meniuri invizbile
{ asociate unei
public void windowClosing ( WindowEvent e) { ferestre şi care se activează uzual prin apăsarea
System . exit (0); butonului drept al
} mouse-ului. O altă diferenţă faţă de meniurile fixe
}); constă în faptul
Button b = new Button (" Alege fisier "); că meniurile de context nu sunt grupate într-o bară
add (b, BorderLayout . CENTER ); de meniuri.
pack (); In figura de mai jos este pusă în evidenţă alcătuirea
b. addActionListener ( this ); unui meniu fix:
} Exemplul de mai sus conţine o bară de meniuri
public void actionPerformed ( ActionEvent e) { formată din două meniuri

72
principale File şi Edit. Meniul Edit conţine la rândul clasei MenuItem reprezintă de fapt un buton sau un
lui alt meniu (submeniu) comutator, cu o anumită
Options, articolul Undo şi două comutatoare Bold şi etichetă care va apărea în meniu, însoţită eventual
Italic. Prin abuz de de un accelerator (obiect
limbaj, vom referi uneori bara de meniuri a unei de tip MenuShortcut) ce reprezintă combinaţia de
ferestre ca fiind meniul taste cu care articolul
ferestrei. poate fi apelat rapid (vezi ”Acceleratori”).
In modelul AWT obiectele care reprezintă bare de Clasa Menu permite crearea unui meniu derulant
meniuri sunt reprezentate într-o bară de meniuri.
ca instanţe al clasei MenuBar. Un obiect de tip Opţional, un meniu poate fi declarat ca fiind tear-o_,
MenuBar conţine obiecte ceea ce înseamnă că
de tip Menu, care sunt de fapt meniurile derulante poate fi deschis şi deplasat cu mouse-ul (dragged)
propriu-zise. La rândul într-o altă poziţie decât
lor, acestea pot conţine obiecte de tip MenuItem, cea originală (”rupt” din poziţia sa). Acest
CheckBoxMenuItem, mecanism este dependent de
dar şi alte obiecte de tip Menu (submeniuri). platformă şi poate fi ignorat pe unele dintre ele.
Pentru a putea conţine un meniu, o componentă Fiecare meniu are o etichetă,
trebuie să implementeze care este de fapt numele său ce va fi afişat pe bara
interfaţa MenuContainer. Cel mai adesea, meniurile de meniuri. Articolele
sunt ataşate ferestrelor, dintr-un meniu trebuie să aparţină clasei MenuItem,
mai precis obiectelor de tip Frame, acestea ceea ce înseamnă că pot
implementând interfaţă fi instanţe ale uneia din clasele MenuItem, Menu
MenuContainer. Ataşarea unei bare de meniuri la o sau CheckboxMenuItem.
fereastră se face prin Clasa CheckboxMenuItem implementează într-un
metoda addMenuBar a clasei Frame. meniu articole de
9.6.1 Ierarhia claselor ce descriu meniuri tip comutator - care au două stări logice
Să vedem în continuare care este ierarhia claselor (validat/nevalidat), acţionarea articolului
folosite în lucrul cu meniuri determinând trecerea sa dintr-o stare în alta. La
şi să analizăm pe rând aceste clase: validarea unui
Clasa MenuComponent este o clasa abstractă din comutator în dreptul etichetei sale va fi afişat un
care sunt extinse simbol grafic care indică
toate celelalte clase folosite la crearea de meniuri, acest lucru; la invalidarea sa, simbolul grafic
fiind similară celeilalte respectiv va dispărea. Clasa
superclase abstracte Component. MenuComponent CheckboxMenuItem are aceeaşi funcţionalitate cu
conţine metode cu caracter cea a casetelor de validare
general, dintre care amintim getName, setName, de tip Checkbox, ambele implementând interfaţa
getFont, setFont, ItemSelectable.
cu sintaxa şi semnificaţiile uzuale. Să vedem în continuare cum ar arăta un program
Clasa MenuBar permite crearea barelor de meniuri care construieşte un
asociate unei ferestre meniu ca în figura prezentată anterior:
cadru de tip Frame, adaptând conceptul de bară de Listing 6.17: Crearea unui meniu
meniuri la platforma import java . awt .*;
curentă de lucru. După cum am mai spus, pentru a import java . awt. event .*;
lega bara de meniuri la public class TestMenu {
o anumită fereastra trebuie apelată metoda public static void main ( String args []) {
setMenuBar din clasa Frame. Frame f = new Frame (" Test Menu ");
// Crearea barei de meniuri MenuBar mb = new MenuBar ();
MenuBar mb = new MenuBar(); Menu fisier = new Menu (" File ");
// Adaugarea meniurilor derulante la bara de meniuri fisier . add( new MenuItem (" Open "));
... fisier . add( new MenuItem (" Close "));
// Atasarea barei de meniuri la o fereastra fisier . addSeparator ();
Frame f = new Frame("Fereastra cu meniu"); fisier . add( new MenuItem (" Exit "));
f.addMenuBar(mb); Menu optiuni = new Menu (" Options ");
Orice articol al unui meniu trebuie să fie o instanţa a optiuni . add( new MenuItem (" Copy "));
clasei Menu- optiuni . add( new MenuItem ("Cut"));
Item. Obiectele acestei clase descriu aşadar optiuni . add( new MenuItem (" Paste "));
opţiunile individuale ale meniurilor Menu editare = new Menu (" Edit ");
derulante, cum sunt ”Open”, ”Close”, ”Exit”, etc. O editare . add( new MenuItem (" Undo "));
instanţă a editare . add( optiuni );
editare . addSeparator ();

73
editare . add( new CheckboxMenuItem (" Bold ")); super ( titlu );
editare . add( new CheckboxMenuItem (" Italic ")); MenuBar mb = new MenuBar ();
mb. add( fisier ); Menu test = new Menu (" Test ");
mb. add( editare ); CheckboxMenuItem check = new
f. setMenuBar (mb); CheckboxMenuItem (" Check me")
f. setSize (200 , 100) ; ;
f. show (); test . add( check );
} test . addSeparator ();
} test . add( new MenuItem (" Exit "));
6.6.2 Tratarea evenimentelor generate de mb. add( test );
meniuri setMenuBar (mb);
La alegerea unei opţiuni dintr-un meniu se Button btnExit = new Button (" Exit ");
generează fie un eveniment de tip add ( btnExit , BorderLayout . SOUTH );
ActionEvent dacă articolul respectiv este de tip setSize (300 , 200) ;
MenuItem, fie ItemEvent show ();
pentru comutatoarele CheckboxMenuItem. Aşadar, test . addActionListener ( this );
pentru a activa opţiunile check . addItemListener ( this );
unui meniu trebuie implementate interfaţele btnExit . addActionListener ( this );
ActionListener sau/şi Item- }
Listener în cadrul obiectelor care trebuie să public void actionPerformed ( ActionEvent e) {
specifice codul ce va fi executat // Valabila si pentru meniu si pentru buton
la alegerea unei opţiuni şi implementate metodele String command = e. getActionCommand ();
actionPerformed, respectiv if ( command . equals (" Exit "))
itemStatChanged. Fiecărui meniu îi putem asocia un System . exit (0);
obiect receptor }
diferit, ceea ce uşurează munca în cazul în care public void itemStateChanged ( ItemEvent e) {
ierarhia de meniuri este complex if (e. getStateChange () == ItemEvent . SELECTED
ă. Pentru a realiza legătura între obiectul meniu şi )
obiectul de tip listener setTitle (" Checked !");
trebuie să adaugăm receptorul în lista de ascultători else
a meniului respectiv, setTitle ("Not checked !");
întocmai ca pe orice componentă, folosind metodele }
addActionListener, public static void main ( String args []) {
respectiv addItemListener. TestMenuEvent f = new TestMenuEvent (" Tratare
Aşadar, tratarea evenimentelor generate de obiecte evenimente
de tip MenuItem este meniuri ");
identică cu tratarea butoanelor, ceea ce face posibil f. show ();
ca unui buton de pe }
suprafaţa de afişare să îi corespundă o opţiune dintr- }
un meniu, ambele cu 6.6.3 Meniuri de context (popup)
acelaşi nume, tratarea evenimentului corespunzător Au fost introduseîncepând cu AWT 1.1 şi sunt
apăsarii butonului, sau implementate prin intermediul
alegerii opţiunii, făcându-se o singură dată într-o clasei PopupMenu, subclasă directă a clasei Menu.
clasă care este înregistrată Sunt meniuri invizibile
ca receptor atât la buton cât şi la meniu. care sunt activate uzual prin apăsarea butonului
Obiectele de tip CheckboxMenuItem tip se găsesc drept al mouse-ului, fiind
într-o categorie comună afişate la poziţia la care se găsea mouse-ul în
cu List, Choice, CheckBox, toate implementând momentul apăsării butonului
interfaţa ItemSelectable său drept. Metodele de adăugare a articolelor unui
şi deci tratarea lor va fi făcută la fel. Tipul de meniu de context sunt
operatie selectare / deselectare moştenite întocmai de la meniurile fixe.
este codificatîn evenimentul generat de câmpurile PopupMenu popup = new PopupMenu("Options");
statice ItemEvent.SELECTED popup.add(new MenuItem("New"));
şi ItemEvent.DESELECTED. popup.add(new MenuItem("Edit"));
Listing 6.18: Tratarea evenimentelor unui meniu popup.addSeparator();
import java . awt .*; popup.add(new MenuItem("Exit"));
import java . awt. event .*; Afişarea meniului de context se face prin metoda
public class TestMenuEvent extends Frame show:
implements ActionListener , ItemListener { popup.show(Component origine, int x, int y)
public TestMenuEvent ( String titlu ) {

74
şi este de obicei rezultatul apăsarii unui buton al this . addMouseListener (new MouseAdapter () {
mouse-ului, pentru a avea public void mousePressed ( MouseEvent e) {
acces rapid la meniu. Argumentul ”origine” if (e. isPopupTrigger ())
reprezintă componenta faţă de popup . show (origin , e. getX () , e. getY ());
originile căreia se va calcula poziţia de afişare a }
meniului popup. De obicei, public void mouseReleased ( MouseEvent e) {
reprezintă instanţa ferestrei în care se va afişa if (e. isPopupTrigger ())
meniul. Deoarece interacţiunea popup . show (origin , e. getX () , e. getY ());
cu mouse-ul este dependentă de platforma de lucru, }
există o metodă care });
determină dacă un eveniment de tip MouseEvent setSize (300 , 300) ;
poate fi responsabil cu // Cream meniul popup
deschiderea unui meniu de context. Aceasta este popup = new PopupMenu (" Options ");
isPopupTrigger şi este popup .add(new MenuItem ("New"));
definită în clasa MouseEvent. Poziţionarea şi popup .add(new MenuItem (" Edit "));
afişarea meniului este însă popup . addSeparator ();
responsabilitatea programatorului. popup .add(new MenuItem (" Exit "));
Meniurile de context nu se adaugă la un alt meniu add ( popup ); // atasam meniul popup ferestrei
(bară sau sub-meniu) popup . addActionListener ( this );
ci se ataşează la o componentă (de obicei la o }
fereastră) prin metoda add public void actionPerformed ( ActionEvent e) {
a acesteia. In cazul când avem mai multe meniuri String command = e. getActionCommand ();
popup pe care vrem să if ( command . equals (" Exit "))
le folosim într-o fereastră, trebuie să le definim pe System . exit (0);
toate şi, la un moment }
dat, vom adăuga ferestrei meniul corespunzător }
după care îl vom face vizibil. public class TestPopupMenu {
După închiderea acestuia, vom ”rupe” legătura între public static void main ( String args []) {
fereastră şi meniu prin Fereastra f = new Fereastra (" PopupMenu ");
instrucţiunea remove: f. show ();
fereastra.add(popup1); }
... }
fereastra.remove(popup1); 6.6.4 Acceleratori (Clasa MenuShortcut)
fereastra.add(popup2); Pentru articolele unui menu este posibilă
In exemplul de mai jos, vom crea un meniu de specificarea unor combinaţii de
contex pe care îl vom activa taste numite acceleratori (shortcuts) care să permită
la apăsarea butonului drept al mouse-ului pe accesarea directă, prin
suprafaţa ferestrei principale. intermediul tastaturii, a opţiunilor dintr-un meniu.
Tratarea evenimentelor generate de un meniu popup Astfel, oricărui obiect
se realizează identic ca de tip MenuItem îi poate fi asociat un obiect de tip
pentru meniurile fixe. accelerator, definit prin
Listing 6.19: Folosirea unui meniu de context intermediul clasei MenuShortcut. Singurele
(popup) combinaţii de taste care pot
import java . awt .*; juca rolul acceleratorilor sunt: Ctrl + Tasta sau Ctrl
import java . awt. event .*; + Shift + Tasta.
class Fereastra extends Frame implements Atribuirea unui accelerator la un articol al unui
ActionListener { meniu poate fi realizată prin
// Definim meniul popup al ferestrei constructorul obiectelor de tip MenuItem în forma:
private PopupMenu popup ; MenuItem(String eticheta, MenuShortcut
// Pozitia meniului va fi relativa la fereastra accelerator), caîn exemplele
private Component origin ; de mai jos:
public Fereastra ( String titlu ) { // Ctrl+O
super ( titlu ); new MenuItem("Open", new
origin = this ; MenuShortcut(KeyEvent.VK_O));
this . addWindowListener (new WindowAdapter () // Ctrl+P
{ new MenuItem("Print", new MenuShortcut(’p’));
public void windowClosing ( WindowEvent e) { // Ctrl+Shift+P
System . exit (0); new MenuItem("Preview", new MenuShortcut(’p’),
} true);
}); 9.7 Folosirea componentelor AWT

75
In continuare vor fi date exemple de folosire ale System . exit (0);
componentelor AWT, în care }
să fie puse în evidentţă cât mai multe din });
particularităţile acestora, precum setLayout ( null );
şi modul de tratare a evenimentelor generate. setSize (200 , 120) ;
6.7.1 Clasa Label Button b1 = new Button ("OK");
Un obiect de tip Label (etichetă) reprezintă o b1. setBounds (30 , 30, 50, 70);
componentă pentru plasarea b1. setFont ( new Font (" Arial ", Font .BOLD ,
unui text pe o suprafaţa de afişare. O etichetă este 14));
formată dintr-o singură b1. setBackground ( Color . orange );
linie de text static ce nu poate fi modificat de către add (b1);
utilizator, dar poate fi Button b2 = new Button (" Cancel ");
modificat din program. b2. setBounds (100 , 30, 70, 50);
Listing 9.20: Folosirea clasei Label b2. setForeground ( Color . blue );
import java . awt .*; add (b2);
public class TestLabel { b1. addActionListener ( this );
public static void main ( String args []) { b2. addActionListener ( this );
Frame f = new Frame (" Label "); }
Label nord , sud , est , vest , centru ; // Metoda interfetei ActionListener
nord = new Label (" Nord ", Label . CENTER ); public void actionPerformed ( ActionEvent e) {
nord . setForeground ( Color . blue ); String command = e. getActionCommand ();
sud = new Label ("Sud ", Label . CENTER ); System . out. println (e);
sud . setForeground ( Color .red); if ( command . equals ("OK"))
vest = new Label (" Vest ", Label . LEFT ); setTitle (" Confirmare !");
vest . setFont ( new Font (" Dialog ", else
Font .ITALIC , 14)); if ( command . equals (" Cancel "))
est = new Label ("Est ", Label . RIGHT ); setTitle (" Anulare !");
est . setFont ( new Font (" Dialog ", Font .ITALIC , }
14)); }
centru = new Label (" Centru ", Label . CENTER ); public class TestButton {
centru . setBackground ( Color . yellow ); public static void main ( String args []) {
centru . setFont ( new Font (" Arial ", Font .BOLD , Fereastra f = new Fereastra (" Button ");
20)); f. show ();
f.add(nord , BorderLayout . NORTH ); }
f.add(sud , BorderLayout . SOUTH ); }
f.add(est , BorderLayout . EAST ); 6.7.3 Clasa Checkbox
f.add(vest , BorderLayout . WEST ); Un obiect de tip Checkbox (comutator) reprezintă o
252 CAPITOLUL 9. INTERFAŢA GRAFIC ă CU componentă care se
UTILIZATORUL poate găsi în două stări: ”selectată” sau
f.add(centru , BorderLayout . CENTER ); ”neselectată” (on/o_). Acţiunea
f. pack (); utilizatorului asupra unui comutator îl trece pe
f. show (); acesta în starea complementar
} ă celei în care se găsea. Este folosit pentru a prelua o
} anumită opţiune de
6.7.2 Clasa Button la utilizator.
Un obiect de tip Button reprezintă o componentă Listing 6.22: Folosirea clasei Checkbox
pentru plasarea unui buton import java . awt .*;
etichetat pe o suprafaţa de afişare. Textul etichetei import java . awt. event .*;
este format dintr-o class Fereastra extends Frame implements
singură linie. ItemListener {
Listing 9.21: Folosirea clasei Button private Label label1 , label2 ;
import java . awt .*; private Checkbox cbx1 , cbx2 , cbx3 ;
import java . awt. event .*; public Fereastra ( String titlu ) {
class Fereastra extends Frame implements super ( titlu );
ActionListener { this . addWindowListener (new WindowAdapter ()
public Fereastra ( String titlu ) { {
super ( titlu ); public void windowClosing ( WindowEvent e) {
this . addWindowListener (new WindowAdapter () System . exit (0);
{ }
public void windowClosing ( WindowEvent e) { });

76
setLayout (new GridLayout (5, 1)); }
label1 = new Label (" Ingrediente Pizza :", Label . });
CENTER ); setLayout (new GridLayout (5, 1));
label1 . setBackground ( Color . orange ); label1 = new Label (" Alegeti postul TV", Label .
label2 = new Label (""); CENTER );
label2 . setBackground ( Color . lightGray ); label1 . setBackground ( Color . orange );
cbx1 = new Checkbox (" cascaval "); label2 = new Label ("", Label . CENTER );
cbx2 = new Checkbox (" sunca "); label2 . setBackground ( Color . lightGray );
cbx3 = new Checkbox (" ardei "); cbg = new CheckboxGroup ();
add ( label1 ); cbx1 = new Checkbox ("HBO", cbg , false );
add ( label2 ); cbx2 = new Checkbox (" Discovery ", cbg , false );
add ( cbx1 ); cbx3 = new Checkbox ("MTV", cbg , false );
add ( cbx2 ); add ( label1 );
add ( cbx3 ); add ( label2 );
setSize (200 , 200) ; add ( cbx1 );
cbx1 . addItemListener ( this ); add ( cbx2 );
cbx2 . addItemListener ( this ); add ( cbx3 );
cbx3 . addItemListener ( this ); setSize (200 , 200) ;
} cbx1 . addItemListener ( this );
// Metoda interfetei ItemListener cbx2 . addItemListener ( this );
public void itemStateChanged ( ItemEvent e) { cbx3 . addItemListener ( this );
StringBuffer ingrediente = new StringBuffer (); }
if ( cbx1 . getState () == true ) // Metoda interfetei ItemListener
ingrediente . append (" cascaval "); public void itemStateChanged ( ItemEvent e) {
if ( cbx2 . getState () == true ) Checkbox cbx = cbg. getSelectedCheckbox ();
ingrediente . append (" sunca "); if (cbx != null )
if ( cbx3 . getState () == true ) label2 . setText (cbx. getLabel ());
ingrediente . append (" ardei "); }
label2 . setText ( ingrediente . toString ()); }
} public class TestCheckboxGroup {
} public static void main ( String args []) {
public class TestCheckbox { Fereastra f = new Fereastra (" CheckboxGroup ");
public static void main ( String args []) { f. show ();
Fereastra f = new Fereastra (" Checkbox "); }
f. show (); }
} 6.7.5 Clasa Choice
} Un obiect de tip Choice defineşte o listă de opţiuni
6.7.4 Clasa CheckboxGroup din care utilizatorul
Un obiect de tip CheckboxGroup defineşte un grup poate selecta una singură. La un moment dat, din
de comutatoare din care întreaga listă doar o singur
doar unul poate fi selectat. Uzual, aceste ă opţiune este vizibilă, cea selectată în momentul
componente se mai numesc butoane curent. O componentă
radio. Această clasă nu este derivată din Choice este însoţită de un buton etichetat cu o
Component, oferind doar o sageată verticală la apăsarea
modalitate de grupare a componentelor de tip căruia este afişată întreaga sa listă de elemente,
Checkbox. pentru ca utilizatorul să
Listing 9.23: Folosirea clasei CheckboxGroup poată selecta o anumită opţiune.
import java . awt .*; Listing 6.24: Folosirea clasei Choice
import java . awt. event .*; import java . awt .*;
class Fereastra extends Frame implements import java . awt. event .*;
ItemListener { class Fereastra extends Frame implements
private Label label1 , label2 ; ItemListener {
private Checkbox cbx1 , cbx2 , cbx3 ; private Label label ;
private CheckboxGroup cbg ; private Choice culori ;
public Fereastra ( String titlu ) { public Fereastra ( String titlu ) {
super ( titlu ); super ( titlu );
this . addWindowListener (new WindowAdapter () this . addWindowListener (new WindowAdapter ()
{ {
public void windowClosing ( WindowEvent e) { public void windowClosing ( WindowEvent e) {
System . exit (0); System . exit (0);

77
} label . setBackground ( Color .red);
}); culori = new List (3);
setLayout (new GridLayout (4, 1)); culori . add(" Rosu ");
label = new Label (" Alegeti culoarea "); culori . add(" Verde ");
label . setBackground ( Color .red); culori . add(" Albastru ");
culori = new Choice (); culori . select (3);
culori . add(" Rosu "); add ( label );
culori . add(" Verde "); add ( culori );
culori . add(" Albastru "); setSize (200 , 200) ;
culori . select (" Rosu "); culori . addItemListener ( this );
add ( label ); }
add ( culori ); // Metoda interfetei ItemListener
setSize (200 , 100) ; public void itemStateChanged ( ItemEvent e) {
culori . addItemListener ( this ); switch ( culori . getSelectedIndex ()) {
} case 0:
// Metoda interfetei ItemListener label . setBackground ( Color .red);
public void itemStateChanged ( ItemEvent e) { break ;
switch ( culori . getSelectedIndex ()) { case 1:
case 0: label . setBackground ( Color . green );
label . setBackground ( Color .red); break ;
break ; case 2:
case 1: label . setBackground ( Color . blue );
label . setBackground ( Color . green ); }
break ; }
case 2: }
label . setBackground ( Color . blue ); public class TestList {
} public static void main ( String args []) {
} Fereastra f = new Fereastra (" List ");
} f. show ();
public class TestChoice { }
public static void main ( String args []) { }
Fereastra f = new Fereastra (" Choice "); 6.7.7 Clasa ScrollBar
f. show (); Un obiect de tip Scrollbar defineşte o bară de
} defilare pe verticală sau
} orizontală. Este utilă pentru punerea la dispoziţia
6.7.6 Clasa List utilizatorului a unei
Un obiect de tip List defineşte o listă de opţiuni care modalităţi sugestive de a alege o anumită valoare
poate fi setată astfel dintr-un interval.
încât utilizatorul să poată selecta o singură opţiune Listing 9.26: Folosirea clasei ScrollBar
sau mai multe. Toate import java . awt .*;
elementele listei sunt vizibile în limita dimensiunilor import java . awt. event .*;
grafice ale componentei. class Fereastra extends Frame implements
Listing6.25: Folosirea clasei List AdjustmentListener {
import java . awt .*; private Scrollbar scroll ;
import java . awt. event .*; private Label valoare ;
class Fereastra extends Frame implements public Fereastra ( String titlu ) {
ItemListener { super ( titlu );
private Label label ; this . addWindowListener (new WindowAdapter ()
private List culori ; {
public Fereastra ( String titlu ) { public void windowClosing ( WindowEvent e) {
super ( titlu ); System . exit (0);
this . addWindowListener (new WindowAdapter () }
{ });
public void windowClosing ( WindowEvent e) { setLayout (new GridLayout (2, 1));
System . exit (0); valoare = new Label ("", Label . CENTER );
} valoare . setBackground ( Color . lightGray );
}); scroll = new Scrollbar ( Scrollbar . HORIZONTAL ,
setLayout (new GridLayout (2, 1)); 0, 1, 0,
label = new Label (" Alegeti culoarea ", Label . 101) ;
CENTER ); add ( valoare );

78
add ( scroll ); }
setSize (200 , 80); 9.7.9 Clasa TextField
scroll . addAdjustmentListener ( this ); Un obiect de tip TextField defineşte un control de
} editare a textului pe o
// Metoda interfetei AdjustmentListener singură linie. Este util pentru interogarea
public void adjustmentValueChanged utilizatorului asupra unor valori.
( AdjustmentEvent e) { Listing 6.28: Folosirea clasei TextField
valoare . setText ( scroll . getValue () + " %"); import java . awt .*;
} import java . awt. event .*;
} class Fereastra extends Frame implements
public class TestScrollbar { TextListener {
public static void main ( String args []) { private TextField nume , parola ;
Fereastra f = new Fereastra (" Scrollbar "); private Label acces ;
f. show (); private static final String UID=" Duke ", PWD="
} java " ;
} public Fereastra ( String titlu ) {
6.7.8 Clasa ScrollPane super ( titlu );
Un obiect de tip ScrollPane permite ataşarea unor this . addWindowListener (new WindowAdapter ()
bare de defilare (orizontal {
ă şsi/sau verticală) oricărei componente grafice. public void windowClosing ( WindowEvent e) {
Acest lucru este util System . exit (0);
pentru acele componente care nu au implementată }
funcţionalitatea de defi- });
lare automată, cum ar fi listele (obiecte din clasa setLayout (new GridLayout (3, 1));
List). setBackground ( Color . lightGray );
Listing 9.27: Folosirea clasei ScrollPane nume = new TextField ("", 30) ;
import java . awt .*; parola = new TextField ("", 10) ;
import java . awt. event .*; parola . setEchoChar (’*’);
class Fereastra extends Frame { Panel p1 = new Panel ();
private ScrollPane sp; p1. setLayout ( new FlowLayout ( FlowLayout .
private List list ; LEFT ));
public Fereastra ( String titlu ) { p1. add( new Label (" Nume :"));
super ( titlu ); p1. add( nume );
this . addWindowListener (new WindowAdapter () Panel p2 = new Panel ();
{ p2. setLayout ( new FlowLayout ( FlowLayout .
public void windowClosing ( WindowEvent e) { LEFT ));
System . exit (0); p2. add( new Label (" Parola :"));
} p2. add( parola );
}); acces = new Label (" Introduceti numele si
list = new List (7); parola !", Label .
list . add(" Luni "); CENTER );
list . add(" Marti "); add (p1);
list . add(" Miercuri "); add (p2);
list . add(" Joi"); add ( acces );
list . add(" Vineri "); setSize (350 , 100) ;
list . add(" Sambata "); nume . addTextListener ( this );
list . add(" Duminica "); parola . addTextListener ( this );
list . select (1); }
sp = new ScrollPane ( ScrollPane . // Metoda interfetei TextListener
SCROLLBARS_ALWAYS ); public void textValueChanged ( TextEvent e) {
sp. add( list ); if ( nume . getText (). length () == 0 ||
add (sp , BorderLayout . CENTER ); parola . getText (). length () == 0) {
setSize (200 , 200) ; acces . setText ("");
} return ;
} }
public class TestScrollPane { if ( nume . getText (). equals ( UID) &&
public static void main ( String args []) { parola . getText (). equals (PWD))
Fereastra f = new Fereastra (" ScrollPane "); acces . setText (" Acces permis !");
f. show (); else
} acces . setText (" Acces interzis !");

79
} PrintWriter out = new PrintWriter (
} new FileWriter ( nume . getText ()));
public class TestTextField { out . print ( continut );
public static void main ( String args []) { out . close ();
Fereastra f = new Fereastra (" TextField "); text . requestFocus ();
f. show (); } catch ( IOException ex) {
} ex. printStackTrace ();
} }
6.7.10 Clasa TextArea }
Un obiect de tip TextArea defineşte un control de }
editare a textului pe mai public class TestTextArea {
multe linii. Este util pentru editarea de texte, public static void main ( String args []) {
introducerea unor comentarii, Fereastra f = new Fereastra (" TextArea ");
etc . f. show ();
Listing 9.29: Folosirea clasei TextArea }
import java . awt .*; }
import java . awt. event .*; Desenarea
import java .io .*; 5.1 Conceptul de desenare
class Fereastra extends Frame implements Un program Java care are interfaţă grafică cu
TextListener , utilizatorul trebuie să deseneze
ActionListener { pe ecran toate componentele sale care au o
private TextArea text ; reprezentare vizuală. Această
private TextField nume ; desenare include componentele standard folosite în
private Button salvare ; aplicaţie precum şi cele
public Fereastra ( String titlu ) { definite de către programator. Desenarea
super ( titlu ); componentelor se face automat şi
this . addWindowListener (new WindowAdapter () este un proces care se execută în următoarele
{ situaţii:
public void windowClosing ( WindowEvent e) { • la afişarea pentru prima dată a unei componente;
System . exit (0); • la operaţii de minimizare, maximizare,
} redimensionare a suprafeţei de
}); afişare;
setBackground ( Color . lightGray ); • ca răspuns al unei solicitări explicite a
text = new TextArea ("", 30, 10, TextArea . programului.
SCROLLBARS_VERTICAL_ONLY ); Metodele care controlează procesul de desenare se
nume = new TextField ("", 12) ; găsescîn clasa Component
salvare = new Button (" Salveaza text "); şi sunt următoarele:
salvare . setEnabled ( false ); • void paint(Graphics g) - Desenează o componentă.
Panel fisier = new Panel (); Este o metodă
fisier . add( new Label (" Fisier :")); supradefinită de fiecare componentăîn parte pentru a
fisier . add( nume ); furniza reprezentarea
add (fisier , BorderLayout . NORTH ); sa grafică specifică. Metoda este apelată de fiecare
add (text , BorderLayout . CENTER ); dată când conţinutul
add ( salvare , BorderLayout . SOUTH ); componentei trebuie desenat sau redesenat şi nu va
setSize (300 , 200) ; fi apelată explicit.
text . addTextListener ( this ); • void update(Graphics g) - Actualizează starea
salvare . addActionListener ( this ); grafică a unei componente.
} Acţiunea acestei metode se realizează în trei paşi:
// Metoda interfetei TextListener 1. şterge componenta prin supradesenarea ei cu
public void textValueChanged ( TextEvent e) { culoarea fundalului;
if ( text . getText (). length () == 0 || 2. stabileşte culoarea (foreground) a componentei;
nume . getText (). length () == 0) 3. apelează metoda paint pentru a redesena
salvare . setEnabled ( false ); componenta.
else • void repaint() - Execută explicit un apel al metodei
salvare . setEnabled ( true ); update pentru
} a actualiza reprezentarea grafică a unei componente.
// Metoda interfetei ActionListener După cum se observă, singurul argument al
public void actionPerformed ( ActionEvent e) { metodelor paint şi update
String continut = text . getText (); este un obiect de tip Graphics. Acesta reprezintă
try { contextul grafic în care se

80
execută desenarea componentelor (vezi ”Contextul }
grafic de desenare - clasa Observaţi că la orice redimensionare a ferestrei
Graphics”). textul ”Aplicatie DEMO”
Atenţie va fi redesenat. Dacă desenarea acestui text ar fi fost
Toate desenele care trebuie să apară pe o suprafaţa facută oriunde în altă
de desenare se realizeaz parte decât în metoda paint, la prima redimensionare
ă în metoda paint a unei componente, în general a ferestrei acesta s-ar
apelată automat sau pierde.
explicit cu metoda repaint ori de câte ori Aşadar, desenarea în Java trebuie să se facă doar în
componenta respectivă trebuie cadrul metodelor
redesenată. Există posibilitatea de a desena şi în paint ale componentelor grafice.
afara metodei paint, însă 5.1.2 Suprafeţe de desenare - clasa Canvas
aceste desene se vor pierde la prima operaţie de In afara posibilităţii de a utiliza componente grafice
minimizare, maximizare, standard, Java oferă
redimensionare a suprafeţei de afişare. şi posibilitatea controlului la nivel de punct (pixel)
5.1.1 Metoda paint pe dispozitivul grafic,
După cum am spus, toate desenele care trebuie să respectiv desenarea a diferite forme grafice direct pe
apară pe o suprafaţă de suprafaţa unei componente.
afişare se realizează în metoda paint a unei Deşi este posibil, în general nu se desenează la nivel
componente. Metoda paint este de pixel direct
definită în superclasa Component însă nu are nici o pe suprafaţa ferestrelor sau a altor containere, ci vor
implementare şi, din acest fi folosite clase dedicate
motiv, orice obiect grafic care doreşte să se acestui scop.
deseneze trebuie să o suprade- In AWT a fost definit un tip special de componentă
finească pentru a-şi crea propria sa reprezentare. numită Canvas
Componentele standard (pânză de pictor), al cărei scop este de a fi extinsă
AWT au deja supradefinită această metodă deci nu pentru a implementa
trebuie să ne preocupe obiecte grafice cu o anumită înfăţişare. Aşadar,
desenarea lor, însă putem modifica reprezentarea lor Canvas este o clasă generică
grafică prin crearea din care se derivează subclase pentru crearea
unei subclase şi supradefinirea metodei paint, având suprafeţelor de desenare (planşe).
însă grijă să apelăm şi Planşele nu pot conţine alte componente grafice, ele
metoda superclasei care se ocupă cu desenarea fiind utilizate doar ca
efectivă a componentei. suprafeţe de desenat sau ca fundal pentru animaţie.
In exemplul de mai jos, redefinim metoda paint Desenarea pe o planşa
pentru un obiect de se face prin supradefinirea metodei paint a acesteia.
tip Frame, pentru a crea o clasă ce instanţiază Concret, o planşă este o suprafaţă dreptunghiulară
ferestre pentru o aplicaţie de culoare albă, pe
demonstrativă (în colţul stânga sus este afişat textul care se poate desena. Dimensiunile sale implicite
”Aplicatie DEMO”). sunt 0 şi, din acest motiv,
Listing 10.1: Supradefinirea metodei paint este recomandat ca o planşa să redefineasca metoda
import java . awt .*; getPreferredSize,
class Fereastra extends Frame { eventual şi getMinimumSize, getMaximumSize,
public Fereastra ( String titlu ) { deoarece acestea vor fi apelate
super ( titlu ); de către gestionarii de poziţionare.
setSize (200 , 100) ; Etapele uzuale care trebuie parcurse pentru crearea
} unui desen, sau mai
public void paint ( Graphics g) { bine zis a unei componente cu o anumită înfăţişare,
// Apelam metoda paint a clasei Frame sunt:
super . paint (g); • crearea unei planşe de desenare, adică o subclasă a
g. setFont (new Font (" Arial ", Font .BOLD , 11)); lui Canvas;
g. setColor ( Color .red ); • redefinirea metodei paint din clasa respectivă;
g. drawString (" Aplicatie DEMO ", 5, 35); • redefinirea metodelor getPreferredSize, eventual
} getMinimumSize,
} getMaximumSize;
public class TestPaint { • adăugarea planşei pe un container cu metoda add.
public static void main ( String args []) { • tratarea evenimentelor de tip FocusEvent,
Fereastra f = new Fereastra (" Test paint "); KeyEvent, MouseEvent,
f. show (); ComponentEvent, dacă este cazul.
}

81
Definirea generică a unei planşe are următorul super ( titlu );
format: setSize (200 , 200) ;
class Plansa extends Canvas implements ...Listener add (new Plansa () , BorderLayout . CENTER );
{ }
//Eventual, unul sau mai multi constructori }
public Plansa() { public class TestCanvas {
... public static void main ( String args []) {
} new Fereastra (" Test Canvas "). show ();
// Metode de desenare a componentei }
public void paint(Graphics g) { }
... 10.2 Contextul grafic de desenare
} Inainte ca utilizatorul să poată desena, el trebuie să
// Metodele folosite de gestionarii de pozitionare obţină un context grafic
public Dimension getPreferredSize() { de desenare pentru suprafaţa căreia îi aparţine
// Dimensiunea implicita a plansei regiunea pe care se va desena.
10.1. CONCEPTUL DE DESENARE 273 Un context grafic este, de fapt, un obiect prin
return ...; intermediul căruia putem
} controla procesul de desenare a unui obiect. In
public Dimension getMinimumSize() { general, desenarea se poate
return ... face:
} • pe o porţiune de ecran,
public Dimension getMaximumSize() { • la imprimantă sau
return ... • într-o zonă virtuală de memorie.
} Un context grafic este specificat prin intermediul
// Implementarea metodelor interfetelor de tip unui obiect de tip Graphics
Listener primit ca parametru în metodele paint şi update. In
... funcţie de dispozitivul
} fizic pe care se face afişarea (ecran, imprimantă,
Să definim o planşă pe care desenăm un pătrat şi plotter, etc) metodele
cercul său circumscris, de desenare au implementări interne diferite,
colorate diferite. La fiecare click de mouse, vom transparente utilizatorului.
interschimba cele două culori Clasa Graphics pune la dispoziţie metode pentru:
între ele. • primitive grafice: desenarea de figuri geometrice,
Listing 5.2: Folosirea clasei Canvas texte şi imagini
import java . awt .*; • stabilirea proprietăţilor contextului grafic, adică
import java . awt. event .*; stabilirea:
class Plansa extends Canvas { – culorii şi fontului curente cu care se face
Dimension dim = new Dimension (100 , 100) ; desenarea,
private Color color [] = { Color .red , Color . blue }; – originii coordonatelor suprafeţei de desenare,
private int index = 0; – suprafeţei în care sunt vizibile componentelor
public Plansa () { desenate,
this . addMouseListener (new MouseAdapter () { – modului de desenare.
public void mouseClicked ( MouseEvent e) { 5.2.1 Proprietăţile contextului grafic
index = 1 - index ; La orice tip de desenare parametrii legaţi de culoare,
repaint (); font, etc. vor fi specificaţi
} pentru contextul grafic în care se face desenarea şi
}); nu vor fi trimişi ca argumente
} metodelor respective de desenare. In continuare,
public void paint ( Graphics g) { enumerăm aceste
g. setColor ( color [ index ]); proprietăţi şi metodele asociate lor din clasa
g. drawRect (0, 0, dim .width , dim. height ); Graphics.
g. setColor ( color [1 - index ]); Proprietate Metode
g. fillOval (0, 0, dim .width , dim. height ); Culoarea de desenare Color getColor()
} void setColor(Color c)
public Dimension getPreferredSize () { Fontul de scriere a textelor Font getFont()
return dim ; void setFont(Font f)
} Originea coordonatelor translate(int x, int y)
} Zona de decupare Shape getClip()
class Fereastra extends Frame { (zona în care sunt vizibile desenele) void
public Fereastra ( String titlu ) { setClip(Shape s)

82
Modul de desenare void setXorMode(Color c) Clasele care oferă suport pentru lucrul cu fonturi
void setPaintMode(Color c) sunt Font şi FontMetrics,
5.2.2 Primitive grafice în continuare fiind prezentate modalităţile de lucru
Prin primitive grafice ne vom referiîn continuare la cu acestea.
metodele clasei Graphics, 10.3.1 Clasa Font
care permit desenarea de figuri geometrice şi texte. Un obiect de tip Font încapsulează informaţii despre
Desenarea textelor se face cu uzual cu metoda toţi parametrii unui
drawString care primeşte font, mai puţin despre metrica acestuia.
ca argumente un şir şi colţul din stânga-jos al Constructorul uzual al clasei este
textului. Textul va fi desenat cel care primeşte ca argument numele fontului,
cu fontul şi culoarea curente ale contextului grafic. dimensiunea şi stilul acestuia:
// Desenam la coordonatele x=10, y=20; Font(String name, int style, int size)
drawString("Hello", 10, 20); Stilul unui font este specificat prin intermediul
Desenarea figurilor geometrice se realizează cu constantelor: Font.PLAIN,
următoarele metode: Font.BOLD, Font.ITALIC iar dimensiunea printr-un
Figură geometrică Metode întreg, ca în exemplele
Linie drawLine de mai jos:
drawPolyline new Font("Dialog", Font.PLAIN, 12);
Dreptunghi simplu drawRect new Font("Arial", Font.ITALIC, 14);
fillRect new Font("Courier", Font.BOLD, 10);
clearRect Folosirea unui obiect de tip Font se realizează uzual
Dreptunghi cu chenar draw3DRect astfel:
”ridicat” sau ”adâncit” fill3DRect // Pentru componente etichetate
Dreptunghi cu colţuri drawRoundRect Label label = new Label("Un text");
retunjite fillRoundRect label.setFont(new Font("Dialog", Font.PLAIN, 12));
Poligon drawPolygon // In metoda paint(Graphics g)
fillPolygon g.setFont(new Font("Courier", Font.BOLD, 10));
Oval (Elipsă drawOval g.drawString("Alt text", 10, 20);
fillOval O platformă de lucru are instalate, la un moment
Arc circular sau drawArc dat, o serie întreagă de
eliptic fillArc fonturi care sunt disponibile pentru scrierea textelor.
Metodele care încep cu ”fill” vor desena figuri Lista acestor fonturi se
geometrice care au interiorul poate obţine astfel:
colorat, adică ”umplut” cu culoarea curentă a Font[] fonturi = GraphicsEnvironment.
contextului de desenare, getLocalGraphicsEnvironment().getAllFonts();
în timp ce metodele care încep cu ”draw” vor Exemplul urmator afişează lista tuturor fonturilor
desena doar conturul figurii disponibile pe platforma
respective. curentă de lucru. Textul fiecărui nume de font va fi
10.3 Folosirea fonturilor scris cu fontul său
După cum vazut, pentru a scrie un text pe ecran corespunzător.
avem două posibilităţi. Listing 5.3: Lucrul cu fonturi
Prima dintre acestea este să folosim o componentă import java . awt .*;
orientată-text, cum ar class Fonturi extends Canvas {
fi Label, iar a doua să apelăm la metodele clasei private Font [] fonturi ;
Graphics de desenare Dimension canvasSize = new Dimension (400 ,
a textelor, cum ar fi drawString. Indiferent de 400) ;
modalitatea aleasă, putem public Fonturi () {
specifica prin intermediul fonturilor cum să arate fonturi = GraphicsEnvironment .
textul respectiv, acest lucru getLocalGraphicsEnvironment (). getAllFonts ();
realizându-se prin metoda setFont fie din clasa canvasSize . height = (1 + fonturi . length ) * 20;
Component, fie din Graphics. }
Cei mai importanţi parametri ce caracterizează un public void paint ( Graphics g) {
font sunt: String nume ;
• Numele fontului: Helvetica Bold, Arial Bold Italic, for (int i=0; i < fonturi . length ; i ++) {
etc. nume = fonturi [i]. getFontName ();
• Familia din care face parte fontul: Helvetica, Arial, g. setFont (new Font (nume , Font .PLAIN , 14));
etc. g. drawString (i + ". " + nume , 20, (i + 1) * 20);
• Dimensiunea fontului: înălţimea sa; }
• Stilul fontului: îngroşat (bold), înclinat (italic); }
• Metrica fontului. public Dimension getPreferredSize () {

83
return canvasSize ; • Distanţa între linii (”leading”): distanţa optimă
} între două linii de text
} scrise cu acelaşi font.
class Fereastra extends Frame { • Inălţimea: distanţa dintre liniile de bază
public Fereastra ( String titlu ) { (leading+ascent+descent);
super ( titlu ); Figura de mai jos prezintă o imagine reprezentativă
ScrollPane sp = new ScrollPane (); asupra metricii unui
sp. setSize (400 , 400) ; font:
sp. add( new Fonturi ()); Reamintim că la metoda drawString(String s, int x,
add (sp , BorderLayout . CENTER ); int y) argumentele
pack (); x şi y repreznită colţul din stânga-jos al textului. Ca
} să fim mai
} precişi, y reprezintă poziţia liniei de bază a textului
public class TestAllFonts { care va fi scris.
public static void main ( String args []) { Un context grafic pune la dispoziţie o metodă
new Fereastra ("All fonts "). show (); specială getFontMetrics
} de creare a unui obiect de tip FontMetrics, pornind
} de la fontul curent al
5.3.2 Clasa FontMetrics contextului grafic:
La afişarea unui şir cu metoda drawString trebuie să public void paint(Graphics g) {
specificăm poziţia la Font f = new Font("Arial", Font.BOLD, 11);
care să apară textul respectiv pe ecran. In momentul FontMetrics fm = g.getFontMetrics();
în care avem de afişat }
mai multe şiruri consecutiv, sau unele sub altele, Cele mai folosite metode ale clasei FontMetrics
trebuie să calculăm poziţiile sunt:
lor de afişare în funcţie de lungimea şi înalţimea în • getHeight - determină înălţimea unei linii pe care
pixeli a celorlalte texte. vor fi scrise caractere
Pentru aceasta este folosită clasa FontMetrics. Un ale unui font;
obiect din această clasă • stringWidth - determină lăţimea totală în pixeli a
se construieşte pornind de la un obiect de tip Font şi unui şir de caractere
pune la dispoziţie specificat;
informaţii despre dimensiunile în pixeli pe care le au • charWidth - determină lăţimea unui anumit
caracterele fontului caracter din font.
respectiv într-un anumit context de desenare. In exemplul următor sunt afişate pe ecran zilele
Aşadar, un obiect de tip FontMetrics încapsulează săptămânii şi lunile anului:
informaţii despre Listing 5.4: Folosirea clasei FontMetrics
metrica unui font, cu alte cuvinte despre import java . awt .*;
dimensiunile în pixeli ale caracterelor class Texte extends Canvas {
sale. Utilitatea principală a acestei clase constă în Dimension canvasSize = new Dimension (800 ,
faptul că permite 100) ;
poziţionarea precisă a textelor pe o suprafaţă de private String [] zile = {
desenare, indiferent de fontul " Luni ", " Marti ", " Miercuri ", " Joi",
folosit de acestea. " Vineri ", " Sambata ", " Duminica "};
Metrica unui font constă în următoarele atribute pe private String [] luni = {
care le au caracterele " Ianuarie ", " Februarie ", " Martie ", " Aprilie ",
sale: "Mai", " Iunie ", " Iulie ", " August ", " Septembrie
• Linia de bază: este linia după care sunt aliniate ",
caracterele unui font; " Octombrie ", " Noiembrie ", " Decembrie "};
• Linia de ascendenţă: linia superioara pe care nu o public void paint ( Graphics g) {
depaseste nici un FontMetrics fm;
caracter din font int x,y;
• Linia de descendenţă: linia inferioară sub care nu String etZile = " Zilele saptamanii :",
coboară nici un caracter etLuni = " Lunile anului :", text ;
din font; // Alegem un font si aflam metrica sa
• Ascendentul: distanţa între linia de bază şi linia de g. setFont (new Font (" Arial ", Font .BOLD , 20));
ascendenţă; fm = g. getFontMetrics ();
• Descendentul: distanţa între linia de bază şi linia x = 0;
de descendenţă; y = fm. getHeight ();
• Lăţimea: lăţimea unui anumit caracter din font; g. drawString (etZile , x, y);
x += fm. stringWidth ( etZile );

84
for (int i=0; i < zile . length ; i ++) { Să vedem mai întâi care sunt constantele definite în
text = zile [i]; aceste clase:
if (i < zile . length - 1) Color SystemColor
text += ", "; black activeCaption
g. drawString (text , x, y); blue activeCaptionBorder
x += fm. stringWidth ( text ); cyan activeCaptionText
} darkGray control
// Schimbam fontul gray controlHighlight
g. setFont (new Font (" Dialog ", Font .PLAIN , green controlShadow
14)); lightGray contolText
fm = g. getFontMetrics (); magenta desktop
x = 0; orange menu
y += fm. getHeight (); pink text
g. drawString (etLuni , x, y); red textHighlight
x += fm. stringWidth ( etLuni ); white window
for (int i=0; i < luni . length ; i ++) { yellow ...
text = luni [i]; Observaţi că în clasa Color sunt definite culori
if (i < luni . length - 1) uzuale din paleta standard
text += ", "; de culori, în timp ce în clasa SystemColor sunt
g. drawString (text , x, y); definite culorile componentelor
x += fm. stringWidth ( text ); standard (ferestre, texte, meniuri, etc) ale platformei
} curente de lucru.
} Folosirea acestor constante se face ca în exemplele
public Dimension getPreferredSize () { de mai jos:
return canvasSize ; Color rosu = Color.red;
} Color galben = Color.yellow;
} Color fundal = SystemColor.desktop;
class Fereastra extends Frame { Dacă nici una din aceste culori predefinite nu
public Fereastra ( String titlu ) { corespunde preferinţelor noastre,
super ( titlu ); atunci putem crea noi culori prin intermediul
add (new Texte () , BorderLayout . CENTER ); constructorilor clasei Color:
pack (); Color(float red, flot green, float blue)
} Color(flot red, float green, float blue, float alpha)
} Color(int red, int green, int blue)
public class TestFontMetrics { Color(int red, int green, int blue, int alpha)
public static void main ( String args []) { Color(int rgb)
Fereastra f = new Fereastra (" FontMetrics "); unde red, green, blue, alpha sunt valorile pentru
f. show (); roşu, verde, albastru şi
} transparenţă iar parametrul ”rgb” de la ultimul
} constructor reprezintă un
5.4 Folosirea culorilor întreg format din: biţii 16-23 roşu, 8-15 verde, 0-7
Orice culoare este formată prin combinaţia culorilor albastru.
standard roşu (red), Valorile argumentelor variază între 0 - 255 pentru
verde (green) şi albastru (blue), la care se adaugă un tipul int, respectiv
anumit grad de transparenţă 0.0 - 1.0 pentru tipul float. Valoarea 255 (sau 1.0)
(alpha). Fiecare din aceşti patru parametri poate pentru transparenţă
varia într-un interval specifică faptul că respectiva culoare este complet
cuprins fie între 0 şi 255 (dacă dorim să specificăm opacă, iar valoarea 0 (sau
valorile prin numere 0.0) specifică transparenţă totală. Implicit, culorile
întregi), fie între 0.0 şi 1.0 (dacă dorim să sunt complet opace.
specificăm valorile prin numere // Exemple de folosire a constructorilor:
reale). Color alb = new Color(255, 255, 255);
O culoare este reprezentată printr-o instanţă a clasei Color negru = new Color(0, 0, 0);
Color sau a subclasei Color rosu = new Color(255, 0, 0);
sale SystemColor. Pentru a crea o culoare avem Color rosuTransparent = new Color(255, 0, 0, 128);
două posibilităţi: Metodele cele mai folosite ale clasei Color sunt:
• Să folosim una din constantele definite în cele brighter Creează o noua versiune a culorii curente
două clase; darker mai deschisă, respectiv mai închisă
• Să folosim unul din constructorii clasei Color. getRed
getGreen Determină parametrii din care

85
getBlue este alcatuită culoarea aValue = new Scrollbar ( Scrollbar .
getAlpha HORIZONTAL , 0, 1, 0,
getRGB Determină valoarea ce reprezintă culoarea 256) ;
respectivă (biţii 16-23 roşu, 8-15 verde, 0-7 aValue . setValue (255) ;
albastru) aValue . setBackground ( Color . lightGray );
Să considerăm o aplicaţie cu ajutorul căreia putem rgbValues .add ( rValue );
vizualiza dinamic culorile rgbValues .add ( gValue );
obţinute prin diferite combinaţii ale parametrilor ce rgbValues .add ( bValue );
formează o culoare. rgbValues .add ( aValue );
Aplicaţia va arăta astfel: rgbValues . setSize (200 , 100) ;
Listing 5.5: Folosirea clasei Color add ( rgbValues , BorderLayout . CENTER );
import java . awt .*; culoare = new Culoare ();
import java . awt. event .*; add ( culoare , BorderLayout . NORTH );
class Culoare extends Canvas { pack ();
public Color color = new Color (0, 0, 0, 255) ; rValue . addAdjustmentListener ( this );
Dimension canvasSize = new Dimension (150 , gValue . addAdjustmentListener ( this );
50) ; bValue . addAdjustmentListener ( this );
public void paint ( Graphics g) { aValue . addAdjustmentListener ( this );
g. setColor ( Color . black ); }
g. setFont (new Font (" Arial ", Font .BOLD , 12)); public void adjustmentValueChanged
String text = ""; ( AdjustmentEvent e) {
text += " R=" + color . getRed (); int r = rValue . getValue ();
text += " G=" + color . getGreen (); int g = gValue . getValue ();
text += " B=" + color . getBlue (); int b = bValue . getValue ();
text += " A=" + color . getAlpha (); int a = aValue . getValue ();
g. drawString (text , 0, 30); Color c = new Color (r, g, b, a);
g. setColor ( color ); culoare . color = c;
g. fillRect (0, 0, canvasSize .width , canvasSize . culoare . repaint ();
height ); }
} }
public Dimension getPreferredSize () { public class TestColor {
return canvasSize ; public static void main ( String args []) {
} Fereastra f = new Fereastra (" Color ");
} f. show ();
class Fereastra extends Frame implements }
AdjustmentListener { }
private Scrollbar rValue , gValue , bValue , aValue ; 10.5 Folosirea imaginilor
private Culoare culoare ; In AWT este posibilă folosirea imaginilor create
public Fereastra ( String titlu ) { extern în format gif sau
super ( titlu ); jpeg. Orice imagine va fi reprezentată ca o instanţă a
this . addWindowListener (new WindowAdapter () clasei Image. Aceasta
{ nu este o clasă de componente (nu extinde
public void windowClosing ( WindowEvent e) { Component) ci implementează
System . exit (0); obiecte care pot fi desenate pe suprafaţa unor
} componente cu metode specifice
}); unui context grafic pentru componenta respectiva
Panel rgbValues = new Panel (); (similar modului cum se
rgbValues . setLayout (new GridLayout (4, 1)); desenează o linie sau un cerc).
rValue = new Scrollbar ( Scrollbar . HORIZONTAL 5.5.1 Afişarea imaginilor
, 0, 1, 0, Afişarea unei imagini presupune realizarea
256) ; următoarilor doi paşi:
rValue . setBackground ( Color .red); 1. Crearea unui obiect de tip Image;
gValue = new Scrollbar ( Scrollbar . 2. Afişarea propriu-zisă într-un context grafic;
HORIZONTAL , 0, 1, 0, Crearea unui obiect de tip Image se face folosind o
256) ; imagine dintr-un fişier
gValue . setBackground ( Color . green ); fie aflat pe maşina pe care se lucrează, fie aflat la o
bValue = new Scrollbar ( Scrollbar . anumită adresă Web
HORIZONTAL , 0, 1, 0, (URL). Metodele pentru încărcarea unei imagini
256) ; dintr-un fişier se găsesc
bValue . setBackground ( Color . blue );

86
în clasele Applet şi Toolkit, având însă aceeaşi g.drawImage(img, 0, 0, this);
denumire getImage şi g.drawImage(img, 0, 200, 100, 100, this);
următoarele formate: g.drawImage(img, 200, 0, 200, 400, Color.yellow,
Applet Toolkit this);
getImage(URL url) getImage(URL url)
getImage(URL url, String fisier) getImage(String Metoda drawImage returnează true dacă imaginea a
fisier) fost afişatăînîntregime
Pentru a obţine un obiect de tip Toolkit se va folosi şi false în caz contrar, cu alte cuvinte metoda nu
metoda getDefaultToolkit, aşteptă ca o imagine să
ca în exemplul de mai jos: fie complet afişată ci se termină imediat ce procesul
Toolkit toolkit = Toolkit.getDefaultToolkit(); de afişare a început. In
Image image1 = toolkit.getImage("poza.gif"); secţiunea următoare vom detalia acest aspect.
Image image2 = toolkit.getImage( 5.5.2 Monitorizarea încărcării imaginilor
new URL("http://www.infoiasi.ro/~acf/poza.gif")); In cazul în care se afişează o imagine care se găseşte
Metoda getImage nu verifică dacă fişierul sau pe Internet sau imaginea
adresa specificata reprezintă afişata este de dimensiuni mari se va observa că
o imagine validă şi nici nuîncarcă efectiv aceasta nu apare complet de
imagineaîn memorie, aceste operaţiuni la început ci este desenată treptat, fără intervenţia
fiind făcute abia în momentul în care se va realiza programatorului. Acest
afişarea imaginii pentru lucru se întâmplă deoarece metoda drawImage nu
prima dată. Metoda nu face decât să creeze un face decât să declanşeze
obiect de tip Image care face procesul de încărcare şi desenare a imaginii, după
referinţă la o anumită imagine externă. care redă imediat controlul
Afişarea unei imagini într-un context grafic se apelantului, lucru deosebit de util întrucât procesul
realizează prin intermediul de încărcare a
metodei drawImage din clasa Graphics şi, în unei imagini poate dura mult şi nu este de dorit ca în
general, va fi facută în metoda acest interval de timp
paint a unei componente. Cele mai uzuale formate (până la încărcarea completă a imaginii) aplicaţia să
ale metodei sunt: fie blocată. Ca urmare,
boolean drawImage(Image img, int x, int y, la apelul metodei drawImage va fi desenată numai
ImageObserver observer) porţiunea de imagine care
boolean drawImage(Image img, int x, int y, Color este disponibilă la momentul iniţial şi care poate fi
bgcolor, incompletă. De aceea
ImageObserver observer) trebuie să existe un mecanism prin care componenta
boolean drawImage(Image img, int x, int y, int să fie redesenată automat
width, int height, în momentul în care au mai sosit informaţii legate
ImageObserver observer) de imagine, până la
boolean drawImage(Image img, int x, int y, int afişarea sa completă. Acest mecanism este realizat
width, int height, prin intermediul interfeţei
Color bgcolor, ImageObserver observer) ImageObserver, implementată de clasa Component
unde: şi deci de toate componentele.
• img este obiectul ce reprezintă imaginea; Această interfaţă descrie obiecte care au început să
• x, y sunt coordonatele stânga-sus la care va fi utilizeze o imagine
afişată imaginea, relative incompletă şi care trebuie anunţate de noile date
la spaţiul de coordonate al contextului grafic; obţinute în legatură cu
• observer este un obiect care ”observă” încărcarea imaginea respectivă.
imaginii şi va fi informat Interfaţa ImageObserver are o singură metodă
pe măsura derulării acesteia; numită imageUpdate,
• width, heigth reprezintă înalţimea şi lăţimea la care ce va fi apelată periodic de firul de execuţie (creat
trebuie scalată automat) care se ocupă
imaginea (dacă lipsesc, imaginea va fi afişată la cu încărcarea imaginii. Formatul acestei metode
dimensiunile ei reale); este:
• bgColor reprezintă culoarea cu care vor fi coloraţi boolean imageUpdate (Image img, int flags,
pixelii transparenţi int x, int y, int w, int h )
ai imaginii (poate să lipsească). Implementarea implicită constă dintr-un apel la
In exemplul următor afişam aceeaşi imagine de trei metoda repaint pentru
ori, folosind forme dreptunghiul specificat la apel şi care reprezintă
diferite ale metodei drawImage: zona din imagine pentru care
Image img = se cunosc noi informaţii. Intregul flags furnizează
Toolkit.getDefaultToolkit().getImage("taz.gif"); informaţii despre starea

87
transferului. Aceste informaţii pot fi aflate prin este următoarea:
intermediul constantelor // Supradefinim update pentru a elimina stergerea
definite de interfaţă: desenului
ABORT Incărcarea imaginii a fost întreruptă, public void update(Graphics g) {
înainte de completarea sa paint(g);
ALLBITS Imaginea a fost încarcată complet }
ERROR A apărut o eroare în timpul public void paint(Graphics g) {
încărcării imaginii // Desenam in memorie pe un obiect de tip Image
FRAMEBITS Toţi biţii cadrului curent sunt // w si h sunt dimensiunile desenului
disponibili Image img = createImage(w, h);
HEIGHT Inălţimea imaginii este disponibilă Graphics gmem = img.getGraphics();
PROPERTIES Proprietăţile imaginii sunt /* Realizam desenul folosind gmem
disponibile gmem.setColor(...);
SOMEBITS Au fost recepţionaţi noi pixeli ai gmem.fillOval(...);
imaginii ...
WIDTH Lăţimea imaginii este disponibilă */
Prezenţa în parametrul flags a unui bit de valoare 1 // Transferam desenul din memorie pe ecran
pe poziţia reprezentata // desenand de fapt imaginea creata
de o constantă înseamnă că respectiva condiţie este g.drawImage(img, 0, 0, this);
îndeplinită. gmem.dispose();
// Imaginea este completa }
(flags & ALLBITS) != 0 }
// Eroare sau transferul imaginii a fost intrerupt 5.5.4 Salvarea desenelor în format JPEG
(flags & ERROR | ABORT ) != 0 Pachetul com.sun.image.codec.jpeg din distribuţia
Metoda imageUpdate poate fi redefintă de o standard Java oferă
componentă pentru a personaliza suport pentru salvarea unei imagini aflate în
procesul de afişare al imaginii. Aceasta va fi apelată memorie într-un fişier în for-
apelată asincron mat JPEG. O clasă responsabilă cu realizarea acestei
de fiecare dată când sunt disponibili noi pixeli. operaţiuni ar putea fi
public boolean imageUpdate(Image img, int flags, definită astfel:
int x, int y, int w, int h) { import com.sun.image.codec.jpeg.*;
// Desenam imaginea numai daca toti bitii sunt import java.awt.image.BufferedImage;
disponibili import java.awt.*;
if (( flags & ALLBITS) != 0) import java.io.*;
repaint(); class JPEGWriter {
// Daca sunt toti bitii nu mai sunt necesare noi static float quality = 0.9f; //intre 0 si 1
update-uri public static void write(BufferedImage img, String
return ( (flags & (ALLBITS | ABORT)) == 0); filename) {
} try {
De asemenea, se observă că metodele clasei Image FileOutputStream out = new
pentru determinarea FileOutputStream(filename);
dimensiunilor unei imagini au ca argument un JPEGImageEncoder encoder =
obiect de tip ImageObserver. JPEGCodec.createJPEGEncoder(out);
int getHeight(ImageObserver observer) JPEGEncodeParam jep =
int getWidth(ImageObserver observer) encoder.getDefaultJPEGEncodeParam(img);
Dacă desenarea se face folosind clasa Canvas, jep.setQuality(quality, false);
atunci argumentul observer // Folosim setarile de codare jpeg implicite
al metodelor referitoare la imagini va fi this. encoder.setJPEGEncodeParam(jep);
5.5.3 Mecanismul de ”double-bu_ering” encoder.encode(img);
Tehnica de double-bu_ering implică realizarea unui out.close();
desen în memorie şi apoi } catch( Exception e ) {
transferul său pe ecran, pentru a elimina efectul e.printStackTrace();
neplăcut de ”clipire” (”flickering”) }
rezultat atunci când sunt efectuate redesenări }
repetate la intervale }
mici de timp. O situaţie frecventă în care se apelează 5.5.5 Crearea imaginilor în memorie
la double-bu_ering este In cazul în care dorim să folosim o anumită imagine
crearea de animaţii. creată direct din program
Secvenţa generală de implementare a mecanismului şi nu încarcată dintr-un fişier vom folosi clasa
de double-bu_ering MemoryImageSource,

88
aflata în pachetul java.awt.image. Pentru aceasta va de metoda paint şi care va specifica şi modalitatea
trebui să definim un de reprezentare a sa la
vector de numere întregi în care vom scrie valorile imprimantă.
întregi (RGB) ale culorilor Un obiect care va fi tipărit trebuie să implementeze
pixelilor ce definesc imaginea noastră. Dimensiunea interfaţa Printable,
vectorului va care conţine o singură metodă print, responsabilă cu
fi înălţimea înmulţită cu lăţimea în pixeli a imaginii. descrierea modalităţii
Constructorul clasei de tipărire a obiectului. In cazul când imaginea de
MemoryImageSource este: pe ecran coincide cu
MemoryImageSource(int w, int h, int[] pixeli, int imaginea de la imprimantă, metodele paint şi print
off, int scan) pot specifica aceeaşi
unde: secvenţă de cod. In general, metoda print are
• w, h reprezintă dimensiunile imaginii (lăţimea şi următorul format:
înălţimea); public int print(Graphics g, PageFormat pf, int
• pixeli[] este vectorul cu culorile imaginii; pageIndex)
• off, scan reprezintă modalitatea de construire a throws PrinterException {
matricii imaginii pornind // Descrirea imaginii obiectului ce va fi afisata la
de la vectorul cu pixeli, normal aceste valori sunt o_ imprimanta
= 0, scan = w // Poate fi un apel la metoda paint: paint(g)
In exemplul urmator vom crea o imagine cu pixeli if (ceva nu este in regula}) {
de culori aleatorii şi o return Printable.NO_SUCH_PAGE;
vom afişa pe ecran: }
int w = 100; return Printable.PAGE_EXISTS;
int h = 100; }
int[] pix = new int[w * h]; Paşii care trebuie efectuaţi pentru tipărirea unui
int index = 0; obiect sunt:
for (int y = 0; y < h; y++) { 1. Crearea unei sesiuni de tipărire:
for (int x = 0; x < w; x++) { PrinterJob.getPrinterJob
int red = (int) (Math.random() * 255); 2. Specificarea obiectului care va fi tipărit:
int green = (int) (Math.random() * 255); setPrintable; acesta trebuie
int blue = (int) (Math.random() * 255); să implementeze interfaţa Printable;
pix[index++] = new Color(red, green, 3. Opţional, iniţierea unui dialog cu utilizatorul
blue).getRGB(); pentru precizarea unor
} parametri legaţi de tipărire: printDialog;
img = createImage(new MemoryImageSource(w, h, 4. Tipărirea efectivă: print.
pix, 0, w)); In exemplul următor vom defini un obiect care are
g.drawImage(img, 0, 0, this); // g este un context aceeaşi reprezentare
grafic pe ecran cât şi la imprimantă (un cerc circumscris
5.0.6 Tipărirea unui pătrat, însotite de
Tipărirea în Java este tratată în aceeaşi manieră ca şi un text) şi vom tipări obiectul respectiv.
desenarea, singurul Listing 5.6: Tipărirea unei componente
lucru diferit fiind contextul grafic în care se execută import java .io .*;
operaţiile. Pachetul import java . awt .*;
care oferă suport pentru tipărire este java.awt.print, import java . awt. event .*;
iar clasa principală import java . awt. print .*;
care controlează procesul de tipărire este PrinterJob. class Plansa extends Canvas implements Printable {
O aplicaţie va apela Dimension d = new Dimension (400 , 400) ;
metode ale acestei clase pentru: public Dimension getPreferredSize () {
• Crearea unei sesiuni de tipărire (job); return d;
• Invocarea dialogului cu utilizatorul pentru }
specificarea unor parametri public void paint ( Graphics g) {
legaţi de tipărire; g. drawRect (200 , 200 , 100 , 100) ;
• Tipărirea efectivă. g. drawOval (200 , 200 , 100 , 100) ;
Orice componentă care poate fi afişată pe ecran g. drawString (" Hello ", 200 , 200) ;
poate fi şi tipărită. In general, }
orice informaţii care trebuie atât afişate cât şi public int print ( Graphics g, PageFormat pf , int pi)
tipărite, vor fi încapsulate throws PrinterException {
într-un obiect grafic - componentă, care are o if (pi >= 1)
reprezentare vizuală descrisă return Printable . NO_SUCH_PAGE ;
paint (g);

89
g. drawString (" Numai la imprimanta ", 200 , 300) ; }
return Printable . PAGE_EXISTS ; public class TestPrint {
} public static void main ( String args []) throws
} Exception {
class Fereastra extends Frame implements Fereastra f = new Fereastra (" Test Print ");
ActionListener { f. show ();
private Plansa plansa = new Plansa (); }
private Button print = new Button (" Print "); }
public Fereastra ( String titlu ) { Tiparirea textelor
super ( titlu ); O altă variantă pentru tipărirea de texte este
addWindowListener ( new WindowAdapter () { deschiderea unui flux către
public void windowClosing ( WindowEvent e) { dispozitivul special reprezentat de imprimantă şi
System . exit (0); scrierea informaţiilor, linie
} cu linie, pe acest flux. In sistemul de operare
}); Windows, imprimanta poate
add (plansa , BorderLayout . CENTER ); fi referită prin ”lpt1”, iar în Unix prin ”/dev/lp”.
Panel south = new Panel (); Observaţi că această
south . setLayout (new FlowLayout ( FlowLayout . abordare nu este portabilă, deoarece necesită tratare
CENTER )); specială în funcţie de
south .add( print ); sistemul de operare folosit.
add (south , BorderLayout . SOUTH ); Listing 5.7: Tipărirea textelor
print . addActionListener ( this ); import java .io .*;
pack (); import java . awt .*;
} class TestPrintText {
public void actionPerformed ( ActionEvent e) { public static void main ( String args []) throws
// 1. Crearea unei sesiuni de tiparire Exception {
PrinterJob printJob = PrinterJob . getPrinterJob (); // pentru Windows
// 2. Stabilirea obiectului ce va fi tiparit PrintWriter imp = new PrintWriter ( new FileWriter
printJob . setPrintable ( plansa ); (" lpt1 "))
// 3. Initierea dialogului cu utilizatorul ;
if ( printJob . printDialog ()) { // pentru UNIX
try { // PrintWriter imp = new PrintWriter (new
// 4. Tiparirea efectiva FileWriter ("/ dev/
printJob . print (); lp "));
} catch ( PrinterException ex) { imp . println (" Test imprimanta ");
System . out. println (" Exceptie la tiparire !"); imp . println (" ABCDE ");
ex. printStackTrace (); imp . close ();
} }
} }
}
------------------------------------------------------------------------------------------------------------------------------------------
realizarea unui segment de dreapta

/**************************************************************
* You can modify the template of this file in the
* directory ..\JCreator\Templates\Template_2\Project_Name.java
*
* You can also create your own project template by making a new
* folder in the directory ..\JCreator\Template\. Use the other
* templates as examples.
*
*/

90
import java.awt.*;
import java.applet.*;

public class X1 extends Applet


{
public void init()
{

public void paint(Graphics g)


{

g.drawLine(25,25,75,75);

}
Realizarea unei linii poligonale

/**************************************************************
* You can modify the template of this file in the
* directory ..\JCreator\Templates\Template_2\Project_Name.java
*
* You can also create your own project template by making a new
* folder in the directory ..\JCreator\Template\. Use the other
* templates as examples.
*
*/

import java.awt.*;
import java.applet.*;

public class X1 extends Applet


{
public void init()
{

public void paint(Graphics g)


{

91
int exes[] = { 39,94,97,142,53,58,26 };
int whys[] = { 33,74,36,70,108,80,106 };
int pts = exes.length;

g.drawPolygon(exes,whys,pts);

}
realizarea unei elipse

/**************************************************************
* You can modify the template of this file in the
* directory ..\JCreator\Templates\Template_2\Project_Name.java
*
* You can also create your own project template by making a new
* folder in the directory ..\JCreator\Template\. Use the other
* templates as examples.
*
*/

import java.awt.*;
import java.applet.*;

public class X1 extends Applet


{
public void init()
{

public void paint(Graphics g)


{

g.drawOval(20,20,60,60);
g.fillOval(120,20,100,60);

}
arc de cerc

/**************************************************************
* You can modify the template of this file in the
* directory ..\JCreator\Templates\Template_2\Project_Name.java
*
* You can also create your own project template by making a new

92
* folder in the directory ..\JCreator\Template\. Use the other
* templates as examples.
*

*/

import java.awt.*;
import java.applet.*;

public class X1 extends Applet


{
public void init()
{

public void paint(Graphics g)


{

g.drawArc(20,20,60,60,90,180);
g.fillArc(120,20,60,60,90,180);

}
arc cu precizarea capetelor

/**************************************************************
* You can modify the template of this file in the
* directory ..\JCreator\Templates\Template_2\Project_Name.java
*
* You can also create your own project template by making a new
* folder in the directory ..\JCreator\Template\. Use the other

93
* templates as examples.
*
*/

import java.awt.*;
import java.applet.*;

public class X1 extends Applet


{
public void init()
{

public void paint(Graphics g)


{

g.drawArc(10,20,150,50,25,-130);
g.fillArc(10,80,150,50,25,-130);

}
sa se realizeze un grafic ca mai jos

/**************************************************************
* You can modify the template of this file in the
* directory ..\JCreator\Templates\Template_2\Project_Name.java
*
* You can also create your own project template by making a new
* folder in the directory ..\JCreator\Template\. Use the other
* templates as examples.
*
*/

import java.awt.*;
import java.applet.*;

public class X1 extends Applet


{
public void init()
{

94
public void paint(Graphics g)
{

// the lamp platform


g.fillRect(0,250,290,290);

// the base of the lamp


g.drawLine(125,250,125,160);
g.drawLine(175,250,175,160);

// the lamp shade, top and bottom edges


g.drawArc(85,157,130,50,-65,312);
g.drawArc(85,87,130,50,62,58);

// lamp shade, sides


g.drawLine(85,177,119,89);
g.drawLine(215,177,181,89);

// dots on the shade


g.fillArc(78,120,40,40,63,-174);
g.fillOval(120,96,40,40);
g.fillArc(173,100,40,40,110,180);
}

}
sa se stabileasca un tip de font sis a se scrie cu el

/**************************************************************
* You can modify the template of this file in the
* directory ..\JCreator\Templates\Template_2\Project_Name.java
*
* You can also create your own project template by making a new
* folder in the directory ..\JCreator\Template\. Use the other
* templates as examples.
*
*/

import java.awt.*;
import java.applet.*;

public class X1 extends Applet


{
public void init()
{

95
}

public void paint(Graphics g)


{

Font f = new Font("TimesRoman", Font.PLAIN, 72);


g.setFont(f);
g.drawString("This is a big font.", 10, 100);

}
sa se scrie cu diferite tipuri de fonturi

/**************************************************************
* You can modify the template of this file in the
* directory ..\JCreator\Templates\Template_2\Project_Name.java
*
* You can also create your own project template by making a new
* folder in the directory ..\JCreator\Template\. Use the other
* templates as examples.
*
*/

import java.awt.*;
import java.applet.*;

public class X1 extends Applet


{
public void init()
{

public void paint(Graphics g)


{

Font f = new Font("TimesRoman", Font.PLAIN, 18);


Font fb = new Font("TimesRoman", Font.BOLD, 18);
Font fi = new Font("TimesRoman", Font.ITALIC, 18);
Font fbi = new Font("TimesRoman", Font.BOLD + Font.ITALIC, 18);

g.setFont(f);
g.drawString("This is a plain font", 10, 25);
g.setFont(fb);
g.drawString("This is a bold font", 10, 50);
g.setFont(fi);

96
g.drawString("This is an italic font", 10, 75);
g.setFont(fbi);
g.drawString("This is a bold italic font", 10, 100);

}
sa se stabileasca un spatiu in care sa se incadreze un text

/**************************************************************
* You can modify the template of this file in the
* directory ..\JCreator\Templates\Template_2\Project_Name.java
*
* You can also create your own project template by making a new
* folder in the directory ..\JCreator\Template\. Use the other
* templates as examples.
*
*/

import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;

public class X1 extends Applet


{
public void init()
{

public void paint(Graphics g)


{

Font f = new Font("TimesRoman", Font.PLAIN, 36);


FontMetrics fm = getFontMetrics(f);
g.setFont(f);

String s = "This is how the world ends.";


int xstart = (size().width - fm.stringWidth(s)) / 2;
int ystart = size().height / 2;

g.drawString(s, xstart, ystart);

97
}
AFISAREA TEXTULUI SE FACE

import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;
import java.awt.Event;
import java.awt.Point;
import java.awt.*;
import java.net.*;
import java.net.MalformedURLException;
import java.awt.*;
import java.io.DataInputStream;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.net.MalformedURLException;

public class X1 extends Applet

TextField textField;

public void init()

textField = new TextField(20);

add(textField);

public void paint(Graphics g)

98
{

String s = textField.getText();

g.drawString(s, 40, 50);

public boolean action(Event event, Object arg)

repaint();

return true;

sa se deseneze niste dreptunghiuri cu diferite caracteristici de culoare

import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;

public class X1 extends Applet


{
public void init()
{

public void paint(Graphics g)


{

int rval, gval, bval;

99
for (int j = 30; j < (size().height -25); j += 30)
for (int i = 5; i < (size().width -25); i += 30) {
rval = (int)Math.floor(Math.random() * 256);
gval = (int)Math.floor(Math.random() * 256);
bval = (int)Math.floor(Math.random() * 256);

g.setColor(new Color(rval,gval,bval));
g.fillRect(i, j, 25, 25);
g.setColor(Color.black);
g.drawRect(i-1, j-1, 25, 25);
}

}
}

sa se preia un text de la tastaura

import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;
import java.awt.Event;
import java.awt.Point;
import java.awt.*;
import java.net.*;
import java.net.MalformedURLException;
import java.awt.*;
import java.io.DataInputStream;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.net.MalformedURLException;

public class X1 extends Applet

100
{

TextField textField;

public void init()

textField = new TextField(20);

add(textField);

}
sa se preia valori numerice sis a se afiseze

import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;
import java.awt.Event;
import java.awt.Point;
import java.awt.*;
import java.net.*;
import java.net.MalformedURLException;
import java.awt.*;
import java.io.DataInputStream;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.net.MalformedURLException;

public class X1 extends Applet

101
public void paint(Graphics g)

int x = 10;

String s = String.valueOf(x);

g.drawString(s, 40, 50);

}
sa se introduca doua numere sis a se calculeze suma cu un applet

import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;
import java.awt.Event;
import java.awt.Point;
import java.awt.*;
import java.net.*;
import java.net.MalformedURLException;
import java.awt.*;
import java.io.DataInputStream;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.net.MalformedURLException;

public class X1 extends Applet

TextField textField1;

102
TextField textField2;

public void init()

textField1 = new TextField(5);

textField2 = new TextField(5);

add(textField1);

add(textField2);

textField1.setText("0");

textField2.setText("0");

public void paint(Graphics g)

int value1;

int value2;

int sum;

g.drawString("Type a number in each box.", 40, 50);

g.drawString("The sum of the values is:", 40, 75);

String s = textField1.getText();

value1 = Integer.parseInt(s);

s = textField2.getText();

value2 = Integer.parseInt(s);

sum = value1 + value2;

s = String.valueOf(sum);

g.drawString(s, 80, 100);

103
public boolean action(Event event, Object arg)

repaint();

return true;

}
sa se testeze instructiunea swith cu apleturi scriind un numar sis a apra un text cu diferite culori dupa optiune

import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;
import java.awt.Event;
import java.awt.Point;
import java.awt.*;
import java.net.*;
import java.net.MalformedURLException;
import java.awt.*;
import java.io.DataInputStream;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.net.MalformedURLException;

public class X1 extends Applet

TextField textField1;

104
public void init()

textField1 = new TextField(5);

add(textField1);
}

public void paint(Graphics g)

{
g.drawString("3. Green", 40, 115);

String s = textField1.getText();

int choice = Integer.parseInt(s);

if (choice == 1)

g.setColor(Color.red);

else if (choice == 2)

g.setColor(Color.blue);

else if (choice == 3)

g.setColor(Color.green);

else

g.setColor(Color.black);

if ((choice >= 1) && (choice <= 3))

g.drawString("This is the color you chose.", 60, 140);

else

g.drawString("Invalid menu selection.", 60, 140);

public boolean action(Event event, Object arg)

repaint();

105
return true;

}
folosind instructiunea WHILE si apleturi sa se listeze numerele dintr-un interval citit de la tastatura

import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;
import java.awt.Event;
import java.awt.Point;
import java.awt.*;
import java.net.*;
import java.net.MalformedURLException;
import java.awt.*;
import java.io.DataInputStream;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.net.MalformedURLException;

public class X1 extends Applet

TextField textField1;

TextField textField2;

public void init()

106
textField1 = new TextField(5);

textField2 = new TextField(5);

add(textField1);

add(textField2);

textField1.setText("1");

textField2.setText("10");

public void paint(Graphics g)

g.drawString("Enter start and end values above.", 50, 45);

String s = textField1.getText();

int start = Integer.parseInt(s);

s = textField2.getText();

int end = Integer.parseInt(s);

int row = 0;

int count = start;

while (count <= end)

s = "Count = ";

s += String.valueOf(count++);

g.drawString(s, 80, row * 15 + 70);

++row;

}
public boolean action(Event event, Object arg)

repaint();

return true;

107
}
folosind instructiuneaDO.. WHILE si apleturi sa se listeze numerele dintr-un interval citit de la tastatura

import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;
import java.awt.Event;
import java.awt.Point;
import java.awt.*;
import java.net.*;
import java.net.MalformedURLException;
import java.awt.*;
import java.io.DataInputStream;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.net.MalformedURLException;

public class X1 extends Applet

TextField textField1;

TextField textField2;

public void init()

textField1 = new TextField(5);

textField2 = new TextField(5);

108
add(textField1);

add(textField2);

textField1.setText("1");

textField2.setText("10");

public void paint(Graphics g)

g.drawString("Enter start and end values above.", 50, 45);

String s = textField1.getText();

int start = Integer.parseInt(s);

s = textField2.getText();

int end = Integer.parseInt(s);

int row = 0;

int count = start;

do

s = "Count = ";

s += String.valueOf(count++);

g.drawString(s, 80, row * 15 + 70);

++row;

while (count <= end);

public boolean action(Event event, Object arg)

109
repaint();

return true;

}
Folosind For si apleturi sa se scrie un nume de 10 ori

import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;
import java.awt.Event;
import java.awt.Point;
import java.awt.*;
import java.net.*;
import java.net.MalformedURLException;
import java.awt.*;
import java.io.DataInputStream;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.net.MalformedURLException;

public class X1 extends Applet

TextField textField1;

110
public void init()

textField1 = new TextField(20);

add(textField1);

textField1.setText("Moe Howard");

public void paint(Graphics g)

g.drawString("Enter a name above.", 70, 45);

String s = textField1.getText();

for (int x=0; x<10; ++x)

g.drawString(s, 80, x * 15 + 70);

public boolean action(Event event, Object arg)

repaint();

return true;

}
folosind For si aplturi sa se sumeze din 5 in 5 intr-un interval si invers

import java.awt.*;
import java.applet.*;
import java.awt.Font;

111
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;
import java.awt.Event;
import java.awt.Point;
import java.awt.*;
import java.net.*;
import java.net.MalformedURLException;
import java.awt.*;
import java.io.DataInputStream;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.net.MalformedURLException;

public class X1 extends Applet

public void paint(Graphics g)

int row = 0;

for (int x=5; x<=40; x+=5)

String s = "Loop counter = ";

s += String.valueOf(x);

g.drawString(s, 80, row * 15 + 15);

++row;

for (int x=40; x>=5; x-=5)

String s = "Loop counter = ";

s += String.valueOf(x);

112
g.drawString(s, 80, row * 15 + 15);

++row;

}
sa se simileze o progresie aritmetica ci For si apleturi

import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;
import java.awt.Event;
import java.awt.Point;
import java.awt.*;
import java.net.*;
import java.net.MalformedURLException;
import java.awt.*;
import java.io.DataInputStream;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.net.MalformedURLException;

public class X1 extends Applet

TextField textField1;

TextField textField2;

TextField textField3;

113
public void init()

textField1 = new TextField(5);

textField2 = new TextField(5);

textField3 = new TextField(5);

add(textField1);

add(textField2);

add(textField3);

textField1.setText("1");

textField2.setText("10");

textField3.setText("1");

public void paint(Graphics g)

g.drawString("Enter loop starting, ending,", 50, 45);

g.drawString("and increment values above.", 50, 60);

String s = textField1.getText();

int start = Integer.parseInt(s);

s = textField2.getText();

int end = Integer.parseInt(s);

s = textField3.getText();

int inc = Integer.parseInt(s);

int row = 0;

114
for (int x=start; x<=end; x+=inc)

String s2 = "Loop counter = ";

s2 += String.valueOf(x);

g.drawString(s2, 50, row * 15 + 85);

++row;

public boolean action(Event event, Object arg)

repaint();

return true;

}
sa se puna in evidenta apelul subprogramelor cu apleturi

import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;
import java.awt.Event;

115
import java.awt.Point;
import java.awt.*;
import java.net.*;
import java.net.MalformedURLException;
import java.awt.*;
import java.io.DataInputStream;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.net.MalformedURLException;
import java.lang.Math;

public class X1 extends Applet

///////////////////////////////////////

// Data fields.

///////////////////////////////////////

TextField textField1;

int guesses;

int number;

////////////////////////////////////////

// Overridden methods.

////////////////////////////////////////

public void init()

textField1 = new TextField(10);

add(textField1);

textField1.setText("50");

guesses = 0;

number = CreateNumber();

public void paint(Graphics g)

116
DrawInstructions(g);

int guess = GetGuess();

ShowMessage(g, guess);

public boolean action(Event event, Object arg)

++guesses;

repaint();

return true;

////////////////////////////////////////

// Private methods.

////////////////////////////////////////

void DrawInstructions(Graphics g)

g.drawString("Try to guess the number I am", 48, 65);

g.drawString("thinking of. The number will be", 48, 80);

g.drawString("between 0 and 100. You have an", 48, 95);

g.drawString("unlimited number of tries.", 48, 110);

g.drawString("Good Luck.", 95, 140);

int GetGuess()

String s = textField1.getText();

int num = Integer.parseInt(s);

return num;

117
int CreateNumber()

float n = (float)Math.random();

number = (int)(n * 100 + 1);

return number;

void ShowMessage(Graphics g, int guess)

String s = "Guesses so far: ";

s += String.valueOf(guesses);

g.drawString(s, 80, 170);

if (guess < number)

g.drawString("Your guess is too low.", 70, 185);

else if (guess > number)

g.drawString("Your guess is too high.", 70, 185);

else

g.drawString("You guessed the number!", 65, 185);

cu aplturi sa se simuleze introducerea si listarea unui vector unidimensioanal

118
import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;
import java.awt.Event;
import java.awt.Point;
import java.awt.*;
import java.net.*;
import java.net.MalformedURLException;
import java.awt.*;
import java.io.DataInputStream;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.net.MalformedURLException;
import java.lang.Math;

public class X1 extends Applet

TextField textField1, textField2, textField3;

int avg1, avg2, avg3;

public void init()

119
textField1 = new TextField(5);

textField2 = new TextField(5);

textField3 = new TextField(5);

add(textField1);

add(textField2);

add(textField3);

textField1.setText("0");

textField2.setText("0");

textField3.setText("0");

public void paint(Graphics g)

g.drawString("Your bowlers' averages are: ", 50, 80);

String s = textField1.getText();

g.drawString(s, 75, 110);

avg1 = Integer.parseInt(s);

s = textField2.getText();

g.drawString(s, 75, 125);

avg2 = Integer.parseInt(s);

s = textField3.getText();

g.drawString(s, 75, 140);

avg3 = Integer.parseInt(s);

public boolean action(Event event, Object arg)

repaint();

return true;

120
}
sa se simuleze cu platuri crearea unui numar mare de componente ale unui vector si afisarea lui

import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;
import java.awt.Event;
import java.awt.Point;
import java.awt.*;
import java.net.*;
import java.net.MalformedURLException;
import java.awt.*;
import java.io.DataInputStream;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.net.MalformedURLException;
import java.lang.Math;

public class X1 extends Applet

TextField textField[];

int avg[];

public void init()

121
{

textField = new TextField[3];

avg = new int[3];

for (int x=0; x<3; ++x)

textField[x] = new TextField(5);

add(textField[x]);

textField[x].setText("0");

public void paint(Graphics g)

g.drawString("Your bowlers' averages are: ", 50, 80);

for (int x=0; x<3; ++x)

String s = textField[x].getText();

g.drawString(s, 75, 110 + x*15);

avg[x] = Integer.parseInt(s);

public boolean action(Event event, Object arg)

repaint();

return true;

}
cu apleturi sa se genereze si sa se afiseze o matrice

122
import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;
import java.awt.Event;
import java.awt.Point;
import java.awt.*;
import java.net.*;
import java.net.MalformedURLException;
import java.awt.*;
import java.io.DataInputStream;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.net.MalformedURLException;
import java.lang.Math;

public class X1 extends Applet

int table[][];

public void init()

table = new int[6][8];

for (int x=0; x<6; ++x)

for (int y=0; y<8; ++y)

123
table[x][y] = x+y*6;

public void paint(Graphics g)

for (int x=0; x<6; ++x)

for (int y=0; y<8; ++y)

String s = String.valueOf(table[x][y]);

g.drawString(s, 50+x*25, 50+y*15);

PRELUCRAREA IMAGINILOR

Conditia e ca ele sa fie de tip gif


sau jpeg
sis a fie localizate in calea : C:\Program Files\Xinox
Software\JCreator\MyProjects\x1 unde x1 e numele proiectului si al clasei iar presupunem ca
desenul se numeste poza.gif

Sa se realizeze importul unei imagini

import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;

124
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;
import java.awt.Image;

public class X1 extends Applet


{

Image bugimg;

public void init()


{
bugimg = getImage(getCodeBase(),"poza.gif");
// C:\Program Files\Xinox Software\JCreator\MyProjects\x1\ poza.gif e
//calea catre poza si x1 e clasa si
//proiectul salvat
}

public void paint(Graphics g)


{
g.drawImage(bugimg, 10, 10,this);
}

}
sa se produca redimensionari intr-un chenar cu fundal al unei poze

import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;
import java.awt.Image;

125
public class X1 extends Applet
{

Image bugimg;

public void init() {


bugimg = getImage(getCodeBase(),
"poza.gif");
}

public void paint(Graphics g) {


int iwidth = bugimg.getWidth(this);
int iheight = bugimg.getHeight(this);
int xpos = 10;

// 25 %
g.drawImage(bugimg, xpos, 10,
iwidth / 4, iheight / 4, this);

// 50 %
xpos += (iwidth / 4) + 10;
g.drawImage(bugimg, xpos , 10,
iwidth / 2, iheight / 2, this);

// 100%
xpos += (iwidth / 2) + 10;
g.drawImage(bugimg, xpos, 10, this);

// 150% x, 25% y
g.drawImage(bugimg, 10, iheight + 30,
(int)(iwidth * 1.5), iheight / 4, this);
}
}
punerea a doua melodii s1 si s2 sa cante dar care se afla in calea ca si pozele anteriaoare se face
astfel

import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;

public class X1 extends java.applet.Applet

implements Runnable {

AudioClip bgsound;
AudioClip beep;
Thread runner;

126
public void start() {
if (runner == null) {
runner = new Thread(this);
runner.start();
}
}

public void stop() {


if (runner != null) {
if (bgsound != null) bgsound.stop();
runner.stop();
runner = null;
}
}

public void init() {


bgsound = getAudioClip(getCodeBase(),"s1");
beep = getAudioClip(getCodeBase(), "s2");
}

public void run() {


if (bgsound != null) bgsound.loop();
while (runner != null) {
try { Thread.sleep(5000); }
catch (InterruptedException e) { }
if (beep != null) beep.play();
}
}

public void paint(Graphics g) {


g.drawString("Playing Sounds....", 10, 10);
}
}
realizarea unei animatii

127
import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;

public class X1 extends java.applet.Applet implements Runnable {

Thread runner;
int xpos;
int ux1,ux2;
Image offscreenImg;
Graphics offscreenG;

public void init() {


offscreenImg = createImage(this.size().width, this.size().height);
offscreenG = offscreenImg.getGraphics();
}

public void start() {


if (runner == null); {
runner = new Thread(this);
runner.start();
}
}

public void stop() {


if (runner != null) {
runner.stop();
runner = null;
}
}

public void run() {


setBackground(Color.blue);
while (true) {
for (xpos = 5; xpos <= 105; xpos+=4) {
if (xpos == 5) ux2 = size().width;

128
else ux2 = xpos + 90;
repaint();
try { Thread.sleep(100); }
catch (InterruptedException e) { }
if (ux1 == 0) ux1 = xpos;
}
xpos = 5;
}
}

public void update(Graphics g) {


g.clipRect(ux1, 5, ux2 - ux1, 95);
paint(g);
}

public void paint(Graphics g) {


// Draw background
offscreenG.setColor(Color.black);
offscreenG.fillRect(0,0,100,100);
offscreenG.setColor(Color.white);
offscreenG.fillRect(100,0,100,100);

// Draw checker
offscreenG.setColor(Color.red);
offscreenG.fillOval(xpos,5,90,90);

g.drawImage(offscreenImg,0,0,this);

// reset the drawing area


ux1 = ux2 = 0;
}

public void destroy() {


offscreenG.dispose();
}
}
sa se determine o animatie in Java referitor la ceas

import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;

129
import java.awt.Image;
import java.applet.AudioClip;

public class X1 extends java.applet.Applet


implements Runnable {

Font theFont = new Font("TimesRoman",Font.BOLD,24);


Date theDate;
Thread runner;

public void start() {


if (runner == null) {
runner = new Thread(this);
runner.start();
}
}

public void stop() {


if (runner != null) {
runner.stop();
runner = null;
}
}

public void run() {


while (true) {
theDate = new Date();
repaint();
try { Thread.sleep(1000); }
catch (InterruptedException e) { }
}
}

public void paint(Graphics g) {


g.setFont(theFont);
g.drawString(theDate.toString(),10,50);
}
}

sau versiunea:
import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;

public class X1 extends java.applet.Applet

130
implements Runnable {

Font theFont = new Font("TimesRoman",Font.BOLD,24);


Date theDate;
Thread runner;

public void start() {


if (runner == null) {
runner = new Thread(this);
runner.start();
}
}

public void stop() {


if (runner != null) {
runner.stop();
runner = null;
}
}

public void run() {


while (true) {
theDate = new Date();
repaint();
try { Thread.sleep(1000); }
catch (InterruptedException e) { }
}
}

public void paint(Graphics g) {


g.setFont(theFont);
g.drawString(theDate.toString(),10,50);
}
}
sa se implementeze un font sclipitor care-si modidfica culoarea

import java.awt.*;
import java.applet.*;

131
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;

public class X1 extends java.applet.Applet


implements Runnable {

Font f = new Font("TimesRoman",Font.BOLD,48);


Color colors[] = new Color[50];
Thread runThread;

public void start() {


if (runThread == null) {
runThread = new Thread(this);
runThread.start();
}
}

public void stop() {


if (runThread != null) {
runThread.stop();
runThread = null;
}
}

public void run() {

// initialize the color array


float c = 0;
for (int i = 0; i < colors.length; i++) {
colors[i] =
Color.getHSBColor(c, (float)1.0,(float)1.0);
c += .02;
}

// cycle through the colors


int i = 0;
while (true) {
setForeground(colors[i]);
repaint();
i++;
try { Thread.sleep(50); }
catch (InterruptedException e) { }
if (i == colors.length ) i = 0;
}
}

public void paint(Graphics g) {


g.setFont(f);
g.drawString("All the Swirly Colors", 15, 50);
}

132
}
sa se miste o s sfera intre doau patrate

import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;

public class X1 extends java.applet.Applet


implements Runnable {

Thread runner;
int xpos;

public void start() {


if (runner == null) {
runner = new Thread(this);
runner.start();
}
}

public void stop() {


if (runner != null) {

133
runner.stop();
runner = null;
}
}

public void run() {


setBackground(Color.blue);
while (true) {
for (xpos = 5; xpos <= 105; xpos+=4) {
repaint();
try { Thread.sleep(100); }
catch (InterruptedException e) { }
}
xpos = 5;
}
}

public void paint(Graphics g) {


// Draw background
g.setColor(Color.black);
g.fillRect(0, 0, 100, 100);
g.setColor(Color.white);
g.fillRect(101, 0, 100, 100);

// Draw checker
g.setColor(Color.red);
g.fillOval(xpos, 5, 90, 90);
}
}
aceiasi animatie ca mai sus dar sfera e parcursa de niste umbre de culoare

import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;

134
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;

public class X1 extends java.applet.Applet implements Runnable {

Thread runner;
int xpos;
int ux1,ux2;

public void start() {


if (runner == null) {
runner = new Thread(this);
runner.start();
}
}

public void stop() {


if (runner != null) {
runner.stop();
runner = null;
}
}

public void run() {


setBackground(Color.blue);
while (true) {
for (xpos = 5; xpos <= 105; xpos+=4) {
if (xpos == 5) ux2 = size().width;
else ux2 = xpos + 90;
repaint();
try { Thread.sleep(100); }
catch (InterruptedException e) { }
if (ux1 == 0) ux1 = xpos;
}
xpos = 5;
}
}

public void update(Graphics g) {


g.clipRect(ux1, 5, ux2 - ux1, 95);
paint(g);
}

public void paint(Graphics g) {


// Draw background
g.setColor(Color.black);
g.fillRect(0, 0, 100, 100);
g.setColor(Color.white);
g.fillRect(101, 0, 100, 100);

// Draw checker

135
g.setColor(Color.red);
g.fillOval(xpos, 5, 90, 90);

// reset the drawing area


ux1 = ux2 = 0;
}
}
GESTIONAREA ACTIVITATII MOUSE-ULUI
Sa se puna cu mouse-ul pe ecran niste cercuri de culoare albastra la apasarea butonului stang

import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;
import java.awt.Event;

public class X1 extends java.applet.Applet {

final int MAXSPOTS = 10;


int xspots[] = new int[MAXSPOTS];
int yspots[] = new int[MAXSPOTS];
int currspots = 0;

public void init() {


setBackground(Color.white);
}

public boolean mouseDown(Event evt, int x, int y) {


if (currspots < MAXSPOTS) {
addspot(x,y);
return true;
}
else {
System.out.println("Too many spots.");
return false;
}
}

void addspot(int x,int y) {

136
xspots[currspots] = x;
yspots[currspots] = y;
currspots++;
repaint();
}

public void paint(Graphics g) {


g.setColor(Color.blue);
for (int i = 0; i < currspots; i++) {
g.fillOval(xspots[i] - 10, yspots[i] - 10, 20, 20);
}
}
}
la apasrea butonului stang sau drept sa se traseze niste linii daca tin butonul apasat

import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;
import java.awt.Event;
import java.awt.Point;

public class X1 extends java.applet.Applet {

final int MAXLINES = 10;


Point starts[] = new Point[MAXLINES]; // starting points
Point ends[] = new Point[MAXLINES]; // endingpoints
Point anchor; // start of current line
Point currentpoint; // current end of line
int currline = 0; // number of lines

public void init() {


setBackground(Color.white);
}

public boolean mouseDown(Event evt, int x, int y) {

137
if (currline < MAXLINES) {
anchor = new Point(x,y);
return true;
}
else {
System.out.println("Too many lines.");
return false;
}
}

public boolean mouseUp(Event evt, int x, int y) {


if (currline < MAXLINES) {
addline(x,y);
return true;
}
else return false;
}

public boolean mouseDrag(Event evt, int x, int y) {


if (currline < MAXLINES) {
currentpoint = new Point(x,y);
repaint();
return true;
}
else return false;
}

void addline(int x,int y) {


starts[currline] = anchor;
ends[currline] = new Point(x,y);
currline++;
currentpoint = null;
anchor = null;
repaint();
}

public void paint(Graphics g) {

// Draw existing lines


for (int i = 0; i < currline; i++) {
g.drawLine(starts[i].x, starts[i].y,
ends[i].x, ends[i].y);
}

// draw current line


g.setColor(Color.blue);
if (currentpoint != null)
g.drawLine(anchor.x,anchor.y,
currentpoint.x,currentpoint.y);
}
}
sa se scrie o litera apoi sa se deplaseze cu tastele directionale aceasta litera la stanga,dreapta,sus sau
jos

138
import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;
import java.awt.Event;
import java.awt.Point;

public class X1 extends java.applet.Applet {

char currkey;
int currx;
int curry;

public void init() {


currx = (size().width / 2) -8; // default

139
curry = (size().height / 2) -16;

setBackground(Color.white);
setFont(new Font("Helvetica",Font.BOLD,36));
}

public boolean keyDown(Event evt, int key) {


switch (key) {
case Event.DOWN:
curry += 5;
break;
case Event.UP:
curry -= 5;
break;
case Event.LEFT:
currx -= 5;
break;
case Event.RIGHT:
currx += 5;
break;
default:
currkey = (char)key;
}

repaint();
return true;
}

public void paint(Graphics g) {


if (currkey != 0) {
g.drawString(String.valueOf(currkey), currx,curry);
}
}
}

OBIECTE DE CONTROL GRAFICE


Sa se creeze trei etichete stang,dreapta si centrata

import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;

140
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;
import java.awt.Event;
import java.awt.Point;

public class X1 extends java.applet.Applet {

public void init() {


setFont(new Font ("Helvetica", Font.BOLD, 14));
setLayout(new GridLayout(3,1));
add(new Label("aligned left", Label.LEFT));
add(new Label("aligned center", Label.CENTER));
add(new Label("aligned right", Label.RIGHT));
}
}

sa se creeze un declansator

import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;
import java.awt.Event;
import java.awt.Point;

public class X1 extends java.applet.Applet {

public void init() {


Button b = new Button("OK");
add(b);
}

}
sa se creeze trei declansatoare care sa si schimbe textul la apasarea unui buton

141
import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;
import java.awt.Event;
import java.awt.Point;
import java.awt.*;
import java.net.*;
import java.net.MalformedURLException;
import java.awt.*;
import java.io.DataInputStream;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.net.MalformedURLException;
import java.lang.Math;

public class X1 extends Applet

Button button1;

Button button2;

Button button3;

public void init()

button1 = new Button("Button1");

button2 = new Button("Button2");

142
button3 = new Button("Button3");

add(button1);

add(button2);

add(button3);

public boolean action(Event evt, Object arg)

if (evt.target instanceof Button)

HandleButtons(arg);

return true;

protected void HandleButtons(Object label)

if (label == "Button1")

button1.setLabel("1nottuB");

else if (label == "Button2")

button2.setLabel("2nottuB");

else if (label == "Button3")

button3.setLabel("3nottuB");

else

button1.setLabel("Button1");

button2.setLabel("Button2");

button3.setLabel("Button3");

143
sa se creze mai multe declansatoare

import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;
import java.awt.Event;
import java.awt.Point;

public class X1 extends java.applet.Applet {

public void init() {


add(new Button("Rewind"));
add(new Button("Play"));
add(new Button("Fast Forward"));
add(new Button("Stop"));
}

}
sa se creeze trei butoane de validare active la clic pee le sis a afiseze mesajul corespunzator

144
import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;
import java.awt.Event;
import java.awt.Point;
import java.awt.*;
import java.net.*;
import java.net.MalformedURLException;
import java.awt.*;
import java.io.DataInputStream;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.net.MalformedURLException;
import java.lang.Math;

public class X1 extends Applet

Checkbox checkbox1;

Checkbox checkbox2;

Checkbox checkbox3;

public void init()

145
checkbox1 = new Checkbox("Option 1", null, true);

checkbox2 = new Checkbox("Option 2", null, false);

checkbox3 = new Checkbox("Option 3", null, false);

add(checkbox1);

add(checkbox2);

add(checkbox3);

public void paint(Graphics g)

Font font = g.getFont();

FontMetrics fontMetrics = g.getFontMetrics(font);

int height = fontMetrics.getHeight();

boolean checked = checkbox1.getState();

if (checked)

g.drawString("Option1 selected", 20, 120);

else

g.drawString("Option1 not selected", 20, 120);

checked = checkbox2.getState();

if (checked)

g.drawString("Option2 selected", 20, 120 + height);

else

g.drawString("Option2 not selected", 20, 120 + height);

checked = checkbox3.getState();

if (checked)

g.drawString("Option3 selected", 20, 120 + 2 * height);

146
else

g.drawString("Option3 not selected", 20, 120 + 2 * height);

public boolean action(Event evt, Object arg)

repaint();

return true;

}
sa se creeze casute de validare care cand sunt selectate isi schimba eticheta

import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;
import java.awt.Event;
import java.awt.Point;
import java.awt.*;
import java.net.*;
import java.net.MalformedURLException;
import java.awt.*;
import java.io.DataInputStream;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.net.MalformedURLException;
import java.lang.Math;

public class X1 extends Applet

147
{

Checkbox checkbox1;

Checkbox checkbox2;

Checkbox checkbox3;

public void init()

checkbox1 = new Checkbox("Option 1", null, true);

checkbox2 = new Checkbox("Option 2", null, false);

checkbox3 = new Checkbox("Option 3", null, false);

add(checkbox1);

add(checkbox2);

add(checkbox3);

public boolean action(Event evt, Object arg)

if (evt.target instanceof Checkbox)

ChangeLabel(evt);

repaint();

return true;

protected void ChangeLabel(Event evt)

Checkbox checkbox = (Checkbox)evt.target;

String label = checkbox.getLabel();

148
if (label == "Option 1")

checkbox.setLabel("Changed 1");

else if (label == "Option 2")

checkbox.setLabel("Changed 2");

else if (label == "Option 3")

checkbox.setLabel("Changed 3");

else

checkbox1.setLabel("Option 1");

checkbox2.setLabel("Option 2");

checkbox3.setLabel("Option 3");

}
sa se creeze un camp si declansator iar la apasarea declansatorului continutul campului sa se schimbe

import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;
import java.awt.Event;

149
import java.awt.Point;
import java.awt.*;
import java.net.*;
import java.net.MalformedURLException;
import java.awt.*;
import java.io.DataInputStream;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.net.MalformedURLException;
import java.lang.Math;

public class X1 extends Applet

TextField textField;

Button button;

public void init()

textField = new TextField("", 25);

button = new Button("Change Echo");

textField.setEchoCharacter('*');

add(textField);

add(button);

public boolean action(Event evt, Object arg)

if (evt.target instanceof Button)

ChangeEcho();

return true;

150
protected void ChangeEcho()

char c = textField.getEchoChar();

if (c == '*')

textField.setEchoCharacter('#');

else if (c == '#')

textField.setEchoCharacter('$');

else

textField.setEchoCharacter('*');

sa se creeze mai multe casute de validare

import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;
import java.awt.Event;
import java.awt.Point;

public class X1 extends java.applet.Applet {

public void init() {


setLayout(new FlowLayout(FlowLayout.LEFT));

151
add(new Checkbox("Shoes"));
add(new Checkbox("Socks"));
add(new Checkbox("Pants"));
add(new Checkbox("Underwear", null, true));
add(new Checkbox("Shirt"));
}

}
sa se creeze mai multe butoane radio

import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;
import java.awt.Event;
import java.awt.Point;

public class X1 extends java.applet.Applet {

public void init() {


setLayout(new FlowLayout(FlowLayout.LEFT));
CheckboxGroup cbg = new CheckboxGroup();

add(new Checkbox("Red", cbg, false));


add(new Checkbox("Blue", cbg, false));
add(new Checkbox("Yellow", cbg, false));
add(new Checkbox("Green", cbg, true));
add(new Checkbox("Orange", cbg, false));
add(new Checkbox("Purple", cbg, false));
}

}
sa se creeze o lista ascunsa care prin alegerea unei optiuni isi schimba culoarea la text

152
import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;
import java.awt.Event;
import java.awt.Point;
import java.awt.*;
import java.net.*;
import java.net.MalformedURLException;
import java.awt.*;
import java.io.DataInputStream;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.net.MalformedURLException;
import java.lang.Math;

public class X1 extends Applet

Choice menu;

Color color;

public void init()

153
Choice menu = new Choice();

menu.addItem("Black");

menu.addItem("Red");

menu.addItem("Green");

menu.addItem("Blue");

add(menu);

color = Color.black;

public void paint(Graphics g)

Font font = new Font("TimesRoman", Font.BOLD, 24);

int height = font.getSize();

g.setFont(font);

g.setColor(color);

g.drawString("This text is drawn in", 32, 75);

g.drawString("the color selected from", 32, 75+height);

g.drawString("the above choice menu.", 32, 75+2*height);

public boolean action(Event evt, Object arg)

if (evt.target instanceof Choice)

HandleMenu(arg);

154
return true;

protected void HandleMenu(Object item)

if (item == "Black")

color = Color.black;

else if (item == "Red")

color = Color.red;

else if (item == "Green")

color = Color.green;

else

color = Color.blue;

repaint();

}
sa se creeze o lista care afiseaza in eticheta alegerea unei optiuni

import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;

155
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;
import java.awt.Event;
import java.awt.Point;
import java.awt.*;
import java.net.*;
import java.net.MalformedURLException;
import java.awt.*;
import java.io.DataInputStream;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.net.MalformedURLException;
import java.lang.Math;

public class X1 extends Applet

List list;

public void init()

list = new List(5, false);

list.addItem("Pearl Jam");

list.addItem("Dream Theater");

list.addItem("Joe Satriani");

list.addItem("Oasis");

list.addItem("Alanis Morissette");

list.addItem("Soul Asylum");

list.addItem("The Rembrandts");

list.addItem("Smashing Pumpkins");

list.addItem("Joan Osborne");

list.addItem("Bjork");

add(list);

resize(300, 150);

156
}

public void paint(Graphics g)

g.drawString("CHOSEN ITEM:", 100, 110);

String s = list.getSelectedItem();

if (s == null)

s = "None";

g.drawString(s, 100, 130);

public boolean action(Event evt, Object arg)

repaint();

return true;

sa se creeze o lista deluranta

import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;

157
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;
import java.awt.Event;
import java.awt.Point;

public class X1 extends java.applet.Applet {

public void init() {


Choice c = new Choice();

c.addItem("Apples");
c.addItem("Oranges");
c.addItem("Strawberries");
c.addItem("Blueberries");
c.addItem("Bananas");

add(c);
}

}
sa se creeze o eticheta si niste campuri dintre care unul ca parola

import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;
import java.awt.Image;

158
import java.applet.AudioClip;
import java.awt.Event;
import java.awt.Point;

public class X1 extends java.applet.Applet {

public void init() {

add(new Label("Enter your Name"));


add(new TextField("your name here", 45));
add(new Label("Enter your phone number"));
add(new TextField(12));
add(new Label("Enter your password"));
TextField t = new TextField(20);
t.setEchoCharacter('*');
add(t);

}
}
sa se puna un chenar in jurul unui buton pe care apas

import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;
import java.awt.Event;
import java.awt.Point;

public class X1 extends java.applet.Applet {

public void init() {


setLayout(new FlowLayout());
add(new Button("One"));
add(new Button("Two"));
add(new Button("Three"));

159
add(new Button("Four"));
add(new Button("Five"));
add(new Button("Six"));
}

}
sa se creeze o caseta text

import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;
import java.awt.Event;
import java.awt.Point;
import java.awt.*;
import java.net.*;
import java.net.MalformedURLException;
import java.awt.*;
import java.io.DataInputStream;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.net.MalformedURLException;
import java.lang.Math;

public class X1 extends Applet

TextArea textArea;

public void init()

160
String s = "This is an example of a\n";

s += "textarea control, which is not\n";

s += "unlike a textfield control.\n";

s += "The big difference is that a\n";

s += "textarea control can hold many\n";

s += "lines of text, whereas a\n";

s += "textfield control deals with\n";

s += "only one line of text at a time.\n";

textArea = new TextArea(s, 9, 30);

add(textArea);

resize(300, 180);

}
sa se creeze o bara de derulare

import java.awt.*;
import java.applet.*;

161
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;
import java.awt.Event;
import java.awt.Point;
import java.awt.*;
import java.net.*;
import java.net.MalformedURLException;
import java.awt.*;
import java.io.DataInputStream;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.net.MalformedURLException;
import java.lang.Math;

public class X1 extends Applet

Scrollbar scrollbar;

String s;

public void init()

BorderLayout layout = new BorderLayout();

setLayout(layout);

scrollbar = new Scrollbar(Scrollbar.HORIZONTAL,

50, 0, 1, 100);

add("North", scrollbar);

s = "50";

Font font = new Font("TimesRoman", Font.BOLD, 72);

setFont(font);

162
resize(200, 200);

public void paint(Graphics g)

g.drawString(s, 60, 120);

public boolean handleEvent(Event evt)

if (evt.target instanceof Scrollbar)

scrollbar = (Scrollbar)evt.target;

int value = scrollbar.getValue();

s = String.valueOf(value);

repaint();

return true;

else

boolean result = super.handleEvent(evt);

return result;

}
sa se creeze un declansator care schimba culoarea unui fundal

163
import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;
import java.awt.Event;
import java.awt.Point;
import java.awt.*;
import java.net.*;
import java.net.MalformedURLException;
import java.awt.*;
import java.io.DataInputStream;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.net.MalformedURLException;
import java.lang.Math;

public class X1 extends Applet

CustomCanvas canvas;

public void init()

setLayout(new BorderLayout());

Button button = new Button("Color");

add("North", button);

canvas = new CustomCanvas();

add("Center", canvas);

resize(200, 250);

164
public boolean action(Event evt, Object arg)

if (arg == "Color")

canvas.swapColor();

return true;

class CustomCanvas extends Canvas

Color color;

public CustomCanvas()

color = Color.black;

public void paint(Graphics g)

Rectangle r = bounds();

g.setColor(color);

g.fillRect(0, 0, r.width, r.height);

g.setColor(Color.white);

g.drawString("CANVAS", 72, 90);

public void swapColor()

165
if (color == Color.black)

color = Color.red;

else if (color == Color.red)

color = Color.green;

else

color = Color.black;

repaint();

}
sa se scrie un program cu declansator care si schimba etichtea la actionare

import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;
import java.awt.Event;
import java.awt.Point;
import java.awt.*;
import java.net.*;
import java.net.MalformedURLException;
import java.awt.*;

166
import java.io.DataInputStream;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.net.MalformedURLException;
import java.lang.Math;

public class X1 extends Applet

CardLayout cardLayout;

Panel panel;

Button button1, button2, button3;

public void init()

panel = new Panel();

add(panel);

cardLayout = new CardLayout(0, 0);

panel.setLayout(cardLayout);

button1 = new Button("Button1");

button2 = new Button("Button2");

button3 = new Button("Button3");

panel.add("Button1", button1);

panel.add("Button2", button2);

panel.add("Button3", button3);

public boolean action(Event evt, Object arg)

167
cardLayout.next(panel);

return true;

}
sa se creeze declansatoare de dimensiuni diferite

import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;
import java.awt.Event;
import java.awt.Point;
import java.awt.*;
import java.net.*;
import java.net.MalformedURLException;
import java.awt.*;
import java.io.DataInputStream;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.net.MalformedURLException;
import java.lang.Math;

public class X1 extends Applet

public void init()

168
GridBagLayout layout = new GridBagLayout();

setLayout(layout);

GridBagConstraints constraints = new GridBagConstraints();

Button button1 = new Button("Button1");

Button button2 = new Button("Button2");

Button button3 = new Button("Button3");

Button button4 = new Button("Button4");

Button button5 = new Button("Button5");

Button button6 = new Button("Button6");

Button button7 = new Button("Button7");

Button button8 = new Button("Button8");

Button button9 = new Button("Button9");

constraints.fill = GridBagConstraints.BOTH;

layout.setConstraints(button1, constraints);

add(button1);

constraints.gridwidth = GridBagConstraints.RELATIVE;

layout.setConstraints(button2, constraints);

add(button2);

constraints.gridwidth = GridBagConstraints.REMAINDER;

layout.setConstraints(button3, constraints);

add(button3);

constraints.gridwidth = GridBagConstraints.REMAINDER;

layout.setConstraints(button4, constraints);

169
add(button4);

constraints.gridwidth = GridBagConstraints.RELATIVE;

layout.setConstraints(button5, constraints);

add(button5);

constraints.gridwidth = GridBagConstraints.REMAINDER;

layout.setConstraints(button6, constraints);

add(button6);

constraints.gridwidth = 1;

constraints.gridheight = 2;

layout.setConstraints(button7, constraints);

add(button7);

constraints.gridwidth = GridBagConstraints.REMAINDER;

constraints.gridheight = 1;

layout.setConstraints(button8, constraints);

add(button8);

layout.setConstraints(button9, constraints);

add(button9);

resize(300, 200);

}
sa se execute un program care ascunde si afisaza o fereastra

170
import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;
import java.awt.Event;
import java.awt.Point;
import java.awt.*;
import java.net.*;
import java.net.MalformedURLException;
import java.awt.*;
import java.io.DataInputStream;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.net.MalformedURLException;
import java.lang.Math;

public class X1 extends Applet

Frame frame;

Button button;

public void init()

frame = new Frame("Frame Window");

button = new Button("Show Window");

add(button);

public boolean action(Event evt, Object arg)

171
{

boolean visible = frame.isShowing();

if (visible)

frame.hide();

button.setLabel("Show Window");

else

frame.show();

frame.resize(200, 100);

button.setLabel("Hide Window");

return true;

}
sau

import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;
import java.awt.Event;
import java.awt.Point;
import java.awt.*;

172
import java.net.*;
import java.net.MalformedURLException;
import java.awt.*;
import java.io.DataInputStream;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.net.MalformedURLException;
import java.lang.Math;

public class X1 extends Applet

CustomFrame frame;

Button button;

public void init()

frame = new CustomFrame("Custom Frame Window");

button = new Button("Show Window");

add(button);

public boolean action(Event evt, Object arg)

boolean visible = frame.isShowing();

if (visible)

frame.hide();

button.setLabel("Show Window");

else

frame.show();

button.setLabel("Hide Window");

173
}

return true;

class CustomFrame extends Frame

CustomFrame(String title)

super(title);

public void paint(Graphics g)

resize(200, 100);

g.drawString("This is a custom window.", 30, 30);

crearea unei ferestre cu meniu

import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;

174
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;
import java.awt.Event;
import java.awt.Point;
import java.awt.*;
import java.net.*;
import java.net.MalformedURLException;
import java.awt.*;
import java.io.DataInputStream;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.net.MalformedURLException;
import java.lang.Math;

public class X1 extends Applet

MenuBarFrame frame;

Button button;

public void init()

frame = new MenuBarFrame("MenuBar Window");

button = new Button("Show Window");

add(button);

public boolean action(Event evt, Object arg)

boolean visible = frame.isShowing();

if (visible)

frame.hide();

button.setLabel("Show Window");

175
}

else

frame.show();

button.setLabel("Hide Window");

return true;

class MenuBarFrame extends Frame

MenuBar menuBar;

String str;

MenuBarFrame(String title)

super(title);

menuBar = new MenuBar();

setMenuBar(menuBar);

Menu menu = new Menu("Test");

menuBar.add(menu);

MenuItem item = new MenuItem("Command 1");

menu.add(item);

item = new MenuItem("Command 2");

menu.add(item);

176
item = new MenuItem("-");

menu.add(item);

CheckboxMenuItem checkItem =

new CheckboxMenuItem("Check");

menu.add(checkItem);

str = "";

Font font = new Font("TimesRoman", Font.BOLD, 20);

setFont(font);

public void paint(Graphics g)

resize(300, 250);

g.drawString(str, 20, 100);

public boolean action(Event evt, Object arg)

if (evt.target instanceof MenuItem)

if (arg == "Command 1")

str = "You selected Command 1";

else if (arg == "Command 2")

str = "You selected Command 2";

else if (arg == "Check")

str = "You selected the Check item";

177
repaint();

return true;

else

return false;

sa se creeze o fereastra care deschide alta la actionarea unui meniu

import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;
import java.awt.Event;
import java.awt.Point;
import java.awt.*;
import java.net.*;
import java.net.MalformedURLException;
import java.awt.*;
import java.io.DataInputStream;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.net.MalformedURLException;
import java.lang.Math;

public class X1 extends Applet

178
DialogFrame frame;

Button button;

public void init()

frame = new DialogFrame("Dialog Window");

button = new Button("Show Window");

add(button);

public boolean action(Event evt, Object arg)

boolean visible = frame.isShowing();

if (visible)

frame.hide();

button.setLabel("Show Window");

else

frame.show();

button.setLabel("Hide Window");

return true;

179
class DialogFrame extends Frame

MenuBar menuBar;

Dialog dialog;

TextField textField;

String str;

DialogFrame(String title)

super(title);

menuBar = new MenuBar();

setMenuBar(menuBar);

Menu menu = new Menu("Test");

menuBar.add(menu);

MenuItem item = new MenuItem("Dialog box");

menu.add(item);

str = "";

public void paint(Graphics g)

resize(300, 250);

g.drawString("THE TEXT YOU ENTERED IS:", 70, 50);

g.drawString(str, 70, 70);

public boolean action(Event evt, Object arg)

180
{

if (evt.target instanceof MenuItem)

if (arg == "Dialog box")

ShowDialogBox();

else if (evt.target instanceof Button)

if (arg == "OK")

dialog.hide();

str = textField.getText();

repaint();

return true;

protected void ShowDialogBox()

dialog = new Dialog(this, "Test Dialog", true);

FlowLayout layout = new FlowLayout();

dialog.setLayout(layout);

textField = new TextField("", 20);

Button button = new Button("OK");

dialog.add(button);

dialog.add(textField);

181
dialog.show();

dialog.resize(200, 100);

sa se creeze niste butoane care sa fie prinse intr-un chenar

import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;
import java.awt.Event;
import java.awt.Point;

public class X1 extends java.applet.Applet {

public void init() {


setLayout(new BorderLayout());
add("North", new Button("One"));
add("East", new Button("Two"));
add("South", new Button("Three"));
add("West", new Button("Four"));
add("Center", new Button("Five"));
add(new Button("Six"));
}

}
sa se creeze niste campuri ,declansator si grilaj

182
import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;
import java.awt.Event;
import java.awt.Point;

public class X1 extends java.applet.Applet {

void buildConstraints(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;
}

public void init() {


GridBagLayout gridbag = new GridBagLayout();
GridBagConstraints constraints = new GridBagConstraints();
setLayout(gridbag);

// Name label
buildConstraints(constraints, 0, 0, 1, 1, 10, 40);
constraints.fill = GridBagConstraints.NONE;
constraints.anchor = GridBagConstraints.EAST;
Label label1 = new Label("Name:", Label.LEFT);
gridbag.setConstraints(label1, constraints);
add(label1);

// Name text field


buildConstraints(constraints, 1, 0, 1, 1, 90, 0);
constraints.fill = GridBagConstraints.HORIZONTAL;
TextField tfname = new TextField();

183
gridbag.setConstraints(tfname, constraints);
add(tfname);

// password label
buildConstraints(constraints, 0, 1, 1, 1, 0, 40);
constraints.fill = GridBagConstraints.NONE;
constraints.anchor = GridBagConstraints.EAST;
Label label2 = new Label("Password:", Label.LEFT);
gridbag.setConstraints(label2, constraints);
add(label2);

// password text field


buildConstraints(constraints, 1, 1, 1, 1, 0, 0);
constraints.fill = GridBagConstraints.HORIZONTAL;
TextField tfpass = new TextField();
tfpass.setEchoCharacter('*');
gridbag.setConstraints(tfpass, constraints);
add(tfpass);

// OK Button
buildConstraints(constraints, 0, 2, 2, 1, 0, 20);
constraints.fill = GridBagConstraints.NONE;
constraints.anchor = GridBagConstraints.CENTER;
Button okb = new Button("OK");
gridbag.setConstraints(okb, constraints);
add(okb);
}

}
sa se creeze niste declansatoare dar la apasarea unui sa se schmbe cularea fondului

import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;
import java.awt.Event;
import java.awt.Point;

184
public class X1 extends java.applet.Applet {

public void init() {


setBackground(Color.white);

add(new Button("Red"));
add(new Button("Blue"));
add(new Button("Green"));
add(new Button("White"));
add(new Button("Black"));
}

public boolean action(Event evt, Object arg) {


if (evt.target instanceof Button) {
changeColor((String)arg);
return true;
} else return false;
}

void changeColor(String bname) {


if (bname.equals("Red")) setBackground(Color.red);
else if (bname.equals("Blue")) setBackground(Color.blue);
else if (bname.equals("Green")) setBackground(Color.green);
else if (bname.equals("White")) setBackground(Color.white);
else setBackground(Color.black);

repaint();
}
}
sa se creeze o caseta text care se poate derula

import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;

185
import java.awt.Image;
import java.applet.AudioClip;
import java.awt.Event;
import java.awt.Point;

public class X1 extends java.applet.Applet {

public void init() {


String str = "Once upon a midnight dreary, while I pondered, weak and weary,\n" +
"Over many a quaint and curious volume of forgotten lore,\n" +
"While I nodded, nearly napping, suddenly there came a tapping,\n" +
"As of some one gently rapping, rapping at my chamber door.\n" +
"\"'Tis some visitor,\" I muttered, \"tapping at my chamber door-\n" +
"Only this, and nothing more.\"\n\n";
// more text deleted for space

add(new TextArea(str,10,50));
}
}
sa se creeze o lista deluranta

import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;
import java.awt.Event;
import java.awt.Point;

public class X1 extends java.applet.Applet {

public void init() {


List lst = new List(5, true);

lst.addItem("Hamlet");
lst.addItem("Claudius");
lst.addItem("Gertrude");
lst.addItem("Polonius");

186
lst.addItem("Horatio");
lst.addItem("Laertes");
lst.addItem("Ophelia");

add(lst);
}
}
sa se creeze o bara care prin deplasare modifica niste valori intr-o eticheta pe ecran

import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;
import java.awt.Event;
import java.awt.Point;

public class X1 extends java.applet.Applet {

Label l;

public void init() {


setLayout(new GridLayout(1,2));
l = new Label("0", Label.CENTER);
add(l);
add(new Scrollbar(Scrollbar.HORIZONTAL,0,0,1,100));
}

public Insets insets() {


return new Insets(15,15,15,15);
}

public boolean handleEvent(Event evt) {


if (evt.target instanceof Scrollbar) {
int v = ((Scrollbar)evt.target).getValue();
l.setText(String.valueOf(v));
repaint();
return true;
} else return false;
}

187
}
sa se creeze o freastra care sa poata fi modificat,deplsata.minimizata

import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;
import java.awt.Event;
import java.awt.Point;

class BaseFrame extends Frame {


String message = "This is a Window";

BaseFrame(String title) {
super(title);
setFont(new Font("Helvetica", Font.BOLD, 12));
}

public void paint(Graphics g) {


g.drawString(message, 20, 20);
}
}

public class X1 extends java.applet.Applet {


Frame window;

public void init() {


add(new Button("Open Window"));
add(new Button("Close Window"));

window = new BaseFrame("A Popup Window");


window.resize(150,150);
window.show();
}

public boolean action(Event evt, Object arg) {


if (evt.target instanceof Button) {
String label = (String)arg;
if (label.equals("Open Window")) {
if (!window.isShowing())
window.show();
}
else if (label.equals("Close Window")) {
if (window.isShowing())
window.hide();

188
}
return true;
}
else return false;
}
}
sa se creeze o fereastra care poate fi inchisa sau deschisa de la niste declansatoare si meniu vertical

import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;
import java.awt.Event;
import java.awt.Point;

class BaseFrame2 extends Frame {


String message = "This is a Window";

BaseFrame2(String title) {
super(title);
setFont(new Font("Helvetica", Font.BOLD, 12));

MenuBar mb = new MenuBar();


Menu m = new Menu("Colors");
m.add(new MenuItem("Red"));
m.add(new MenuItem("Blue"));
m.add(new MenuItem("Green"));
m.add(new MenuItem("-"));
m.add(new CheckboxMenuItem("Reverse Text"));
mb.add(m);

189
setMenuBar(mb);
}

public boolean action(Event evt, Object arg) {


String label = (String)arg;
if (evt.target instanceof MenuItem) {
if (label.equals("Red")) setBackground(Color.red);
else if (label.equals("Blue")) setBackground(Color.blue);
else if (label.equals("Green")) setBackground(Color.green);
else if (label.equals("Reverse Text")) {
if (getForeground() == Color.black) {
setForeground(Color.white);
} else setForeground(Color.black);
}
repaint();
return true;
} else return false;
}

public void paint(Graphics g) {


g.drawString(message, 20, 20);
}

public boolean handleEvent(Event evt) {


if (evt.id == Event.WINDOW_DESTROY) hide();
return super.handleEvent(evt);
}
}

public void paint(Graphics g) {


g.drawString(message, 20, 20);
}
}

public class X1 extends java.applet.Applet {


Frame window;

public void init() {


add(new Button("Open Window"));
add(new Button("Close Window"));

window = new BaseFrame2("A Popup Window");


window.resize(150,150);
window.show();
}

public boolean action(Event evt, Object arg) {


if (evt.target instanceof Button) {
String label = (String)arg;
if (label.equals("Open Window")) {
if (!window.isShowing())
window.show();
}
else if (label.equals("Close Window")) {
if (window.isShowing())
window.hide();

190
}
return true;
}
else return false;
}
}
sa se faca niste declansatoare care acceseaza diferite site-uri

import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;
import java.awt.Event;
import java.awt.Point;
import java.awt.*;
import java.net.*;
import java.net.MalformedURLException;

public class X1 extends java.applet.Applet {

Bookmark bmlist[] = new Bookmark[3];

public void init() {


bmlist[0] = new Bookmark("Laura's Home Page",
"http://www.lne.com/lemay/");
bmlist[1] = new Bookmark("Gamelan",
"http://www.gamelan.com");
bmlist[2]= new Bookmark("Java Home Page",
"http://java.sun.com");

setLayout(new GridLayout(bmlist.length,1, 10, 10));


for (int i = 0; i < bmlist.length; i++) {
add(new Button(bmlist[i].name));
}
}

191
public boolean action(Event evt, Object arg) {
if (evt.target instanceof Button) {
linkTo((String)arg);
return true;
}
else return false;
}

void linkTo(String name) {


URL theURL = null;
for (int i = 0; i < bmlist.length; i++) {
if (name.equals(bmlist[i].name))
theURL = bmlist[i].url;
}
if (theURL != null)
getAppletContext().showDocument(theURL);
}
}

class Bookmark {
String name;
URL url;

Bookmark(String name, String theURL) {


this.name = name;
try { this.url = new URL(theURL); }
catch ( MalformedURLException e) {
System.out.println("Bad URL: " + theURL);
}
}
}
sa se creeze o zona de editare prin care caut intr-un site

import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;

192
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;
import java.awt.Event;
import java.awt.Point;
import java.awt.*;
import java.net.*;
import java.net.MalformedURLException;
import java.awt.*;
import java.io.DataInputStream;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.net.MalformedURLException;

public class X1 extends java.applet.Applet implements Runnable {


URL theURL;
Thread runner;
TextArea ta = new TextArea("Getting text...");

public void init() {


setLayout(new GridLayout(1,1));

String url = "http://www.lne.com/Web/JavaProf/raven.txt";


try { this.theURL = new URL(url); }
catch ( MalformedURLException e) {
System.out.println("Bad URL: " + theURL);
}
add(ta);
}

public Insets insets() {


return new Insets(10,10,10,10);
}

public void start() {


if (runner == null) {
runner = new Thread(this);
runner.start();
}
}

public void stop() {


if (runner != null) {
runner.stop();
runner = null;
}
}

public void run() {


URLConnection conn = null;
DataInputStream data = null;
String line;
StringBuffer buf = new StringBuffer();

try {
conn = this.theURL.openConnection();
conn.connect();

193
ta.setText("Connection opened...");
data = new DataInputStream(new BufferedInputStream(
conn.getInputStream()));
ta.setText("Reading data...");
while ((line = data.readLine()) != null) {
buf.append(line + "\n");
}
ta.setText(buf.toString());
}
catch (IOException e) {
System.out.println("IO Error:" + e.getMessage());
}
}
}
accesul la o baza de date se verifica astfel
//sa se numere numarul de instate (chemari) ale unei metode
package j1;

import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;
import java.awt.Event;
import java.awt.Point;
import java.awt.*;
import java.net.*;
import java.net.MalformedURLException;
import java.awt.*;
import java.io.DataInputStream;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.net.MalformedURLException;
/*
Output: DBServer.class
Function: The DBServer is waiting on 9090 port SQL statements.
When it receive a SQL statement it lunch a thread that
identifies
the SQL statement, send it to the local DBMS, receive the
result
and send it back to the client.
*/

import java.net.*;
import java.sql.*;
import java.util.*;

public class DBServer extends Thread


{

194
private final int SERVER_PORT = 9090;
public final int ACCEPT_QUEUE_DIMENSION = 10;

protected ServerSocket acceptSocket;


private int activeConexions;
protected String url="jdbc:odbc:personal";
protected Connection con;
protected String driver ="sun.jdbc.odbc.JdbcOdbcDriver";

public DBServer()
{

try
{
acceptSocket = new ServerSocket(SERVER_PORT,
ACCEPT_QUEUE_DIMENSION);
activeConexions = 0;
Class.forName(driver);
con=DriverManager.getConnection(url,"","");
System.out.println("ruleaza (m-am conectat la: " +
url + " baza de date sursa)... ");
this.start();
}
catch (BindException bindErr)
{
System.out.println("nu am gasit serverul la portul
" + SERVER_PORT + ".");
}
catch( ClassNotFoundException exc )
{
System.err.println("avem o exceptie la clasa care
nu are sens: " + exc.getMessage());
System.exit(0);
}
catch (SQLException exc){}
catch (IOException createErr)
{
System.out.println("Eroare la crearea soclului de
ascultare.");
}
catch (Exception exc)
{
System.out.println("Error: " + exc);
}
}
public synchronized int activeThreadsNumber()
{
return activeConexions;
}

public static void main(String args[])


{
new DBServer();
}

195
public synchronized void threadStarted()
{
activeConexions++;
}
public synchronized void threadStoped()
{
activeConexions--;

}
}
Lucrul cu baze de date
15.1 Introducere
15.1.1 Generalităţi despre baze de date
Aplicaţiile care folosesc baze de date sunt, în Crearea unei baze de date se face uzual folosind
general, aplicaţii complexe aplicaţii specializate oferite
folosite pentru gestionarea unor informaţii de de producătorul tipului respectiv de sistem de
dimensiuni mari într-o manieră gestiune a datelor, dar există
sigură şi eficientă. şi posibilitatea de a crea o baza folosind un script
Ce este o bază de date ? SQL. Acest aspect ne va
La nivelul cel mai general, o bază de date reprezintă preocupa însă mai puţin, exemplele prezentate
o modalitate de stocare a presupunând că baza a fost
unor informaţii (date) pe un suport extern, cu creată deja şi are o anumită structură specificată.
posibilitatea regăsirii acestora. Accesul la baza de date
Uzual, o bază de date este memorată într-unul sau Se face prin intermediul unui driver specific tipului
mai multe fişiere. respectiv de SGBD.
Modelul clasic de baze de date este cel relaţional, în Acesta este responsabil cu accesul efectiv la datele
care datele sunt stocate, fiind legatura
memorate în tabele. Un tabel reprezintă o structură dintre aplicaţie şi baza de date.
de date formată dintr-o Limbajul SQL
mulţime de articole, fiecare articol având definite o SQL (Structured Query Language) reprezintă un
serie de atribute - aceste limaj de programare ce
atribute corespund coloanelor tabelului, în timp ce o permite interogarea şi actualizarea informaţiilor din
linie va reprezenta un baze de date relaţionale.
articol. Pe lânga tabele, o bază de date mai poate Acesta este standardizat astfel încât diverse tipuri de
conţine: proceduri şi drivere să se comporte
funcţii, utilizatori şi grupuri de utilizatori, tipuri de identic, oferind astfel o modalitate unitară de lucru
date, obiecte, etc. cu baze de date.
Dintre producătorii cei mai importanţi de baze de 4.1.2 JDBC
date amintim companiile JDBC (Java Database Connectivity) este o interfaţă
Oracle, Sybase, IBM, Informix, Microsoft, etc. standard SQL de acces
fiecare furnizând o la baze de date. JDBC este constituită dintr-un set de
serie întreagă de produse şi utilitare pentru lucrul cu clase şi interfeţe
baze de date. Aceste scrise în Java, furnizând mecanisme standard pentru
produse sunt în general referite prin termenii DBMS proiectanţii aplicaţiilor
(Database Management ce folosesc de baze de date.
System) sau, în traducere, SGBD (Sistem de Folosind JDBC este uşor să transmitem secvenţe
Gestiune a Bazelor de Date). In SQL către baze de date
acest capitol vom analiza lucrul cu baze de date din relaţionale. Cu alte cuvinte, nu este necesar să
perspectiva programării scriem un program pentru a
în limbajul Java, fără a descrie particularităţi ale accesa o bază de date Oracle, alt program pentru a
unei soluţii de stocare a accesa o bază de date
datelor anume. Vom vedea că, folosind Java, putem Sybase şi asa mai departe. Este de ajuns să scriem
crea aplicaţii care să un singur program folosind
ruleze fără nici o modificare folosind diverse tipuri API-ul JDBC şi acesta va fi capabil să comunice cu
de baze care au aceeaşi drivere diferite, trimiţând
structură, ducând în felul acesta noţiunea de secvenţe SQL către baza de date dorită. Bineînţeles,
portabilitate şi mai departe. scriind codul sursă în
Crearea unei baze de date

196
Java, ne este asigurată portabilitatea programului. feluri:
Deci, iată două motive – De la linia de comandă:
puternice care fac combinaţia Java - JDBC demnă java -Djdbc.drivers=TipDriver Aplicatie
de luat în seamă. – Din program:
Pachetele care oferă suport pentru lucrul cu baze de System.setProperty("jdbc.drivers", "TipDriver");
date sunt java.sql Folosind această metodă, specificarea mai multor
ce reprezintă nucleul tehnologiei JDBC şi, preluat drivere se face separând
de pe platforma J2EE, numele claselor cu punct şi virgulă.
javax.sql. Dacă suntînregistrate mai multe drivere, ordinea de
In linii mari, API-ul JDBC oferă următoarele precedenţăîn alegerea
facilităţi: driverului folosit la crearea unei noi conexiuni este:
1. Stabilirea unei conexiuni cu o bază de date. 1) Drivereleînregistrate folosind proprietatea
2. Efectuarea de secvenţe SQL. jdbc.drivers la iniţializarea
3. Prelucrarea rezultatelor obţinute. maşinii virtuale ce va rula procesul.
15.2 Conectarea la o bază de date 2) Driverele înregistrate dinamic din aplicaţie.
Procesul de conectare la o bază de date implică 4.2.2 Specificarea unei baze de date
efectuarea a două operaţii: O dată ce un driver JDBC a fostînregistrat, acesta
1. Inregistrarea unui driver corespunzător. poate fi folosit la stabilirea
2. Realizarea unei conexiuni propriu-zise. unei conexiuni cu o bază de date. Având în vedere
Definiţie faptul ca pot exista mai
O conexiune (sesiune) la o bază de date reprezintă multe drivere încărcate în memorie, trebuie să avem
un context prin care posibilitea de a specifica
sunt trimise secvenţe SQL şi primite rezultate. Intr-o pe lângă un identificator al bazei de date şi driverul
aplicaţie pot exista ce trebuie folosit. Aceasta
simultan mai multe conexiuni la baze de date se realizează prin intermediul unei adrese specifice,
diferite sau la aceeaşi bază. numită JDBC URL, ce
Clasele şi interfeţele responsabile cu realizarea unei are următorul format:
conexiuni sunt: jdbc:sub-protocol:identificator
• DriverManager - este clasa ce se ocupă cu Câmpul sub-protocol denumeşte tipul de driver ce
înregistrarea driverelor ce trebuie folosit pentru
vor fi folosite în aplicaţie; realizarea conexiunii şi poate fi odbc, oracle, sybase,
• Driver - interfaţa pe care trebuie să o db2 şi aşa mai departe.
implementeze orice clasă ce Identificatorul bazei de date este un indicator
descrie un driver; specific fiecărui driver corespunz
• DriverPropertyInfo - prin intermediul acestei clase ător bazei de date cu care aplicaţia doreşte să
pot fi specificate interacţioneze. In funcţie
diverse proprietăţi ce vor fi folosite la realizarea de tipul driver-ului acest identificator poate include
conexiunilor; numele unei maşini
• Connection - descrie obiectele ce modelează o gazdă, un număr de port, numele unui fişier sau al
conexiune propriu-zisă unui director, etc., ca
cu baza de date. în exemplele de mai jos:
15.2.1 Inregistrarea unui driver jdbc:odbc:test
Primul lucru pe care trebuie să-l facă o aplicaţie în jdbc:oracle:thin@persistentjava.com:1521:test
procesul de conectare jdbc:sybase:test
la o bază de date este să înregistreze la maşina jdbc:db2:test
virtuală ce rulează aplicaţia Subprotocolul odbc este un caz specical, în sensul
driverul JDBC responsabil cu comunicarea cu că permite specificarea
respectiva bază de date. Acest în cadrul URL-ului a unor atribute ce vor fi realizate
lucru presupune încărcarea în memorie a clasei ce la crearea unei conexiuni.
implementează driver-ul şi Sintaxa completa subprotocolului odbc este:
poate fi realizată în mai multe modalităţi. jdbc:odbc:identificator[;atribut=valoare]*
a. Folosirea clasei DriverManager: jdbc:odbc:test
DriverManager.registerDriver(new TipDriver()); jdbc:odbc:test;CacheSize=20;ExtensionCase=LOW
b. Folosirea metodei Class.forName ce apelează ER
ClassLoader-ul maşinii jdbc:odbc:test;UID=duke;PWD=java
virtuale: La primirea unui JDBC URL, DriverManager-ul va
Class.forName("TipDriver"); parcurge lista driverelor
Class.forName("TipDriver").newInstance(); înregistrate în memorie, pâna când unul dintre ele va
c. Setarea proprietăţii sistem jdbc.drivers, care poate recunoaşte URL-ul respectiv.
fi realizată în două

197
Dacă nu exista nici unul potrivit, atunci va fi lansata Tip 4. Driver JDBC nativ
o excepţie de Acest tip de driver transformă cererile JDBC direct
tipul SQLException, cu mesajul "no suitable în cereri către baza
driver". de date folosind protocolul de reţea al acesteia.
4.2.3 Tipuri de drivere Această soluţie este cea mai
Tipurile de drivere existente ce pot fi folosite pentru rapidă, fiind preferată la dezvoltarea aplicaţiilor care
realizarea unei conexiuni manevrează volume
prin intermediul JDBC se împart în următoarele mari de date şi viteza de execuţie este critică.
categorii: Drivere de acest tip pot fi
Tip 1. JDBC-ODBC Bridge procurate de la diverşi producători de SGBD-uri.
Acest tip de driver permite conectarea la o bază de 4.2.4 Realizarea unei conexiuni
date care a fost Metoda folosită pentru realizarea unei conexiuni
înregistrată în prealabil în ODBC. ODBC (Open este getConnection din
Database Conectivity) clasa DriverManager şi poate avea mai multe forme:
reprezintă o modalitate de a uniformiza accesul la Connection c = DriverManager.getConnection(url);
baze de date, asociind Connection c = DriverManager.getConnection(url,
acestora un identificator DSN (Data Source Name) username, password);
şi diverşi parametri necesari Connection c = DriverManager.getConnection(url,
conectării. Conectarea efectivă la baza de date se va dbproperties);
face prin intermediul Stabilirea unei conexiuni folosind driverul JDBC-
acestui identificator, driver-ul ODBC efectuând ODBC
comunicarea cu driverul nativ String url = "jdbc:odbc:test" ;
al bazei de date. // sau url = "jdbc:odbc:test;UID=duke;PWD=java" ;
Deşi simplu de utilizat, soluţia JDBC-ODBC nu este try {
portabilă şi comunicarea Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
cu baza de date suferă la nivelul vitezei de execuţie } catch(ClassNotFoundException e) {
datorită multiplelor System.err.print("ClassNotFoundException: " + e) ;
redirectări între drivere. De asemenea, atât ODBC- return ;
ul cât şi driver-ul nativ }
trebuie să existe pe maşina pe care rulează aplicaţia. Connection con ;
Clasa Java care descrie acest tip de driver JDBC try {
este: con = DriverManager.getConnection(url, "duke",
sun.jdbc.odbc.JdbcOdbcDriver "java");
şi este inclusă în distribuţia standard J2SDK. } catch(SQLException e) {
Specificarea bazei de date se System.err.println("SQLException: " + e);
face printr-un URL de forma: } finally {
jdbc:odbc:identificator try{
unde identificator este profilul (DSN) creat bazei de con.close ;
date în ODBC. } catch(SQLException e) {
Tip 2. Driver JDBC - Driver nativ System.err.println(SQLException: " + e) ;
Acest tip de driver transformă cererile JDBC direct }
în apeluri către }
driverul nativ al bazei de date, care trebuie instalat Stabilirea unei conexiuni folosind un driver MySql
în prealabil. Clase Java Folosirea diferitelor tipuri de drivere implică doar
care implementează astfel de drivere pot fi procurate schimbarea numelui clasei
de la producătorii de ce reprezintă driverul şi a modalităţii de specificare
SGBD-uri, distribuţia standard J2SDK neincluzând a bazei de date.
nici unul. String url = "jdbc:mysql://localhost/test" ;
Tip 3. Driver JDBC - Server // sau url = "jdbc:mysql://localhost/test?
Acest tip de driver transformă cererile JDBC user=duke&password=java";
folosind un protocol de reţea try {
independent, acestea fiind apoi transormate folosind Class.forName("com.mysql.jdbc.Driver") ;
o aplicaţie server într-un } catch(ClassNotFoundException e) {
protocol specfic bazei de date. Introducerea ...
serverului ca nivel intermediar O conexiune va fi folosită pentru:
aduce flexibilitate maximă în sensul că vor putea fi • Crearea de secvenţe SQL utilizate pentru
realizate conexiuni cu interogarea sau actualizarea
diferite tipuri de baze, fără nici o modificare la bazei.
nivelul clientului. Protocolul • Aflarea unor informaţii legate de baza de date
folosit este specific fiecărui producător. (meta-date).

198
De asemenea, clasa Connection asigură facilităţi String sql = "DELETE FROM persoane WHERE
pentru controlul tranzacţiilor cod > 100";
din memorie către baza de date prin metodele int linii = stmt.executeUpdate(sql);
commit, rollback, setAutoCommit. // Nr de articole care au fost afectate (sterse)
Inchiderea unei conexiuni se realizează prin metoda sql = "DROP TABLE temp";
close. stmt.executeUpdate(sql); // returneaza 0
4.3 Efectuarea de secvenţe SQL 3. execute
O dată facută conectarea cu metoda Această metodă va fi folosită doar dacâ este posibil
DriverManager.getConection, se poate ca rezultatul unei interog
folosi obiectul Connection rezultat pentru a se crea ări să fie format din două sau mai multe obiecte de
obiecte de tip Statement, tip ResultSet sau
PreparedStatement sau CallableStatement cu rezultatul unei actualizări să fie format din mai mule
ajutorul cărora valori, sau o combinaţie
putem trimite secvenţe SQL către baza de date. Cele între aceste cazuri. Această situaţie, deşi mai rară,
mai uzuale comenzi este posibilă atunci când
SQL sunt cele folosite pentru: sunt executate proceduri stocate sau secvenţe SQL
• Interogarea bazei de date: SELECT cunoscute abia la momentul
• Actualizarea datelor: INSERT, UPDATE, execuţiei, programatorul neştiind deci dacă va fi
DELETE vorba de o actualizare
• Actualizarea structurii: CREATE, ALTER, DROP a datelor sau a structurii. Metoda întoarce true dacă
- acestea mai sunt numite rezultatul obţinut
instrucţiuni DDL (Data Definition Language) este format din obiecte de tip ResultSet şi false dacă
• Apelarea unei proceduri stocate: CALL e format din întregi.
După cum vom vedea, obţinerea şi prelucrarea In funcţie de aceasta, pot fi apelate metodele:
rezultatelor unei interogări getResultSet sau getUpdateCount
este realizată prin intermediul obiectelor de tip pentru a afla efectiv rezultatul comenzii SQL.
ResultSet. Pentru a prelua
4.3.1 Interfaţa Statement toate rezultatele va fi apelată metoda
Interfaţa Statement oferă metodele de bază pentru getMoreResults, după care vor fi
trimiterea de secvenţe apelate din nou metodele amintite, până la obţinerea
SQL către baza de date şi obţinerea rezultatelor, valorii null, respectiv
celelalte două interfeţe: -1. Secvenţa completă de tratare a metodei execute
PreparedStatement şi CallableStatement fiind este prezentată mai
derivate din aceasta. jos:
Crearea unui obiect Statement se realizează prin String sql = "comanda SQL necunoscuta";
intermediul metodei stmt.execute(sql);
createStatement a clasei Connection, fără nici un while(true) {
argument: int rowCount = stmt.getUpdateCount();
Connection con = if(rowCount > 0) {
DriverManager.getConnection(url); // Este o actualizare datelor
Statement stmt = con.createStatement(); System.out.println("Linii afectate = " + rowCount);
Execuţia unei secvenţe SQL poate fi realizată prin stmt.getMoreResults();
intermediul a trei continue;
metode: }
1. executeQuery if(rowCount = 0) {
Este folosită pentru realizarea de interogări de tip // Comanda DDL sau nici o linie afectata
SELECT.Metoda returnează System.out.println("Comanda DDL sau 0
un obiect de tip ResultSet ce va conţine sub o formă actualizari");
tabelară rezultatul stmt.getMoreResults();
interogării. continue;
String sql = "SELECT * FROM persoane"; }
ResultSet rs = stmt.executeQuery(sql); // rowCount este -1
2. executeUpdate // Avem unul sau mai multe ResultSet-uri
Este folosită pentru actualizarea datelor (INSERT, ResultSet rs = stmt.getResultSet();
UPDATE, DELETE) sau if(rs != null) {
a structurii bazei de date (CREATE, ALTER, // Proceseaza rezultatul
DROP). Metoda va returna un ...
întreg ce semnifică numărul de linii afectate de stmt.getMoreResults();
operaţiunea de actualizare a continue;
datelor, sau 0 în cazul unei instrucţiuni DDL. }

199
// Nu mai avem nici un rezultat unde XXX este tipul corespunzător parametrului, iar
break; argumentele metodei
} sunt numărul de ordine al parametrului de intrare (al
Folosind clasa Statement, în cazul în care dorim să semnului de întrebare)
introducem valorile şi valoarea pe care dorim să o atribuim.
unor variabile într-o secvenţă SQL, nu avem altă pstmt.setString(1, "Ionescu");
soluţie decât să creăm un pstmt.setInt(2, 100);
şir de caractere compus din instrucţiuni SQL şi După stabilirea parametrilor de intrare secvenţa
valorile variabilelor: SQL poate fi executată.
int cod = 100; Putem apoi stabili alte valori de intrare şi refolosi
String nume = "Popescu"; obiectul PreparedStatement
String sql = "SELECT * FROM persoane WHERE pentru execuţii repetate ale comenzii SQL. Este însă
cod=" + cod + posibil ca SGBD-ul
" OR nume=’" + nume + "’"; folosit să nu suporte acest tip de operaţiune şi să nu
ResultSet rs = stmt.executeQuery(sql); reţină obiectul precompilat
4.3.2 Interfaţa PreparedStatement pentru execuţii ulterioare. In această situaţie
Interfaţa PreparedStatement este derivată din folosirea interfeţei
Statement, fiind diferită de PreparedStatement în loc de Statement nu va
aceasta în următoarele privinţe: îmbunătăţi în nici un fel
• Instanţele de tip PreparedStatement conţin performanţa codului, din punctul de vedere al
secvenţe SQL care au fost vitezei de execuţie a acestuia.
deja compilate (sunt ”pregătite”). Execuţia unei secvenţe SQL folosind un obiect
• O secvenţă SQL specificată unui obiect PreparedStatement se
PreparedStatement poate să realizează printr-una din metodele executeQuery,
aibă unul sau mai mulţi parametri de intrare, care executeUpdate sau
vor fi specificaţi execute, semnificaţiile lor fiind aceleaşi ca şi în
prin intermediul unui semn de întrebare (”?”) în cazul obiectelor de tip
locul fiecăruia dintre Statement, cu singura deosebire că în cazul de faţă
ei. Inainte ca secvenţa SQL să poată fi executată ele nu au nici un argument.
fiecărui parametru String sql = "UPDATE persoane SET nume=?
de intrare trebuie să i se atribuie o valoare, folosind WHERE cod=?";
metode specifice Statement pstmt = con.prepareStatement(sql);
acestei clase. pstmt.setString(1, "Ionescu");
Execuţia repetată a aceleiaşi secvenţe SQL, dar cu pstmt.setInt(2, 100);
parametri diferiţi, va pstmt.executeUpdate();
fi în general mai rapidă dacă folosim pstmt.setString(1, "Popescu");
PreparedStatement, deoarece nu mai pstmt.setInt(2, 200);
trebuie să creăm câte un obiect de tip Statement pstmt.executeUpdate();
pentru fiecare apel SQL, ci sql = "SELECT * from persoane WHERE cod
refolosim o singură instanţă precompilată >= ?";
furnizându-i doar alte argumente. pstmt = con.prepareStatement(sql);
Crearea unui obiect de tip PreparedStatement se pstmt.setInt(1, 100);
realizează prin intermediul ResultSet rs = pstmt.executeQuery();
metodei prepareStatement a clasei Connection, Fiecărui tip Java îi corespunde un tip generic SQL.
specificân ca argument Este responsabilitatea
o secvenţă SQL ce conţine căte un semn de programatorului să se asigure că foloseşte metoda
întrebare pentru fiecare adecvată de tip setXXX la
parametru de intrare: stabilirea valorii unui parametru de intrare. Lista
Connection con = tuturor tipurilor generice
DriverManager.getConnection(url); disponibile, numite şi tipuri JDBC, este definită de
String sql = "UPDATE persoane SET nume=? clasa Types, prin constantelor
WHERE cod=?"; declarate de aceasta. Metoda setObject permite
Statement pstmt = con.prepareStatement(sql); specificarea unor
Obiectul va pstmt conţine o comandă SQL valori pentru parametrii de intrare, atunci când
precompilată care este trimisă dorim să folosim maparea
imediat către baza de date, unde va aştepta implicită între tipurile Java şi cele JDBC sau atunci
parametri de intrare pentru a când dorim să precizăm
putea fi executată. explicit un tip JDBC.
Trimiterea parametrilor se realizează prin metode de pstmt.setObject(1, "Ionescu", Types.CHAR);
tip setXXX,

200
pstmt.setObject(2, 100, Types.INTEGER); // sau Connection con =
doar DriverManager.getConnection(url);
pstmt.setObject(2, 100); CallableStatement cstmt = con.prepareCall(
Folosind metoda setNull putem să atribuim unui "{call proceduraStocata(?, ?)}");
parametru de intrare Trimiterea parametrilor de intrare se
valoare SQL NULL, trebuind însă să specificăm şi realizeazăîntocmai ca la PreparedStatement,
tipul de date al coloanei în cu metode de tip setXXX. Dacă procedura are şi
care vom scrie această valoare. Acelaşi lucru poate parametri de ieşire (valori
fi realizat cu metode de returnate), aceştia vor trebui înregistraţi cu metoda
tipul setXXX dacă argumentul folosit are valoarea registerOutParameter
null. înainte de execuţia procedurii. Obţinerea valorilor
pstmt.setNull(1, Types.CHAR); rezultate în parametrii
pstmt.setInt(2, null); de ieşie se va face cu metode de tip getXXX.
Cu ajutorul metodelor setBytes sau setString avem CallableStatement cstmt = con.prepareCall(
posibilitatea de a "{call calculMedie(?)}");
specifica date de orice dimensiuni ca valori pentru cstmt.registerOutParameter(1,
anumite articole din baza java.sql.Types.FLOAT);
de date. Există însă situaţii când este de preferat ca cstmt.executeQuery();
datele de mari dimensiuni float medie = cstmt.getDouble(1);
să fie transferate pe ”bucăţi” de o anumită Este posibil ca un parametru de intrare să fie şi
dimensiune. Pentru a realiza parametru de ieşire. In
acest lucru API-ul JDBC pune la dispoziţie acest caz el trebuie să primească o valoare cu
metodele setBinaryStream, setXXX şi, de asemenea, va fi
setAsciiStream şi setUnicodeStream care ataşează înregistrat cu registerOutParameter, tipurile de date
un flux de intrare pe specificate trebuind
octeţi, caractere ASCII, respectiv UNICODE, unui să coincidă.
parametru de intrare. Pe 15.3.4 Obţinerea şi prelucrarea rezultatelor
măsură ce sunt citite date de pe flux, ele vor fi 15.3.5 Interfaţa ResultSet
atribuite parametrului. Exemplul In urma execuţie unei interogări SQL rezultatul va fi
de mai jos ilustrează acest lucru, atribuind coloanei reprezentat printr-un
continut conţinutul obiect de tip ResultSet, ce va conţine toate liniile ce
unui anumit fişier: satisfac condiţiile
File file = new File("date.txt"); impuse de comanda SQL. Forma generală a unui
int fileLength = file.length(); ResultSet este tabelară,
InputStream fin = new FileInputStream(file); având un număr de coloane şi de linii, funcţie de
java.sql.PreparedStatement pstmt = secvenţa executată. De
con.prepareStatement( asemenea, obiectul va conţine şi meta-datele
"UPDATE fisiere SET continut = ? WHERE nume interogării cum ar fi denumirele
= ’date.txt’"); coloanelor selectate, numărul lor, etc.
pstmt.setUnicodeStream (1, fin, fileLength); Statement stmt = con.createStatement();
pstmt.executeUpdate(); String sql = "SELECT cod, nume FROM persoane";
La execuţia secvenţei, fluxul de intrare va fi apelat ResultSet rs = stmt.executeQuery(sql);
repetat pentru a Rezultatul interogării de mai sus va fi obiectul rs cu
furniza datele ce vor fi scrise în coloana continut a următoarea structură:
articolului specificat. cod nume
Observaţi că este necesar înă să ştim dinainte 100 Ionescu
dimensiunea datelor ce vor fi 200 Popescu
scrise, acest lucru fiind solicitat de unele tipuri de Pentru a extrage informaţiile din această structură va
baze de date. trebui să parcurgem
4.3.3 Interfaţa CallableStatement tabelul linie cu linie şi din fiecare să extragem
Interfaţa CallableStatement este derivată din valorile de pe coloane. Pentru
PreparedStatement, instanţele acest lucru vom folosi metode de tip getXXX, unde
de acest tip oferind o modalitate de a apela o XXX este tipul de
procedură stocată într-o bază dată al unei coloane iar argumentul primit indică fie
de date, într-o manieră standar pentru toate SGBD- numărul de ordine din
urile. cadrul tabelului, fie numele acestuia. Coloanele sunt
Crearea unui obiect CallableStatement se realizează numerotate de la stânga
prin metoda prepareCall la dreapta, începând cu 1. In general, folosirea
a clasei Connection: indexului coloanei în loc de

201
numele său va fi mai eficientă. De asemenea, pentru Linia curentă anterioară a cursorului va fi memorată
maximă portabilitate pentru a se putea
se recomandă citirea coloanelor în ordine de la reveni la ea.
stânga la dreapta şi fiecare • insertRow - inserează articolul din zona linie nouă
citire să se facă o singură dată. în baza de date;
Un obiect ResultSet foloseşte un cursor pentru a cursorul trebuie să fie poziţionat le linia nouă la
parcurge articolele execuţia acestei operaţiuni.
rezultate în urma unei interogări. Iniţial acest cursor • moveToCurrentRow - revine la linia curentă din
este poziţionat înaintea tabel.
primei linii, fiecare apel al metodei next • deleteRow - şterge linia curentă din tabel şi din
determinând trecerea la următoarea baza de date; nu
linie. Deoarece next returnează false când nu mai poate fi apelată când cursorul este în modul linie
sunt linii de adus, uzual nouă.
va fi folosită o buclă while-loop petru a itera prin Nu toate sistemele de gestiune a bazelor de date
articolele tabelului: oferă suport pentru
String sql = "SELECT cod, nume FROM persoane"; folosirea cursoarelor care pot fi modificate. Pentru a
ResultSet rs = stmt.executeQuery(sql); determina dacă baza de
while (rs.next()) { date permite acest lucru pot fi utilizate metodele
int cod = r.getInt("cod"); supportsPositionedUpdate
String nume = r.getString("nume"); şi supportsPositionedDelete ale clasei
/* echivalent: DatabaseMetaData. In cazul
int cod = r.getInt(1); în care acest lucru este permis, este responsabilitatea
String nume = r.getString(2); driver-ului bazei de
*/ date să asigure rezolvarea problemelor legate de
System.out.println(cod + ", " + nume); actualizarea concurentă a
} unui cursor, astfel încât să nu apară anomalii.
Implicit, un tabel de tip ResultSet nu poate fi 4.3.6 Exemplu simplu
modificat iar cursorul In continuare vom da un exemplul simplu de
asociat nu se deplasează decât înainte, linie cu linie. utilizare a claselor de bază
Aşadar, putem itera menţionate anterior. Programul va folosi o bază de
prin rezultatul unei interogări o singură dată şi date MySql, ce conţine
numai de la prima la ultima un tabel numit persoane, având coloanele: cod,
linie. Este însă posibil să creăm ResultSet-uri care nume şi salariu. Scriptul
să permită modificarea SQL de creare a bazei este:
sau deplasarea în ambele sensuri. Exemplul următor create table persoane(cod integer, nume char(50),
va folosi un cursor care salariu double);
este modificabil şi nu va reflecta schimbările Aplicaţia va goli tabelul cu persoane, după care va
produse de alţi utilizatori după adăuga aleator un
crearea sa: număr de articole, va efectua afişarea lor şi calculul
Statement stmt = con.createStatement( mediei salariilor.
ResultSet.TYPE_SCROLL_INSENSITIVE, Listing 15.1: Exemplu simplu de utilzare JDBC
ResultSet.CONCUR_UPDATABLE); import java . sql .*;
String sql = "SELECT cod, nume FROM persoane"; public class TestJdbc {
ResultSet rs = stmt.executeQuery(sql); public static void main ( String [] args ) {
Dacă un ResultSet foloseşte un cursor modificabil şi String url = " jdbc : mysql :// localhost / test " ;
care poate naviga try {
în ambele sensuri, atunci are la dispoziţie o serie de Class . forName ("com . mysql . jdbc . Driver ");
metode ce se bazează pe } catch ( ClassNotFoundException e) {
acest suport: System . out. println (" Eroare incarcare driver !\n"
• absolute - Deplasează cursorul la o anumită linie + e);
specificată absolut; return ;
• updateXXX - Actualizează valoarea unei coloane }
din linia curentă, try {
unde XXX este un tip de date. Connection con = DriverManager . getConnection
• updateRow - Transferă actualizările făcute liniei în (url);
baza de date. // Golim tabelul persoane
• moveToInsertRow - deplasează cursorul la o linie String sql = " DELETE FROM persoane ";
spceială, numită Statement stmt = con . createStatement ();
linie nouă, utilizateă pentru a introduce noi articole stmt . executeUpdate (sql);
în baza de date. // Adaugam un numar de persoane generate aleator

202
// Tabelul persoane are coloanele (cod , nume , După realizarea unui conexiuni la o bază de date,
salariu ) putem apela metoda get-
int n = 10; MetaData pentru a afla diverse informaţii legate de
sql = " INSERT INTO persoane VALUES (?, ?, ?)"; baza respectivă, aşa
PreparedStatement pstmt = con . prepareStatement ( numitele meta-date (”date despre date”); Ca rezult al
sql); apelului metodei, vom
for (int i=0; i<n; i++) { obţine un obiect de tip DatabaseMetaData ce oferă
int cod = i; metode pentru determinarea
String nume = " Persoana " + i; tabelelor, procedurilor stocate, capabilităţilor
double salariu = 100 + Math . round ( Math . conexiunii, gramaticii
random () * SQL suportate, etc. ale bazei de date.
900) ; Programul următor afişează numele tuturor tabelelor
// salariul va fi intre 100 si 1000 dintr-o bază de dat
pstmt . setInt (1, cod ); înregistrată în ODBC.
pstmt . setString (2, nume ); Listing 4.2: Folosirea interfeţei DatabaseMetaData
pstmt . setDouble (3, salariu ); import java . sql .*;
pstmt . executeUpdate (); public class TestMetaData {
} public static void main ( String [] args ) {
// Afisam persoanele ordonate dupa salariu String url = " jdbc : odbc : test ";
sql = " SELECT * FROM persoane ORDER BY try {
salariu "; Class . forName ("sun . jdbc . odbc .
ResultSet rs = stmt . executeQuery (sql); JdbcOdbcDriver ");
while (rs. next ()) } catch ( ClassNotFoundException e) {
System . out. println (rs. getInt ("cod ") + ", " + System . out. println (" Eroare incarcare driver !\n"
rs. getString (" nume ") + ", " + + e);
rs. getDouble (" salariu ")); return ;
// Calculam salariul mediu }
sql = " SELECT avg( salariu ) FROM persoane "; try {
rs = stmt . executeQuery (sql); Connection con = DriverManager . getConnection
rs. next (); (url);
System . out. println (" Media : " + rs. getDouble DatabaseMetaData dbmd = con. getMetaData ();
(1)); ResultSet rs = dbmd . getTables (null , null , null ,
// Inchidem conexiunea null );
con . close (); while (rs. next ())
} catch ( SQLException e) { System . out. println (rs. getString ("
e. printStackTrace (); TABLE_NAME "));
} con . close ();
} } catch ( SQLException e) {
} e. printStackTrace ();
4.4 Lucrul cu meta-date }
4.4.1 Interfaţa DatabaseMetaData }
}
4.4.2 Interfaţa ResultSetMetaData
Meta-datele unui ResultSet reprezintă informaţiile despre rezultatul conţinut
în acel obiect cum ar fi numărul coloanelor, tipul şi denumirile lor, etc. Acestea
sunt obţinute apelând metoda getMetaData pentru ResultSet-ul respectiv,
care va returna un obiect de tip ResultSetMetaData ce poate fi
apoi folosit pentru extragerea informaţiilor dorite.
ResultSet rs = stmt.executeQuery("SELECT * FROM tabel");
ResultSetMetaData rsmd = rs.getMetaData();
// Aflam numarul de coloane
int n = rsmd.getColumnCount();
// Aflam numele coloanelor
Sring nume[] = new String[n+1];
for(int i=1; i<=n; i++)
nume[i] = rsmd.getColumnName(i);

CREAREA SI CONECTAREA LA BAZE DE DATE CU JAVA

203
CREARE

PROIECT

204
APAS PE inchiderea ferestrei

205
enter pe zoo ca sa introduce datele

1)START/SETTINGS/CONTROL PANEL
2)

206
3)

4)

ADD

207
5)

finish

advanced

208
ok

select

ok/ok

209
ok
Conectarea la baza de date
Tools/connect to database

NEXT

210
OK
AVEM URMATOAREA SITUATIE

ADAUGAREA UNEI NOI CONEXIUNI SE FACE CU CLICK DREAPTA PE Data conections

add connection

211
aleg tabela

tools/connect to server

212
VIZUALIZAREA DATELOR SE FACE CU CLICK DREAPTA PE TABLES

conectarea la baza de date

package j1;

import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;
import java.awt.Event;
import java.awt.Point;
import java.awt.*;
import java.net.*;
import java.net.MalformedURLException;
import java.awt.*;
import java.io.DataInputStream;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.net.MalformedURLException;
import java.net.*;
import java.sql.*;

import java.util.*;
import java.io.*;

213
import java.util.*;
import java.sql.*;
import sun.jdbc.odbc.*;
import java.io.*;

import java.lang.*;
import java.sql.*;
import sun.jdbc.odbc.*;
public class sample2
{
public static void main(String arg[])
{
int id;
float amount;
Date dt;
String status;
String result;
try
{
//connect to ODBC database
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
String url = "jdbc:odbc:Zoo";
// connect
Connection con =
DriverManager.getConnection(url,"dba", "sql");
// create Statement object
Statement stmt = con.createStatement();
String srch = arg[0];
String sqlselect = "Select company_id, order_dt,
po_amount, status_cd"
+ " from dba.purchase_order where company_id
= " + srch;
// run query
ResultSet rs = stmt.executeQuery(sqlselect);
// process results
while(rs.next())
{
result = "";
id = rs.getInt(1);
amount = rs.getFloat(3);
dt = rs.getDate(2);
status = rs.getString(4);
result = result.valueOf(id) + " ";
result+= result.valueOf(amount) + " ";
result+= dt.toString() + " " + status;
System.out.println("Values are: " + result);
}

//close connection
con.close();
}
catch(Exception e)
{
System.out.println(e.getMessage());
}
}

}
listarea tuturor tranzactiilor

214
package j1;

import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;
import java.awt.Event;
import java.awt.Point;
import java.awt.*;
import java.net.*;
import java.net.MalformedURLException;
import java.awt.*;
import java.io.DataInputStream;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.net.MalformedURLException;
import java.net.*;
import java.sql.*;

import java.util.*;
import java.io.*;
import java.util.*;
import java.sql.*;
import sun.jdbc.odbc.*;
import java.io.*;

import java.lang.*;
import java.sql.*;
import sun.jdbc.odbc.*;
public class sample3
{
public static void main(String arg[])
{
try
{
//connect to ODBC database
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
String url = "jdbc:odbc:Zoo";
// connect
Connection con =
DriverManager.getConnection(url,"dba", "sql");
con.setAutoCommit(false);

// create Statement object


Statement stmt = con.createStatement();
String updatestring = "INSERT INTO
RETAIL_ITEM(item_nbr,item_desc, qty_per_pkg, "
+ "wholesale_cost, retail_cost, company_id,
color, size) "
+ "VALUES(25,'some item', 1, 10.00, 15.00, 1,
'orange', 'M')";

215
// run query
int ct = stmt.executeUpdate(updatestring);
// process results
System.out.println("Insert row: " +
updatestring.valueOf(ct));
updatestring = "UPDATE PERSON "
+ "set zip_cd = '97228' where "
+ "zip_cd = '97229'";
// run query
ct = stmt.executeUpdate(updatestring);
// process results
System.out.println("Updated rows: " +
updatestring.valueOf(ct));
//back out modifications
updatestring = "DELETE FROM RETAIL_ITEM "
+ "where item_nbr = 25 and company_id = 1";
// run query
ct = stmt.executeUpdate(updatestring);
// process results
System.out.println("Delete row: " +
updatestring.valueOf(ct));
updatestring = "UPDATE PERSON "
+ "set zip_cd = '97229' where "
+ "zip_cd = '97228'";
// run query
ct = stmt.executeUpdate(updatestring);
// process results
System.out.println("Updated rows: " +
updatestring.valueOf(ct));
//close connection
con.commit();
con.close();
}
catch(Exception e)
{
System.out.println(e.getMessage());
}
}

}
numararea coloanelor si liniilor actualizate

package j1;

import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;
import java.awt.Event;
import java.awt.Point;
import java.awt.*;
import java.net.*;

216
import java.net.MalformedURLException;
import java.awt.*;
import java.io.DataInputStream;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.net.MalformedURLException;
import java.net.*;
import java.sql.*;

import java.util.*;
import java.io.*;
import java.util.*;
import java.sql.*;
import sun.jdbc.odbc.*;
import java.io.*;

import java.lang.*;
import java.sql.*;
import sun.jdbc.odbc.*;

public class sample6


{
public static void main(String arg[])
{
String result;
try
{
//connect to ODBC database
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
String url = "jdbc:odbc:Zoo";
// connect
Connection con =
DriverManager.getConnection(url,"dba", "sql");
con.setAutoCommit(false);
String sqlselect =
"Select * from retail_item where company_id =
?";
// create Statement object
PreparedStatement stmt =
con.prepareStatement(sqlselect);
ResultSet rs;
ResultSetMetaData rsmd;
for (int i = 1; i <= 3; i++)
{
stmt.setInt(1,i);
rs = stmt.executeQuery();
rsmd = rs.getMetaData();
int colcount = rsmd.getColumnCount();
// process results
while(rs.next())
{
result = "";
for (int k = 1; k <= colcount; k++)
{
result+= rs.getString(k) + " ";
}
System.out.println("Values are: " +
result);
}

217
}

//close connection
con.close();
}
catch(Exception e)
{
System.out.println(e.getMessage());
}
}

}
filtrarea datelor

package j1;

import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;
import java.awt.Event;
import java.awt.Point;
import java.awt.*;
import java.net.*;
import java.net.MalformedURLException;
import java.awt.*;
import java.io.DataInputStream;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.net.MalformedURLException;
import java.net.*;
import java.sql.*;

import java.util.*;
import java.io.*;
import java.util.*;
import java.sql.*;
import sun.jdbc.odbc.*;
import java.io.*;

import java.lang.*;
import java.sql.*;
import sun.jdbc.odbc.*;

public class sample7


{
public static void main(String arg[])
{
String result;
try

218
{
//connect to ODBC database
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
String url = "jdbc:odbc:Zoo";
// connect
Connection con =
DriverManager.getConnection(url,"dba", "sql");
// create Statement object
Statement stmt = con.createStatement();
String sqlstmt = arg[0];
// run statement
boolean b = stmt.execute(sqlstmt);
// if true, result set
result = "";
if (b)
{
// process results
ResultSet rs = stmt.getResultSet();
ResultSetMetaData rsmd = rs.getMetaData();
int colcount = rsmd.getColumnCount();
while(rs.next())
{
result = "";
for (int i=1; i <= colcount; i++)
{
result+= rs.getString(i) + " ";
}
System.out.println("Values are: " +
result);
}
}
else
{
int ct = stmt.getUpdateCount();
result = "Update count is " +
result.valueOf(ct);
System.out.println(result);
}
//close connection
con.close();
}
catch(Exception e)
{
System.out.println(e.getMessage());
}
}

}
interogarea mai multor tabele deodata

package j1;

import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;

219
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;
import java.awt.Event;
import java.awt.Point;
import java.awt.*;
import java.net.*;
import java.net.MalformedURLException;
import java.awt.*;
import java.io.DataInputStream;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.net.MalformedURLException;
import java.net.*;
import java.sql.*;

import java.util.*;
import java.io.*;
import java.util.*;
import java.sql.*;
import sun.jdbc.odbc.*;
import java.io.*;

import java.lang.*;
import java.sql.*;
import sun.jdbc.odbc.*;

public class sample9


{
public static void main(String arg[])
{
String invalue;
String outvalue;
String id, name, add1, add2,
add3,city,state,country,post,phone;
int pos, endpos;
try
{
System.out.println("Refreshing company...");
//connect to mSQL database
Class.forName("imaginary.sql.iMsqlDriver");
String url = "jdbc:msql://yasd.com:1112/yasd";
// mSQL connection
Connection con = DriverManager.getConnection(url);
// mSQL statement
Statement stmt = con.createStatement();
// clean out existing data
stmt.executeUpdate("DELETE from company");
//connect to Access database
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
url = "jdbc:odbc:cityzoo";
// Access Connection
Connection con2 =
DriverManager.getConnection(url,"Admin","sql");
// Access Statement
Statement stmt2 = con2.createStatement();
ResultSet rs = stmt2.executeQuery("Select
company_id,"

220
+ "company_name, address_1, address_2,
address_3,"
+ "city, state_cd, country_cd, postal_cd,
phone_nbr "
+ "from company");
// for each line, enter into database
while (rs.next())
{
// get id
id = rs.getString(1);
name = rs.getString(2);
add1= rs.getString(3);
add2=rs.getString(4);
add3=rs.getString(5);
city=rs.getString(6);
state=rs.getString(7);
country=rs.getString(8);
post=rs.getString(9);
phone=rs.getString(10);
// create and execute insert statement
stmt.executeUpdate("insert into company
(company_id, company_name,"
+ "address_1,address_2,address_3, "
+
"city,state_cd,country_cd,postal_cd,phone_nbr) values("
+ id + ",'" + name + "','" + add1 +
"','"
+ add2 + "','"
+ add3 + "','" + city + "','" + state +
"','"
+ country + "','" + post +
"','" + phone + "')");
}
stmt.close();
stmt2.close();
rs.close();
}
catch(Exception e)
{
System.out.println(e.getMessage());
}
}

conectarea la o baza de date

package j1;

import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;

221
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;
import java.awt.Event;
import java.awt.Point;
import java.awt.*;
import java.net.*;
import java.net.MalformedURLException;
import java.awt.*;
import java.io.DataInputStream;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.net.MalformedURLException;
import java.net.*;
import java.sql.*;

import java.util.*;
import java.io.*;
import java.util.*;
import java.sql.*;
import sun.jdbc.odbc.*;
import java.io.*;

import java.lang.*;
import java.sql.*;
import sun.jdbc.odbc.*;
public class sample1
{
public static void main(String arg[])
{
String status;

try
{
//connect to ODBC database
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
String url = "jdbc:odbc:personal";
// connect
Connection con = DriverManager.getConnection(url);
// create Statement object
Statement stmt = con.createStatement();
String sqlselect="SELECT nume
FROM personal";
ResultSet rs =
stmt.executeQuery(sqlselect);
while(rs.next())
{

int marca=rs.getInt("marca");
String nume=rs.getString("nume");
int schimb=rs.getInt("schimb");
System.out.println("marca"+ marca);
}

//close connection
con.close();
}

222
catch(Exception e)
{
System.out.println(e.getMessage());
}
}

//testarea unei baze de date

public class databasestest


{
public static void output_procedure_info(DatabaseMetaData dmd,
String soption)
{
boolean b;

try
{
// are all procedures callable
if (soption.compareTo("callable") == 0)
{
b = dmd.allProceduresAreCallable();
if (b)
System.out.println("You can call
procedures");
else
System.out.println("You cannot call
procedures");
}
// do stored procedures support escape syntax
else
{
b = dmd.supportsStoredProcedures();
if (b)
System.out.println("Stored Procedures
support escape syntax");
else
System.out.println("Stored Procedures
do not support escape syntax");
}
}
catch(SQLException e)
{
System.out.println(e.getMessage());
}

public static void output_table_info(DatabaseMetaData dmd,


String soption)
{
boolean b;
ResultSet rs;
ResultSet rs2;
String tempString = "";
String resultString = "";
String sschema;
try

223
{
// are tables selectable
if (soption.compareTo("selectable") == 0)
{
b = dmd.allTablesAreSelectable();
if (b)
System.out.println("You can select from
all tables");
else
System.out.println("You cannot select
from all tables");
}
// for each schema get table names and types
else if (soption.compareTo("tables") == 0)
{
rs = dmd.getSchemas();
while(rs.next())
{
sschema = rs.getString(1);
System.out.println("Searching Schema "
+ sschema + "\n");
rs2 = dmd.getTables(null,sschema,
"%",null);
while(rs2.next())
{
tempString = rs2.getString(3) + "
";
tempString+= rs2.getString(4);
resultString+= tempString + "\n";
}
}
System.out.println("Tables are \n" +
resultString);
}
}
catch(SQLException e)
{
System.out.println(e.getMessage());
}

}
public static void output_database_info(DatabaseMetaData dmd,
String soption)
{
boolean b;
ResultSet rs;
String s;
String tempString;
String stringResult = " ";
try
{
// get url
if (soption.compareTo("url") == 0)
{
s = dmd.getURL();
System.out.println("URL of database is " +
s);
}
// get user name
else if (soption.compareTo("user") == 0)

224
{
s = dmd.getUserName();
System.out.println("User name is " + s);
}
// get schemas
else if (soption.compareTo("schema") == 0)
{
rs = dmd.getSchemas();
while(rs.next())
{
tempString = rs.getString(1) + "\n";
stringResult+=tempString;
}
System.out.println("Database Schemas are: \n"
+ stringResult);
}
// is database readonly
else if (soption.compareTo("readonly") == 0)
{
b = dmd.isReadOnly();
if (b)
System.out.println("Database is
readonly");
else
System.out.println("Database is not
readonly");
}
// get database catalogs
else
{
rs = dmd.getCatalogs();
while (rs.next())
{

// get catalog
tempString = rs.getString(1) + "\n";
stringResult+=tempString;
}
System.out.println("Catalogs are: \n" +
stringResult);
}
}
catch(SQLException e)
{
System.out.println(e.getMessage());
}
}
public static void output_transaction_info(DatabaseMetaData
dmd,
String soption)
{
boolean b;
try
{
// does database support dm transactions
if (soption.compareTo("dm") == 0)
{
b =
dmd.supportsDataManipulationTransactionsOnly();
if (b)

225
System.out.println("You can use data
manipulation statements");
else
System.out.println("You cannot use data
manipulation statements");
}
// do ddl statements force a commit
else
{
b =
dmd.dataDefinitionCausesTransactionCommit();
if (b)
System.out.println("A data definition
statement will force a commit");
else
System.out.println("A data definition
statement will not force a commit");
}
}
catch(SQLException e)
{
System.out.println(e.getMessage());
}
}
public static void output_column_info(DatabaseMetaData dmd,
String soption)
{
ResultSet rs;
ResultSet rs2;
ResultSet rs3;
String tempString;
String resultString = "";
String sschema;
String stable;
try
{
if (soption.compareTo("columns") == 0)
{
// for each schema
rs = dmd.getSchemas();
while (rs.next())
{
sschema = rs.getString(1);
System.out.println("Searching through
schema " + sschema + "\n");
// for each table
rs2 =
dmd.getTables(null,sschema,"%",null);
while (rs2.next())
{
stable = rs2.getString(3);
System.out.println("Searching
through table " + stable + "\n");
// get and print out columns
rs3 = dmd.getColumns(null,
sschema,stable,"%");
while (rs3.next())
{
tempString =
rs3.getString(3) + " ";

226
tempString+=
rs3.getString(4) + " ";
tempString+=
rs3.getString(6) + "\n";
resultString+= tempString;
}
System.out.println("Columns are :
\n" + resultString + "\n");
}
}
}
}
catch(SQLException e)
{
System.out.println(e.getMessage());
}
}

public static void main(String arg[])


{
try
{
//connect to ODBC database
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
String url = "jdbc:odbc:" + arg[0];
// connect
Connection con =
DriverManager.getConnection(url,arg[1],arg[2]);
// get databasemetadata object
DatabaseMetaData dmd = con.getMetaData();
// get option 1 and 2
String soption = arg[3];
String soption2 = arg[4];
//check argument to see which load to run
if (soption.compareTo("procedures") == 0)
{
// output procedure information
output_procedure_info(dmd,soption2);
}
else if (soption.compareTo("database") == 0)
{
// output database information
output_database_info(dmd,soption2);
}
else if (soption.compareTo("tables") == 0)
{
// output table information
output_table_info(dmd,soption2);
}
else if (soption.compareTo("columns") == 0)
{
// output column information
output_column_info(dmd,soption2);
}
else
{
// output transaction information
output_transaction_info(dmd,soption2);

227
}
//close connection
con.close();
}
catch(Exception e)
{
System.out.println(e.getMessage());
}

}
}

Intrări şi ieşiri
7.1 Introducere
7.1.1 Ce sunt fluxurile?
Majoritatea aplicaţiilor necesită citirea unor Un flux care citeşte date se numeşte flux de
informaţii care se găsesc pe intrare.
o sursă externă sau trimiterea unor informaţii Un flux care scrie date se numeşte flux de
către o destinaţie externă. ieşire.
Informaţia se poate găsi oriunde: într-un fişier Observaţii:
pe disc, în reţea, în memorie Fluxurile sunt canale de comunicaţie seriale pe
sau în alt program şi poate fi de orice tip: date 8 sau 16 biţi.
primitive, obiecte, imagini, Fluxurile sunt unidirecţionale, de la producător
sunete, etc. Pentru a aduce informaţii dintr-un la consumator.
mediu extern, un progam Java Fiecare flux are un singur proces producător şi
trebuie să deschidă un canal de comunicaţie un singur proces consumator.
(flux) de la sursa informaţiilor Intre două procese pot exista oricâte fluxuri,
(fişier, memorie, socket, etc) şi să citească orice proces putând fi atât producator
secvenţial informaţiile respective. cât şi consumator în acelaşi timp, dar pe
Similar, un program poate trimite informaţii fluxuri diferite.
către o destinaţie externă Consumatorul şi producatorul nu comunică
deschizând un canal de comunicaţie (flux) direct printr-o interfaţă de flux
către acea destinaţie şi scriind ci prin intermediul codului Java de tratare a
secvenţial informaţiile respective. fluxurilor.
Indiferent de tipul informaţiilor, citirea/scrierea Clasele şi intefeţele standard pentru lucrul cu
de pe/către un mediu fluxuri se găsesc în pachetul
extern respectă următorul algoritm: java.io. Deci, orice program care necesită
deschide canal comunicatie operaţii de intrare sau ieşire trebuie
while (mai sunt informatii) { să conţină instrucţiunea de import a pachetului
citeste/scrie informatie; java.io:
} import java.io.*;
inchide canal comunicatie; 7.1.2 Clasificarea fluxurilor
Pentru a generaliza, atât sursa externă a unor Există trei tipuri de clasificare a fluxurilor:
date cât şi destinaţia lor • După direcţia canalului de comunicaţie
sunt văzute ca fiind nişte procese care produc, deschis fluxurile se împart în:
respectiv consumă informaţii. – fluxuri de intrare (pentru citirea datelor)
Definiţii: – fluxuri de ieşire (pentru scrierea datelor)
Un flux este un canal de comunicaţie • După tipul de date pe care operează:
unidirecţional între două procese. – fluxuri de octeţi (comunicarea serială se
Un proces care descrie o sursă externă de date realizează pe 8 biţi)
se numeşte proces producător. – fluxuri de caractere (comunicarea serială se
Un proces care descrie o destinaţie externă realizează pe 16 biţi)
pentru date se numeşte proces • După acţiunea lor:
consumator.

228
– fluxuri primare de citire/scriere a datelor (se Superclasele abstracte Reader şi InputStream
ocupă efectiv cu definesc metode similare pentru
citirea/scrierea datelor) citirea datelor.
– fluxuri pentru procesarea datelor Reader InputStream
7.1.3 Ierarhia claselor pentru lucrul cu int read() int read()
fluxuri int read(char buf[]) int read(byte buf[])
Clasele rădăcină pentru ierarhiile ce reprezintă ... ...
fluxuri de caractere sunt: De asemenea, ambele clase pun la dispoziţie
• Reader- pentru fluxuri de intrare şi metode pentru marcarea
• Writer- pentru fluxuri de ieşire. unei locaţii într-un flux, saltul peste un număr
Acestea sunt superclase abstracte pentru toate de poziţii, resetarea poziţiei
clasele ce implementează curente, etc. Acestea sunt însă mai rar folosite
fluxuri specializate pentru citirea/scrierea şi nu vor fi detaliate.
datelor pe 16 biţi şi vor conţine Superclasele abstracte Writer şi OutputStream
metodele comune tuturor. sunt de asemenea paralele,
Ca o regulă generală, toate clasele din aceste definind metode similare pentru scrierea
ierarhii vor avea terminaţia datelor:
Reader sau Writerîn funcţie de tipul lor, cum ar Reader InputStream
fiîn exemplele: FileReader, void write(int c) void write(int c)
BufferedReader, FileWriter, BufferedWriter, void write(char buf[]) void write(byte buf[])
etc. De asemenea, se observ void write(String str) -
ă ca o altă regulă generală, faptul că unui flux ... ...
de intrare XReader îi
Inchiderea oricărui flux se realizează prin
corespunde uzual un flux de ieşire XWriter, metoda close. In cazul în care
însă acest lucru nu este obligatoriu.
aceasta nu este apelată explicit, fluxul va fi
Clasele radacină pentru ierarhia fluxurilor de automatînchis de către colectorul
octeţi sunt:
de gunoaie atunci când nu va mai exista nici o
• InputStream- pentru fluxuri de intrare şi referinţă la el, însă acest lucru
• OutputStream- pentru fluxuri de ieşire. trebuie evitat deoarece, la lucrul cu fluxrui cu
Acestea sunt superclase abstracte pentru clase zonă tampon de memorie,
ce implementează fluxuri datele din memorie vor fi pierdute la
specializate pentru citirea/scrierea datelor pe 8 închiderea fluxului de către gc.
biţi. Ca şi în cazul fluxurilor Metodele referitoare la fluxuri pot genera
pe caractere denumirile claselor vor avea excepţii de tipul IOException
terminaţia superclasei lor: sau derivate din această clasă, tratarea lor fiind
FileInputStream, BufferedInputStream, obligatorie.
FileOutputStream, 7.2 Folosirea fluxurilor
BufferedOutputStream, etc., fiecărui flux de Aşa cum am văzut, fluxurile pot fi împărţite în
intrare XInputStream corespunz funcţie de activitatea lor
ându-i uzual un flux de ieşire XOutputStream, în fluxuri care se ocupă efectiv cu
fără ca acest lucru să citirea/scrierea datelor şi fluxuri pentru
fie obligatoriu. procesarea datelor (de filtrare). In continuare,
Până la un punct, există un paralelism între vom vedea care sunt cele mai
ierarhia claselor pentru fluxuri importante clase din cele două categorii şi la ce
de caractere şi cea pentru fluxurile pe octeţi. folosesc acestea, precum şi
Pentru majoritatea programelor modalităţile de creare şi utilizare a fluxurilor.
este recomandat ca scrierea şi citirea datelor să 7.2.1 Fluxuri primitive
se facă prin intermediul
Fluxurile primitive sunt responsabile cu
fluxurilor de caractere, deoarece acestea permit citirea/scrierea efectivă a datelor,
manipularea caracterelor
punând la dispoziţie implementări ale
Unicode în timp ce fluxurile de octeţi permit metodelor de bază read, respectiv
doar lucrul pe 8 biti -
write, definite în superclase. In funcţie de tipul
caractere ASCII. sursei datelor, ele pot fi
7.1.4 Metode comune fluxurilor împărţite astfel:
• Fişier

229
FileReader, FileWriter a informaţiilor, reducând astfel numărul de
FileInputStream, FileOutputStream accesări la dispozitivul ce
Numite şi fluxuri fişier, acestea sunt folosite reprezintă sursa/destinaţia originală a datelor.
pentru citirea datelor Sunt mult mai eficiente
dintr-un fişier, respectiv scrierea datelor într-un decât fluxurile fără bu_er şi din acest motiv se
fişier şi vor fi analizate recomandă folosirea lor
într-o secţiune separată (vezi ”Fluxuri pentru ori de câte ori este posibil (vezi ”Citirea şi
lucrul cu fişiere”). scrierea cu zona tampon”).
• Memorie • Filtrare
CharArrayReader, CharArrayWriter FilterReader, FilterWriter
ByteArrayInputStream, FilterInputStream, FilterOutputStream
ByteArrayOutputStream Sunt clase abstracte ce definesc o interfaţă
Aceste fluxuri folosesc pentru scrierea/citirea comună pentru fluxuri care
informaţiilor în/din memorie filtrează automat datele citite sau scrise (vezi
şi sunt create pe un vector existent deja. Cu ”Fluxuri pentru filtrare”).
alte cuvinte, permit • Conversie octeţi-caractere
tratarea vectorilor ca sursă/destinaţie pentru InputStreamReader, OutputStreamWriter
crearea unor fluxuri de Formează o punte de legatură între fluxurile de
intrare/ieşire. caractere şi fluxurile
StringReader, StringWriter de octeţi. Un flux InputStreamReader citeşte
Permit tratarea şirurilor de caractere aflateîn octeţi dintr-un flux
memorie ca sursă/destinaţie InputStream şi îi converteşte la caractere,
pentru crearea de fluxuri. folosind codificarea standard
• Pipe a caracterelor sau o codificare specificată de
PipedReader, PipedWriter program. Similar,
PipedInputStream, PipedOutputStream un flux OutputStreamWriter converteşte
caractere în octeţi şi trimite
Implementează componentele de intrare/ieşire
ale unei conducte de rezutatul către un flux de tipul OutputStream.
date (pipe). Pipe-urile sunt folosite pentru a • Concatenare
canaliza ieşirea unui program SequenceInputStream
sau fir de execuţie către intrarea altui program Concatenează mai multe fluxuri de intrare într-
sau fir de execuţie. unul singur (vezi ”Concatenarea
7.2.2 Fluxuri de procesare fişierelor”).
Fluxurile de procesare (sau de filtrare) sunt • Serializare
responsabile cu preluarea datelor ObjectInputStream, ObjectOutputStream
de la un flux primitiv şi procesarea acestora Sunt folosite pentru serializarea obiectelor
pentru a le oferi într-o altă formă, (vezi ”Serializarea obiectelor”).
mai utilă dintr-un anumit punct de vedere. De • Conversie tipuri de date
exemplu, BufferedReader DataInputStream, DataOutputStream
poate prelua date de la un flux FileReader şi să Folosite la scrierea/citirea datelor de tip
ofere informaţia dintr-un primitiv într-un format binar,
fişier linie cu linie. Fiind primitiv, FileReader independent de maşina pe care se lucrează
nu putea citi decât caracter (vezi ”Folosirea claselor
cu caracter. Un flux de procesare nu poate fi DataInputStream şi DataOutputStream”).
folosit decât împreună cu un • Numărare
flux primitiv. LineNumberReader
Clasele ce descriu aceste fluxuri pot fi LineNumberInputStream
împartite în funcţie de tipul de
Oferă şi posibilitatea de numărare automată a
procesare pe care îl efectueaza astfel: liniilor citite de la un
• ”Bu_erizare” flux de intrare.
BufferedReader, BufferedWriter • Citire în avans
BufferedInputStream, BufferedOutputStream PushbackReader
Sunt folosite pentru a introduce un bu_er în PushbackInputStream
procesul de citire/scriere

230
Sunt fluxuri de intrare care au un bu_er de 1- Aşadar, crearea unui flux pentru procesarea
caracter(octet) în care datelor are formatul general:
este citit în avans şi caracterul (octetul) care FluxProcesare numeFlux = new
urmează celui curent citit. FluxProcesare(fluxPrimitiv);
• Afişare In general, fluxurile pot fi compuse în
PrintWriter succesiuni oricât de lungi:
PrintStream DataInputStream in = new DataInputStream(
Oferă metode convenabile pentru afisarea new BufferedInputStream(
informaţiilor. new FileInputStream("fisier.dat")));
7.2.3 Crearea unui flux 7.2.4 Fluxuri pentru lucrul cu fişiere
Orice flux este un obiect al clasei ce Fluxurile pentru lucrul cu fişiere sunt cele mai
implementează fluxul respectiv. Crearea usor de înteles, întrucât
unui flux se realizează aşadar similar cu operaţia lor de bază este citirea, respectiv
crearea obiectelor, prin instrucţiunea scrierea unui caracter sau octet
new şi invocarea unui constructor dintr-un sauîntr-un fişier specificat uzual prin
corespunzător al clasei respective: numele său complet sau relativ
Exemple: la directorul curent.
//crearea unui flux de intrare pe caractere După cum am văzut deja, clasele care
FileReader in = new FileReader("fisier.txt"); implementează aceste fluxuri sunt
//crearea unui flux de iesire pe caractere următoarele:
FileWriter out = new FileWriter("fisier.txt"); FileReader, FileWriter - caractere
//crearea unui flux de intrare pe octeti FileInputStream, FileOutputStream - octeti
FileInputStream in = new Constructorii acestor clase acceptă ca
FileInputStream("fisier.dat"); argument un obiect care să specifice
//crearea unui flux de iesire pe octeti un anume fişier. Acesta poate fi un şir de
FileOutputStrem out = new caractere, on obiect de tip File
FileOutputStream("fisier.dat"); sau un obiect de tip FileDesciptor (vezi ”Clasa
Aşadar, crearea unui flux primitiv de date care File”).
citeşte/scrie informaţii de Constructorii clasei FileReader sunt:
la un dispozitiv extern are formatul general: public FileReader(String fileName)
FluxPrimitiv numeFlux = new throws FileNotFoundException
FluxPrimitiv(dispozitivExtern); public FileReader(File file)
Fluxurile de procesare nu pot exista de sine throws FileNotFoundException
stătătoare ci se suprapun pe public FileReader(FileDescriptor fd)
un flux primitiv de citire/scriere a datelor. Din Constructorii clasei FileWriter:
acest motiv, constructorii public FileWriter(String fileName)
claselor pentru fluxurile de procesare nu throws IOException
primesc ca argument un dispozitiv
public FileWriter(File file)
extern de memorare a datelor ci o referinţa la
throws IOException
un flux primitiv responsabil
public FileWriter(FileDescriptor fd)
cu citirea/scrierea efectivă a datelor:
public FileWriter(String fileName, boolean
Exemple:
append)
//crearea unui flux de intrare printr-un buffer
throws IOException
BufferedReader in = new BufferedReader(
Cei mai uzuali constructori sunt cei care
new FileReader("fisier.txt")); primesc ca argument numele
//echivalent cu fişierului. Aceştia pot provoca excepţii de tipul
FileReader fr = new FileReader("fisier.txt"); FileNotFoundException în
BufferedReader in = new BufferedReader(fr); cazul în care fişierul cu numele specificat nu
//crearea unui flux de iesire printr-un buffer există. Din acest motiv orice
BufferedWriter out = new BufferedWriter( creare a unui flux de acest tip trebuie făcută
new FileWriter("fisier.txt"))); într-un bloc try-catch sau
//echivalent cu metoda în care sunt create fluxurile respective
FileWriter fo = new FileWriter("fisier.txt"); trebuie să arunce excepţiile
BufferedWriter out = new BufferedWriter(fo);

231
de tipul FileNotFoundException sau de tipul mult mai eficiente decât fluxurile fără bu_er şi
superclasei IOException. din acest motiv se recomandă
Să considerăm ca exemplu un program care folosirea lor ori de câte ori este posibil.
copie conţinutul unui fişier Clasa BufferedReader citeşte în avans date şi
cu numele ”in.txt” într-un alt fişier cu numele le memorează într-o zonă
”out.txt”. Ambele fişiere sunt tampon. Atunci când se execută o operaţie de
considerate în directorul curent. citire, caracterul va fi preluat
Listing 7.1: Copierea unui fisier din bu_er. In cazul în care bu_er-ul este gol,
import java .io .*; citirea se face direct din
public class Copiere { flux şi, odată cu citirea caracterului, vor fi
public static void main ( String [] args ) { memorati în bu_er şi caracterele
try { care îi urmează. Evident, BufferedInputStream
funcţionează după acelaşi
FileReader in = new FileReader ("in.txt ");
principiu, singura diferenţă fiind faptul că sunt
FileWriter out = new FileWriter ("out .txt ");
citiţi octeţi.
int c;
Similar lucreaza şi clasele BufferedWriter şi
while ((c = in. read ()) != -1) BufferedOutputStream.
out . write (c); La operaţiile de scriere datele scrise nu vor
in. close (); ajunge direct la destinaţie, ci vor
out . close (); fi memorate jntr-un bu_er de o anumită
} catch ( IOException e) { dimensiune. Atunci când bu_erul
System . err. println (" Eroare la operatiile cu este plin, conţinutul acestuia va fi transferat
fisiere !"); automat la destinaţie.
e. printStackTrace (); Fluxurile de citire/scriere cu bu_er sunt fluxuri
} de procesare şi sunt
} folosite prin suprapunere cu alte fluxuri, dintre
} care obligatoriu unul este
In cazul în care vom lansa aplicaţia iar în primitiv.
directorul curent nu există un BufferedOutputStream out = new
fişier cu numele ”in.txt”, va fi generată o BufferedOutputStream(
excepţie de tipul new FileOutputStream("out.dat"), 1024)
FileNotFoundException. Aceasta va fi prinsă //1024 este dimensiunea bufferului
de program deoarece, IOException Constructorii cei mai folosiţi ai acestor clase
este superclasă pentru FileNotFoundException. sunt următorii:
Dacă există fişierul ”in.txt”, aplicaţia va crea BufferedReader(Reader in)
un nou fişier ”out.txt” în care BufferedReader(Reader in, int dim_buffer)
va fi copiat conţinutul primului. Dacă există BufferedWriter(Writer out)
deja fişierul ”out.txt” el va fi re- BufferedWriter(Writer out, int dim_buffer)
scris. Dacă doream să facem operaţia de BufferedInputStream(InputStream in)
adăugare(append) şi nu de rescriere BufferedInputStream(InputStream in, int
pentru fişierul ”out.txt” foloseam: dim_buffer)
FileWriter out = new FileWriter("out.txt", BufferedOutputStream(OutputStream out)
true); BufferedOutputStream(OutputStream out, int
4.2.5 Citirea şi scrierea cu buffer dim_buffer)
Clasele pentru citirea/scrierea cu zona tampon In cazul constructorilorîn care dimensiunea
sunt: bu_er-ului nu este specificată,
BufferedReader, BufferedWriter - caractere aceasta primeşte valoarea implicită de 512
BufferedInputStream, BufferedOutputStream - octeţi (caractere).
octeti Metodele acestor clase sunt cele uzuale de
Sunt folosite pentru a introduce un bu_er (zonă tipul read şi write. Pe lânga
de memorie) în procesul acestea, clasele pentru scriere prin bu_er mai
de citire/scriere a informaţiilor, reducând astfel au şi metoda flush care goleşte
numarul de accesări ale explicit zona tampon, chiar dacă aceasta nu
dispozitivului ce reprezintă sursa/destinaţia este plină.
atelor. Din acest motiv, sunt BufferedWriter out = new BufferedWriter(

232
new FileWriter("out.dat"), 1024) Exemplul cel mai elocvent de folosirea a
//am creat un flux cu buffer de 1024 octeti acestei clase este concatenarea a
for(int i=0; i<1000; i++) două sau mai multor fişiere:
out.write(i); Listing 4.2: Concatenarea a două fişiere
//bufferul nu este plin, in fisier nu s-a scris /* Concatenarea a doua fisiere
nimic ale caror nume sunt primite de la linia de
out.flush(); comanda .
//bufferul este golit, datele se scriu in fisier Rezultatul concatenarii este afisat pe ecran .
Metoda readLine */
Este specifică fluxurilor de citire cu bu_er şi import java .io .*;
permite citirea linie cu linie a public class Concatenare {
datelor de intrare. O linie reprezintă o public static void main ( String args []) {
succesiune de caractere terminată cu if ( args . length <= 1) {
simbolul pentru sfârşit de linie, dependent de System . out. println (" Argumente insuficiente
platforma de lucru. Acesta !");
este reprezentat în Java prin secvenţa escape ’\ System . exit ( -1);
n’; }
BufferedReader br = new BufferedReader(new try {
FileReader("in"))
FileInputStream f1 = new FileInputStream
String linie; ( args [0]) ;
while ((linie = br.readLine()) != null) { FileInputStream f2 = new FileInputStream
... ( args [1]) ;
//proceseaza linie SequenceInputStream s = new
} SequenceInputStream (f1 , f2)
br.close(); ;
} int c;
7.2.6 Concatenarea fluxurilor while ((c = s. read ()) != -1)
Clasa SequenceInputStream permite unei System . out. print (( char )c);
aplicatii să combine serial mai s. close ();
multe fluxuri de intrare astfel încât acestea să // f1 si f2 sunt inchise automat
apară ca un singur flux de } catch ( IOException e) {
intrare. Citirea datelor dintr-un astfel de flux se e. printStackTrace ();
face astfel: se citeşte din
}
primul flux de intrare specificat pâna când se
}
ajunge la sfârsitul acestuia,
}
după care primul flux de intrare este închis şi
se deschide automat următorul Pentru concatenarea mai multor fişiere există
două variante:
flux de intrare din care se vor citi în continuare
datele, după care procesul se • folosirea unei enumerări - primul constructor
(vezi ”Colecţii”);
repetă pâna la terminarea tuturor fluxurilor de
intrare. • concatenarea pe rând a acestora folosind al 2-
lea constructor; concatenarea
Constructorii acestei clase sunt:
a 3 fişiere va construi un flux de intrare astfel:
SequenceInputStream(Enumeration e)
FileInputStream f1 = new
SequenceInputStream(InputStream s1,
FileInputStream(args[0]);
InputStream s2)
FileInputStream f2 = new
Primul construieste un flux secvential dintr-o
FileInputStream(args[1]);
mulţime de fluxuri de intrare.
FileInputStream f3 = new
Fiecare obiect în enumerarea primită ca
FileInputStream(args[2]);
parametru trebuie să fie de
SequenceInputStream s = new
tipul InputStream.
SequenceInputStream(
Cel de-al doilea construieşte un flux de intrare
f1, new SequenceInputStream(f2, f3));
care combină doar două fluxuri
7.2.7 Fluxuri pentru filtrarea datelor
s1 şi s2, primul flux citit fiind s1.
Un flux de filtrare se ataşează altui flux pentru
a filtra datele care sunt

233
citite/scrise de către acel flux. Clasele pentru respectiv DataOutput. Acestea definesc
filtrarea datelor superclasele metodele pe care trebuie să le pună la
abstracte: dispoziţie în vederea citireii/scrierii datelor de
• FilterInputStream - pentru filtrarea fluxurilor tip primitiv. Cele mai folosite
de intrare şi metode, altele decât cele comune tuturor
• FilterOutputStream - pentru filtrarea fluxurilor, sunt date în tabelul de
fluxurilor de ieşire. mai jos:
Cele mai importante fluxruri pentru filtrarea DataInputStream DataOutputStream
datelor sunt implementate readBoolean writeBoolean
de clasele: readByte writeByte
DataInputStream, DataOutputStream readChar writeChar
BufferedInputStream, BufferedOutputStream readDouble writeDouble
LineNumberInputStream readFloat writeFloat
PushbackInputStream readInt writeInt
PrintStream readLong writeLong
Observaţi că toate aceste clase descriu fluxuri readShort writeShort
de octeţi. readUTF writeUTF
Filtrarea datelor nu trebuie văzută ca o metodă Aceste metode au denumirile generice de
de a elimina anumiţi readXXX şi writeXXX, specifi-
octeti dintr-un flux ci de a transforma aceşti cate de interfetele DataInput şi DataOutput şi
octeţi în date care să poată fi pot provoca excepţii de tipul
interpretate sub altă formă. Aşa cum am văzut IOException. Denumirile lor sunt sugestive
la citirea/scrierea cu zonă pentru tipul de date pe care îl
tampon, clasele de filtrare prelucrează. mai puţin readUTF şi writeUTF
BufferedInputStream şi BufferedOutputStream care se ocupă cu obiecte de tip
colectează datele unui flux într-un bu_er, String, fiind singurul tip referinţă permis de
urmând ca citirea/scrierea să se aceste clase.
facă prin intermediu acelui bu_er. Scrierea datelor folosind fluxuri de acest tip se
Aşadar, fluxurile de filtrare nu elimină date face în format binar, ceea
citite sau scrise de un anumit ce înseamnă că un fişier în care au fost scrise
flux, ci introduc o noua modalitate de informaţii folosind metode
manipulare a lor, ele mai fiind numite writeXXX nu va putea fi citit decât prin
şi fluxuri de procesare. Din acest motiv, metode readXXX.
fluxurile de filtrare vor conţine Transformarea unei valori în format binar se
anumite metode specializate pentru numeşte serializare. Clasele
citirea/scrierea datelor, altele decât cele DataInputStream şi DataOutputStream permit
comune tuturor fluxurilor. De exemplu, clasa serializarea tipurilor primitive
BufferedInputStream pune şi a şirurilor de caractere. Serializarea
la dispoziţie metoda readLine pentru citirea celorlalte tipuri referinţă va fi
unei linii din fluxul de intrare. făcută prin intermediul altor clase, cum ar fi
Folosirea fluxurilor de filtrare se face prin ObjectInputStream şi
ataşarea lor de un flux care se ObjectOutputStream (vezi ”Serializarea
ocupă efectiv de citirea/scrierea datelor: obiectelor”).
FluxFiltrare numeFlux = new 4.3 Intrări şi ieşiri formatate
FluxFiltrare(referintaAltFlux); Incepând cu versiunea 1.5, limbajul Java pune
7.2.8 Clasele DataInputStream şi la dispoziţii modalităţi simplificate
DataOutputStream pentru afişarea formatată a unor informaţii,
Aceste clase oferă metode prin care un flux nu respectiv pentru citirea
mai este văzut ca o însiruire de date formatate de la tastatură.
de octeţi, ci de date primitive. Prin urmare, vor 7.3.1 Intrări formatate
furniza metode pentru
Clasa java.util.Scanner oferă o soluţie simplă
citirea şi scrierea datelor la nivel de tip primitiv pentru formatarea unor informaţii
şi nu la nivel de octet.
citite de pe un flux de intrare fie pe octeţi, fie
Clasele care oferă un astfel de suport pe caractere, sau chiar dintr-un
implementează interfeţele DataInput,

234
obiect de tip File. Pentru a citi de la tastatură de ieşire.
vom specifica ca argument catch(Exception e) {
al constructorului fluxul System.in: System.err.println("Exceptie:" + e);
Scanner s = Scanner.create(System.in); }
String nume = s.next(); Fluxurile de ieşire pot fi folosite aşadar fără
int varsta = s.nextInt(); probleme deoarece tipul lor
double salariu = s.nextDouble(); este PrintStream, clasă concretă pentru scrierea
s.close(); datelor. In schimb, fluxul
7.3.2 Ieşiri formatate standard de intrare System.out este de tip
Clasele PrintStream şi PrintWriter pun la InputStream, care este o clasă
dispoziţiile, pe lângă metodele abstractă, deci pentru a-l putea utiliza eficient
print, println care ofereau posibilitatea de a va trebui sa-l folosimîmpreuna
afişa un şir de caractere, şi cu un flux de procesare(filtrare) care să
metodele format, printf (echivalente) ce permit permită citirea facilă a datelor.
afişarea formatată a unor 7.4.2 Citirea datelor de la tastatură
variabile. Uzual, vom dori să folosim metoda readLine
System.out.printf("%s %8.2f %2d %n", nume, pentru citirea datelor de la
salariu, varsta); tastatura şi din acest motiv vom folosi intrarea
Formatarea şirurilor de caractere se bazează pe standard împreună cu o clasă
clasa java.util.Formatter. de procesare care oferă această metodă.
4.4 Fluxuri standard de intrare şi ieşire Exemplul tipic este:
Mergând pe linia introdusă de sistemul de BufferedReader stdin = new BufferedReader(
operare UNIX, orice program Java new InputStreamReader(System.in));
are : System.out.print("Introduceti o linie:");
• o intrare standard String linie = stdin.readLine()
• o ieşire standard System.out.println(linie);
• o ieşire standard pentru erori In exemplul următor este prezentat un program
In general, intrarea standard este tastatura iar care afişeaza liniile introduse
ieşirea standard este ecranul. de la tastatură până în momentul în care se
Intrarea şi ieşirea standard sunt reprezentate de introduce linia ”exit” sau
obiecte pre-create ce o linie vidă şi menţioneazădacă şirul respectiv
descriu fluxuri de date care comunică cu reprezintă un număr sau nu.
dispozitivele standard ale sistemului. Listing 7.3: Citirea datelor de la tastatură
Aceste obiecte sunt definite publice în clasa /* Citeste siruri de la tastatura si verifica
System şi sunt: daca reprezinta numere sau nu
• System.in - fluxul standar de intrare, de tip */
InputStream import java .io .*;
• System.out - fluxul standar de ieşire, de tip public class EsteNumar {
PrintStream public static void main ( String [] args ) {
• System.err - fluxul standar pentru erori, de tip BufferedReader stdin = new BufferedReader (
PrintStream
new InputStreamReader ( System .in));
7.4.1 Afisarea informaţiilor pe ecran
try {
Am văzut deja numeroase exemple de utilizare
while ( true ) {
a fluxului standard de ieşire,
String s = stdin . readLine ();
el fiind folosit la afişarea oricăror rezultate pe
ecran (în modul consola): if (s. equals (" exit ") || s. length () ==0)
System.out.print (argument); break ;
System.out.println(argument); System . out. print (s);
System.out.printf (format, argumente...); try {
System.out.format (format, argumente...); Double . parseDouble (s);
Fluxul standard pentru afişarea erorilor se System . out. println (": DA");
foloseşte similar şi apare uzual } catch ( NumberFormatException e) {
în secvenţele de tratare a excepţiilor. Implicit, System . out. println (": NU");
este acelaşi cu fluxul standard }

235
} try {
} catch ( IOException e) { BufferedInputStream in = new
System . err. println (" Eroare la intrarea BufferedInputStream (
standard !"); new FileInputStream (" intrare .txt"));
e. printStackTrace (); PrintStream out = new PrintStream (
} new FileOutputStream (" rezultate .txt"));
} PrintStream err = new PrintStream (
} new FileOutputStream (" erori .txt"));
Incepând cu versiunea 1.5, varianta cea mai System . setIn (in);
comodă de citire a datelor System . setOut (out);
de la tastatură este folosirea clasei System . setErr (err);
java.util.Scanner. BufferedReader br = new BufferedReader (
7.4.3 Redirectarea fluxurilor standard new InputStreamReader ( System .in));
Redirectarea fluxurilor standard presupune String s;
stabilirea unei alte surse decât
while ((s = br. readLine ()) != null ) {
tastatura pentru citirea datelor, respectiv alte
/* Liniile vor fi citite din fisierul intrare .txt
destinaţii decât ecranul pentru
si vor fi scrise in fisierul rezultate .txt
cele două fluxuri de ieşire. In clasa System
există următoarele metode statice */
care realizează acest lucru: System . out. println (s);
setIn(InputStream) - redirectare intrare }
setOut(PrintStream) - redirectare iesire // Aruncam fortat o exceptie
setErr(PrintStream) - redirectare erori throw new IOException (" Test ");
Redirectarea ieşirii este utilă în special atunci } catch ( IOException e) {
când sunt afişate foarte multe /* Daca apar exceptii ,
date pe ecran. Putem redirecta afisarea către un ele vor fi scrise in fisierul erori .txt
fişier pe care să-l citim după */
execuţia programului. Secvenţa clasică de System . err. println (" Eroare intrare /
redirectare a ieşirii este către un iesire !");
fişier este: e. printStackTrace ();
PrintStream fis = new PrintStream( }
new FileOutputStream("rezultate.txt"))); }
System.setOut(fis); }
Redirectarea erorilor într-un fişier poate fi de 7.4.4 Analiza lexicală pe fluxuri (clasa
asemenea utilă şi se face într-o StreamTokenizer)
manieră similară: Clasa StreamTokenizer procesează un flux de
PrintStream fis = new PrintStream( intrare de orice tip şiîlîmparte
new FileOutputStream("erori.txt"))); în ”atomi lexicali”. Rezultatul va consta în
System.setErr(fis); faptul că în loc să se citească
Redirectarea intrării poate fi folositoare pentru octeţi sau caractere, se vor citi, pe rând, atomii
un program în mod consol lexicali ai fluxului respectiv.
ă care primeşte mai multe valori de intrare. Printr-un atom lexical se în]elege în general:
Pentru a nu le scrie de la • un identificator (un şir care nu este între
tastatură de fiecare dată în timpul testării ghilimele)
programului, ele pot fi puse întrun • un numar
fişier, redirectând intrarea standard către acel • un şir de caractere
fişier. In momentul când • un comentariu
testarea programului a luat sfârsit redirectarea • un separator
poate fi eliminată, datele fiind Atomii lexicali sunt despărţiti între ei de
cerute din nou de la tastatură. separatori. Implicit, aceşti separatori
Listing 7.4: Exemplu de folosire a redirectării: sunt cei obişnuţi: spaţiu, tab, virgulă, punct şi
import java .io .*; virgula, etc., însă pot fi
class Redirectare { schimbaţi prin diverse metode ale clasei.
public static void main ( String [] args ) { Constructorii clasei sunt:

236
public StreamTokenizer(Reader r) Aşadar, modul de utilizare tipic pentru un
public StreamTokenizer(InputStream is) analizor lexical este într-o bucla
Identificarea tipului şi valorii unui atom lexical ”while”, în care se citesc atomii unul câte unul
se face prin intermediul cu metoda nextToken,
variabilelor: pâna se ajunge la sfârsitul fluxului (TT EOF).
• TT EOF - atom ce marchează sfâarşitul In cadrul buclei ”while” se determin
fluxului ă tipul atomul curent curent (întors de metoda
• TT EOL - atom ce marchează sfârşitul unei nextToken) şi apoi se află
linii valoarea numerică sau şirul de caractere
• TT NUMBER - atom de tip număr corespunzător atomului respectiv.
• TT WORD- atom de tip cuvânt In cazul în care tipul atomilor nu ne
interesează, este mai simplu să
• ttype- tipul ultimului atom citit din flux
citim fluxul linie cu linie şi să folosim clasa
• nval- valoarea unui atom numeric
StringTokenizer, care realizează
• sval - valoarea unui atom de tip cuvânt
împărţirea unui şir de caractere în atomi
Citirea atomilor din flux se face cu metoda lexicali, sau metoda split a clasei
nextToken(), care returneză
String.
tipul atomului lexical citit şi scrie în variabilele
7.5 Clasa RandomAccesFile (fişiere cu acces
nval sau sval valoarea corespunzato
direct)
ăre atomului.
După cum am văzut, fluxurile sunt procese
Exemplul tipic de folosire a unui analizor secvenţiale de intrare/ieşire.
lexical este citirea unei secvenţe
Acestea sunt adecvate pentru lucrul cu medii
de numere şi şiruri aflate într-un fişier sau secvenţiale de memorare a
primite de la tastatură:
datelor, cum ar fi banda magnetică sau pentru
Listing 7.5: Citirea unor atomi lexicali dintr-un transmiterea informaţiilor
fisier
prin reţea, desi sunt foarte utile şi pentru
/* Citirea unei secvente de numere si siruri dispozitive în care informaţia poate
dintr -un fisier specificat fi accesată direct.
si afisarea tipului si valorii lor Clasa RandomAccesFile are următoarele
*/ caracteristici:
import java .io .*; • permite accesul nesecvenţial (direct) la
public class CitireAtomi { conţinutul unui fişier;
public static void main ( String args []) throws • este o clasă de sine stătătoare, subclasă
IOException { directă a clasei Object;
BufferedReader br = new BufferedReader • se găseşte în pachetul java.io;
( new FileReader (" • implementează interfeţele DataInput şi
fisier . txt")); DataOutput, ceea ce înseamna
StreamTokenizer st = new StreamTokenizer ca sunt disponibile metode de tipul readXXX,
(br); writeXXX, întocmai ca
int tip = st. nextToken (); la clasele DataInputStream şi
// Se citeste primul atom lexical DataOutputStream;
while (tip != StreamTokenizer . TT_EOF ) { • permite atât citirea cât şi scriere din/in fişiere
switch (tip) { cu acces direct;
case StreamTokenizer . TT_WORD : • permite specificarea modului de acces al unui
System . out. println (" Cuvant : " + st. sval ); fişier (read-only, readwrite).
break ; Constructorii acestei clase sunt:
case StreamTokenizer . TT_NUMBER : RandomAccessFile(StringnumeFisier,
StringmodAcces)
System . out. println (" Numar : " + st. nval );
throws IOException
}
RandomAccessFile(StringnumeFisier,
tip = st. nextToken ();
StringmodAcces)
// Trecem la urmatorul atom
throws IOException
}
unde modAcces poate fi:
}
• ”r” - fişierul este deschis numai pentru citire
} (read-only)

237
• ”rw” - fişierul este deschis pentru citire şi permit accesul la fişiere acceptă ca argument
scriere (read-write) un obiect de tip File în locul
Exemple: unui şir ce reprezintă numele fişierului
RandomAccesFile f1 = new respectiv.
RandomAccessFile("fisier.txt", "r"); File f = new File("fisier.txt");
//deschide un fisier pentru citire FileInputStream in = new FileInputStream(f)
RandomAccesFile f2 = new Cel mai uzual constructor al clasei File este:
RandomAccessFile("fisier.txt", "rw"); public File(String numeFisier)
//deschide un fisier pentru scriere si citire Metodele mai importante ale clasei File au
Clasa RandomAccesFile suportă noţiunea de denumiri sugestive şi vor fi
pointer de fişier. Acesta este prezentate prin intermediul exemplului următor
un indicator ce specifică poziţia curentă în care listează fişierele şi subdirectoarele
fişier. La deschiderea unui fişier unui director specificat şi, pentru fiecare din
pointerul are valoarea 0, indicând începutul ele afişează diverse
fişierului. Apeluri la metodele informaţii:
de citire/scrirere deplasează pointerul fişierului Listing 7.6: Listarea conţinutului unui director
cu numărul de octeţi citiţi /* Programul listeaza fisierele si
sau scrişi de metodele respective. subdirectoarele unui
In plus faţăde metodele de tip read şi write director .
clasa pune la dispozitie şi Pentru fiecare din ele vor fi afisate diverse
metode pentru controlul poziţiei pointerului de informatii .
fişier. Acestea sunt: Numele directorului este primit ca argument de
• skipBytes - mută pointerul fişierului înainte la
cu un număr specificat de linia de comanda , sau este directorul curent .
octeţi */
• seek - poziţioneaza pointerului fişierului import java .io .*;
înaintea unui octet specificat
import java . util .*;
• getFilePointer - returnează poziţia pointerului
public class ListareDirector {
de fişier.
private static void info ( File f) {
7.6 Clasa File
// Afiseaza informatii despre un fisier sau
Clasa File nu se referă doar la un fişier ci poate
director
reprezenta fie un fişier
String nume = f. getName ();
anume, fie multimea fişierelor dintr-un
director. if(f. isFile ())
Specificarea unui fişier/director se face prin System . out. println (" Fisier : " + nume );
specificarea căii absolute spre else
acel fişier sau a căii relative faţă de directorul if(f. isDirectory ())
curent. Acestea trebuie să respecte System . out. println (" Director : " + nume );
convenţiile de specificare a căilor şi numelor System . out. println (
fişierelor de pe platforma " Cale absoluta : " + f. getAbsolutePath () +
de lucru. "\n Poate citi : " + f. canRead () +
Utilitate clasei File constă în furnizarea unei "\n Poate scrie : " + f. canWrite () +
modalităţi de a abstractiza "\n Parinte : " + f. getParent () +
dependenţele cailor şi numelor fişierelor faţăde "\n Cale : " + f. getPath () +
maşina gazdă, precum şi "\n Lungime : " + f. length () +
punerea la dispoziţie a unor metode pentru "\n Data ultimei modificari : " +
lucrul cu fisere şi directoare la
new Date (f. lastModified ()));
nivelul sistemului de operare.
System . out. println (" --------------");
Astfel, în această clasă vom găsi metode pentru
}
testarea existenţei, ştergerea,
public static void main ( String [] args ) {
redenumirea unui fişier sau director, crearea
unui director, listarea fişierelor String nume ;
dintr-un director, etc. if ( args . length == 0)
Trebuie menţionat şi faptul că majoritatea nume = "."; // directorul curent
constructorilor fluxurilor care else

238
nume = args [0]; } catch ( Exception e) {
try { e. printStackTrace ();
File director = new File ( nume ); }
File [] continut = director . listFiles (); }
for (int i = 0; i < continut . length ; i ++) }
info ( continut [i]);
-----------------------------------------------------------------------------
Interfeţe
8.1 Introducere şi sunt separate prin virgulă. (vezi ”Moştenirea
8.1.1 Ce este o interfaţă ? multiplă prin intermediul
Interfeţele duc conceptul de clasă abstractă cu interfeţelor”).
un pas înainte prin eliminarea Corpul unei interfeţe poate conţine:
oricăror implementări de metode, punând în • constante: acestea pot fi sau nu declarate cu
practică unul din conceptele modificatorii public,
programării orientate obiect şi anume cel de static şi final care sunt impliciţi, nici un alt
separare a modelului unui obiect modificator neputând
(interfaţă) de implementarea sa. Aşadar, o apărea în declaraţia unei variabile dintr-o
interfaţă poate fi privita ca un interfaţă. Constantele unei
protocol de comunicare între obiecte. interfeţe trebuie obligatoriu iniţializate.
O interfaţă Java defineşte un set de metode dar interface Exemplu {
nu specifică nici o implementare int MAX = 100;
pentru ele. O clasă care implementează o // Echivalent cu:
interfaţă trebuie obligatoriu public static final int MAX = 100;
să specifice implementări pentru toate int MAX;
metodele interfeţei, supunându-se
// Incorect, lipseste initializarea
aşadar unui anumit comportament.
private int x = 1;
Definiţie
// Incorect, modificator nepermis
O interfaţă este o colecţie de metode fără
}
implementare şi declaraţii de
• metode fără implementare: acestea pot fi sau
constante.
nu declarate cu modificatorul
Interfeţele permit, alături de clase, definirea
public, care este implicit; nici un alt
unor noi tipuri de date.
modificator nu poate
8.2 Folosirea interfeţelor
apărea în declaraţia unei metode a unei
8.2.1 Definirea unei interfeţe interfeţe.
Definirea unei interfeţe se face prin interface Exemplu {
intermediul cuvântului cheie interface:
void metoda();
[public] interface NumeInterfata
// Echivalent cu:
[extends SuperInterfata1, SuperInterfata2...]
public void metoda();
{
protected void metoda2();
/* Corpul interfetei:
// Incorect, modificator nepermis
Declaratii de constane
Atenţie
Declaratii de metode abstracte
• Variabilele unei interfeţe sunt implicit
*/ publice chiar dacă nu sunt declarate
} cu modificatorul public.
O interfaţă poate avea un singur modificator şi • Variabilele unei interfeţe sunt implicit
anume public. O interfaţă constante chiar dacă nu sunt
publică este accesibilă tuturor claselor, declarate cu modificatorii static şi final.
indiferent de pachetul din care fac
• Metodele unei interfeţe sunt implicit publice
parte, implicit nivelul de acces fiind doar la chiar dacă nu sunt declarate
nivelul pachetului din care face
cu modificatorul public.
parte interfaţa.
• In variantele mai vechi de Java era permis şi
O interfaţă poate extinde oricâte interfeţe. modificatorul abstract
Acestea se numesc superinterfeţe

239
în declaratia interfeţei şi în declaraţiile • empty - testează dacă stiva este vidă
metodelor, însă acest lucru nu • toString - returnează conţinutul stivei sub
mai este valabil, deoarece atât interfaţa cât şi forma unui şir de caractere.
metodele sale nu pot fi Din punctul de vedere al structurii interne, o
altfel decât abstracte. stivă poate fi implementată
7.2.2 Implementarea unei interfeţe folosind un vector sau o listă înlănţuită, ambele
Implementarea uneia sau mai multor interfeţe soluţii având avantaje şi
de către o clasă se face prin dezavantaje. Prima soluţie este mai simplu de
intermediul cuvântului cheie implements: înţeles, în timp ce a doua este
class NumeClasa implements NumeInterfata mai eficientă din punctul de vedere al folosirii
sau memoriei. Deoarece nu dorim
class NumeClasa implements Interfata1, să legăm tipul de date Stack de o anumită
Interfata2, ... implementare structurală, îl vom
O clasă poate implementa oricâte interfeţe sau defini prin intermediul unei interfeţe. Vom
poate să nu implementeze vedea imediat avantajele acestei
nici una. abordări.
In cazul în care o clasă implementează o Listing 5.1: Interfaţa ce descrie stiva
anumită interfaţă, atunci trebuie public interface Stack {
obligatoriu să specifice cod pentru toate void push ( Object item ) throws
metodele interfeţei. Din acest StackException ;
motiv, odată creata şi folosită la implementarea void pop () throws StackException ;
unor clase, o interfaţă nu Object peek () throws StackException ;
mai trebuie modificată, în sensul că adăugarea boolean empty ();
unor metode noi sau schimbarea String toString ();
signaturii metodelor existente vor duce la erori }
în compilarea claselor Pentru a trata situaţiile anormale care pot
care o implementează. Evident, o clasă poate apărea atunci când încercăm
avea şi alte metode şi variabile să punem un element în stivă şi nu este posibil
membre în afară de cele definite în interfaţă. din lipsă de memorie, sau
Atenţie încercăm să accesăm vârful stivei şi aceasta
Modificarea unei interfeţe implică modificarea este vidă, vom defini o excepţie
tuturor claselor care implementeaz proprie StackException:
ă acea interfaţă. Listing 7.2: Tipul de excepţie generat de stivă
O interfaţă nu este o clasă, dar orice referinţă public class StackException extends Exception
de tip interfaţă poate primi {
ca valoare o referinţa la un obiect al unei clase public StackException () {
ce implementează interfaţa super ();
respectivă. Din acest motiv, interfeţele pot fi }
privite ca tipuri de date şi vom
public StackException ( String msg) {
spune adesea că un obiect are tipul X, unde X
super (msg);
este o interfaţă, dacă acesta
}
este o instanţă a unei clase ce implementează
interfaţa X. }
Implementarea unei interfeţe poate să fie şi o Dăm în continuare prima implementare a
clasă abstractă. stivei, folosind un vector:
8.2.3 Exemplu: implementarea unei stive Listing 5.3: Implementarea stivei folosind un
vector
Să considerăm următorul exemplu. Dorim să
implementăm un nou tip de // Implementarea stivei folosind un vector de
obiecte .
date numit Stack, care să modeleze noţiunea de
stivă de obiecte. Obiectele public class StackImpl1 implements Stack {
de tip stivă, indiferent de implementarea lor, private Object items [];
vor trebui să conţină metodele: // Vectorul ce contine obiectele
• push - adaugă un nou element in stývă private int n=0;
• pop - elimină elementul din vârful stivei // Numarul curent de elemente din stiva
• peek - returnează varful stivei public StackImpl1 (int max ) {

240
// Constructor înlănţuită:
items = new Object [ max ]; Listing 5.4: Implementarea stivei folosind o
} listă
public StackImpl1 () { // Implementarea stivei folosind o lista
this (100) ; inlantuita .
} public class StackImpl2 implements Stack {
public void push ( Object item ) throws class Node {
StackException { // Clasa interna ce reprezinta un nod al listei
if (n == items . length ) Object item ; // informatia din nod
throw new StackException (" Stiva este Node link ; // legatura la urmatorul nod
plina !"); Node ( Object item , Node link ) {
items [n++] = item ; this . item = item ;
} this . link = link ;
public void pop () throws StackException { }
if ( empty ()) }
throw new StackException (" Stiva este private Node top= null ;
vida !"); // Referinta la varful stivei
items [--n] = null ; public void push ( Object item ) {
} Node node = new Node (item , top);
public Object peek () throws StackException { top = node ;
if ( empty ()) }
throw new StackException (" Stiva este public void pop () throws StackException {
vida !"); if ( empty ())
return items [n -1]; throw new StackException (" Stiva este
} vida !");
public boolean empty () { top = top . link ;
return (n ==0) ; }
} public Object peek () throws StackException {
public String toString () { if ( empty ())
String s=""; throw new StackException (" Stiva este
for (int i=n -1; i >=0; i --) vida !");
s += items [i]. toString () + " "; return top. item ;
return s; }
} public boolean empty () {
} return (top == null );
Remarcaţi că, deşi în interfaţă metodele nu }
sunt declarate explicit cu public String toString () {
modificatorul public, ele sunt totuşi publice şi String s="";
trebuie declarate ca atare în Node node = top;
clasă. while ( node != null ) {
Trebuie remarcat şi faptul că metoda toString s += ( node . item ). toString () + " ";
este definită deja în clasa
node = node . link ;
Object, deci clasa noastră o are deja
}
implementată şi nu am fi obţinut nici
return s;
o eroare la compilare dacă nu o implementam
explicit. Ceea ce facem acum }
este de fapt supradefinirea ei. }
O altă observaţie importantă se referă la faptul Singura observaţie pe care o facem aici este că,
că trebuie să declarăm în deşi metoda push din
cadrul interfeţei şi excepţiile aruncate de interfaţă declară aruncarea unor excepţii de
metode, ce trebuie obligatoriu tipul StackException, nu este
tratate. obligatoriu ca metoda din clasă să specifice şi
ea acest lucru, atât timp cât
Să vedem acum modalitatea de implementare a
stivei folosind o listă

241
nu generează excepţii de acel tip. Invers este Deosebirea constă în faptul că unele clase sunt
însă obligatoriu. forţate să extindă o anumită
In continuare este prezentată o mică aplicaţie clasă (de exemplu orice applet trebuie să fie
demonstrativă care foloseşte subclasa a clasei Applet) şi nu ar
tipul de date nou creat şi cele două mai putea sa extindă o altă clasă, deoarece în
implementări ale sale: Java nu exista decât moştenire
Listing 7.5: Folosirea stivei simpla. Fara folosirea interfeţelor nu am putea
public class TestStiva { forţa clasa respectivă să
public static void afiseaza ( Stack s) { respecte diverse tipuri de protocoale.
System . out. println (" Continutul stivei este : La nivel conceptual, diferenţa constă în:
" + s); • extinderea unei clase abstracte forţează o
} relaţie între clase;
public static void main ( String args []){ • implementarea unei interfeţe specifică doar
try { necesitatea implementării
Stack s1 = new StackImpl1 (); unor anumie metode.
s1. push ("a"); In multe situaţii interfeţele şi clasele abstracte
sunt folosite împreună
s1. push ("b");
pentru a implementa cât mai flexibil şi eficient
afiseaza (s1);
o anumită ierarhie de clase. Un
Stack s2 = new StackImpl2 ();
exemplu sugestiv este dat de clasele ce descriu
s2. push ( new Integer (1)); colecţii. Ca sa particularizăm,
s2. push ( new Double (3.14) ); există:
afiseaza (s2); • interfaţa List care impune protocolul pe care
} catch ( StackException e) { trebuie să îl respecte o
System . err. println (" Eroare la lucrul cu stiva clasă de tip listă,
!"); • clasa abstractă AbstractList care
e. printStackTrace (); implementează interfaţa List şi
} oferă implementări concrete pentru metodele
} comune tuturor tipurilor
} de listă,
Observaţi folosirea interfeţei Stack ca un tip de • clase concrete, cum ar fi LinkedList,
date, ce aduce flexibilitate ArrayList care extind AbstractList.
sporită în manevrarea claselor ce 5.4 Moştenire multiplă prin interfeţe
implementează tipul respectiv. Metoda Interfeţele nu au nici o implementare şi nu pot
afiseaza acceptă ca argument orice obiect al fi instanţiate. Din acest motiv,
unei clase ce implementează nu reprezintă nici o problemă ca anumite clase
Stack. să implementeze mai multe
Observaţie interfeţe sau ca o interfaţă să extindă mai multe
In pachetul java.util există clasa Stack care interfeţe (să aibă mai multe
modelează noţiune de stivă superinterfeţe)
de obiecte şi, evident, aceasta va fi folosită în class NumeClasa implements Interfata1,
aplicaţiile ce au nevoie de acest Interfata2, ...
tip de date. Exemplu oferit de noi nu are interface NumeInterfata extends Interfata1,
legătură cu această clasă şi are rol Interfata2, ...
pur demonstrativ. O interfaţă mosteneste atât constantele cât şi
8.3 Interfeţe şi clase abstracte declaraţiile de metode de la
La prima vedere o interfaţă nu este altceva superinterfeţele sale. O clasă moşteneste doar
decât o clasă abstractă în care constantele unei interfeţe şi
toate metodele sunt abstracte (nu au nici o responsabilitatea implementării metodelor sale.
implementare). Să considerăm un exemplu de clasa care
Aşadar, o clasă abstractă nu ar putea înlocui o implementeaza mai multe interfeţe:
interfaţă ? interface Inotator {
Raspunsul la intrebare depinde de situaţie, însă void inoata();
în general este ’Nu’. }
interface Zburator {

242
void zboara(); void metoda(); //corect
} //int metoda(); //incorect
interface Luptator { }
void lupta(); class C implements I1, I2 {
} public void metoda() {
class Erou implements Inotator, Zburator, System.out.println(I1.x); //corect
Luptator { System.out.println(I2.x); //corect
public void inoata() {} System.out.println(x); //ambiguitate
public void zboara() {} }
public void lupta() {} }
} Să recapitulăm câteva lucruri legate de clase şi
Exemplu de interfaţă care extinde mai multe interfeţe:
interfeţe: • O clasă nu poate avea decât o superclasă.
interface Monstru { • O clasă poate implementa oricâte interfeţe.
void ameninta(); • O clasă trebuie obligatoriu să trateze
} metodele din interfeţele pe care
interface MonstruPericulos extends Monstru { la implementează.
void distruge(); • Ierarhia interfeţelor este independentă de
} ierarhia claselor care le implementeaz
interface Mortal { ă.
void omoara(); 8.5 Utilitatea interfeţelor
} După cum am văzut, o interfaţă defineşte un
interface Vampir extends MonstruPericulos, protocol ce poate fi implementat
Mortal { de orice clasă, indiferent de ierarhia de clase
void beaSange(); din care face parte. Interfeţele
} sunt utile pentru:
class Dracula implements Vampir { • definirea unor similaritati între clase
independente fără a forţa artificial
public void ameninta() {}
o legatură între ele;
public void distruge() {}
• asigură că toate clasele care implementează o
public void omoara()() {}
interfaţă pun la dipoziţie
public void beaSange() {}
metodele specificate în interfaţă - de aici
} rezultă posibilitatea implement
Evident, pot apărea situaţii de ambiguitate, ării unor clase prin mai multe modalităţi şi
atunci când există constante folosirea lor într-o
sau metode cu aceleaşi nume în mai multe manieră unitară;
interfeţe, însă acest lucru trebuie
• definirea unor grupuri de constante;
întotdeauna evitat, deoarece scrierea unui cod
• transmiterea metodelor ca parametri;
care poate fi confuz este un stil
7.5.1 Crearea grupurilor de constante
prost de programare. In cazul in care acest
lucru se întâmplă, compilatorul Deoarece orice variabilă a unei interfeţe este
implicit declarată cu public,
nu va furniza eroare decât dacă se încearcă
referirea constantelor ambigue static si final, interfeţele reprezintă o metodă
convenabilă de creare a unor
fără a le prefixa cu numele interfeţei sau dacă
metodele cu acelaşi nume nu grupuri de constante care să fie folosite global
într-o aplicaţie:
pot fi deosbite, cum ar fi situaţia când au
aceeaşi listă de argumente dar public interface Luni {
tipuri returnate incompatibile. int IAN=1, FEB=2, ..., DEC=12;
interface I1 { }
int x=1; Folosirea acestor constante se face prin
expresii de genul
void metoda();
NumeInterfata.constanta, ca în exemplul de
}
mai jos:
interface I2 {
if (luna < Luni.DEC)
int x=2;
luna ++

243
else }
luna = Luni.IAN; }
8.5.2 Transmiterea metodelor ca parametri public class TestCallBack {
Deoarece nu există pointeri propriu-zişi, public static void main(String args[]) {
transmiterea metodelor ca parametri Graf G = new Graf();
este realizată în Java prin intermediul G.explorare(new AfisareRo());
interfeţelor. Atunci când o metodă G.explorare(new AfisareEn());
trebuie să primească ca argument de intrare o }
referinţă la o altă funcţie
}
necesară execuţiei sale, cunoscută doar la
Al doilea xemplu va fi prezentat în secţiunea
momentul execuţiei, atunci argumentul
următoare, întrucât face
respectiv va fi declarat de tipul unei interfeţe
parte din API-ul standard Java şi vor fi puse în
care conţine metoda
evidenţă, prin intermediul
respectivă. La execuţie metoda va putea primi
său, şi alte tehnici de programare.
ca parametru orice obiect ce
8.6 Interfaţa FilenameFilter
implementează interfaţa respectivă şi deci
conţine şi codul funcţiei respective, Instanţele claselor ce implementează aceasta
interfaţă sunt folosite pentru a
aceasta urmând să fie apelată normal pentru a
obţine rezultatul dorit. crea filtre pentru fişiere şi sunt primite ca
argumente de metode care listează
Această tehnică, denumită şi call-back, este
extrem de folosită în Java conţinutul unui director, cum ar fi metoda list a
clasei File.
şi trebuie neapărat înţeleasă. Să considerăm
mai multe exemple pentru a Aşadar, putem spune că metoda list primeşte
ca argument o altă funcţie
clarifica lucrurile.
care specifică dacă un fişier va fi returnat sau
Primul exemplu se referă la explorarea
nu (criteriul de filtrare).
nodurilor unui graf. In fiecare
Interfaţa FilenameFilter are o singură metodă:
nod trebuie să se execute prelucrarea
accept care specifică
informaţiei din nodul respectiv prin
criteriul de filtrare şi anume, testează dacă
intermediul unei funcţii primite ca parametru.
numele fişierului primit ca parametru
Pentru aceasta, vom defini o
îndeplineşte condiţiile dorite de noi.
interfaţă Functie care va specifica metoda
trimisă ca parametru. Definiţia interfeţei este:
interface Functie { public interface FilenameFilter {
public void executa(Nod u); public boolean accept(File dir, String
numeFisier);
}
}
class Graf {
Aşadar, orice clasă de specificare a unui filtru
//...
care implementeză interfaţa
void explorare(Functie f) {
FilenameFilter trebuie să implementeze
//... metoda accept a acestei interfeţe.
if (explorarea a ajuns in nodul v) { Aceste clase mai pot avea şi alte metode, de
f.executa(v); exemplu un constructor care să
//... primeasca criteriul de filtrare. In general, o
} clasă de specificare a unui filtru
} are următorul format:
} class FiltruFisiere implements FilenameFilter {
//Definim doua functii String filtru;
class AfisareRo implements Functie { // Constructorul
public void executa(Nod v) { FiltruFisiere(String filtru) {
System.out.println("Nodul curent este: " + v); this.filtru = filtru;
} }
} // Implementarea metodei accept
class AfisareEn implements Functie { public boolean accept(File dir, String nume) {
public void executa(Nod v) { if (filtrul este indeplinit)
System.out.println("Current node is: " + v); return true;

244
else class Filtru implements FilenameFilter {
return false; String extensie ;
} Filtru ( String extensie ) {
} this . extensie = extensie ;
Metodele cele mai uzuale ale clasei String }
folosite pentru filtrarea fişierelor public boolean accept ( File dir , String nume )
sunt: {
• endsWith - testează dacă un şir are o anumită return ( nume . endsWith ("." + extensie ) );
terminaţie }
• indexOf - testează dacă un şir conţine un }
anumit subşir, returnând 8.6.1 Folosirea claselor anonime
poziţia acestuia, sau 0 în caz contrar. In cazul în care nu avem nevoie de clasa care
Instanţele claselor pentru filtrare sunt primite reprezintă filtrul pentru listarea
ca argumente de metode fişierelor dintr-un director decât o singură dată,
de listare a conţinutului unui director. O astfel pentru a evita crearea unei
de metodă este list din noi clase de sine stătătoare care să fie folosită
clasa File: pentru instanţierea unui singur
String[] list (FilenameFilter filtru) obiect, putem folosi clasă internă anonimă,
Observati că aici interfaţa este folosită ca un această situaţie fiind un exemplu
tip de date, ea fiind substituit tipic de folosire a acestora.
ă cu orice clasă care o implementează. Acesta Listing 5.7: Folosirea unei clase anonime
este un exemplu tipic de /* Listarea fisierelor din directorul curent
transmitere a unei funcţii (funcţia de filtrare folosind o clasa anonima pentru filtru .
accept) ca argument al unei
*/
metode.
import java .io .*;
Să considerăm exemplul complet în care dorim
class Listare {
să listăm fişierele din directorul
public static void main ( String [] args ) {
curent care au o anumită extensie.
try {
Listing 5.6: Listarea fişierelor cu o anumită
extensie File director = new File (".");
/* Listarea fisierelor din directorul curent String [] list ;
care au anumita extensie primita ca argument . if ( args . length > 0) {
Daca nu se primeste nici un argument , vor fi final String extensie = args [0];
listate toate list = director . list ( new FilenameFilter () {
. // Clasa interna anonima
*/ public boolean accept ( File dir , String nume )
import java .io .*; {
class Listare { return ( nume . endsWith ("." + extensie ) );
public static void main ( String [] args ) { }
try { });
File director = new File ("."); }
String [] list ; else
if ( args . length > 0) list = director . list ();
list = director . list ( new Filtru ( args [0]) ); for (int i = 0; i < list . length ; i ++)
else System . out. println ( list [i]);
list = director . list (); } catch ( Exception e) {
for (int i = 0; i < list . length ; i ++) e. printStackTrace ();
System . out. println ( list [i]); }
} catch ( Exception e) { }
e. printStackTrace (); }
} Aşadar, o modalitate uzuală de folosire a
claselor anonime pentru instanţierea
}
unui obiect care trebuie să respecte o interfaţă
}
este:

245
metoda(new Interfata() { La execuţia acestei aplicaţii va fi obţinută o
// Implementarea metodelor interfetei excepţie, deoarece metoda
}); sort nu ştie care este ordinea naturală a
8.7 Compararea obiectelor obiectelor de tip Persoana. Va
Am văzut în primul capitol că o soluţie facilă trebui, într-un fel sau altul, să specificăm acest
şi eficientă de sortare a unui lucru.
vector este folosirea metodei sort din clasa 8.7.1 Interfaţa Comparable
java.util.Arrays. Interfaţa Comparable impune o ordine totală
int v[]={3, 1, 4, 2}; asupra obiectelor unei clase ce
java.util.Arrays.sort(v); o implementează. Această ordine se numeşte
ordinea naturală a clasei şi este
// Sorteaza vectorul v
specificată prin intermediul metodei
// Acesta va deveni {1, 2, 3, 4}
compareTo. Definiţia interfeţei este:
In cazul în care elementele din vector sunt de
public interface Comparable {
tip primitiv, ca in exemplul
int compareTo(Object o);
de mai sus, nu există nici o problemă în a
determina ordinea firească }
a elementelor. Ce se întămplă însă atunci când Aşadar, o clasă ale cărei instanţe trebuie să fie
vectorul conţine referinţe la comparabil va implementa
obiecte de un anumit tip ? Să considerăm metoda compareTo care trebuie să returneze:
următorul exemplu, în care dorim • o valoare strict negativă: dacă obiectul curent
să sortăm un vector format din instanţe ale (this) este mai mic
clasei Persoana, definită mai jos: decâ obiectul primit ca argument;
Listing 5.8: Clasa Persoana (fără suport pentru • zero: dacă obiectul curent este egal decâ
comparare) obiectul primit ca argument;
class Persoana { • o valoare strict pozitivă: dacă obiectul curent
int cod ; este mai mare decâ
String nume ; obiectul primit ca argument.
public Persoana ( int cod , String nume ) { Reamintim că metoda equals, moştenită din
Object de toate clasele,
this .cod = cod;
determină dacă două obiecte sunt egale (au
this . nume = nume ;
aceeaşi valoare). Spunem că
}
ordinea naturală a unei clase C este consitentă
public String toString () { cu equals dacă şi numai
return cod + " \t " + nume ; dacă (e1.compareTo((Object)e2) == 0) are
} aceeaŞsi valoare logică cu
} e1.equals((Object)e2, pentru orice e1, e2
Programul următor ar trebui să sorteze un instanţe ale lui C.
vector de persoane: null nu este instanţă a nici unei clase şi
Listing 5.9: Sortarea unui vector de tip e.compareTo(null) trebuie să
referinţă arunce o excepţie de tip NullPointerException
class Sortare { chiar dacă e.equals(null)
public static void main ( String args []) { returnează false.
Persoana p[] = new Persoana [4]; Să presupunem că dorim ca ordinea naturală a
p[0] = new Persoana (3, " Ionescu "); persoanelor să fie după
p[1] = new Persoana (1, " Vasilescu "); codul lor intern.
p[2] = new Persoana (2, " Georgescu "); Listing 7.10: Clasa Persoana cu suport pentru
p[3] = new Persoana (4, " Popescu "); comparare
java . util . Arrays . sort (p); class Persoana implements Comparable {
System . out. println (" Persoanele ordonate int cod ;
dupa cod:"); String nume ;
for (int i=0; i<p. length ; i++) public Persoana ( int cod , String nume ) {
System . out. println (p[i]); this .cod = cod;
} this . nume = nume ;
} }

246
public String toString () { Listing 7.11: Sortarea unui vector folosind un
return cod + " \t " + nume ; comparator
} import java . util .*;
public boolean equals ( Object o) { class Sortare {
if (!( o instanceof Persoana )) public static void main ( String args []) {
return false ; Persoana p[] = new Persoana [4];
Persoana p = ( Persoana ) o; p[0] = new Persoana (3, " Ionescu ");
return (cod == p.cod) && ( nume . equals (p. p[1] = new Persoana (1, " Vasilescu ");
nume )); p[2] = new Persoana (2, " Georgescu ");
} p[3] = new Persoana (4, " Popescu ");
public int compareTo ( Object o) { Arrays . sort (p, new Comparator () {
if (o== null ) public int compare ( Object o1 , Object o2) {
throw new NullPointerException (); Persoana p1 = ( Persoana )o1;
if (!( o instanceof Persoana )) Persoana p2 = ( Persoana )o2;
throw new ClassCastException ("Nu pot return (p1. nume . compareTo (p2. nume ));
compara !"); }
Persoana p = ( Persoana ) o; });
return (cod - p.cod ); System . out. println (" Persoanele ordonate
} dupa nume :");
} for (int i=0; i<p. length ; i++)
Observaţi folosirea operatorului instanceof, System . out. println (p[i]);
care verifică dacă un obiect }
este instanţă a unei anumite clase. Metoda }
compareTo va arunca o excepţie Observaţi cum compararea a două şiruri de
de tipul ClassCastException dacă se încearcă caractere se face tot cu metoda
compararea unui obiect de compareTo, clasa String implemenând
tip Persoana cu un obiect de alt tip. Metoda interfaţa Comparable.
equals va returna, pur şi 8.8 Adaptori
simplu, false. In cazul în care o interfaţă conţine mai multe
8.7.2 Interfaţa Comparator metode şi, la un moment
In cazul în care dorim să sortăm elementele dat, avem nevoie de un obiect care
unui vector ce conţine referinţe implementează interfaţa respectiv dar nu
după alt criteriu decât ordinea naturală a specifică cod decât pentru o singură metodă, el
elemenetelor, avem nevoie de o altă trebui totuşi să implementeze
soluţie. Aceasta este oferită tot de metoda sort toate metodele interfeţei, chiar dacă nu
din clasa java.util.Arrays, specifică nici un cod.
dar în varianta în care, pe lângă vectorul ce interface X {
trebuie sortat, vom transmite void metoda_1();
un argument de tip Comparator care să void metoda_2();
specifice modalitatea de comparare
...
a elementelor.
void metoda_n();
Interfaţa java.util.Comparator conţine metoda
}
compare, care impune
...
o ordine totală asupra elementelor unei
colecţii. Aceasta returnează un întreg // Avem nevoie de un obiect de tip X
cu aceeaşi semnificaţie ca la metoda // ca argument al unei functii
compareTo a interfeţei Comparator şi functie(new X() {
are următoarea definiţie: int compare(Object public void metoda_1() {
o1, Object o2); // Singura metoda care ne intereseaza
Să presupunem că dorim să sortăm persoanele ...
ordonate după numele lor. }
Pentru definirea comparatorului vom folosi o // Trebuie sa apara si celelalte metode
clasă anonimă. // chiar daca nu au implementare efectiva
public void metoda_2() {}

247
public void metoda_3() {} ...
... public void metoda_n() {}
public void metoda_n() {} }
}); In situaţia când avem nevoie de un obiect de
Această abordare poate fi neplăcută dacă avem tip X vom folosi clasa
frecvent nevoie de obiecte abstractă, supradefinind doar metoda care ne
ale unor clase ce implementează interfaţa X. interesează:
Soluţia la această problemă este functie(new XAdapter() {
folosirea adaptorilor. public void metoda_1() {
Definiţie // Singura metoda care ne intereseaza
Un adaptor este o clasă abstractă care ...
implementează o anumită interfaţă }
fără a specifica cod nici unei metode a });
interfeţei. Mai multe exemple de folosire a adaptorilor
public abstract class XAdapter implements X { vor fi dateîn capitolul ”Interfaţa
public void metoda_1() {} grafică cu utilizatorul”.
public void metoda_2() {}

FISIERE SI BUFFERE
Fisierele se pun in directorul proiectului

//SA SE CREEZE UN BUFFER SA SE COPIEZE IN ALTUL SI SA SE AFISEZE


package j1;

import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;

248
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;
import java.awt.Event;
import java.awt.Point;
import java.awt.*;
import java.net.*;
import java.net.MalformedURLException;
import java.awt.*;
import java.io.DataInputStream;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.net.MalformedURLException;
import java.net.*;
import java.sql.*;

import java.util.*;
import java.io.*;
import java.util.*;
import java.sql.*;
import sun.jdbc.odbc.*;
import java.io.*;

import java.lang.*;
import java.sql.*;
import sun.jdbc.odbc.*;

import java.io.*;
import java.util.*;

class EX13A
{
void printInputStream(InputStream s)
{
try
{
System.out.print("[");
while (s.available() > 0)
{
System.out.print(s.read());
}
System.out.println("]");
s.reset();
}
catch (Exception e)
{
System.err.println("Error displaying array: " + e);
}
}

public static void main(String args[])


{
byte buf1[] = { 1, 2, 3, 4, 5 };
// Create an input stream based on buf1.
InputStream is1 = new ByteArrayInputStream(buf1);
EX13A example = new EX13A();

249
example.printInputStream(is1); // Print the stream as
is.
buf1[0] = 0; // Modify the array
outside of the stream.
example.printInputStream(is1); // Print it again.
byte buf2[] = { 6, 7, 8, 9 }; // Create another
array...
buf1 = buf2; // ... and assign it to
buf1.
example.printInputStream(is1); // Print it one last
time.
// Create another input stream based on buf2 that works
with
// the last two bytes of the array only.
InputStream is2 = new ByteArrayInputStream(buf2, 2,
buf2.length - 2);
example.printInputStream(is2); // Finally, print is2.
}
}
//citirea unei linii dintr-un fisier
package j1;

import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;
import java.awt.Event;
import java.awt.Point;
import java.awt.*;
import java.net.*;
import java.net.MalformedURLException;
import java.awt.*;
import java.io.DataInputStream;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.net.MalformedURLException;
import java.net.*;
import java.sql.*;

import java.util.*;
import java.io.*;
import java.util.*;
import java.sql.*;
import sun.jdbc.odbc.*;
import java.io.*;

import java.lang.*;
import java.sql.*;
import sun.jdbc.odbc.*;

import java.io.*;

250
import java.util.*;

class EX13B
{
public static void main(String args[])
{

try
{
String lines;
int linen;
// Create a simple file input stream.
FileInputStream is = new FileInputStream("fis");
DataInputStream ds=new DataInputStream(is);
// Read the entire contents of the file.
while ((lines=ds.readLine())!=null)
{
System.out.print(lines);
}
ds.close();
}
catch (Exception e)
{
System.err.println("Eroare la citirea fisierului: "
+ e);
}
}
}
//afisarea continutului unui buffer
package j1;

import java.awt.*;
import java.applet.*;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.util.Date;
import java.awt.Image;
import java.applet.AudioClip;
import java.awt.Event;
import java.awt.Point;
import java.awt.*;
import java.net.*;
import java.net.MalformedURLException;
import java.awt.*;
import java.io.DataInputStream;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.net.MalformedURLException;
import java.net.*;
import java.sql.*;

import java.util.*;
import java.io.*;

251
import java.util.*;
import java.sql.*;
import sun.jdbc.odbc.*;
import java.io.*;

import java.lang.*;
import java.sql.*;
import sun.jdbc.odbc.*;

import java.io.*;
import java.util.*;

class EX13D
{
public static void main(String args[])
{
try
{

BufferedInputStream bis = new


BufferedInputStream(new FileInputStream("aaaaa"));

while (bis.available() > 0)


{
System.out.print((char)bis.read());
}
}
catch (Exception e)
{
System.err.println("Error reading file: " + e);
}
}
}

252

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