理解二进制兼容的关键是要理解延迟绑定(late binding)。延迟绑定是指java直到运行时才检查类、域、方法的名称,而不象c/c++的编译器那样在编译期间就清除了类、域、方法的名称,代之以偏移量数值――这是java二进制兼容得以发挥作用的关键。
由于采用了延迟绑定技术,方法、域、类的名称直到运行时才解析,意味着只要域、方法等的名称(以及类型)一样,类的主体可以任意替换――当然,这是一种简化的说法,还有其他一些规则制约java类的二进制兼容性,例如访问属性(private、public等)以及是否为abstract(如果一个方法是抽象的,那么它肯定是不可直接调用的)等,但延迟绑定机制无疑是二进制兼容的核心所在。
只有掌握了二进制兼容的规则,才能在改写类的时候保证其他类不受到影响。下面再来看一个例子,frodomail和sammail是两个email程序:
abstract class message implements classifiable { }
class emailmessage extends message {
public boolean isjunk() { return false; }
}
interface classifiable {
boolean isjunk();
}
class frodomail {
public static void main(string a[]) {
classifiable m = new emailmessage();
system.out.println(m.isjunk());
}
}
class sammail {
public static void main(string a[]) {
emailmessage m = new emailmessage();
system.out.println(m.isjunk());
}
}
如果我们重新实现message,不再让它实现classifiable接口,sammail仍能正常运行,但frodomail会抛出异常:java.lang.incompatibleclasschangeerror at frodomail.main。这是因为sammail不要求emailmessage是一个classifiable,但frodomail却要求emailmessage是一个classifiable,编译frodomail得到的二进制.class文件引用了classifiable这个接口名称。符合classifiable接口定义的方法仍旧存在,但该类却根本没有提到classifiable这个接口。
闽公网安备 35060202000074号