Domanda

Ho un metodo di utilità e quando la logica irrilevante viene rimosso da essa, il metodo semplificato sarebbe simile a questa:

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

Il problema è, che se clazz è una classe interna come Foo.Bar.class, allora il metodo newInstance() non funzionerà anche se Bar sarebbe pubblica, in quanto sarà gettare un java.lang.InstantiationException.

C'è un modo per istanziare dinamicamente le classi interne?

È stato utile?

Soluzione

Se è veramente un interno classe invece di un annidati (statica) di classe, c'è un parametro del costruttore implicito, che è il riferimento alla istanza della classe esterna. Non è possibile utilizzare Class.newInstance in quella fase - si deve ottenere il costruttore appropriato. Ecco un esempio:

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() {}
    }
}

Altri suggerimenti

Qualcosa di più generico:

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

Questa eccezione verrà generata solo se Clazz rappresenta sia una classe astratta o un'interfaccia. Sei sicuro che stai passando un oggetto di classe che rappresenta una classe concreta?

In JMockit 1.41, utilizzare questo:

ConstructorReflection.newInstance

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top