Bei der Arbeit mit Variablen / Parametern, die nur eine begrenzte Anzahl von Werten annehmen können, versuche ich, immer Java zu verwenden enum
, wie in
public enum BonusType {
MONTHLY, YEARLY, ONE_OFF
}
Solange ich in meinem Code bleibe, funktioniert das einwandfrei. Ich muss jedoch häufig eine Schnittstelle zu anderem Code herstellen, der einfache int
(oder String
) Werte für denselben Zweck verwendet, oder ich muss aus / in eine Datenbank lesen / schreiben, in der die Daten als Zahl oder Zeichenfolge gespeichert sind.
In diesem Fall hätte ich gerne eine bequeme Möglichkeit, jeden Aufzählungswert mit einer Ganzzahl zu verknüpfen, sodass ich beide Möglichkeiten konvertieren kann (mit anderen Worten, ich benötige eine "umkehrbare Aufzählung").
Von enum nach int zu wechseln ist einfach:
public enum BonusType {
public final int id;
BonusType(int id) {
this.id = id;
}
MONTHLY(1), YEARLY(2), ONE_OFF(3);
}
Dann kann ich auf den int-Wert als zugreifen BonusType x = MONTHLY; int id = x.id;
.
Ich sehe jedoch keinen guten Weg für das Gegenteil, dh von int nach enum. Im Idealfall so etwas wie
BonusType bt = BonusType.getById(2);
Die einzigen Lösungen, die ich finden könnte, sind:
- Fügen Sie eine Suchmethode in die Aufzählung ein, die verwendet
BonusType.values()
eine Karte "int -> enum" gefüllt wird, speichern Sie diese dann zwischen und verwenden Sie sie für Suchvorgänge. Würde funktionieren, aber ich müsste diese Methode identisch in jede von mir verwendete Aufzählung kopieren :-(. - Fügen Sie die Suchmethode in eine statische Dienstprogrammklasse ein. Dann würde ich nur eine "Nachschlage" -Methode benötigen, aber ich müsste mit der Reflexion herumspielen, damit sie für eine beliebige Aufzählung funktioniert.
Beide Methoden scheinen für ein so einfaches (?) Problem furchtbar umständlich.
Irgendwelche anderen Ideen / Einsichten?
quelle
ordinal()
.ordinal()
) oder werden sie von externen Kräften festgelegt?Antworten:
http://www.javaspecialists.co.za/archive/Issue113.html
Die Lösung beginnt ähnlich wie Ihre mit einem int-Wert als Teil der Aufzählungsdefinition. Anschließend erstellt er ein generikbasiertes Suchdienstprogramm:
Diese Lösung ist nett und erfordert kein "Fummeln mit Reflexion", da sie auf der Tatsache basiert, dass alle Aufzählungstypen implizit die Aufzählungsschnittstelle erben.
quelle
Number
anstelle von verwenden würdeByte
, da mein Hintergrundwert möglicherweise größer ist.Aufzählung → int
int → enum
String → Aufzählung
Aufzählung → Zeichenfolge
Eine Randnotiz:
Wie Sie richtig hervorheben,
ordinal()
kann das von Version zu Version "instabil" sein. Dies ist der genaue Grund, warum ich Konstanten immer als Zeichenfolgen in meinen Datenbanken speichere. (Wenn ich MySql verwende, speichere ich sie tatsächlich als MySql-Aufzählungen !)quelle
BonusType.valueOf("MONTHLY")
) verwendenordinal()
scheint mir eine problematische Lösung zu sein, da sie unterbrochen wird, wenn die Liste der Enum-Werte neu angeordnet oder ein Wert gelöscht wird. Dies ist auch nur dann praktisch, wenn die int-Werte 0 ... n sind (was ich oft als nicht der Fall befunden habe).values()
Arrays funktioniert nur, wenn alle Ihre Werte für ihre ID auf 0 indiziert und der Reihe nach deklariert sind. (Getestet habe ich dies , dass zu überprüfen , ob Sie erklären ,FOO(0), BAR(2), BAZ(1);
dassvalues[1] == BAR
undvalues[2] == BAZ
trotz der vergangen ids in.)double
).Ich fand dies im Web, es war sehr hilfreich und einfach zu implementieren. Diese Lösung wurde NICHT von mir gemacht
http://www.ajaxonomy.com/2007/java/making-the-most-of-java-50-enum-tricks
}}
quelle
Die Antworten auf diese Frage scheinen mit der Veröffentlichung von Java 8 veraltet zu sein.
quelle
Collectors.toMap()
seinFunctions.identity()
stattnull
?org.apache.commons.lang.enums.ValuedEnum;
Um mir das Schreiben einer Menge Boilerplate-Code oder das Duplizieren von Code für jede Aufzählung zu ersparen, habe ich
ValuedEnum
stattdessen Apache Commons Langs verwendet.Definition :
Verwendung:
int -> ValuedEnum:
quelle
Sie könnten vielleicht so etwas gebrauchen
Dies würde den Reflexionsbedarf in Ihrer Utility-Klasse verringern.
quelle
In diesem Code haben Sie für eine permanente und intensive Suche Speicher oder Prozess zur Verwendung, und ich wähle Speicher mit Konverter-Array als Index aus. Ich hoffe es ist hilfreich
quelle
Verwenden Sie eine Schnittstelle, um zu zeigen, wer der Boss ist.
Und das Ergebnis:
quelle
Sowohl die
.ordinal()
als auchvalues()[i]
sind instabil, da sie von der Reihenfolge der Aufzählungen abhängen. Wenn Sie also die Reihenfolge der Aufzählungen ändern oder einige hinzufügen / löschen, wird Ihr Programm beschädigt.Hier ist eine einfache, aber effektive Methode, um zwischen enum und int abzubilden.
Das Anwenden auf Saiten sollte nicht schwierig sein.
quelle
Schritt 1 Definieren Sie einen
interface
EnumConverterSchritt 2
Erstellen Sie einen Klassennamen ReverseEnumMap
Schritt 3
Gehen Sie zu Ihrer
Enum
Klasse undimplement
sieEnumConverter<ContentType>
überschreiben und überschreiben natürlich die Schnittstellenmethoden. Sie müssen auch eine statische ReverseEnumMap initialisieren.Schritt 4
Erstellen Sie nun eine
Communication
Klassendatei und rufen Sie die neue Methode zum Konvertieren vonEnum
nachString
undString
nach aufEnum
. Ich habe gerade die Hauptmethode zur Erklärung angegeben.Klicken Sie hier für eine vollständige Erklärung
quelle
ContentType convert(String pKey)
statisch zu machen , wodurch die Notwendigkeit für dieCommunication
Klasse entfällt und mehr nach meinem Geschmack war. +1Ich bin nicht sicher, ob es in Java dasselbe ist, aber Aufzählungstypen in C werden automatisch auch Ganzzahlen zugeordnet, sodass Sie entweder den Typ oder die Ganzzahl verwenden können, um darauf zuzugreifen. Haben Sie schon versucht, einfach mit einer Ganzzahl darauf zuzugreifen?
quelle
.ordinal()
Methode zugreifen kann. (Umgekehrt verwendenBonusType.values()[i]
.) In dem oben genannten Beispiel stimmen die Indizes hier und die äußeren Werte jedoch nicht überein.Wirklich tolle Frage :-) Ich habe vor einiger Zeit eine ähnliche Lösung wie Mr.Ferguson verwendet. Unsere dekompilierte Aufzählung sieht folgendermaßen aus:
Dies zu sehen ist offensichtlich, warum
ordinal()
es instabil ist. Es ist dasi
insuper(s, i);
. Ich bin auch pessimistisch, dass Sie sich eine elegantere Lösung vorstellen können als die, die Sie bereits aufgezählt haben. Immerhin sind Aufzählungen Klassen wie alle Abschlussklassen.quelle
Der Vollständigkeit halber ist hier ein allgemeiner Ansatz zum Abrufen von Aufzählungswerten nach Index von jedem Aufzählungstyp. Meine Absicht war es, die Methode wie Enum.valueOf (Class, String) aussehen zu lassen . Zu Ihrer Information, ich habe diese Methode von hier kopiert .
Indexbezogene Probleme (die hier bereits ausführlich erörtert wurden) gelten weiterhin.
quelle
MyEnumType.values()
- keine statische Hilfsmethode erforderlich.quelle
Ich brauchte etwas anderes, weil ich einen generischen Ansatz verwenden wollte. Ich lese die Aufzählung von und zu Byte-Arrays. Hier komme ich auf:
Beispiel für Aufzählungen:
}}
quelle
Nur weil die akzeptierte Antwort nicht in sich geschlossen ist:
Support-Code:
Anwendungsbeispiel:
quelle
gegeben:
public enum BonusType {MONATLICH (0), JAHR (1), ONE_OFF (2)}
BonusType Bonus = JAHR;
System.out.println (Bonus.Ordinal () + ":" + Bonus)
Ausgabe: 1: JAHR
quelle
Wenn Sie eine Klasse haben Car
Und die Eigenschaft Farbe ist eine Klasse
Und Sie möchten Farbe in eine Aufzählung konvertieren
Einfach ein Verfahren in hinzufügen Farbklasse zu konvertieren Farbe in ColorEnum
und implementiert in ColorEnum die Methode getById ()
Jetzt können Sie eine classMap verwenden
quelle