【问题标题】:Java: instantiating an enum from a number using reflectionJava:使用反射从数字实例化枚举
【发布时间】:2012-03-07 12:10:16
【问题描述】:

信令协议经常使用具有明确定义的整数值的枚举类型。例如

public enum IpHdrProtocol {

TCP(6),
SCTP(132),
MPLS(137);
int Value;

IpProtocol(int value) {
    Value = value;
}

我正在尝试找到一种方法,仅使用 Enum Class 类型和实例的整数值将此类值反序列化为其对应的 Enumerated 类型。

如果这需要将静态 getEnumFromInt(int) 函数添加到每个枚举,那么如何定义这个“接口”,以便枚举作者可以确保他们的枚举可以序列化。

如何做到最好?

【问题讨论】:

    标签: java serialization binary-serialization


    【解决方案1】:

    不确定你想走多远,但这里有一些非常丑陋的代码,可以减少对枚举的侵入:

    public class Main {
    
        public enum IpHdrProtocol {
    
            TCP(6), SCTP(132), MPLS(137);
            int Value;
    
            IpHdrProtocol(int value) {
                Value = value;
            }
        }
    
        public static void main(String[] argv) throws NoSuchMethodException, IllegalArgumentException, InvocationTargetException,
                IllegalAccessException, SecurityException, NoSuchFieldException {
            System.err.println(getProtocol(6));
            System.err.println(getProtocol(132));
            System.err.println(getProtocol(137));
        }
    
        private static IpHdrProtocol getProtocol(int i) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException,
                SecurityException, NoSuchFieldException {
            Field f = IpHdrProtocol.class.getDeclaredField("Value");
            Method m = IpHdrProtocol.class.getMethod("values", null);
            Object[] invoke = (Object[]) m.invoke(null, null);
            for (Object o : invoke) {
                if (!f.isAccessible()) {
                    f.setAccessible(true);
                }
                if (((Integer) f.get(o)).intValue() == i) {
                    return (IpHdrProtocol) o;
                }
            }
            return null;
        }
    
        }
    

    【讨论】:

    • 这就是我想要的,并基于此实现了一个解决方案。实际上,我首先创建了一个反序列化器对象,该对象如您所示询问枚举类,但创建整数值和相应枚举实例值的映射。当我使用它来反序列化时,我只需在地图中查找即可。简单的。对特定枚举类的所有要求是它实现了一个支持 getIntValue() 的简单接口,这非常干净。
    【解决方案2】:

    如果你在谈论 Java 的内置序列化,Enums 已经实现了 Serializable 接口。只需序列化枚举值,就完成了。

    如果你想构建自己的序列化,你可以读写 int 值,并在反序列化时将对应的枚举值添加到你的枚举中:

    public static IpHdrProtocol valueOf(int value) {
      for (IpHdrProtocol p : values()) {
        if (p.Value == value) return p;
      }
      return null; // or throw exception
    }
    

    【讨论】:

    • 我想定义一个接口,以便枚举作者可以确保他们的枚举可以序列化,但静态函数不允许这样做。任何想法如何解决这个问题?
    【解决方案3】:

    首先,您的代码无法编译。解决方案如下(如果这是您想要的):

     public enum IpHdrProtocol {
    
        TCP(6),
        SCTP(132),
        MPLS(137);
        int Value;
    
        IpHdrProtocol(int value) {
            Value = value;
        }
    
        public static IpHdrProtocol getFromInt(int val) {
            for(IpHdrProtocol prot : values()) {
                if(prot.Value == val) {
                    return prot;
                }
            }
    
            return null;
        }
    }
    

    【讨论】:

    • getFromInt 应该是静态的吗?
    • 是的...所以你可以使用分类器而不是实例来调用方法(你想得到实例,你还没有)。
    • 我想定义一个接口,以便枚举作者可以确保他们的枚举可以序列化,但静态函数不允许这样做。任何想法如何解决这个问题?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-12
    • 1970-01-01
    • 1970-01-01
    • 2017-10-01
    • 1970-01-01
    • 2013-09-01
    相关资源
    最近更新 更多