Ich bin sehr vertraut mit C #, fange aber an, mehr in Java zu arbeiten. Ich hatte erwartet zu erfahren, dass Enums in Java im Grunde denen in C # entsprechen, aber anscheinend ist dies nicht der Fall. Anfangs war ich begeistert zu erfahren, dass Java-Enums mehrere Daten enthalten können, was sehr vorteilhaft erscheint ( http://docs.oracle.com/javase/tutorial/java/javaOO/enum.html ). Seitdem fehlen jedoch viele Funktionen, die in C # trivial sind, z. B. die Möglichkeit, einem Aufzählungselement auf einfache Weise einen bestimmten Wert zuzuweisen, und folglich die Möglichkeit, eine Ganzzahl ohne großen Aufwand in eine Aufzählung umzuwandeln ( dh Konvertieren Sie einen ganzzahligen Wert in eine übereinstimmende Java-Aufzählung .
Meine Frage lautet also: Gibt es einen Vorteil für Java-Aufzählungen gegenüber einer Klasse mit einer Reihe öffentlicher statischer Endfelder? Oder bietet es nur eine kompaktere Syntax?
EDIT: Lassen Sie mich klarer sein. Was ist der Vorteil von Java-Aufzählungen gegenüber einer Klasse mit einer Reihe öffentlicher statischer Endfelder desselben Typs ? Was ist beispielsweise im Planetenbeispiel unter dem ersten Link der Vorteil einer Aufzählung gegenüber einer Klasse mit diesen öffentlichen Konstanten:
public static final Planet MERCURY = new Planet(3.303e+23, 2.4397e6);
public static final Planet VENUS = new Planet(4.869e+24, 6.0518e6);
public static final Planet EARTH = new Planet(5.976e+24, 6.37814e6);
public static final Planet MARS = new Planet(6.421e+23, 3.3972e6);
public static final Planet JUPITER = new Planet(1.9e+27, 7.1492e7);
public static final Planet SATURN = new Planet(5.688e+26, 6.0268e7);
public static final Planet URANUS = new Planet(8.686e+25, 2.5559e7);
public static final Planet NEPTUNE = new Planet(1.024e+26, 2.4746e7);
Soweit ich das beurteilen kann, ist die Antwort von casablanca die einzige, die dies befriedigt.
public static final
Felder erwähnte , bei denen es sich möglicherweise um typisierte Werte handelt und nicht unbedingt umint
s.S
, so dass jetzt reden wir über sie wahrscheinlich in Funktionen vorbei, usw. Haben wir brauchen -saftey geben? Nun, nein, aber dann betrachten die meisten Leute C-Style-Typen von "Alles ist einvoid*
" guter Stil und es kann Fehler stoppen (insbesondere wenn mehr als ein Enum / String-Parameter übergeben wird!). Außerdem werden die Konstanten in ihren eigenen Namespace usw. eingefügt. Im Gegensatz dazu gibt es keinen wirklichen Vorteil, nur einfache Variablen zu haben.int
s gibt es keine Typensicherheit, da man jeden Wert übergeben kann. Typisierte Objekte unterscheiden sich dagegen in Bezug auf die Typensicherheit nicht von Aufzählungen.Antworten:
Technisch könnte man Enums tatsächlich als eine Klasse mit einer Reihe typisierter Konstanten betrachten, und auf diese Weise werden Enum-Konstanten tatsächlich intern implementiert. Die Verwendung von
enum
bietet Ihnen jedoch nützliche Methoden ( Enum javadoc ), die Sie sonst selbst implementieren müssten, zEnum.valueOf
.quelle
.values()
die Möglichkeit, die Werteliste zu durchlaufen.switch
Anweisungen zu verwendencase
Aussagen ohne Qualifikation.ordinal().
EnumSet
undEnumMap
Klassen.quelle
switch
Aussagen aufgenommen, die die ursprüngliche Motivation für die Verwendung einesEnum
überhaupt waren.Niemand erwähnte die Fähigkeit, sie in
switch
Aussagen zu verwenden; Ich werde das auch einwerfen.Auf diese Weise können beliebig komplexe Aufzählungen auf saubere Weise verwendet werden, ohne dass
instanceof
möglicherweise verwirrendeif
Sequenzen oder Nicht-String / Int-Schaltwerte verwendet werden. Das kanonische Beispiel ist eine Zustandsmaschine.quelle
Der Hauptvorteil ist die Typensicherheit. Mit einer Reihe von Konstanten kann jeder Wert desselben intrinsischen Typs verwendet werden, was zu Fehlern führt. Mit einer Aufzählung können nur die zutreffenden Werte verwendet werden.
Beispielsweise
vs.
quelle
setSize(null)
Ihr zweites Beispiel aufrufen , aber es wird wahrscheinlich viel früher als der Fehler des ersten Beispiels fehlschlagen.Es gibt weniger Verwirrung. Nehmen Sie
Font
zum Beispiel. Es hat einen Konstruktor, der den Namen desFont
gewünschten Konstruktors , seine Größe und seinen Stil (new Font(String, int, int)
) übernimmt . Bis heute kann ich mich nicht erinnern, ob Stil oder Größe an erster Stelle stehen. WennFont
ein benutzt hat ,enum
für alle seine verschiedenen Stile (PLAIN
,BOLD
,ITALIC
,BOLD_ITALIC
), würde der Konstruktor aussehenFont(String, Style, int)
, jede Verwirrung zu vermeiden. Leider gabenum
es bei derFont
Erstellung der Klasse keine s , und da Java die umgekehrte Kompatibilität beibehalten muss, werden wir immer von dieser Mehrdeutigkeit geplagt sein.Dies ist natürlich nur ein Argument für die Verwendung von
enum
anstelle vonpublic static final
Konstanten. Aufzählungen eignen sich auch perfekt für Singletons und die Implementierung von Standardverhalten, während eine spätere Anpassung möglich ist (dh das Strategiemuster ). Ein Beispiel für letzteres istjava.nio.file
‚sOpenOption
undStandardOpenOption
: wenn ein Entwickler seinen eigenen Nicht-Standard schaffen wollteOpenOption
, er konnte.quelle
enum
ohne varargs oder aSet
zu verwenden, um eine beliebige Anzahl von ihnen zu nehmen.interface Foo { public void bar(String baz); }
. Jemand macht eine Klasse, die aufruftbar
:someFoo.bar(baz = "hello");
. Ich ändere die Unterschrift vonFoo::bar
aufpublic void bar(String foobar)
. Jetzt muss die Person, die angerufensomeFoo
hat, ihren Code ändern, wenn sie weiterhin funktionieren soll.Hier gibt es viele gute Antworten, aber keine erwähnt, dass es hochoptimierte Implementierungen der Collection API-Klassen / -Schnittstellen speziell für Enums gibt :
Diese enumspezifischen Klassen akzeptieren nur
Enum
Instanzen (dieEnumMap
einzigen akzeptieren nurEnum
s als Schlüssel) und kehren, wann immer möglich, in ihrer Implementierung zu einer kompakten Darstellung und Bitmanipulation zurück.Was bedeutet das?
Wenn unser
Enum
Typ nicht mehr als 64 Elemente enthält (die meisten Beispiele aus dem wirklichen Leben sindEnum
dafür geeignet), speichern die Implementierungen die Elemente in einem einzigenlong
Wert. JedeEnum
betreffende Instanz wird mit einem Bit dieser 64-Bit-Länge verknüpftlong
. Das Hinzufügen eines Elements zu einemEnumSet
setzt einfach das richtige Bit auf 1, das Entfernen setzt nur das Bit auf 0. Das Testen, ob sich ein Element im Element befindet,Set
ist nur ein Bitmaskentest! Jetzt musst duEnum
s dafür lieben !quelle
What does this mean?
Abteilung gelernt . Ich wusste, dass es bei Größe 64 eine Kluft in der Implementierung gab, aber ich wusste nicht wirklich warumBeispiel:
Einschränkung von Java-Konstanten
1) Keine Typensicherheit : Erstens ist es nicht typsicher; Sie können int einen gültigen int-Wert zuweisen, z. B. 99, obwohl es keine Münze gibt, die diesen Wert darstellt.
2) Kein aussagekräftiger Druck : Der Druckwert einer dieser Konstanten gibt den numerischen Wert anstelle des aussagekräftigen Münznamens aus. Wenn Sie beispielsweise NICKLE drucken, wird "5" anstelle von "NICKLE" gedruckt.
3) Kein Namespace : Um auf die KonstanterencyDenom zuzugreifen, müssen wir dem Klassennamen, z. B. CurrencyDenom.PENNY, ein Präfix voranstellen, anstatt nur PENNY zu verwenden. Dies kann jedoch auch durch statischen Import in JDK 1.5 erreicht werden
Vorteil der Aufzählung
1) Aufzählungen in Java sind typsicher und haben einen eigenen Namensraum. Dies bedeutet, dass Ihre Aufzählung im folgenden Beispiel den Typ "Währung" hat und Sie keinen anderen Wert als den in Aufzählungskonstanten angegebenen zuweisen können.
Currency coin = Currency.PENNY; coin = 1; //compilation error
2) Enum in Java sind Referenztypen wie Klasse oder Schnittstelle. Sie können Konstruktoren, Methoden und Variablen in Java Enum definieren, wodurch es leistungsfähiger als Enum in C und C ++ ist, wie im nächsten Beispiel des Java Enum-Typs gezeigt.
3) Sie können zum Zeitpunkt der Erstellung Werte für Enum-Konstanten angeben, wie im folgenden Beispiel gezeigt: public enum Currency {PENNY (1), NICKLE (5), DIME (10), QUARTER (25)}; Damit dies funktioniert, müssen Sie eine Mitgliedsvariable und einen Konstruktor definieren, da PENNY (1) tatsächlich einen Konstruktor aufruft, der den int-Wert akzeptiert (siehe Beispiel unten).
Referenz: https://javarevisited.blogspot.com/2011/08/enum-in-java-example-tutorial.html
quelle
Der erste Vorteil von Aufzählungen ist, wie Sie bereits bemerkt haben, die Einfachheit der Syntax. Der Hauptpunkt von Aufzählungen besteht jedoch darin, einen bekannten Satz von Konstanten bereitzustellen, die standardmäßig einen Bereich bilden und dazu beitragen, eine umfassendere Codeanalyse durch Sicherheitsüberprüfungen für Typ und Wert durchzuführen.
Diese Attribute von Enums helfen sowohl einem Programmierer als auch einem Compiler. Angenommen, Sie sehen eine Funktion, die eine Ganzzahl akzeptiert. Was könnte diese ganze Zahl bedeuten? Welche Werte können Sie weitergeben? Sie wissen es nicht sofort. Wenn Sie jedoch eine Funktion sehen, die Enum akzeptiert, kennen Sie alle möglichen Werte, die Sie übergeben können, sehr gut.
Für den Compiler helfen Aufzählungen dabei, einen Wertebereich zu bestimmen. Wenn Sie Aufzählungsmitgliedern keine speziellen Werte zuweisen, handelt es sich um Bereiche von 0 und höher. Dies hilft, Fehler im Code durch Typensicherheitsprüfungen und mehr automatisch aufzuspüren. Beispielsweise kann der Compiler Sie warnen, dass Sie nicht alle möglichen Aufzählungswerte in Ihrer switch-Anweisung behandeln (dh wenn Sie keine
default
Groß- und Kleinschreibung haben und nur einen von N Aufzählungswerten behandeln). Es warnt Sie auch, wenn Sie eine beliebige Ganzzahl in eine Ganzzahl konvertieren, da der Wertebereich von enum kleiner als der von Ganzzahlen ist und dies wiederum Fehler in der Funktion auslösen kann, die eine Ganzzahl nicht wirklich akzeptiert. Außerdem wird das Generieren einer Sprungtabelle für den Schalter einfacher, wenn die Werte von 0 und höher sind.Dies gilt nicht nur für Java, sondern auch für andere Sprachen mit einer strengen Typprüfung. C, C ++, D, C # sind gute Beispiele.
quelle
Eine Aufzählung ist implizit endgültig. Bei privaten Konstruktoren sind alle ihre Werte vom gleichen Typ oder Untertyp. Sie können alle ihre Werte mit
values()
abrufen, ihrenname()
oderordinal()
Wert abrufen oder eine Aufzählung nach Nummer oder Name suchen.Sie können auch Unterklassen definieren (obwohl dies fiktiv endgültig ist, was Sie auf keine andere Weise tun können)
quelle
Aufzählung Vorteile:
"wie die Fähigkeit, einem Aufzählungselement leicht einen bestimmten Wert zuzuweisen"
"und folglich die Fähigkeit, eine Ganzzahl ohne großen Aufwand in eine Aufzählung umzuwandeln" Fügen Sie eine Methode hinzu, die int in eine Aufzählung umwandelt, die dies tut. Fügen Sie einfach die statische HashMap <Integer, EnumX> hinzu, die die Mapping- Java- Enumeration enthält .
Wenn Sie ord = VAL_200.ordinal () wirklich zurück in val_200 konvertieren möchten, verwenden Sie einfach: EnumX.values () [ord]
quelle
Ein weiterer wichtiger Unterschied besteht darin, dass der Java-Compiler
static final
Felder primitiver Typen und Zeichenfolgen als Literale behandelt. Dies bedeutet, dass diese Konstanten inline werden. Es ist ähnlich wieC/C++
#define
Präprozessor. Siehe diese SO-Frage . Dies ist bei Aufzählungen nicht der Fall.quelle
Sie erhalten eine Überprüfung der Kompilierungszeit gültiger Werte, wenn Sie eine Aufzählung verwenden. Schau dir diese Frage an.
quelle
Der größte Vorteil ist enum Singletons sind einfach zu schreiben und threadsicher:
und
beide sind ähnlich und es handhabte die Serialisierung selbst durch Implementierung
Mehr
quelle
Ich denke ein
enum
kann nicht seinfinal
, weil unter der Haube Compiler Unterklassen für jede generiertenum
Eintrag .Weitere Informationen Aus der Quelle
quelle
Es gibt viele Vorteile von Aufzählungen, die hier veröffentlicht werden, und ich erstelle gerade solche Aufzählungen, wie in der Frage gestellt. Aber ich habe eine Aufzählung mit 5-6 Feldern.
In solchen Fällen ist es sehr schwierig zu verstehen, welcher Wert zu welchem Feld gehört, wenn Sie Konstruktor und Augapfel sehen müssen, wenn Sie mehrere Felder in Aufzählungen haben.
Eine Klasse mit
static final
Konstanten und die Verwendung vonBuilder
Mustern zum Erstellen solcher Objekte macht sie lesbarer. Sie würden jedoch alle anderen Vorteile der Verwendung einer Aufzählung verlieren, wenn Sie sie benötigen. Ein Nachteil solcher Klassen ist, dass Sie diePlanet
Objekte manuell zumlist/set
von hinzufügen müssenPlanets.
Ich bevorzuge immer noch Enum gegenüber solchen Klassen, da dies
values()
praktisch ist und man nie weiß, ob man sie inswitch
oderEnumSet
oderEnumMap
in Zukunft verwenden muss :)quelle
Hauptgrund: Enums helfen Ihnen dabei, gut strukturierten Code zu schreiben, bei dem die semantische Bedeutung von Parametern beim Kompilieren klar und stark typisiert ist - aus all den Gründen, die andere Antworten angegeben haben.
Quid pro quo: In Java ist die Anzahl der Mitglieder einer Enum endgültig. Das ist normalerweise gut, da es die Sicherheit und das Testen verbessert, aber in einigen Situationen kann es ein Nachteil sein, beispielsweise wenn Sie vorhandenen Basiscode möglicherweise aus einer Bibliothek erweitern. Wenn sich dieselben Daten in einer Klasse mit statischen Feldern befinden, können Sie zur Laufzeit problemlos neue Instanzen dieser Klasse hinzufügen (möglicherweise müssen Sie auch Code schreiben, um diese zu einer Iterable hinzuzufügen, die Sie für diese Klasse haben). Dieses Verhalten von Enums kann jedoch geändert werden: Mithilfe von Reflection können Sie zur Laufzeit neue Mitglieder hinzufügen oder vorhandene Mitglieder ersetzen. Dies sollte jedoch wahrscheinlich nur in speziellen Situationen erfolgen, in denen es keine Alternative gibt: dh es handelt sich um eine hackige Lösung, die zu unerwarteten Problemen führen kann. siehe meine Antwort aufKann ich hinzufügen und Elemente der Aufzählung zur Laufzeit in Java entfernen .
quelle