【问题标题】:Converting int to Enum in Java reflection在 Java 反射中将 int 转换为 Enum
【发布时间】:2014-06-26 09:55:19
【问题描述】:

这可能看起来与其他一些问题相似,但到目前为止我还没有找到解决方案..

我正在使用反射将我的 JSON 解析为不同的类,它为我节省了编写特定于类的解析代码的大量精力,所有的整数、长整数、字符串和日历等都很容易处理,但现在我发现自己陷入了 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}

【问题讨论】:

  • 我对 int 值与枚举的关系有点困惑。您能否举一个简短的示例说明如何知道示例枚举的 int 值是什么? EG:你在用ordinal()吗?
  • hummm,以问题中的TransactionType为例:public static enum TransactionType{ cashback(0),deposit(1),withdraw(2),invitation(3);public int code; TransactionType(int code){ this.code = code; }}
  • 还有一个fromtInt函数:private final static TransactionType[] map = TransactionType.values(); public static TransactionType fromInt(int n){ return map[n]; }

标签: java parsing generics reflection enums


【解决方案1】:

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


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

【讨论】:

  • 尝试了一些不同的解决方案,你的工作就像魅力一样,按照你的方法我也能够解决其他一些问题:D 谢谢
【解决方案2】:

Java 不支持从字面量到值的隐式转换。

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

返回此枚举常量的序数(它在其枚举声明中的位置,>initial 常量被分配零序数)。

一个不安全的解决方案

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

为什么不向我们推荐它,因为它被设计为 API 的一部分。

这种情况的建议是在 enum 的定义中定义。

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

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

【讨论】:

  • 嗯是的,这几乎就是我声明我的枚举的方式,问题是该字段是枚举,它可能是 TransactionType 或 MyEnum 或任何 Enum,现在我有了那个字段,我该如何转换int 到实际的枚举类型作为字段是什么?
  • 如果你有一个字段实例,你可以调用getType()。这将是 TransactionType、MyEnum 或其他。然后你使用那​​个类来获取带有常量的数组。
  • 刚刚在问题中添加了一些代码..是的,我发现我实际上可以简单地使用 getEnumConstants..谢谢!
  • @MatthewYang,奇怪的是你接受了只回复了我写的同一件事的答案。
  • 对不起...那是误点击,我不接受
【解决方案3】:

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

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

【讨论】:

  • 不敢相信我没有找到这个 ealier..非常感谢
  • @MatthewYang 此方法确实依赖于定义枚举值的顺序,而不是“代码”变量。
猜你喜欢
  • 2018-12-13
  • 1970-01-01
  • 2014-07-20
  • 2017-08-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-01
相关资源
最近更新 更多