Как правило, я видел, как люди используют литерал класса следующим образом:
Class<Foo> cls = Foo.class;
Но что, если тип является общим, например, List? Это работает нормально, но есть предупреждение, так как список должен быть параметризован:
Class<List> cls = List.class
Так почему бы не добавить <?>
? Ну, это вызывает ошибку несоответствия типов:
Class<List<?>> cls = List.class
Я подумал, что-то вроде этого будет работать, но это просто ошибка синтаксиса:
Class<List<Foo>> cls = List<Foo>.class
Как получить Class<List<Foo>>
статически, например, используя литерал класса?
Я мог бы использовать, @SuppressWarnings("unchecked")
чтобы избавиться от предупреждений, вызванных непараметрическим использованием List в первом примере Class<List> cls = List.class
, но я бы не хотел.
Какие-либо предложения?
List<Integer> list1 = new ArrayList<Integer>(); List<String> list2 = (List<String>)list1; list2.add("foo"); // perfectly legal
Вы не можете сделать это в Java, вы получите ошибку компиляции несоответствия типов!List<String> list2 = (List<String>) (Object) list1;
Для параметризованных типов не существует литералов Class, однако есть объекты Type, которые правильно определяют эти типы.
См. Java.lang.reflect.ParameterizedType - http://java.sun.com/j2se/1.5.0/docs/api/java/lang/reflect/ParameterizedType.html.
Библиотека Google Gson определяет класс TypeToken, который позволяет просто генерировать параметризованные типы и использует его для спецификации объектов json со сложными параметризованными типами универсальным дружественным способом. В вашем примере вы бы использовали:
Я намеревался публиковать ссылки на классы Javadoc TypeToken и Gson, но переполнение стека не позволит мне публиковать более одной ссылки, так как я новый пользователь, вы можете легко найти их с помощью поиска Google
источник
clzz = new TypeToken<E>(){}.getRawType();
для последующей итерации по схожим структурированным перечислениям сclzz.getEnumConstants()
последующим использованием рефлексии для вызова методов-членов а-ляMethod method = clzz.getDeclaredMethod("getSomeFoo");
победа! Спасибо!Вы можете управлять этим с двойным броском:
@SuppressWarnings("unchecked") Class<List<Foo>> cls = (Class<List<Foo>>)(Object)List.class
источник
Object
на,Class
вы, вероятно, можете сэкономить накладные расходы (бессмысленного) проверенного броска во время выполнения.Class
вместоObject
, как вы предлагаете, кажется более значимым, но это не устраняет необходимость в@SuppressWarnings("unchecked")
аннотации, оно даже добавляет новое предупреждение:Class is a raw type. References to generic type Class<T> should be parameterized
Class<?>
:(Class<List<Foo>>)(Class<?>)List.class
unchecked
предупреждение. Этот ответ не меняет и не улучшает ничего из этого. OP даже заявляет в своем вопросе, что он не хочет использоватьSuppressWarnings
...Чтобы разъяснить ответ Cletus, во время выполнения удаляются все записи универсальных типов. Обобщения обрабатываются только в компиляторе и используются для обеспечения дополнительной безопасности типов. Они на самом деле просто стенография, которая позволяет компилятору вставлять типы типов в соответствующих местах. Например, ранее вы должны были сделать следующее:
становится
Это позволяет компилятору проверять ваш код во время компиляции, но во время выполнения он все еще выглядит как первый пример.
источник
Java Дженерики FAQ и поэтому также Клетуса ответ звучит как нет смысла в том
Class<List<T>>
, однако , реальная проблема заключается в том , что это крайне опасно:Это
cast()
выглядит так, как будто это безопасно, но на самом деле это совсем не безопасно.Хотя я не понимаю, где не может быть
List<?>.class
=,Class<List<?>>
так как это было бы очень полезно, когда у вас есть метод, который определяет тип на основе универсального типаClass
аргумента.Поскольку
getClass()
существует JDK-6184881, запрашивающий переключение на использование подстановочных знаков, однако не похоже, что это изменение будет выполнено (очень скоро), поскольку оно несовместимо с предыдущим кодом (см. Этот комментарий ).источник
Ну, как мы все знаем, что это стирается. Но это может быть известно при некоторых обстоятельствах, когда тип явно упоминается в иерархии классов:
И теперь вы можете делать такие вещи, как:
Больше информации здесь . Но опять же, почти невозможно найти:
где это стирается.
источник
GenericEntity
иGenericType
.Ввиду того факта, что литералы класса не имеют информации общего типа, я думаю, вы должны предположить, что избавиться от всех предупреждений будет невозможно. В некотором смысле использование
Class<Something>
- это то же самое, что использование коллекции без указания универсального типа. Лучшее, что я мог предложить, было:источник
Вы можете использовать вспомогательный метод, чтобы избавиться от
@SuppressWarnings("unchecked")
всего класса.Тогда вы могли бы написать
Другие примеры использования
Тем не менее, поскольку он редко действительно полезен, а использование метода отрицательно сказывается на проверке типов компилятором, я бы не рекомендовал реализовывать его там, где он общедоступен.
источник