непроверенное предупреждение для класса <Collection> - PullRequest
0 голосов
/ 21 сентября 2010

Предположим, у меня есть следующий метод, который можно использовать для создания коллекции указанного типа.

private static Collection<?> void create(Class<? extends Collection<?>> cls) {
    return cls.newInstance();
}

Это все хорошо, если аргумент cls передается во время выполнения:

List<String> list = new LinkedList<String>();
create(list.getClass());

Но как мне вызвать этот метод в коде без непроверенного предупреждения? Скажем, я хочу сделать что-то вроде:

create(LinkedList.class);

Будет жаловаться, что create (Class) не определен, что строго говоря правильно, потому что List не #capture of Collection, но как мне заставить его работать?

Большое спасибо!

Ответы [ 2 ]

3 голосов
/ 21 сентября 2010

Нил Гафтер говорит примерно об этой проблеме здесь .Исправление заключается в использовании супертипов .Это то, что Guice использует для хранения информации об общем типе, я считаю.

По сути, это дополнительный класс, который вы можете использовать для представления типа вместо использования Foo.class.Вы бы использовали это так:

TypeReference<LinkedList<String>> x = new TypeReference<LinkedList<String>>() {};
create(x);

Обратите внимание, что ваша попытка использовать raw type LinkedList все равно заставит компилятор жаловаться, и намеренно так - когда вы используетенеобработанные типы, вы в основном отказываетесь от безопасности типов.Но эта схема позволяет вам выразить универсальный тип более сложным способом.

0 голосов
/ 21 сентября 2010

у нас есть два универсальных типа: один для подтипа коллекции, другой для типа элемента коллекции.может работать следующий код:

private static <C extends Collection<E>, E>
C create(Class<C> cls) throws Exception
{
    return cls.newInstance();
}

пример использования.предупреждений нет.

    Class<LinkedList<String>> clazz = ...;
    LinkedList<String> result = create(clazz);

Теперь возникает вопрос, как мы можем получить clazz?Вы должны убедительно убедить компилятор:

    List<String> list = new LinkedList<String>();
    clazz = (Class<LinkedList<String>>)list.getClass();

    clazz = (Class<LinkedList<String>>)(Class<?>)LinkedList.class;

у нас может быть вспомогательный метод для облегчения приведения типов:

public static <C extends Collection, E, T extends Collection<E>>
Class<T> type(Class<C> classC, Class<E> classE)
{
    return (Class<T>)classC;
}

//usage:
    clazz = type(LinkedList.class, String.class);
    result = create(clazz);

Забавно, что вы получите:

    Class<LinkedList<LinkedList<String>>> clazz2;
    LinkedList<LinkedList<String>> result2;

    clazz2 = type(LinkedList.class, clazz);
    result2 = create(clazz2);

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

...