首页 > 解决方案 > 是否将枚举更改为分类中断二进制兼容

问题描述

如果我有这样的枚举:

public enum Test {
    TEST_VALUE(42), OTHER_TEST_VALUE(1337);

    private int val;
    Test(int val) {
        this.val = val;
    }

    public void increment() {
        val++;
    }

    public int getVal() {
        return val;
    }

如果我将其更改为以下内容,是否会破坏二进制兼容性:

public class Test {
    public static final Test TEST_VALUE = new Test(42);
    public static final Test OTHER_TEST_VALUE = new Test(1337);

    private int val;
    private final String oldEnumName;
    private Test(int val, String oldEnumName) {
        this.val = val;
        this.oldEnumName = oldEnumName;
    }

    public void increment() {
        val++;
    }

    public int getVal() {
        return val;
    }

    public String name() {
        return oldEnumName;
    }

   public static Test valueOf(String name)
   ...

并将所有其他枚举方法(如“值”和“序数”)添加到新类?那么其他的jar就可以不用重新编译就可以继续使用了吗?

标签: javaclassenumsbinary-compatibility

解决方案


我首先用这个枚举做了一些测试

public enum Test {
    TEST_VALUE(42), OTHER_TEST_VALUE(1337);

    private int val;
    Test(int val) {
        this.val = val;
    }

    public void increment() {
        val++;
    }

    public int getVal() {
        return val;
    }
}

然后用这个类来测试:

公共类枚举测试{

    public static void main(String[] args) {
        for (Test enumClass : Test.values()) {
            enumClass.increment();
        }
        System.out.println(Test.OTHER_TEST_VALUE.name() + Test.OTHER_TEST_VALUE.getVal());
        System.out.println(Test.TEST_VALUE.name() + Test.TEST_VALUE.getVal());
        System.out.println("For name : " + Test.valueOf("TEST_VALUE"));
        System.out.println(Test.OTHER_TEST_VALUE.ordinal());
    }
}

然后我编译了这些类,并复制了 EnumTesting 类以供将来参考。我将测试枚举更改为:

 public class Test {
    private static int globalOrdinal = 0;
    public static final Test TEST_VALUE = new Test(42, "TEST_VALUE");
    public static final Test OTHER_TEST_VALUE = new Test(1337, "OTHER_TEST_VALUE");

    private int val;
    private final String oldEnumName;
    private int ordinal;

    private Test(int val, String oldEnumName) {
        this.val = val;
        this.oldEnumName = oldEnumName;
        this.ordinal = globalOrdinal++;
    }

    public void increment() {
        val++;
    }

    public int getVal() {
        return val;
    }

    public String name() {
        return oldEnumName;
    }

    @Override
    public String toString() {
        return oldEnumName;
    }

    public int ordinal() {
        return this.ordinal;
    }

    public static final Test[] VALUES = new Test[] {TEST_VALUE, OTHER_TEST_VALUE};

    public static Test[] values() {
        return VALUES;
    }

    public static Test valueOf(String oldEnumName) {
        for (Test enumClass : VALUES) {
            if (enumClass.oldEnumName.equals(oldEnumName))
            {
                return enumClass;
            }
        }
        throw new IllegalArgumentException();
    }
}

并重新编译一切。EnumTesting 类的字节码在重新编译后保持不变。所以这确实是一个二进制兼容的变化。


推荐阅读