2013-07-05 19 views
51

cerco di creare un'istanza della classe interna definita nel seguente codice Java:Come istanziare la classe interna con la riflessione in Java?

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

Quando provo ad ottenere un'istanza del bambino come questo

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

ottengo questa eccezione:

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

Cosa mi manca?

+2

Uhm, la tua classe interiore non è statica ... È apposta? Venendo da uno sfondo in C# forse? ;) – fge

+1

Grazie per aver suggerito un'idea "statica"! In effetti, usare una classe nidificata statica invece di una classe interiore mi semplifica la vita. – Stephan

+2

La cosa è, se una classe interna non è dichiarata statica, le istanze di questa classe dipendono dall'esistenza di un'istanza della classe esterna; questo è diverso da C# in cui tutte le classi interne sono "statiche" per impostazione predefinita e possono essere istanziate senza un'istanza padre. – fge

risposta

100

C'è un ulteriore parametro "nascosto", che è l'istanza della classe di chiusura. Avrai bisogno di arrivare al costruttore usando Class.getDeclaredConstructor e quindi fornire un'istanza della classe che racchiude come argomento. Ad esempio:

// 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: In alternativa, se la classe nidificata realtà non deve fare riferimento a un'istanza racchiude, ne fanno un nidificata classe statica invece:

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

Credo che il vero problema sia che OP non significava che la classe non fosse statica per cominciare, ma potrei sbagliarmi – fge

+0

@fge: Possibly. Lo menzionerò nella risposta. –

+6

Solo un extra è che se la classe interna non è pubblica, devi chiamare 'ctor.setAccessible (true)' per farlo funzionare! – Beccari

0

Questo codice crea istanza di classe interna.

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}); 
Problemi correlati