Sunteți pe pagina 1din 21

C11: Java P2 Utilizarea claselor si obiectelor in Java

Cuprins:

Introducere; Crearea obiectelor; Variabile asociate clasei; Metode asociate clasei; Distrugerea obiectelor.

C11: Java P2

1. Introducere :

O clasa este o colectie de date si metode care opereaza asupra acelor date. Datele si metodele servesc la definirea proprietatilor unor obiecte. Sa consideram exemplul unui cerc, pe care il putem defini prin pozitia (x,y) a centrului si raza. Prevedem metode de calcul pentru perimetru si arie. public class Circle { public double x, y, r; public double circumference() { return 2.0 * 3.14159 * r; } public double area() { return 3.14159 * r * r; } }

//Definind clasa Circle, am creat un nou tip de date. // Putem declara variabile de acest tip prin: Circle c; c = new Circle();

//Accesul la datele si metodele obiectului se face prin sintaxa cunoscuta de la C: Circle c = new Circle(); c.x = 2.0; c.y = 1.0; c.r = 3.0; double a; 2 a = c.area();

C11: Java P2
Toate metodele (nestatice) primesc ca parametru "invizibil" o variabila referinta numita this (referinta catre obiectul curent). Metoda area ar fi putut fi scrisa si astfel: public double area() { return 3.14159 * this.r * this.r; }

C11: Java P2
Crearea obiectului c prin: c = new Circle();

2. Crearea obiectelor :

Se sugereaza un apel de metoda constructor.

Orice clasa Java are cel putin o metoda constructor, chiar daca utilizatorul nu defineste nici una.

Constructorul predefinit nu are argumente si nu face nici o initializare.

Invocarea lui new creeaza dinamic un obiect de tip specificat (Circle). Apoi, se apeleaza metoda constructor, careia i se transmite tacit referinta this catre noul obiect creat si eventualii parametri specificati la apelul constructorului.

Putem defini constructori (chiar mai multi). Ei sunt metode fara tip (nici macar void) si au acelasi nume cu clasa. De fapt, constructotul intoarce o instanta a clasei (prin referinta this), desi in textul sursa nu trebuie sa apara vreo instructiune return.
4

C11: Java P2

Exemplu:

public class Circle { public double x, y, r; public Circle (double x, double y, double r) { this.x = x; this.y = y; this.r = r; } public Circle (double r) { this.x = 0.0; this.y = 0.0; this.r = r; } public Circle (Circle c) { this.x = c.x; this.y = c.y; this.r = c.r; } public Circle () { this.x = 0.0; this.y = 0.0; this.r = 1.0; } public double circumference() { return 2.0 * 3.14159 * r; } public double area() { return 3.14159 * r * r; } }

C11: Java P2

Existenta mai multor metode cu acelasi nume in aceeasi clasa este o proprietate generala a limbajului Java si se numeste "supraincarcarea metodelor". Diferentierea dintre metode se face prin tipul si lista lor de parametri (la constructori, numai prin lista).

Supraincarcarea metodelor (method oveloading - metode diferite cu acelasi nume dar cu tip si lista de argumente diferite) nu trebuie confundata cu supradefinirea metodelor (method overriding - metode cu aceleasi nume, tip si lista de argumente, care apar in clase derivate).

Cuvintul-cheie this poate fi folosit in situatia in care o clasa are mai multi constructori si un constructor apeleaza un alt constructor explicit. Constructorii de mai sus ar putea fi scrisi astfel: public Circle (double x, double y, double r) { this.x = x; this.y = y; this.r = r; } public Circle (double r) { this(0.0, 0.0, r); } public Circle (Circle c) { this(c.x, c.y, c.r); } public Circle () { this(0.0, 0.0, 1.0); }
6

C11: Java P2

3. Variabile asociate claselor :

Variabilele clasei Circle (x, y, si r) apar in fiecare instanta a clasei. De aceea se mai numesc si variabile instanta. Sunt situatii in care dorim ca pentru o variabila sa existe o singura copie, caz in care definim variabila cu atributul static. Asemenea variabile se mai numesc si variabile ale clasei sau variabile statice.

Sa presupunem ca dorim sa stim cite obiecte de tip Circle exista la un moment dat:

