Überschreiben Sie valueof() und toString() in Java-Enum

Lesezeit: 6 Minuten

Benutzer-Avatar
WildBamaBoy

Die Werte in meiner enum sind Wörter, die Leerzeichen enthalten müssen, aber Aufzählungen können keine Leerzeichen in ihren Werten enthalten, also ist alles gebündelt. Ich möchte überschreiben toString() um diese Leerzeichen hinzuzufügen, wo ich es sage.

Ich möchte auch, dass die Aufzählung die richtige Aufzählung liefert, wenn ich sie verwende valueOf() auf der gleichen Zeichenfolge, der ich die Leerzeichen hinzugefügt habe.

Zum Beispiel:

public enum RandomEnum
{
     StartHere,
     StopHere
}

Anruf toString() an RandomEnum dessen Wert ist StartHere gibt Zeichenfolge zurück "Start Here". Anruf valueof() auf derselben Saite ("Start Here") gibt den Aufzählungswert zurück StartHere.

Wie kann ich das machen?

  • Fügen Sie das „Java“-Tag hinzu, um mehr Kommentare/Antworten zu erhalten.

    – Java42

    12. März 2012 um 6:02 Uhr

  • mögliches Duplikat von Implementing toString on Java enums

    – Steve Kammern

    5. Februar 2014 um 9:02 Uhr

Benutzer-Avatar
Jugal Schah

Sie können diesen Code ausprobieren. Da kann man nicht überschreiben valueOf Methode müssen Sie eine benutzerdefinierte Methode definieren (getEnum im Beispielcode unten), der den benötigten Wert zurückgibt, und ändern Sie Ihren Client so, dass er stattdessen diese Methode verwendet.

public enum RandomEnum {

    StartHere("Start Here"),
    StopHere("Stop Here");

    private String value;

    RandomEnum(String value) {
        this.value = value;
    }

    public String getValue() {
        return value;
    }

    @Override
    public String toString() {
        return this.getValue();
    }

    public static RandomEnum getEnum(String value) {
        for(RandomEnum v : values())
            if(v.getValue().equalsIgnoreCase(value)) return v;
        throw new IllegalArgumentException();
    }
}

  • getEnum könnte verkürzt werden, wenn Sie Folgendes tun: v.getValue().equals(value); die Nullprüfung kann weggelassen werden.

    – rtcarlson

    27. März 2014 um 18:45 Uhr


  • Sie können eine Karte auch faul erstellen und wiederverwenden, aber achten Sie beim Erstellen auf Threading-Probleme.

    – Maarten Bodewes

    30. Juni 2014 um 9:07 Uhr

  • funktioniert nicht in Szenarien, in denen Sie den Aufruf der Methode valueOf() nicht in getValue() ändern können, z. B. wenn Sie bestimmte Felder über Hibernate-Anmerkungen definieren, um sie Aufzählungswerten zuzuordnen

    – mmierins

    19. September 2014 um 11:06 Uhr

  • Bis Enums in Java behoben sind, hat @Bat eine geeignetere und OO-freundlichere Lösung. name() sollte nicht final sein.

    – Andrew T. Finnell

    15. August 2018 um 14:53 Uhr


  • Anstelle von for können Sie valueOf(RandomEnum.class, value) verwenden;

    – Wojtek

    22. Mai 2020 um 11:41 Uhr


Probieren Sie es aus, aber ich bin mir nicht sicher, ob das überall funktioniert 🙂

public enum MyEnum {
    A("Start There"),
    B("Start Here");

    MyEnum(String name) {
        try {
            Field fieldName = getClass().getSuperclass().getDeclaredField("name");
            fieldName.setAccessible(true);
            fieldName.set(this, name);
            fieldName.setAccessible(false);
        } catch (Exception e) {}
    }
}

  • Warum bin ich der Einzige, für den so etwas böse aussieht? Ich meine, es sieht wirklich cool aus, aber jemand ohne Kontext, der diesen Code liest, würde höchstwahrscheinlich “WTF?” sagen.

    – Nikolaus Guillaume

    25. April 2016 um 23:51 Uhr

  • @NicolasGuillaume Das ist die Art von Code, der, wenn er implementiert wäre, dringend einen Kommentar benötigen würde, der erklärt, warum er da ist und welches Problem der Programmierer zu lösen versuchte. 🙂

    – Ti Strga

    6. Juni 2016 um 19:28 Uhr

  • Fangen Sie keine generische Ausnahme ab, da dies OutOfMemory oder sein könnte irgendetwas

    – knusprig

    27. Juni 2017 um 10:20 Uhr

  • Das ist eine schreckliche Idee. Nicht zuletzt besteht die Möglichkeit eines stillen Fehlers ohne Anzeige oder Wiederherstellung. Außerdem sind jetzt der “Name”-Wert und der symbolische Wert im Code (z. B. A, B) unterschiedlich. +2 für clever sein. -200, weil er so schlau ist. Auf keinen Fall würde ich dies jemals einer Codeüberprüfung zustimmen.

    – Pedroro

    24. Juli 2018 um 16:04 Uhr


  • @pedorro Das scheint nicht so schrecklich zu sein, wie du es darstellst. Jeder, der verstanden hat, dass alles, was das Java-Komitee tut, nicht als Evangelium angesehen werden sollte, würde dies in einem Code Review bestehen. Es ist unendlich schlimmer, alle Enum-Utility-Methoden neu schreiben und dann warten zu müssen, weil name() nicht überschrieben werden kann. Anstatt die Ausnahme abzufangen und zu schlucken, sollte eine RuntimeException geworfen werden und dann ist das in Ordnung.

    – Andrew T. Finnell

    15. August 2018 um 14:52 Uhr


