我对此进行了测试。
不幸的是,当方法的返回类型更改为原始类型的子类型时,调用时会出现NoSuchMethodError 异常。
因此,进行此更改不是二进制向后兼容的。
这太糟糕了……
测试设置
test
├── c
├── c_int
│ └── C.java
├── c_num
│ └── C.java
└── Test.java
test/c_num/C.java:
package test.c;
public class C {
public Number f() {
System.out.println("f Number");
return 0.0;
}
}
test/c_int/C.java:
package test.c;
public class C {
public Integer f() {
System.out.println("f Integer");
return 1;
}
}
test/Test.java:
package test;
import test.c.C;
public class Test {
public static void main(String[] args) throws Exception {
C b = new C();
Number n = b.f();
System.out.println(n);
}
}
测试
编译两个返回类型不同的C类:
$ javac test/c_int/C.java
$ javac test/c_num/C.java
针对C 编译Test,返回类型为Number:
$ cp test/c_num/C.class test/c/
$ javac test/Test.java
针对C 运行Test,返回类型为Number:
$ java test.Test
f Number
0.0
对C 运行Test,返回类型为Integer,无需重新编译Test:
$ cp test/c_int/C.class test/c/
$ java test.Test
Exception in thread "main" java.lang.NoSuchMethodError: 'java.lang.Number test.c.C.f()'
at test.Test.main(Test.java:8)
字节码
我们还可以在字节码中看到f的方法调用包含了方法的返回类型:
$ javap -c test/Test.class
Compiled from "Test.java"
public class test.Test {
public static void main(java.lang.String[]);
Code:
...
9: invokevirtual #4 // Method test/c/C.f:()Ljava/lang/Number;
...
}
Eclipse 文档
Eclipse 基金会维护一个名为Evolving Java-based APIs 的文档。
文档说明了二进制兼容性:
Evolving API classes - API methods and constructors
....
Change result type (including void) - Breaks compatibility
这不会对仅缩小返回类型的更改进行例外处理。对返回类型的所有更改都会破坏二进制兼容性。