Constructori
Există uneori restricții de integritate care trebuie îndeplinite pentru crearea unui obiect. Java permite acest lucru prin existența noțiunii de constructor.
Astfel, la crearea unui obiect al unei clase se apelează automat o funcție numită constructor. Constructorul o metodă specială care are numele clasei, nu returnează explicit un tip anume (nici măcar void!) și poate avea oricâți parametri.
Obiectele se constuiesc utilizând keywordul new. Acesta apelează constructorul din clasa respectivă:
class MyClass { // ... }
MyClass instanceObject = new MyClass(param_1, param_2, ..., param_n); // în dreapta semnului egal avem apel la constructor
Exemplu
String myFirstString, mySecondString; myFirstString = new String(); mySecondString = "This is my second string";
Acesta creează întâi un obiect de tip String folosind constructorul fără parametru (alocă spațiu de memorie și efectuează inițializările specificate în codul constructorului), iar apoi creează un alt obiect de tip String pe baza unui șir de caractere constant.
Clasele pe care le-am creat până acum însă nu au avut nici un constructor. În acest caz, Java crează automat un constructor implicit (default constructor) care face inițializarea câmpurilor neinițializate, astfel:
- referințele la obiecte se inițializează cu null
- variabilele de tip numeric se inițializează cu 0
- variabilele de tip logic (boolean) se inițializează cu
false
Pentru a exemplifica acest mecanism, să urmărim exemplul:
class SomeClass { String name = "Some Class"; public String getName() { return name; } }
class Test { public static void main(String[] args) { SomeClass instance = new SomeClass(); System.out.println(instance.getName()); } }
La momentul execuției, în consolă se va afișa “Some Class” și nu se va genera nicio eroare la compilare, deși în clasa SomeClass nu am declarat explicit un constructor de forma:
public SomeClass() { // Eventuale initializari }
Tipuri de constructori
Putem identifica mai multe tipuri de constructori, printre care: fără parametri (implicit), cu parametri şi de copiere.
public class Floare { String culoare; int petale; // constructor fara parametri public Floare() { culoare = “”; petale = 4; } // constructor cu parametri public Floare(String culoare, int petale) { this.culoare = culoare; this.petale = petale; } // constructor de copiere public Floare(Floare f) { // creaza in memorie un obiect identic this.nume = f.nume; // in general: this.nume = new String(f.nume); this.petale = f.petale; } }
Pot exista mai mulți constructori într-o clasă, care să difere între ei prin numărul, tipul și ordinea parametrilor pe care îi primesc. Nu pot exista 2 constructori identici, trebuie să difere ceva - fie numărul parametrilor, fie tipul lor, fie ordinea lor:
String marca = "Intel"; double procesor = 3.2; int ram = 4096; Computer computer = new Computer(); Computer computer2 = new Computer(marca, procesor, ram);
unde clasa Computer este:
public class Computer { String marca; double procesor; int ram; public Constructor() { //constructorul default } public Constructor(String marca, double procesor, int ram) { this.marca = marca; this.procesor = procesor; this.ram = ram; } }
Unde this face referire la atributul clasei (vezi subcapitolul următor).
Să analizăm acum un exemplu general:
Student.java
class Student { String name; int averageGrade; // (1) constructor fără parametri public Student() { name = "Necunoscut"; averageGrade = 5; } // (2) constructor cu 2 parametri, folosit dacă știm numele și media public Student(String n, int avg) { name = n; averageGrade = avg; } // (3) constructor cu un singur parametru, folosit atunci când cunoaștem doar numele studentului public Student(String n) { this(n, 5); // Astfel, se va apela constructorul (2) } // (4) metoda set pentru câmpul name al clasei Student public void setName(String n) { name = n; averageGrade = 5; } // (5) metoda getter pentru câmpul name public String getName() { return name; } }
Declararea unui obiect de tip Student se face astfel:
Student st;
Crearea unui obiect Student se face prin apel la unul din cei 3 constructori de mai sus:
st = new Student(); // apel al constructorului 1 st = new Student("Gigel", 6); //apel al constructorului 2 st = new Student("Gigel"); //apel al constructorului 3
Atenție! Dacă nu introducem niciun constructor când definim clasa, compilatorul va introduce constructorul default. Dar dacă într-o clasă se definesc doar constructori cu parametri, acest lucru nu se mai întâmplă! Exemplul următor va genera eroare la compilare:
class Student { String name; int averageGrade; public Student(String n, int avg) { name = n; averageGrade = avg; } public static void main(String[] args) { Student s = new Student(); // EROARE: constructorul implicit este ascuns de constructorul cu parametri // solutia aici este sa definim manual un constructor gol, fara parametri } }
Referinţa this
Keywordul this
face referire la obiectul în care se găseşte.
Apelurile unor funcții sau atribute din interiorul unui obiect se fac direct prin nume. Apelurile de funcții sau atribute aparținând unui alt obiect se fac prefixând numele funcţiei sau atributului cu numele obiectului (ex.: computer.marca
).
Totuși, unele funcții pot trimite un parametru cu același nume ca și un câmp membru. În aceste situații, se folosește cuvântul cheie this pentru dezambiguizare, el prefixând denumirea câmpului când se dorește utilizarea acestuia:
public class VeterinaryReport { int dogs; int cats; [...] public void setAnimalsNo(int cats, int dogs) { this.dogs = dogs; this.cats = cats; } }