3

次のような列挙型があります。

public enum SomeType {
    SOME_KEY (some-display-value-as-label);
    private String label;

    private SomeType(String label){
        this.label=label;
    }
    public String getLabel() {
        return label;
    }
    public void setLabel(String value) {
        this.label = value;
    }
}

今、私はGoogleリフレクションライブラリを使用しており、@makejsonのような注釈で上記の列挙型をマークするカスタム注釈を考え出しました.

@makejson アノテーションを使用してすべてのクラスのリフレクションを使用してアプリの起動時にスキャンし、これらの列挙型ごとに json オブジェクトを生成するという考え方です。

私がやろうとしているのは、スタートアップクラスです:

Reflections reflections = new Reflections("my.package.name");
Set<Class<?>> annotatedClasses = reflections.getTypesAnnotatedWith(MakeJson.class);
    for (Class<?> annotated : annotatedClasses) {
        if  (annotated.isEnum()) {
            MakeJson j = annotated.getAnnotation(MakeJson.class);
            Object[] constants = annotated.getEnumConstants();
            Method[] methods = annotated.getMethods();
            Method getValue = null;
            for (Method m : methods) {
                if ("valueOf".equals(m.getName())) {
                    getValue = m; //get Reference of valueOf method
                    break;
                }    
            }
            //List<Object> labels = Arrays.asList(m.invokem.getReturnType().isEnum()(annotated));
            for (Object constant : constants) {
                System.out.println(constant.toString());
                System.out.println(getValue.invoke(annotated,constant.toString()));
            }
        }
    }

このコードは次の例外で中断されます: Exception in thread "main" java.lang.IllegalArgumentException: wrong number of arguments

どんな助けでも大歓迎です。最終的な目的は、SomeType{SOME_KEY:"display-value"} の json オブジェクトを取得できるようにすることです。このため、リフレクションを使用して列挙型定数の値を取得できません。

4

3 に答える 3

2

私の以前の答えは間違っています。ここで起こっていることは、Enum クラスがpublic static valueOf(Class<?>, String)メソッドを定義していることです。Java コンパイラenum SomeTypeがクラスに変換すると、 が生成され、クラスに別のメソッドpublic class SomeType extends Enum<SomeType>が追加されます。したがって、クラスには「valueOf」と呼ばれる2 つのメソッドが作成されます。私には、あなたが実際に電話しているように見えますが、実際には電話するつもりでしたvalueOf(String)SomeTypevalueOf(Class, String)valueOf(String)

この問題を解決するには、ループを次のように変更します。

Method[] methods = annotated.getMethods();
Method getValue = null;
for (Method m : methods) {
    if ("valueOf".equals(m.getName())) {
        getValue = m; //get Reference of valueOf method
        break;
    }    
}

Method getValue = annotated.getMethod("valueOf", new Class<?>[]{String.class});

その後、問題を修正する必要があります。

于 2012-10-08T14:10:50.670 に答える
1

これはどうですか:

    Map tmp = new HashMap<SomeType, String>();
    for(SomeType type : SomeType.values()){
        tmp.put(type, type.getLabel());
    }
    String desiredJson = new Gson().toJson(tmp);
于 2013-04-28T22:24:13.070 に答える
0

@makejson アノテーションを変更して、必須であり、列挙型の SOME_KEY に関連付けられた説明を返すことができるメソッドに設定する必要がある label というフィールドを含めました。

注釈は次のようになります。

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MakeJson {
    String label();
}

そのため、enum 宣言の注釈は @makejson(label="getLabel") public enum SomeType { ... // 上記の質問と同じ } のようになります

次に、解析クラスで、アノテーションのメソッドからこのメソッドを取得し、正しい定数に対して呼び出すだけです。

    Reflections reflections = new Reflections("my.package.name");
    Set<Class<?>> annotatedClasses = reflections.getTypesAnnotatedWith(MakeJson.class);
    for (Class<?> annotated : annotatedClasses) {
        if  (annotated.isEnum()) {
            Jsonify j = annotated.getAnnotation(MakeJson.class);
            Object[] constants = annotated.getEnumConstants();
            Method m = annotated.getMethod(j.label()); // get the method name
            for (Object constant : constants) {
                System.out.println(constant.toString());
                System.out.println(m.invoke(constant));
                // construct json object here
            }
        }
    }

そのため、最後に、注釈を使用して実行時にこの情報をプラグインすることで、リフレクションを使用してメソッドを呼び出すことができないという問題を回避しました!

于 2012-10-08T14:40:50.340 に答える