enum cu câmpuri și metode în Java

Un enum poate avea câmpuri, constructor, metode, metode diferite pentru fiecare constantă și poate implementa interfețe.

Sintaxă
enum Planeta {
    MERCUR(3.303e+23), PAMANT(5.976e+24);   // constructorul primește valorile

    private final double masa;
    Planeta(double masa) { this.masa = masa; }
    double masa() { return masa; }
}

Ce face enum cu câmpuri și metode

Constantele unui enum sunt obiecte, deci pot avea date proprii. Le dai valori între paranteze, după numele constantei, iar constructorul enum-ului le salvează în câmpuri final. Constructorul este implicit private: nimeni nu poate crea constante noi cu new.

Poți adăuga metode obișnuite (ca la orice clasă) și metode statice, de exemplu o căutare după cod. O metodă declarată abstract în enum trebuie implementată de fiecare constantă, în corpul ei propriu { ... }, astfel încât fiecare constantă să se comporte diferit.

Un enum poate implementa interfețe, dar nu poate extinde altă clasă (extinde deja java.lang.Enum). Lista de constante trebuie să fie primul lucru din corp și se termină cu ; când urmează câmpuri sau metode.

Exemple

Exemplul 1: Câmpuri, constructor și metode

Fiecare monedă are simbolul și cursul ei. Metoda inLei folosește câmpul constantei pe care a fost apelată.

enum Moneda {
    RON("lei", 1.0),
    EUR("€", 5.08),
    USD("$", 4.37),
    GBP("£", 5.86);

    private final String simbol;
    private final double curs;

    Moneda(String simbol, double curs) {
        this.simbol = simbol;
        this.curs = curs;
    }

    double inLei(double suma) {
        return suma * curs;
    }

    String formateaza(double suma) {
        return String.format("%.2f %s", suma, simbol);
    }
}

public class Main {
    public static void main(String[] args) {
        for (Moneda m : Moneda.values()) {
            System.out.printf("%-8s = %s%n", m.formateaza(100), Moneda.RON.formateaza(m.inLei(100)));
        }
    }
}

Rezultat

100.00 lei = 100.00 lei
100.00 € = 508.00 lei
100.00 $ = 437.00 lei
100.00 £ = 586.00 lei

Exemplul 2: Comportament diferit pentru fiecare constantă

Metoda abstractă aplica este scrisă separat în corpul fiecărei constante. Câmpul semn ține simbolul afișat.

enum Operatie {
    ADUNARE("+") {
        @Override int aplica(int a, int b) { return a + b; }
    },
    SCADERE("-") {
        @Override int aplica(int a, int b) { return a - b; }
    },
    INMULTIRE("*") {
        @Override int aplica(int a, int b) { return a * b; }
    };

    final String semn;

    Operatie(String semn) {
        this.semn = semn;
    }

    abstract int aplica(int a, int b);
}

public class Main {
    public static void main(String[] args) {
        for (Operatie op : Operatie.values()) {
            System.out.println("12 " + op.semn + " 4 = " + op.aplica(12, 4));
        }
    }
}

Rezultat

12 + 4 = 16
12 - 4 = 8
12 * 4 = 48

Exemplul 3: Căutare după cod și interfață implementată

Metoda statică dupaCod găsește județul după indicativ și returnează Optional. Enum-ul implementează interfața Descriptibil.

import java.util.Optional;

interface Descriptibil {
    String descriere();
}

enum Judet implements Descriptibil {
    IASI("IS", "Iași"),
    CLUJ("CJ", "Cluj-Napoca"),
    TIMIS("TM", "Timișoara"),
    CONSTANTA("CT", "Constanța");

    private final String cod;
    private final String resedinta;

    Judet(String cod, String resedinta) {
        this.cod = cod;
        this.resedinta = resedinta;
    }

    static Optional<Judet> dupaCod(String cod) {
        for (Judet j : values()) {
            if (j.cod.equalsIgnoreCase(cod)) {
                return Optional.of(j);
            }
        }
        return Optional.empty();
    }

    @Override
    public String descriere() {
        return "județul " + name() + " (" + cod + "), reședința " + resedinta;
    }
}

public class Main {
    public static void main(String[] args) {
        for (String cod : new String[] {"tm", "CT", "XX"}) {
            System.out.println(cod + " -> " + Judet.dupaCod(cod).map(Judet::descriere).orElse("necunoscut"));
        }
    }
}

Rezultat

tm -> județul TIMIS (TM), reședința Timișoara
CT -> județul CONSTANTA (CT), reședința Constanța
XX -> necunoscut

Greșeli frecvente

  • Uiți ; după ultima constantă când urmează câmpuri: compilatorul dă erori greu de citit, de tipul ',', '}', or ';' expected.
  • Faci câmpurile enum-ului modificabile (fără final, cu setteri). Constantele sunt partajate de tot programul; o modificare se vede peste tot.
  • Pui public pe constructorul enum-ului: modifier public not allowed here. Constructorul este mereu privat.

Comenzi înrudite

  • enum: enum declară un tip cu un set fix de valori cu nume (zilele săptămânii, stările unei comenzi), verificat de compilator.
  • Interfețe (interface, implements): O interfață (interface) descrie ce metode trebuie să aibă o clasă; clasa o promite cu implements și poate implementa mai multe interfețe.
  • Clase abstracte (abstract): O clasă abstract nu poate fi instanțiată direct; poate avea metode abstracte, pe care subclasele concrete sunt obligate să le scrie.
  • record: record declară o clasă imutabilă pentru date: constructorul, accesorii, equals, hashCode și toString sunt generați automat.