2013-07-05 70 views
51

我尝试实例下面的Java代码中定义的内部类:如何在Java中使用反射来实例化内部类?

public class Mother { 
     public class Child { 
      public void doStuff() { 
       // ... 
      } 
     } 
} 

当我试图让孩子的一个实例是这样

​​

我得到这个异常:

java.lang.InstantiationException: com.mycompany.Mother$Child 
    at java.lang.Class.newInstance0(Class.java:340) 
    at java.lang.Class.newInstance(Class.java:308) 
    ... 

我错过了什么?

+2

呃,你的内部类不是静态的......这是故意的吗?可能来自C#背景? ;) – fge

+1

感谢您提出“静态”的想法!事实上,使用静态嵌套类而不是内部类可以让我的生活更轻松。 – Stephan

+2

问题是,如果内部类未声明为静态,则此类的实例取决于外部类的实例的存在;这与C#不同,默认情况下,所有内部类都是“静态”的,并且可以在没有父实例的情况下实例化。 – fge

回答

100

还有一个额外的“隐藏”参数,它是封闭类的实例。您需要使用Class.getDeclaredConstructor来获取构造函数,然后提供封闭类的实例作为参数。例如:

// All exception handling omitted! 
Class<?> enclosingClass = Class.forName("com.mycompany.Mother"); 
Object enclosingInstance = enclosingClass.newInstance(); 

Class<?> innerClass = Class.forName("com.mycompany.Mother$Child"); 
Constructor<?> ctor = innerClass.getDeclaredConstructor(enclosingClass); 

Object innerInstance = ctor.newInstance(enclosingInstance); 

编辑:另外,如果嵌套类实际上并不需要参考一个类实例,使之成为嵌套静态类,而不是:

public class Mother { 
    public static class Child { 
      public void doStuff() { 
       // ... 
      } 
    } 
} 
+1

我相信真正的问题在于,OP并不意味着班级不是静态的,但我可能会误会 – fge

+0

@fge:可能。我会在答案中提到这一点。 –

+6

只是一个额外的是,如果内部类不公开,您需要调用'ctor.setAccessible(true)'以使其工作! – Beccari

0

此代码创建内部类实例。

Class childClass = Child.class; 
    String motherClassName = childClass.getCanonicalName().subSequence(0, childClass.getCanonicalName().length() - childClass.getSimpleName().length() - 1).toString(); 
    Class motherClassType = Class.forName(motherClassName) ; 
    Mother mother = motherClassType.newInstance() 
    Child child = childClass.getConstructor(new Class[]{motherClassType}).newInstance(new Object[]{mother}); 
相关问题