据我了解源兼容性以及如何轻松展示会破坏源兼容性的示例(更改方法的名称,删除方法等),我遇到一些问题,看看二进制兼容性如何在实践中被打破。有没有人有一个简单的例子来保存源兼容性会导致二进制兼容性问题,即不需要更改代码但重新编译是必要的?
答案 0 :(得分:2)
如果库中方法的签名以兼容的方式更改,那么一个示例(并且这是 no 表示唯一的一个)。例如,考虑:
// Library.java v1
public class Library {
public static void print(String foo) {
System.out.println(foo);
}
}
// Client.java v1
public class Client {
public static void main(String[] args) {
Library.print("hello");
}
}
编译并运行:
$ javac Client.java Library.java
$ java Client
hello
现在更改Library.java - 注意foo
参数的类型:
// Library.java v2
public class Library {
public static void print(Object foo) {
System.out.println(foo);
}
}
只需重新编译Library.java
并尝试重新运行Client
:
$ javac Library.java
$ java Client
Exception in thread "main" java.lang.NoSuchMethodError: Library.print(Ljava/lang/String;)V
at Client.main(Client.java:3)
答案 1 :(得分:1)
首先需要了解兼容性。
源兼容性 - 如果可以使用新版本的代码(库或api)编译程序,则程序与新版本源兼容
二进制兼容性 - 如果程序可以与该代码链接而无需重新编译,则程序与新版本的代码二进制兼容
以下链接有“源兼容但二进制不兼容”的更多示例
阅读http://praitheesh.blogspot.com.au/2014/09/compatibility-and-api-evolution-in-java.html了解更多详情。
答案 2 :(得分:0)
如果导入带有字符串常量的接口。 (Java中的反模式。)
然后导入类复制常量表中的常量,并立即使用这些常量。然后缺少对接口的导入依赖性。
当接口中常量的字符串值发生更改时,编译器不会看到它需要重新编译将保留使用旧值的类 - 因为不再导入接口。
运行没有被破坏,但行为是 - 错误的值。
答案 3 :(得分:0)
我遇到的一个例子:
public class Class1 {
public void do() {
System.out.println("do!");
}
}
客户端部分:
public class Class2 {
public void callDo() {
Class1 c = new Class1();
c.do();
}
}
现在你改变了do方法的回报:
public class Class1 {
public String do() {
System.out.println("do!");
return "done!";
}
}
如果在没有重新编译的情况下运行客户端代码,则会收到NoSuchMethodError异常,因为方法签名已更改。