zx_*_*ing 5 java binary-compatibility getter-setter
我正在阅读"实用API设计"并找到以下段落:
" 可以在JVM规范中找到优先使用字段的方法的另一个原因.您可以将方法从类移动到其超类之一,并且仍然保持二进制兼容性.因此,最初作为Dimension javax.swing引入的方法.JComponent.getPreferredSize(Dimension d)可以在新版本中删除并移动到Dimension java.awt.Component.getPreferredSize(Dimension d),因为JComponent是Component的子类.这样的更改确实发生在JDK 1.2中,并且这可以仅仅因为字段被方法封装而完成.对于字段不允许这样的操作.一旦在类中定义字段,它必须永远保持在那里以保持二进制兼容性,这是另一个原因保持字段私密 "
因为我同意使用getter/setter是更好的方法.但是我不明白为什么将公共字段移到父类会打破二进制兼容性?您仍然可以通过子类访问该字段,只要它在父级中是公共的.
\n\n一旦在类中定义了字段,它就必须永远保留在那里以保持二进制兼容性
\n
这将是非常令人惊讶的:
\nJava 语言规范 Java SE 7 版定义了非限定字段访问表达式的二进制名称,如下所示:
\n\n\n给定一个表示类 C 中字段访问的合法表达式,引用在(可能不同的)类或接口 D 中声明的名为 f 的非常量 (\xc2\xa713.4.9) 字段,我们定义字段引用的限定类型如下:
\n\n
\n- 如果表达式的形式为 Primary.f,则:\n
\n\n
\n- 如果 Primary 的编译时类型是交集类型 (\xc2\xa74.9) V1 & ... & Vn,则引用的限定类型为 V1。
\n- 否则,Primary 的编译时类型是引用的限定类型。
\n
(Java 1.5 的语言规范使用完全相同的措辞)
\n也就是说,字段访问表达式的二进制名称并不引用声明该字段的类型,仅引用我们用来访问该字段的主表达式的类型,因此无论该类型的哪个超类声明该字段,编译器都会需要将相同的字段引用发出到类文件中。
\n确实,当我刚才尝试从
\npackage p;\n\npublic class Super {\n\n}\n\npackage p;\n\npublic class Sub extends Super {\n public String message;\n\n @Override\n public String toString() {\n return message;\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n到
\npackage p;\n\npublic class Super {\n public String message;\n}\n\npackage p;\n\npublic class Sub extends Super {\n @Override\n public String toString() {\n return message;\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n无需重新编译
\npackage p;\n\npublic class Main {\n public static void main(String[] args) {\n Sub sub = new Sub();\n sub.message = "hello";\n System.out.println(sub);\n System.out.println(sub.message);\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n我仍然收到了输出
\nhello\nhello\nRun Code Online (Sandbox Code Playgroud)\n,不是LinkageError。
总而言之,这种说法对于 Java 7 来说并不正确。对于 JDK 1.4 或更早版本可能是正确的,JDK 1.4 或更早版本在 5 年多前就被宣布终止生命。不管怎样,也许你应该使用一本更好/更新的书?
\n