Подтвердить что ты не робот

Java: литье объекта в общий тип

В Java при отбрасывании из объекта в другие типы, почему вторая строка создает предупреждение, относящееся к приведению, но первое не работает?

void a(Object o) {
  Integer i = (Integer) o;
  List<Integer> list = (List<Integer>) o;
}

/*Type safety: Unchecked cast from Object to List<Integer>*/
4b9b3361

Ответ 1

Это потому, что объект не будет проверяться на наличие List<Integer> во время выполнения из-за стирания типа. Это будет просто отбрасывание на List. Например:

List<String> strings = new ArrayList<String>();
strings.add("x");
Object o = strings;

// Warning, but will succeeed at execution time
List<Integer> integers = (List<Integer>) o;
Integer i = integers.get(0); // Bang!

Подробнее см. Часто задаваемые вопросы по Java Generics Angelika Langer, в частности раздел стирания стилей.

Ответ 2

Для ясности позвольте мне немного переписать примеры...

Я бы сказал, ключевое различие между:

void a(Object o) {
  Integer i = (Integer) o;
  ...
}

и

void a(Object o) {
  List<Integer> list = (List<Integer>) o;
  ...
}

заключается в том, что при условии, что существует ошибка типа, первый приведение всегда сразу бросает исключение RuntimeException (в частности, ClassCastException) при выполнении.

В то время как второй может отсутствовать - если входной параметр o является любым типом List<?>, выполнение будет продолжаться, несмотря на неправильного литая.

Будет ли код где-нибудь позже выдавать исключение или нет, зависит от того, что вы делаете со списком.

Но независимо от того, что Exception может не быть брошенным на строку, в которой был сделан актерский состав, но где-то еще (что может быть сложной ошибкой для отслеживания) или вообще нет.

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

Ответ 3

Ответ Jon - правильный, но иногда вы не можете обойти это предупреждение (например, когда вы работаете с устаревшим API). В таких случаях вы можете подавить предупреждение так:

@SuppressWarnings("unchecked")
List<Integer> list = (List<Integer>) someApiThatReturnsNonGenericList();