0% au considerat acest document util (0 voturi)
40 vizualizări103 pagini

Java Basis

Încărcat de

Alexandra Rosca
Drepturi de autor
© Attribution Non-Commercial (BY-NC)
Respectăm cu strictețe drepturile privind conținutul. Dacă suspectați că acesta este conținutul dumneavoastră, reclamați-l aici.
Formate disponibile
Descărcați ca DOC, PDF, TXT sau citiți online pe Scribd
0% au considerat acest document util (0 voturi)
40 vizualizări103 pagini

Java Basis

Încărcat de

Alexandra Rosca
Drepturi de autor
© Attribution Non-Commercial (BY-NC)
Respectăm cu strictețe drepturile privind conținutul. Dacă suspectați că acesta este conținutul dumneavoastră, reclamați-l aici.
Formate disponibile
Descărcați ca DOC, PDF, TXT sau citiți online pe Scribd

1.

Mediul Java pentru Internet

1.1. Descrierea succintã a mediului


[Link] este Java?

Java este un limbaj de programare orientat obiect, asemãnator cu C++, dar cu un alt
conţinut important ceea ce il face un instrument foarte robust pentru dezvoltarea de aplicaţii
WWW. Menirea limbajului Java este de a fi un standard pentru transferul de conţinut executabil pe
Internet prin WWW. Datorită limbajului Java se schimbă natură pasivă a reţelei Internet, deoarece
un program binar portabil generat de compilatorul Java, poate fi încarcat şi executat în mod
interpretativ pe orice calculator legat la Internet.
Proiectarea orientată pe obiecte este un instrument puternic, deoarece facilitează definirea
clară a interfeţelor şi permite reutilizarea unor module de program identificate ca şi obiecte. Fiind
conceput ca un limbaj obiectual, tot ce există într-un program este incapsulat în obiecte, care în
Java poartă denumirea de clase, limbajul permiţâd moştenirea şi extinderea unei clase şi
reutilizarea oricărui program sau modul în alte programe.
O clasa Java este o colecţie de variabile şi de metode, care încapsulează o anumită
funcţionalitate, într-un obiect reutilizabil şi încărcabil în mod dinamic. Mediul Java încarcã în mod
dinamic clasele, ceea ce înseamnă ca un program Java care se execută poate adăuga funcţionalităţi
noi în mod dinamic, prin încãrcarea claselor necesare la un moment dat.
Portabilitatea programelor este un deziderat major, care nu se poate realiza numai printr-o execuţie
interpretativa şi în acest sens în mediul Java pentru Internet un program sursă este compilat mai
intâi în cod binar portabil (codul binar), care este apoi adaptat cerinţelor codului nativ al
calculatorului pe care se execută. Aceast mecanism este o maşină Java virtuală (JVM), care la
rândul ei este implementată pe orice calculator ca şi interpretorul Java. Portabilitatea este asigurată
şi prin standardizarea tipurilor fundamentale.[LEMA-96]
Robusteţea mediului permite scrierea unor programe suple şi puternice, care funcţionează
corect astfel încât totul se decide dinamic, în timpul execuţiei, pentru a evita conflicte. Gestiunea
memoriei se realizează automat, nu prin instrucţiuni scrise în programul sursă ci printr-un sistem
complex implementat astfel încât să gestioneze clasele şi obiectele utilizate, interfeţele necesare şi
să elibereze în mod dinamic spaţiul de memorie neutilizat.

Avand în vedere ca mediul Java este un mediu de programare şi utilizare distribuit pe Internet,
care este implementat pe principiile tehnologiei Corba, se impun metode de protecţie atât pentru
sistemele clienţilor, cât şi pentru servere. Java permite crearea unor sisteme protejate, realizate
prin:[An-97]
 Eliminarea pointerilor ca punctele slabe ale securităţii sistemelor împreună cu
aritmetica pointerilor, recunoscută ca o cauză importantă ce determină distrugeri
accidentale ale sistemelor.
 Gestiunea automată a memoriei prin alocarea spaţiului la crearea un obiect şi
urmărirea pe parcursul execuţiei appletului până în momentul în care acesta nu mai este
referit, caz în care memoria este dezalocată automat. In opoziţie, gestiunea memoriei in C
şi C++ este realizată explicit de programatori cu ajutorul instrucţiunilor malloc şi free,
precum şi cu alte funcţii standard de gestiune a memoriei.

1
 Alocarea dinamicã a memoriei este realizată automat în timpul execuţiei pentru
clasele create, eliminând alocarea statică a memoriei.
 Gestionarea spaţiului alocat separat pentru fiecare clasă este soluţionată de
interpretorul Java care oferă spaţiu separat de variabile pentru clasele create.
 Verificarea codului binar înainte de execuţie de către interpretorul Java, care
