Вопрос по generics, java – Есть ли чистый способ присвоения класса универсального типа переменной?

12

Учитывая этот код:

List<Integer> ints = new ArrayList<Integer>();

// Type mismatch: 
// cannot convert from Class<capture#1-of ? extends List> to Class<List<Integer>>       
Class<List<Integer>> typeTry1 = ints.getClass(); 

// Type safety: 
// Unchecked cast from Class<capture#2-of ? extends List> to Class<List<Integer>>
Class<List<Integer>> typeTry2 = (Class<List<Integer>>) ints.getClass();

// List is a raw type. References to generic type List<E> should be parameterized
Class<? extends List> typeTry3 = ints.getClass(); 

Есть ли способ получитьClass изList<Integer> без ошибки или предупреждения? Я могу достаточно легко подавить предупреждения, но если Java требует, чтобы я подавил предупреждение для этого допустимого кода, я оченьразочаровывать.

С другой стороны, если подавление предупреждений является единственным способом, что является самым безопасным для подавления?

Видимо нет предупреждения свободного пути из-за стирания.stackoverflow.com/questions/339699/… user845279
На самом деле нет смысла использовать конкретный универсальный тип для ссылки на объект Class, потому что эта информация отсутствует в объекте, на который делается ссылка, поэтому в моем мненииClass<? extends List> или жеClass<? extends List<?>> являются лучшими типами для переменной. Я был удивлен тем, что не смог найти приведение без предупреждения к целевому типу с подстановочными символами ... Однако, поскольку объекты Class в основном используются для отражения в любом случае, вы можете использоватьClass<?>, который работает без предупреждения Silly Freak

Ваш Ответ

2   ответа
5

Это настоящий Catch-22 на Java.

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

// WARN: List is not typed
Class<? extends List> typeTry3 = ints.getClass();

Это потому, что в большинстве случаев действительно лучше всего печатать свои списки.

Однако из-за стирания типа у Java нет способа выяснить общий типList во время выполнения, и компилятор это знает. Таким образом, нет никакого метода наClass который вернет типизированный объект:

// ERROR: ints.getClass() doesn't return a Class<List<Integer>>, it returns a Class<List>
Class<? extends List<? extends Integer>> var = ints.getClass();

Так что выmust приведите его к печатному списку. Однако, как вы знаете, поскольку проверка типов во время выполнения не выполняется, Java предупреждает вас о любых приведениях к типизированной переменной:

// WARN: Casting to typed List
Class<List<Integer>> typeTry2 = (Class<List<Integer>>) ints.getClass();

Любая попытка обойти это, по сути, является средством запутывания компилятора, и оно неизбежно будет запутанным.

Тогда вам лучше всего выбрать вариант B:

On the other hand, if warning suppression is the only way, what is the safest to suppress?

Самый безопасный способ подавить это предупреждение -@SuppressWarnings("unchecked") аннотация как можно более локализована. Поместите их над каждым отдельным непроверенным составом. Таким образом, абсолютно ясно, кто вызывает предупреждение.

3

Один из способов сделать это - создать свойсобственный класс, Я не уверен, если это будет соответствовать вашим потребностям.

Я не совсем уверен, чего вы пытаетесь достичь. Так что возможноподстановочные это ответ.

import java.util.*;

class Main
{
      public static void main(String[] args)
      {
            List<Integer> list = new ArrayList<Integer>();
            Class<?> clazz = list.getClass();
            System.out.println(clazz) ;
      }
}
Мне кажется, что честное решение - сказать компилятору: «Я знаю, что получу классsomethingПожалуйста, дайте мне это без жалоб, хотяyou (компилятор) может быть не в состоянии определить / сохранить тип этогоsomething& Quot ;.
+1 за отсутствие предупреждений или ошибок, но все же довольно хакерский :) cqcallaw

Похожие вопросы