Kann ich Aufzählungselemente zur Laufzeit in Java hinzufügen und entfernen

Lesezeit: 7 Minuten

Kann ich Aufzahlungselemente zur Laufzeit in Java hinzufugen und entfernen
brabster

Ist es möglich, zur Laufzeit Elemente aus einer Aufzählung in Java hinzuzufügen und zu entfernen?

Könnte ich beispielsweise die Labels und Konstruktorargumente einer Aufzählung aus einer Datei einlesen?


@saua, es ist nur die Frage, ob man das wirklich aus Interesse machen kann. Ich hatte gehofft, es gäbe eine nette Möglichkeit, den laufenden Bytecode zu ändern, vielleicht mit BCEL oder so. Ich bin dieser Frage auch nachgegangen, weil mir klar wurde, dass ich nicht ganz sicher war, wann eine Aufzählung verwendet werden sollte.

Ich bin ziemlich davon überzeugt, dass die richtige Antwort darin besteht, anstelle einer Aufzählung eine Sammlung zu verwenden, die die Eindeutigkeit gewährleistet, wenn ich den Inhalt sicher zur Laufzeit ändern möchte.

  • Wenn Sie dies wollen, missbrauchen Sie sie normalerweise. Können Sie uns sagen, wofür Sie das brauchen?

    – Joachim Sauer

    26. Januar 09 um 0:05 Uhr

  • Meine Antwort wurde mit einer HashMap hinter den Kulissen implementiert, sodass Sie die Eindeutigkeit sicherstellen können.

    – moffdub

    27. Januar 09 um 11:44 Uhr

  • FWIW, es hilft beim Testen von Standardfällen für das Einschalten von Enumerationen.

    – Daniel C. Sobral

    27. Juli 16 um 6:31 Uhr

Kann ich Aufzahlungselemente zur Laufzeit in Java hinzufugen und entfernen
Tom Hawtin – Tackline

Nein, Aufzählungen sollen eine vollständige statische Aufzählung sein.

Zur Kompilierzeit möchten Sie vielleicht Ihre Enum-Java-Datei aus irgendeiner anderen Quelldatei generieren. Sie könnten sogar eine .class-Datei wie diese erstellen.

In einigen Fällen möchten Sie möglicherweise einen Satz von Standardwerten, lassen aber eine Erweiterung zu. Der übliche Weg, dies zu tun, ist ein interface für die Schnittstelle und ein enum der das umsetzt interface für die Standardwerte. Natürlich verliert man die Fähigkeit dazu switch wenn Sie nur einen Verweis auf die haben interface.

  • Würden Sie wissen, wo ich ein gutes Beispiel für eine Aufzählung finden kann, die eine solche Schnittstelle implementiert? Ich werde an einer solchen Funktionalität interessiert sein.

    – megalucio

    19. Oktober 17 um 15:10 Uhr


  • @megalucio Ich glaube, ich dachte an java.nio.file.StandardOpenOption docs.oracle.com/javase/8/docs/api/java/nio/file/… aber es gibt auch java.net.StandardProtocolFamily und javax.tools.StandardLocation.

    – Tom Hawtin – Angelleine

    20. Oktober 17 um 21:54 Uhr

  • Vielen Dank . Ich werde mir das mal anschauen.

    – megalucio

    23. Oktober 17 um 16:51 Uhr

Kann ich Aufzahlungselemente zur Laufzeit in Java hinzufugen und entfernen
Yuval

Hinter dem Vorhang sind Enumerationen POJOs mit einem privaten Konstruktor und einer Reihe öffentlicher statischer Endwerte des Typs der Enumeration (siehe Hier zum Beispiel). Tatsächlich galt es bis Java5 als bewährte Methode, Ihre eigene Aufzählung auf diese Weise zu erstellen, und Java5 führte die enum Schlüsselwort als Kurzform. Siehe die Quelle für Enum um mehr zu lernen.

Es sollte also kein Problem sein, ein eigenes ‘TypeSafeEnum’ mit einem öffentlichen statischen endgültigen Array von Konstanten zu schreiben, die vom Konstruktor gelesen oder an ihn übergeben werden.

Tun Sie sich auch selbst einen Gefallen und überschreiben Sie equals, hashCode und toStringund wenn möglich erstellen Sie eine values Methode

Die Frage ist, wie man eine solche dynamische Aufzählung verwendet … Sie können den Wert “PI = 3.14” nicht aus einer zu erstellenden Datei lesen enum MathConstants und dann weitermachen und verwenden MathConstants.PI wo immer Sie wollen…

  • Schreiben Sie niemals ein öffentliches statisches nicht leeres Array-Feld – sie sind nicht konstant.

    – Tom Hawtin – Angelleine

    25. Januar 09 um 22:37 Uhr

  • Ist das wahr? Da die Instanz am Ende der Referenz unveränderlich ist, bin ich mir nicht sicher, wie Sie sie tatsächlich ändern könnten … sind es nur gekreuzte Drähte, ob es sich um eine Array-Instanz handelt oder nicht?

    – Brabster

    26. Januar 09 um 20:13 Uhr

  • Sammlungen und Arrays sind beide veränderliche Objekte (und “Objekte”). Ein “endgültiges” Array zu haben bedeutet nur, dass Sie die Größe des Arrays nicht ändern oder anderweitig neu zuweisen werden, aber Sie können trotzdem Werte ersetzen, die bereits in seine Grenzen passen.

    – Ed Brannin

    1. September 2009 um 14:57 Uhr

1643906829 872 Kann ich Aufzahlungselemente zur Laufzeit in Java hinzufugen und entfernen
Andy

Ich musste so etwas tun (für Unit-Testzwecke) und bin auf das hier gestoßen – den EnumBuster:
http://www.javaspecialists.eu/archive/Issue161.html