testeazã anumite convenţii ale limbajului şi ale mediului Java. Astfel se verifică dacă nu se
va execută o acţiune daunatoare pentru sistem: violarea restrictiilor de acces, efectuarea
unor conversii ilegale de date, depãşirea superioară sau inferioară a stivei, etc.
 Reţea, clurul cu protocoale TCP/IP(Transmission Control , UDP(User Datagram
protocol), IP (Internet Protocol)
 Internaţionalizare prin adaptarea programelor la setări locale de limbă şi fus orar.
 Securitate la diverse niveluri, gestiunea cheilor publice şi private, restricţii selective
de acces, control şi securitate,etc.
 Componente software reutilizabile -JavaBeans integrabile în arhitectura existentă.
 Serializare/ deserializare de obiecte, care permite persistenţa şi comunicaţia între
obiecte la distanţă folosind Remote Method Invocation (RMI)
 Acces la baze de date relaţionale, de diverse tipuri, folosint Java Database
Connectivity (JDBC)
 Grafică bi/tridimensională, animaţie, etc.

Performanţele mediului sunt date şi de codul binar portabil rezultat în urma compilãrii, care
este adaptat în timpul execuţiei la codul nativ al calculatorului real pe care se rulează aplicaţia. In
anumite situaţii, compilarea este amânată pană în momentul execuţiei.
Java este un sistem dinamic extensibil, care poate achizitiona fişiere din orice punct al retelei
Internet. Fiind orientat pe obiecte, extensibilitatea dinamică se răsfrânge şi asupră obiectelor, caz
în care un program poate achizitiona în mod dinamic, din orice punct al reţelei, clasele de care are
nevoie în timpul execuţiei. In Java legarea variabilelor şi a metodelor se face tarziu (late binding),
chiar în momentul execuţiei iar interpretorul este cel care rezolvă referinţele simbolice şi
determină alocarea dinamică a memoriei. Regăsirea variabilelor şi a metodelor se face prin nume,
nu prin adrese relative. Orice clasa poate fi modificată in orice moment, fără a fi nevoie să se
recompileze toate subclasele sale. Avantajul referinţelor în momentul execuţiei este dat de
posibilitatea utilizării dinamice a claselor, care se pot actualiza tot timpul.
Limbajul Java a fost proiectat cu scopul de a se realiza un mijloc de transfer a conţinutului
executabil, dinamic, pe Internet iar funcţiile de reţea sunt cele care trebuie implementate în mediul
Java astfel încât să poată fi exploatat ca un mediu distribuit în Internet.

Odată cu paradigma business object, Enterprise1 Java s-a răspândit rapid în lumea calculatoarelor
desemnând acele aplicaţii Java dezvoltate pentru intranet-ul unei companii, care foloseşte
tehnologii Internet ca:e-mail, ftp, telnet, news, servicii Web,etc.

Facilitatea de multifir (multithreading) reprezintă posibilitatea de a incorpora mai multe fire de


execuţie, performanţă ce conferă mediului atuuri suplimentare. In timpul execuţiei unui program,
timpul în care acesta ocupă unitatea centrală este relativ redus faţă de restul timpului în care
1
Enterprise=întreprindere, companie, organizaţie, firmă, în IT este organizaţie care utilizează
sisteme de calcul

2
programul aşteaptă intervenţia utilizatorului, sau este ocupat cu accesul la fişiere sau la reţea. In
aplicaţiile cu un singur fir de aşteptare, unitatea centralã rãmâne neocupată intervale lungi de timp.
In mediul Java, acest timp este ocupat imediat de alte fire de execuţie, prin care se realizează
anumiţe acţiuni specifice.[Naugh-96]
Deşi este un limbaj de programare destinat WWW, permite definirea de aplicaţii independente,
fiind executate în mod interpretativ. Astfel se pot realiza aplicaţii pentru domenii ca: editoare de
texte, foi de calcul, baze de date, proiectare asistată de calculator. Utilizarea aplicaţiilor
independente în contextul unui mediu distribuit pe Internet oferă posibilitatea lansării de aplicaţii
care se află pe alte calculatoare dar pentru utilizarea applet-urilor java este necesară accesarea unor
site-uri Web cu browsere dotate cu interpretoare Java.
Pentru programatori, limbajul Java oferă o platformă unică pentru dezvoltarea de aplicaţii - un
calculator virtual, maşină virtuală Java şi aplicaţiile care se dezvoltă sau se distribuie pe reteaua
Internet. Pentru utilizatori, conţinutul executabil Java asigură integrarea perfectă a datelor cu
funcţiile şi interactiunile programelor, precum şi cu lucrul în retea, fără a fi sunt necesare aplicaţii
ajutatoare (helper applications) sau fişiere ajutătoare pentru diferite tipuri de protocoale, deoarece
Java permite încapsularea datelor şi a metodelor în clase.

1.1.2. Avantajele programãrii în Java

Appleturile Java (sau programele interactive) permit abordarea de la nivelul superficial -


imagini animate, text în mişcare, etc- la nivelul substanţial - educaţie interactivă continuă, aplicaţii
orientate în afaceri. etc. Java este proiectat ca limbaj cross-platform, ceea ce înseamnă că poate
rula pe orice maşină, folosind orice sistem de operare. Codul sursă Java este compilat în
instrucţiuni pentru o maşină virtuală (un cip imaginar în exenţă simulat soft) iar aceste
instrucţiuni sunt interpretate de interpreterul Java, ce translatează codul binar în instrucţiuni în
limbaj maşină, care vor fi executate pe calculatorul virtual. Setul de instrucţiuni pentru maşina
virtuală şi codul binars în care acestea vor fi convertite sunt întotdeauna aceleaşi, fără a ţine seama
de diferenţele date de suportul hardware pe care rulează interpreterul.
Interpreterul în sine, pentru a-şi realiza obiectivele, trebuie să cunoască limbajul maşină al
dispozitivului hardware specific pe care rulează. De acceea softul scris în Java este independent
de platformă, fără a necesita portare sau recompilare, interpreterul Java portând platforma înainte
de a rula programul pe calculator.
Animaţia este un beneficiu simplu pe care îl aduce Java permiţând paginilor Web să conţină
imagini în mişcare. Appleturile Java oferă abilitatea animaţiei astfel încât paginile sunt continuu
interactive, pentru a răspunde direct, în timp real, intrărilor utilizatorului.
Interactivitatea pe partea clientului este realizată diferit faţă de paginile Web tradiţionale, unde
procesul este preluat pe partea serverului. Utilizând un browser disponibil java, pagina Web
conţine URL-ul appletului Java. Accesând această pagină, appletul este trimis pe calculatorul
propriu, care îl execută. Marea majoritate a prelucrărilor este transferată pe partea clientului, de la
serverul la distanţă. Aceasta permite interactivitate, fără întârzierile datorate timpului de răspuns ce
apar când informaţia este trimisă înapoi pe Internet. Intrările utilizatorului sunt trimise direct
programului responsabil pentru procesarea lor, ceea ce aduce interactivitatea paginilor Web.
Dezvoltarea API (Application Programming Interface) oferă programatorului acces la clase,
furnizând structuri comune de date, rutine I/O, tabele, fişiere, dispozitive reţea, grafică şi audoi,
funcţii matematice, etc. Java API furnizează elemente predefinite (butoane, bare de defilare, casete
de dialog, etc.) necesare construcţiei GUI (Graphic User Interface) şi referite în AWT (Abstract
Window Toolkit).[java_4]

3
Aplicaţiile de sine stătătoare (standalone) sunt foarte uşor de realizat deoarece Java este un limbaj
de programare complet, configurat OO. Când appleturile rulează fără browser disponibil java,
aplicaţiile standalone sunt complet autorizate, putând rula pe un calculator, sau preluâd avantajele
suportului Internet oferit de Java API. Spre exemplu Sun HotJava este scris complet în limbajul
Java.
Un alt exemplu este cel în care există o bază de date (BD) centrală pe un calculator şi toţi
utilizatorii din firmă au acces la ea, chiar dacă birourile sunt plasate în diverse locuri din oraş sau
chiar în oraşe diferite. Practic întregul program front-end care accesează BD este conceput ca
aplicaţie client ce nu trebuie portată şi recompilată pentru diverse platforme, avantaj resimţit mai
ales la construcţia interfeţei utilizator. Acelaşi program client este compilat o singură dată şi poate
rula pe toate platformele, iar funcţiile interfeţei utilizator sunt aceleaşi. Chiar dacă HTML este
independent de platformă, apar probleme când se introduce o cerere incompletă sau impropriu
formulată în cadrul unui formular. Java oferă posibilitatea de a crea “forme inteligente” (smart
form) care verifică legitimitatea cererilor de intrare ale clientului, eliminând consumurile
inadecvate de lăţime de bandă din scenariul anterior.
Din punct de vedere teoretic nu sunt restricţii cu privire la aplicaţiile de sine stătătoare, respectiv
tot ce realizează acestea poate realiza un applet rezident pe pagina Web. Se preferă appleturile
deoarece oferă securitate a structurilor construite pe un [Link] poate utiliza structuri de date
gestionate de Security Manager şi indiferent de localizarea calculatorului poate activa sau inhiba
programe Java pentru a prelucra operaţii certe: încărcarea automată a unui program sau formă
dintr-o locaţie Internet, închiderea/deschiderea unui fişier,[Link] lucru este utilizat pentru a
preveni încărcarea unui applet infectat (ca şi virulsul Troian Horse), care poate crea prejudicii
acestui applet (sau sistemului local de fişiere) ori să faciliteze curiozităţi neautorizate din exterior.
Unele caracteristici de securitate sunt accesibile din caseta de dialog a meniului Security
Preferences dar nu pot fi modificate de utilizator şi nici nu pot fi alterate de codul încărcat de un
host la distanţă. Netscape ca şi alte browsere impune doar limitări extinse la appleturile ce
beneficiază de înteaga gama de facilităţi Java, dar este necesară dezvoltarea browserelor pentru a
limita extensiile de către acei utilizatori care pot relaxa restricţiile de securitate locală ale
appleturilor. Interacţiunea utilizator-utilizator prin reţea poate fi necesară pentru a avea aplicaţii
Java de sine stătătoare, care sunt implementate cu politici diferite de securitate pe Netscape, luând
măsuri specifice pentru drepturi, pentru a se asigura că nu pot apare breşe de securitate.[An_96]
Protocol handler este un progam care aparţine JDK şi permite unui browser disponibil Java
interpretarea unui nou tip de protocol. Acest lucru elimină inconvenientul browserelelor
tradiţionale, unde apariţia unui nou protocol implica dezvoltarea browserului, astfel încât să
conţină tot codul ce permite manipularea solicitărilor făcute de protocol, ceea ce implică realizarea
unui program monilitic, care consumă multă memorie RAM. Dezvoltarea browserelor disponibile
Java este modulară şi extensibilă iar browserul în sine este un program cu flux liniar, care
utilizează un set de protocoale ce reprezintă repertoriul curent ce poate fi interpretat.
Manipulatorul poate fi încărcat "transparent" astfel încât utilizatorul nu trebuie să fie preocupat de
detalii, singura sarcină fiind accea de a naviga în URL-ul propice. Protocul handler încarcă în
background tot ce trimite browserul iar browserul îşi încarcă doar handler-ele necesare realizând o
optimizare a memoriei RAM ocupate.
Content handlers are rolul de a furniza o alternativă a ideii de aplicaţii standallone, permiţând
programatorului Java să scrie codul ce extinde browserul, dându-I abiliatea de a interpreta
conţinutul inline fără a solicita apelul unor aplicaţii externe. In dezvoltarea browserelor
programatorii şi-au dat seama că nu se poate determina tipul conţinutului trimis prin MIME şi
apoi să se lege browserul de "helper-e" prezente pe calculatorul local al utilizatorului. Content

4
handler este încărcat automat la fel ca şi protocul handler, atunci când se accesează pagina Web, ce
conţine un nou tip (video, audio, conţinut special de pe Web, etc) deşi Netscape nu suportă
modelul Java pentru content handler.

1.2. Primii paşi în programarea Java

Pentru a realiza o aplicaţie Java sunt necesare un editor de texte, JDK (Java Development Kit) şi
un browser disponibil [Link] de platforma utilizată, la despachetarea JDK se crează
directorul JAVA şi o serie de subdirectoare (lib - ce conţine fişierul [Link], bin - ce conţine
codul binar executabil pentru unelte Java memorate, javac - interpretor java de sine stătător şi
appletviewer). Acestea nu se despachetează pentru a nu consuma spaţiu de memorie pe disc. In
final se setează variabilele de mediu CLASSPATH care identifică locaţia unde se caută uneltele
Java pentru orice clasă care nu este găsită în partea standard, inclusă în JDK.
In momentul de fată sunt întâlnite mai multe tipuri de aplicaţii scise în limbajul Java:
♦ appleturi - aplicaţiile ce rulează într-un browser ce suportă Java şi respectă convenţii clar
definite;
♦ aplicaţiide sine stătătoare (standalone)- foarte uşor de realizat deoarece Java este un limbaj
de programare complet, configurat OO. Când appleturile rulează fără browser disponibil java,
aplicaţiile standalone sunt complet autorizate, putând rula pe un calculator, sau preluâd
avantajele suportului Internet oferit de Java API. Spre exemplu Sun HotJava este scris complet
în limbajul Java.
♦ appletcation sau applet-aplicaţiile care sunt tratate în context, fie ca aplicaţii grafice
standalone de către interpretorul Java, fie appleturi de către browser disponibil java, sau
appletviewer.
♦ servlet - aplicaţii similare cu appleturile dar care rulează într-o aplicaţie ce rezidă pe un Web
server care suportă Java şi respectă conveţiile impuse. Practic servle-urile rezidă în aplicaţii
Web interactive şi înlocuiesc CGI-urile, mărind performanţele aplicaţiilor.

Crearea şi editarea codului Java presupune încapsularea în clase Java. In general fiecare clasă
trebuie să meargă cu propriul fişier sursă, numit prealabil înaintea clasei (spre exemplu:
[Link]). De fapt se pot edita mai multe clase într-un fişier sursă, depinzând de declaraţiile
public realizate şi se poate utiliza un editor standard, pentru Windows sau Unix.
Dacă se utilizează IDE (Java Integrated Development Environment) ca şi Symatecs Café pentru
Windows NT sau Natural Intelligence Roaster pentru Macintosh, se apelează la editorul
încorporat. IDE are avantajul creării documentului sursă, compilării, rulării şi depanării într-un
mediu încorporat.
Dacă appletul este integrat într-un fişier HTML, apelul se face din secţiunea BODY astfel:

<applet code = "[Link]" width=200, height=60>



<applet>

Fişierul sursă ([Link]) se salvează în acelaşi director ca şi fişierul HTML şi conţine:


import [Link];
public class Primul extends [Link] {
public void paint(Graphics g) {
[Link]("debut de programare",40,30);

5
}

Explicaţiile codului:
Pentru a avea acces la metodele de desenare pe ecran se importă clasa/clasele în care sunt declarate
aceste metode (Graphics), din pachetul [Link]. Pachetul este o legătură de clase aflate în relaţie.
Appletul este declarat ca şi clasa public, pentru a putea fi accesibilă interpreterului construit în
Web browser sau aplletviewer, de oricâte ori rulează.

Când codul sursă este compilat, numele fişierelor class este luat din numele clasei din codul sursă
şi nu din numele fişierului ce conţine codul sursă, (spre exemplu: [Link]) iar dacă în codul
sursă sunt încă două clase declarate (A şi B), atunci vor apare 3 fişiere: [Link], [Link] şi
[Link]. Menţinerea paralelismului între fişierul sursă şi fişierul de ieşire este făcută uşor,
permiţând recompilarea automată a oricărei clase necesare.
Metoda paint este apelată din exteriorul appletului ori de câte ori interpreterul java are nevoie să
afişeze sau să reafişeze un applet. Atunci când este apelată, se trece obiectul în context grafic,
(clasa Graphics) ca parametru. De aceea se importă clasa Graphics pentru a furniza compilatorului
caracteristicile clasei. AWT este legat de limbajul Java şi nu este construit în acesta astfel încât ori
de câte ori [Link]() este apelat, se apelează metoda definită în clasa Graphics pentru a
desena în context grafic. Primul parametru este şirul desenat iar ceilalţi doi sunt coordonatele
verticale şi orizontale ale punctului de unde începe linia de bază a primului caracter din şir.
Punctul este măsurat în pixeli din marginea stânga-sus a appletului pe pagină, astfel încât y creşte
ca şi cum s-ar muta în jos pe ecran.[Ramb_96]

Compilarea aplletului presupune că directorul ce conţine codul binar Java este în PATH iar
uneltele JDK sunt în CLASSPATH. Comanda de compilare este:
javac nume_fiş[Link]
Compilatorul rulează şi apoi se întoarce la prompter iar în cazul erorilor de compilare se fac
corecţiile necesare, relansând compilatorul. De obicei apelul compilatorului se face din directorul
unde se află fişierul sursă, rezultând, conform exemplului anterior:
[Link]
[Link]
[Link]
Dacă se doreşte vizualizarea sursei compilate se foloseşte:
javap -c Primul
şi apare reprezentarea în instrucţiuni a codul binar generat pentru acest fişier.
Execuţia appletului solicită un browser disponibil Java sau appletviewer oferit de JDK. Browserul
permite vizualizarea întregii pagini ce conţine appletul iar appletviewer vizualizează doar appletul,
ignorând comenzile HTML ce nu privesc execuţia appletului.
Exemple:
[Link]
sau appletviewer [Link]

Dacă apelul se face din alt director se indică şi calea completă către fişier astfel:
C:>appletviewer [Link] (la Windows 98)
sau:
appletviewer [Link] (la UNIX)

6
Observaţie:
Argumentul din appletviewer nu este fiş[Link] sau .java ci mai degrabă URL-ul fişierului html,
care include protocolul utilizat pentru acest fişier (file sau http dacă este accesat la distanţă).
Aplicaţiile standalone (de sine stătătoare) sunt semnificativ diferite faţă de appleturi în termeni de
structură. Appleturile moştenesc avantajele atributelor şi comportamentului claselor din AWT şi ca
rezultat, sunt capabile să iasă "din tipar pentru a utiliza facilităţi ale GUI din AWT. Aplicaţiile
standalone pot fi utilizate cu GUI din AWT dar solicită efort suplimentar pentru a le realiza.
Toate aplicaţiile au definită o metodă main(), care indică interpretorului de unde începe execuţia
programului.
Exemplu :
class NumeClasa{
public static void main (String args[]) {
[Link] ("Test de programare Java");

}
}
Daca în clasa care se defineşte se vor folosi elemente din alte clase disponibile în mediul Java, este
nesesară realizarea unui import de clase iar declaraţia de import trebuie să apară înaintea claselor
care folosesc elementele respective.
Exemplu : import NumeClasa
Metoda main() trebuie să accepte argumente din linia de comandă, sub forma şirului de caractere
args[ ] şi nu returneaza nici o valoare (tipul void). Metoda este aceeaşi pentru toate instanţele
clasei, fapt specificat prin cuvântul cheie static, şi poate fi invocată de orice altă clasa, fiind
declarată public. Funcţia main() ia parametri din tabloul de obiecte String trecute în linia de
comandă.
Apelând aplicaţia
Java ClasaIn master 9 9.5
Constatăm că tabloul are 3 elemente ("master","9", "9.5") iar dimensiunea acestuia este
dată de variabila [Link]
[Link] ("Test de programare Java"); echivalent cu printf din C şi cont din C++ apelând
tipărirea la consolă. Termenul de aplicaţie stand alone este greşit utilizat pentru că aplicaţia însuşi
necesită interpreterul Java pentru a o utiliza deci nu este de sine stătătoare.
Exemplu:
java Clasa

1.3. Structurarea programului

După scrierea unui program, se impune utilizarea unui compilator Java (javac) pentru a traduce
programul sursa într-un cod binar portabil. Acestă preia programul sursă Java scris în format
Unicode şi identifică elementele lexicale ale limbajului (tokens). Aceste elemente lexicale pot fi
identificatori, cuvinte cheie, literali, operatori şi separatori. In programul sursă Java, elementele
lexicale trebuie să fie separate între ele cu ajutorul următorilor separatori lexicali: spatiu (blanc),
sfârşit de linie (Enter), sau comentariu. Compilatorul traduce programul sursa Java într-un cod
binar, independent de calculator, neglijând separatorii lexicali.[java_1]

[Link]

7
Comentariile sunt secvenţe de caractere care nu afectează semantica programelor, ele având rolul
de a explica secvenţe de instrucţiuni din programul sursă. In limbajul Java există trei stiluri de
comentarii:
• Stilul /* … */, utilizat iniţial în limbajul C standard, a fost preluat apoi in C++, iar acum este
disponibil în Java şi se foloseste în cazul comentariilor pe mai multe linii.
• Stilul // … a fost adaugat în limbajul C++ pentru a uşura scrierea comentariilor într-o linie,
acest tip de comentariu fiind disponibil şi în Java.
• Stilul /** … */ este nou adaugat de limbajul Java şi este utilizat pentru întocmirea automată a
documentaţiei pentru programele Java. Acesta se poate plasa numai în faţa declaraţiilor, textul
comentariului fiind copiat automat în documentaţia aplicaţiei de către generatorul automat al
documentatiei (javadoc).

1.3.2. Unităţile de compilare


Conform normelor de programare tradiţionale, un program este o succesiune de structuri sintactice
a căror execuţie este coerentă şi acest lucru rămâne valabil şi pentru Java, cu deosebirea că o
succesiune de declaraţii şi instrucţiuni devine un program Java numai dacă este încapsulată într-o
clasă. Un program Java este în mod obligatoriu o clasă, care poate fi alcatuită la rândul ei din alte
clase sau interfeţe şi cuprinde cel putin un fişier sursa cu extensia .java. Acest fişier numit unitate
de compilare (compilation unit) este alcatuit cu ajutorul următoarelor patru tipuri de declaraţii:
declaraţii de import, declaraţii de pachet, declaraţii de clasă şi declaraţii de interfaţă.
Unitatea de compilare tipică este alcătuită dintr-o singură instrucţiune package, multiple
instrucţiuni de import şi multiple declaraţii de clasă, unele dintre acestea putând fi de tip public.
Declaraţiile reprezintă instrucţiuni sintactice, alcatuite din structuri sintactice de tip instructiuni,
declaraţii de tip sau declaraţii de clasă iar declaraţia de clasă este alcatuiă din variabile şi metode.

1.3.3. Pachete şi interfeţe


Daca o clasă va fi folosită ulterior în mai multe aplicaţii, aceasta se poate include într-un pachet,
conceput ca structură superioară sau un grup de clase, tratate ca o entitate. Spre exemplu există
pachetul de clase [Link], care conţine câteva clase de baza, folosite frecvent, cum ar fi System,
String, precum şi pachetul de clase [Link], care conţin clasele InputStream, PrintStream.
Pachetele restricţionează accesul la variabile şi metode pe baza nivelelor de protecţie definite
pentru clase. Variabilele sau metodele unui pachet care nu sunt declaraţe explicit public, private
sau protected, pot fi văzute doar de clasele din acelasi pachet şi prin aceasta se permite claselor din
acelaşi pachet să aibă acces la oricare din metode, fără a ţine cont de compromisul încapsularii
oferit de programarea orientată pe obiecte.

Declararea unui pachet se face prin inserarea la începutul fişierului a unei declaraţii de forma:
package nume_pachet, unde numele pachetelor sunt identificatori Java. Grupurile de instrucţiuni
package leagă clasele şi interfeţele pentru a evita conflictele şi pentru o mai bună organizare.
Spre exemplu definim clasa ecran utilizată atât de appletul aplic1 cât şi de aplic2. Acestea
se disting prin pachetul unde sunt plasate astfel:
aplic1_pack.ecran
aplic2_pack.ecran
unde aplic1_pack şi aplic2_pack sunt directoare din CLASSPATH.
Exemplul sugerează faptul că fiecare clasă şi interfaţă are nume unic, clasele şi interfeţele din
aceaşi pachet au nume unic şi pachetele la rândul lor au nume unic. Problema gravă apare când 2
persoane au clase pe acelaşi host, caz în care se recomandă numirea ierarhică a pachetelor.

8
Exemplu:
NumeOrganizaţ[Link]

Numele pachetelor este separat cu punct în componente, nefiind limitat numărul componentelor
dintr-un pachet. Fiecare componentă reprezintă un element din structura ierarhică, mapat direct pe
structura de directoare a sistemului unde se află memorat pachetul.
Instrucţiunea package este prima linie din unitatea de compilare, toate clasele şi interfeţele din
unitate fiind legate de acest pachet. O unitate de compilare poate avea mai multe clase şi interfeţe
membre, dar numai o instrucţiune package. Fiecare clasă aparţine unui pachet iar dacă o unitate
de compilare nu are instrucţiunea package este plasată în pachetul implicit (fără nume). Pentru
aplicaţii simple nu este recomandată dar dacă apar aplicaţii complexe cu multiple clase şi interfeţe
este de recomandat organizarea acestora într-un pachet, conform figurii 1.1.

1 FIRMA

2 FURNIZOR CLIEN

Figura 1.1. Structura de directoare pentru o aplicaţie complexă

Considerăm pachetele Furnizori şi Clienţi (nivel 2) care corespund celor 2 subdirectoare create ca
făcând parte din directorul FIRMA (nivel 1), sub CLASSPATH. Fiecare din cele 2 subdirectoare
vor conţine unităţile de compilare (nivel 3) proprii.
Astfel includem:
package [Link];
package [Link];

Respectând convenţia standard de creare a pachetelor, pachetele utilizator încep cu majusculă şi li


se dă nume unic bazat e DNS (Internet Domain Name).Pachetele ce fac parte din API standard
încep cu componenta java (litere mici).
Exemple:
[Link]
[Link]

1.3.4. Instrucţiunea import


Pentru a utiliza pachete compilate anterior este necesară importarea cu ajutorul unei comenzi de
import:[Proda-97]
Exemple:
import [Link]; // import de clasă
import [Link]; // import de interfaţă
import NumePachet.*; // import de clase şi interfeţe publice din
//pachetul specificat

9
Instrucţiunea import permite claselor utilizarea numelor abreviate pentru referirea claselor şi
interfeţelor declarate în exteriorul acestei unităţi de compilare, ceea ce conduce la un cod uşor de
citit. In schimb aceasta nu permite alte avantaje decât convenţia sintactică utilă pentru
programatori. Import se poate utiliza o singură dată într-un pachet cu nume complet de calificare
astfel:
import [Link];
şi odată plasată se poate referi clasa importată simplu: Applet fără calificare completă
[Link].

Instrucţiunea nu determină încărcarea clasei în memorie ci înregistrează doar o legătură simbolică


ce mapează direct către clasa unde poate fi găsită. Clasa se încarcă doar când este referită. La
importul tuturor claselor şi interfeţelor ( spre exemplu: import [Link].*) se cere din partea
programatorului anticiparea claselor particulare ce vor fi utilizate. Aceasta înseamnă că
interpreterul sau compilatorul caută în fiecare fişier .class la acestă instrucţiune import pentru a
vedea dacă aparţine pachetului sau nu şi pentru a face referinţă la o utilizare ulterioară. Rezultă
astfel o încetinire substanţială a vitezei de execuţie dar o siguranţă maximă în depanare. Ulterior
finalizării unităţii de compilare se înlocuieşte această instrucţiune cu importuri specifice explicite
pentru fiecare clasă şi interfaţă utilizată.
O potenţială problemă de import este dată de stil, prin care se pot introduce inadvertenţe de nume
şi implicit conflicte. Spre exemplu, există în două pachete diferite clasa Conturi şi acestea se
importă astfel:
import Pach1.*;
import Pach2.*;
In momentul în care compilatorul încearcă să redenumească local clasa Conturi ambele clase au
acelaşi nume. Nu este o eroare de utilizare a ambelor clase în aceeaşi unitate de compilare pentru
că pot fi referite complet calificate prin nume unic dar apare o eroare când se importă ambele
clase.
Erori de utilizare:
import java.* /* eroare- [Link] şi [Link] sunt pachete*/
import [Link].* //implicită

Fiecare pachet sau program java importă automat toate clasele şi interfeţele exenţiale din java şi
nu este necesar importul explicit de interfeţe ca [Link], [Link],
[Link], [Link],etc. Instrucţiunile package şi import nu generează cod ci au un
rol bine definit în programarea OO.

1.3.5. Declaraţii de clasă şi interfaţă


Moştenirea claselor va permite construcţia unei noi clase pe baza alteia existente, iar prin
intermediul cuvântului cheie extends asupra unei clase existente. Astfel pentru defini moştenirea
unei clase (exemplu: MyClass), este necesară importarea clasei respective şi referirea la ea in clasa
nou creată:
Exemplu:
import Mclasa;
class Nouaclasa extends Mclasa { // mostenitoarea clasei MClasa
// codul sursă al noi clase
}

10
Relaţia 1-1 între clasele public şi numele fişierului sursă permite compilartorului căuarea,
verificarea şi recompilarea fişierului sursă ce este memorat, cu menţiunea că numele clasei şi
fişirului sunt case-sensitive.

1.3.6. Biblioteci de clase în mediul Java

In mediul Java există mai multe pachete care conţin biblioteci de clase, unele având caracter
general, altele fiind orientate spre diferite tipuri de aplicaţii. Acestea conţin metode care se pot
folosi în programe dar pentru a putea folosi anumite clase dintr-o bibliotecă, trebuie să importăm
clasele respective sau întreaga biblioteca. Singura bibliotecă prezentă tot timpul este biblioteca de
baza a limbajului Java numită [Link].[Laur-98]
Bibliotecile de clase se împart în două categorii: cele destinate a fi folosite în programe care, după
ce sunt compilate, urmează să fie executate cu ajutorul interpretorului Java. In a doua categorie
sunt incluse applet-uri, adică subclase ale clasei Applet din pachetul [Link]. Aceste clase
sunt folosite în programe care urmează să fie executate de către browser pentru conţinut dinamic
(executabil) Java.
Mediul Java oferă pachete cu biblioteci de clase în care se gasesc metode pentru functiile de baza
ale modulelor sistemului. Compilatorul Java creaza o structură de directoare sub formă de arbore,
pentru fiecare nume de pachet fiind creat un director. In denumirea clasei se gaseste operatorul
punct (.) pentru a lega directorul java de subdirectorul care conţine o biblioteca de clasa. Pentru a
se referi aceste biblioteci sau anumite clase din biblioteci este necesară folosirea aceluiaşi operator
astfel:
[Link]
unde biblioteca poate fi ună din clasele lang, io, util, applet, awt sau net, iar clasa este clasa din
biblioteca respectivă.[Proda-97]

Java Runntime Environment (JRE) conţine maşina virtuală Java, clasele de bază şi alte fişiere
necesare rulării, Java 2 SDE (Software Development Kit) incluzând pe lângă JRE compilatorul
javac, debugger-ul şi alte instrumente de dezvoltare. O trecere în revistă a bibilotecilor existente în
limbajul Java:
 [Link] – aici se pot gasi clase în care sunt implementate funcţiile de bază din
mediul Java şi acest pachet va fi încărcat automat, odată cu compilatorul, fără a fi
necesară o declaraţie explicită de import. Această bibliotecă conţine clase pentru
extensia tipurilor elementare de date, pentru prelucrarea sirurilor de caractere, pentru
funcţii matematice, pentru interactiuni de baza cu sistemul, pentru fire de executie,
clase abstracte şi pentru biblioteci.
 [Link] se utilizează pentru verificarea entităţilor Java, a claselor şi
obiectelor, foarte utilă în realizarea unor aplicaţii dinamice şi flexibile.
 [Link] – cu rol de implementare a applet-urilor, care sunt destinate a fi
executate de un browser pentru conţinut executabil Java. Pentru a crea un applet
executabil într-o pagină Web sau rulat cu appletviewer, se poate extinde această clasa
cu metode de includere a efectelor sonore, legături cu alte pagini Web, pentru definirea
unor formate.
 [Link] (Abstract Window Toolkit) – în această biblioteca se afla clasele de bază
care oferă instrumente pentru crearea elementelor de interfaţă grafica. Prin includerea
acestor elemente de interfaţă grafica, appletul va deveni o altă intefată grafica. Clasele

11
din acest pachet includ [Link], [Link], [Link]
[Link], [Link], [Link] metode pentru crearea de ferestre,
meniuri, butoane, comutatoare, liste, bare de defilare verticale şi orizontale, operarea cu
fonturi, imagini 2D şi 3D, [Link] ce permite definirea de clase şî metode de
intrare.
 [Link] – conţine clase de bază pentru implementarea operaţiilor de intrare-ieşire în
mediul Java. Se pot efectua citiri de la dispozitivul de intrare, scrieri la unitatea
standard de ieşsire, citiri de pe disc sau din retea. Pentru efectuarea acestor operatii este
necesară folosirea metodelor gată pregatite pentru diferite structuri de informaţii:
fişiere, zone tampon (buffere), filtre, pipes.
 [Link] – este destinată funcţii speciale în mediul Java, ca suport pentru lucrul cu
date calendaristice, operaţii cu stive, operaţii cu tabele sau operaţii cu vectori. Dacă
appleturile folosesc algoritmi de compresie/ decompresie au la dispoziţie [Link]
şi [Link]
 [Link] – cuprinde clase de baza pentru crearea de interfeţe pentru protocoale de
reţea (telnet, ftp, nttp, WWW) şi legături de tip socket.
 [Link] se foloseşte pentru diverse funcţii matematice standard implementate.
 [Link] este destinată creării de componente reutilizabile, denumite beans-uri.
 [Link], [Link], [Link], [Link] asigură accesul la
obiectele distribuite şi facilitează acces la metode ale acestora. Pachetele sunt destizate
dezvoltării aplicaţiilor distribuite folosind Remote Method Invocation (RMI).
 [Link], [Link], [Link] asigură mecanismele de
securitate a softului în care sunt incluse.
 [Link] facilitează maparea API OMG CORBA în limbajul Java,
incluzând clasa ORB pe care programatorul o poate utiliza ca şi un Object Request
Broker.
 [Link], [Link], [Link],
[Link], [Link] permit dezvoltarea metodelor de intrare care
pot fi utilizate cu orice JRE.

Pentru a folosi clasele din bibliotecile de mai sus este posibil importul pachetului în întregime,
folosind declaraţia de import corespunzătoare.

Exemple:
import [Link].*;
import [Link].*;
Dacă se doreşte includerea selectivă a unor clase, pentru a reduce dimensiunile programului binar,
se precizează în declaraţiile respective.
Exemple:
import [Link];
import [Link];
Prezentăm câteva detalii ale clasei applet, destinată a fi utilizată în realizarea unei pagini HTML,
care pune accentul mai ales pe o interfaţă grafică atractivă şi interactivitate mare.
In proiectarea de applet-uri trebuie urmărit scopul aplicaţiei respective şi modul în care acesta
poate fi atins de potenţialii utilizatori pentru că un applet Java este mai mult decât un cod care să
realizeze operaţii elementare de calcul şi afişare - un mod de realizare a interfeţei cu utilizatorii.

12
Biblioteca de clase applet conţine peste 40 de clase şi interfeţe pentru dezvoltarea de programe de
tip applet iar functia de baza a acestora este de a realiza, prin intermediul metodelor obţinute, un
control asupră applet-urilor din mediu.
Clase cum sunt Basicstyle, Document ajută in controlul vizualizarii documentelor HTML şi a
oricarui applet la care se face referire din aceste documente. Clasa applet este superclasa pentru
toate applet-urile nou create şi pot fi vizualizate de browser iar un applet creat moşteneste toate
metodele clasei applet, care constau nu numai din clasa applet şi din metodele superclaselor
acestei clase, care fac parte din awt (nu din clasa applet).[Naugh-96]

1.4. Elemente lexicale şi structuri sintactice


1.4.1. Tipuri, operatori şi expresii

Setul de caractere Unicode, care se foloseşte acum în locul setului de caractere standard ASCII
permite reprezentarea caracterelor pe 16 biti, în timp ce setul de caractere ASCII foloseşte numai
8 biti. Cele doua subseturi de caractere sunt compatibile, vechiul standard ASCII fiind un subset al
setului Unicode. Această necesitate de extindere a setului de caractere - determinată de nevoia de
a reprezenta mai mult de 256 de caractere - a apărut din dorinţa de a reprezenta literele ce există în
diferite alfabete de pe glob.
Cuvintele cheie, sau cuvintele rezervate, sunt identificatori utilizati în limbajul Java într-un mod
bine precizat prin gramatica limbajului, fiind interzisăa utilizarea lor în alte scopuri. Un
identificator este o secventă de litere, cifre şi alte caractere în format Unicode, primul caracter
fiind obligatoriu o literă, un caracter underscore (_) sau simbolul dolar ($). Aceştia trebuie să fie
diferiţi de cuvintele cheie şi se utilizează pentru a desemnă variabile, clase şi metode.

Literalii se folosesc pentru a desemna valori constante în cadrul unui program Java şi au la baza
doua categorii de date: numere şi caractere. Literalii numerici se împart în două subcategorii:
întregi ( cu format: zecimal, hexazecimal, octal) şi flotanţi (numere cu parte fracţionară). Un
caracter literal se referă la o singură valoare din setul de caractere Unicode, în timp ce un şir de
caractere se referă la o succesiune de unul să mai multe caractere. Pe lângă aceştia mai există
caracterul boolean, literal considerat numeric pentru compatibilitate cu limbajele C şi C++, iar
valorile de adevar true şi false în C şi C++, sunt reprezentate prin valorile intregi 1 şi 0.
Constantele literale pot fi exemplificate astfel:
Intregi
5 întreg
5l (intreg scurt)
5L(întreg cu tip lung)
O5 întreg octal
OxaBa (hexazecimal case-sensitive)
Double şi Float
4.5, 6.7d, 7.8D - constante duble
3.4E8 - constante duble cu exponent
6.7f sau 6.7F - tip float
Booleene: true, false
Constante caracter (Escape)
\ continuare în linia următoare
\n linie nouă
\t tab orizontal

13
\r carriage return
\f form feed
\\ backslash
\' apostrof simplu
\" apostrof dublu
\ddd formă octal
\xdd formă hexa
\uddd caracter unicode
"exemplu" sir de caractere

Separatorii, delimitatorii şi terminatorii sunt caractere utile compilatorului pentru a detecta


elemente lexicale dar înafară de spaţii, tab-uri mai există şi alti separatori, denumiti delimitatori
sau terminatori, care participă la construcţiile sintactice ale limbajului. O parte dintre aceştia au un
rol activ în structurile sintactice ale limbajului, şi ar putea fi considerati operatori. De exemplu
punctul (.) se foloseşte pentru a obţine un nume unic pentru clasa care aparţine unei biblioteci, prin
concatenarea numelui clasei cu numele bibliotecii: [Link] spre exemplu.
O variabilă reprezintă o adresa de memorie în care se păstrează o valoare de un tip prestabili,
fiecare variabilă fiind inclusă în declaraţii de forma:
tip identificator[, identificator];.
La întâlnirea unei declaraţii de acest fel, compilatorul crează pentru fiecare identificator din listă
câte o variabilă având numele identificator şi tipul tip. După crearea unei variabile, i se poate
atribui o valoare iar tipul variabilelor specifică natura valorii variabilelelor şi ce fel de operaţii sunt
admise asupra acestora. In limbajul Java există doua categorii de tipuri: simple – care nu sunt
construite cu ajutorul altor tipuri, intreg, flotant, boolean şi caracter şi tipurile compuse – care se
crează pe baza unor agregări de tipuri simple (tablourile, clasele şi intefeţele).[Naugh_96]
Domeniul de aplicabilitate al variabilei este în zona de program unde este recunoscută, de
la declararea acesteia până la finalul blocului
Exemplu:
Class Vedem {
int a /*zona a */
void vedemMethod (double c) {
//zona c
int x,y;
// zona x,y
….
}
void vedemMethod2 (int a) {
//zona a unde variabila este locala pt.vedemMethod2
// instanţierea variabilei din clasa Vedem şi traterea ca
//variabila globală
this.a=a;
// zona z;
float z;
….
}
}

14
Tipulile întregi sunt tip de dată şi pot fi caracterizate: byte ( 8 biţi), short (16 biţi), int (32 biţi) şi
long (64 biţi) dar spre deosebire de clasă nu există un comportament asociat tipului întreg.
Clasa Integer din [Link] are declaraţia:
class IntegerClass // conţine variabile intregi
//si set de metode de activare
int MAX_VALUE;
int MIN_VALUE;
public static String toString(int i) //metoda
{…}
}
Spre deosebire de C sau C++ unde dimensiunea diferitelor tipuri de primitive este dependentă de
calculator la Java tipurile de primitive au dimensiune fixă, indiferent de hard-ul unde rulează
maşina virtuală Java.
Tipurile întregi sunt cu semn, fiecare variabilă declarată întreg putând lua valori +/- iar tipul
determină nivelul valorii şi proprietăţile aritmetice ale variabilei ce-l deţine. Dacă o valoare
depăşeşte dimensiunea de reprezentare se trunchiază automat la modulo rang.

Exemplu:
Dacă byte b=-129; => b=-129-(-256)=127
Dacă byte b=128; => b=-128-256=128

Tipul Floating-Point (IEEE 754) permite reprezenarea float (32 biţi) şi double (64 biţi) implicit
fiind double. Pentru testarea depăşirii superioare sau inferioare se utilizează variabila NaN (not a
number).
Tipul caracter este definit conform reprezentării Unicode la 16 biţi/caracter (spre deosebire de C
unde se reprezintă la 8 biţi/caracter) iar la iniţializare se foloseşte apostof simplu.
Exemplu:
char a, b='parola', c='\n';
Tipul boolean are două valori (true sau false) iar maşina virtuală Java îl gestionează în mod
propriu, manipulând biţi individuali ai caracterelor întregi, astfel încât se pot declara mai multe
variabile boolean, fiecare solicitând un bit. In Java valorile booleene nu sunt numere şi nu pot fi
convertite sau operate ca întregi.
Tablourile sunt liste de elemente separate prin virgulă, crete cu operatorul new.
Exemple:
int col[ ]= new int [3];
int [ ]col= new int [15];
int col[ ]; // echivalent cu int [ ] col

col = new int[3]; //alocarea dinamică a memoriei

Variabila col are lungime 3 (întreagă) indexată [0-2] şi poate beneficia de alocare
dinamică ceea ce permite programatorului să rezerve spaţiu optim pentru memoria alocată.
Exemple:
int n=2;
double d=5.5;
double Dtablou1[ ]=new float[n+1] //corect
double Dtablou2[ ]=new float[d] //eronat

15
double Dtablou3[ ]=new float[int(d+2)] //corect
//iniţializarea elementelor
Dtablou[0]=0.1;
Dtablou[1]=0.12;
Dtablou[2]=-0.13;

//tablouri multidimensionale
int mat1[ ] [ ] = new int [2] [3];
//sau
int [ ] [ ]mat1 = new int [3] [5];
La tablourile multidimensionale precizarea ultimei dimensiuni este opţională:
int [ ] [ ]mat1 = new int [3] [ ];
Este necesară însă definirea celei de a n-a dimensiuni prealabil utilizării ei:

Exemplu:
for (i=1, i<3, i++) {
mat1[I]=new int [5];
}
Alocarea memoriei pentru tablouri se face tot cu operatorul new, cu excepţia iniţializării în
timpul declarării:
char litere[ ]={'a','j', 'p','l','m','n'};//tablou de 6 elemente
Operatorul new este utilizat pentru memorarea oricărui tip compus (tablou, obiecte din
clasă, interfeţe) iar alocarea explicită pentru tipurile de bază nu este necesară.

Exemplu:
char a; // nu trebuie new
char char Tab1[ ] = new char[3];
In timpul compilării se crează clasa tablou are marchează clasa compilată şi este un obiect
ce nu trebuie subclasat explicit (figura 1.2).[Hoff_96]
Obiect

Array

byte[ ] short[ ] int[ ] long[ ] float[ ] double[ ] char[ ] boolean[ ]

Figura 1.2. Ierarhia de tipuri în Java

1.4.2. Tablouri versus pointeri în C

Este deja cunoscut faptul că în C pointerul este adresa unei variabile, orice porţiune de memorie
fiind accesibilă prin pointeri. Pointerul aritmetic oferă unul din cele mai puternice concepte C
oferind posibilitatea calculelor (+,-,/,*) şi putând fi utilizat la accesarea memoriei. In Java s-a
elinminat accest concept recunoscută fiind periculozitatea utilizării eronate a pointerilor aritmetici
şi s-a introdus handler (manipulator).[Chan_95] Un handler Java este asociat cu un obiect şi nu cu
o adresă.

16
Exemple:
int col [ ];//handler null

int mat1[ ][ ]= new int [4] [ ];

Instrucţiunea precedentă alocă memorie pentru cei 4 manipulatori (mat1[0], mat1[1], mat1[2],
mat1[3]) şi fiecare punct la null. Alocarea dinamică pentru tabloul actual se realizează cu secvenţa:
for (i=1, i<3, i++){
mat1[I]=new int [3];
}
matricea mat1 este:

0 1 2...
3
int int
int int int int int int
int
int int int
2

Figura 1.3. Alocarea dinamică la tablouri

1.4.3. Operatori
Operatorii sunt folosiţi pentru a realiza anumite operaţii elementare între obiecte, fiecare operator
joacă şi rolul de separator între două elemente lexicale şi au prorpietăţi similare cu cei din C:
precedenţa (ordinea în care sunt interpretaţi) şi asociativitatea (direcţia de evaluare). [Laur-98]

Operatori Precedenţa Asociativitatea


. Accesoriu de clasă, variabilă,
metodă
[] Accesoriu de tablou
() Casting Stânga la dreapta
++ Increment
-- Decrement
! Not
~ Complement unar
Instance of Test subclasă
* Multiplicare
/ Impartire
% Modul Stânga la dreapta
+ Adunare Stânga la dreapta
- Scădere Stânga la dreapta
<< Deplasare stânga Stânga la dreapta
>> Deplasare dreapta Stânga la dreapta
>>> Deplasare dreapta cu umplere cu 0 Stânga la dreapta

17
Operatori Precedenţa Asociativitatea
< Mai mic
> Mai mare
<= Mai mic sau egal
>= Mai mare sau egal
== Test de egalite
!= Test not equal
& Si binar
^ XOR binar
| OR binar
&& And
|| OR
?! Operator ternar condiţional Dreapta la stânga
=,+,=,- Atribuiri
=,*=,/+,
%=,&=,^=,|
=,<<=,>>=
a operand b Echivalent cu a=a operand b
a+=b echivalent cu a=a+b

Tabelul 1.1. Operatori Java

Dacă rezultatul calculelor este de tip întreg şi operandul este long se realizează conversia la tipul
long, înrest rezultatul este int.
Exemplu:
class Test1{
public static void main(String args[ ]) {
short i=10, j=11,k;
int m;
k=i+j; //eroare, trebuie forţată explicitarea
k=(short) (i+j); // k=21
m=i+j; // m=21
}
}

Dacă rezultatul produce o depăşire superioară sau inferioară el va fi trunchiat la dimensiunea de


reprezentare.

Exemplu:
class Test2 {
public static void main(String args[ ]) {
Integer i= new Integer(0);
int overflowN=i.MAX_VALUE+1;
//valoarea maximă posibilă
[Link] ("valoarea minimă posibilă=" +i.MIN_VALUE);
[Link] ("valoarea care depăşeşte="+overflowN);

18
if(i. MIN_VALUE=overflowN)
[Link] ("truncherea");
}
}
Rezultatul programului:
valoarea minimă posibilă=-2147483648
valoarea care depăşeşte=-2147483649
truncherea
Operatorii acceptaţi pentru tipuri întregi sunt =,-,*,/,%,++,-- şi op=
Operatorii ~,<<,>>,>>>,&,^,| iau operanzi de tip întreg şi întorc valori întregi iar operatorii
<,>,<=,>= iau operanzi de tip întreg şi întorc valori booleene. Pentru tipurile de virgulă flotantă
sunt acceptaţi operatorii de tip întreg mai puţin cei la nivel de bit. Definiţia modulo este diferită de
cea dată pentru întregi. Dacă x şi y sunt double sau float:
x%= [Link](x/y)*y
Dacă numărul are parte fracţionară 5 este convertit la întregul superior.
[Link](7.0/2.0)= [Link](3.5)=4
Spre deosebire de tipul întreg la cele float depăşirea superioară generează Inf(infinit) şi cea
inferioară generează 0 iar rezultatul împărţirii cu o generează Inf.

Exemple:
double depsup=1.0/0.0 // overflow
double depinf=27/0.0 // underflow
Operatorii relaţionali se utilizează cu precauţii în comparaţii pentru că dacă a<b este fals, nu
implică a>=b sau a!=b nu înseamnă a>b || a<b
NaN este un număr fără semnificaţie, fără semn şi nu poate fi comparat nici măcar cu el însuşi,
pentru că rezultă din calcule.
Exemplu:
double a=0.0/0.0;
if ([Link](a))
[Link] ("a este NaN");
else
[Link] ("a nu este NaN");

double b=a;
if ([Link](b))
[Link] ("b este NaN");
else
[Link] ("b nu este NaN");

if (a==b)
[Link] ("a==b");
else
[Link] ("a!=b");

Rezultatul obţinut:
a este NaN
a!=b

19
Operatorii de tip boolean sunt relaţionali sau logici şi folosesc şi produc valori booleene.
Exemplu:
return((mask>0)?true:false;
echivalent cu:
if (mask>0)
return true;
else
return false;

Operatorii de tablou [ ] se folosesc pentru a crea o dimensiune specificată sau pentru a


regăsi o parte din informaţiile din tablou.
Exemple:
Tip NumeTablou [ ] = new tip[dimensiune];
int [ ] [ ] = new int[3][ ];
NumeTablou[expresieIntreaga];
a[1]; a[n+5];// n intreg

Tablourile pot fi accesate cu valori cuprinse între [0,dimensiune-1] iar încercarea de


accesare a tabloului înafara acestor limite generează :
Array Index Out Of Bounds Exceptions.
Operatorii pentru obiecte şir sunt + şi += deşi mult timp metodele [Link]() au fost
metode aplicate pentru concatenarea şirurilor.
Operatorii pentru obiecte sunt: new, necesar pentru instanţierea obiectului şi instanceof,
utilizat pentru test dacă obiectul specificat este instanţiat unei subclase/clase.
Exemple:
String str1=new string();
….
if(str1 instanceof String)
[Link] ('str1 este instanţiat');
In Java orice tip numeric poate fi transformat (casting) cu excepţia transformărilor tipurilor
de bază în tipuri compuse.
Exemple:
float f=float(3.7);
int i;;
i=int(f);//i=3
f=float(i);//f=3

Transformarea subclaselor şi superclaselor este permisă dar deşi o instanţă poate fi transformată în
superclasă, transformarea unei subclase generează erori de execuţie. Interpreterul Java verifică
dacă subclasa este extensie a unei superclase transformate şi dacă un obiect nu este instanţă de
subclasă (sau una din subclase) se rulează rutina Class CastException. Expresiile sunt combinaţii
de variabile, literali şi operatori ce determină un rezultat. Atribuirea este procesul de memorare a
valorii iar variabila căreia I se atribuie se numeşte variabila stângă. Separatorii Java din expresii
sunt ( ), { }, [ ] ;,. Ordinea de evaluare este dată de dictată de precedenţele operatorilor şi de
separatorii incluşi.

20
1.5. Instrucţiuni de control al fluxului de execuţie
1.5.1 Instrucţiunea label
label:
Instrucţiunea label serveşte la etchetarea blocului în care se află. Ea nu modifică fluxul de
prelucrare ci serveşte ca marker pentru eventuale salturi în secvenţe normale. Java procedează la
scurtcircuitarea evaluărilor astfel încât pentru un operator de tip && la prima evaluare de expresie
falsă renunţă la evaluarea expresiei rămase. Pentru o mai bună optimizare, dacă în compilare se
identifică valoarea falsă întotdeauna, la o evaluare de expresie dintr-un if, nu se generează cod
pentru ramura true.

1.5.2. Instrucţiunea IF
if <expl1> {
Instrucţiuni1 ;
[else } if <expl2> {
instrucţiuni2;
}else {
instrucţiuni3 ;]
}

Instrucţiunea execută primul set de instrucţiuni <instrucţiuni1> dacă <expl1>=true


(adevarată) şi daca <expl1>=false (falsă) se execută setul de după else (adică unul sau mai
multe teste if imbricate, condiţionate <expl2>, sau setul de instrucţiuni <instrucţiuni3> .
Când else nu este specificat se execută instrucţiunea de după }. Se pot imbrica mai multe
conenzi if succesive, marcate între paranteze {} iar evaluarea se face de sus în jos.

1.5.3. Instrucţiunea switch

switch (expr) {
case const1: instrucţiuni1;
break;
case const2: instrucţiuni2;
break;

default: instrucţiuniN;
}
Instrucţiunea switch este în realitate echivalentul unui if imbricat, unde:
 expr - este o expresie tip caracter, byte, short sau int;
 const1, const2, constN - valori constante ce sunt asociate execuţiei grupurilor
de instructiuni;
 instrucţiuni1, instrucţiuni2, … - grupuri de instrucţiuni care se execută
condiţionate de const1, const2, constN;
 default -- grup de instrucţiuni (instrucţiuniN) care se execută dacă nici una din
condiţiile de const1, const2, constN nu este îndeplinită.
Exemplu:
import [Link].*;

21
class UnDictionar {
public static void main (String args [ ] ){
char alege;
[Link] ("Selectati una din lectiile de instruire:");
[Link] ("AWT");
[Link] ("API");
[Link] ("Corba");

[Link]();
try {
switch (alege=(char)[Link]();
{
case "W": [Link] ("am selectat AWT");
break;
case "P": [Link] ("am selectat API");
break;
case "C": [Link] ("am selectat Corba");

default: [Link] ("Selectie eronata");

}
catch(IOException e)
{ [Link] ([Link]());
}
}
}

1.5.4. Instrucţiunea while


while (exprl) {
instrucţiuni;
}

Instrucţiunea while permite execuţia grupului de instrucţiuni până când expresia logică
expl evaluată este adevărată.
Exemplu:
int i;
boolean test=false;
while (test == false){
i=(int)([Link]()/500);
}
if (i%2==0)
test=true;
}

1.3.5. Instrucţiunea do
do {
instrucţiuni;
}
while (exprl) ;

22
Spre deosebire de instrucţiunea while, instrucţiunea do permite execuţia grupului de
instrucţiuni cel puţin odată, prealabil evaluării expresiei logice expl .
Exemplu:
int i;
boolean test=false;
do {
i=(int)([Link]()/500);
}
if (i%2==0)
test=true;
}
while (test == false)

1.5.6. Instrucţiunea for


for (expresie1, expresie booleană, expresie2) {
instrucţiuni;
}

Instrucţiuea for (de ciclare) execută grupul de instrucţiuni, pornind de la expresia1, până
când este îndeplinită condiţiă dată de expresia booleană, cu pasul (incrementul) dat de
expresie2.
Exemplu:
int k=7;
int []vo= new int[k];// vector
for (int i=0, i<k, i++) {
vo[i]=(int)([Link]()/100);
}

1.5.7. Instrucţiunea break


break [etichetă];
Instrucţiunea break determină întreruperea fluxului normal de execuţie şi se foloseşte în
corpul instrucţiunilor switch, while, do, [Link] lipsa etichetei controlul se trece la prima
instrucţiune de după cele condiţionale sau repetitive (switch, while, do, for). Eticheta
trebuie să aibă corespondent o instruţiune executabilă.

Exemplu:
public int cautMatrice (int [ ] [ ] matrice, int [ ] tinta){
int sumaMatr=0;
for (int nTinta=1, nTinta<[Link], nTintai++) {
nouaTinta:
for (int i=o, i<[Link],i++) {
for (int j=0, i<matrice[0].length, j++) {
sumaMatr++;
break nouaTinta;
}
}
}

23
return sumaMatr;
}

1.5.8. Instrucţiunea continue


continue [etichetă];
Instrucţiunea continue este similară cu break şi se foloseşte în corpul instrucţiunilor
iterarive ca: while, do, for, mai puţin [Link] absenţa etichetei controlul este redat la
sfârşitul blocului unde se află aceasta. Dacă este plasată într-un bloc finally se execută
blocul finally şi se predă contolul la sfârşitul blocului. Intr-o buclă do sau while, expresia
booleană este evaluată imediat după continue, iar dacă este plasată într-o buclă for, înaintea
expresiei booleene se execută expressionexe_after_one_iteration. Dacă instrucţiunea este
etichetată, eticheta trebuie să fie inclusă în instrucţiuni iterative, altfel se trece controlul la
cel mai apropiat bloc iterativ.
Exemplu:
class Lot ;
int numMatrice [ ];
//constructorul
Lot(int [ ]nP){
//alocarea memorieii
NumMatrice= new int[nP];
}
//generare numere aleatoare
public void pick(){
int num;
for (int i=0, i<[Link]) {
//I se incrementează dacă numărul din curenta iteratie nu a fost //extras
num=(int)([Link]()*33)+1;
if (duplicat(i,num)) {
//num se atribuie lui numMatr si i nu se incrementează
continue;
}
numMatr[i++]=num;
//aici continua
}
}
//intoarce true daca numarul a fost extras
private boolean duplicat(int nP, int num) {
for (int i=0, i<nP, i++) {
if (numMatr[i]==num)
return true;
}
return false
}
}
}

