ysh*_*vit 21 java language-design
警告#1:这实际上是一个潜在的两个部分:首先,私有内部类的构造函数是否具有形式参数?如果是的话,为什么JLS说不呢?如果不是,怎么/为什么不呢?
警告#2:这个问题不适合猜测.我只是在寻找权威的答案.
默认构造函数在JLS 8.8.9中定义,它声明(部分):
默认构造函数没有形式参数,除非在非私有内部成员类中,默认构造函数隐式声明一个形式参数,表示该类的直接封闭实例(§8.8.1,§15.9.2,§15.9.3) ).
(重点补充)
"非私有"位对我来说似乎很奇怪:为了让内部类访问其封闭类中定义的字段,它需要对该实例的引用.无论内部类是否为私有,这都应该是相同的.
事实上,javac似乎与我一致,与规范相矛盾.如果我编译这个:
public class Ctors {
private class MyInner {
}
}
Run Code Online (Sandbox Code Playgroud)
...然后运行javap -c -private,然后我们看到一个带有单个形式参数的构造函数,用于封闭类的实例:
$ javap -c -private Ctors\$MyInner
Compiled from "Ctors.java"
class Ctors$MyInner {
final Ctors this$0;
private Ctors$MyInner(Ctors);
Code:
0: aload_0
1: aload_1
2: putfield #1 // Field this$0:LCtors;
5: aload_0
6: invokespecial #2 // Method java/lang/Object."<init>":()V
9: return
}
Run Code Online (Sandbox Code Playgroud)
作为参考,这是在Oracle JDK 1.8.0_05上.
所以JLS说私有内部成员类的默认构造函数没有正式参数,但javac/javap说它有一个.(我对最自然的工作方式的理解也会说它应该有一个,对于那些值得的东西.)哪个是正确的,为什么JLS明确排除私人内部类?
实现和规范之间存在差异.
在我看来,"除了"JLS声明
...... 除了非私人内部成员班......
措辞不好.
这意味着,编译器不需要隐式声明一个表示类的直接封闭实例的形式参数......但它可以.
为什么非私有内部成员类需要隐式形式参数?
来自JLS 8.8.1:
成员类可能是由编译器发出的,该编译器与类实例创建表达式的编译器不同.因此,创建表达式的编译器必须有一种标准方法将引用(表示立即封闭的实例)传递给成员类的构造函数
例如,如果我用第一个编译器编译这个内部类:
package p1;
public class Ctors {
public class MyInner {
}
}
Run Code Online (Sandbox Code Playgroud)
如果我想用另一个编译器编译这个子类:
package p2;
import p1.Ctors;
public class SubCtors {
public SubCtors() {
new Ctors();
}
}
Run Code Online (Sandbox Code Playgroud)
第二个编译器必须能够使用带有形参的默认构造函数.在这种情况下,带有SubCtors实例的封闭类的实例.
为什么非私有内部成员类不需要隐式形式参数?
因为非私有内部成员类总是由编译它的同一编译器访问.如您所示,无论类可见性如何,javac都会生成相同的构造函数,但不需要.另一种编译器实现可以自由选择另一种方式.
JLS 8.8.1还有另外一点,它在同一条线上
在本地类(不在静态上下文中)或匿名类的类实例创建表达式中,§15.9.2指定了本地/匿名类的直接封闭实例.本地/匿名类必须由与类实例创建表达式相同的编译器发出.该编译器可以表示它所希望的直接封闭的实例.Java编程语言不需要在local/anonymous类的构造函数中隐式声明参数.
| 归档时间: |
|
| 查看次数: |
1034 次 |
| 最近记录: |