代码之家  ›  专栏  ›  技术社区  ›  Daniel Widdis

我可以在Java中将常量从int改为byte而不破坏向后兼容性吗?

  •  8
  • Daniel Widdis  · 技术社区  · 6 年前

    change JNA 它在以前的版本中定义了一组常量 int

    int VER_EQUAL = 1;
    int VER_GREATER = 2;
    int VER_GREATER_EQUAL = 3;
    ... etc...
    

    interface 它们是自动生成的 static final .)

    这些常数用作 Condition VerSetConditionMask 函数,它需要 BYTE 参数,在JNA中映射到Java的 byte .

    int ,例如:。,

    byte VER_EQUAL = 1;
    byte VER_GREATER = 2;
    byte VER_GREATER_EQUAL = 3;
    ... etc...
    

    我不认为这一更改破坏了向后兼容性,因为任何使用这些常量的代码当前都必须至少有一个 字节 Object Integer Byte

    int 原始的

    2 回复  |  直到 6 年前
        1
  •  4
  •   Marco13    6 年前

    也许这是显而易见的。但也许不是。如果某个第三方用户获取了 int 值,并将其本地存储在 Integer byte 将在此处导致编译时错误:

    interface IntToByteWithInt
    {
        int VER_EQUAL = 1;
        int VER_GREATER = 2;
        int VER_GREATER_EQUAL = 3;
    }
    
    interface IntToByteWithByte
    {
        byte VER_EQUAL = 1;
        byte VER_GREATER = 2;
        byte VER_GREATER_EQUAL = 3;
    }
    
    public class IntToByte
    {
        public static void main(String[] args)
        {
            Integer a = IntToByteWithInt.VER_EQUAL;
    
            // Type mismatch: cannot convert from byte to Integer  
            Integer b = IntToByteWithByte.VER_EQUAL;
        }
    }
    

    除此之外,我认为至少应该提到 为了完整性。

    https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.25.2 )作为热门候选人,但没有设法造成错误。

        2
  •  3
  •   Jorn Vernee    6 年前

    此更改是否向后兼容?

    int . 例如:

    // defined in `MyClass`
    static final byte x = 10;
    
    public static void main(String[] args) throws Throwable {
        lookup().findStaticGetter(MyClass.class, "x", int.class); // old code
    }
    

    这就抛出了一个 NoSuchFieldException

    这也适用于访问字段的字节码编写API,例如 ASM :

    ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
    cw.visit(55, ACC_PUBLIC, "Test", null, "java/lang/Object", null);
    
    MethodVisitor mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "m", "()V", null, null);
    mv.visitCode();
    mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
    mv.visitFieldInsn(GETSTATIC, "MyClass", "x", "I"); // looking for int field
    mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(I)V", false);
    mv.visitInsn(RETURN);
    mv.visitMaxs(-1, -1);
    mv.visitEnd();
    
    Class<?> cls = lookup().defineClass(cw.toByteArray());
    cls.getMethod("m").invoke(null); // NoSuchFieldError
    

    上面的代码可以工作并打印 10 int ,但更改为后将失败 byte