24
1.5.9. Instrucţiunea return
return [valoare intoarsă];
Instrucţiunea return este utilizată de o metodă sau constructor pentru a întoarce controlul la
apelant şi apare în mod uzual la finalul metodei sau constructorului. Dacă metoda întoarce
tip void sau constructorul nu are tip întors, return este opţional. Se poate folosi şi pentrua
forţa întoarcerea, ca mod de prevenire a execuţiei restului metodei, ceea ce salvează nivelul
indentărilor, permiţând un cod uşor de citit (în aceste cazuri este inclusă în if).
Exemplu:
void Lot (int x) {
if (x<=20) {
return;
} else return;
void altLot (int x){
if (x>20) {
return;
}
}
In cazul în care metoda sau constructorul este declarat cu tip de valoare întoarsă, instrucţiunea
return trebuie să întoarcă tipul corespunzător declaraţiei. Dacă return este inclus într-un bloc try,
urmat de finally, instrucţiunile finally din bloc sunt executate înainte de a reda controlul
apelantului.

1.6. Manipularea şirurilor

Crearea şirurilor în Java se realizează cu operatorul new iar concatenarea lor cu append
Exemplu:
String d = new StringBuffer ("Am obtinut");
.append (calif)
.append ("la testul de baza")
.toString();

Secvenţa de mai sus este echivalentă cu


String d = "Am obtinut"+calif+"la testul de baza";

Caracteristicile precedenţei operatorilor


In exemplul de mai sus, valoarea int este trecută metodei supraîncărcate append în StringBuffer,
care o converteşte în reprezentare şir la sfârşitul instanţei StringBuffer. La expresii mixte, ce
conţin mai multe valori, operatorul + are precedenţe diferite.
Exemplu:
String d2 = "Am calculat:"+2+2;
//ceea ce conduce la d2= Am calculat:22

1.6.1. Conversia şirurilor


StringBuffer este o versiune supraîncărcată a metodei append pentru orice tip posibil. La fiecare
concatenare (operatorul +) este apelată versiunea potrivită a metodei append. Metoda cheamă de
fapt metoda String denumită valueOf pentru a construi reprezentarea şir. Pentru tipuri simple,
valueOf crează reprezentări şir vizibile de int sau float iar la obiecte apelează metoda toString a

25
obiectului respectiv. Fiecare clasă implementează toString în virtutea implementării moştenite din
clasa Object.
Exemplu:
class Point {
int x,y;
Point (int x, int y);
this.x=x;
this.y=y;
}
public String toString() {
return "punctul ("+x+","+y+")";
}
}

class DemoSir() {
public static void main ( String args [ ] ) {
Point p = new Point (20,30);
[Link]("Obtinem"+p);
}
}

Versiunea clasei Point include suprascrierea metodei toString din object, formată dintr-un şir
conţinând valorile curente (x,y) ale instanţei Point. Ieşirea este dată de:
Obtinem punctul (20,30).

1.6.2. Extragerea caracterelor


Extragerea caracterelor se realizează cu metoda charAt pentru un singur caracter şi care
presupune parametri cuprinşi în intervalul (o, length()) ai şirului [Link]ă se doreşte extragerea
mai multor caractere se foloseşte metoda getChars ce permite specificarea indexului de început şi
de sfârşit al subşirului, precum şi tabloul de tip char în care s eva plasa rezultatul.
Exemplu:
class DemosubSir() {
public static void main ( String args [ ] ) {
String s= "Exemplu de utilizare a metodei getChars");
int start=6;
int sfarsit=20;
char buf[ ] = new char[sfarsit-start];
[Link](start, sfarsit, buf, 0);
[Link]("Obtinem subsirul"+buf);
}
}

Metoda getChars nu include char la sfârşitul indexului şi este foarte utilă în special la exportul
String într-un mediu ce nu suportă 16-biţi Unicode. Protocoalele Internet folosesc 8-biţi ASCII
pentru text. Faţă de această metodă, apar particularităţi de xtragere a caracterelor la metodele:
 toCharArray, care întoarce un tablou de caractere pentru întregul şir;

26
 getBytes care ia caractere dintr-un tablou de biţi, în ordinea apariţiei acestora şi este
similară cu getChars cu deosebirea că al treilea parametru este tablou de byte.

1.6.3. Comparaţia şirurilor


Comparaţia prin egalitate la tipul string se realizează cu metodele equal sau equalIgnoreCase.
Metoda regionMatches este folosită pentru compararea unei regiuni specifice din interiorul unui
şir cu o altă regiune specifică din alt şir, ignorând sau nu UpperCase şi LowerCase. Prototipul
funcţional este:
boolean regionMatches (int tooffset, String altsir, int aoffset, int len);
boolean regionMatches (boolean ignoreCase, int tooffset, String altsir, int aoffset, int
len);
unde int tooffset - regiunea specifică
String altsir al doilea şir
int aoffset - regiunea specifică din al doilea şir
int len - dimensiunea de comparaţie.

Cele două şiruri sunt comparate pe dimensiunea len caractere, începând de la cele două offset-uri
specificate. Pentru verificări speciale impuse şirurilor se folosesc două metode
pereche:startsWith, care verifică dacă şirul începe cu parametrul transmis şi endWith, care
verifică dacă şirul se termină cu parametrul transmis şi sunt deosebit de utile în programarea
appleturilor.[Chan_95]
Exemple:
"[Link]("ie") returnează true
"[Link]("Cat") returnează true
"[Link]("eg",3) returnează true

Egalitatea dintre şiruri poate fi testată fie cu metoda equal, fie cu operatorul ==, deosebirea fiind
fundamentală deoarece metoda equal compară caracterele din interiorul tipului String pe când
operatorul == compară două referinţe obiect.
Exemplu:
class DemoEgalSir() {
public static void main ( String args [ ] ) {
String s1= "Exemplu de utilizare a metodei equal");
String s2= new String(s1);
[Link](s1+"egal cu sirul s2"+s2+'->"+ [Link](s2));
[Link](s1+"==cu sirul s2"+s2+'->"+ (s1==s2));
}
}

In exemplul de mai sus, s1 este creat ca instanţă de şir iar s2 este creată prin construtor String care
ia intrarea şi o întoarce caracter. Fiind obiecte distincte ele nu sunt == dar sunt equal. Ordinea într-
un şir este determinată cu metoda compareTo.
Exemplu:
class DemoBubbleSortlSir() {
static String arr[ ] = {"acum", "facem","ordonare", "prin", "comparatie", "de",..}
public static void main ( String args [ ] ) {
for (int j=0, j<[Link], j++) {

27
for (int i=0, i<[Link], i++) {
if arr[i].compareTo(arr[j])<0) {
String t= arr[j];
arr[j] = arr[i];
arr[i]=t;
}
[Link](arr[j]);
}
}
}
Căutarea în şir se poate face cu indexOf sau lastIndexOf care sunt supraîncărcate în orice mediu,
pentru a căuta caractere sau subşiruri, începând de la offset până la sfârşitul sursei String.
Exemple de utilizare:
int indexOf ( int ch);
int lastIndexOf ( int ch);
int indexOf ( String str);
int lastIndexOf ( String str);
int indexOf ( int ch, int index); - cautare de la indexul precizat
int lastIndexOf ( int ch, int index);
int indexOf ( String str, int index );
int lastIndexOf ( String str, int index);

Modificatorii de copiere ai şirurilor


De vreme ce String nu este modificabil, pentru a realiza totuşi operaţii de modificare, se copiază în
StringBuffer sau se foloseşte una din metodele String de construire a unei noi copii, cu modificări
complete.
Metodele uzuale folosite sunt:
• substring permite extragerea unui subşir:
• concat crează un nou obiect prin concatenare;
• replace ia două caractere ca parametri şi toate apariţiile primului caracter din şir sunt înlocuite
cu al doilea caracter;
• toLowerCase şi toUpperCase converteşte şirurile;
• valueOf este folosită pentru acele tipuri ce pot fi converite în şir. Metoda este apelată de
operatorul + al tipului String, prin metoda append a lui StringBuffer şi este practic echivalentă cu
toString.
Exemple:
"Pentru un sir".substring(4)

1.7. Clase frecvent utilizate în programare


1.7.1. Clasa Math

Această clasă oferă o gamă diversificată de metode necesare efectuării operaţiilor de bază la
nivelul tipurilor int, double, float, etc.Fără a intra în detalii de funcţionare, cunoscute de altfel la
limbajele de generaţia a treia şi a patra, prezentăm câteva funcţii utile:[Naugh_96]

Funcţiile trigonometrice sunt realizate cu:


sin/cos/tan (double a) - sinus, cosinus, tangentă de unghi exprimat în radiani;

28
asin/acos/atan (double a) - arcsinus, arccosinus, arctangentă;
atan2 (double a, double b) - arctangentă(a/b);

Funcţii exponenţiale şi logaritmice:


pow(double x, double y);- puterea unui număr yx
Exemplu:
x=pow(2,3); //x=8
exp (double x);
log (double x);
sqrt (double x);

Rotunjirea numerelor se realizează cu funcţiile:

ceil (double x); //cel mai mic întreg >=a


floor (double x); //cel mai mare număr <=a
rint (double x); //valoarea trunchiată double a lui a
round (float x); //valoarea trunchiată a lui a
round (double x); //valoarea trunchiată double a lui a

Alte funcţii matematice des utilizate:


abs(a); //valoarea absolută
min (a,b); //valoarea minimă dintre a şi b
max (a,b); //valoarea maximă dintre a şi b

1.7.2. Clasa Random

Random este clasa ce generează 5 tipuri de numere aleatoare care pot fi extrase din obiectul
Random:[java_1]
 int, uniform distribui în rang int, extras cu metoda nextInt;
 long, uniform distribui în rang long, extras cu metoda nextLong;
 float, uniform distribui în rang float, extras cu metoda nextFloat;
 double, uniform distribui în rang double, extras cu metoda nextDouble;
 nextGaussian, care întoarce distribuţia Gaussiană double, centrată 0.0, cu deviaţie standard
de 1.0 (curba clopot- bell curve);

1.7.3. Clasa Date

Clasa Date este utilizată la reprezentarea orei şi/sau timpului şi are câţiva constructori de bază:
 Date(year, month, date);
 Date(year, month, date, hours, minutes);
 Date(year, month, date, hours, minutes, seconds).

Metodele implementate getYear, getMonth, getDate, getDay, getHours, getMinutes, getSeconds


întorc valori întregi date de anul/luna/data/ziua/ora/minutul/secunda curentă iar metodele setYear,
setMonth, setDate, setDay, setHours, setMinutes, setSeconds iau valori întregi ca parametru şi
permit setarea datei.

29
Reprezentarea long poate fi realizată prin getTime iar comparaţia dintre două obiecte de tip Date
se face cu una din metodele:
Boolean before (Data cand);
Boolean after (Data cand);
Boolean equals (alta Data ).
Obiectele Date pot fi convertite în String prin metoda toString sau toLocalString respectiv
toGMTString. Dacă se doreşte obţinerea unui offset în minute faţă de GMT se foloseşte
getTimezoneOffset.

1.7.4. Clasa Runtime

Runtime este clasă încapsulată în procesul de rulare a interpreterului Java. Practic nu se poate
instanţia Runtime, se pot doar referi obiecte ce rulează prin metoda statică [Link].
Sunt câteva metode de control a stării şi comportamentului maşinii virtuale prin
SecurityException. Metoda exit (int cod) dă o ieşire cu codul erorii întâlnmite la execuţia
programului.[java_8]
Managementul memoriei se face prin GC iar metodele totalMemory() şi freeMemory() din
Runtime dau memoria totală ocupată respectiv memoria liberă.
Metoda exec() permite apelul altor programe cu nume specificat la fel ca şi parametri de intrare.
Problema este că programul se execută independent de sistem. Metoda exec() întoarce obiectul
Process care poate fi utilizat la controlul modului în care programul java interacţionează cu noul
proces executabil.
Exemplu:
class ExeDemo {
public static void main (String args [ ] ) {
Runtime s = [Link]();
Process p=null;
Sting cmd[ ] = {"notepad", "java/lang/[Link]"};
try {
p=[Link](cmd);
} catch (Exception e) {
[Link] ("eroare la execuţie"+cmd[0]);
}
}}
Procesul returnat de exec poate fi manipulat după ce noul program a început rularea şi se poate
distruge procesul cu metoda destroy().
Metoda waitfor() determină aşteptarea programului până când a terminat subprocesul iar metoda
exitValue() întoarce valoarea de ieşire din subproces ( număr natura sau 0 dacă ieşirea a avut loc
fără probleme).

2. Programarea orientată obiect în Java

[Link] Java
2.1.1. Caracteristicile claselor în Java

30
Arhitectura limbajului Java este bazată pe metodologia orientată spre obiecte. Inafară de tipurile
fundamentale (int, float, char, boolean), în Java totul se reprezintă prin obiecte denumite clase.
Prin încapsularea caracteristicilor limbajului în clase, Java devine un mediu extensibil în care
programatorii pot folosi rutinele din alte programe sau aplicaţii. Limbajul Java evalueaza structura
claselor în mod dinamic în momentul executiei şi datorită dinamicii, bibliotecile de clase pot fi
reutilizate cu uşurinţă.

Moştenirea multiplă - caracteristica specifică limbajelor orientate pe obiecte nu este prezentă în


limbajul Java dar pentru a suplini acest neajuns, limbajul Java pune la dispoziţia utilizatorilor o
facilitate numită interfaţă, care permite definirea unui anumit comportament pentru o clasa de
obiecte, altul decât cel definit de clasa de bază.
Implementarea unui obiect în Java poartă denumirea de clasă iar declaraţia unei clase este văzută
ca un model pentru crearea obiectelor. Ulterior declarării unei clase, aceasta se poate utiliza
pentru crearea mai multor obiecte de tipul respectiv sau se pot defini în program noi tipuri de
variabile iar dacă tipurile fundamentale sunt predefinite, tipurile noi se pot crea după nevoia
utilizatorului.

Clasa Object

Clasa 1 Clasa n

Clasa 11 Clasa 1m Clasa n1 Clasa np

Figura 2.1. Reprezentarea ierarhiei de clase în Java

Limbajul Java pune la dispozitie metode şi operatori pentru crearea variabilelor de clasă, dar este
necesară definirea unei metode de creare a clasei şi ulterior se poate crea o altă clasa că şi copie a
obiectului (adică a definiţiei de clasă) utilizând operatorul new. [Lema_98]
Metoda de creare are acelaşi nume cu numele clasei şi nu returnează nici o valoare dar prelabil
apelului metodei de creare trebuie alocată memoria necesară instanţierii şi initializată cu valorile
specificate sau implicite. Pentru a crea o clasă care foloseşte o altă clasă (initial construită),
este necesară o instanţiere a clasei cu operatorul new.
Exemplu:
clasa varClasa= new clasa()
unde clasa este numele clasei, varClasa este numele variabilei care se declară, iar clasa este
constructorul variabilei respective. In continuare, variabila varClasa va putea conţine o referintă la
un obiect de clasa clasa sau la un obiect derivat din clasa creată.[Lema-96]

La executia unui applet sau o aplicaţie de sine stătătoare într-un browser, în mediul Java se
creeaza o instanţiere (adica o variabilă) a clasei încărcate. Toate clasele in limbajul Java sunt
descendente dintr-o clasa superioară numită Object, clasele proprii putând fi create prin derivare

31
sau moştenire din Object sau din orice altă clasa, care la rândul ei moşteneste direct sau indirect
clasa Object. In figura de mai jos se prezintă structură ierarhică a claselor din mediul Java.
Pe fiecare ramură din ierahia de mai sus, subclasa moşteneşte proprietăţile superclasei şi astfel,
chiar dacă o clasă nu succede direct din clasa Object, ci în urma unei şir de succesiuni, această
clasă este totusi o subclasă a lui Object. Clasa Object este singură clasa care nu are o superclasa şi
poate fi considerată ca un tip fundamental dar dacă pentru clasă nu se declară explicit ascendentul,
în mod implicit acea clasă este o succesoare directă a clasei Object.[Naugh-96]

In Java declararea unei clase se realizază prin:


[modificatorii clasei] Class nume [ extends superclasa ]
implements Interfaţa1, interfaţa2, …, interfaţaN {
//corpul clasei (cu declaraţii de variabile şi metode)

}
Dacă se declară o clasa cu public class NumeClasa, această clasă nou creată va fi o subclasă a
clasei obiect, deoarece nu este specificată în declaraţie clasa din care este derivata. Clasa se
declară public pentru ca apoi să fie plasată intr-un pachet şi exportata. In cazul in care clasa este
declaraţă in acelasi fişier in care este şi utilizata, declaraţia public nu este necesară.
După crearea unei clase este necesară definirea variabilelor clasei. Pentru fiecare variabila din
interiorul unei clase, se va specifica tipul precum şi identificatorul variabilei după modelul: tip
nume. In clase se includ şi metode, pentru a realiza anumite calcule, iar rezultatul să poată fi
returnat sub forma unei valori de tipul tipReturnat, conform declaraţiei de metodă:
TipReturnat nume(parametru1, parametru2,…) {
// corpul funcţiei
}
In alte cazuri o metoda indică faptul ca s-au incheiat cu succes anumite operaţii, nefiind necesară
returnarea unui rezultat iar o astfel de metodă (care nu returnează o valoare în urma execuţiei), are
în definiţie cuvântul void.
Alături de metoda de creare există şi o metoda de finalizare care are rol de a închide fişierele care
au fost deschise şi de curăţare a obiectului pentru care este finalizator, pentru ca ulterior
colectorul de reziduri să elimine obiectul din memorie. Nu există nici o garanţie că limbajul Java
va invoca metoda de finalizare definită, considerand metoda ca şi o optimizare a codului, motiv
pentru care este indicat ca aplicaţia să nu depinda prea mult de această metodă pentru a evita
anomalii în execuţie.
Pentru a se şterge un obiect, trebuie apelată metoda de finalizare care distruge variabila
respectivă, şi ulterior se apeleaza colectorul de reziduri. In limbajul Java nu este necesară apelarea
în mod implicit a distrugerii unei variabile de clasă, deoarece sistemul are un mecanism de
colectare a rezidurilor care descoperă situaţiile în care o variabilă de clasa ( sau un obiect) nu mai
este referită şi o distruge automat. Se recomandă însă ca metoda de finalizare să fie apelată
explicit pentru a nu apărea manifestări accidentale în execuţie.

2.1.2. Modificatorii clasei

Aceesibilitatea clasei şi informaţiile despre variabilele şi metodele definite în clasă sunt date prin
modificatorii clasei. Dacă aceştia sunt omişi în întregime, obiectele din clasă sunt definite şi
accesate de alte clase din acelaşi pachet iar această clasă poate avea la rândul ei subclase în acelaşi
pachet. Sunt cunoscuţi trei modificatori de clasă: public, abstract şi final.

32
O clasă declarată public este global accesibilă, ceea ce însemnă că orice clasă definită în acelaşi
pachet poate accesa obiectele din această clasă. Dacă nu este declarată public, accesibilitatea se
limitată la nivelul pachetului sau claselor din care derivă. Dacă o clasă este declarată public, ea
trebuie să fie publică în codul sursă şi mai mult, numele fişierului sursă trebuie să fie acelaşi cu
numele clasei public, cu extensie java.
Exemplu
public class Clasa1 {
Corpul clasei
…}
Observaţie:
In fişierul [Link] există doar o clasă declarată public.

In general se declară o clasă public, atunci când se doreşte a fi global accesibilă, astfel încât orice
applet public permite utilizatorului care navighează în pagină, să îl execute. Suplimenar se pot
declara pachete relative la clase, ce au intenţia de a furniza funcţionalitate generală, adesea pentru
a fi reutilizate în programe diferite. Pentru a face clasele accesibile în exteriorul pachetului, acestea
trebuie declarate public. Totuşi nu toate clasele dintr-un asemenea pachet pot fi utilizate în
exterior; unele sunt destinate doar uzului intern deşi se poate declara o clasă public, care poate fi
invizibilă în exteriorul pachetului.

O clasă abstract este cea care conţine una sau mai multe metode abstract. Uneori se declară o
metodă în clasă fără a preciza detaliile interne ce presupun metode de implementare diferite pentru
fiecare subclasă. Spre exemplu, dacă declarăm clasa [Link], are sens să se definească
metoda de afişare pentru fiecare tip de format al fişierului (JPEG,GIF,BMP, etc.) pentru că este
cunoscut faptul că există în plus informaţii legate de dimensiunea fişierelor, care determină
implementări diferite. Intr-un asemenea caz este necesară structurarea definiţiilor acestei metode
ale subclaselor. Pentru a realiza acest lucru, se lasă definiţia blank şi se declară metoda abstractă.
Dacă o clasă conţine una sau mai multe metode abstract, atunci clasa însuşi se declară abstract,
pentru a evita erori de complilare. Nu trebuie instanţiat direct un obiect din clasa abstract. Pentru
a-l utiliza este necesară crearea unei subclase ce include definiţiile pentru metodele lăsate blank în
clasa abstract, iar această clasă trebuie apoi instanţiată.

Clasele abstract permit implementarea polimorfismului pur, în care aceste clase abstract nu pot fi
ele însele instanţiate ci au rol de a servi ca şi clase de bază pentru un grup de clase aflate în relaţie.
Aceste clase de bază sunt generice astfel încât este greu sau aproape imposibil de definit detaliile
sau comportamentul acestora. Detalliile sunt lăsate subclaselor şi fiecare subclasă implementează
comportamente diferite. De aceea se începe fără implementări finalizând apoi cu implementări
distincte, proprii fiecărei subclase. Clasele abstracte se pot declara public sau fără acces implicit,
caz în care sunt vizibile doar în interiorul pachetului.[Ramb_96]

Clasele final nu pot fi subclase, sunt opuse lui abstract, motiv pentru care nu pot fi simultan final
şi abstract pentru că generează erori de complilare. Există două motive pentru care se folosesc
aceste clase: eficienţa şi posibilitatea de a extinde metodele definite în clasele părinte. De aceea
când o metodă dintr-o clasă este apelată, nu este posibil să se determine la momentul compliării ce
versiune a metodei se execută, deoarece versiunea metodei definită în clasă poate fi extinsă într-o
subclasă, cu acelaşi nume şi tip de parametri. Acest lucru trebuie determinat dinamic, în timpul

33
execuţiei de fiecare dată când se rulează acea secţiune de cod, depinzând de segmentele generate
când obiectul este instanţiat.

De fiecare dată când se fac determinări, se poate solicita încărcarea unei clase ce nu a fost anterior
rezidentă în memorie. Aceste performanţe se asociază cu costul încărcării clasei. Cum o clasă
finală nu are subclase, pentru a garanta faptul că aceste metode nu vor fi estinse, instrucţiunile ce
le compun sunt incluse în codul compilat, eliminând necesitatea de a lua o decizie şi posibilitatea
încărcării unei noi clase, în timp ce programul rulează. Al doilea motiv de declarare a acestor clase
final este dat de securitatea şi claritatea asigurată, deoarece se poate specifica o clasă cu
comportament cert, se poate dori ca nimeni să nu aibă posibilitatea de modificare a
comportamentului unei clase, extinzându-I metodele. Declarând-o final, se previn subclase
asociate, respectând funcţionalitatea şi securitatea ei.[java_8]
Numele clasei este identificator unic în acelaşi pachet. La importul claselor din alte pachete,
numele claselor din pachetul propriu nu trebuie să intre în conflict cu numele celor din pachetele
importate. Prin convenţie, programatorii Java scriu primul caracter din clasă cu majuscule, pentru
a asigura numele clasei şi variabilelor distincte, făcând codul uşor de citit.

Clasa Cont
abstract void tip();
String tip() {/*…*/}
abstract void sold();

extends
Clasa ContSintetic
void tip();
String tip() {/*…*/}
void sold();

extends

Clasa ContAnalitic
void tip();
String tip() {/*…*/}
void sold();
implements abstract void detaliu();
extends extends
extends extends
Clasa
Clienti Clasa
Clasa
Clasa Clasa
Agenti
A
Furnizori ContBancar

Figura 2.2. Reprezentarea ierarhiei de clase în Java

2.1.3. Extensiile superclaselor

34
Clasele extends specifică clasa din care se moştenesc, fiind superclase imediate sau clase părinte.
O subclasă estinde funcţionalitatea clasei părinte, în Java existând doar moşteniri simple (figura
2.2.). Clasele final nu apar în clase extends iar în absenţa clauzei extends, clasa moşteneşte
implicit caracteristicile clasei Object (rădăcina tuturor claselor).
Moştenirea, conceptul central OOP este implementat în Java cu un puternic mecanism de control
ceea ce însemnă că se pot specifica acele caracteristici ale clasei, care vor fi/ nu vor fi vizibile în
subclase şi acele metode care pot/ nu pot fi extinse.
Implicit o clasă moşteneşte toate câmpurile (variabile şi metode), exceptând constructorii, din
superclasă. Inafara constructorilor, variabilele şi metodele declarate private, vor fi invizibile
oricărei clasă ce o moşteneşte.
implements Interfata1, Interfata2,…InterfaţaN
Mecanismul interface oferă unele funcţionalităţi ce permit implementarea moştenirilor multiple,
evitând caracteristici circulare şi alte elemente periculoase ce implică moştenirile multiple.
[An_96] O clasă poate extinde doar o superclasă dar poate implementa oricâte interfeţe (nelimitate
ca număr). Interfeţele se specifică în declaraţia de clasă după cuvântul rezervat implements ca şi
listă separată prin virgulă.Clauza implements este opţională, prezentă doar dacă se implementează
interfeţe (figura 2.2.).

2.1.4. Supraîncărcarea metodelor


Studiu de caz:
Creăm o subclasă Point3D care moşteneşte implementările distanţei dintre două puncte din
superclasă (Point), pe care o supraîncarcă2 apoi.
Exemplu:
Class Point()
int x,y;
Point( int x, int y){
this.x=x;
this.y=y;
}
double distance(int x, int y){
int dx=this.x-x;
int dy=this.y-y;
return [Link](dx*dx+dy*dy);
}
double distance(Point p){
return distance(p.x,p.y);
}
}