Es ermöglicht das Hinzufügen, Entfernen und Wiederherstellen von Enum-Werten.

Bearbeiten: Ich habe gerade erst damit begonnen und festgestellt, dass für Java 1.5 einige geringfügige Änderungen erforderlich sind, an denen ich derzeit festhalte:

  • Fügen Sie Array copyOf statische Hilfsmethoden hinzu (nehmen Sie z. B. diese 1.6-Versionen: http://www.docjar.com/html/api/java/util/Arrays.java.html)
  • Ändern Sie EnumBuster.undoStack in einen Stack<Memento>
    • Ändern Sie in undo() undoStack.poll() in undoStack.isEmpty() ? null : undoStack.pop();
  • Die Zeichenfolge VALUES_FIELD muss für die Java 1.5-Enumerationen, die ich bisher ausprobiert habe, “ENUM$VALUES” sein

  • Bei modernen Versionen von Java müssen Sie einige Dinge ändern, wie im überarbeiteten Artikel dokumentiert: javaspecialists.eu/archive/…

    – blalasaadri

    1. Dezember 2020 um 13:04 Uhr

Ich stand vor diesem Problem auf der prägendes Projekt meiner jungen Karriere.

Mein Ansatz bestand darin, die Werte und Namen der Aufzählung extern zu speichern, und das Endziel bestand darin, Code schreiben zu können, der einer Sprachenaufzählung so ähnlich wie möglich war.

Ich wollte, dass meine Lösung so aussieht:

enum HatType
{
    BASEBALL,
    BRIMLESS,
    INDIANA_JONES
}

HatType mine = HatType.BASEBALL;

// prints "BASEBALL"
System.out.println(mine.toString());

// prints true
System.out.println(mine.equals(HatType.BASEBALL));

Und ich endete mit etwas in der Art:

// in a file somewhere:
// 1 --> BASEBALL
// 2 --> BRIMLESS
// 3 --> INDIANA_JONES

HatDynamicEnum hats = HatEnumRepository.retrieve();

HatEnumValue mine = hats.valueOf("BASEBALL");

// prints "BASEBALL"
System.out.println(mine.toString());

// prints true
System.out.println(mine.equals(hats.valueOf("BASEBALL"));

Da meine Anforderungen darin bestanden, dass Mitglieder zur Laufzeit zur Aufzählung hinzugefügt werden können, habe ich diese Funktionalität ebenfalls implementiert:

hats.addEnum("BATTING_PRACTICE");

HatEnumRepository.storeEnum(hats);

hats = HatEnumRepository.retrieve();

HatEnumValue justArrived = hats.valueOf("BATTING_PRACTICE");
// file now reads:
// 1 --> BASEBALL
// 2 --> BRIMLESS
// 3 --> INDIANA_JONES
// 4 --> BATTING_PRACTICE

Ich habe es das “Muster” der dynamischen Aufzählung genannt, und Sie haben darüber gelesen das ursprüngliche Design und seine überarbeitete Auflage.

Der Unterschied zwischen den beiden besteht darin, dass die überarbeitete Ausgabe entworfen wurde, nachdem ich wirklich angefangen hatte, OO und DDD zu groken. Das erste, das ich entworfen habe, als ich noch nominell prozedurale DDD geschrieben habe, nicht weniger unter Zeitdruck.

Sie können eine Java-Klasse zur Laufzeit aus der Quelle laden. (Mit JCI, BeanShell oder JavaCompiler)

Auf diese Weise können Sie die Enum-Werte nach Belieben ändern.

Hinweis: Dies würde keine Klassen ändern, die sich auf diese Aufzählungen beziehen, daher ist dies in der Realität möglicherweise nicht sehr nützlich.

Ein weit verbreitetes Arbeitsbeispiel ist das modifizierte Minecraft. Siehe EnumHelper.addEnum()-Methoden auf GitHub

Beachten Sie dies jedoch in seltenen Situationen Die praktische Erfahrung hat gezeigt, dass das Hinzufügen von Enum-Mitgliedern zu einigen Problemen mit dem JVM-Optimierer führen kann. Die genauen Probleme können je nach JVM variieren. Aber im Großen und Ganzen scheint der Optimierer davon auszugehen, dass einige interne Felder eines Enums, insbesondere die Größe des Enums, davon ausgehen .values() Array, wird sich nicht ändern. Sehen Themendiskussion. Die empfohlene Lösung gibt es nicht zu machen .values() ein Hotspot für den Optimierer. Wenn also zur Laufzeit Mitglieder einer Enum hinzugefügt werden, sollte dies einmal und nur einmal erfolgen, wenn die Anwendung initialisiert wird, und dann das Ergebnis von .values() sollte zwischengespeichert werden, um zu vermeiden, dass es zu einem Hotspot wird.

Die Funktionsweise des Optimierers und die Art und Weise, wie er Hotspots erkennt, ist unklar und kann zwischen verschiedenen JVMs und verschiedenen Builds der JVM variieren. Wenn Sie das Risiko dieser Art von Problemen im Produktionscode nicht eingehen möchten, ändern Sie Enums nicht zur Laufzeit.

1643906830 358 Kann ich Aufzahlungselemente zur Laufzeit in Java hinzufugen und entfernen
Eldelshell

Sie könnten versuchen, der ENUM, die Sie erstellen möchten, Eigenschaften zuzuweisen und sie mithilfe einer geladenen Eigenschaftendatei statisch zu erstellen. Großer Hack, aber es funktioniert 🙂

.

757680cookie-checkKann ich Aufzählungselemente zur Laufzeit in Java hinzufügen und entfernen

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

Privacy policy