在Java反射中将int转换为Enum

时间:2014-06-26 09:55:19

标签: java parsing generics reflection enums

这看起来可能类似于其他几个问题,但到目前为止我还没有找到解决方案..

我使用反射将我的JSON解析为不同的类,并且通过编写特定于类的解析代码省去了很多工作,所有的int,long,字符串和日历等都很容易处理,但现在我发现自己处于Enum特定铸件的地狱

类似的东西:

else if (field.getType().isAssignableFrom(TransactionType.class)){
    field.set(representation, TransactionType.fromInt(Integer.parseInt(value, 10)));
}

问题是枚举在JSON中存储为整数,当我不知道它具体是什么时,我找不到通用的方法来解析或将这些整数转换回枚举,而且我有相当多的枚举,所以70%的解析代码现在专门用于检查枚举类型......

有没有一种方法,只给出field.getType()。isEnum()== true,将int值解析为该字段的枚举类型

枚举类型声明为:

public static enum TransactionType{
    cashback(0),deposit(1),withdraw(2),invitation(3);
    public int code;
    TransactionType(int code){
        this.code = code;
    }
    private final static TransactionType[] map = TransactionType.values();
    public static TransactionType fromInt(int n){
        return map[n];
    }
}

JSON可能有点复杂,但枚举相关字段的格式为:

{transactionType: 1, someOtherEnumType: 0}

3 个答案:

答案 0 :(得分:3)

根据所提供的信息,我将如何解决这个问题。使用一个辅助方法,该方法位于枚举类型之外,可以转换任何实现某个接口的枚举类型。


public static interface Codeable {
    public int getCode();
}
public static enum TransactionType implements Codeable {
    cashback(0),deposit(1),withdraw(2),invitation(3);

    public int code; 
    TransactionType(int code) { 
        this.code = code; 
    }

    @Override
    public int getCode() {
        return code;
    }
}
public static <T extends Codeable> T fromCodeToEnum(int code, Class<T> clazz) {
    for(T t : clazz.getEnumConstants()) {
        if(t.getCode() == code) {
            return t;
        }
    }
    return null;
}
public static void main(String [] args) {
    TransactionType type = fromCodeToEnum(1, TransactionType.class);
    System.out.println(type); // deposit
}

编辑或者您当然可以获取枚举值并迭代它们。这可以放在你想要的任何地方。

public static TransactionType findTransactionTypeByCode(int code) {

    for(TransactionType t : TransactionType.values()) {
        if(t.getCode() == code) {
            return t;
        }
    }
    return null;
}

答案 1 :(得分:2)

Java不支持从literal到value的隐式转换。

然后Java中的枚举方法ordinal(),返回int值。

  

返回此枚举常量的序号(它在枚举声明中的位置,其中&gt;初始常量的序数为零)。

不安全的解决方案

if(field.getType().isEnum()) {
  Object itemInstance = field.getType().getEnumConstants()[ordinal];
}

我们不建议将它作为API的一部分设计。

本案例的建议是在枚举的定义中定义。

enum MyEnum {
 ITEM(1);

 private final int index;

 MyEnum(int index) {
   this.index;
 }
}

然后你应该实现额外的逻辑来序列化和反序列化,例如基于默认方法的接口。

interface SerializableEnum<E extends Enum<E>> {

        Class<E> getType();


        default E valueOf(int ordinal) {
            return getType().getEnumConstants()[ordinal];
        }
    }

请注意,最佳解决方案是序列化枚举,而不是通过数字,而是通过其名称。

答案 2 :(得分:1)

Class.getEnumConstants()就是您所需要的。

Class<?> cls = field.getType();
if (cls.isEnum()) {
  field.set(representation, 
    cls.getEnumConstants()[Integer.parseInt(value, 10)]);
}