class Point3D extends Point {


int z;
Point3D (int x, int y, int z) {
super(x,y);
this.z;
double distance(int x, int y, int z){
2
Sursa: Java Handbook

35
int dx=this.x-x;
int dy=this.y-y;
int dz=this.z-z;
return [Link](dx*dx+dy*dy+dz*dz);
}
double distance (Point3D other){
return distance(other.x, other.y, other.z);
}
double distance(int x, int y){
double dx=(this.x/z)-x;
double dy=(this.y/z)-y;
return [Link](dx*dx+dy*dy);
}
}
class Point3Ddist {
public static void main (String args[ ])[
point3D p1= new Point3D(30,40,10);
point3D p2= new Point3D(0,0,0);
Point p= new Point(4,9);
[Link] ("p1 este "+p1.x,p1.y,p1.z);
[Link] ("p2 este "+p2.x,p2.y,p2.z);
[Link] ("p este "+p.x,p.y);
[Link] (" distanta p1-p2"+[Link](p2);
[Link] ("[Link](8,5)"+[Link](8,5));
[Link] ("[Link](p)"+[Link](p));
}
}
Definind punctele p1 şi p2 tridimensionale, am solicitat distanţa între un punct tridimensional şi
unul bidimensional apelând distanţa din 3D cu un obiect de tip Point din 2D şi executând metoda
distance moştenită din Point, deoarece Poit3D nu supraîncarcă distance(Point p) ca metodă în
Point. Apelul distance(int x, int y ) se face din Point3D şi nu din Point (2D) dat fiind faptul că în
Java, metoda este selectată bazându-se pe tipul instanţei la un moment dat şi nu pe clasa în care
metoda curentă este executată.

2.1.5. Polimorfismul dinamic

Când se apelează la o metodă utilizând operatorul punct (.) şi referinţa obiect, declararea tipului
obiectului referit este verificată la compilare, pentru a se asigura că metoda apelată există în
declaraţia de clasă. In rulare, obiectul referinţă poate fi referit ca şi o instanţă a unei sublclase a
tipului de referinţă declarat. In acest caz, Java foloseşte actuala instanţă pentru a decide ce metodă
apelează evenimentul pe care subclasa supraîncarcă metoda ce a fost apelată3. [Hoff_96]

Exemplu:
Presupunem două clase care au o superclasă cu o singură metodă supraîncărcată în clasă.
class A {
void apel(){
3
Dynamic method dispatch

36
[Link].("Metoda de apel a lui A");
}
}
class B extends A {
void apel(){
[Link].("Metoda de apel a lui B");
}
}

class disp () {
public static void main(String args [ ]){
A a = new B();
A apel();
}
}
Această formă de polimorfism dinamic al execuţiei este cel mai puternic mecanism pe care îl oferă
programarea OO atât pentru codul reutilizat cât şi pentru robusteţea programelor.
In clasa disp definim metoda main() în interiorul căreia se declară variabila a de tip A, care
memorează o referinţă la o instanţă din clasa B. In linia următoare apelăm apel() ca metodă a lui a
dar când compilatorul Java verifică dacă a are această metodă rezultatul este corect. In schimb
Java runtime notează că referinţa este de fapt instanţa lui B şi astfel cheamă metoda apel a clesei
B. Vom obţine astfel:
Metoda de apel a lui B

2.1.6. Finalizarea

In timp ce Java runtime este un sistem colector de deşeuri (garbage collector system) nu este
necesar managementul memoriei însă apar unele situaţii de excepţie în care se impune efectuarea
unui cod special atunci când un obiect este solicitat de garbage collector. Spre exemplu dacă o
clasă foloseşte resurse non-Java ( spre exemplu: fişiere manipulate sau fonturile ferestrei sistem)
trebuie utilizată metoda de finalizare pentru a ne asigura că sunt eliberate toate resursele. Această
metodă funcţionează similar cu destructorul din C şi nu se poate confunda cu final.
Rezolvarea acestor excepţii se face adăugând metoda finalize în orice clasă caz în care Java
runtime o apelează de oricâte ori se reclamă eliberarea saţiului pentru un obiect. Metoda trebuie să
ia explicit orice acţiune solicitată pentru a elibera resursele deoarece garbage collector rulează
periodic, verificând obiectele care nu mai sunt referite de alte stări în lucru, sau referite indirect,
prin alte obiecte.
Colectorul de reziduri elibereaza resursele de memorie utilizate de obiectele pe care le distruge dar
obiectele mai păstrează şi alte tipuri de resurse cum ar fi descriptorii sau socket-urile. Colectorul
de reziduri nu poate elibera aceste resurse, astfel încât este necesară o metodă de finalizare proprie
fiecarui obiect care să realizeze operaţii specifice cum ar fi închiderea de fişiere care ramân
deschise accidental sau terminarea unei conexiuni în reţea.

[Link] şi metode
2.2.1. Variabilele

37
In Java variabilele înmagazinează dată iar conform paradigmei OO înglobează starea unui obiect
dat. Acestea sunt divizate în 2 categorii: variabile de instanţă, ce permit individualizarea
obiectelor din clasă şi variabile statice, care se referă la toate obiectele dintr-o clasă dată. Fiecare
obiect individual dintr-o clasă dată este numit instanţă sau instanţiere a clasei. Când se creează un
obiect specific al unei clase, se instanţiază un obiect din clasă şi spaţiul este alocat pentru toate
variabilele de instanţă ale obiectului. Fiecare obiect ce este instanţiat are un spaţiu alocat
independent de variabilele de instanţă.
Variabilele static, pe de altă parte, sunt create odată şi sunt folosite de toate obiectele din clasa
dată şi de clasele moştenite. Nu are importanţă câte obiecte se creează dintr-o clasă, se face o copie
a variabilelor statice ce aparţin clasei. Spre exemplu, în clasa [Link], variabila
MAX_VALUE este statică şi conţine valoarea maximă a unui întreg. Deoarece acest număr este
unic, nu are importanţă câte obiecte întregi sunt instanţiate, se face o singură copie a acestei
variabile şi astfel se alocă memorie minimă.
Referirea variabilelor de instanţă a unui obiect se face prin:
numele_instanţei_specifice.numele_variabilei_de_instanţă.
Exemplu:
In clasa Clasa1 definim variabile de instanţă por şi două obiecte care instanţiază clasa: ap2
şi ap3. Referinţa la variabilă se va face:
[Link]
[Link]

Pentru a referi variabilele statice se apelează la


numele_clasei.numele_variabilei.
Exemplu:
Pentru variabila statica suprafata vom apela:
[Link] sau [Link] sau [Link]

In definiţia de clasă varibilele statice şi de instanţă se pot referi şi fără calificare (suprafata, por,
etc)

2.2.2. This, super şi null


Fiecare obiect are încapsulate trei variabile: this, super şi null. This este pseudonimul obiectului
însuşi dat fiind faptul că în interiorul definiţiei de clasă se pot referi instanţe ale clasei fără a
specifica un obiect; this.n este spre exemplu o variabilă de instanţă a clasei în timp ce fără punct
(n) este variabilă a metodei. Explicitarea this este necesară pentru a distinge între variabila locală n
şi varibila de instanţă this.n.
Super este pseudonimul obiectelor din superclasa imediată, numită în clauza extends. Deoarece
variabilele din superclasă sunt moştenite în subclasă (dacă nu se limitează accesul prin private) se
referă simplu fără calificarea ca variabile de instanţă a clasei locale. Totuşi este posibil să se
declare ca variabilele de instanţă într-o subclasă, cu acelaşi nume ca şi variabilele de instanţă din
superclasă. Variabila definită în subclasă "maschează" sau "umbreşte" variabila definită în
superclasă. Pentru a o referi, se foloseşte cuvântul cheie super.
Exemplu:
Class SuperClasa {
int n=10; // se iniţializează n

38
}
class Clasa1 extends Superclasa {
int i,n;
public void main Method (int n) {
this.n=n; // necesar this, altfel apare conflict de nume
i=super.n; //i=10
}
}
This şi super sunt folosite numai în interiorul metodelor non-statice.
Inainte de a iniţializa un obiect el nu are valoare dar după iniţializare el are valoare implicită null.
Există situaţii în care atribuirea explicită a valorii null este necesară pentru obiecte, în special la
determinarea structurii dinamice de date ca arbori, liste, etc. Aceste structuri pot creşte şi se pot
extinde fără limite iar valoarea null marchează sfârşitul structurii. Un alt caz este thread(firul) de
execuţie, care se opreşte setându-l pe null. [Lema_98]

Observaţie: Se poate atribui valoarea null obiectelor sin orice clasă dar nu şi metodelor şi
variabilelor unor tipuri primitive de dată ( int, float, char, etc).
Exemplu: String str;
După această declaraţie str, este manipulat de obiectul String. Manipulatorul (handle) este similar
cu pointerul C, C++. După declaraţie nu se alocă memorie lui str, considerat ca manipulator null.
Handle nu are sens de "poiter la pointer" ca şi în C sau C++ ci mai degrabă ca referinţă la obiect şi
nu implică adresă fizică.

2.2.3. Declaraţiile de variabile

Declaraţia de variabile se realizează conform sintaxei:


[modificatori de variabile] tip numevariabilă [=Valoare initială]
Modificatorii de variabile specifică accesibilitatea variabilelor declarate la nivelul clasei. Implicit
variabilele dintr-o clasă pot fi:
 Moştenite şi vizibile în orice clasă declarată în interiorul pachetului ce extinde această
clasă.
 Accesibile tuturor claselor din interiorul pachetului;
 Inaccesibile din exteriorul pachetului;
Dacă nu există alte intenţii se indică specificând unul din cuvintele rezervate: public, protected,
private, static, sau final.
Variabila declarată public are aceeaşi aceesibilitate ca şi clasa dar nu depăşeşte accesibilitatea
clasei. Intr-o clasă cu acces implicit variabila public este accesibilă numai în interiorul pachetului
dar într-o clasă cu acces public varibila public va fi accesibilă [Link] public sunt
moştenite în orice subclasă derivată din lcasa în care sunt declarate.
Variabilele declarate protected sunt aceesibile tuturor claselor din pachetul ce conţine clasa în
care sunt declarate. In exteriorul pachetului variabilele protected sunt accesibile doar subclaselor
derivate din clasa în care sunt [Link] protected sunt eliberate de restricţii implicite
de moştenire dar reţin restricţiile de acees la clasele fără legătură din exteriorul pachetului .

Observaţie: Spre deosebire de C++ unde variabilele protected sunt aceesibile nimai în clasa dată şi
sublcasele ei, Java extinde conceptul la nivel de pachet, în interiorul căruia variabilele sunt
aceesibile tuturor claselor, chiar dacă aceste clase nu derivă din clasa în care au fost create.

39
Variabilele private sunt accesibile numai în clasele în care sunt declarate şi restricţiile se extind şi
la clasele derivate.
Variabilele static sunt instanţiate odată şi împărţite între toate obiectele clasei în care sunt
declarate şi în toate subclasele moştenite.
Există distincţie între variabilele statice (care aparţin clasi ca întreg) şi varibilele de instanţă care
sunt create separat pentru fiecare obiect al clasei şi este instanţiat ca aparţinând obiectului. Toate
variabilele ce nu sunt explicit declarate static sau final sunt variabile de instanţă.. Static poate fi
combinat cu orice specificator de acces: public, protected, private sau implicit.
Variabilele final sunt de fapt constantele şi de aceea la declararea lor se atribuie şi valoare, altfel
valoarea nu mai poate fi modificată. Deseori se declară constante ca final static. Tip-ul poate fi tip
primitiv, tablou, tip obiect, incluzând obiectele din această clasă. Nume variabilă începe de obicei
cu literă mică.[java_1], [java_8]

2.2.4. Metodele

Comenzile executate de Java sunt conţinute în metode, excepţie făcând blocurile statice. Toate
metodele sunt aflate în clase şi esistă o strictă similitudine cu OO din C++, unde funcţiile pot
exista independente de obiecte dacă programatorul doreşte.
Blocurile statice conţin cod executabil în interiorul metodei şi sunt excepţii. Aceste coduri sunt
folosite pentru a iniţializa variabilele statice ce nu pot fi complet iniţializate sau liniile de declaraţii
(ca şi tablourile).
Blocul static se referă doar la variabile statice şi la cele locale decarate în interiorul blocului.
Exemplu:
class Repar{
static double[] vcos= new double[100]; // variabile statice
static {
// blocul static
for (int i=1, i<100, i++) {
vcos[I]=[Link]((double)i/100.0);
}
…}
}
}
Chiar variabila locală I este implicit statică deoarece este declarată în bloc static şi nu este
accesibilă din esteriorul acestui [Link] interiorul clasei Repar sunt date valori specifice pentru
[Link].

2.2.5. Declaraţiile de metodă


O metodă se declară folosind sintaxa generală:
[modificatoriMetodă] Tiprezultat numeMetodă([listă argumente])
[Throws Exceptia1, …ExceptiaN
{

//corpul metodei
}

40
Modificatorii metodei pot fi public, protected şi private, cu aceeaşi semnificaţie ca şi
modificatorii de variabilă. Apar câţiva modificatori adiţionali, definiţi pentru metode şi în absenţa
modificatorilor accesul implicit este similar cu cel al variabilelor. Metodele fără modificatori au
câteva caracteristici: sunt moştenite de orice clasă declarată în interiorul pachetului, vizibile în
orice clasă şi disponibile pentru a fi supraacoperite în orice clasă ce o extinde în interiorul
pachetului şi sunt inaccesibile în exteriorul pachetului
Metodele static sunt în acord cu noţiunea de OO încapsulat şi constau în general din metode de
instanţiere care au acces la variabilele de instanţă ale unui obiect instanţiat în [Link]
de instanţiere sunt invocate folosint numele obiectului ca şi codificator.
Exemplu:
[Link](argumente);

Metodele statice la fel ca şi variabilele statice sunt instanţiate odată pentru toate obiectele din clasă
şi de aceea nu pot referi variabile de instanţă, care aparţin obiectelor specifice, nu clasei ca
î[Link] statice pot accesa variabile statice şi sunt implicit final fără a putea fi
supraîncărcate de clase derivate. Invocarea se face cu numele clasei ca şi calificator sau numele
obiectului instanţiat ca şi calificator de clasă.
Exemple: Metoda static din [Link]
String unSir= new String();
String altSir= new String();
UnSir =[Link](5);// echivalente
UnSir =[Link](5);// echivalente
UnSir =[Link](5);// echivalente

Metodele statice nu pot utiliza this şi super şi sunt împărţite de toate instanţele clasei, motiv pentru
care nu aparţin unei instanţe [Link] o metodă cu this pot fi sute de obiecte ce
instanţiază clasa şi nu se poate determina la care se face referire. La super, care este nivelul
moştenirii la care se află metoda? Care clasă e superclasă?- Intrebări fără răspuns. De aceea
metodele statice nu pot face referire la câmpuri non-statice.
Exemplu:
public class Test1{
String str="un sir"// constructor apelat implicit
public static void main (String args[ ]) {
[Link] (str);//eroare, str nu este variabilă non-statică
[Link] ([Link]);//eroare, nu se foloseşte this în metodă
}
}

Metoda final nu poate fi acoperită de clase derivate şi se poate combina cu public, private,
protected sau static sau specificată însuşi cu combinaţiile acestora, în concordanţă cu accesul
implicit precizat. Metoda abstact este declarată dar are implementări diferite în subclase, având
inteles contextual. Ea nu poate fi combinată cu metode ce restrâng moştenirea sau acoperirea
(private, static sau final) iar deoarece un constructor nu poate fi moştenit, nu poate fi final.

Native este metodă proprie în esenţă un apel exterior la funcţii scrise în alt limbaj de programare
(C, C++, etc.). Dearece Java este multithread (multifir) este necesară furnizarea mecanismului de
control al concurenţei pentru că sunt câteva operaţii care se execută simultan iar alte operaţii

41
(citire, scriere de date comune implică manipulări delicate. Declarând metoda sycronized se
garantează că doar un fir va fi executat la un moment dat.[Naugh_96]

2.2.6. Transferul argumentelor

Apelul unei metode presupune şi transferul parametrilor (argmentelor) care sunt substituiţi în
interiorul metodei în timpul execuţiei acesteia. Parametri de tip primitiv (int, float, char, boolean)
sunt transferaţi prin valoare, ceea ce înseamnă că se crează o copie locală cu acceaşi valoare ca
parametrul în interiorul metodei iar în exteriorul metodei nu se resimt modificările făcute în copia
locală. Obiectele de tip tablou sunt transferate prin referinţă, ceea ce înseamnă că în interiorul
metodei nu există o copie locală ci poate fi chemat prin valoare. Modificările afectează obiectul
actual şi de aceea ele persistă şi după metodă. [An_96] La declararea metodei se cunosc explicit
tipurile de parametri ce urmează a fi primiţi din lista de argumente a metodei. In OOP nu este
necesară precizarea tuturor informaţiilor solicitate în lista de parametri deoarece metoda ştie deja
despre ele şi are acces la toate variabilele de instanţă precum şi la cele statice în care este
definită.In lista de termeni se precizează doar acele informaţii la care metoda nu are acces, ca şi
instanţele variabilelor pentru alte obiecte, care pot fi diferite de fiecare dată când metoda este
apelată.
Exemplu:
class Fargum{
double d=3.14;
public void fMetoda (double d, Fargum other){
x=x*2.0;
d=other.d;
other.d=0.0; //efect global
}
}

pblic class Principala {


public static void main(String args[ ] ){
double noud=28.8;
Fargum nouFargum= new Fargum;
Fargum altFargum= new Fargum;
nouFargum.d=14.4;
altFargum.d=19.2;
[Link] ('Inainte de apel");
[Link] ("noud "+noud);
[Link] ('nouFargum.d "+ nouFargum.d);
[Link] ('altFargum.d "+ altFargum.d);
//apel metodă
[Link] (noud, altFargum);
[Link] ('După apel");
[Link] ("noud "+noud);
[Link] ('nouFargum.d "+ nouFargum.d);
[Link] ('altFargum.d "+ altFargum.d);
}
}

42
Rezultatele obţinute:
Inainte de apel
noud 28.8
nouFargum.d 14.4
altFargum.d 19.2
După apel
noud 28.8
nouFargum.d 1105.92
altFargum.d 0

Când se apelează [Link]() nu este necesar transferul lui d pentru că obiectul


nouFargum nu-l reclamă, dat fiind faptul că d este variabilă de instanţă a clasei Fargum şi orice
instanţiere a clasei cunoaşte valoarea lui d.
Mofificările făcute asupra lui x în interiorul metodei nu au efect în noud pentru că ea este de tip
primitiv şi se transferă prin [Link]ări făcute asupra lui other.d au efect global asupra
stării obiectului altFargum pentru că el este transferat ca orice obiect prin referinţa sa .

2.2.7. Metodele statice

De multe ori se doreşte crearea unei metode utilizată în exteriorul contextului oricărei instanţe, caz
în care se folosesc metodele statice, care pot apela direct doar metode static şi nu pot fi referite ca
this şi super .In cadrul acestor metode se declară doar variabile static.
Exemplu:
class Static {
static int a=3;
static int b;
static void metoda (int x) {
[Link] ("x="+x);
[Link] ("a="+a);
[Link] ("b="+b);
}
static {
[Link] ("Initializarea blocului static");
b=a*8;
}
public static void main (String args[] ){
metoda (33);
}
}

Un alt mod de a utiliza static este crearea metodelor ce pot fi apelate direct, referind numele clasei
în care sunt declarate. Similar cu apelul metodelor de instanţă prin variabilele de referinţă ale
obiectului, se apelează metoda static pentru a referi variabile static, utilizând . (punct) în numele
clasei.
Exemplu:
class StaticClass {
static int a=23;

43
static int b=90;
static void apel () {
[Link] ("a="+a);
}
class StaticprinNume {
public static void main (String args[] ){
[Link] ();
[Link] ("b="+StaticprinNume.b);
}
}
Modificatorii sunt cuvinte cheie ale limbajului Java care specifică proprietăţi speciale pentru unele
variabile sau metode. Un astfel de modificator este cuvântul rezervat static iar variabilele şi
metodele declarate static într-o clasă, sunt acelaşi pentru toate clasele, adică pentru toate
variabilele de tipul acelei clase. Variabilele statice pot fi accesate fără a fi nevoie o instanţiere a
clasei respective şi analog, nici metodele statice nu au nevoie de o instanţiere a clasei pentru a fi
folosite. Metodele statice pot utiliza variabile statice declarate în interiorul clasei.

2.2.8. Supraîncărcarea metodelor

Semnătura unei metode este definită prin lista de argumente specificată (număr, ordine şi tip) al
fiecărui [Link] se disting prin prin combinaţii de nume şi semnătură. In Java, la fel ca
şi în C++, este posibilă crearea metodelor supraîncărcate (overloading), care au acelaşi nume şi
semnături diferite. Deseori este utilă oferirea unor funcţionalităţi similare pentru diferite tipuri de
argumente, ceea ce permit metodele cu acelaşi nume iar când acestea sunt apelate, nu apar
ambiguităţi la execuţie, pentru că metodele sunt distinse prin semnătură.
Exemplu:
In clasa [Link] sunt metodele:
public static String valueOf(int i) {…}
public static String valueOf(float i) {…}
Metoda String valueOf(i) ia de fiecare dată tipul de parametru transferat şi în converteşte
în şir. Este normal ca paşii ce se execută la conversia întregului să difere de cei executaţi a
conversia float. Compilatorul foloseşte semnătura pentru a determina versiunea ce trebuie
executată.
Metoda supraîncărcării este mecanismul prin care Java furnizează polimorfismul adhoc în care
copilatorul decide versiunea metodei prin semnătura ei, la momentul apelului metodei, în contrast
cu polimorfirmul pur, furnizat de clasele abstracte. [Chan_96]

Metode supraacoperite (overriding)


In multe aplicaţii este utilă existenţa unei subclase care îşi defineşte propria versiune a metodei
date, cu acelaşî nume şi semnătură ca şi în superclasă, ceea ce reprezintă în fapt supraacoperirea.
Noua metodă din subclasă se numeşte metodă overriding (de supraacoperire) şi metoda din
superclasă este overridden (supraacoperită).Metoda supraacoperirii oferă moştenirii flexibilitatea
necesară deoarece prin aceasta se reţin acele metode care sunt potrivite subclasei şi furnizează o
nouă versiune particulară pentru acea implementare. Clasele abstract se bazează pe această metodă
pentru a furniza polimorfismul pur. Mai mult, orice metodă non-statică sau non-finală dintr-o
metodă non-statică sau clasă non-finală poate fi supraacoperită (când clasa are subclase).

44
2.2.9. Valoarea întoarsă de metode

Toate metodele cu exceptia constructorilor, trebuie declarate cu valoare întoarsă şi în caz contrar
cu void, deoarece în Java, omiterea tipului întors este o eroare, spre deosebire de C, C++ care
declară implicit tip int.
Spre deosebire de metodele care întorc void, instrucţiunea return se include în corpul metodelor în
orice punt de execuţie; aceasta opreşte execuţia metodei şi redă controlul metodei apelante.
Compilatorul se asigură de acest lucru şi trateaza fiecare if..then…else din metodă pentru a se
asigura că pe orice ramură metoda este terminată.
Exemplu:
Class MulteIntoarceri {
void maIntorc(String s){
if [Link]("M-am intors"){
return;//intoarcere rapida
}
…// alte instructiuni
return //optional

}
int eronat (Boolean b, Boolean t} {
int i;
double d;
if (b) {

return; //eroare, trebuie intors int
}else if (t){

return d;// eroare, d este double
}else if (i>0t){
return i;//bine
}else{

// lipseste return pentru ca nu este declarat void
}
}
}
Numele metodei urmează regulile anterior descrise şi se recomandă scrierea cu literă mică pentru a
o distinge de constructorii apelaţi.
Lista de argumente se include între paranteze, solicitate chiar în lipsa parametrilor, pentru a fi
distinse de declaraţii de variabile şi metode. Fiecare parametru este precedat de tip

Exemplu:
void diM(String s, int[ ] unTablou, double altTablou[ ])
//sir, tablou de intregi, tablou de reale duble

In general se aşteaptă ca excepţiile să fie rare iar în lipsa lor throws poate fi omis. In rest fiecare
exceptie tratată este separată prin virgulă.

45
2.3. Constructorii

Declaraţiile pure ale unui obiect nu alocă spaţii pentru variabile de instanţă ale acestora. Când un
obiect este delcarat, se instanţiază valoarea null. Instanţierea obiectului se face cu operatorul new.
Exemplu: Contul c=new Contul();
Constructorul este în fapt apelul unei metode speciale definită în orice clasă şi acesta împarte
acelaşi nume cu clasa în care este definit, având rolul de a iniţializa variabilele de instanţă ale unui
obiect, atunci când obiectul este iniţializat.[Lema_98]

Faţă de alte metode, constructorii posedă anumite caracteristici speciale:


 Nu au valoare întoarsă, implicit întorc tipul void, motiv pentru care în interiorul
constructorului nu este necesară instrucţiunea return;
 Nu sunt moşteniţi de subclase şi fiecare clasă utilizează propriul constructor, cu
acelaşi nume ca şi [Link] în lipsa moştenirii, este posibil ca în prima linie a
constructorului să aibă loc apelul explicit al constructorului de superclasă, utilizând
cuvântul cheie super în apel.
 Sunt apelaţi diferit faţă de metodele obişnuite, invocarea constructorului necesitând
calificarea prin nume, precedat de operatorul new. Operatorul new indică faptul că o
nouă memorie va fi alocată.
Exemplu:
String str=new String("Utilizator");
 Nu poate trata excepţii chiar dacă apelează o metodă ce tratează excepţii, o face cu
ajutorul unui constructor.
Din alt punt de vedere constructorii sunt trataţi ca şi metodele şi pot fi supraîncărcaţi.
Supraîncărcarea constructorului este distinsă prin semnătura conţinută în lista de arumente şi
aceasta permite furnizarea flexibilităţii în construcţia obiectelor din clasă.
Exemple:
[Link] are 7 constructori supraîncărcaţi şi vom prezenta diverse variante de
utilizare:
String() construieşte şir vid în absenţa parametrilor.
String(String) construieşte şir nou, copie a celui transmis
String(Char[ ]) construieşte şir nou, din tablou de caractere

Deoarece constructorii pot fi supraîncărcaţi, este convenabil ca în interiorul unui constructor să se


apeleze un alt constructor din acceaşi clasă. In acest sens este util să se declare un constructor
pentru clasă ca şi un constructor fără argumente.
Presupunem că se defineşte constructorul:
Aclass (int i, int j) iar în caz implicit:
Aclass(0,0), echivalent cu:
Aclass(){ // constructor implicit fără argumente
this(0,0); // prima instrucţiune obligatorie
Apelul this(0,0) invocă un constructor din aceeaşi clasă, cu acceaşi semnătură (int, int) şi este
unicul loc în care se utilizează cuvântul cheie this, ca şi constructor apelat în interiorul
constructorului; în caz contrar, apar erori de compilare.

46
Când se declară clase derivate, se moştenesc variabilele de instanţă din superclasă. Deoarece
constructorul din clasa derivată nu este el însuşi moştenit, este necesară o iniţializare a variabilelor
de instanţă moştenite. Acest lucru se poate face manual, ceea ce ia mult timp, însă dacă sarcina
este preluată de superclasă este mult mai comod, mai ales dacă se moştenesc varibile private la
care utilizatorul nu are acces. Din fericire, apelând la constructorul super cu condiţia că apare ca
primă instrucţiune în corpul constructorului.
Exemplu:
class Aclass extends AsuperClass {
double unDublu;
Aclass (int I, int j, double d){
super(i,j);//apel Aclass(i,j)
UnDublu=d; //nu a fost iniţializat de super
}

}

Se poate declara o clasă fără a specifica constructorul, fapt mai comod în special când o clasă este
moştenită direct din altă clasă. Omiţând constructorul din clasă, compilatorul Java, generează
automat constructorul implicit din superclasă.
Exemplu:
class FinalAclass extends B {
// nu se furnizează constructor
// compilatorul generează automat
FinalAclass{
super();//apel B()
}

}
Dacă superclasa imediată (B în exemplu) nu are constructor care să preia argumentele, apar erori
de compilare.

In programare se pot declara constructori private, furnizând metode public static care apelează
constructorul şi întoarce obiectul construit. Pentru crearea unui obiect din exteriorul pachetului se
apelează metoda static însă este util să se verifice argumentele din constructor şi să se trateze
excepţiile care pot apare. Constructorul în sine nu tratează excepţiile dar metodele static pot
analiza excepţiile şi să apeleze constructorul cu argumente corecte.

2.4. Rolul interfeţelor în programare


2.4.1. Definirea interfeţelor

Limbajul Java pune la dispozitie o metoda pentru crearea claselor complet abstracte, cunoscute ca
şi interfete. Interfeţele sunt destinate pentru a suporta rezoluţiile metodelor dinamice în timpul
execuţiei. Pentru ca o metodă să poată fi apelată dintr-o clasă în alta, ambele clase trebuie să fie
prezente la un moment dat în timpul compilării, pentru a ne asigura că semnăturile metodelor sunt
compatibile. Mecanismul de deconectare a metodei/metodelor din ierarhia moştenirii este protocol
în C obiectual şi interfaţă în Java.[Chan_95], [java_1]

47
public inteface nume_intefată {
// listă metodelor abstracte
}

Exemplu:
interface P(){
byte[]pack();
void unpack(byte b[]);
}
class Punct {
int x,y;
Punct (int x, int y) {
this.x=x;
this.y=y;
}
}
class AltPunct extends Punct implements P {
AltPunct (int x, int y){
super (x,y);
}
AltPunct(){
this (0,0);
}
private byte p(int t, int n) {
return (byte)((t>>n)&Oxff); //octal
}
public byte pack()[]{
byte ret[]=new byte[8];
ret[0]=p(x,24);
ret[1]=p(x,16);
ret[2]=p(x,8);
ret[3]=p(x,0);
ret[4]=p(y,24);
ret[5]=p(y,16);
ret[6]=p(y,8);
ret[7]=p(y,0);
return ret;
}
private int n(byte b, int n){
return ((b&Oxff)<n);
}
public void unpack(byte b[]){
x=u(b[0],24| b[1],16| b[2],8| b[3],0);
x=u(b[4],24| b[5],16| b[6],8| b[7],0);
}
public String toString(){
return("Noul punct"+x+'.'+y);

48
}
}
class PointPack{
public static void main(String args[]){
P p=Altpunct(123456789,555566667);
byte packed[]=[Link]();
AltPunct pnou= new AltPunct();
[Link](packed);
[Link] ("p"+pnou);
}
}

2.4.2. Variabile în interfeţe

Interfeţele pot avea şi subinterfeţe, care moştenesc variabile (constante în cazul interfeţei) şi
metodele interfeţei din care derivă, dar au posibilitatea de a folosi variabile şi metode proprii.
Pentru a implementa o intefaţă, se utilizeaza cuvantul cheie implements. O clasa poate
implementă mai multe interfete iar daca o clasă declară implementarea unei interfeţe, este
obligatoriu ca ea să implementeze toate metodele din intefaţa respectivă. Programele Java
utilizează interfeţele pentru a suplini lipsa moştenirilor multiple, adică a claselor care derivă din
două sau mai multe clase.
Putem utiliza interfeţele pentru a importa constante împărţite în multiple clase, declarând simplu o
interfaţă ce conţine toate numele şi toate variabilele. Când se implementează apoi această interfaţă,
toate numele acestor variabile vor fi folosite în scop de constante (similar cu fişierul header din
C++ utilizat la crerea unor constante definite prin #defined ca şi constructor). Dacă interfaţa nu
conţine metode, orice clasă ce o implementează nu trebuie să implementeze nimic în plus şi se
comportă ca şi un import de constante dintr-o clasă, ca variabile de tip final.
Exemplu:
import [Link];
interface ConstanteImpartite {
int a=0;
int a1=1;
int a2=2;
int a3=3;
int a4=5;
}
class Prima implements ConstanteImpartite {
Random r=new Random();
int intreb{
int prob= (int)(100*[Link]());
if (prob<30)
return a;
else if prob(<60)
return a1;
else if prob(<75)
return a2;
else if prob(<90)

49
return a3;
}
}
class Doi implements ConstanteImpartite {
static void rasp (int rez) {
switch(rez) {
case a:
[Link] ('Da");
case a1:
[Link] ('Nu");
case a2:
[Link] ('Poate");
case a3:
[Link] ('Nu sunt sigur");
}
}
public static void main (String args[]){
Prima q1= new Prima();
rasp([Link]);
rasp([Link]);
rasp([Link]);
rasp([Link]);
}
}

In interiorul celor două clase codul care referă constantele este dat ca şi cu ele ar fi definite sau
moştenite direct. Toate metodele declarate într-o interfaţă sunt implicit abstract şi similar, toate
variabilele dintr-o interfaţă sunt implicit static şi final deoarece sunt formate ca şi constante. Spre
deosebire de clasă, o interfaţă poate extinde multiple interfeţe moştenind variabilele şi metodele
definite în interior. Orice clasă ce implementează o asemenea interfaţă trebuie să ofere definiţii
pentu toate metodele definite în interfaţă şi toate interfeţele esenţiale.
Exemplu:
interface Simplu1 {
int a;
void absolM1(){
}

interface Simplu2 {
String str;
void absolM2(){
}
Interface Combinata extends Simplu1,Simplu2 {
void absolM3(){
}
}
//ImpClasa cere implementarea metodelor absolM1()
// absolM2(), absolM3()

50
class ImpClass implements Combinata {
public absolM1 (){
// definitia metodei 1
}
public absolM2 (){
// definitia metodei 2
}
public absolM3 (){
// definitia metodei 3
}
// alte metode ale clasei ImpClasa

}
Dacă o clasă implementează o interfaţă sublcasele moştenite pot extinde aceste metode
implementate, respectând restricţiile impuse de specificatorii de acces. In plus dacă o clasă
implementează o interfaţă sau un set de interfeţe nu este necesară includerea acestora în clauzele
implements ale subclaselor.

2.4.3. Modul de utilizare a interfeţelor


Apelăm la clasicul exemplu din literatura de specialitate - modul în care Java implementează
erorile şi firele (threads). Frecvent un applet rulează cu un fir în timp ce alte fire sunt abilitate să se
execute simultan, utilizând sistemul eficient.
Dacă appletul extinde [Link], nu poate extinde [Link] pentru că violează
restricţiile moştenirilor [Link]ţia o oferă [Link], caz în care appletul propriu
implementează metoda run() plasată în corpul principal al appletului. Apoi se construieşte un fir
thread() în interiorul appletului, transmiţând this ca parametru al constructorului Thread (). Acest
constructor poate lua ca parametru orice obiect ce implementează o interfaţă Runnable astfel:
public Thread(Runnable tinta);

Metoda constructorului lansează un fir a căriu corp, când este rulat ia metoda run() furnizată d
epropriul applet- cheia înţelegerii interfeţelor. Dacă appletul este declarat Runnable, appletul este
tratat ca obiect Runnable şi orice metodă ( ca şi constructorul anterior) care ia Runnable ca
parametru, poate accepta appletul. Când se apelează metodele ce fac parte din interfaţa Runnable -
în cazul de faţă run()- appletul propriu a furnizat metoda consistentă cu cererea, ceea ce este ca şi
cum ar fi clasă obişnuită numită Runnalbe şi appletul propriu este derivat din clasă. Interfaţa
Runnable este cel mai intuitiv exemplu care ilustrează în acelaşi timp un important concept de
proiectare: keep it simple.

Există doar o metodă implementată în interfaţa Runnalbe şi de aceea este foarte uşor de
implementat în orice clasă proiectată. Dacă se definesc n metode, este greu de imaginat că cineva
consideră convenabilă implementarea tuturor acestor interfeţe iar dacă aceste metode sunt
disparate în câteva interfeţe este facilă implementarea acelor interfeţe care asigură funcţionalitate
absolut necesară.[Ramb_96]. Modificatorii de interfaţă sunt public şi abstract iar în lipsa lor
interfaţa este accesibilă doar în interiorul pachetului. O interfaţă spre deosebire de clasă, poate
extinde mai multe interfeţe.

2.4.5. Specificatorii de acces

51
Incercăm să sintetizăm în cele ce urmează caracteristicile specificatorilor de acces la nivelul
claselor, variabilelor şi metodelor.
Public
Clasa - accesibil tuturor claselor din exteriorul pachetului;
Variabile - vizibile tuturor claselor ce acceseză această clasă şi din exteriorul pachetului;
- vizibile în toate clasele derivate din această clasă în şi din exteriorul pachetului;
Metode - vizibile tuturor claselor ce acceseză această clasă şi din exteriorul pachetului;
- vizibile în toate clasele derivate din această clasă în şi din exteriorul pachetului;
- pot fi suprascrise în toate clasele derivate din aceasta în şi din exteriorul pachetului.
Protected
Clasa - inaplicabilă;
Variabile - vizibile tuturor claselor ce acceseză această clasă în interiorul pachetului;
- vizibile numai în clasele derivate în exteriorul pachetului;
Metode - vizibile tuturor claselor ce pot extinde această clasă în interiorul pachetului;
- vizibile doar claselor derivate din această clasă în exteriorul pachetului;
[default] (implicit)
Clasa - în interiorul pachetului accesibile tuturor claselor;
- în exteriorul pachetului inaccesibile;
Variabile - vizibile tuturor claselor în interiorul pachetului;
- vizibile numai în clasele derivate în exteriorul pachetului;
Metode - vizibile tuturor claselor ce pot suprascrie această clasă în interiorul pachetului;
- vizibile doar claselor derivate din această clasă şi pot fi suprascrise de aceste clase, în
exteriorul pachetului;
Private protected
Clasa - inaplicabilă;
Variabile - vizibile doar claselor derivate din aceasta în interiorul şi exteriorul pachetului;
Metode - vizibile doar claselor derivate din această clasă în interiorul/exteriorul pachetului
- pot fi acoperite de clase derivate
Private
Clasa - inaplicabilă;
Variabile - vizibile doar în interiorul clasei;
Metode - - vizibile doar în interiorul clasei.
Final
Clasa - nu pot fi extinse;
Variabile - atribute cu valoare permanentă în declaraţiile lor;
- valoarea nu poate fi schimbată în orice clasă chiar dacă sunt sau nu sunt derivate din
acestă clasă;
metode - nu poate fi acoperită.
Static
Clasa - inaplicabilă;
Variabile - numai copia variabilelor se împarte de toate subclasele;
Metode - - metoda este împărţită de toate subclasele dar nu poate fi extinsă.
Abstract
Clasa - conţine una sau mai multe metode abstracte;
- nu poate fi instanţiată;
Variabile inaplicabilă;

52
Metode - nu este definită şi va fi pusă la dipoziţie de subclasă;
- trebuie acoperită când este subclasată sau subclasa însuşi este abstract.
Native
Clasa - inaplicabilă;
Variabile inaplicabilă;
Metode - este definită în alt limbaj (exterior) ca şi C, C++, etc.
Syncronized
Clasa - inaplicabilă;
Variabile inaplicabilă;
Metode - la momentul dat, numai un fir poate spune obiectului instanţat să
execute această metodă;
- dacă este static, numai un fir poate executa această metodă la un timp dat, periodic.

2.4.6. Moştenirea multiplă şi interfeţele


Moştenirea multiplă (multiple inheritance-MI) este un acronim al OO, care porneşte de a ideea
că o clasă poate fi derivată din mai multe superclase. Cum Java nu suportă MI, oferă o alternativă
prin interfeţe. Utilizarea eronată a Mi conduce la două categorii de erori grave: ambiguitatea şi
circularitatea. Ambiguitatea rezultă când unul sau mai mulţi ascendenţi ai clasei definesc aceeaşi
variabilă v sau metodă(variabilă) cu acelaşi nume. Spre exemplu în C++ declarăm clasa Ascend_1
cu variabila v şi metoda asMetoda() şi altă clasa Ascend_2 cu variabila v proprie şi metoda
asMetoda() şi altă clasă Descen ce moşteneşte cele 2 varibile şi metode. Apare întrebarea: care
dintre variabile este moştenită şi de cine? Greu de răspuns. Circularitatea apare când o clasă se
moşteneşte direct sau indirect pe ea însuşi (simultan este bunic şi nepot). Cum nu se poate şti care
este ascendentul şi descendentul se distruge claritatea noţiunii de moştenire.
Cele două inconveniente sunt soluţionate în Java prin definirea interfeţelor, în care este cunoscut
faptul că variabilele sunt definite static şi final deci nu crează ambiguităţi pentru că servesc drept
constante. In plus, datorită distincţiei între clase şi interfeţe sunt evitate circularităţi ascunse; chiar
dacă se implementează oricâte interfeţe, o clasă nu poate fi regăsită în ea însuşi.

2.5. Rolul pachetelor în programare


In disponibilitatea pachetelor, Java poate adresa 4 categorii de vizibilităţi între elementele clasei:
 subclase ale aceluiaşi pachet;
 clase care nu sunt subclase ale aceluiaşi pachet;
 sublclase în pachete diferite;
 clase ce nu sunt în acelaşi pachet şi nici nu sunt subclase.
Ca şi o regulă generală orice se declară public este accesibil oriunde iar orice clasă sau
variabilă declarată private nu este vizibilă în exteriorul clasei.

Private Nomodifie Private Protected Public


r Protected
Aceaşi clasă Da Da Da Da Da
Subclasă în acelaşi Nu Da Da Da Da
pachet
Acelaşi pachet non- Nu Da Nu Da Da
subclasă
Subclasă din pachete Nu Nu Da Da Da

53
Private Nomodifie Private Protected Public
r Protected
diferite
Diferite pachete non- Nu Nu Nu Nu Da
subclasă

Tabelul 2.1. Vizibilitatea şi modificatorii de acces

In definirea unei clase se pot include şi nivele de protecţie pentru variabile şi metode, cu ajutorul
unor cuvinte rezervate numite modificatori de acces: protected, public sau private. In lipsa acestor
nivele de protecţie implicit se consideră nivelul prietenos (friendley).[An_96]
In Java protected induce comportament similar cu friend din C++ iar private protected ca şi
protected din c++.
Semnificatiile acestor nivele de protecţie sunt diferite, astfel:
• Protected – metodele şi variabilele sunt declarate protected, sunt disponibile în
clasa în care sunt definite şi în subclasele din această clasă.
• Public - metodele şi variabilele sunt declarate public, fiind disponibile în toate
clasele.
• Private - metodele şi variabilele sunt declarate private, fiind disponibile numai în
clasa în care sunt definite; nici măcar subclasele derivate din această clasă nu au acces
la ele.
• Prietenos(friendly) – nivelul implicit, ele sunt disponibile pentru toate clasele din
pachetul curent.
O variabilă sau o metodă nu poate avea declaraţe mai multe nivele de protecţie simultan, sau în
discordanţă cu pachetul din care face parte, acestea determinând erori la compilare.
Exemplu:
package p1;
public class Protectia {
int n=1;
private int n_pri=2;
protected int n_pro=3;
private protected int n_pripro=4;
public n_pub=5;
public Protectia(){
[Link] ("Constructorii de bază");
[Link] (n);
[Link] (n_pri);
[Link] (n_pro);
[Link] (n_pripro);
[Link] (n_pub);
}
}
class Derivata extends Protectia {
Derivata(){
[Link] ("Constructori derivati");
[Link] (n);
//numai în clasă

54
//[Link] (n_pri);
[Link] (n_pro);
[Link] (n_pripro);
[Link] (n_pub);
}
}
class acPachet {
acPachet(){
Protectia p=new Protectia();
[Link] ("Constructori in acelaşi pachet");
[Link] (p.n);
//numai în clasă
//[Link] (p.n_pri);
[Link] (p.n_pro);
//in clasa si subclasa
[Link] (p.n_pripro);
[Link] (p.n_pub);
}
}
In pachetul p2 două definiţii de clasă acoperă două condiţii ce sunt afectate de controlul accesului.
Prima clasă este subclasă a lui [Link] ce garantează acces la toate variabilele [Link], cu
excepţia lui n_pri (deoarece ea este private) şi n declarată prin protecţie implicită (în interiorul
clasei sau în pachet nu în subclase extrapachet).Clasa AltPachet are acces doar la o variabilă n_pub
declarată public.
Exemplu:
package p2;
class Protectia2 extends [Link] {
Protectia2 () {
[Link] ("Constructor derivat din alt pachet");
// numai in clasa sau pachet
//[Link] (n);
//numai in clasa
//[Link] (n_pri);
[Link] (n_pro);
[Link] (n_pripro);
[Link] (n_pub);
}
}
class AltPachet{
AltPachet (){
[Link] p= new [Link]();
[Link] ("Constructor in alt pachet");
// numai in clasa sau pachet
[Link] (p.n);
//numai in clasa, subclasa si pachet
//[Link] (p.n_pro);
//numai in clasa sau sbclasa

55
//[Link] (p.n_pripro);
[Link] (p.n_pub);
}
}

56
3. Tehnica programării în Java

3.1. Appleturi Java

Considerăm utilă vizualizarea appleturilor cu Netscape, deşi nu se recomandă utilizarea -o


(optimization) ca opţiune din javac, deoarece acesta face verificarea codul binar înaintea trecerii
spre interpreter. Netscape permite tratarea erorilor depistate înainte a pune appletul pe
[Link] nu realizează acest lucru nici măcar pentru appleturile încărcate local, dar
ocupă mai puţin spaţiu de memorie. Rulând cu flag -debug permite depanarea appletului dar nu
oferă posibilitatea vizualizării întregii pagini Web, doar a appleturilor, însă oferă posibilitatea
implementării relaxate şi sigure, în special la nivelul appleturilor încărcate pe sistemul local de
fişiere. Pentru a crea un applet se extinde clasa [Link] prin moştenire simplă. Această
clasă la rândul ei este descendent al altor clase moştenind un mare bagaj de funcţionalitate la orice
nivel.

3.1.1. Ciclul de viaţă al appletului

Spre deosebire de aplicaţiile monouser, unde programatorul scrie metoda principală care
direcţionează activitatea programului de la început la sfârşit, appleturile nu au în general o metodă
main() fiind manipulate de appletviewer sau Web browser care decide asupra iniţializării, rulării,
întreruperii şi distrugerii appletului.[Ramb_96]

start() stop()
Iniţializarea Execuţia Oprirea
appletului appletuluiu appletului

init() start()
destroy()

Distrugerea
appletului

Figura 3.1. Ciclul de viaţă al appletului

Conform figurii 3.1., programul principal aşteaptă ca appletul să fiec în măsură să execute metode
clare ca: init(), start(0, stop(), destroy() ce constituie ciclul de viaţă al unui applet şi sunt definite în
clasa [Link]. Deşi sunt metode cu corp void se aşteaptă ca programatorul să le
defineasă astfel încât ele să poată fi utilizate în scopul solicitat de appletul proiectat.
Metoda init() este apelată la prima încărcare a appletului, practic odată în tot ciclul de viaţă al
appletului şi se foloseşte pentru a iniţializa variabilele de instanţă, pentru setarea dimensiunii
appletului final, fundalul şi primplanul acestuia sau pentru stabilirea unor condiţii iniţiale de
execuţie propriu-zisă.
Metoda start() este similară cu main() method a appletului şi este apelată imediat după init()
declanşând execuţia appletului. Dacă appletul este oprit, metoda poate fi apelată din nou, pentru a

57
re-rula appletul, apărând ori de câte ori se doreşte instanţierea firelor sau pentru execuţia unui task
principal din applet.
Metoda stop() este apelată când appletul rulează şi utilizatorul minimizează fereastra browserului
sau reîncarcă pagina. Dacă se doreşte oprirea appletulului sau a firelor, metoda poate fi apelată şi
succedată de start() pentru a re-rula appletul..
Metoda destroy() este apelată când appletul poate fi eliminat din memorie (purge) deşi garbage
collector face acest lucru şi fără metoda în sine. In mod normal extinderea metodei se impune doar
în situaţii limită când appletul foloseşte resurse ale altor clase externe care trebuie gestionate de
către utilizator.
Exemplu:Structura generală a unui applet
import [Link];
import [Link].*;
import [Link].*;
public class StructuraApplet extends Applet {
public void init() {
}
public void start() {
}
public void stop() {
}
public void destroy() {
}

public void paint(Graphics g) {


}
}
In Windows 98 sau Windows NT minimizarea appletului nu invocă stop() şi de accea nu se va
invoca start la maximizarea ferestrei şi appletul se execută lăsând procesorului posibilitatea de a
rula alt fir în acest timp.
Legarea cu altă pagină ce nu conţine appleturi determină automat apelul lui stop() şi este
recomandată când se doreşte minimizarea ferestrei browserului.
Metodele anterior descrise nu trebuie explicitate decât dacă se doreşte executarea unor acţiuni
specifice.

3.1.2. Elemente esenţiale în dezvoltarea unui applet

Pentru a construi un applet este nevoie să creăm o clasă care este derivată din clasa de bază Applet
aflată în pachetul [Link]. Clasa Applet este clasa ce oferă cadrul absolut necesar comunicării
cu browserul WWW, practice o interfaţă de comunicare a unui program Java cu browserul. Orice
applet este implementat prin crearea unei subclase a clasei Applet. Ierarhia claselor din care deriva
Applet este prezentată în figura 3.2. Fiind derivata din clasa Container, clasa Applet descrie de fapt
suprafete de afisare, asemenea claselor Frame sau Panel.

58
Figura 3.2. Ierarhia de clasă a appletului

Tagul html de conexiune cu fişierul class este tagul APPLET şi are varianta minimală de forma:

<APPLET CODE=”[Link]”
WIDTH=300
HEIGHT=200>
</APPLET>

Exemplu:
import [Link];
import [Link].*;
public class AppletExemplu extends Applet {
public void paint(Graphics g) {
[Link](new Font("Arial", [Link], 16));
[Link]("Java", 0, 30);
}
}

Figura [Link] dezvoltării şi execuţiei unui applet Java


Browser Web cu
fişier html ([Link]) suport Java
Editor text -conţine eticheta de (appletviewer,
legătură cu fişierul .class Netscape, etc.)
[Link]

fişier executabil JVM execuţie program


Bytecodes Java în JVM
([Link])

fişier sursă Java


([Link]) Compilator Java
(javac)
Clasa principala va fi salvata într-un fisier cu acelasi nume şi extensia .java. Spre exemplu:
fişierul [Link].
Compilarea se face la fel ca şi la aplicatiile independente, apelând compilatorul javac pentru clasa
principala a appletului (cea care extinde Applet).
javac [Link]

59
In cazul în care compilarea a reusit va fi generat fisierul [Link].
Pentru a vizualiza un applet trebuie creat un document HTML (ex: [Link]), în care se
specifică cel putin următoarele informaţii:
 clasa ce contine codul appletului
 latimea si înaltimea suprafetei alocate pe pagina Web

<HTML>
<HEAD>
<TITLE> Exemplu de applet </TITLE>
</HEAD>
<APPLET CODE="[Link]" WIDTH=100 HEIGHT=50></APPLET>
</HTML>

Vizualizarea acestui document se poate face cu orice browser (Internet Explorer, Netscape, etc),
sau cu utilitarul appletviewer ce vine în pachetul JDK.
appletviewer [Link]

3.1.3. Prelucrarea parametrilor din fişiere HTML


Sintaxa tagului applet
In fişierul HTML apar o serie de tag-uri utilizate la transferul parametrilor între appleturi şi aceste
fişiere.
Fără a insista prea mult asupra semnificaţiei tagului applet, amintim câteva aspecte referitoare la
tagurile de imagine şi sunet.[Rado-96],[Murh_98]
Tag-ul <APPLET>
[CODEBASE = directorApplet]
CODE = clasaApplet
[ALT = textAlternativ]
[NAME = numeInstantaApplet]
WIDTH = latimeInPixeli
HEIGHT = înaltimeInPixeli
[ALIGN = aliniere]
[VSPACE = spatiuVertical]
[HSPACE = spatiuOrizontal]
< APPLET
[< PARAM NAME = numeParametru1 VALUE = valoare1 >]
[< PARAM NAME = numeParametru2 VALUE = valoare2 >]
...
[text HTML alternativ]
</APPLET>
Atributele dintre paranteze patrate sunt optionale.
Semnificaţia parametrilor este:
 CODEBASE = directorApplet - Specifica URL-ul în care se gaseste clasa appletului;
uzual se exprima relativ la directorul documentului HTML iar în cazul în care lipseste, se
considera implicit URL-ul documentului.
 CODE = clasaApplet - este numele fisierului ce contine clasa principala a appletului.
Acesta va fi cautat în directorul specificat de CODEBASE şi nu poate fi absolut.

60
 ALT = textAlternativ specifică textul ce trebuie afisat daca browserul întelege tagul
APPLET dar nu poate rula appleturi Java.
 NAME = numeInstantaApplet oferă posibilitatea de a da un nume respectivei instanţe
a appletului, astfel încât mai multe appleturi aflate pe aceeasi pagina să comunice între ele
folosindu-se de numele lor.
 WIDTH = latimeInPixeli respective HEIGHT = înaltimeInPixeli - specifică laţimea şi
înalţimea suprafeţei în care va fi afişat appletul.
 ALIGN = aliniere - semnifică modalitatea de aliniere a appletului în pagina Web şi
poate primi una din urmatoarele valori: left, right, top, texttop, middle, absmiddle,
baseline, bottom, absbottom similare cu si la tagul IMG.
 VSPACE = spatiuVertical şi HSPACE = spatiuOrizontal - specifică numărul de
pixeli dintre applet şi marginile suprafeţei de afişare.
 < PARAM NAME = numeParametru1 VALUE = valoare1 >
Tag-urile <PARAM> sunt folosite pentru specificarea parametrilor unui applet.
text HTML alternativ - textul ce va fi afisat în cazul în care browserul nu poate interpreta tagul
APPLET iar browserele care înteleg Java vor ignora acest text.

Manipularea şi definirea parametrilor


Parametrii appleturilor sunt similari cu argumentele de la linia de comanda pentru aplicaţiile
independente şi permit utilizatorului personalizarea aspectul sau comportarea unui applet fără a-i
schimba codul şi a recompila clasele ce-l compun.
Definirea parametrilor se face în cadrul tagului APPLET din documentul HTML ce conţine
appletul şi sunt identificati prin atributul PARAM. Fiecare parametru are un nume, specificat prin
NAME şi o valoare, specificată prin VALUE, ca în exemplul de mai jos:
<APPLET CODE="[Link]" WIDTH=100 HEIGHT=50
<PARAM NAME=textAfisat VALUE="Java">
<PARAM NAME=numeFont VALUE="Times New Roman">
<PARAM NAME=dimFont VALUE=20>
</APPLET>

Tipul parametrilor este şir de caractere, indiferent dacă valoarea este între ghilimele sau nu şi
fiecare applet are în plus un set de parametri prestabiliţi ale caror nume nu vor putea fi folosite
pentru definirea de noi parametri (folosind metoda de mai sus). Aceştia apar direct în corpul
tagului APPLET şi definesc informaţii generale despre applet (spre exemplu parametri CODE,
WIDTH sau HEIGHT). Folosirea parametrilor primiţi de către un applet se face prin intermediul
metodei getParameter() care primeşte ca argument numele unui parametru şi returnează valoarea
acestuia. In cazul în care nu exista nici un parametru cu numele specificat, metoda întoarce null,
caz în care programul trebuie să atribuie o valoare implicită variabilei associate respectivului
parametru.

Exemplu:rescrierea appletului considerat initial (AppletExemplu) astfel încât acesta sa afiseze


textul primit ca parametru, folosind un font cu numele si dimensiunea specificate de asemenea ca
parametri.

import [Link];
import [Link].*;

61
public class AppletExemplu extends Applet {
String text, numeFont;
int dimFont;
public void init() {
text = getParameter("textAfisat");
if (text==null)
text="Java"; // valoare implicita
numeFont = getParameter("numeFont");
if (numeFont==null)
numeFont="Arial";
try {
dimFont = [Link](getParameter("dimFont"));
}
catch(NumberFormatException e) {
dimFont = 16;
}
}
public void paint(Graphics g) {
[Link](new Font(numeFont, [Link], dimFont));
[Link](text, 20, 20);
}
}
In general se evită definirea şi utilizarea unui număr mare de parametri în appleturi deoarece le
face practic neutilizabile, datorită dificultăţii de memorare a acestora. Soluţia recomandată este
utilizarea şi extinderea metodei getParameterInfo() definită în clasa [Link] pentru
appleturile proiectate, ceea ce oferă posibilitatea vizualizării tuturor parametrilor appletului
precum şi a altor informaţii ofetite de appletviwer.
Exemplu:
public String[ ][ ] getParrameterInfo() {
String [ ] [ ] Info={
{"MESSAGE", "String", "mesaj afisat"},
{"PAUSE", "int", "durata pauzei"},
{"STEPSIZE", "int", "dimensiunea pasului"},
{"FONTNAME", "String", "nume font"},
{"FONTSTYLE", "int", "stil font 0-PLAIN, 1-BOLD"+
"2-ITALIC"+"combinatii"},
{"FONTSIZE", "int", "dimensiunea fontului"},
{"MSG_COLOR", "int", "nume culoare"}
};
return Info;
}

In exemplul de mai sus, metoda întoarce un tablou de tablou de şiruri. Variabila locală Info se
iniţializează în timpul declaraţiei iar tabloul este iniţializat unidimensional, fiecare element fiind
la rândul lui un tablou. Dacă şirul este prea lung, pentu o linie, el se întrerupe cu " şi se continuă cu
operatorul de concatenare + deşi se poate folosi simplu return pentru continuarea textului pe o
nouă linie deoarece compilatorul recunoaşte faptul că nu s-a terminat şirul.

62
Observaţie: Java nu are operator de supraîncărcare (overloading) şi nu permite programatorilor
atribuirea unui alt inţeles operatorilor. Singura excepţie de la regulă este + (concatenarea şirurilor),
deşi operatorii aritmetici (+,-,*,/) care pot fi utilizaţi în int, flat, long, double sunt ei însuşi
supraîncărcaţi prin moştenirile acestora.

Clasa [Link] defineşte metoda getParameter(String Nume1) prin care întoarce valoarea
pereche a şirului Nume1 din interiorul fişierului HTML (tag-ul parameter). In caz contrar,
înroarce şirul null. Prin wrapper classes (clasele acoperitoare) se pot utiliza şi valori int, boolean,
float dacă sunt apelate metodele de conversie între şiruri şi tipurile primitive.
Orice applet poate pune la dispozitie o "documentatie" referitoare la parametrii pe care îi suporta,
pentru a veni în ajutorul utilizatorilor care doresc sa includa appletul într-o pagina Web. Aceasta se
realizeaza prin supradefinirea metodei getParameterInfo, care returneaza un vector format din
triplete de siruri. Fiecare element al vectorului este de fapt un vector cu trei elemente de tip
String, cele trei siruri reprezentând numele parametrului, tipul sau si o descriere a sa.

public String[][] getParameterInfo() {


String[][] info = {
//Nume Tip Descriere
{"textAfisat", "String", "Sirul ce va fi afisat"},
{"numeFont", "String", "Numele fontului"},
{"dimFont", "int", "Dimensiunea fontului"}
};
return info;
}

Informatiile furnizate de un applet pot fi citite din browserul folosit pentru vizualizare prin metode
specifice acestuia. De exemplu, în Netscape se foloseste optiunea Page info din meniul View.

Manipularea informaţiilor despre applet Similară cu metoda getParameterInfo există


metoda getAppletInfo ce permite specificarea unor informatii legate de applet cum ar fi
numele, autorul, versiunea, etc. Metoda returneaza un şir de caractere continând informatii
despre applet.

Exemplu:
public String getAppletInfo() {
return "Exemplu de applet, autor Delia Corches, ver 1.0";
}

3.1.4. Facilităţi de lucru cu imagini şi fişiere audio

Pentru un applet animat tagul este:


<APPLET CLASS="Animator"
IMAGESOURCE="unDirector"--directorul care are cadrele animate (o serie de desene în
format GIF, namite [Link], [Link], ...)
STARTUP="Fisier1" -- imagine ce se afişează la momentul încărcării
BACKGROUND="Fişier2"-- imagine ce se desenează pe fundalul cadrului

63
STARTIMAGE="Numar1" -- numărul cadrului de început (1..n)
ENDIMAGE="Numar2" -- numărul cadrului de sfârşit (1..n)
PAUSE="100" -- millisecunde de pauză între imagini, implicit poate fi suprascris prin
PAUSES)
PAUSES="300|200||400|200||100" -- millisecond întârziere pe cadru
Blank utilizează valoarea implicită a lui PAUSE
REPEAT="true" -- repetă secvenţa?
POSITIONS="100@200||200@100||200@200|100@100|105@105"
 posiţiia (X@Y) pentru fiecare cadru
 Blank - permite utilizarea poziţia cadrului anterior
IMAGES="3|3|2|1|2|3|17" -- ordine explicită de cadre
SOUNDSOURCE="Director2" -- directorul ce are fişiere audio
SOUNDTRACK="Fişier3" -- fişier audio ce este redat
SOUNDS="[Link]|||||[Link]" -- fişiere audio asociate cadrelor individuale

Parametri IMAGES, STARTIMAGE şi ENDIMAGE permit specificarea fie a unei liste de


imagini (IMAGES) sau interval de imagini (STARTIMAGE/ENDIMAGE) dar nu ambele
simultan. Lista din IMAGES este un şir de numere de cadre în ordinea în care se afişează,
separate prin bare verticale. STARTIMAGE and ENDIMAGE permit specificarea ordinii
imaginilor. Specificând ENDIMAGE număr mai mic decât STARTIMAGE, se afişează imaginile
în ordine inversă. Ambii parametrii au valoare implicită 1, aşa încât specificând numai
STARTIMAGE="12" înseamnă că se deseneză cadrele de la 12 la 1. Nu se pot specifica în acelaşi
timp STARTIMAGE şi ENDIMAGE.

Cum clasa Applet este o extensie a superclasei Container, înseamnă ca appleturile sunt,
înainte de toate, suprafeţe de afisare. Plasarea componentelor, gestionarea pozitionarii lor şi
tratarea evenimentelor generate se realizează la fel ca şi în cazul aplicaţiilor. Adăugarea
componentelor pe suprafata appletului şi stabilirea obiectelor responsabile cu tratarea
evenimentelor generate sunt operaţiuni ce vor fi realizate în metoda init. Gestionarul de
pozitionare implicit este FlowLayout, care poate fi schimbat prin metoda setLayout.
Exista o categorie întreagă de appleturi ce nu comunica cu utilizatorul prin intermediul
componentelor, ci executia lor se rezuma la diverse operatiuni de desenare executate în metoda
paint. Metoda paint permite definirea aspectului grafic al oricărei componente şi trebuie
supradefinită. In acest caz evenimentele tratate uzual vor fi cele generate de mouse sau tastatură.

Pentru manipularea imaginilor clasa Applet pune la dispoziţia programatorului două metode de
creare obiect de tip imagine:
 public Image getImage(URL url)- metodă care crează un obiect imagine (de tipul
Image) având ca şi parametru locaţia absolută WWW (URL-ul) unde se găseşte fişierul
imagine. Fişierul trebuie să fie unul din tipurile suportate de Java (gif, jpg).
 public Image getImage(URL url, String name)- returnează un obiect imagine. Are ca
parametrii locaţia relativă WWW şi numele fişierului imagine.
Afisarea imaginilor într-un applet se face fie prin intermediul unei componente ce permite acest
lucru - o suprafaţă de desenare de tip Canvas, fie direct în metoda paint a applet-ului, folosind
metoda drawImage a clasei Graphics. In ambele cazuri, încarcarea imaginii în memorie se va
face cu ajutorul metodei getImage din clasa Applet. Aceasta poate primi ca argument fie adresa
URL absoluta a fisierului ce contine imaginea, fie calea sa relativa la o anumita adresa URL, cum

64
ar fi cea a directorului în care se gaseste documentul HTML ce contine appletul
(getDocumentBase) sau a directorului în care se gaseste clasa appletului (getCodeBase).

Ex: import [Link];


import [Link].*;
public class AppletImagine extends Applet {
Image img = null;
public void init() {
img = getImage(getCodeBase(), "[Link]");
}
public void paint(Graphics g) {
[Link](img, 0, 0, this);
}
}

Pentru eliminarea problemelor de flashing se poate folosi tehnica double-buffering. Prin această
tehnică se desenează appletul într-o imagine ascunsă după care se afişează această imagine în zona
vizibilă.
Pentru a lucra cu fişiere audio, există în clasa Applet două metode care returnează un obiect Java
de tip AudioClip. Acest obiect poate fi folosit mai apoi pentru execuţia sunetului:

public AudioClip getAudioClip(URL url)


public AudioClip getAudioClip(URL url, String name).
Parametrii acestor metode sunt asemănători parametrilor de la metodele legate de imagine cu
deosebirea că fişierul care conţine sunetul trebuie să fie unul de tipul celor suportate de Java (au).

3.1.5. Comunicarea dintre browser şi applet


a. Transmiterea de parametrii prin pagina html
Parametrii unui applet sunt utili atunci când dorim să lăsăm la latitudinea utilizatorului appletului
(a celui care crează pagina html) setările unor valori de lucru.

Ex: applet care afişează un şir setat în pagina html


import [Link].*;
import [Link].*;
public class FirstApplet extends Applet {
public void paint(Graphics g) {
String sir=getParameter(“DISPLAYED_STRING”);
if(sir==null)sir=” Sirul afisat in interiorul appletului!”;
[Link](sir,30,30);
}
}

Fişierul html corespunzător appletului dezvoltat conţine:

<APPLET CODE=”[Link]”
WIDTH=300
HEIGHT=200>

65
<PARAM NAME=”DISPLAYED_STRING”VALUE=”Bine ati venit pe site-ul meu”>
</APPLET>

Pentru a putea face cunoscută în exterior lista parametrilor, numele, tipul şi scopul acestora,
programatorul poate suprascrie metoda
public String[][] getParameterInfo()
În cazul exemplului de mai sus avem:

public String[][] getParameterInfo() {


String pinfo[][]=
{{“DISPLAYED_STRING”,”String”,”Sirul afisat in interiorul appletului”}}
return pinfo;
}

[Link]ţinerea unor informaţii de la browser


Există o serie de metode care pot fi utilizate în interiorul appletului pentru a obţine anumite
informaţii de la browser, cu metodele:
public URL getDocumentBase()-returnează locaţia (adresa www) la care se găseşte pagina în care
se află appletul
public URL getCodeBase()-returnează locaţia la care se găseşte appletul.
Pentru a transmite anumite mesaje browserului din interiorul unui applet se pot folosi metodele
definite în interfaţa AppletContext. Un obiect de tipul AppletContext se poate obţine prin metoda
clasei Applet, getAppletContext(). Pentru comunicarea cu browserul avem următoarele metode
definite în interfaţa AppletContext:
public void showDocument(URL url)- cere browserului încărcărea unei noi pagini în fereastra de
afişaj curentă, pagină aflată la adresa specificată prin parametrul url.
public void showDocument(URL url, String target)-cere browserului încărcarea unei noi pagini
specificând în plus faţă de metoda anterioară cadrul în care se va afişa pagina. Un browser poate
avea mai multe cadre (frame) de afişaj în interiorul ferestrei sale, deschizând şi afişând astfel mai
multe pagini html în aceeaşi fereastră de browser. Parametrul target poate avea următoarele valori:
"_self" –pagina se afişează în cadrul curent
"_parent" –pagina se afişează în cadrul părinte
"_top" –pagina se afişează în cadrul superior al ferestrei browserului
"_blank" –pagina se afişează într-o nouă fereastră de browser fără nume
"name" –pagina se afişează într-o nouă fereastră de browser cu numele
name.
public void showStatus(String status)-prin această metodă appletul poate cere browserului afişarea
unui şir în interiroul “status window” a browserului. Acest “status window” reprezintă o
componentă grafică în care browserul afişează diferite informaţii legate de încărcarea paginilor, de
stabilirea conexiunii, etc. Această metodă este disponibilă şi în clasa Applet.
public Enumeration getApplets()-returnează toate appleturile disponibile în pagina în care se află
appletul curent (într-o pagină pot exista mai multe appleturi Java). Ca urmare, appletul curent
poate accesa diferite metode publice ale altor appleturi aflate în aceeaşi pagină html.
public Applet getApplet(String name)-prin această metodă appletul poate cere browserului
referinţa la appletul cu numele name.

c. Afisarea unor mesaje în bara de stare a browserului se realizeaza cu metoda showStatus

66
public void init() {
showStatus("Initializare applet...");
}

d. Afisarea unor documente în browser se face cu metoda showDocument ce primeste adresa


URL a fisierului ce contine documentul dorit (text, html, imagine, etc). Aceasta metoda se gaseste
în interfata AppletContext.
try {
URL doc = new URL("[Link]
getAppletContext().showDocument(doc);
} catch(MalformedURLException e) {}

e. Comunicarea cu alte applet-uri aflate pe aceeaşi pagină implică de fapt identificarea unui
applet aflat pe aceeasi pagina si apelarea unei metode sau setare unei variabile publice a acestuia.
Identificarea se face prin intermediu numelui pe care orice instanta a unui applet îl poate specifica
prin atributul NAME. Obtinerea unei instante a unui applet al carui nume îl cunoastem sau
obtinerea unei enumerari a tuturor applet-urilor din pagina se fac cu metodele definite de interfata
AppletContext getApplet si getApplets.

f. Contextul de execuţie al unui applet se refera la pagina în care acesta rulează şi este descris de
interfata AppletContext. Crearea unui obiect ce implementează aceasta interfaţă se realizeaza de
catre browser, la apelul metodei getAppletContext a clasei Applet. Prin intermediul acestei
interfete un applet poate "vedea" în jurul sau, putând comunica cu alte applet-uri aflate pe aceeasi
pagina sau cere browser-ului sa deschida diverse documente.
AppletContext env = getAppletContext();

3.1.6. Probleme de securitate


Ferestrele folosite de un applet, altele decât cea a browserului, vor arata altfel decât într-o aplicatie
obişnuită. Sunt evidente o serie de probleme de securitate care se pun în cazul execuţiei
appleturilor în cadrul unui browser. Fiecare browser implementează o serie de politici de securitate
pentru a împiedica compromiterea sistemului. Aceste politici pot însă să difere de la un browser la
altul. În majoritatea cazurilor însă se impun unui applet următoarele restricţii:
• nu poate citi sau scrie fişiere de pe maşina pe care se execută
• nu poate şterge sau modifica fişiere de pe maşina pe care se execută
• nu poate citi anumite proprietăţi de sistem
• nu poate porni un program pe maşina pe care se execută
• nu poate deschide o conexiune de reţea decât cu maşina de pe care a fost adus
• nu poate încărca librării sau metode native.

Pentru a împiedica accesul unor appleturi maliţioase la resursele maşinii locale, browserul
implementează o serie de politici de securitate. Astfel unui applet îi sunt interzise o serie de
operaţii (unele descrise mai sus) care pot fi executate în cazul aplicaţiilor Java stand-alone. Politica
de securitate este implementată prin clasa SecurityManager.

67
Fiecare browser are un SecurityManager care implemntează politica de securitate. Când se
încearcă o violare a drepturilor acest SecurityManager aruncă o excepţie de tipul
SecurityException.
JDK oferă o soluţie prin care se pot acorda unor categorii speciale de appleturi anumite drepturi
de acces (altfel interzise) la resursele maşinii client. Pentru aceasta se foloseşte semnătura digitală
a appleturilor.

3.1.7. Documentarea parametrilor appleturilor


Spre exemplu, dacă utilizăm întârzierea ca parametru furnizat de fişierul HTML, vom avea:
Exemplu:
pause=100; care se va regăsi în codul Java:
String pause_str=getParameter("pause");
pause= [Link] (pause_str); //
//sau combinând cele 2 linii
pause=[Link](getparameter("pause"));

In general se testează valabilitatea corespondenţei parametrilor în fişierele HTML astfel:


Exemplu:
String msg=getParameter("mesaj");
String pause_str=getParameter("pause");
if (msg = null){
msg="Paramatreu lipsa in fisier HTML";
}
if (pause_str != null){
pause [Link](pause_str);
} else {
pause=200; //implicit
}

In fişierul HTML apare:

Observaţii:
 Toate numele parametrilor se trec între ghilimele şi sunt necesare când există
spaţii sau caracere de separaţie a căilor.
 Nu toate clasele acoperite construite furnizează convesrie facilă în clasa Integer,
când se solicită parametri numerici în appleturi. Astfel, pentru conversie float:
Exemplu:
float f;
String f_string=getParameter("f_par");
float f_acop=[Link](f_string);//conversie
f=f_acop.floatValue();
//valoarea conţinută

[Link]

68
In problema anterioară este necesară existenţa unui applet care execută animaţia în fir separat şi un
altul ce rulează concurent, evitând monopolizarea CPU. Problema centrală este de a crea un fir
responsabil d emanipularea evenimentelor, scopul fiind de a rula animaţia, în timp ce redă
controlul CPU.
Faţă de conceptul tradiţional în are programul execută o serie de instrucţiuni în ordine, firele sunt
în fapt o localizare independentă a controlului unui program. Manipulând mai multe fire de
execuţie, se poate executa o parte a instrucţiunilor din lista unui fir, după care să se execute o altă
succesiune de instrucţiuni din alt fir, dar la momentul revenirii la firul anterior, să se localizeze
exact porţiunea de instrucţiuni din listă (locus of control - localizarea controlului). Programele
multithread au simultan mai multe loc of control deşi unele sisteme utilizează un singur procesor,
simulând în fapt execuţia paralelă sau multifir, în realitate oferind o cuantă de timp în care
utilizează microprocesporul (de ordinul câtorva microsecunde), algoritmii de planificare, ajungând
la un sistem dependent.[Zaha_00]
Implementarea interfeţei Runnable este un mod convenabil de creare a appletului [Link]
[Link] este subclasă a lui [Link], creând un applet ca subclasă a
[Link], contrazicem principiul moştenirii simple. De aceea la implementarea interfeţei
Runnable se cer implementate toate metodele acesteia - adică run() - metoda definită de Runnable
astfel încât appletul presupune:
 Includerea clauzei implements Runnable în declaraţia de clasă a appletului;
 Estinderea metodei run() a interfeţei Runnable, cu codul principal în appletul propriu;
 Metoda start() a appletului propriu crează un fir trecând appletul ca parametru al
constructorului, prin cuvântul cheie this
 Metoda stop() a appletului propriu, cu codul acestuia, opreşte execuţia firului.
Pentru exemplificare vom modifica exemplul anterior astfel încât să nu monopilizăm CPU.
Exemplu:
import [Link];
import [Link];
import [Link];

public class BandaDefilanta extends Applet {


String msg; // mesaj defilant
int x, y // coordonatele desenului
int orizPas;//dimensiune pas în pixeli
int pause;// numar de iteratii in bucla pauza
int msgWidth; dimesiunea mesajului în font curent
Thread proFir; // firul manipulează desenarea şi defilarea textului

public void init(){


msg="Applet Multithread fără monopolizarea CPU";
pause=100;
orizPas=2;
FontMetrics fm=get FontMetrics(get Font());
msgWidth=[Link](msg);
// incepe x din dreapta
x=size().width;
// incepe y mai sus de capăt
y=size().height-(int)([Link]()/3);

69
}

public void start(){


proFir = new Thread(this);
//apel run() si intoarcere imediată
[Link]();
}

public void run(){


// defilarea pana cand firul este oprit
while (proFir !=null){
repaint (); // apel update() si paint()
}

proFir = new Thread(this);


//apel run() si intoarcere imediată
[Link]();
//avans stânga
if(x>0-msgWidth){
x=x-orizPas;
}else{
//incepe din dreapta
x=size().width;
}
try {
// pauza de milisecunde pentru a redesena CPU liber
[Link](pause);
}catch (InterruptedException e){
[Link]();// eroare de tiparire
}
}
}
public void paint(Graphics g){
// desenarea mesajului
[Link](msg,x,y);
}

public void stop(){


// definim fir candidat la garbage collector
proir=null;
}
}
Codul fişierului HTML conţine:
<applet code=[Link] width=250, height=150>
</applet>

Rularea appletului

70
BandaDefinlanta are superclasa imediata Applet şi totuşi moşteneşte metoda abstractă run() din
interfaţa Runnable, care trebuie extinsă pentru instanţierea appletului [Link]ă aceasta,
metoda poate fi trecută ca parametru în orice metodă care poate primi un obiect Runnable, de fapt
în metoda start().
Se instanţiază un obiect din [Link] (cum [Link].* este importat automat) iar
constructorul Thread() utilizat ia obiectul Runnable ca parametru şi setează metoda run() a lui
Thread pentru a apela metoda run() transmisă în obiect.
Cu proFir instanţiat apelul [Link]() este motivat deja, iar acesta apelează la rândul lui
[Link]() şi apoi întoarce [Link] justifică de ce nu trebuie aşteptat ca [Link]() să
se execute complet, în modul sincron, în care s-ar executa normal o metodă. Aceasta înseamnă că
se dă controlul lui [Link]() în firul principal, în timp ce metoda run() se execută în
firul paralel, ca fir separat (proFir). Acum [Link]() completează, returnând controlul
asupra sistemului astfel încât se pot asimila ca evenimente manipulate, poate chiar apelate de
propria metodă stop() a appletului.[java_5], [java_6]
Un aspect neobişnuit este faptul că BandaDerulanta şi proFir împart acceaşi metodă run() în timp
ce metodele proprii start() nu sunt echivalente. In fapt metodele run() au doar similitudini de apel,
funcţionalitatea lor fiind distinctă.Realitatea este că BandaDerulanta şi proFir nu împart acceaşi
metodă run() ci Thread este instanţiat într-un asemenea mod încât apelează metoda run() a
appletului.
După instanţierea firului şi apelul lui [Link]() appletul are 2 fire de execuţie: cel principal, care
manipulează evenimentele şi apelează metodele din ciclul de viaţă al appletului şi al doilea care
produce execuţia animaţ[Link]ţia este de fapt o buclă întreruptă când firul este oprit (while
proFir !=null;). Deoarece se utilizează o variabilă locală pentru reprezentarea firului în metoda
run(), când metoda run() se termină firul îşi atinge scopul şi valoarea devine null (sinonim cu
terminarea firului).
Metoda repaint() a appeltului este moştenită din [Link] şi apelează metoda
update() implicită, care redesenează fundalul şi apoi paint().

Pauza a fost implementată printr-o buclă iterativă, care de fapt consumă timpul procesorului fără a
face nimic (buzy-waiting). Apelând [Link]() cu parametru întreg, se indică timpul după care
se eliberează CPU. In interiorul blocului try şi catch se apelează [Link]() şi de fapt nu se
execută efectiv manipularea excepţiilor ci se indică ceea ce clasa nu poate proiecta ca excepţii
manipulate. In mod normal InterruptedException are un simplu return prin care metoda run() se
termină. Metoda stop() se apelează când utilizatorul comută diferite pagini sau monimizează
browserul, caz în care CPU este eliberat, proFir=null şi devine candidat la gerbage collector.
"Omorârea" (kill) nu presupune distrugerea lui (destroy), rămânând starea memorată în varibilele
de instanţă.La apelul lui start() se crează un nou fir, continuând proFir de unde a fost lăsat.[java_7]

3.2.1. Firele şi prioritatea lor

Priorităţile firelor sunt valori întregi (1-10) utilizate la schimbarea (switch) a firului [Link]
execută un singur fir la un moment dat deşi un fir poate renunţa voluntar la control prin
determinări explicite, dormind sau blocând prin agăţare I/O sau poate fi pre-empted. In primul caz
sunt examinate firele în funcţie de priorităţi şi cel cu prioritate maximă şi care este gata de rulare
are controlul CPU. In al doilea caz, cumun fir renunţă voluntar, firul cu prioritate maximă care
vrea să ruleze o va face dar situaţia limită apare când 2 fire cu aceeaşi prioritate cer control CPU.

71
[Link] defineşte conceptul de monitorizare. De vreme ce firele introduc comportament
asincron al programului, trebuie să existe o metodă de a forţa sincronizarea necesară. Monitoarele
sunt prescrise pentru a proteja resursele partajabile sa în vederea manipulării acestora de mai multe
ori la un moment dat. In Java monitorul este dat de metoda syncronized. Mesajele schimbate între
2 fire sunt focalizate cu metodele wait şi notify. Un fir poate introduce metoda syncronized pe un
obiect şi să aştepte până când un alt fir notifică explicit ieşirea. Analog, mai multe fire pot
introduce metoda syncronized pe un obiect şi să aştepte până când apare aceeaşi notificare. Firul
curent ce se execută poate fi terminat cu [Link].[java_4]

3.2.2. Utilizarea firelor în programare

Metodele clasei sunt statice, apelate din clasa Thread direct:


 currentThread - indică firul curent;
 yield - determină execuţia în contextul switch de la firul curent către alt fir runnable
disponibil.
 sleep(int n) - sleep n milisecunde.

Metodele de instanţă sunt:


start(), run(), stop() - cu semnificaţii binecunoscute;
suspend() - diferit de stop cauzează oprirea fără distrugerea stării şi se poate relua prin
resume();
resume() - reia execuţia firului, făcându-l disponibil.
set priority(int p) - setarea priorităţii firelor. Majoritatea folosesc NORM_PRIORITY -1 iar
taskurile background operaţii I/O sau retipărire) au MIN_PRIORITY
MIN_PRIORITY=1, NORM_PRIORITY=5, MAX_PRIORITY=10
GetPriority() - întoarce prioritatea;
SetName( String nume) dă numele firului;
GetName() întoarce valoarea precizată de setName.

In continuare vom exemplifica utilizarea acestor metode.


Exemplu:
class FirCurentEx {
public static void main(String args[]){
Thread t=[Link]();
[Link]=("firul meu");
[Link] ("firul curent"+t);
try {
for (int n=5; n>0; n_-){
[Link] (" "+n);
}
catch(InterruptedException e){
[Link] ("intrerupt");
}
}
}
Rezultatul execuţiei:
Firul curent Thread[firul meu,5,main]

72
5
4
3
2
1
unde main este numele unui grup de fire cu care se leagă.
Runnable este în fapt o simplă interfaţă ce abstractizează noţiunea de aştepare înaintea execuţiei
asincrone, cum putem observa în exemplul următor.
Exemplu:
class FirCurent implements Runnable {
Thread ct=[Link]();
[Link] ("firul curent"+ct);
Thread t=new Thread (this, "Noul Thread");
[Link] ("firul nou"+t);
[Link]();
try {
[Link]();
}catch(InterruptedException e){
[Link] ("intrerupt");
}
[Link] ("Iesire din firul principal");
}
}
public void run(){
try{
for (int n=5; n>0; n_-){
[Link] (" "+n);
[Link](1000};
} catch(InterruptedException e){
[Link] ("Fir intrerupt");
}
[Link] ("Iesire din firul fiu");
}
public static void main(String args[]){
new FirCurent();
}
}

Rezultatul execuţiei:
Firul curent Thread[main,5,main]
Firul nou Thread[Noul Thread,5,main]
5
4
3
Iesire din firul principal
2
1

73
Iesire din firul fiu
Setarea priorităţii de realizaeză cu metoda setPriority cu 2 nivele faţă de cea normală
reprezentată de Thread.NORM_PRIORITY(HIGH,LOW)
Exemplu:
class ClasaFir implements Runnable {
int click=0;
private Thread t;
private boolean ruleaza=true;
public ClasaFir (int p) {
t= new Thread(this);
[Link](p);
}
public void run(){
while(ruleaza) {
click++;
}
}
public void stop(){
ruleaza=false;
}

public void start(){


[Link]();
}
}
class MaMicPri {
public static void main (String args[]){
[Link]().setPriority(Thread.MAX_PRIORITY);
ClasaFir mare=new ClasaFir(Thread,NORM_PRIORITY+2);
ClasaFir mic=new ClasaFir(Thread,NORM_PRIORITY-2);
[Link]();
[Link]();
try [Link](1000); catch(InterruptedException e);
[Link]();
[Link]();
[Link] ([Link]+"comparat cu firul "+[Link]);}
}
}

3.2.3. Sincronizarea firelor

Alte sisteme multifir expun conceptul de monitor. Un monitor este obiectul ce foloseşte blocajul
mutual exclusiv 4 şi numai un fir poate deţine monitorul la un moment dat. Când un fir solicită
blocarea se spune că a intrat în monitor. Toate celelate fire care încearcă să intre şi să blocheze

4
Mutual exclusive lock - mutex

74
monitorul sunt suspendate până când este eliberat, deşi un fir ce deţine monitor poate reintra la
acelaşi monitor dacă doreş[Link] este soluţionată prin metoda syncronized.[Naugh_96]

Exemplu:
Clasa apel are o singură metodă - apel, cu parametru msg şi încearcă tipărirea mesajului după care
cheamă [Link]. Constructorul clasei Apelant ia o referinţă către o instanţă a clasei Apel şi un
şir memorat în tinta şi mesajur respectiv msg. Constructorul crează un fir Thread care va apela
metoda run() a acestui obiect. Firul începe imediat şi metoda run a lui Apelant este simplă, apelând
doar instanţa tinta a lui Apel, trecând mesajul. In final, clasa Sync ia lucrurile, pornind de la
crearea unei instanţe Apel şi trei instanţe Apelant, fiecare cu mesajul său. Aceeaşi instanţă este
trimisă la fiecare Apelant.
Codul sursă:
class Apel {
void apel(String msg){
[Link] ("["+msg);
try [Link](1000); catch(InterruptedException e);
[Link] ("]");
}
}
class Apelant implements Runnable {
String msg;
Apel tinta;
public apelant (Apel t, String s){
tinta=t;
msg=s;
new Thread(this).start();
}
public void run(){
[Link](msg);
}
}
class Sync {
public static void main(string args[]);
Apel tinta= new Apel();
new Apelant (tinta, "Bine");
new Apelant (tinta, "sincronizate");
new Apelant (tinta, "firele");
}
}
Rezultat:
[Bine[sincronizate][firele]

inlocuind cu
syncronized void Apel(String msg){
apare ieşirea metodei sincronizate astfel:
[Bine]
[sincronizate]

75
[firele]

3.2.4. Comnunicarea între fire

Java include un mecanism de cumunicare inter-proces, prin wait, notify şi notifyAll implementate
ca metode finale în Object şi toate clasele acestuia. Cele trei metode pot fi apelate numai din
interiorul unei metode syncronized şi au rolul:
 wait- spune firului să lase monitorul şi apoi sa "doarmă" (sleep) până când alt fir intră
în acelaşi monitor şi apelează notify.
 notify - trezeşte primul fir ce a chemat wait pe acelaşi obiect.
 notifyAll - trezeşte toate firele ce au chemat wait pe acelaşi obiect şi firul cu prioritatea
cea mai mare este rulat primul.
Exemplu:
Construim 4 clase:Q care încearcă sincronizarea accesului, PC care crează simplu
următoarele clase, respectiv Producator- care produce intrări în coadă, Consumator şi obiectul
Threaded care consumă intrările din coadă

class Q{
int n;
syncronized int iau(){
[Link] ("iau:"+n);
return n;
}
syncronized void pun (int n){
this.n=n;
[Link] ("pun"+n);
}
}
class Producator implements Runnable {
Q q;
Producator( Q q) {
this.q=q;
new Thread(this, "producator").start();
}
public void run() {
int i=0;
while(true) {
[Link](i++);
}
}
}

class Consumator implements Runnable {


Q q;
Consumator ( Q q) {
this.q=q;
new Thread(this, "Consumator").start();

76
}
public void run() {
int i=0;
while(true) {
[Link](i++);
}
}
}

class PC {
public static void main(String args[]){
Q q=new Q();
new producator(q);
new Consumator(q);
}
}
Chiar dacă metodele pun şi iau sunt sincronizate, nu opreşte nimic pe Producător să ruleze
peste Consumator şi nici Consumatorul să consume o valoare d e2 ori astfel:
Rezultat:
Pun 1
Iau 1
Iau 1
Iau 1
Pun 2
Pun 3
Pun 4
Pun 5
Pun 6
Iau 6
Modalitatea polling fixează ceea ce se primeşte setând o variabilă booleană, trecând apoi într-un
loop de evaluare şi aşteptând valoare avariabilei consumate astfel:
class Q{
int n;
boolean valset=false;
int iau(){
while ( !valset){
[Link] ("iau:"+n);
valset=false;
return n;
}
void pun (int n){
while ( !valset){
this.n=n;
valset=true;
[Link] ("pun"+n);
}
}

77
Varianta anterioară consumă enorme resurse CPU şi practic nu face nimic. O altă soluţie
este:
class Q{
int n;
boolean valset=false;
sycronized int iau(){
if ( !valset){
try wait();
catch(Interrupted Exception e);
[Link] ("iau:"+n);
valset=false;
notify();
return n;
}
syncronized void pun (int n){
if (valset){
try wait();
catch(Interrupted Exception e);
this.n=n;
valset=true;
[Link] ("pun"+n);
notify();
}
}
Rezultat:
Pun 1
Iau 1
Pun 2
Iau 2
Pun 3
Iau 3

Pun 7
Iau 7

3.2.5. Blocajul

Practic blocajul5 este foarte greu sau nu poate fi depanat deloc când este condiţionat de 2 fire ce au
dependenţă circulară de o pereche de obiecte sincronizate. [An-96],[java_5] Spre exemplu, un fir
intră pe monitor pe obiectul X şi apoi încearcă să apeleze o metodă sincronizată pe y. Dacă y
încearcă să apeleze orice metodă sincronizată cu y aşteaptă întotdeauna până este deblocat de x
pentru că nu se poate elibera de propriul blocaj.
Exemplu:
class A {
syncronized void prima (B b){
String nume=[Link]().getName();
5
deadlock

78
[Link] (nume+"introdus de metoda [Link]);
try Thread sleep(1000); catch (Exception e );
[Link] (nume+"ce incearca apel [Link]"+[Link]);
[Link]();
}
syncronized void last(){
[Link] (" interior [Link]");
}
}
class B{
syncronized void bar (A a){
String nume=[Link]().getName();
[Link] (nume+"introdus de metoda [Link]);
try Thread sleep(1000); catch (Exception e );
[Link] (nume+"ce incearca apel [Link]"+[Link]);
[Link]();
}
syncronized void last(){
[Link] (" interior [Link]");
}
}

class Deadlock implements Runnable{


A a = new A();
B b = new b();
[Link]().setName("firul primar"};
new Thread(this).start();
[Link](b); // ia lock on in firul lui
[Link] ("Inapoi la fir principal");
}
public void run(){
[Link]().setName("firul al doilea "};
[Link](a);
[Link] ("Inapoi la ALT fir");
}
public static void main (String args[]){
new Deadlock();
}
}

3.2.6. Folosirea firelor de executie în appleturi

Fiecare applet aflat pe o pagina Web se executa într-un fir de executie propriu. Acesta este creat de
catre browser si este responsabil cu desenarea appletului (apelul metodelor update si paint)
precum si cu transmiterea mesajelor generate de catre componentele appletului. In cazul în care
dorim sa realizam si alte operatiuni consumatoare de timp este recomandat sa le realizam într-un

79
alt fir de executie, pentru a nu bloca interactiunea utilizatorului cu appletul sau redesenarea
acestuia.

Structura unui applet care doreste sa lanseze un fir de executie poate avea doua forme. In prima
situatie appletul porneste un fir de executie la initialzarea sa, iar acesta va rula indiferent daca
appletul mai este sau nu vizibil, pâna la oprirea sa naturala (terminarea metodei run).

Ex: import [Link];


class AppletThread1 extends Applet implements Runnable {
Thread appletThread = null;
public void init() {
if (appletThread == null) {
appletThread = new Thread(this);
[Link]();
}
}
public void run() {
//codul firului de executie
}
}

In cazul în care firul de executie pornit de applet efectueaza operatii ce au sens doar daca appletul
este vizibil, cum ar fi animatie, ar fi de dorit ca acesta sa se opreasca atunci când appletul nu mai
este vizibil (la apelul metodei stop) si sa reporneasca atunci când appletul redevine vizibil (la
apelul metodei start).
Ex: import [Link];
public class StructuraApplet extends Applet implements Runnable {
Thread appletThread = null;
boolean running = false;
public void start() {
//reporneste firul de executie
if (appletThread == null) {
appletThread = new Thread(this);
running = true;
[Link]();
}
}
public void stop() {
//opreste firul de executie
running = false;
appletThread = null;
}
public void run() {
while (running) {
//codul firului de executie
}
}

80
}

Un applet este considerat activ imediat dupa apelul metodei start si devine inactiv la apelul
metodei stop. Pentru a afla daca un applet este activ se foloseste metoda isActive.

3.5. Aspecte particulare ale manipulării excepţiilor

Excepţia este o condiţie excepţională, deosebită ce apare în timpul execuţiei unui program.
Excepţională este condiţia a cărei cunoaştere este posibilă dar se aşteaptă să apară rar sau deloc.
Limbajul Java defineşte clasa [Link] pentru încapsularea noţiunii de excepţie, prin
cele două clase ale sale: [Link] şi [Link]. Excepţia poate fi prinsă (caucht)
şi anulată într-o manieră oarecare, chiar permiţând un impact negativ asupra execuţiei unui
program. Eroarea nu poate fi prinsă de utilizator şi în general obligă la terminarea programului 6.
Când apare o excepţie, metoda ce o generează proiecteaza excepţia şi în general se termină
execuţia metodei, trimiţând un mesaj apelantului în forma unui obiect excepţie din clasa
[Link]. Când o metodă cauzează excepţie, aceasta poate fi prinsă (catch) prin
plasarea apelului "periculos" intr-o buclă try/catch sau poate fi ignorată (netratată). Dacă excepţia
care apare nu este controlată se spune că nu este proiectată (trown) sau dacă este tratată (catch)
poate genera la manipulare alte erori sau chiar o nouă excepţie.
Manipularea erorilor se realizează prin blocul try/catch cu sau fără finally cu sintaxa:
try {
//codul ce generează excepţia

} catch (ClasădeExcepţii nume) {
// codul ce le manipulează orice subclasă din ClasădeExcepţii
} catch (AltaClasădeExcepţii nume) {
// codul ce le manipulează orice subclasă din AltaClasădeExcepţii
}finally {
// cod ce preia execuţia
}

Blocul try este utilizat pentru excepţii de orice tip şi ieşiri anormale (break, return, continue). La
apariţia unei excepţii, interpreterul analizează primul bloc try/catch întâlnit, în care caută clauza ce
marchează o clasă de excepţii. Din acest motiv se specifică întâi excepţiile frecvente şi apoi în
mod gradula cele [Link] blocul finally se preia execuţia dacă blocul try este completat normal
(fără excepţii), dacă unul din blocurile catch manipulează excepţii respectiv dacă in blocurile catch
nu este tratată excepţia respectivă. Acestea sunt aşa numitele excepţii trigger, caz în care fiecare
catch va avea asociat un bloc finally. Pentru a defini comportamentul în toate cazurile, indiferent
dacă excepţia apare sau nu, se specifică bloul finally, executat ori de câte ori se termină un bloc try
(normal sau nu) şi după execuţia unui bloc catch.

Excepţiile nemanipulate (unhandled exceptions) apar când blocul try/catch este inexistent sau nu
are clauză pentru excepţia apărută, caz în care interpreterul caută în cel mai apropiat bloc închis.
Dacă nici o metodă nu tratează excepţia, ea se propagă înapoi în metoda main() şi interpreterul va

6
De obicei de foloseşte termenul de excepţie la ambii descendenţi (Exception şi Error)

81
ieşi, tipărind eroarea, un mesaj şi stack trace (urma stivei).[Chan_95] Dacă se decide ignorarea
unei excepţii, metoda trebuie să aibă precizată în declaraţie faptul că proiectează o clasă
particulară de excepţii, cu menţiunea că o metodă poate proiecta oricâte clase de excepţii, separate
prin virgulă în declaraţie. Metodele extinse nu pot proiecta excepţii.
Spre deosebire de excepţiile normale, apar excepţiile Runtime (anormale) subclasate în
[Link], care pot fi generate de o serie de acţiuni în timpul execuţiei (acces
nepermis la tablouri, operaţii aritmetice, etc.). Dacă metodele nu includ catch pentru aceste
excepţii nu este necesară includerea clauzei throws în declaraţia metodei. Spre exemplu, se omite
throws la apariţia ArrayIndexOutOfBounds xceptions sau ArithmeticExceptions.

[Link] de bază JSE

4.1. Grafică şi animaţie în Java folosind pachetul [Link]


4.1.1. Utilizarea fonturilor şi culorilor în appleturi

Este deja cunoscut un principiu de bază în programerea OO şi anume reutilizarea codului, motiv
pentru care la extinderea unui applet care foloseşte clase din pachetul [Link]. se au în vedere
metodele proprii apletului şi cele extinse ale claselor [Link], [Link],
[Link], etc. Clasa [Link] foloseşte culori încapsulate, declarând 13 culori
constante care pot fi nuanţate, specificând valori numerice din gama RGB (red,green,blue).
Appletul îşi poate seta fundalul şi primplanul prin setForeground() şi setBackground(), la fel
cum poate utiliza getForeground() şi getBackground() pentru a regăsi culorile de primplan şi
fundal. Cele 4 metode sunt moştenite din [Link]. Clasa [Link] foloseşte la
rândul ei fonturi încapsulate, declarând 3 constante pentru reprezentarea stilului de font
[Link], [Link] şi [Link], care pot fi folosite în combinaţie, iar appletul îşi poate
seta fontull prin setFont() şi poate declara fontul dorit prin getFont() [java_4], [Lema_96]
Exemplu:
import [Link];
public class TipFont extends [Link] {
String fontLista[ ];
public void init() {
fontLista=[Link]();
}

public void paint ([Link] g){


int y=10;
for (int i=0; i<[Link](); i++){
[Link](fontLista[i],10,y+15);
}
}
}

Deoarece s-au definit în paragrafele anterioare variante de înglobare a fişierelor grafice, imagini,
executabile din alte medii, este necesară structurarea lor în pachete şi clase pentru a asigura
accesul şi modificarea facilă, paralel cu reutilizarea codului pentru unele clase şi metode definite.
Recomandăm astfel ca appletul să aibă acces direct la directorul principal, creând astfel o
structură arborescentă, prezentată schematic în figura 4.1.:

82
Directorul
principal

Pachet 1 Pachet 2 .classes .java .html

Alte
clase

[Link] [Link]

Figura 4.1. Structura directoarelor pentru o aplicaţie Java

Rădăcina structurii se denumeşte director principal (main) în care se plasează de obicei fişierele
HTML (opţional într-un subdirector al lui main şi un director numit classes (care poate fi opţional
o legătură simbolică cu directorul claselor centrale, oriunde în altă parte pe server).Toate
fişierele .class sunt memorate în acest director, sau în subdirectoare ale acestora, pentru a facilita
utilizarea pachetelor şi claselor în proiectele viitoare, referându-se şi extinzându-se ori de câte ori
este necesar.
In fişierele .HTML este necesară prezenţa atributului CODEBASE="classes" sau alte convenţii
corespunzătoare structurii de de directoare ( spre exemplu: CODEBASE="../classes"), calea
completă fiind specificată în [Link] şi fişierele audio sunt memorate în
subdirectoare distincte (figura 7)corespunzător directorului main şi pot avea legături opţionale.
Structura prezentată are avantajele organizării serverului, mentenabilităţii facile şi posibilităţii
reutilizării codului. In plus, dezvoltarea ulterioară a appletului pe o altă maşină sau un alt server,
nu implică reîncărcarea appleturilor completate şi a paginilor Web spre directoare potrivite
serverului deoarece toate legăturile funcţionează şi oferă portabilitate maximă de la o maşină la
alta. Pentru o aplicaţie complexă se recomandă crearea unui pachet propriu. Proiectarea acestui
pachet este realizată astfel încât să fie memorat în locul unde poate fi accesat pentru necesităţile de
utilizare. Unele pachete sunt create cu uz local, iar altele necesate pentru paginile Web, sunt create
în directoare de unde clientul le poate încărca.
La momentul la care sistemul java trebuie să încarce o clasă, caută pentru fiecare locaţie
specificată în CLASSPATH directorul în care numele este identic cu numele pachetului clasei.
Găsindu-l, utilizează numele pachetului pentru a reconstitui calea potrivită pentru fişierul .class, în
caz contrar, caută în locaţia specificată în CODEBASE, în care se află fişierele .class ale
[Link] mai simplă cale de a face pachetul disponibil clienţilor pentru execuţia appletului
este de a asigura acelaşi director pachetului şi appletului din care face parte.
Exemplu:
public class BandaSimplaextends toolBox ParamP implements Runnable{
int width;

83
int heigh;

4.1.2. Aspecte de alocare dinamică a cadrelor animate

Este deja cunoscut faptul că, la alocare dinamică a unui tablou Java, el nu are valoare. Dacă tabloul
este de tip obiect (opus tipurilor primitive) la instanţierea tabloului nu are loc şi alocarea memoriei
pentru obiectele comprimate în tablou. In fapt, instanţierea tabloului este realizată ca o colecţie de
manipulatori null.
Exemplu:
Se declară tabloul de imagini din clasa [Link]:
Image cadruAnim[ ];

Apare manipulatorul null denumit cadruAnim care nu are valoare şi nici dimensiune

cadruAnim
= null

Figura 4.2. Tabloul de imagini

Când are loc instanţierea tabloului:


CadruAnim = new Image[nume_ cadru];
tabloul are deja manipulatori obiecte Image (figura 4.3.).
cadruAnim
0 1 2 3 4 5 6

= = = null
Figura 4.3. Tabloul de imagini instanţiat

Când se instanţiază elementele individuale de tablou, memoria este alocată individual şi


dinamic pentru fiecare grup de obiecte, aşezate unul în altul, în garbage-collector. In realitate
ele pot sau nu pot fi contigue în memorie, dar după bucla iterativă de instanţiere ele arată
conform figurii 4.4..

cadruAnim
0 1 2 3 4 5 6

= = = null

84
Figura 4.4. Schema de alocare dinamică a cadrelor în tablouri

Java utilizează schema de alocare dinamică pentru toate obiectele care sunt alocate static, nu şi
pentru tipuri primitive (int, float, long, char). Pentru manipularea tablourilor de cadrelor în
animaţie se utilizează clasa abstract [Link] folosind:import [Link]. Cum nu
se poate instanţia direct un obiect din clasa abstractă, se subclasează şi apoi se instanţiază:
Image cadruAnim[ ] ;
Când se instanţiază un tablou de manipulatori ai clasei Image nu se vor instanţia niciodată
elementele individuale ale tabloului ci se apelează [Link]() care construieşte un
obiect independent de platformă, subclasă a lui [Link] şi întoarce manipulator al
acestui obiect. Deoarece obiectul este subclasă a lui [Link], este compatibil cu aceasta
şi poate fi astfel atribuit unui element de tablou.

Metoda [Link]() returnează asincronism deoarece produce un fir către


metoda care încarcă imaginea şi nu aşteaptă completarea firului ci returnează un manipulator
către obiectul Image. Dar firul care încarcă imaginea este în plin proces de încărcare când are
loc getImage() şi return(). Chiar dacă se iniţiază incărcarea tururor imaginilor în timpul
metodei init(), are loc mai mult o încărcare paralel cu debutul buclei de afişare a imaginii pe
ecran. Astfel încât privind un applet care realizează animaţie cu tablouri de cadre afişate
succesiv, are loc o iniţializare a background-ului şi apoi o succesiune de imagini total sau
parţial încărcate, până în final când se încarcă integral tabloul şi are loc animaţia. In realitate
începe desenarea pe ecran inainte e a fi integral încărcate (datorită asincronismului care
permite execuţia simultană a mai multor fire).

Metoda [Link]() întoarce URL-ul directorului ce conţine


fişierul HTML referit de applet. Combinată cu calea relativă a fiecărui fişier imagine, se obţine
calea completă a URL-ului pentru fiecare imagine încărcată. Există o metodă similară
[Link] Base() care întoarce URL-ul directorului ce conţine fişierul .class
referit de applet deoarece nu este o regulă ca fişirul HTMl şi appletul să fie în acelaşi director
(nici măcar pe acelaşi server).
Metoda [Link]() a ca parametru Image şi (x,y) coordonatele ce indică
poziţia relativă faţă de colţul stânga-sus al appletului şi manipulează un obiect din clasa
[Link]. In realitate acesta nu est un obiect ci o interfaţă care permite
obiectelor din diferite ierarhii de clase să s eprezinte ca şi cum ar aparţine aceluiaşi nivel, unei
aceleiaşi clase, simulând astfel moştenirea multiplă. Deoarece [Link]
implementează ImageObserver practic se trece appletul către orice metodă dorită de acesta.
ImageObserver moşteneşte metodele din [Link] deci nu putem vorbi de o
implementare directă ci mai degrabă de o extensie orin moştenire.
Dând this în ImageObserver se poate construi imaginea deoarece metoda paint() este apelată
odată, la fel ca şi drawImage() sau drawString(). Menţionăm că în metoda paint() a appletului s
epoat apela oricâte metode grafice care permit desenarea unei imagini, a unui şir la începutul
ei, urmată de altă imagine, poligo, etc. Nivelul de prioritate superior dă mai mult timp CPU,
motiv pentru care se execută mai repede acel fir care are prioritate mai mare. Nivelul de
prioritate poate fi modificat şi din fişierul HTML. In plus, depinzând de sistemul propriu, firele
cu prioritate mare pot ţine pe loc pe cele cu prioritate mai mică, făcându-le să aştepte până
când cele cu prioritate mai mare termină de exectat taskul lor.

85
4.1.3. Efectele speciale

Pîlpîirea sau vibraţia (flinker) este o metodă des utilizată în animaţie. La apelul metodei
repaint() sistemul invocă metoda update() a appletului, care este moştenită din clasa
[Link] iar codul sursă al versiunii implicite este:
Exemplu:
public void update(Graphics g){
[Link](getBackground());
[Link](0,0,width,height);
[Link](getForeground());
paint (g);
}

Metoda şterge porţiunea appletului pe ecran şi apoi apelează metoda paint(). Din acest
motiv, când se desenează o imagine, apare fundalul blank un timp scurt înainte ca imaginea să
fie desenată şi este parţial responsabil pentru vibraţiile (flinker) din animaţie.
Când se redesenează imaginea peste ea însuşi nu este nesară redesenarea fundalului de
fiecare dată, motiv pentru care se extinde metoda update care reduce pîlpîirea:
Exemplu:
public void update(Graphics g) {
paint (g);
}

Acest "truc" nu se aplică la desenarea textului în mişcare pentu că ştergerea fundalului este
necesară de această dată, permitând o afişare inteligibilă a informaţiei din text.
Whiteboard (hârtia albă) este reprezentarea analogică a contextului grafic, structura de
date pe care le utilizează sistemul şi interfeţele acestuia pentru a desena pe ecran. Utilizând
tehnica "double-buffering" se ţine invizibil contextul grafic din jur şi se desenează textul in
acest context. După finalizarea metodei paint() se face vizibil contextul grafic, ceea ce ai mai
puţin timp faţă de operaţiile actuale de desenare care au loc în spatele ecranului.

4.1.4. Ierarhia componentelor GUI

In GUI la nivelul cel mai înalt apar două tipuri de componente: componente de bază:
Canavas,Scroolbar, Button,Checkbox,etc şi conteinere sau componente ce conţin alte componente
ca şi Window şi subclasele Frame, Panel (cel mai familiară subclasă Applet) (figura 4.6.).
Containerele sunt subclasate în [Link] (figura 4.5.).
Este util de precizat că ierahia componentelor este diferită de ierarhia de clasă. Structura
ierarhiilor (figura 4.6.) nu are legătură cu moştenirea, de accea componentele ce aparţin
conteinerelor sunt cele cu săgeată ar cele reprezentate cu linie simplă sunt clauze extends.
Clasa [Link] (figura 4.5.) include metoda add() ce adaugă componente în
conteiner, utilizată la secţiunea Panel prin:
[Link](CheckboxPanel);

4.1.5. Interfaţa LayoutManager

86
Pentru aşezarea pe ecran, AWT utilizează un obiect ce implementează interfaţa
LayoutManager, care controlează regulile prin care un Conteiner dat îşi va aşeza propriile
componente constituente. Se instanţiază un obiect din LayoutManager pentru fiecare Conteiner
creat, utilizând metoda conteinerului getLayout() pentru a specifica ceea ce utilizează
LayoutManager.[java_7]

[Link]

[Link] [Link]

[Link]

[Link]

[Link]

[Link] [Link] [Link]

[Link]
Figura 4.5. Gruparea componentelor Java
Exemplu:
[Link](new BorderLayout());

87
Applet

Panel Panel Panel

Button

Checkbox Panel Label Chioce

Checkbox Checkbox

RectCanvas Scrollbar Scrollbar


Figura
4.6. Ierarhia
componentelor GUI

Pachetul [Link] defineşte căteva LayoutManager standard, incluzând:FlowLayout,


BorderLayout, CardLauout, GridLayout, GridBayLayout,etc.

FlowLayout
Cel mai simplu LayoutManager este FlowLayout care aranjează componentele în Conteiner de la
stânga la dreapta. Când se umple un rând, FlowLayout crează un nou rând, punând componentele
în aceeaşi ordine. Dacă nu se specifică LayoutManager pentru Panel sau Applet, este folosit
implicit.

BorderLayout
BorderLayout divide în 5 regiuni spaţiul alocat, aranjând componentele în Conteiner în regiunile
specificate (figura 4.7.).

North

East Center Vest

South

Figura 4.7. Regiunile FlowLayout

88
CardLayout
Intr-un conteiner setat CardLayout, numai un component constituent este vizibil la un moment dat.
CardLayout furnizează metode first(), last(), next(), previous() şi show() pentru a selecta
componenta vizibilă. Tipic fiecare component adăugat în CardLayout va fi un Conteiner, ce
conţine alte componente. Acest mod este util pentru proiectarea ecranelor tabbed (tabulate) unde
fiecar ecran prezintă un set de controale legate în relaţie şi utilizatorul poate traversa ecranele în
ordine prin click pe un anume tip de control, de obicei simulând index tab la începutul
directoarelor de fişier.

GridLayout
Acest standard subdivide componentele într-un număr de linii şi coloane (specificate de
constructor). Componentele sunt plasate în celule divizate în ordinea adăugării lor.în Conteiner.
Celulele se extind sau se contractă cât este necesar pentru a se potrivi cu dimensiunea preferată de
componente.

GridBagLayout
Cea ma mare flexibilitate şi control al programatorului îl oferă "regina" LayoutManager-
GridBagLayout, deşi este cel mai complex de utilizat. La fel ca şi GridLayout se subdivide în
celule. Fiecare Component manipulat poate lua una sau mai multe celule, paote fi alungit pentru a
ocupa spaţiu mai mare relativ la alte componente şi poate dispune de o arie de aşezare ce permite
spaţiu liber între el şi alte componente. Pentru fiecare Component, GridBagLayout menţine o
instanţă a lui GridbagConstraints, care conţine constrângeri specifice, informaţii despre modul în
care va fi aşezat acest Component particular. Setarea acestor informaţii se face prin construcţia
unui obiect din clasa GridbagConstraints, setând câmpurile apropiate şi apoi trecând în metoda
setConstraints, pentu a referi componenta ce utilizează constrângerile setate.
Exemplu:
Gb= new GridBagLayout();
//referinta la gb apoi apelam metoda lui
c= new GridBagConstraints();
[Link](gb);
[Link]=20;
//lugime orizontala relativa 2
[Link](my Component, c);
[Link](myComponent);

la apelul [Link](my Component, c); gb crează o copie a obiectului


GridBagConstraints şi o utilizează pentru manipularea lui myComponent. GridBagLayout nu
utilizează obiectul original ci o instanţă a lui GridBagConstraints. Este uşor de craet o singură
instanţă a lui GridBagConstraints, setarea câmpurilor după dorinţă şi apoi utilizarea lui pentru
adăugarea componentelor multiple ce se aşează cu aceleaşi caracteristici7.

4.1.6. Construcţia GUI cu pachetul [Link]

[Link] este un program simplu de desenare, ce permite desenarea unui obiect de tip
Rectangle umplut sau nu cu o culoare. Prin acest exemplu se ilustrează diferenţa între desenarea
7
Detalii se află în API Documentation

89
bitmap şi cea OOP8 . Fiecare dreptunghi este vizibil utilizatorului ca un obiect, modelat ca atare şi
tratat ca o colecţie de biţi, fără a face distincţie între obiectele individuale ce compun imaginea.
Extinzând moştenirea, se poate desena orice obiect.[Ramb_96]
Exemplu:
import [Link];
import [Link].*;
import [Link];
// clasa ce extinde Rectangle
class DrawableRect extends Rectangle{
Color color=[Link];
Boolean filled=false;
//construcţia dreptunghiului
DrawableRect (int x, int y, int width, int heigh, Color, color, boolean filled) {
Super(x,y,width, heigh);
[Link]=Color;
[Link]=filled;
}

//desenare in contur offset specificat


void drawn (Graphics g, int offset_x, int offset_y) {
[Link]=[Link]();
[Link](color);
if (filled) {
[Link] (x-offset_x, y- offset_y, width, heigh);
}else{
[Link] (x-offset_x, y- offset_y, width, heigh);
}
[Link](temp);
}
}
class CheckBoxPanel extends Panel {
// grup de CheckBox mutual exclusive
CheckBox Group myGroup;
//2 CheckBox in grup
CheckBox filledBox;
CheckBoxnotfilledBox;
CheckBoxPanel(){
//alt [Link]
super();
setLauout(new BorderLayout());
filledBox=new CheckBox("Filled",myGroup, false);
notfilledBox=new CheckBox("Not Filled",myGroup, true);
[Link](notFilledBox);
add("North", filledBox);
add("South", notFilledBox);
}
8
Painting program = program de desenare orientat obiect (OOP)

90
// intoarce starea grupului CheckBox
boolean isFilled(){
return [Link]==filledBox);
}
}

Class RectCanavas extends Canavas {


//mouse punctul de jos
int orig_x;
int orig_y;
// cand se face scroll
public int offset_x=0;
public int offset_y=0;
// setare curenta pentru un nou dreptunghi
boolean filled=alse;
Color rectColor=[Link];

//colectia d edreptunghiuri
int numRects=0;
Vector rects= new Vector(100,10);
//numai pentru convenienta
DrawableRect currentRect;
// crează un dreptunghi desenabil si il adauga in lista
DrawableRect addRect ( int x,int y ; int width, int height){
DrawableRect r = new DrawableRect (x,y,width;height, rectColor, filled);
[Link] ( r );
NumRects++;
return r;
}

//dispune toate dreptunghiurile si incepe o noua lista


void clearRects() {
numRects=0;
rects= new Vector(100,10);
repaint();
}

//seteaza culaorea pt. Adaugarea unui nou dreptunghi


void setRectColor(Color c) {
rectColor =c;
}

//seteaza atributele de umplere pt. Adaugarea unui nou dreptunghi


void setFilled(boolean b) {
filled =b;
}

91
//raspuns la eveniment mouseDrawn
//apelat de handleEvent mostenit
public boolean mouseDown (Event evt, int x, int y) {
//seteaza punct mouse down
orig_x=x;
orig_y=y;
//incepe un nou dreptunghi
current Rect=addRect(orig_x+offset_x,orig_y+offset_y,0,0);
return true;
}

//raspuns la eveniment mouseDrag


//apelat de handleEvent mostenit
public boolean mouseDrag (Event evt, int x, int y) {
//cat se trage punctul
int x_diff=x-orig_x;
int y_diff=y-orig_y;

//dreptunghiul nu are dimensiuni negatige


//cautam coltul stanga=sus
int x_val=(x_diff>0) ? orig_x+offset_x : x+offset_x;
int y_val=(y_diff>0) ? orig_y+offset_y : y+offset_y;

// inaltime si latime determinate prin lungime drag


int width_val=[Link](x_diff);
int height_val=[Link](y_diff);

//redesenare interactiva a dreptunghiului


current Rect=reshape(x_val, y_val,width_val, height_val);

//arata rezultat cand utilizatorul retrage


repaint();
return true;
}

//Deseneaza toate dreptunghiurile pe Canavas


public void paint(Graphics g){
DrawableRect r;

for (int i=0; i<numRects; i++) {


r=(DrawableRect).[Link](i);
//deseneaza fiecare dreptunghi offset fata de dimensiunea scroll
[Link](g,offest_x,offset_y);
}
}

92
}
public GUIExample extends Applet {
//varful paletei si sub-itemii ei

panel topPanel = new Panel();


CheckboxPanel chechboxPanel= new CheckboxPanel();
Label colorLabel= new Label("color:");
Choice colorChoice= new Choice();

//mijlocul paletei si sub-itemii ei

panel middlePanel = new Panel();


RectCanavas rCanavas= new RectCanavas();
Scroll_bar x_scroll= new ScrollBar([Link]);
Scroll_bar y_scroll= new ScrollBar([Link]);

//sfarsitul paletei si sub-itemii ei

panel bottomPanel = new Panel();


Button clearButton=new Button("clear");
}
public void init() {
// crearea unui manager implicit si setarea appletului pt. Utilizare
[Link] (new BorderLayout());

//selectia culorilor
[Link]("Black");
[Link]("Blue");
[Link]("Red");
[Link]("Green");
[Link]("Yelow");
[Link]("Cyan");

[Link]("Black");

// adaugarea tuturot itemilor la inceputul paletei


[Link](checkboxPanel);
[Link](colorLabel);
[Link](colorChoice);

//adaugarea inceputului paletei la applet


[Link]("North",topPanel);

// mijlocul Panel
[Link](new BorderLayout ( r )) ;

93
//setarea la mijlocul paletei a RectCanavas
[Link]([Link]());
[Link](getSelectedColor());
[Link]([Link]);
//adaugarea tuturor itemilor la mijlocul paletei
[Link]("South", x_scroll);
[Link]("Est", y_scroll);
[Link]("Center", rCanavas);

//sfarsitul paletei
[Link](clearButton);

//adaugarea paletei la applet


[Link]("South",bottomPanel);
resize(350,350);
}

public void paint (Graphics g){


[Link]();
}

//se citeste culoarea selectata


Color [Link]() {
if([Link]().eguals("Black")){
return [Link];
}else { if([Link]().eguals("Blue")) {
} else {

}
}

//suprascrie [Link]()
public boolean handleEvent(Event evt){
if ([Link]==colorChoice){
[Link](getSelectedColor());
}else { if ([Link] instance of Checkbox){
[Link]([Link]());

}else if {[Link]== x_scroll){


switch (evt_id) {
case Event.SCROLL_LINE_UP:
case Event.SCROLL_LINE_DOWN:
case Event.SCROLL_PAGE_UP:
case Event.SCROLL_PAGE_DOWN:
case Event.SCROLL_ABSOLUTE:

94
//[Link] tin valorile cu care bara este deplasata
rCanavas.offset_x=((Integer)[Link]).intValue();
break;
}
else if ([Link]==y_scroll){
switch (evt_id) {
case Event.SCROLL_LINE_UP:
case Event.SCROLL_LINE_DOWN:
case Event.SCROLL_PAGE_UP:
case Event.SCROLL_PAGE_DOWN:
case Event.SCROLL_ABSOLUTE:

//[Link] tine valoare cu care se deplaseaza bara


rCanavas.offset_y=((Integer)[Link]).intValue();
break;
}
}
//canavas a fost deplasat
[Link]();
// ne asiguram ca alte evenimente nu sunt manipulate
return [Link](evt));
}
//raspuns la actiunea evenimentelor
public boolean action(Event evt, Object what) {
if ([Link](clearButton){
[Link]();
}
}
//numai cand parintele are nevoie de eveniment
return [Link](evt,what);
}

//suprascrie [Link]()
//apelata la redimensionarea appletului
public void reshape(int x, int y, int width, int height){
[Link](x,y,width,height);

//ajustare scrollbar cu valori vizibile


x_scroll.setValues(rCanavas.offset_x,canavasWidth,0,1000-canavasWidth);
y_scroll.setValues(rCanavas.offset_y,canavasWidth,0,1000-canavasWidth);

[Link]();
}
}

Explicaţia codului

95
Exemplul de mai sus are 4 clase, una dintre ele fiind chiar appletul GUIExample.
DrawableRectangle este o extensie a lui [Link] deoarece [Link] are rol de
a modela o cutie dreptunghiulară în general, iar obiectul appletului este modelarea unei clase de
dreptunghiri care să se deseneze şi în care să se poată include starea informaţiilor despre umplerea
dreptunghiurilor şi culoarea de umplere.
Celelalte 2 clase sunt extensii ale [Link] din categoria widgets9 şi anume
RectCanavas este o colecţie de DrawableRectangles iar CheckBoxPanel dă un mod convenabil de
încapsulare a grupului de elemente Checkbox Group.
Un mare avantaj al funcţionalităţii appletului le dau widgets utilizate şi subclasate în (scrollbar,
buttons, checkbox, etc) avantaje ale OoP demonstrate prin proiectarea GUI.
OOP permite "mascarea" acestor widgets în ierarhii de clasă şi prezintă o interfaţă simplă şi relativ
abstractă a acestora. API reduce complexitatea dezvoltării programelor şi furnizează abstractizarea
necesară.
Componenta Checkbox Grup are capacitatea de a grupa în ea, folosind selecţii mutual exclusive de
Checkbox. Checkbox însuşi răspunde imediat la mouse-click selectându-se grafic pe el însuşi, şi
dacă programatorul a alocat un grup pentru el, deselectează celelalte checkbox din grup10 .
Elementul Choice automat oferă meniul de selecţie iar odată selectată opţiunea se poate transporta
cu metoda getSelectedChoice(). In aceste componente nu trebuie să răspundem de evenimentul
mouse-click pentru că este proiectată metoda handleEvent() în fiecare. In general, componentele
ce răspund în mod normal la evenimente mouse-click sau alte evenimente de la tastatură,
suprascriu handleEvent() şi gestionează click-mouse, generând alte evenimente, d eobicei de tip
ACTION_EVENT.

4.1.7. Manipularea evenimentelor în funcţie de ierarhia componentelor

Când apare un eveniment, sistemul crează un obiect din clasa [Link], determinat de
componentă şi acesta ia evenimentul apelat de metoda handleEvent() a componentei, trecând
obiectul Event ca [Link] manipularea evenimentelor trebuie să se ţină cont de iararhia
componentelro. Spre exemplu, ce se întâmplă dacă apare evenimentul mouse-click pe Canavas,
conţinut d ePanel, conţinut la rândul lui de Applet? Sistemul respectă următoarea regulă; începe cu
cel mai mic component din ierarhie şi îl tratează urmâd ca apoi să examineze alte evenimente din
ierarhie. Ierarhia de componente este cea stabilită de Components (figura 4.6.) şi Conteir-ele lor şi
nu este ierarhia moş[Link]ă handleEvent() a componentei întoarce true, însemnă că
evenimentul este manipulat de acel component şi nu se întreprinde nici o acţiune. Dacă returnează
true, sistemul apelează metoda handleEvent() a următorului component din ierarhie:conteinerul
componentului. Evenimentul continuă să se propage în sus pe ierarhie, până câd un component
întoarce true din handleEvent() sau nu au rămas componente cărora să le aparţină evenimentul.
Unele componente ca şi Checkbox, Button, Choice, ce nu au nivel cert al funcţionalităţii
moştenite, răspund la evenimente, generând evenimente adiţionale, cel mai frecvent
Event.ACTION_EVENT. Barele de defilare generează variate tipuri de evenimente. Listele de
selecţie generează Event.LIST_SELECT şi Event.LIST_DESELECT în plus faţă de
Event.ACTION_EVENT.

[Link]()

9
putem asimila widgets ca elemente grafice prefabricate
10
respectând selecţii mutual exclusive

96
Câteva tipuri de evenimete ca şi Event.MOUSE_DOWN, Event.MOUSE_DRAG şi
Event.ACTION_EVENT sunt manipulate de [Link]() ce răspunde de
ele, apelând mouseDown(), mouseDrag() şi action(). In componentele generice (în particular
Applet, Panel şi Canavas) aceste metode sunt void. Dacă se doreşte ca un component să răspundă
într-un anume mod la aceste evenimente, se vor subclasa şi prin simpla suprascriere a metodelor
mouseDown(), mouseDrag() şi action() se va adăuga acţiunea dorită. Versiunea implicită a lui
handleEvent() nu răspunde la toate tipurile de Event definite în [Link]. Dacă este necesar
un răspuns la evenimente ce n-au fost prinse în handleEvent(), implicit se suprascrie handleEvent()
ca şi clasa applet . Se poate utiliza o versiune proprie a lui handleEvent() , care răspunde la aceste
tipuri de evenimente şi care nu sunt prinse în versiunea implicită. Odată terminată verificarea
acestora, se apelează [Link], pentru a lăsa versiunea implicită să manipuleze
evenimente ce sunt deja programate pentru a fi manipulate ca şi ACTION_EVENT.
Codul [Link]()11 este:
public boolean handleEvent(Event evt){
switch (evt.id0 {
case Event.MOUSE_ENTER:
return mouseEnter(evt, evt.x,evt.y);
case Event.MOUSE_EXIT:
return mouseExit(evt, evt.x,evt.y);
case Event.MOUSE_MOVE:
return mouseMove(evt, evt.x,evt.y);
case Event.MOUSE_DOWN:
return mouseDown(evt, evt.x,evt.y);
case Event.MOUSE_DRAG:
return mouseDrag(evt, evt.x,evt.y);
case Event.MOUSE_UP:
return mouseUp(evt, evt.x,evt.y);
case Event.KEY_PRESS:
case Event.KEY_ACTION:
return keyDown(evt, [Link]);
case Event.KEY_RELEASE:
return keyUp(evt, [Link]);
case Event.ACTION_EVENT:
return keyDown(evt, [Link]);
case Event.GOT_FOCUS:
return gotFocus(evt, [Link]);
case Event.LOST_FOCUS:
return lostFocus(evt, [Link]);
}
return false;
}

Câmpuri din [Link]

Obiectul Event are o serie de câmpuri dar facem referire doar la cele mai importante folosite în
programare:
• id - conţinut de tipul Event ca şi Event.ACTION_EVENT sau Event.MOUSE_DOWN;
• target - conţinând widgets ce generează evenimetul;

11
[java_4] Java Soft INC., Java Advanced API Specification, [Link]

97
• when- caracteristica de timp indicată când evenimentul apare (utilizat numai pentru mouse şi
tastatură);
• x,y, coordonatele evenimentului (utilizat numai pentru mouse şi tastatură şi
WINDOW_MOVED);
• key -cod ASCII pentru cheia apăsată în evenimentul de la tastatură;
• modificatori- indicaţii asupra cheilor (SHIFT,CTRL) care sunt jos când evenimentul keyboard
sau mouse apare. Ele nu sunt utilizate la MOUSE_ENTER sau MOUSE_EXIT. Cheile
modificatoare nu generează ele însele evenimente. Fiecare este reprezentată de un set de biti
neacoperibili astfel încât se pot utiliza constante mască furnizate de clasa Event, pentru a
determina câd un modificator dat a fost jos în timpul evenimentului de la tastatură sau mouse.
• arg conţin un Object ce variază pentru tipurile particulare de evenimente. Pentru
ACTION_EVENT este String cu eticheta elementului selectat, generat când Button este apăsat
sau Choice, Checkbox sau MenuItem sunt selectate, ListItem sau double-click sau utilizatorul
apasă cheia Return din textField. Pentru evenimente din Scrollbar, fiecare dintre acestea conţine
un int ce indică poziţia cu care Scrollbar a fost mutată. In final, când utilizatorul dă single-click în
List, se generează unul din evenimentele LIST_SELECT sau LIST_DESELECTpentru acre
câmpul arg este int şi indică aloare indexului elementului pe care s-a acţionat click.[java_5]
Pentru a redimensiona componentele apelăm la metoda supascrisă a lui
[Link]() deoarece appletul conţine Scroolbar şi sunt necesare modificări
de dimensiune pentru a asigura dimensiuni "vizibile" în conţinutul virtual dat de Canavas. In cazul
în care se suprascrie reshape(0 se apelează apoi [Link]() dat fiind faptul că metoda
implicită face o serie de reamenajări care în cazul în care nu sunt realizate, conduc la apariţia unor
efecte nedorite pe ecran.

4.1.8. Animaţie în Java

Orice animaţie are ca obiective specifice în realizarea acestor "filme" sau secvenţe animate,
care pot constitui parametri utilizator în funcţie de care se realizează diferite variante de "film" 12.
Acestea presupun:[java_7]
• specificarea ordinii cadrelor în scopul reutilizării lor;
• specificarea punctului de unde se repetă animaţia;
• specificarea soundtrack-ului;
• specificarea sunetelor ce pot fi dispuse în cadre individuale;
• specificarea cuantei de timp pentru pauza dintre cadre (atât pentru întreaga animaţie cât şi
pentru cadrele individuale);
• specificarea unei imagini de început afişată la momentul încărcării;
• specificarea background-ului de imagine peste care se afişează animaţia propriu-zisă;
• specificarea poziţiei de la care se afişează fiecare cadru13.

Animaţia simplă presupune afişarea unei imagini statice (cadru) la un moment dat, într-o buclă
şi ideea centrală este de a afişa un cadru de secvenţe, făcând transfer de la cadru la cadru, atât de
repede încât percepţia naturală este realizată ca întreg, simulând o imagine în mişcare14

12
Pentru detalii consultaţi site-ul java@[Link]
13
Conform Herb Jellinek | jellinek@[Link]
14
durata cu care se schimbă cadrele este egală cu durata persistenţei imaginii pe retina ochiului

98
Respectând principiile de proiectare a directoarelor anterior expuse, cadrele se înmagazinează
într-un director de imagini iar appleturile şi fişierele HTMl au în general direcor comun sau două
subdirectoare de acelaşi nivel.

In documentaţia API, [Link] defineşte metoda paint() moştenită de la unul din


ascendenţi [Link]. Moştenirea este cumulativă, clasa moştenind tot ce are superclasa
inclusiv moştenirile superclasei în sine. Browserul apelează paint() ori de câte ori este necesară
afişarea unei porţiuni de ecran ce conţine appletul propriu. In general gând se glisează o fereastră
peste appletul propriu (parţial sau integral) browserul redesenează porţiunea appletului ascunsă de
fereastră, apelând metoda paint(). [java_4]
Exemplu:
import [Link];
import [Link];
import [Link];
public class Desen extends Applet {
// coordonatele desenului
int x_coord[ ]={120,250,50,230,70,170};
int y_coord[ ]={20,250,150,130,170,20};
public void init(){
// definim metoda init
[Link] ('initializarea appletului");
SetBackground([Link]);
SetForeground([Link]);
resize(400,400);
}
public void start(){
// definim metoda start
[Link] ('rularea appletului");
}

//desenul
public void paint(Graphics g){
[Link] ('desenarea ");
[Link](x_coord, y_coord,5);
}
public void stop(){
// definim metoda stop
[Link] ('oprirea appletului");
}
public void destroy(){
// definim metoda destroy
[Link] ('distrugerea appletului");
}

}
Codul fişierului HTML conţine:

99
<applet code=[Link] width=450, height=450>
</applet>

Observaţie: Dacă se rulează cu Netscape, se setează Show Java Console care permite afişarea
mesajelor.

Rularea appletului:
Este deja cunoscut faptul că utilizarea opţiunii Reload din Netscape reîncarcă pagina ce conţine
appletul, dar browserul nu încarcă appletul în sine. Dacă se doreşte cel mai recent vizitat applet, cu
comportamentele noi ale acestuia, se selectează Network Preferences din meniul Options ştergând
disk cache astfel încât sistemul utilizează memoria cache. Când appletul se încarcă se va afişa cea
mai recentă versiune a lui.
Pentru a exemplifica acţiunile specifice ciclului de viaţă se recomandă următoarele experimente:
 Se lasă pagina şi apoi se reîntoarce la ea;
 Se încearcă minimizarea ferestrei browser;
 Se readuce fereastra la dimensiune normală;
 Se mută fereastra consolei in faţa appletului pentru a-l umbri;
 Se readuce fereastra appletului în primplan şi se defilează prin applet.
Cele trei instrucţiuni importă clasele Graphics, Color şi Applet care nu devin parte integrată a
codului appletului şi nu afectează dimensiunea [Link]ă import ele se referă conform
convenţiei sintactice:
public class Desen extends Applet {
Fiecare applet este o nouă clasă ce extinde clasa Applet şi moşteneşte variabilele şi metodele din
[Link]. Desen este clasă declarată public pentru că se utilizează de o aplicaţie din
exterior iar în caz contrar browserul nu poate avea acces la Desen şi nu il poate rula.
Cele două declaraţii de tablou:
int x_coord[ ]={120,250,50,230,70,170};
int y_coord[ ]={20,250,150,130,170,20};
permit alocarea spaţiului automat.
In momentul apelului [Link]() se afişează un mesaj şi apoi se apelează cele două metode
moştenite din [Link] ([Link] şi [Link]) care sunt variabile [Link] final
redimensionează appletul la (400,400). La Netscape se remarcă un scurt flash de la dimensiunea
din HTML (450,450) la cea a appletului. Toate metodele sunt publice pentru a avea acelaşi tip de
acces cu clasa din care fac parte. Dacă se doreşte în jurul appletului se poate completa cu text.

Spre deosebire de appletviewer, în Netscape pagina rămâne statică iar resize() nu are efect. La
apelul resize() (redesenare) se specifică aria pe care appletul o recunoaşte ca proprie iar la
redesenare se actualizează doar aria respectivă. Acest lucru este des utilizat în animaţie pentru a
optimiza zona efectiv actualizată.[java_5]
Browserul trece metoda paint() unui obiect din clasa Graphics. Obiectul însuşi este referit în
context grafic, creat, menţinut şi posedat de sistem. După ce anunţă consola că paint() este apelat,
metoda trimite mesaj către obiectul Graphics, cerându-I să execute drawPolygon(), metodă din
[Link] care ia 3 parametri: (x,y) din zonă şi numărul de laturi-n. Poligonul poate fi
(0,0) y
închis (când n=numărul de laturi, sau deschis n> numărul de laturi). In Java, originea sistemului de
coordonate este stânga-sus şi coordonatele cresc în jos pe ecran (figura 3.2.).

100
x (120,150)
Figura 3.2. Coordonatele grafice în Java

Metodele stop() şi destroy() au rolul de a demonstra ciclul de viaţă al appletului.

Folosirea appleturilor Java în paginile web


Când NU trebuie folosite Applet-urile Java:
• pentru simple animaţii, acestea pot fi făcute cu gif-uri animate care se încarcă mai repede şi
sunt compatibile cu mult mai multe browsere;
• pentru butoane: nu toata lumea are browsere care rulează Applet-uri sau în unele cazuri
această opţiune poate fi dezactivată. Dacă totuşi un programator foloseşte Applet-uri pentru
butoane, trebuie să fie sigur că aceasta este numai o alternativă şi că aduce ceva în plus faţă de
un link obişnuit ;
• nu se umple pagina web cu multe applet-uri, aceasta va face ca pagina să se încarce foarte
greu;
• în general nu trebuie lăsat numai pe seama Applet-urilor Java lucrurile esentiale din pagina
web! (pe site-urile marilor companii, applet-urile Java sunt aproape inexistente).
Când trebuie folosite Applet-urile Java:
• Când pagina web trebuie să prezinte lucruri care nu sunt posibil de realizat numai cu HTML
(ex: mici programe interactive, jocuri, animaţii cu sunet etc )
• Când se doreşte ca pagina să ofere un înalt grad de interactivitate.
• Java este sinonim cu Internetul. Applet-urile Java nu sunt indispensabile pentru Web. Ele
sunt ca sarea si piperul unei pagini web si nu trebuie abuzat de ele.

4.1.9. Realizarea animaţiei

Prezentăm un exemplu imperfect dat de o buclă infinită ce redă controlul CPU. Appletul are rolul
de a demonstra ce se întâmplă când un applet animat nu-şi crează un fir propriu independent
pentru a rula animaţia. Executat pe sistem multitasking la sfârşit se poate forţa terminarea
appletului.[java_6]
Exemplu:
import [Link];
import [Link];
import [Link];

public class BandaDefilanta extends Applet {

101
String msg; // mesaj defilant
int x, y // coordonatele desenului
int orizPas;//dimensiune pas în pixeli
int pause;// numar de iteratii in bucla pauza
int msgWidth; dimesiunea mesajului în font curent

public void init(){


msg="Monopolizarea CPU";
pause=100000;
orizPas=2;
FontMetrics fm=get FontMetrics(get Font());
MsgWidth=[Link](msg);
// incepe x din dreapta
x=size().width;
// incepe y mai sus de capăt
y=size().height-(int)([Link]()/3);
}
public void paint(Graphics g) {
while (true) {
//redesenarea appletului in fundal
[Link](getBackground());
[Link](0,0,size().width, size().height);
//desenarea mesajului în poziţia curentă
[Link](getForeground());
[Link] (msg,x,y);
//avans stânga
if(x>0-msgWidth){
x=x-orizPas;
}else{
//incepe din dreapta
x=size().width;
}
pauza(pause)
}
}
void pauza(int contor){
// definim metoda de pierdere de timp
for(int i=0,i<contor,i++) {
}
}
Codul fişierului HTML conţine:
<applet code=[Link] width=250, height=150>
</applet>

Rularea appletului
Metoda [Link]() trimite un mesaj către obiectul grafic g, contextul grafic îl trece ca parametru
lui paint(), comunicând şi setul de culori al "peniţei" pentru a umple sau desena figuri geometrice

102
sau şiruri. Prin apelul lui [Link](getBackground()) se ia fundalul curent. Dacă se utilizează un
dreptunghi pentru fundal, acesta umple zona appletului, ştregând aria pe ecran. Se setează culoarea
de primplan a appletului pentru a putea desena mesajul pe ecran. Metoda size() moştenită din
[Link] dă înălţimea şi lăţimea appletului şi întoarce un obiect de tip
[Link] (clasă care conţie 2 variabile width şi height). Aceşti 2 membri ai obiectului
pot fi accesaţi direct, fără a declara un obiect din clasa Dimension. Dacă se intenţionează
utilizarea succesivă a variabilelor width şi height, este de preferat memorarea lor într-un obiect,
pentru a nu permite apelurile redundante ale lui size(). Datorită faptului că dimensiunea appletului
se schimbă, cel mai simplu mod de a garanta valoarea recentă este de a apela size() direct. In
exemplu se foloseşte o metodă atipică de a plasa bucla de animaţie loop în interiorul metodei
paint(). In plus, fundalul se redesenează de fiecare dată când se redesenează şirul dar utilizând
update() se poate desena numai fundalul. Obiectul FontMetrics este util pentru a calcula lingimea
şirului din mesaj, dat fiind faptul că multe fonturi sunt proporţionale, înafară de monospaţii şi este
de dorit ca fonturile să fie cât mai aspectuase deşi sunt dependente de sistemele pe care se rulează
appletul.[java_7]

103

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