JDK 1.7 vs JDK 1.6 内部类继承差异
Posted
技术标签:
【中文标题】JDK 1.7 vs JDK 1.6 内部类继承差异【英文标题】:JDK 1.7 vs JDK 1.6 inner classes inheritance difference 【发布时间】:2016-03-07 20:07:53 【问题描述】:我正在解决一些 Java 难题,偶然发现了这个:
public class Outer
class Inner1 extends Outer
class Inner2 extends Inner1
在使用 javac 1.6.0_45
编译此代码时,正如预期的那样,我得到了这个错误:
Outer.java:8: cannot reference this before supertype constructor has been called
class Inner2 extends Inner1
^
这是因为编译器为 Inner2
类生成了具有类似代码的默认构造函数,这解释了上面的错误:
Inner2 ()
this.super();
现在很明显,因为在 Java 1.6.0_45、JLS 8.8.7.1 中确实无法做到这一点(我猜到了):
构造函数体中的显式构造函数调用语句可以 不引用在中声明的任何实例变量或实例方法 此类或任何超类,或在任何表达式中使用 this 或 super; 否则,会发生编译时错误。
请参阅(Odd situation for "cannot reference this before supertype constructor has been called" 中的accepted answer)
但如果我尝试用javac 1.7.0_79
编译它 - 没关系!
问题来了 - Java 1.7 中发生了什么变化,这段代码现在是正确的吗?
提前致谢!
【问题讨论】:
@EJP 你检查了那个accepted answer,因为那个看起来确实相关 @EJP,另外,this.super()
不等同于super()
。如果您尝试在非内部非嵌套类中执行此操作,您将收到 [JLS1.6 8.8.7.1] 之前的编译时错误。 If S is not an inner class, or if the declaration of S occurs in a static context, no immediately enclosing instance of i with respect to S exists. A compiletime error occurs if the superclass constructor invocation is a qualified superclass constructor invocation.
类似于 [JLS1.7 8.8.7.1]。
【参考方案1】:
似乎在 Java 错误跟踪器上讨论了与错误 JDK-6708938: Synthetic super-constructor call should never use 'this' as a qualifier 相同的问题。
另外,我认为您最好看看上一期的其他相关问题,例如JDK-4903103: Can't compile subclasses of inner classes 。
注意两个错误的固定版本。
结果见Maintenance Review of JSR 901 (Java Language Specification) for Java SE 7。
来自The Java Language Specification Third Edition
否则,
S
是内部成员类(第 8.5 节)。这是一个编译时 如果S
不是词法封闭类的成员,或者不是 超类或其超接口。让O
成为最里面的词汇S
是其成员的封闭类,让 n 为整数,例如O
是C
的第 n 个词法封闭类。立即i
相对于S
的封闭实例在词法上是第 n 个 this 的封闭实例。
以及来自 Java SE 7 的 JSR 901(Java 语言规范)的维护审查(完整版,第 242 页,蓝色文本)或The Java Language Specification, Java SE 7 Edition 中的相同内容(就在第 8.8.8 节之前)
否则,S 是内部成员类(第 8.5 节)。
令 O 为 S 的最内层词法封闭类,令 n 为整数,使得 O 为 C 的第 n 个词法封闭类。
立即封闭 i 相对于 S 的实例是第 n 个词法封闭 这个例子。
所以你可以看到编译时错误的部分已经消失了。
【讨论】:
感谢您的回复!现在我有一个线索,肯定已经改变了!但我不明白具体是什么。在整个 8.8 部分中,我没有发现JLS SE 7
和 JLS Third Edition
之间有任何重大区别。
@ar4ers 我已经添加了与问题相关的这两个版本的 JSL 的差异。
非常感谢您的补充说明!现在我明白了其中的区别。而且,您可能还知道,在哪里可以找到特定的行为定义(如合成构造函数创建)?我可以猜到 - 它是 JVMS,我猜对了吗?
@ar4ers 我猜你可以在 JLS(更具体的编译器)和 JVMS(更具体的运行时)中找到它。如果你想阅读它们,你可以在Java Language and Virtual Machine Specifications page找到它们【参考方案2】:
我怀疑这与 invoke dynamic 有关,它是在 java 1.7 中添加的,用于为 java 8 中的 lambda 做准备。
【讨论】:
我首先检查过它。可悲的是,事实并非如此。我在所有三个.class
文件、Outer.class
、Outer$Inner1.class
和Outer$Inner2.class
上都使用了javap -c
。没有invokedynamic
的证据,只有invokespecial
和putfield
。我目前正在调查这个问题,但还没有结果。以上是关于JDK 1.7 vs JDK 1.6 内部类继承差异的主要内容,如果未能解决你的问题,请参考以下文章
为啥 Maven 使用 JDK 1.6 但我的 java -version 是 1.7