Sunteți pe pagina 1din 22

Tehnici avansate de programare

1. Recapitulare (OOP folosind Java) 2. Programare generica (STL-C++) 3. Metode de elaborarea algoritmilor (Greedy, Programare dinamica, Divide et impera, backtracjing, Branch & Bound) 4. Programare concurenta in Java (fire de executare)

*************************************************************

1. Programare orientat spre obiecte n Java [2 ore C + 2 ore L] 1.1. Introducere


Programarea orientata spre obiecte (Object Oriented Programming) reprezinta o tehnica care permite realizarea programelor complexe in conditii de puternica structurare, modularizare si abstractizare. Obiectele lumii reale sunt modelate prin obiecte software. Limbajele de programare care dispun de mecanisme de definire, manipulare si interactiune a obiectelor se numesc limbaje de programare orientate spre obiecte. Un limbaj de programare orientat spre obiecte este caracterizat prin urmatoarele trei proprietati importante: incapsulare, mostenire si polimorfism. Prin incapsulare se combina o inregistrare cu functiile si procedurile care manipuleaza aceasta inregistrare, formandu-se un nou tip de date care se numeste obiect. Datele descriu proprietatile (starea) obiectului, iar functiile (si procedurile in Object Pascal) definesc comportamentul. Mostenirea apare atunci cand se defineste un obiect si se foloseste aceasta definitie pentru a construi o ierarhie de obiecte, fiecare descendent mostenind accesul la datele si instructiunile aflate in nodurile stramosilor (ierarhia de obiecte se poate reprezenta ca un arbore, nodul radacina fiind obiectul ale carui proprietati vor fi mostenite). Prin polimorfism se permite ca numele unui subprogram care defineste comportamentul unui obiect sa .

fie partajat de obiectele din ierarhie, pentru fiecare obiect subprogramul ac#ion|nd conform propriilor necesit{#i. Din cele de mai sus observ{m c{ obiectele sunt mai puternice ca modulele. Obiectele pot fi privite ca ni~te capsule care limiteaz{ accesul neautorizat la datele interne ~i la anumite subprograme. Exist{ restric#ii de acces chiar ~i pentru membrii unei ierarhii. Dac{ datele unui obiect descriu starea sa, subprogramele, numite metode }n cadrul program{rii orientate spre obiecte, descriu interac#iunea unui obiect cu mediul. Prin intermediul metodelor obiectele pot comunica unele cu altele. Apelul unei metode se nume~te ~i transmitere de mesaj. O mul#ime de obiecte de acela~i fel formeaz{ o clas{ care poate fi descris{ prin modelul comun al obiectelor sale. O clas{ este similar{ no#iunii de tip de date abstract din limbajele de programare conven#ionale precum Ada ~i Modula-2. Totu~i, }n limbajele conven#ionale, nu se pot construi tipuri noi de date pornind de la tipuri existente. Clasele au diverse roluri }n programarea orientat{ obiect: furnizeaz{ mecanismul prin care se pot identifica obiecte cu acelea~i propriet{#i; reprezint{ un mecanism de structurare similar subprogramelor ~i modulelor. Exist{ o rela#ie de tip unula mai mul#i }ntre obiecte ~i clase. Mai precis, fiecare obiect apar#ine unei singure clase, dar o clas{ poate con#ine mai multe obiecte. Dac{ C este o clas{, iar x este un obiect al clasei C, se mai spune c{ x este o instan#{ a clasei C. No#iunea de obiect dateaz{ din anii 60, odat{ cu apari#ia limbajului Simula. ]n prezent exist{ at|t limbaje procedurale dezvoltate pentru a oferi posibilitatea lucrului cu obiecte (Pascal, C++, etc.) c|t ~i limbaje obiectuale pure (Smalltalk, Eiffel, Java etc.). ]n cele ce urmeaz{ continu{m prezentarea terminologiei utlizate }n cadrul program{rii orientate spre obiecte folosind limbajul Java. Se presupun cunoscute elementele de baz{ ale limbajului C.

1.2. OOP n Java prin exemple comentate


