Constructori în Java

Constructorul are numele clasei, nu are tip returnat și pregătește obiectul nou; o clasă poate avea mai mulți constructori.

Sintaxă
class Elev {
    String nume;
    int an;

    Elev(String nume, int an) {   // același nume ca clasa, fără tip returnat
        this.nume = nume;
        this.an = an;
    }

    Elev(String nume) {
        this(nume, 1);            // apelează celălalt constructor
    }
}

Ce face Constructori

Constructorul rulează o singură dată, imediat după ce new a alocat obiectul. Rolul lui este să pună obiectul într-o stare validă: completează câmpurile și verifică datele. Se scrie ca o metodă cu numele clasei, fără tip returnat (nici măcar void).

Dacă nu scrii niciun constructor, compilatorul adaugă unul implicit, fără parametri. Imediat ce scrii un constructor cu parametri, cel implicit dispare: new Elev() nu mai compilează până nu îl scrii explicit.

Poți avea mai mulți constructori cu liste diferite de parametri (supraîncărcare). Unul îl poate apela pe altul cu this(...), pe prima linie, ca logica să stea într-un singur loc. Din Java 25, înainte de this(...) sau super(...) poți pune instrucțiuni care nu folosesc obiectul (de exemplu validări).

Exemple

Exemplul 1: Constructor cu parametri și constructor implicit

Oras are un constructor cu doi parametri; Setari nu are niciunul scris, deci primește constructorul implicit și câmpurile păstrează valorile date la declarare.

class Oras {
    String nume;
    int locuitori;

    Oras(String nume, int locuitori) {
        this.nume = nume;
        this.locuitori = locuitori;
    }
}

class Setari {
    String limba = "ro";
    boolean modNoapte;
}

public class Main {
    public static void main(String[] args) {
        Oras iasi = new Oras("Iași", 271_692);
        System.out.println(iasi.nume + ": " + iasi.locuitori);

        Setari s = new Setari();
        System.out.println("limba=" + s.limba + ", modNoapte=" + s.modNoapte);
    }
}

Rezultat

Iași: 271692
limba=ro, modNoapte=false

Exemplul 2: Mai mulți constructori și this(…)

Constructorii scurți completează valorile lipsă și delegă cu this(...) către cel complet. Codul de inițializare nu se repetă.

class Comanda {
    String client;
    String produs;
    int cantitate;

    Comanda(String client, String produs, int cantitate) {
        this.client = client;
        this.produs = produs;
        this.cantitate = cantitate;
        System.out.println("  [comandă nouă pentru " + client + "]");
    }

    Comanda(String client, String produs) {
        this(client, produs, 1);
    }

    Comanda(String client) {
        this(client, "pâine");
    }

    @Override
    public String toString() {
        return client + ": " + cantitate + " x " + produs;
    }
}

public class Main {
    public static void main(String[] args) {
        System.out.println(new Comanda("Ana", "lapte", 3));
        System.out.println(new Comanda("Ion", "ouă"));
        System.out.println(new Comanda("Elena"));
    }
}

Rezultat

  [comandă nouă pentru Ana]
Ana: 3 x lapte
  [comandă nouă pentru Ion]
Ion: 1 x ouă
  [comandă nouă pentru Elena]
Elena: 1 x pâine

Exemplul 3: Validarea datelor în constructor

Constructorul refuză datele invalide aruncând o excepție. Astfel nu poate exista un obiect Varsta cu valoare negativă.

class Varsta {
    final int ani;

    Varsta(int ani) {
        if (ani < 0 || ani > 150) {
            throw new IllegalArgumentException("vârstă invalidă: " + ani);
        }
        this.ani = ani;
    }
}

public class Main {
    public static void main(String[] args) {
        int[] valori = {34, -2, 200, 7};
        for (int v : valori) {
            try {
                Varsta varsta = new Varsta(v);
                System.out.println("OK: " + varsta.ani + " ani");
            } catch (IllegalArgumentException e) {
                System.out.println("Eroare: " + e.getMessage());
            }
        }
    }
}

Rezultat

OK: 34 ani
Eroare: vârstă invalidă: -2
Eroare: vârstă invalidă: 200
OK: 7 ani

Greșeli frecvente

  • Pui un tip returnat: void Elev(String n) { ... } nu este constructor, ci o metodă obișnuită cu numele clasei. Obiectul rămâne neinițializat.
  • Scrii un constructor cu parametri și apoi apelezi new Elev(): constructor Elev in class Elev cannot be applied to given types. Adaugă și constructorul fără parametri, dacă îți trebuie.
  • Uiți this. când parametrul are același nume ca și câmpul: nume = nume; atribuie parametrul lui însuși, iar câmpul rămâne null.

Comenzi înrudite

  • this: this este referința către obiectul curent: deosebește câmpurile de parametri, apelează alt constructor sau returnează obiectul.
  • new: new creează un obiect nou (sau un array) în memorie, apelează constructorul și returnează referința către el.
  • super: super apelează constructorul superclasei sau versiunea din superclasă a unei metode rescrise.
  • Clase și obiecte (class): O clasă (cuvântul cheie class) descrie un tip nou: câmpuri pentru date și metode pentru comportament; obiectele sunt instanțele ei.
  • record: record declară o clasă imutabilă pentru date: constructorul, accesorii, equals, hashCode și toString sunt generați automat.