Java:使用反射从数字中实例化枚举

时间:2012-03-07 12:10:17

标签: java serialization binary-serialization

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

public enum IpHdrProtocol {

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

IpProtocol(int value) {
    Value = value;
}

我试图找到一种方法,只使用Enum类类型和实例的整数值将这样的值反序列化为相应的Enumerated类型。

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

如何才能做到最好?

3 个答案:

答案 0 :(得分: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;
    }

    }

答案 1 :(得分:1)

如果您正在谈论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
}

答案 2 :(得分:0)

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

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