この質問は、Java の興味深い動作に関するものです。状況によっては、ネストされたクラスの追加の (デフォルトではない) コンストラクターが生成されます。
この質問は、Javaがその奇妙なコンストラクターで生成する奇妙な匿名クラスに関するものでもあります。
次のコードを検討してください。
package a;
import java.lang.reflect.Constructor;
public class TestNested {
class A {
A() {
}
A(int a) {
}
}
public static void main(String[] args) {
Class<A> aClass = A.class;
for (Constructor c : aClass.getDeclaredConstructors()) {
System.out.println(c);
}
}
}
これにより、次が出力されます。
a.TestNested$A(a.TestNested)
a.TestNested$A(a.TestNested,int)
Ok。次に、コンストラクターをA(int a)
非公開にします。
private A(int a) {
}
プログラムを再度実行します。受け取る:
a.TestNested$A(a.TestNested)
private a.TestNested$A(a.TestNested,int)
こちらもOKです。しかし今、main()
そのような方法でメソッドを変更しましょう(クラスA
作成の新しいインスタンスの追加):
public static void main(String[] args) {
Class<A> aClass = A.class;
for (Constructor c : aClass.getDeclaredConstructors()) {
System.out.println(c);
}
A a = new TestNested().new A(123); // new line of code
}
入力は次のようになります。
a.TestNested$A(a.TestNested)
private a.TestNested$A(a.TestNested,int)
a.TestNested$A(a.TestNested,int,a.TestNested$1)
それは何ですか: a.TestNested$A(a.TestNested,int,a.TestNested$1) <<<---??
わかりました、再びコンストラクタA(int a)
パッケージをローカルにしましょう:
A(int a) {
}
プログラムを再度実行します (作成のインスタンスを含む行は削除しませんA
!)、出力は最初と同じです:
a.TestNested$A(a.TestNested)
a.TestNested$A(a.TestNested,int)
質問:
1)これはどのように説明できますか?
2)この 3 番目の奇妙なコンストラクターは何ですか?
更新:以下に示す調査。
1) 他のクラスからのリフレクションを使用して、この奇妙なコンストラクターを呼び出してみましょう。TestNested$1
その奇妙なクラスのインスタンスを作成する方法がないため、これを行うことはできません。
2) わかりました。トリックをしましょう。TestNested
そのような静的フィールドをクラスに追加しましょう:
public static Object object = new Object() {
public void print() {
System.out.println("sss");
}
};
良い?わかりました。これで、この 3 番目の奇妙なコンストラクターを別のクラスから呼び出すことができます。
TestNested tn = new TestNested();
TestNested.A a = (TestNested.A)TestNested.A.class.getDeclaredConstructors()[2].newInstance(tn, 123, TestNested.object);
申し訳ありませんが、まったくわかりません。
UPDATE-2:追加の質問は次のとおりです。
3) Java がこの 3 番目の合成コンストラクターの引数の型に特別な匿名内部クラスを使用するのはなぜですか? Object
特別な名前を持つコンストラクターのタイプだけではないのはなぜですか?
4)これらの目的で、既に定義されている匿名内部クラスを使用できる Java はどれですか? これはある種のセキュリティ違反ではありませんか?