Java 使用反射实例化内部类时实例化Exception。为什么?

Java 使用反射实例化内部类时实例化Exception。为什么?,java,generics,reflection,factory,inner-classes,Java,Generics,Reflection,Factory,Inner Classes,我不能创建B对象,但为什么 public class AFactory { public int currentRange; private abstract class A { protected final Object range = currentRange; public int congreteRange = 28; } public class B extends A { public int

我不能创建B对象,但为什么

public class AFactory {

    public int currentRange;

    private abstract class A {
        protected final Object range = currentRange;

        public int congreteRange = 28;
    }

    public class B extends A {
        public int congreteRange = 42;
    }

    synchronized A createNew(Class<? extends A> clazz) throws Exception {
        // EDIT: there is accessible default constructor
        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);
    }
}

您无法创建,因为您将
clazz
定义为扩展
B
的类型,
A
不扩展
B
-相反(
B
扩展
A

您应该将
createNew
签名更改为:

synchronized A createNew(Class<? extends A> clazz) throws Exception

synchronized A createNew(Class问题是您试图实例化一个内部类,您只能在外部类的实例上访问它。内部类的构造函数获取封闭类的一个隐式隐藏的
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
}

使用非
静态
内部类-最终代码:

如果不想使它们成为静态的,那么必须首先创建封闭类的实例,并将其传递给内部类的构造函数。要获取内部类的构造函数,可以使用方法

现在,您必须修改factory方法,将
构造函数
作为参数。修改代码如下:

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));
    }
}
公共类工厂{
公共范围;
私有抽象类A{
受保护的最终对象范围=当前范围;
}
公共类B扩展了A{
公共int CongreterRange=42;
}

已同步createNew(构造函数将类和变量更改为静态

public class AFactory {

public static int currentRange;

private static abstract class A {
    protected final Object range = 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);
}
}
公共类工厂{
公共静态范围;
私有静态抽象类A{
受保护的最终对象范围=当前范围;
}
公共静态类B扩展了{
公共int CongreterRange=42;
}

已同步createNew(ClassMore over
clazz.newInstance()
调用了两次。我更改了问题,出现了相同的异常。但我已经有了外部类
new AFactory()的实例
!@SotiriosDelimanolis。现在是静态字段。我已经更改了它。@Rohit Jain-你确定吗?我认为可以创建内部类的实例。它是公共的,并且有一个
工厂
()要附加到的实例。@SotiriosDelimanolis hm,我们可以将currentRange设置为静态,只要createNew被同步,它就可以工作。@PeterRader是的,您已经有了,但您只能访问该实例上的方法。内部类的构造函数将enlclosing实例作为隐式参数。将它们设置为所有静态-默认答案:D?我想禁止任何其他类生成A的实例。@PeterRader:“我想禁止任何其他类生成A的实例。”这意味着什么?因为B是公共的,即使B是一个非静态的内部类,任何人都可以创建它的实例,只要他们有一个
AFactory
的实例。你是对的,我想禁止任何其他类在没有
AFactory
实例的情况下创建a的实例。
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));
    }
}
public class AFactory {

public static int currentRange;

private static abstract class A {
    protected final Object range = 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);
}
}