2009-04-08 7 views
14

J'ai une méthode d'utilité et lorsque la logique non pertinente est retirée de celle-ci, la méthode simplifiée ressemblerait à ceci:instanciation une classe interne

public static <A extends Foo> List<A> getFooList(Class<A> clazz) { 
    List<A> returnValue = new ArrayList<A>(); 
    for(int i=0; i < 5; i++) { 
     A object = clazz.newInstance(); 
     returnValue.add(object); 
    } 

    return returnValue; 
} 

Le problème est que si clazz est une classe interne, comme Foo.Bar.class , alors la méthode newInstance() ne fonctionnera pas même si Bar serait publique, car elle enverra un java.lang.InstantiationException.

Existe-t-il un moyen d'instancier dynamiquement des classes internes?

Répondre

27

Si c'est vraiment une classe intérieure au lieu d'un imbriquée classe (statique), il y a un paramètre constructeur implicite, qui est la référence à l'instance de la classe externe. Vous ne pouvez pas utiliser Class.newInstance à ce stade - vous devez obtenir le constructeur approprié. Voici un exemple:

import java.lang.reflect.*; 

class Test 
{ 
    public static void main(String[] args) throws Exception 
    { 
     Class<Outer.Inner> clazz = Outer.Inner.class; 

     Constructor<Outer.Inner> ctor = clazz.getConstructor(Outer.class); 

     Outer outer = new Outer(); 
     Outer.Inner instance = ctor.newInstance(outer); 
    } 
} 

class Outer 
{ 
    class Inner 
    { 
     // getConstructor only returns a public constructor. If you need 
     // non-public ones, use getDeclaredConstructors 
     public Inner() {} 
    } 
} 
0

Cette exception sera levée uniquement si clazz représente une classe abstraite ou une interface. Êtes-vous sûr de passer un objet Class représentant une classe concrète?

5

Quelque chose plus générique:

public static <T> T createInstance(final Class<T> clazz) throws SecurityException, NoSuchMethodException, 
      IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException { 

      T instanceToReturn = null; 
      Class<?> enclosingClass = clazz.getEnclosingClass(); 

      if (enclosingClass != null) { 
       Object instanceOfEnclosingClass = createInstance(enclosingClass); 

       Constructor<T> ctor = clazz.getConstructor(enclosingClass); 

       if (ctor != null) { 
        instanceToReturn = ctor.newInstance(instanceOfEnclosingClass); 
       } 
      } else { 
       instanceToReturn = clazz.newInstance(); 
      } 

      return instanceToReturn; 
    } 
+0

Vous devez toujours vérifier si la classe intérieure n'est pas statique ... – Corin

Questions connexes