Überschreiben Sie valueof() und toString() in Java-Enum
Lesezeit: 6 Minuten
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
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 🙂
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
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:
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.
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
corlaez
Wie wäre es mit einer Java 8 Implementierung? (Null kann durch Ihre Standard-Enum ersetzt werden)
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