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;
    }
}

You could leave a comment if you were logged in.