Создание экземпляра внутреннего класса

У меня есть метод утилиты, и когда ненужная логика удаляется из него, упрощенный метод будет выглядеть так:

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

Проблема заключается в том, что если clazz является внутренним классом, таким как Foo.Bar.class, то метод newInstance() не будет работать, даже если Bar будет общедоступным, так как он выкинет java.lang.InstantiationException.

Есть ли способ динамически создавать внутренние классы?

Ответы

Ответ 1

Если он действительно является внутренним классом вместо вложенного (статического) класса, существует неявный параметр конструктора, который является ссылкой на экземпляр внешнего класса. Вы не можете использовать Class.newInstance на этом этапе - вы должны получить соответствующий конструктор. Вот пример:

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

Ответ 2

Что-то более общее:

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

Ответ 3

Это исключение будет вызываться только в том случае, если clazz представляет собой абстрактный класс или интерфейс. Вы уверены, что передаете объект класса, представляющий конкретный класс?