我正在阅读“实用API设计”并找到以下段落:
“在JVM规范中可以找到优先于字段的方法的另一个原因。您可以将方法从类移动到其超类之一并仍然保持二进制兼容性。所以,最初的方法作为Dimension javax.swing.JComponent引入.getPreferredSize(Dimension d)可以在新版本中删除并移动到Dimension java.awt.Component.getPreferredSize(Dimension d),因为JComponent是Component的子类。 A这样的改变确实发生在JDK 1.2中,这只能因为字段被方法封装而完成。字段不允许这样的操作。一旦在类中定义了字段,它就必须永远保留在那里保持二进制兼容性,这是保持字段私有的另一个原因 “
因为我同意使用getter / setter是更好的方法。但是我不明白为什么将公共字段移到父类会打破二进制兼容性?您仍然可以通过子类访问该字段,只要它在父级中是公共的。
答案 0 :(得分:3)
一旦在类中定义了一个字段,它就必须永远保留在那里以保持二进制兼容性
这将是非常令人惊讶的:
Java语言规范,Java SE 7 Edition,defines非限定字段访问表达式的二进制名称,如下所示:
给定一个表示C类中字段访问的合法表达式,引用在(可能是不同的)类或接口D中声明的名为f的非常量(第13.4.9节)字段,我们定义该字段的限定类型参考如下:
- 如果表达式的形式为Primary.f,则:
- 如果Primary的编译时类型是交集类型(§4.9)V1& ......& Vn,那么参考的合格类型是V1。
- 否则,Primary的编译时类型是引用的限定类型。
(Java 1.5的语言规范uses完全相同的措辞)
也就是说,字段访问表达式的二进制名称不是指声明字段的类型,而是指我们用于访问该字段的主表达式的类型,因此该类型的任何超类都声明该字段,编译器 required 将相同的字段引用发送到类文件中。
的确,当我刚才尝试从
演变的时候package p;
public class Super {
}
package p;
public class Sub extends Super {
public String message;
@Override
public String toString() {
return message;
}
}
到
package p;
public class Super {
public String message;
}
package p;
public class Sub extends Super {
@Override
public String toString() {
return message;
}
}
不重新编译
package p;
public class Main {
public static void main(String[] args) {
Sub sub = new Sub();
sub.message = "hello";
System.out.println(sub);
System.out.println(sub.message);
}
}
我仍然收到了
的输出hello
hello
,而不是LinkageError
。
总而言之,Java 7的这种主张并非如此。对于JDK 1.4或更早版本来说,这可能是正确的,它在5年前被宣布为报废。无论哪种方式,也许你应该使用更好/更新的书?
答案 1 :(得分:0)
如果我没记错的话,这本书解释了这个,但我目前还没有。我认为这是关于Java语言和类文件格式之间的细微差别(除了Java之外,其他语言也使用它)。
在书之前或之后检查一下书。询问您是否对该部分有更多疑问。