So definieren Sie Eigenschaften für Enum-Elemente

Lesezeit: 4 Minuten

Benutzer-Avatar
iTEgg

Ich habe die Frage “Unterschied von Enum zwischen Java und C++” gelesen. aber ich bin immer noch verwirrt.

Ich möchte Folgendes, um den zugehörigen String zurückzugeben:

public enum Checker {
    EMPTY ("Empty"),
    RED ("Red"),
    YELLOW ("Yellow");
}

Soweit ich gelesen habe, sollte dies möglich sein. Ich möchte nur, dass Sie etwas Licht darauf werfen, wie man es umsetzt.

Benutzer-Avatar
Sean Patrick Floyd

Kurze Antwort

Sie benötigen einen Konstruktor, ein Feld und einen Getter.

Konstrukteure

Aufzählungstypen können Konstruktoren haben, vorausgesetzt, ihre Zugriffsebene ist entweder privat oder standardmäßig (paketprivat). Sie können diese Konstruktoren nicht direkt aufrufen, außer in der Enum-Deklaration selbst. Ähnlich wie bei Klassen rufen Sie beim Definieren einer Aufzählungskonstante ohne Parameter tatsächlich den vom Compiler generierten Standardkonstruktor auf. Z.B

public enum King {
    ELVIS
}

ist äquivalent zu

public enum King {
    ELVIS() // the compiler will happily accept this
}

Und genau wie in Klassen fügt der Compiler keinen Standardkonstruktor ein, wenn Sie einen expliziten Konstruktor definieren, sodass dies nicht kompiliert wird:

public enum King {
    ELVIS, // error, default constructor is not defined
    MICHAEL_JACKSON(true)
    ;
    private boolean kingOfPop;
    King(boolean kingOfPop){this.kingOfPop = kingOfPop;}
}

Das ist eine ziemlich gute Referenz auf Enums das erklärt auch die Konstruktorprobleme.

Felder und Accessoren

Aufzählungen sind Konstanten und als solche unveränderlich. Sie können jedoch Felder definieren, die einen Status haben können. Dies ist eine schreckliche Praxis, da Entwickler erwarten, dass Aufzählungen und ihre zugehörigen Werte Konstanten sind, aber Sie kann Definieren Sie immer noch ein nicht finales Feld in einer Aufzählung mit Gettern und Settern.

Dies ist legaler Java-Code:

public enum Color {
    RED("FF0000"),
    GREEN("00FF00"),
    BLUE("0000FF");
    private String code;
    public String getCode(){return code;}
    public void setCode(String code){this.code = code;}
    private Color(String code){this.code = code;}
}

Aber es ermöglicht bösen Code wie diesen:

String oldBlue = Color.BLUE.getCode();
Color.BLUE.setCode(Color.RED.getCode());
Color.RED.setCode(oldBlue);

Also in 99,99 % der Fälle: Wenn Sie Felder in Ihren Aufzählungen haben, sollten Sie sie endgültig machen und nur Getter bereitstellen. Wenn die Felder selbst nicht unveränderlich sind, stellen Sie defensive Kopien bereit:

public enum Band {
    THE_BEATLES("John","Paul","George","Ringo");
    private final List<String> members;
    public List<String> getMembers(){
        // defensive copy, because the original list is mutable
        return new ArrayList<String>(members);
    }
    private Band(String... members){
        this.members=Arrays.asList(members);
    }
}

Lösung

In Ihrem Fall ist es sehr einfach: Sie brauchen nur ein einzelnes Feld vom Typ String (unveränderlich), also ist es vollkommen in Ordnung, es im Konstruktor zu initialisieren und einen Getter bereitzustellen:

public enum Checker {

    EMPTY ("Empty"),
    RED ("Red"),
    YELLOW ("Yellow");

    private final String value;

    private Checker(final String value) {
        this.value = value;
    }

    public String getValue() { return value; }
}

  • @Joachim: Ohne Setter sehe ich keinen Unterschied.

    – Michael myers

    16. Juni 2010 um 14:37 Uhr

  • @Joachim: genau, das habe ich hinzugefügt, während du den Kommentar hinzugefügt hast 🙂

    – Sean Patrick Floyd

    16. Juni 2010 um 14:37 Uhr


  • @mmyers Ich denke, dass in den letzten Feldern einige Compiler-Optimierungszauber im Gange sind

    – Sean Patrick Floyd

    16. Juni 2010 um 14:38 Uhr

  • @mmyers Seltsam aber wahr. Es ist in der JLS. Die Laufzeit darf Optimierungen vornehmen, die sie sonst nicht machen würde, nur wegen der final. Aber ein besserer Grund für das Hinzufügen final ist, dass jemand den Code lesen möchte.

    – Tom Hawtin – Angelleine

    16. Juni 2010 um 15:20 Uhr

  • @mmyers: Abgesehen von dem, was Tom gesagt hat, ist es auch eine wichtige Möglichkeit, die Absicht zu dokumentieren. Es gibt keinen Grund, warum sich das Feld jemals ändern sollte, es sollte immer initialisiert werden, sobald der Konstruktor fertig ist, und es sollte nicht zulässig sein, es zu setzen. Warum das nicht mit einem Stichwort dokumentieren, das genau das ausdrückt.

    – Joachim Sauer

    16. Juni 2010 um 17:32 Uhr

Wenn das Muster gilt, funktioniert dies ebenfalls und eliminiert die Wiederholung:

public enum Checker {
    EMPTY,
    RED,
    YELLOW;


    public String getDescription(){
        String name = name();
        return ""+Character.toUpperCase(name.charAt(0))
                 +name.substring(1).toLowerCase();
    }

}

  • Warum ist das besser? Sie weisen all diese Zeichenfolgen jedes Mal neu zu, und ich würde nicht besonders sagen, dass dies besser lesbar ist.

    – Danben

    16. Juni 2010 um 14:47 Uhr

  • Es vermeidet die Wiederholung des Namens (DRY-Prinzip) und benötigt keinen Konstruktor oder Feld (und damit weniger Speicher). Wenn die Neuzuweisung ein Problem ist und die Verwendung des Speichers nicht, könnte man sie in einem Feld oder einer EnumMap zwischenspeichern. Höchstwahrscheinlich spielt es keine Rolle und die kürzere Lösung ist besser.

    – Michael Borgwardt

    16. Juni 2010 um 14:53 Uhr


  • Tatsächlich könnte es zwei Konstruktoren geben, einen mit einem Wert, der den Wert direkt speichert, und einen leeren Konstruktor, der den Wert mithilfe Ihrer getDescription-Methode generiert. Ich würde sie aber trotzdem in ein Feld schreiben

    – Sean Patrick Floyd

    16. Juni 2010 um 14:56 Uhr

  • Offensichtlich kann man DRY viel zu weit treiben! Es ist nicht einmal sicher, ob der Aufzählungsname und “verwandt” String werden immer so verwandt sein, wie sie naiv erscheinen. Sie möchten vielleicht FUSCHIA("Fuchsia"), WTF("Dusty Lavendar").

    – Tom Hawtin – Angelleine

    16. Juni 2010 um 15:28 Uhr

  • @Tom genau, deshalb habe ich das Szenario mit zwei Konstruktoren vorgeschlagen

    – Sean Patrick Floyd

    16. Juni 2010 um 15:35 Uhr

1100410cookie-checkSo definieren Sie Eigenschaften für Enum-Elemente

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy