Этот вопрос касается интересного поведения 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 может использовать уже определенный анонимный внутренний класс для этих целей? Разве это не какое-то нарушение безопасности?