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

现在我正在使用谷歌反射库并提出了一个自定义注释,我在上面用@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()));
            }
        }
    }

此代码因以下异常而中断:线程“main”java.lang.IllegalArgumentException 中的异常:参数数量错误

任何帮助将不胜感激。最终目标是能够获得 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(String)方法添加到你的SomeType类中。因此,您最终会在您的类中使用两个名为“valueOf”的方法。在我看来,您实际上是在打电话valueOf(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 注释以包含一个名为 label 的字段,该字段是必需的,并且应该设置为可以返回与枚举中的 SOME_KEY 关联的描述的方法。

注释如下所示:

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

所以枚举声明处的注释看起来像 @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 回答