Vom exemplifica cele de mai sus prin urm{torul cod Java: class dreptunghi { double lungime; double latime; dreptunghi(double a, double b){ lungime=a; latime=b; } double perimetrul(){ return 2*(lungime+latime); } double suprafata(){ return lungime*latime; } } class patrat extends dreptunghi {

patrat (double latura){ super(latura, latura);} double latura(){return this.latime;} } class testpatrat{ public static void main(String[] args){ patrat x = new patrat(10); System.out.println(Dimensiunile patratului sunt: ); System.out.println(x.lungime+ : +x.latime); System.out.println(sau, folosind metoda latura(): +x.latura()); System.out.println(Suprafata patratului este:); System.out.println(x.suprafata()); } } ]n exemplul de mai sus sunt definite trei clase: dreptunghi, patrat ~i testpatrat. Clasa patrat extinde clasa dreptunghi care se nume~te superclas{ a clasei patrat. Elementele clasei dreptunghi sunt: c|mpurile lungime ~i latime care definesc starea unei instan#e particulare a clasei ~i metodele: perimetrul() ~i suprafata(). Identificatorul x se refer{ la o instan#{ a clasei patrat, c|nd este declarat prin patrat x; ~i este efectiv un obiect c|nd este creat dinamic folosind operatorul new: patrat x; x = new patrat(10); sau patrat x = new patrat(10); Deoarece clasa patrat extinde clasa dreptunghi, x este un obiect compatibil cu clasa dreptunghi, el se refera la un dreptunghi particular. Are sens s{ acces{m datele obiectului x prin x.lungime, respectiv prin x.latime. Sunt definite metodele dreptunghi ~i patrat, identificatorii fiind identici cu numele clasei pentru care o metod{ este definit{. Aceste metode se numesc constructori. Constructorii sunt apela#i la crearea unui obiect (observa#i apelurile precedate de new) ~i returneaz{ un obiect (o instan#{) apar#in|nd clasei corespunz{toare. Trebuie spus c{ nu trebuie utilizat{ instruc#iunea return }n corpul unui constructor ~i nici cuv|ntul void }n antetul constructorului. Obiectul this desemneaz{ obiectul curent. La apelul x.latura() se returneaz{ valoarea stocat{ }n c|mpul latime al obiectului. O alt{ utilizare a cuv|ntului cheie this este exemplificat{ prin: public class Cerc{ public double xc,yc,r; // centrul(xc,yc) si raza r //urmeaza mai multi constructori public Cerc(double x, double y, double r) { xc=x; yc=y; this.r = r; } public Cerc(double r){ xc=0.0; yc=0.0; this.r=r;} public Cerc(Cerc a){ xc=a.xc; yc=a.yc; r=a.r;} public Cerc(){xc=0.0; yc=0.0; r=1.0;}

// metode specifice comportamentului public double lungimea(){return 2*3.14159*r:} public double suprafata(){return 3.14159*r*r;} } Dup{ cum se vede }n acest exemplu, o clas{ poate avea mai mul#i constructori. Definirea mai multor metode cu acela~i nume, dar cu argumente sau tipuri diferite se nume~te supra}nc{rcarea metodelor. Totu~i, cuv|ntul this poate fi utilizat ~i cu alt }n#eles. ]n exemplul care urmeaz{, construc#ia this() apare numai ca prima instruc#iune }n corpul unui constructor ~i desemneaz{ apelul constructorului clasei }n care apare. Se consider{ clasa Cerc definit{ mai sus ~i se descriu c|#iva constructori: public Cerc (double xc, double yc, double r){ //prima forma a lui this this.xc=xc; this.yc=yc; this.r=r; } public Cerc (double r){this(0.0, 0.0, r);}//a doua forma public Cerc (Cerc a){this(a.xc, a.yc, a.r);} public Cerc (){this(0.0, 0.0, 1.0);} S{ observ{m variabilele xc, yc ~i r care descriu starea oric{rei instan#e a clasei Cerc. Orice obiect va avea starea sa stocat{ }n aceste c|mpuri (fiecare obiect va avea o copie a variabilelor xc, yc, r). Astfel de variabile se numesc variabile instan#{. Observa#i c{ declara#ia acestora este precedat{ de cuv|ntul cheie public. De~i variabilele lungime ~i latime din primul exemplu, nu sunt precedate de public ele tot variabile instan#{ sunt. Exist{ ~i variabile specifice clasei. Acestea sunt globale tuturor instan#elor. Ele sunt precedate de cuv|ntul cheie static. Vom exemplifica, redefinind clasa Cerc astfel }nc|t s{ avem un indicator al num{rului de obiecte create. public class Cerc{ static int contor_cerc = 0; public static final double PI=3.14159265358979323846; public double xc,yc,r; public Cerc(double xc, double yc, double r){ this.xc=xc; this.yc=yc; this.r=r; contor_cerc ++;} public Cerc(double r){this(0.0, 0.0, r);} public Cerc(Cerc a){this(a.xc, a.yc, a.r);} public Cerc(){this(0.0, 0.0, 1.0);} public double lungimea(){return 2*Cerc.PI*r;} public double suprafata(){return Cerc.PI*r*r;} } public class TestMain { // Metoda main public static void main(String[] args){ Cerc c1= new Cerc(); Cerc c2= new Cerc(3.0, 3.0, 10.0); Cerc c3= new Cerc(c1); c3.r = 10; System.out.println(Au fost create + Cerc.contor_cerc+ cercuri.);} }

Deoarece variabilele statice sunt asociate clasei ~i nu obiectelor, aceste variabile sunt accesate prin intermediul identificatorului clasei: Cerc.contor_cerc. S{ observ{m prezen#a cuv|ntului cheie final care introduce o constant{ a clasei. Aceast{ definire elimin{ posibilitatea de a modifica PI prin instruc#iuni de atribuire: Cerc.PI=2;. Urm{rind exemplele de mai sus observ{m c{ declararea unei clase con#ine cuv|ntul cheie class ~i identificatorul clasei.

1.3. Class (sintaxa)


Sintaxa pentru declararea unei clase este: [mod_utilizare] class Nume_Clasa [extends Nume_Super_Clasa] [implement Nume_Interfata]{ //Declararea variabilelor //Declararea metodelor } unde: mod_utilizare precizeaz{ modul }n care poate fi utilizat{ clasa declarat{. Dac{ mod_utilizare este public atunci se declar{ o clas{ care poate fi apelabil{ de oriunde. Dac{ mod_utilizare lipse~te clasa poate fi apelabil{ numai de clasele din acela~i pachet cu ea. Dac{ mod_utilizare este abstract se declar{ o clas{ care nu poate fi instan#iat{ (o clas{ abstract{). Cuv|ntul final se utilizeaz{ pentru declararea acelor clase care nu se mai extind (clase finale). class Nume_Clasa specific{ identificatorul clasei; extends Nume_Super_Clasa este o construc#ie care indic{ superclasa c{reia }i apar#ine clasa definit{. ]n limbajul Java, orice clas{ are o superclas{. Pentru clasele care nu au specificat{ superclasa, ele sunt clase ce extind clasa Object. implement Nume_Interfata se utilizeaz{ pentru a descrie interfe#ele implementate de aceast{ clas{. Odat{ declarat{ clasa urmeaz{ }ntre acoladele { ~i }, corpul clasei. Acesta con#ine codul prin care se }ntre#ine ciclul de via#{ al obiectelor create: starea clasei, starea obiectelor, comportamentul clasei, comportamentul obiectelor, constructorii, finalizatorii etc. Variabilele ~i metodele structurii sunt numite membrii.

1.4. Variabila membru


Starea clasei ~i a obiectelor clasei este stocat{ }n variabilele membre. Variabilele declarate }n corpul metodelor sunt locale acestora, ele nu descriu

starea clasei sau a obiectelor. Formatul general pentru declararea unei variabile membru este: [mod_acces] [static][final][transient][volatile] tip Nume_Variabila; unde: mod_acces determin{ clasele care au acces la o variabil{ membru. Pentru a specifica modul de acces se utilizeaz{ unul dintre cuvintele rezervate: public, protected, package sau private. static - indic{ o variabil{ a clasei ~i nu o variabil{ instan#{. O modificare asupra variabilei face ca variabila s{ aib{ aceea~i valoare pentru toate instan#ele clasei (vezi variabila contor_cerc). final - define~te o constant{ care se ini#ializeaz{ }n declararea sa (vezi declararea constantei PI). transient indic{ faptul c{ variabila nu este o component{ a st{rii persistente a obiectului, iar volatile indic{ posibilitatea modific{rii variabilei din motive de optimizare. tip - indic{ tipul variabilei: byte (}ntreg pe 8 bi#i, cod direct), short (}ntreg pe 16 bi#i, complement fa#{ de doi), int (}ntreg pe 32 de bi#i, complement fa#{ de doi), long (}ntreg pe 64 de bi#i, complement fa#{ de doi), float (reprezentare IEEE754 pe 32 de bi#i), double (reprezentare IEEE 754 pe 64 de bi#i), char (caracter Unicode, pe 16 bi#i), boolean (valoare boolean{ (true sau false) pe 1 bit), tablou (declarare ca }n C, cu alocarea spa#iului folosind new), clas{ (class ca mai sus) sau interfa#{. Nume_Variabila - desemneaz{ identificatorul variabilei. ]ntr-o clas{ nu pot fi declarate mai multe variabile cu acela~i nume, dar o variabil{ membru ~i o metod{ pot avea acela~i nume.

1.5. Metodele unei clase


Metodele unei clase se execut{ preciz|nd obiectul pe care se aplic{ (exemplu: p1.latura). Ele sunt definite }n corpul clasei prin specificarea p{r#ii declarative ~i a corpului: Parte_declarativa { corp }. Corpul metodei con#ine variabilele locale ~i instruc#iunile Java care se vor executa la apelul metodei. Parte_declarativa con#ine informa#ii necesare compilatorului, platformei pe care se execut{, precum ~i altor clase sau obiecte. Partea declarativ{ are urm{toarea sintax{ general{: [Mod_Acces] [static] [abstract] [final] [native] [syncronized] Tip_Rezultat Nume_Metoda ([lista_parametri]) [throws lista_exceptii] unde:

Mod_Acces - indic{ modul de acces al altor clase la metod{. Accesul se specific{ prin utilizarea unuia dintre cuvintele cheie: public, protected, package sau private. static - indic{ o metod{ a clasei, nu o metod{ a instan#elor. ]n pachetul java.lang este definit{ clasa Math care introduce constantele matematice E ~i PI, ~i define~te metodele statice pentru calcul trigonometric, exponen#ial, logaritmic, ~i alte func#ii precum }n fi~ierul antet math.h din C. Exemplific{m descriind o metod{ care verific{ dac{ un punct este }n interiorul unui cerc: public class Cerc{ private double xc, yc, r; // constructori // alte metode public double interior(double x, double y){ double dx = x - xc; double dy = y - yc; double dist = Math.sqrt(dx*dx+dy*dy); if (dist<r) return true; else return false; } //alte metode } abstract - indic{ o metod{ abstract{ care nu are implementare; ea trebuie s{ apar#in{ unei clase abstracte. O clas{ abstract{ A poate avea subclase, aceastea sunt r{spunz{toare de implementarea metodelor definite ca abstracte }n A. ]n acest fel, o clas{ abstract{ poate fi utilizat{ pentru a defini o interfa#{ de programare complet{ (programming interface). Sintaxa unei clase abstracte este: abstract class Nume_Clasa_A { tip_1 nume_Var_1; tip_2 nume_Var_2; ........ tip_Rezultat_1 nume_Metoda_1(){ corp implementat} ........ abstract tip_Rezultat_n nume_Metoda_n(); //metoda abstracta ........ } Metoda nume_Metoda_n() va fi implementat{ diferit }n sublasele derivate din Nume_Clasa_A: class Nume_Clasa_B extends Nume_Clasa_A { ........ tip_Rezultat_n nume_Metoda_n() { corp implementat } ........} class Nume_Clasa_C extends Nume_Clasa_A { ........ tip_Rezultat_n nume_Metoda_n(){ corp implementat } ........

} final - indic{ o metod{ care nu va putea fi rescris{ }n clasele extinse (numite subclase sau clase derivate). Toate metodele declarate static ca ~i cele declarate final precum ~i toate metodele unei clase declarate cu final sunt implicit finale. native - indic{ implementarea metodei }ntr-un alt limbaj de programare (de exemplu C, C++ etc.) syncronized - indic{ posibilitatea ca metoda s{ fie utilizat{ concuren#ial. Procesele care se execut{ }n mod concurent apeleaz{ deseori metode ce opereaz{ cu acelea~i date. Aceste metode trebuie declarate syncronized pentru a asigura accesul exclusiv la informa#ie (o modalitate pentru a rezolva problema excluderii mutuale }n sisteme concurente). Tip_Rezultat - indic{ tipul datei returnate de metod{. Valoarea de retur poate fi de tip numeric (}ntregi, IEEE754, caracter, logic), structurat (tablou, clasa sau interfata) sau descris{ prin void, prin care se specific{ inexisten#a unei valori de retur. Nu este definit un tip de retur implicit ca }n alte limbaje de programare. nume_Metoda - este identificatorul metodei. Mai multe metode pot avea acela~i identificator (supra}nc{rcarea metodelor), }n acest caz este necesar ca metodele s{ difere prin num{rul parametrilor, tipul parametrilor sau tipul rezultatului returnat. ]ntr-o clas{ derivat{ (subclas{) poate fi rescris{ o metod{ a superclasei. Metoda rescris{ va avea acela~i nume, tip de retur ~i list{ a parametrilor cu metoda superclasei. Trebuie diferen#iat }ntre supra}nc{rcare (overloading) ~i rescriere (overridden). lista_parametri - descrie tipul ~i identificatorul argumentelor transmise metodei. throws lista exceptii - con#ine lista metodelor ce vor fi apelate }n cazul apari#iei unor erori (excep#ii).

1.6. Metoda main


Orice aplica#ie trebuie s{ con#in{ metoda main (a se vedea primul exemplu). Aceast{ metod{ controleaz{ executarea unui program, este responsabil{ cu alocarea resurselor necesare ~i apelul altor metode. Metoda main este de tip public (poate fi apelata de orice obiect), este o metod{ a clase aplica#ie (specificatorul static) ~i nu }ntoarce vreun rezultat. Metoda main este con#inut{ de prima clas{ care este apelat{ de interpretorul java ~i accept{ un singur argument - un tablou cu elemente de tip String - prin care sistemul de operare transmite informa#ii c{tre aplica#ie. Fiecare element al

tabloului con#ine un argument din linia de comand{. Declara#ia metodei main se realizeaz{ prin: public static void main (String[] argumente){ ... } Reutilizarea unei clase existente ~i extinderea claselor care nu sunt finale, at|t structural c|t ~i comportamental, se realizeaz{ prin intermediul mecanismului de mo~tenire. Rela#ia de extindere }ntre clase eviden#iaz{ dou{ categorii de clase: superclasa - o clas{ care face obiectul extinderii; subclasa - clasa extins{. Subclasele mo~tenesc toate caracteristicile superclasei prin variabilele ~i metodele acesteia, dar pot avea ~i caracteristici proprii. Elementele mo~tenite pot fi utilizate a~a cum sunt sau pot fi redefinite }n subclas{. Pentru a accesa variabila superclasei }n una dintre metodele subclasei se specific{ numele superclasei sau se utilizeaz{ nota#ia: super.NumeVariabila Exemplu: class A { int a = 1; void m1() {System.out.println(a);} } class B extends A { double a = Math.PI; // variabila redefinita void m1() {System.out.println(a);} // metoda redefinita void m2() {System.out.println(A.a);} void m3() {m1(); super.m1();} } public class TEST{ public static void main(String [ ] arg){ A obA = new A(); B obB = new B(); obA.m1(); // tipareste numarul 1 obB.m1(); // tipareste constanta PI obB.m2(); //tipareste numarul 1 obB.m3(); //tipareste: 1 (pe primul rand) si PI (pe al doilea rand.) A obC = (A)obB; //obiectul obC este obB ca apartinand superclasei System.out.println(obc.a); // tipareste valoarea 1 obC.m1(); // se refera la obB si va tipari constanta PI. }} Metodele redefinite sunt tratate diferit de variabilele redefinite atunci c|nd se folose~te operatorul cast pentru conversie (a se vedea obC.m1() in exemplul de mai sus), altfel pentru ambele tipuri de entit{#i se utilizeaz{ cuv|ntul super. Exemplu: class C1 {

double x = 2.73; double f() {return x;} } class C2 extends C1 { double x; double f() { x = Math.cos(super.x)/Math.exp(super.x); return x+super.f()*Math.atan(Math.sqrt(3)); } } Pentru referirea unei variabile a superclasei C1 redefinit{ }n clasa C2, }n loc de a utiliza super, putem folosi ~i conversia cast la tipul C1 a obiectului this: ((C1)this).x. Metodele redefinite nu pot fi apelate prin conversie, trebuie utilizat cuv|ntul super.

1.7. Motenire multipl


Alte limbaje de programare orientate obiect permit mo~teniri multiple }n ierarhia claselor. ]n limbajul Java, o clas{ Java poate avea numai o superclas{ ~i poate implementa una sau mai multe interfe#e. Interfa#a reprezint{ o specificare formal{ a unei clase, }n care se declar{ un set de valori constante ~i metode. Se disting dou{ componente ale unei interfe#e: declararea interfe#ei ~i corpul interfe#ei. Declararea interfe#ei necesit{ utilizarea cuv|ntului cheie interface ca }n specificarea: [public] interface NumeInterfata [extends SuperInterfata1 [, SuperInterfata2] ...] unde: prezen#a cuv|ntului public indic{ posibilitatea utiliz{rii interfe#ei de c{tre orice clas{ din orice pachet, iar absen#a sa precizeaz{ posibilitatea utiliz{rii interfe#ei numai de c{tre clasele definite }n acela~i pachet cu interfa#a; NumeInterfata este un identificator Java care specific{ numele interfe#ei; extends este clauza prin care se declar{ o interfa#{ ca extensie a uneia sau mai multor interfe#e, interfa#a mo~tenind toate valorile constante ~i metodele superinterfe#ei (superinterfe#elor). Corpul interfe#ei con#ine declararea constantelor ~i metodelor interfe#ei. Toate valorile constante definite }n interfa#a sunt }n mod implicit din categoria entit{#ilor declarate folosind cuvintele: public, static ~i final. Tot }n mod implicit, specificatorii public ~i abstract sunt asocia#i metodelor declarate }n interfa#{. Cu alte cuvinte: orice metod{ a unei

interfe#e poate fi implementat{ de orice clas{ ~i este o metod{ abstract{. Deci, nici una dintre metodele declarate nu este ~i implementat{. Reamintim, existen#a }n Java a claselor abstracte. O clas{ abstract{ poate avea o subclas{ (poate fi extins{) dar nu poate fi instan#iat{. Printr-o clas{ abstract{ sunt prezentate variabilele ~i metodele ce pot fi partajate de toate subclasele. O subclas{ a unei clase abstracte poate fi instan#iat{ numai dac{ redefine~te ~i implementeaz{ fiecare din metodele abstracte ale superclasei. Dac{ o subclas{ a unei clase abstracte nu implementeaz{ toate metodele abstracte mo~tenite, atunci aceast{ clas{ este tot una abstract{. Exemplu: public abstract class FiguriGeometrice { public abstract double suprafata(); public abstract double perimetru(); } public class Dreptunghi extends FiguriGeometrice { protected double l, L; public Dreptunghi(){l=0.0; L=0.0;} public Dreptunghi(double l; double L) { this.l=l; this.l=L; } public double suprafata(){return l*L;} public double perimetru(){return 2*(l+L);} public double lungime(){return L;} public double latime(){return l;} } public class Cerc extends FiguriGeometrice { protected double r; public Cerc(){r=1.0;} public Cerc(double r){this.r = r;} public double suprafata(){return Math.PI*r*r;} public double perimetru(){return 2*Math.PI*r;} public double raza(){return r;} } Trebuie re#inut c{ o clas{ abstract{ poate avea ~i metode non-abstract, dar toate metodele unei interfe#e sunt declarate abstract.

1.8. Pachete
Realizarea modular{ a unei aplica#ii Java este permis{ prin intermediul conceptului de pachet (package). Codul surs{ al unei clase Java reprezint{ unitatea de compilare. O unitate de compilare, }n mod normal, con#ine definirea unei singure clase. Pentru aplica#iile complexe, clasele pot fi grupate }n pachete. Un pachet este declarat prin specificarea }n prima linie a fi~ierului surs{ a declara#iei:

package NumePachet; dup{ care urmeaz{ clasele ~i interfe#ele. Pachetele pot fi ~i acestea organizate ierarhic, dar o clas{ nu poate apar#ine la mai multe pachete. Dac{ }ntr-un fi~ier surs{ nu este utilizat{ instruc#iunea package, atunci clasele definite apar#in unui pachet anonim ~i nu vor putea fi importate de nici un alt pachet. Specificarea importului de clase se poate realiza }n unul din urm{toarele moduri: import pachet1.pachet2. ..., pachetn - utilizarea oric{rei clase, dar ca prefix; import pachet1.pachet2. ..., pachetn.clasa - pentru importarea unei clase; import pachet1.pachet2. ..., pachetn.* - pentru importarea tuturor claselor; O clas{ poate fi utilizat{ ~i prin specificarea complet{ a numelui. Exemple: a) specificarea complet{ a numelui - nu se folose~te instruc#iunea import. class Test1 { public static void main(String [ ] args){ int xp, yp; int[] x = {10, 20, 30, 40, 50}; int[] y = {10, 5, 0, 20, 40}; java.awt.Polygon p = new java.awt.Polygon(x, y, 5); java.awt.Point q = new java.awt.Point(10, 10); xp=q.x; yp=q.y; System.out.println(q.toString());//p.toString() eronat System.out.println(x = + xp + y = + yp); p.addPoint(xp,yp); System.out.println(numarul de puncte este: + p.npoints); } } b) utilizarea numelui clasei ca prefix import java.awt; class Test2 { public static void main(String [ ] args){ int dx, dy; awt.Point p = awt.Point(10,10); awt.Point q = awt.Point(10,30); dx = q.x -p.x; dy = q.y -p.y; System.out.println(Dist= +Math.sqrt(dx*dx+dy*dy)); } }

c) importarea unei singure clase import java.awt.Polygon; import java.awt.Point; class Test3 { public static void main(String [ ] args){ int xq=20, yq=30; int[] x = {10, 20, 30, 40, 10}; int[] y = {10, 5, 0, 20, 10}; Polygon p = new Polygon(x, y, 5); Point q = new Point(xq, yq); System.out.println(q.toString()); System.out.println(x = + xq + y = + yq); System.out.println(Q este in interior? +p.inside(xq,yq)); } } d) importul tuturor claselor pachetului import java.io.*; // Tip{rirea liniilor unui fi~ier care con#in un anumit sub~ir // Sub~irul ~i numele fi~ierului se introduc }n linia de comand{ public class Test4 { public static void main(String [ ] args){ if((args.length == 0) || (args.length > 2) ) { System.out.println( Apel: java Test4 subsir [fisier]); System.exit(0); } try { DataInputStream fin; if (args.length == 2) fin = new DataInputStream(new FileInputStream(args[1])); else fin = new DataInputStream(System.in); GrepInputStream g = new GrepInputStream(fin, args[0]); String linie; for (; ; ) { linie = g.readLine(); if (linie == null) break; System.out.println(linie); } g.close(); }catch (IOException e) System.err.println(e); } } Prin acest exemplu, arat{m c{ limbajul Java permite ~i lucrul cu fi~iere. Prezentarea pachetelor Java nu face obiectul acestei lucr{ri. Enun#{m totu~i numele ~i rolul pachetelor Java: java.applet - constituit din 3 clase ~i o interfa#{ este utilizat }n realizarea unui aplet;

java. lang - gestioneaz{ tipurile ~i elementele de baz{ ale limbajului Java. Clasa r{d{cin{ este Object, din care deriv{ clase precum: 1. clase finale: Boolean, Character, Math, String, StringBuffer; 2. clase abstracte: ClassLoader, Number cu subclasele finale (Double, Float, Integer, Long), Process, SecurityManager; 3. clase f{r{ instan#iere: Class, Compiler, Runtime, System 4. clase pentru tratarea erorilor, excep#iilor ~i pentru modelarea accesului concuren#ial. java.io - include clase pentru gestiunea fluxurilor de intrare/ie~ire (fi~iere). java.util - gestioneaz{ diverse structuri de date ~i include clase utilitare precum: Vector, Hashtable, BitSet, Date, Random etc. java.awt - ofer{ o colec#ie de clase pentru realizarea interfe#elor grafice }n Java. Acestea asigur{ crearea ~i afi~area ferestrelor, utilizarea imaginilor ~i a componentelor precum: butoane, bare de derulare, bare de meniuri, zone pentru introducerea textelor etc. Aplica#iile Java realizate cu AWT (Abstract Window Toolkit) pot lucra }n acela~i mod pe toate platformele. java.net - pentru gestionarea comunic{rii }n re#ea. Pentru eliminarea obiectelor create ~i de care nu mai este nevoie, se ocup{ interpretorul Java care dispune de un colector al obiectelor inutile (garbage colector). Totu~i, acesta poate fi informat de programator c{ un anumit obiect nu mai este necesar, pentru a urgenta eliminarea acestuia din memoria intern{.

1.9 EXEMPLE
]n continuare vom prezenta c|teva aplica#ii Java care s{ eviden#ieze modul de realizare a programelor Java. Nu vom ilustra modul de realizare a applet-urilor Java ~i nici tehnicile de programare concurent{; pentru acestea cititorul poate consulta literatura specific{. Exemplul 1. (Tablouri }n Java - metoda quick-sort). Principiul ~i complexitatea algoritmului Quick Sort au fost prezentate anterior. Aici prezent{m implementarea }n Java a unei clase adecvate ~i modul de utilizare al acesteia. Se vor ilustra c|t mai multe dintre structurile de control ale limbajului si tehnica program{rii recursive }n Java. Datele de test vor fi numere pseudo-aleatoare. class TablouQs {

private double [] Tablou; private int nrelem; private int dim; public TablouQs (int dim){ Tablou = new double[dim]; nrelem = 0; this.dim=dim; } public void Insert(double x){ if (nrelem < dim) { Tablou[nrelem] = x; nrelem++; } else System.out.println(Nu pot insera!); } public void Afisare(){ System.out.println(Elementele tabloului sunt:); for (int i=0; i<nrelem; i++) System.out.print(Tablou[i]+ ); System.out.println(); } public void Quicksort(int l, int r){ // Algoritmul este de tip Divide et Impera if (r-l+1 <= 3) Sortdirect(l,r); // Sortare directa (dimensiune mica) else { int m=(l+r)/2; //divizare double t=tablou[m]; int k = Partitionare(l,r,t); // pozitionarea pivotului t la locul lui Quicksort(l,k-1); // sortarea elementelor din stanga Quicksort(k+1,l); // sortarea elementelor din dreapta } } public int Partitionare(int l, int r, double t){ int lp=l-1; int rp=r; while (true) { while (Tablou[++lp]<t); while (rp>0 && Tablou[-rp]>t); if (lp=rp) break; else eXch(lp,rp); } eXch(lp,r); return lp; } public void eXch(int p1, int p2){ double t = Tablou[p1]; Tablou[p1]=Tablou[p2]; Tablou[p2]=t; } public void Sortdir(int l, int r){ int s=r-l+1; switch(s) {

case 1: case 2: default: }

return; if (Tablou[l]>Tablou[r]) eXch(l,r);return; if (Tablou[l]>Tablou[r-1]) eXch(l, r-1); if (Tablou[l]>Tablou[r]) eXch(l,r); if (Tablou[r-1]>Tablou[r]) eXch(r-1,r);

} public Sort(){ Quicksort(0, nrelem-1);} } // sf. clasei QsTablou; class Qs { public static void main(String[] args){ int dim = 64; TablouQs x; x = new TablouQs(dim); for (int i = 0; i<dim; i++) { double t = (int) (java.lang.Math.random()*99); x.Insert(t); } x.Afisare(); x.Sort(); x.Afisare(); } } // sf. clasei principale care utilizeaza obiectele supuse sortarii.

Exemplul 2. (Implementarea unei stive folosind liste simplu }nl{n#uite). Tipurile referin#{ sunt folosite pentru a referi un obiect din interiorul unui alt obiect. Prin aceasta se pot }nl{n#ui informa#iile aflate }n memorie. Valoarea implicit{ care este atribuit{ automat oric{rei variabile de tip referin#{ care nu a fost ini#ializat{ este null. Ca ~i }n alte limbaje de programare, simpla declara#ie a unei referin#e nu duce automat la rezervarea spa#iului de memorie pentru obiectul referit. Pentru rezervare se folose~te o expresie de alocare care folose~te cuv|ntul rezervat new. ]n exemplele anterioare au fost declarate ~i folosite diferite obiecte, inclusiv referin#e c{tre tablouri. Acest exemplu ilustreaz{ }nl{n#uirea obiectelor }ntr-o list{ ~i prelucrarea listei conform disciplinei LIFO (Last In First Out). import java.io.*; class Nod { public String info; public Nod leg; public Nod(String x){ info = x; } public Afisare(){ System.out.println(info+ ); } } class Lista { // se defineste lista inlantuita private Nod capLista; public Lista(){ capLista = null; }

public boolean ListaVida() { return (capLista == null); } public void InsertStart(String x) { Nod q = new Nod(x); q.leg = capLista; capLista = q; } public String StergPrimul(){ Nod t = capLista; capLista = capLista.leg; return t.info; } public void Afisare() { Nod c = capLista; while (c != null) { c.Afisare(); c = c.leg; } System.out.println( ); }} class Stiva { private Lista s; public Stiva(){ s = new Lista(); } public Insert(String x) { s.InsertStart(x); } public String Extrage(){ return s.StergPrimul();} public boolean StivaVida(){ return s.ListaVida();} public void Afisare(){ System.out.println(Stiva de la varf la baza este:); s.Afisare(); } } // Demonstratie: crearea unei liste cu siruri de caractere si afisarea // acestora in oridine inversa introducerii. class aplicatie { public static void main(String [] args) throws IOException { String inp; Stiva s = new Stiva(); System.out.println(Introduceti elementele listei:); System.out.flush(); while (true) { inp= getString(); if (inp.equals()) break; s.Insert(inp); } System.out.println(Elementele introduse sunt:); System.out.flush(); s.Afisare(); } public static String getString() throws IOException { InputStreamReader isr = new InputStreamReader(System.in); BufferedReader br = new BufferedReader (isr); String s = br.readLine(); return s; } } // sfarsitul aplicatiei

Exemplul 3. (Arbori binari, reprezentare }nl{n#uit{, opera#ii de baz{: c{utare, inserare, ~tergere, parcurgeri). Acest exemplu reia principalele aspecte legate de prelucrarea arborilor binari (defini#ia de baz{) ~i ilustreaz{ structura clasic{ a programelor Java. import java.io.*; import java.lang.Integer; class Nod { public int cheie; public String altceva; public Nod fiust; public Nod fiudr; public void AfisareNod(){ System.out.print((); // afisarea unui caracter System.out.print(cheie); System.out.print( , ); // afisarea unui sir de caractere System.out.print() ); // afisare unui sir } } class ArboreBinar { private Nod radacina; public ArboreBinar(){ radacina = null; } public Nod Cauta(int x) { Nod c = radacina; if (c == null) return null; while (c.cheie != x) { if (x < c.cheie) c = c.fiust; else c = c.fiudr; if (c == null) break; } return c; } public void Insert(int ch, String st) { Nod q = new Nod(); q.cheie = ch; q.altceva = st; if (radacina == null) radacina = q; else { Nod c = radacina; Nod tata; while (true) { tata = c; if (ch < c.cheie) { c = c.fiust; if (c == null) { tata.fiust = q; return; } } else { c = c.fiud; if (c == null) {tata.fiudr = q; return; } }

} // sfarsit while } } public boolean Elimina(int ch) { // sterge nodul cu cheia ch Nod c = radacina; Nod tata = radacina; boolean st = true; if (c== null) return false; while (c.cheie != ch) { tata = c; if (ch < c.cheie) { st = true; c = c.fiust; } else { st = false; c = c.fiudr; } if (c == null) return null; } // nodul c trebuie sters; nodul tata este ascendentul lui c // cazul 1: Are c fii? if (c.fiust == null && c.fiudr == null) { if (c == radacina) radacina = null; else if (st) tata.fiust = null; else tata.fiudr = null; } else //Cazul 2: Nu are fiudr. Vom inlocui cu subarborele stang if (c.fiudr == null) if (c == radacina) radacina = c.fiust; else if (st) tata.fiust = c. fiust; else tata.fiudr = c.fiust; else // Cazul 3: Nu are fiust. Vom inlocui cu subarborele drept if (c.fiust == null) if (c == radacina) radacina = c.fiudr; else if (st) tata.fiust = c.fiudr; else tata.fiudr = c.fiudr; else { // are doi fii. Vom inlocui cu succesorul in traversarea inordine Nod succesor = ObtineSuccesorInordine(c); if (c == radacina) radacina = succesor; else if (st) tata.fiust = c.fiudr; else tata.fiudr = c.fiudr; succesor.fiust = c.fiust; } return true; } private Nod ObtineSuccesorInordine(Nod p) { Nod succesor = p; Nod c = p.fiudr; // treci la fiul din dreapta while (c != null) { // avans pe stanga cat se poate succesor = c; c = c.fiust; } return succesor; } public void Parcurgere(int tip) { switch (tip) { case 1: System.out.print(\n Preordine: ); preordine(radacina); break; case 2:System.out.print(\n inordine: ); inordine(radacina);

break; default:System.out.print(\n postordine: ); postordine(radacina); break; } System.out.println(); } private void preordine(Nod p) { if (p != null) { p.AfisareNod(); preordine(p.fiust); preordine(p.fiudr); } } private void inordine(Nod p) { if (p != null) { inordine(p.fiust); p.AfisareNod(); inordine(p.fiudr); } } private void postordine(Nod p) { if (p != null) { postordine(p.fiust); postordine(p.fiudr); p.AfisareNod(); } } } // terminat definirea clasei ArboreBinar. class aplicatie { public static void main(String[] args) throws IOException { int n, ch; String alt; ArboreBinar arb = new ArboreBinar(); // crearea arborelui : se introduc n perechi, n se citeste. System.out.print(Numarul nodurilor:); System.out.flush(); n=getInt(); for (int k=1; k<=n; k++) { ch = getInt(); alt = getString(); arb.Insert(ch,alt); } while (true){ putString(Introduceti:\n); putString( I - inserare\n); putString( C - cautare\n); putString( S - stergere\n); putString( P - parcurgere\n); int optiune = getchar(); switch(optiune){ case I: case i: putString(Cheia:); ch=getInt(); putString(Restul:); alt = getString();

arb.Insert(ch,alt); break; case C: case c: putString(Cheia de cautat:); ch = getInt(); Nod gasit = arb.Cauta(ch); if (gasit != null) { putString(Am gasit: ); gasit.AfisareNod(); putString(\n); } else putString(Cheia +ch+ nu este in arbore.); break; case D: case d: putString(Cheia de sters:); ch = getInt(); boolean reusit = arb.Stergere(ch); if (reusit) putString(Am sters !\n); else { putString(Cheia nu este in arbore); putString( sau arborele este vid\n); } break; case P: case p: putString(Introduceti 1-pre, 2-in, 3-post (ordine) :); ch = getInt(); arb.Parcurgere(ch); break; default: putString(Optiune eronata!); } } } public static void putString(String s) { System.out.print(s); System.out.flush(); } public static String getString() throws IOException{ InputStreamReader inputStream = new InputStreamReader(System.in); BufferedReader buffer = new BufferedReader(inputStream); String sir = bufferr.readLine(); return sir; } public static char getchar() throws IOException{ String sir=getString(); return sir.charAt(0); } public static int getInt() throws IOException { String sir = getString(); return Integer.parseInt();

} } // terminat aplicatia

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