匿名 class 的隐式构造函数,其 super class 是内部 Class
Implicit constructor in case of anonymous class whose super class is an Inner Class
考虑 JLS 中的以下文章:§15.9.5.1
当匿名 class 扩展内部 class - 那么对于匿名 class 的隐式构造函数 - 以下是关于隐式构造函数主体的规则:
The constructor body consists of an explicit constructor invocation (§8.8.7.1) of
the form o.super(...)
, where o
is the first formal parameter of the constructor,
and the actual arguments are the subsequent formal parameters of the constructor,
in the order they were declared.
以下是我们从这里了解到的-:
o
- 是 class 的实例 - 仅包含匿名 class. 的超级 class
- 当我们执行
o.super(...)
时,我们实际上是在调用封闭实例的超级 class。
考虑以下程序:
class A_ {
public A_(Boolean st){}
public class B_ {
public B_(Integer a){}
public class C_ {
public C_(String str){}
}
}
}
//when creating the anonymous constructor out of C - in a separate class:
public class ThisInAnonymousTesting {
public static void main(String[] args) {
A_.B_.C_ member =
new A_(true)
.new B_(23)
.new C_("Hey"){
};
}
}
现在当我们反编译 anonymous class 时,我们得到以下内容:
/**
=== Anonymous class Declaration
*/
import A_.B_;
import A_.B_.C_;
final class ThisInAnonymousTesting extends C_ {
// - Rule : the 1st argument is the class instance which is the enclosing instance
// of the Super class(C in this case) - ie B
ThisInAnonymousTesting(B_ x0, String str) {
x0.getClass();
//But the super() invocation here is for the super class - not for the enclosing instance
super(x0, str);
}
}
以下是我的问题:
- 为什么我们需要做
o.super(...)
- 当我们已经将 o
的初始化实例传递给匿名 class 构造函数时?
- ie
o
只有在它的超 classes 已经被调用时才会被创建。
- 构造函数中的
super()
调用显然是在尝试实例化 class C_
这很好 - 因为它是当前匿名 class 的超级 class.
- 在反编译版本中,
x0.getClass();
是什么意思——我的意思是为什么JVM需要做getClass()
?
不确定我对 o.super()
子句的解释是否正确?
我想你误解了o.super(...)
的意思。报表报表:
ExpressionName . [TypeArguments] super ( [ArgumentList] ) ;
Primary . [TypeArguments] super ( [ArgumentList] ) ;
是合格的超级class 构造函数调用,并在 JLS 的 explicit constructor invocations 部分中指定。
它不调用o
的超级class 构造函数。它调用封闭 class 的超级 class 构造函数,其中 o
作为 封闭实例 .
这是一个简单的例子:
class Outer {
public static final Outer OUTER1 = new Outer(1);
public static final Outer OUTER2 = new Outer(2);
public Outer(int x) {
this.x = x;
}
private final int x;
class Inner {
public Inner() {
System.out.println("In Inner constructor, the enclosing instance's field x is: " + x);
}
}
class InnerSubclass extends Inner {
public InnerSubclass() {
OUTER1.super();
System.out.println("In InnerSubclass constructor, the enclosing instance's field x is: " + x);
}
}
}
如果你Outer.OUTER2.new InnerSubclass();
,输出是:
In Inner constructor, the enclosing instance's field x is: 1
In InnerSubclass constructor, the enclosing instance's field x is: 2
OUTER1.super();
调用 Inner
的构造函数(OUTER1
是封闭对象),而不是 Outer
的构造函数。请注意,这与仅执行 super();
不同,因为这将使用 InnerSubclass
的封闭实例来调用 superclass 构造函数,无论它是什么,不一定 OUTER1
.
所以规范所说的是匿名构造函数将调用超级class'构造函数,封闭实例是匿名构造函数的第一个参数.匿名构造函数的第一个参数是什么?这是在几行之前说明的:
Otherwise, the first formal parameter of the anonymous constructor represents the value of the immediately enclosing instance of i
with respect to S
在你的情况下,new A_(true).new B_(23)
。
所以整体效果是这样的:
final class ThisInAnonymousTesting extends C_ {
ThisInAnonymousTesting(B_ o, String str) {
o.super(str); // recall that this calls C's constructor
}
}
// the callsite now becomes like this:
A_.B_.C_ member = new ThisInAnonymousTesting(new A_(true).new B_(23), "Hey");
注意:ThisInAnonymousTesting extends C_
无效 Java,但在字节码中是允许的。
在反编译代码中,你看到语法super(x0, str);
,因为字节码中没有内部classes。内部 classes 的封闭实例都只是转换为私有字段,并通过构造函数的第一个参数进行分配。因此,如果您查看字节码,o.super(...)
实际上只是 super(o, ...)
。
考虑:
class Outer {
class Inner {}
}
Outer$Inner.class 的字节码是:
class Outer$Inner {
final Outer this[=15=];
Outer$Inner(Outer);
Code:
0: aload_0
1: aload_1
2: putfield #1 // this.this[=15=] = Outer parameter (aka enclosing instance)
5: aload_0
6: invokespecial #7 // super()
9: return
}
考虑 JLS 中的以下文章:§15.9.5.1 当匿名 class 扩展内部 class - 那么对于匿名 class 的隐式构造函数 - 以下是关于隐式构造函数主体的规则:
The constructor body consists of an explicit constructor invocation (§8.8.7.1) of the form
o.super(...)
, whereo
is the first formal parameter of the constructor, and the actual arguments are the subsequent formal parameters of the constructor, in the order they were declared.
以下是我们从这里了解到的-:
o
- 是 class 的实例 - 仅包含匿名 class. 的超级 class
- 当我们执行
o.super(...)
时,我们实际上是在调用封闭实例的超级 class。
考虑以下程序:
class A_ {
public A_(Boolean st){}
public class B_ {
public B_(Integer a){}
public class C_ {
public C_(String str){}
}
}
}
//when creating the anonymous constructor out of C - in a separate class:
public class ThisInAnonymousTesting {
public static void main(String[] args) {
A_.B_.C_ member =
new A_(true)
.new B_(23)
.new C_("Hey"){
};
}
}
现在当我们反编译 anonymous class 时,我们得到以下内容:
/**
=== Anonymous class Declaration
*/
import A_.B_;
import A_.B_.C_;
final class ThisInAnonymousTesting extends C_ {
// - Rule : the 1st argument is the class instance which is the enclosing instance
// of the Super class(C in this case) - ie B
ThisInAnonymousTesting(B_ x0, String str) {
x0.getClass();
//But the super() invocation here is for the super class - not for the enclosing instance
super(x0, str);
}
}
以下是我的问题:
- 为什么我们需要做
o.super(...)
- 当我们已经将o
的初始化实例传递给匿名 class 构造函数时?- ie
o
只有在它的超 classes 已经被调用时才会被创建。 - 构造函数中的
super()
调用显然是在尝试实例化 classC_
这很好 - 因为它是当前匿名 class 的超级 class.
- ie
- 在反编译版本中,
x0.getClass();
是什么意思——我的意思是为什么JVM需要做getClass()
?
不确定我对 o.super()
子句的解释是否正确?
我想你误解了o.super(...)
的意思。报表报表:
ExpressionName . [TypeArguments] super ( [ArgumentList] ) ;
Primary . [TypeArguments] super ( [ArgumentList] ) ;
是合格的超级class 构造函数调用,并在 JLS 的 explicit constructor invocations 部分中指定。
它不调用o
的超级class 构造函数。它调用封闭 class 的超级 class 构造函数,其中 o
作为 封闭实例 .
这是一个简单的例子:
class Outer {
public static final Outer OUTER1 = new Outer(1);
public static final Outer OUTER2 = new Outer(2);
public Outer(int x) {
this.x = x;
}
private final int x;
class Inner {
public Inner() {
System.out.println("In Inner constructor, the enclosing instance's field x is: " + x);
}
}
class InnerSubclass extends Inner {
public InnerSubclass() {
OUTER1.super();
System.out.println("In InnerSubclass constructor, the enclosing instance's field x is: " + x);
}
}
}
如果你Outer.OUTER2.new InnerSubclass();
,输出是:
In Inner constructor, the enclosing instance's field x is: 1
In InnerSubclass constructor, the enclosing instance's field x is: 2
OUTER1.super();
调用 Inner
的构造函数(OUTER1
是封闭对象),而不是 Outer
的构造函数。请注意,这与仅执行 super();
不同,因为这将使用 InnerSubclass
的封闭实例来调用 superclass 构造函数,无论它是什么,不一定 OUTER1
.
所以规范所说的是匿名构造函数将调用超级class'构造函数,封闭实例是匿名构造函数的第一个参数.匿名构造函数的第一个参数是什么?这是在几行之前说明的:
Otherwise, the first formal parameter of the anonymous constructor represents the value of the immediately enclosing instance of
i
with respect toS
在你的情况下,new A_(true).new B_(23)
。
所以整体效果是这样的:
final class ThisInAnonymousTesting extends C_ {
ThisInAnonymousTesting(B_ o, String str) {
o.super(str); // recall that this calls C's constructor
}
}
// the callsite now becomes like this:
A_.B_.C_ member = new ThisInAnonymousTesting(new A_(true).new B_(23), "Hey");
注意:ThisInAnonymousTesting extends C_
无效 Java,但在字节码中是允许的。
在反编译代码中,你看到语法super(x0, str);
,因为字节码中没有内部classes。内部 classes 的封闭实例都只是转换为私有字段,并通过构造函数的第一个参数进行分配。因此,如果您查看字节码,o.super(...)
实际上只是 super(o, ...)
。
考虑:
class Outer {
class Inner {}
}
Outer$Inner.class 的字节码是:
class Outer$Inner {
final Outer this[=15=];
Outer$Inner(Outer);
Code:
0: aload_0
1: aload_1
2: putfield #1 // this.this[=15=] = Outer parameter (aka enclosing instance)
5: aload_0
6: invokespecial #7 // super()
9: return
}