Clase și obiecte (class) în Java

O clasă (cuvântul cheie class) descrie un tip nou: câmpuri pentru date și metode pentru comportament; obiectele sunt instanțele ei.

Sintaxă
class Elev {
    String nume;        // câmp (stare)
    int nota;

    void afiseaza() {   // metodă (comportament)
        System.out.println(nume + ": " + nota);
    }
}

Elev e = new Elev();   // obiect (instanță)

Ce face Clase și obiecte (class)

O clasă este un „șablon”: spune ce date are un lucru (câmpurile) și ce poate face (metodele). Cuvântul cheie class declară clasa. Un obiect este un exemplar concret construit după șablon cu new: clasa Elev este una singură, dar poți avea mii de obiecte Elev, fiecare cu numele și nota lui.

Câmpurile fără static aparțin fiecărui obiect în parte. Le accesezi cu punct: e.nume, iar metodele le apelezi la fel: e.afiseaza(). În interiorul clasei, o metodă vede direct câmpurile obiectului pe care a fost apelată.

Variabila de tip clasă nu conține obiectul, ci o referință către el. Dacă scrii Elev b = a;, ambele variabile arată spre același obiect, iar o modificare făcută prin b se vede și prin a. Orice clasă moștenește din Object metode precum toString(), pe care le poți rescrie.

Exemple

Exemplul 1: O clasă cu câmpuri și metode

Fiecare obiect are propriile valori în câmpuri. Metoda promovat() folosește câmpul nota al obiectului pe care a fost apelată.

class Elev {
    String nume;
    String oras;
    double nota;

    boolean promovat() {
        return nota >= 5;
    }

    void afiseaza() {
        System.out.println(nume + " (" + oras + "): " + nota + (promovat() ? " - promovat" : " - corigent"));
    }
}

public class Main {
    public static void main(String[] args) {
        Elev ana = new Elev();
        ana.nume = "Ana";
        ana.oras = "Iași";
        ana.nota = 9.5;

        Elev radu = new Elev();
        radu.nume = "Radu";
        radu.oras = "Cluj";
        radu.nota = 4.25;

        ana.afiseaza();
        radu.afiseaza();
    }
}

Rezultat

Ana (Iași): 9.5 - promovat
Radu (Cluj): 4.25 - corigent

Exemplul 2: Două variabile, același obiect

copie = cont copiază doar referința, nu obiectul. Depunerea făcută prin copie modifică același cont. Pentru un obiect nou ai nevoie de încă un new.

class Cont {
    String titular;
    double sold;

    void depune(double suma) {
        sold += suma;
    }
}

public class Main {
    public static void main(String[] args) {
        Cont cont = new Cont();
        cont.titular = "Maria";
        cont.sold = 100;

        Cont copie = cont;            // aceeași referință
        copie.depune(50);
        System.out.println("cont.sold = " + cont.sold);
        System.out.println("același obiect? " + (cont == copie));

        Cont altul = new Cont();      // obiect nou
        altul.titular = "Maria";
        altul.sold = 150;
        System.out.println("altul == cont? " + (altul == cont));
    }
}

Rezultat

cont.sold = 150.0
același obiect? true
altul == cont? false

Exemplul 3: toString() pentru afișare

Fără toString(), println afișează ceva de forma Produs@1b6d3586 (numele clasei și un cod hash). Rescriind metoda moștenită din Object, alegi tu textul.

class Produs {
    String denumire;
    double pret;

    @Override
    public String toString() {
        return denumire + " - " + pret + " lei";
    }
}

public class Main {
    public static void main(String[] args) {
        Produs p = new Produs();
        p.denumire = "Cozonac";
        p.pret = 32.5;
        System.out.println(p);
        System.out.println("În coș: " + p);
    }
}

Rezultat

Cozonac - 32.5 lei
În coș: Cozonac - 32.5 lei

Greșeli frecvente

  • Folosești un obiect neconstruit: Elev e = null; e.afiseaza(); aruncă NullPointerException. O variabilă locală neinițializată nici nu compilează (variable e might not have been initialized).
  • Crezi că b = a copiază obiectul. Copiază doar referința; ambele variabile arată spre același obiect.
  • Compari obiecte cu ==. Operatorul verifică dacă este același obiect, nu dacă au aceleași valori. Pentru conținut folosește equals (vezi pagina equals și hashCode).

Comenzi înrudite

  • new: new creează un obiect nou (sau un array) în memorie, apelează constructorul și returnează referința către el.
  • Constructori: Constructorul are numele clasei, nu are tip returnat și pregătește obiectul nou; o clasă poate avea mai mulți constructori.
  • this: this este referința către obiectul curent: deosebește câmpurile de parametri, apelează alt constructor sau returnează obiectul.
  • Modificatori de acces (public, protected, private): public, protected, private și lipsa modificatorului stabilesc cine poate vedea o clasă, un câmp, o metodă sau un constructor.
  • equals și hashCode: equals decide când două obiecte sunt „egale” ca valoare; hashCode trebuie rescris împreună cu el, altfel HashMap și HashSet nu funcționează corect.
  • record: record declară o clasă imutabilă pentru date: constructorul, accesorii, equals, hashCode și toString sunt generați automat.