Benutzer-Avatar
Pedro

Sie können eine statische Map in Ihrer Aufzählung verwenden, die Strings auf Aufzählungskonstanten abbildet. Verwenden Sie es in einer statischen ‘getEnum’-Methode. Dadurch entfällt die Notwendigkeit, die Aufzählungen jedes Mal zu durchlaufen, wenn Sie eine aus ihrem String-Wert abrufen möchten.

public enum RandomEnum {

    StartHere("Start Here"),
    StopHere("Stop Here");

    private final String strVal;
    private RandomEnum(String strVal) {
        this.strVal = strVal;
    }

    public static RandomEnum getEnum(String strVal) {
        if(!strValMap.containsKey(strVal)) {
            throw new IllegalArgumentException("Unknown String Value: " + strVal);
        }
        return strValMap.get(strVal);
    }

    private static final Map<String, RandomEnum> strValMap;
    static {
        final Map<String, RandomEnum> tmpMap = Maps.newHashMap();
        for(final RandomEnum en : RandomEnum.values()) {
            tmpMap.put(en.strVal, en);
        }
        strValMap = ImmutableMap.copyOf(tmpMap);
    }

    @Override
    public String toString() {
        return strVal;
    }
}

Stellen Sie einfach sicher, dass die statische Initialisierung der Karte unterhalb der Deklaration der Enum-Konstanten erfolgt.

Übrigens – dieser Typ “ImmutableMap” stammt von der Google-Guava-API, und ich empfehle ihn auf jeden Fall in solchen Fällen.


BEARBEITEN – Gemäß den Kommentaren:

  1. Diese Lösung geht davon aus, dass jeder zugewiesene Zeichenfolgenwert eindeutig und nicht null ist. Angesichts der Tatsache, dass der Ersteller der Aufzählung dies steuern kann und die Zeichenfolge dem eindeutigen und Nicht-Null-Aufzählungswert entspricht, scheint dies eine sichere Einschränkung zu sein.
  2. Ich habe die Methode ‚toSTring()‘ hinzugefügt, wie in der Frage verlangt

  • Ich habe ein paar Abwertungen zu dieser Antwort erhalten – möchte jemand näher erläutern, warum diese Antwort schlecht ist? Ich bin nur neugierig, was die Leute denken.

    – Pedroro

    7. Mai 2015 um 22:17 Uhr

  • Dies wird für das Szenario mit fehlschlagen mehrere enum-Konstanten mit gleichem ‘Wert’ like RestartHere("replay"), ReplayHere("replay") oder gar keinen ‘Wert’ mögen PauseHere, WaitHere (dh enum hat einen Standardkonstruktor wie etwa private RandomEnum() { this.strVal = null; }

    – saktiw

    25. Juni 2015 um 18:25 Uhr


  • Sie sollten ImmutableMap.Builder verwenden, anstatt eine MutableMap zu erstellen, um + ImmutableMap::copyOf zu erstellen.

    – Avery Michelle Dawn

    25. Mai 2018 um 19:30 Uhr

  • Das sieht interessant aus, aber wenn die Aufzählung nur wenige verschiedene Werte hat, wird es nicht lange dauern, sie zu durchlaufen. Es lohnt sich wahrscheinlich nur, wenn die Aufzählung viele Werte hat.

    – Ben Thurley

    23. Juli 2018 um 16:52 Uhr

Benutzer-Avatar
corlaez

Wie wäre es mit einer Java 8 Implementierung? (Null kann durch Ihre Standard-Enum ersetzt werden)

public static RandomEnum getEnum(String value) {
    return Arrays.stream(RandomEnum.values()).filter(m -> m.value.equals(value)).findAny().orElse(null);
}

Oder Sie könnten verwenden:

...findAny().orElseThrow(NotFoundException::new);

Ich glaube nicht, dass Sie valueOf (“Start Here”) zum Laufen bringen werden. Aber was Leerzeichen angeht … versuchen Sie Folgendes …

static private enum RandomEnum {
    R("Start There"), 
    G("Start Here"); 
    String value;
    RandomEnum(String s) {
        value = s;
    }
}

System.out.println(RandomEnum.G.value);
System.out.println(RandomEnum.valueOf("G").value);

Start Here
Start Here

Benutzer-Avatar
Ausnahme

Das Folgende ist eine nette generische Alternative zu valueOf()

public static RandomEnum getEnum(String value) {
  for (RandomEnum re : RandomEnum.values()) {
    if (re.description.compareTo(value) == 0) {
      return re;
    }
  }
  throw new IllegalArgumentException("Invalid RandomEnum value: " + value);
}

Benutzer-Avatar
Andrej Lebedenko

Sie haben immer noch die Möglichkeit, dies in Ihrer Aufzählung zu implementieren:

public static <T extends Enum<T>> T valueOf(Class<T> enumType, String name){...}

1335430cookie-checkÜberschreiben Sie valueof() und toString() in Java-Enum

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

Privacy policy