Как получить параметризованный экземпляр класса - PullRequest
9 голосов
/ 16 сентября 2008

С тех пор, как были введены дженерики, класс параметризован, поэтому List.class создает класс . Это понятно.

Что я не могу понять, так это как получить экземпляр класса типа, который сам параметризован, то есть класс <список <String>>. Как в этом фрагменте:

public class GenTest {
    static <T> T instantiate(Class<T> clazz) throws Exception {
        return clazz.newInstance();
    }
    public static void main(String[] args) throws Exception {
        // Is there a way to avoid waring on the line below
        // without using  @SuppressWarnings("unchecked")?
        // ArrayList.class is Class<ArrayList>, but I would like to
        // pass in Class<ArrayList<String>>
        ArrayList<String> l = GenTest.instantiate(ArrayList.class);
    }
}

Я довольно часто сталкиваюсь с вариантами этой проблемы и до сих пор не знаю, просто ли я что-то упускаю или действительно нет лучшего способа. Спасибо за предложения.

Ответы [ 4 ]

8 голосов
/ 16 сентября 2008

Класс Class является представлением типа во время выполнения. Поскольку параметризованные типы подвергаются стиранию типов во время выполнения, объект класса для Class будет таким же, как и для Class > и Class >.

Причина, по которой вы не можете создать их экземпляр с помощью нотации .class, заключается в том, что это специальный синтаксис, используемый для литералов классов. Спецификация языка Java специально запрещает этот синтаксис при параметризации типа, поэтому List .class не допускается.

1 голос
/ 16 сентября 2008

Я не думаю, что вы можете делать то, что вы пытаетесь. Во-первых, ваш экземплярный метод не знает, что он имеет дело с параметризованным типом (вы также можете легко передать его java.util.Date.class). Во-вторых, из-за стирания сделать что-то особенно специфичное для параметризованных типов во время выполнения сложно или невозможно.

Если бы вы подошли к проблеме по-другому, есть и другие маленькие хитрости, которые вы можете сделать, например, вывод типа:

public class GenTest
{
    private static <E> List<E> createList()
    {
        return new ArrayList<E>();
    }

    public static void main(String[] args)
    {
        List<String> list = createList();
        List<Integer> list2 = createList();
    }
}
1 голос
/ 16 сентября 2008

Классы представляют классы, загруженные загрузчиком классов, которые являются необработанными типами. Чтобы представить параметризованный тип, используйте java.lang.reflect.ParameterizedType.

0 голосов
/ 13 ноября 2012

Единственное, что вы можете сделать, это создать экземпляр List<String> напрямую и вызвать его getClass():

instantiate(new List<String>() { ... }.getClass());

Для типов с несколькими абстрактными методами, такими как List, это довольно неудобно. Но, к сожалению, вызов конструкторов подклассов (например, new ArrayList<String>) или фабричных методов (Collections.<String>emptyList()) не работает.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...