2009-04-08 40 views
14

Tengo un método de utilidad y cuando la lógica irrelevante se retira de él, el método simplificado se vería así:Instantiating una clase interna

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; 
} 

El problema es, que si clazz es una clase interna tal como Foo.Bar.class , entonces el método newInstance() no funcionará aunque Bar sea público, ya que lanzará un java.lang.InstantiationException.

¿Hay alguna manera de crear instancias dinámicas de las clases internas?

Respuesta

27

Si es realmente una clase interior lugar de una clase anidada (estática), hay un parámetro de constructor implícito, que es la referencia a la instancia de la clase externa. No puede usar Class.newInstance en esa etapa; debe obtener el constructor apropiado. Aquí hay un ejemplo:

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

Esta excepción se lanzará solo si clazz representa una clase abstracta o una interfaz. ¿Estás seguro de que estás pasando un objeto de Clase que representa una clase concreta?

5

algo más genérico:

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

usted todavía tiene que comprobar si la clase interna no es estático ... – Corin