class OuterA {
class InnerA {
}
}
class SubclassC extends OuterA.InnerA {
SubclassC(OuterA outerRef) {
outerRef.super();
}
}
class XYZ {
public static void main(String[] args) {
new SubclassC(new OuterA());
}
}
在上面的代码中
OuterA
对象引用传递给。SubclassC
构造函数以进行编译?InnerA
对象引用不需要传递给SubclassC
构造函数?答案 0 :(得分:6)
为什么我需要将OuterA对象引用传递给SubclassC构造函数才能编译.java文件?
因为SubclassC
扩展了 InnerA
类的定义。同时,InnerA
类绑定到OuterA
(即InnerA
的所有实例都将绑定到OuterA
的相应实例。因此,要获取SubclassC
的实例,您需要OuterA
的实例。
为什么不需要将InnerA对象引用传递给SubclassC构造函数?
因为在创建SubclassC
时,首先会创建其超类的实例,即会有InnerA
的实例。您实际上可以将SubclassC
视为特殊类InnerA
。
答案 1 :(得分:4)
- 为什么我需要将OuterA对象引用传递给SubclassC构造函数以便编译.java文件?
醇>
因为InnerA
是OuterA
的内部类。这意味着OuterA.InnerA
类型的对象或其任何子类型(例如SubclassC
)只能存在于封闭类(在本例中为OuterA
)实例的上下文中。
这称为合格的超类构造函数调用。来自JLS:
合格的超类构造函数调用以Primary表达式开头。它们允许子类构造函数显式指定新创建的对象关于直接超类(第8.1.3节)的直接封闭实例。 当超类是内部类时,这可能是必要的。
如果您不需要将SubclassC
实例链接到已存在的OuterA
实例,则可以在OuterA
构造函数中创建新的SuperclassC
对象:
static class SubclassC extends OuterA.InnerA {
SubclassC() {
new OuterA().super();
}
}
- 为什么不需要将InnerA对象引用传递给SubclassC构造函数?
醇>
由于SubclassC
延伸OuterA.InnerA
,执行outerRef.super()
时,您正在调用OuterA.InnerA
构造函数。要查看是这种情况,请考虑以下代码:
public class Example {
static class OuterA {
OuterA() {
System.out.println("Call OuterA constructor");
}
class InnerA {
InnerA() {
System.out.println("Call InnerA constructor");
}
}
}
static class SubclassC extends OuterA.InnerA {
SubclassC(OuterA outerRef) {
outerRef.super();
System.out.println("Call SuperclassC constructor");
}
}
public static void main(String[] args) {
OuterA outerA = new OuterA();
System.out.println("Before new SuperclassC()");
new SubclassC(outerA);
}
}
输出:
Call OuterA constructor
Before new SuperclassC()
Call InnerA constructor
Call SuperclassC constructor
答案 2 :(得分:2)
1.Why do I need to pass OuterA object reference to SubclassC constructor for the .java file to compile?
因为您需要知道该类实例的名称才能调用该函数,因为SubclassC
扩展了类OuterA.InnerA
:SubclassC extends OuterA.InnerA {
SubclassC(OuterA outerRef) {
outerRef.super();
第二
2. Why is InnerA object reference not required to be passed to SubclassC constructor?
因为Innera在你创建对象new SubclassC(new OuterA());
时正在调用的Outtera内部(即你不需要创建单独的对象,因为InnerA
位于OuterA
内在这种情况下,创建OuterA
就足够了
答案 3 :(得分:2)
我们期望在构造函数运行之前发生两件事:
Object
如果未使用extends
)构造函数应该已经运行 Java通过在构造函数的开头自动放置super()
调用来强制实施第一条规则。请注意,没有任何内容可以作为父实例:当您执行new File()
时,您不需要提供Object
- 所以没有您需要的谜InnerA
1}}在构建SubclassC
时。
当在另一个类的词法范围中定义非静态类时,它可以访问封闭对象的字段:
class Outer {
int val;
class Inner {
int val() {
return val; // <-- we can access val, it's in scope
}
}
}
所以很明显我们需要一个链接。以下是通常创建链接的方式:
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner(); // baroque, I admit
同样的事情发生在扩展Inner
的类的第一行:
class InnerExtended extends Outer.Inner {
public InnerExtended(Outer outer) {
outer.super(); // <-- calls Outer.Inner ctor
}
}
即使看到相似之处也不容易:
super(); // plain superclass ctor call
outer.new Inner(); // instantiation of inner class
outer.super(); // super() call in class extending inner