Этот вопрос вы пытаетесь создать экземпляр внутренний класс, который вы можете только доступ на экземпляр внешнего класса. Конструктор внутренних классов принимает скрытый скрытый класс instance
. Вы можете увидеть его, анализируя байт-код этого простого класса:
public class Demo {
class Test {
}
}
Теперь, компилировать код:
javac Demo.java
Это создаст два файла класса:
Demo.class
Demo$Test.class
Запускаем следующую команду для получения кода байта Demo$Test.class
:
javap -c . Demo$Test
Вы получите следующий результат:
class Demo$Test {
final Demo this$0;
Demo$Test(Demo);
Code:
0: aload_0
1: aload_1
2: putfield #1 // Field this$0:LDemo;
5: aload_0
6: invokespecial #2 // Method java/lang/Object."<init>":
()V
9: return
}
Итак, вы видите, конструктор класса? В качестве параметра требуется Demo
. Таким образом, нет конструктора 0-arg.
Однако, если вы сделаете свои внутренние классы static
, это сработает, потому что тогда вам не нужен какой-либо экземпляр класса, для вызова внутреннего конструктора классов.
С static
внутренних классов - Альтернатива:
public class AFactory {
public static int currentRange;
private static abstract class A {
protected final Object range = AFactory.currentRange;
}
public static class B extends A {
public int congreteRange = 42;
}
synchronized A createNew(Class<? extends B> clazz) throws Exception {
currentRange = clazz.newInstance().congreteRange;
return clazz.newInstance();
}
public static void main(String[] args) throws Exception {
AFactory factory = new AFactory();
System.out.println(factory.createNew(B.class).range);
}
}
С непредставленных static
внутренних классов - Финальный код:
Если вы не хотите, чтобы сделать их static
, то вам нужно будет сначала создать экземпляр окружающего класса. И передайте его конструктору внутреннего класса. Чтобы получить конструктор внутреннего класса, вы можете использовать метод Class#getDeclaredConstructor
.
Теперь вам нужно будет изменить свой заводский метод, чтобы принять параметр Constructor
. Измените код следующим образом:
public class AFactory {
public int currentRange;
private abstract class A {
protected final Object range = currentRange;
}
public class B extends A {
public int congreteRange = 42;
}
synchronized A createNew(Constructor<? extends A> ctor) throws Exception {
// Pass `this` as argument to constructor.
// `this` is reference to current enclosing instance
return ctor.newInstance(this);
}
public static void main(String[] args) throws Exception {
AFactory factory = new AFactory();
// Get constructor of the class with `AFactory` as parameter
Class<B> bClazz = B.class;
Constructor<B> ctor = bClazz.getDeclaredConstructor(AFactory.class);
System.out.println(factory.createNew(ctor));
}
}
Но у меня уже есть экземпляр внешнего класса 'new AFactory()'! –
@SotiriosDelimanolis. Это статическое поле. Я изменил его. –
@ Rohit Jain - Ты уверен? Я думаю, что нормально создавать экземпляр внутреннего класса. Он является общедоступным и имеет экземпляр 'AFactory'() для прикрепления. – Avi