public class Circle { public double x, y, r; // var. instanta public static int num_circles = 0; // var. statica public Circle (double x, double y, double r) { this.x = x; this.y = y; this.r = r; num_circles++;} public Circle (double r) { this(0.0, 0.0, r); } public Circle (Circle c) { this(c.x, c.y, c.r); } public Circle () { this(0.0, 0.0, 1.0); } public double circumference() { return 2.0 * 3.14159 * r; } public double area() { return 3.14159 * r * r; } }

C11: Java P2
! Circle.num_circles in loc de c.x sau c.y, unde c este de tip Circle, ceea ce confirma numele de variabila asociata clasei. Constantele sunt o alta categorie de variabile asociate clasei. De exemplu, pentru a defini constanta PI, putem scrie: public class Circle { public static final double PI = 3.14159266; public double x, y, r; //.......... } Accesul la asemenea variabile se face prin:

Atributul final interzice atribuiri de genul: Circle.PI = 4.0;


8

In interiorul metodelor clasei Circle putem folosi numele PI, iar in afara Circle.PI.

C11: Java P2

4. Metode asociate claselor :

Sa definim acum o metoda care testeaza daca un punct este in interiorul cercului curent:

public class Circle { public double x, y, r; // Este punctul (a,b) in interiorul cercului? public boolean inside(double a, double b) { double dx = a - x; double dy = b - y; double distance = Math.sqrt(dx*dx, dy*dy); return (distance < r); } //.......... }

C11: Java P2

Apelul Math.sqrt() arata ca sqrt este o metoda a clasei Math si nu a unui obiect de tip Math.

Asemenea metode se numesc metode ale clasei (metode statice) si se declara tot cu atributul static. Concret, pentru toate instantele unei clasei, exista o singura metoda.

Metodele statice nu au asociata o referinta this, ceea ce deriva din faptul ca ele nu sunt asociate unui obiect.

Sa consideram doua metode cu acelasi nume ale clasei Circle, una apartinind clasei (statica) si una apartinind instantelor: public class Circle { public double x, y, r; // O metoda de tip instanta: intoarce o referinta catre cercul // cu raza cea mai mare public static Circle bigger(Circle c) { if (c.r > r) return c; else return this; } public Circle bigger(Circle a, Circle b) { if (a.r > b.r) return a; else return b; } //.......... }
10

C11: Java P2

//Aceste metode se vor apela astfel: Circle a = new Circle(2.0); Circle b = new Circle(3.0); Circle c; c = a.bigger(b); // sau b.bigger(a); c = Circle.bigger(a, b);

Ambele implementari sunt la fel de justificate. Atit variabilele instantelor cit si cele ale clasei pot avea initializari: static int num_circles = 0; double r = 1.0;

Variabilele clasei sunt initializate o singura data la prima incarcare a clasei. Variabilele instanta sunt initializate la crearea obiectului.

11

C11: Java P2

Uneori dorim initializari mai complexe decit simpla atribuire a unei valori.

Pentru variabilele instanta avem la dispozitie metode constructor apelate la crearea obiectului.

Java permite existenta unor metode de initializare pentru variabilele statice (ale clasei), care sa fie apelate o singura data, la incarcarea clasei. Asemenea metode se numesc initializari statice.

Sintaxa acestor metode este putin neobisnuita, dar explicabila imediat din proprietatile acestora: deoarece sunt apelate la incarcarea clasei (inainte de existenta oricarui obiect de tipul clasei) nu avem ce parametri sa le transmitem (spre deosebire de constructori, care pot avea parametri). Nu exista nici valoare intoarsa. Deci initializarile statice nu au tip si lista de argumente.

Mai mult, nu e nevoie nici de nume, deoarece sistemul le apeleaza automat. Ce mai ramine atunci din declaratia unei metode? Doar cuvintul static si acoladele!

Sa consideram o varianta a clasei Circle in care folosim initializarea variabilelor statice si metode statice de initializare. E vorba de tabelarea functiilor sin si cos, pentru a calcula apoi rapid valorile acestora prin interpolare.
12

C11: Java P2

Exemplu:
// Aceste alocari // au loc // o singura data

public class Circle { static private double sines [] = new double [1000];

static private double cosines [] = new double [1000]; static { double x, deltax; deltax = (Circle.PI/2.0)/(1000 - 1); for (int i = 0, x = 0.0; i < 1000; i++, x += deltax) { sines[i] = Math.sin(x); cosines[i] = Math.cos(x); } } //..........

13

C11: Java P2

Sa observam ca declararea variabilei x locala blocului static nu intra in conflict cu variabila x membru a clasei. La incheierea blocului, variabilele definite in el "dispar".

Java permite oricite asemenea blocuri statice, in pozitii diverse din definitia clasei (sa nu uitam insa ca ele sunt metode, deci nu se pot intersecta cu definitiile altor metode). Ele vor fi apelate in ordinea in care sunt scrise.

14

C11: Java P2

5. Distrugerea obiectelor :

Obiectele sunt distruse automat in Java. Nu exista operatorul delete si nici functii de tip free() care sa elibereze memoria alocata. Aceasta scuteste programatorii Java de multe batai de cap.

Tehnica folosita in Java se numeste colectarea spatiului disponibil (garbage collection). Interpretorul Java stie in permanenta ce obiecte a alocat. Stie de asemenea ce obiecte refera alte obiecte. Atunci cind un obiect nu mai este referit de nici un alt obiect sau variabila, el poate fi distrus in siguranta (se elibereaza memoria).

Colectorul de spatiu disponibil ruleaza cu o prioritate scazuta si in general isi realizeaza functiile atunci cind nu mai e nimic de facut. Singura situatie in care trebuie sa ruleze in paralel cu o activitate de prioritate mare este atunci cind interpretorul nu mai are prea multa memorie la dispozitie.

Pentru programator, colectarea spatiului disponibil inseamna ca atunci cind a terminat de lucrat cu un obiect, poate uita linistit de el. Exemplul urmator ilustreaza asa ceva:

15

C11: Java P2

String processString(String s) { // Creeaza un StringBuffer pentru a prelucra sirul. // In Java, String-urile se considera constante si trebuie convertite la // StringBuffer si eventual inapoi la String StringBuffer b = new StringBuffer(s); // Prelucreaza b // Intoarce b convertit la String. // Putem uita de obiectul StringBuffer return b.toString();

} Examinind mai atent codul de mai sus, observam ca referinta b catre obiectul StringBuffer creat cu new isi inceteaza durata de viata la terminarea functiei. Acesta este momentul in care obiectul StringBuffer nu mai are nici o referinta la el si poate fi eliberat.

! De aici concluzia ca daca folosim o variabila cu durata de viata mai mare (de exemplu o variabila statica a unei clase) putem intirzia mult acest proces de colectare:
16

C11: Java P2
class A { static StringBuffer b; String processString(String s) { b = new StringBuffer(s); return b.toString(); } }

In acest caz putem forta disparitia referintei la obiectul creat prin atribuirea variabilei cu null:

class A { static StringBuffer b; String processString(String s) { String srez; b = new StringBuffer(s); srez = b.toString(); b = null; return srez; } }
17

C11: Java P2

Aceeasi problema apare cind functia respectiva nu se incheie niciodata (de exemplu, intr-o bucla in care se asteapta actiunea utilizatorului):

public static void main(String args[]) { int big_array = new int [10000]; int result = compute(big_array); // Am terminat lucrul cu big_array, dar main va intra intr-o bucla infinita // deci anulam referinta explicit big_array = null; // Bucla infinita care prelucreaza comenzile date de utilizator for(;;) ghandle_input();

}
18

C11: Java P2

Asa cum un constructor realizeaza initializarea unui obiect, o metoda Java de finalizare (finalizer) poate efectua operatii de finalizare ("curatenie"), la distrugerea obiectului.

Colectorul de spatiu disponibil se ocupa de eliberarea memoriei, dar un obiect poate detine si alte tipuri de resurse, cum ar fi descriptori de fisiere, canale de comunicatie etc.

Pentru a elibera acest gen de resurse trebuie sa scriem o metoda de finalizare (metoda a clasei), care sa inchida fisiere, sa elibereze conexiuni etc.

19

C11: Java P2

! O asemenea metoda este nestatica (deci apartine instantelor), este fara parametri, nu intoarce valori (deci are tipul void) si trebuie sa aiba numele finalize.

Mai jos este o listata metoda finalize() a clasei Java predefinite FileOutputStream, care ofera suport pentru operatii de scriere in fisiere:

public void finalize () throws IOException { if (fd != null) close(); }

Daca descriptorul de fisier fd este diferit de null (deci fisierul este deschis) se apeleaza metoda close() pentru a inchide fisierul. Sintaxa throws IOException precizeaza ca aceasta metoda poate declansa exceptia IOException, daca apare o eroare la operatia inchidere.
20

C11: Java P2

Exista citeva proprietati ale metodelor de finalizare:

Daca un obiect are o metoda finalize(), aceasta va fi invocata inainte de colectarea spatiului disponibil pentru acel obiect.

b) Interpretorul Java poate sa-si incheie executia fara a colecta intreg spatiul disponibil. Ca atare e posibil ca anumite metode de finalizare sa nu se execute. De regula, in aceasta situatie resursele principale sunt eliberate de catre sistemul de operare.

c) Nu se garanteaza cind anume va avea loc colectarea spatiului disponibil sau care va fi ordinea in care obiectele vor fi eliberate. De aceea nu se poate garanta nici momentul sau ordinea in care vor fi invocate metodele de finalizare.

d) Dupa invocarea unei metode de finalizare, obiectele nu sunt eliberate imediat. Aceasta pentru ca o metoda de finalizare poate "invia" un obiect prin memorarea undeva a referintei this, astfel incit obiectul sa aiba numarul de referinte diferit de zero. In aceasta situatie, dupa invocarea lui finalize(), mediul Java va trebui sa contorizeze din nou referintele la obiectul respectiv pentru a putea decide daca spatiul de memorie poate fi colectat. Chiar daca obiectul este "inviat". metoda de finalizare nu este niciodata invocata mai mult decit o data.
21

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