Java 使用反射实例化内部类时实例化Exception。为什么?
我不能创建B对象,但为什么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
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 overclazz.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);
}
}