web-dev-qa-db-ja.com

Javaで実行時に列挙の要素を追加および削除できますか

実行時にJava?で列挙型の要素を追加および削除できますか?

たとえば、ファイルから列挙型のラベルとコンストラクター引数を読み取ることができますか?


@saua、それは本当に興味のないことをすることができるかどうかの問題です。おそらく [〜#〜] bcel [〜#〜] などを使用して、実行中のバイトコードを変更する適切な方法があることを望んでいました。私は この質問 でフォローアップしました.

実行時に安全にコンテンツを変更できるようにしたい場合、正しい答えは列挙型ではなく一意性を確保したコレクションを使用することだと確信しています。

55
brabster

いいえ、列挙型は完全な静的列挙型であると想定されています。

コンパイル時に、ある種の別のソースファイルからenum .Javaファイルを生成できます。このような.classファイルを作成することもできます。

場合によっては、標準値のセットが必要な場合がありますが、拡張は許可されます。これを行う通常の方法は、インターフェース用のinterfaceと、標準値用のenumを実装するinterfaceを用意することです。もちろん、switchへの参照しかない場合は、interfaceの機能を失います。

41

カーテンの後ろで、列挙型はプライベートコンストラクターと列挙型のパブリックな静的最終値の束を持つPOJOです(例については here を参照)。実際、Java5までは、この方法で独自の列挙を作成するのがベストプラクティスと見なされていました。Java5では、短縮形としてenumキーワードが導入されました。詳細については、 Enum <T> のソースを参照してください。

そのため、コンストラクターによって読み取られるか、またはコンストラクターに渡される、定数のパブリック静的最終配列を使用して独自の 'TypeSafeEnum'を作成しても問題ありません。

また、あなた自身に感謝し、equalshashCode、およびtoStringをオーバーライドし、可能であればvaluesメソッドを作成してください

問題は、このような動的列挙の使用方法です。ファイルから値「PI = 3.14」を読み取ってenum MathConstantsを作成してから、どこでもMathConstants.PIを使用することはできません。 ..

13
Yuval

(ユニットテストの目的で)このようなことをする必要があり、これに遭遇しました-EnumBuster: http://www.javaspecialists.eu/archive/Issue161.html

列挙値を追加、削除、復元できます。

Edit:私はこれを使い始めたばかりで、Java 1.5、私は現在にこだわっています:

  • 配列copyOf静的ヘルパーメソッドを追加します(たとえば、これらの1.6バージョンを使用します: http://www.docjar.com/html/api/Java/util/Arrays.Java.html
  • EnumBuster.undoStackをStack<Memento> に変更します
    • Undo()で、undoStack.poll()をundoStack.isEmpty()に変更しますか? null:undoStack.pop();
  • 文字列VALUES_FIELDは、これまでに試したJava 1.5列挙型の場合は「ENUM $ VALUES」である必要があります
9
Andy

私の若いキャリアの形成的なプロジェクト でこの問題に直面しました。

私が取ったアプローチは、列挙の値と名前を外部に保存することであり、最終目標は、可能な限り言語列挙に近いコードを記述できるようにすることでした。

私のソリューションを次のようにしたかったのです。

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));

そして、私はこのようなものになりました:

// 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"));

私の要件は、実行時に列挙にメンバーを追加できるようにする必要があることであったため、その機能も実装しました。

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

私はそれを動的列挙「パターン」と名付け、あなたは 元の設計改訂版 について読みました。

2つの違いは、改訂版は、実際にgrok OO and DDD。 。

6
moffdub

作成しようとしているENUMにプロパティを割り当てて、ロードされたプロパティファイルを使用して静的に構築することができます。大きなハックが、それは動作します:)

0
Eldelshell

実行時にソースからJavaクラスをロードできます。(JCI、BeanShellまたはJavaCompilerを使用)

これにより、必要に応じてEnum値を変更できます。

注:これは、これらの列挙型を参照するクラスを変更しないため、実際にはあまり有用ではありません。

0
Peter Lawrey