Javaの列挙型(Enum)へ新しい要素を追加2 - Javassist
前回、Java の列挙型(Enum)へ新しい要素(識別子)を追加するためリフレクションを駆使しましたが、今回は Javassist を使ってもっと容易に実現する方法をご紹介します。
ソースは http://github.com/fits/try_samples/tree/master/blog/20140316/
はじめに
前回と同様の列挙型へ Second 要素を追加してみる事にします。
EType.java
enum EType {
First
}
Javassist を使った列挙型への要素追加
Javassist を使う場合、下記を実施して $VALUES
フィールドへ列挙型の要素を好きなように設定するだけです。
CtConstructor
のinsertAfter
メソッドを使って、静的初期化子へ$VALUES
を書き換える処理を挿入
なお、静的初期化子のための CtConstructor オブジェクトは CtClass オブジェクトの getClassInitializer
メソッドで取得します。
EnumAddValueJavassist.java
import javassist.*; public class EnumAddValueJavassist { public static void main(String... args) throws Exception { ClassPool pool = ClassPool.getDefault(); CtClass cc = pool.get("EType"); // 静的初期化子(static イニシャライザ)へ $VALUES を変更する処理を追加 cc.getClassInitializer().insertAfter("$VALUES = new EType[] { First, new EType(\"Second\", 1) };"); cc.toClass(); System.out.println(EType.valueOf("Second")); System.out.println("-----"); for (EType type : EType.values()) { System.out.println(type); } } }
実行すると下記のように Second の追加を確認できます。
ビルドと実行
> javac -cp .;javassist-3.18.1-GA.jar *.java > java -cp .;javassist-3.18.1-GA.jar EnumAddValueJavassist Second ----- First Second
実際は、下記のように Second クラスフィールドを追加しておいた方が望ましいかもしれません。
EnumAddValueJavassist2.java
import javassist.*; public class EnumAddValueJavassist2 { public static void main(String... args) throws Exception { ClassPool pool = ClassPool.getDefault(); CtClass cc = pool.get("EType"); // Second フィールドの追加 CtField second = CtField.make("public static final EType Second = new EType(\"Second\", 1);", cc); cc.addField(second); cc.getClassInitializer().insertAfter("$VALUES = new EType[] { First, Second };"); cc.toClass(); ・・・ } }