Этот вопрос касается интересного поведения 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:
private A(int a) {
}
Запустите программу еще раз. Прием:
a.TestNested$A(a.TestNested)
private a.TestNested$A(a.TestNested,int)
Это тоже нормально. Но теперь давайте модифицируем метод 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)
package local:
A(int a) {
}
Повторить программу снова (мы не удаляем строку с экземпляром A
creation!), вывод как в первый раз:
a.TestNested$A(a.TestNested)
a.TestNested$A(a.TestNested,int)
Вопросы:
1) Как это можно объяснить?
2) Что это за третий странный конструктор?
ОБНОВЛЕНИЕ: Исследование показано ниже.
1) Попробуем вызвать этот странный конструктор, используя отражение от другого класса.
Мы не сможем это сделать, потому что нет никакого способа создать экземпляр этого странного класса TestNested$1
.
2) Хорошо. Давайте сделаем трюк. Давайте добавим к классу TestNested
такое статическое поле:
public static Object object = new Object() {
public void print() {
System.out.println("sss");
}
};
Ну? Итак, теперь мы могли бы назвать этот третий странный конструктор из другого класса:
TestNested tn = new TestNested();
TestNested.A a = (TestNested.A)TestNested.A.class.getDeclaredConstructors()[2].newInstance(tn, 123, TestNested.object);
Извините, но я этого абсолютно не понимаю.
ОБНОВЛЕНИЕ-2: Дополнительные вопросы:
3) Почему Java использует специальный анонимный внутренний класс для типа аргумента для этого третьего синтетического конструктора? Почему не просто тип Object
, конструктора со специальным именем?
4). Какая Java может использовать уже определенный анонимный внутренний класс для этих целей? Разве это не какое-то нарушение безопасности?