[英]Implicit constructor in case of anonymous class whose super class is an Inner Class
考慮 JLS 中的以下文章:§15.9.5.1 當匿名 class 擴展內部 class - 然后對於匿名 class 的隱式構造函數的隱式構造函數:以下是關於主體構造函數的規則:
構造函數體由
o.super(...)
形式的顯式構造函數調用(第 8.8.7.1 節)組成,其中o
是構造函數的第一個形參,實際的 arguments 是構造函數的后續形參,按照它們被聲明的順序。
以下是我們從中了解到的——:
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"){
};
}
}
現在,當我們反編譯匿名 class時,我們得到以下信息:
/**
=== Anonymous class Declaration
*/
import A_.B_;
import A_.B_.C_;
final class ThisInAnonymousTesting$1 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$1(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 構造函數時?
o
僅在它的超類已經被調用時才被創建。super()
調用顯然試圖實例化 class C_
這很好 - 因為它是當前匿名 class 的超級 class。x0.getClass();
- 我的意思是為什么 JVM 需要做getClass()
? 不確定我對o.super()
子句的解釋是否正確?
我認為您誤解了o.super(...)
的含義。 forms的聲明:
ExpressionName . [TypeArguments] super ( [ArgumentList] ) ;
Primary . [TypeArguments] super ( [ArgumentList] ) ;
是限定的超類構造函數調用,並在 JLS 的顯式構造函數調用部分中指定。
它不調用o
的超類構造函數。 它調用封閉類的超類構造函數,其中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();
,output為:
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
的封閉實例來調用超類構造函數,無論它可能是什么,不一定是OUTER1
。
所以規范的真正含義是匿名構造函數將調用超類的構造函數,封閉實例是匿名構造函數的第一個參數。 匿名構造函數的第一個參數是什么? 這在之前的幾行中已經說明:
否則,匿名構造函數的第一個形參表示
i
相對於S
的直接封閉實例的值
在您的情況下, new A_(true).new B_(23)
。
所以這個的整體效果是這樣的:
final class ThisInAnonymousTesting$1 extends C_ {
ThisInAnonymousTesting$1(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$1(new A_(true).new B_(23), "Hey");
注意: ThisInAnonymousTesting$1 extends C_
是無效的 Java,但在字節碼中是允許的。
在反編譯的代碼中,您會看到語法super(x0, str);
因為字節碼中沒有內部類。 內部類的封閉實例都只是轉換為私有字段,並通過構造函數的第一個參數進行分配。 因此,如果您查看字節碼, o.super(...)
實際上只是super(o, ...)
。
考慮:
class Outer {
class Inner {}
}
Outer$Inner.class 的字節碼是:
class Outer$Inner {
final Outer this$0;
Outer$Inner(Outer);
Code:
0: aload_0
1: aload_1
2: putfield #1 // this.this$0 = Outer parameter (aka enclosing instance)
5: aload_0
6: invokespecial #7 // super()
9: return
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.