2013-07-05 22 views
51

próbuję instancję klasy wewnętrzny zdefiniowany w następujący kod Java:Jak utworzyć instancję klasy wewnętrznej z odbiciem w Javie?

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

Kiedy próbuję dostać wystąpienie dziecko lubi tego

Class<?> clazz= Class.forName("com.mycompany.Mother$Child"); 
Child c = clazz.newInstance(); 

otrzymuję ten wyjątek:

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

Czego mi brakuje?

+2

Uhm, twoja wewnętrzna klasa nie jest statyczna ... Czy to celowo? Może pochodzić z tła C#? ;) – fge

+1

Dzięki za sugestię "statycznego" pomysłu! W rzeczywistości używanie statycznej klasy zagnieżdżonej zamiast klasy wewnętrznej ułatwia życie. – Stephan

+2

Chodzi o to, że jeśli klasa wewnętrzna nie jest zadeklarowana jako statyczna, instancje tej klasy zależą od istnienia instancji klasy zewnętrznej; różni się to od języka C#, w którym wszystkie klasy wewnętrzne są domyślnie "statyczne" i mogą być tworzone bez instancji nadrzędnej. – fge

Odpowiedz

100

Istnieje dodatkowy "ukryty" parametr, który jest instancją otaczającej klasy. Konieczne będzie pobranie konstruktora przy użyciu Class.getDeclaredConstructor, a następnie dostarczenie instancji klasy otaczającej jako argumentu. Na przykład:

// 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); 

EDIT: Ewentualnie, jeśli zagnieżdżona klasa faktycznie nie muszą odnosić się do instancji osłaniającego, sprawiają, że zagnieżdżony statyczny klasę Zamiast:

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

Wierzę, że prawdziwym problemem jest to, że OP nie oznacza, że ​​klasa nie jest statyczna, ale mogę się mylić – fge

+0

@fge: Możliwe. Wspomnę o tym w odpowiedzi. –

+6

Jedynym dodatkowym warunkiem jest to, że jeśli klasa wewnętrzna nie jest publiczna, musisz wywołać 'ctor.setAccessible (true)', aby to zadziałało! – Beccari

0

Kod ten tworzy instancja klasy wewnętrznej.

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}); 
Powiązane problemy