Каковы риски явного кастинга из списка списка типов <? расширяет MyObject> до списка списка типов <MyObject> в Java?

Я думаю, что заголовок должен объяснить все это, но на всякий случай...

Я хочу знать, какие риски и потенциальные проблемы, касающиеся кастинга, могут явиться результатом следующего отрывка кода Java:

List<? extends MyObject> wildcardList = someAPI.getList();
List<MyObject> typedList = (List<MyObject>) wildcardList;

Мои мысли - то, что все объекты в wildcardList должны быть экземпляром MyObject (точный тип или подкласс) и поэтому каждый раз, когда объекты получены от typedList затем никогда не должно быть ClassCastException. Это корректно? Раз так, почему компилятор генерирует предупреждение?

7
задан skaffman 4 August 2010 в 07:19
поделиться

5 ответов

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

    List<Integer> intList = new ArrayList<Integer>();
    intList.add(2);

    List<? extends Number> numList = intList;
    List<Number> strictNumList = (List<Number>) numList;
    strictNumList.add(3.5f);

    int num = intList.get(1); //java.lang.ClassCastException: java.lang.Float cannot be cast to java.lang.Integer
7
ответ дан 7 December 2019 в 01:15
поделиться

Вы правы насчет извлечения объектов из typedList, это должно работать.

Проблема возникает, когда вы позже добавляете больше объектов в typedList. Если, например, MyObject имеет два подкласса A и B, а wildcardList был типа A, то вы не можете добавить к нему B. Но поскольку typedList имеет родительский тип MyObject, эта ошибка будет поймана только во время выполнения.

2
ответ дан 7 December 2019 в 01:15
поделиться

Предположим, вы делаете что-то вроде:

List<ChildClassOne> childClassList = new ArrayList<ChildClassOne>();
childClassList.add(childClassOneInstanceOne);
childClassList.add(childClassOneInstanceTwo);

List<? extends MyObject> wildcardList = childClasslist; // works fine - imagine that you get this from a method that only returns List<ChildClassOne>
List<MyObject> typedList = (List<MyObject>) wildcardList; // warning

typedList.add(childClassTwoInstanceOne); // oops my childClassList now contains a childClassTwo instance
ChildClassOne a = childClassList.get(2); // ClassCastException - can't cast ChildClassTwo to ChildClassOne

Это единственная серьезная проблема. Но если вы читаете только из своего списка, все должно быть в порядке.

1
ответ дан 7 December 2019 в 01:15
поделиться

Это похоже на

List<Object> obj = (List<Object>) new ArrayList<String>();

Надеюсь, проблема очевидна. Список подтипов не может быть приведен к списку супертипов.

0
ответ дан 7 December 2019 в 01:15
поделиться

В дополнение к уже опубликованным ответам, обратите внимание на следующие

Компилятор выдает предупреждение, если к элементу из этого типа будет осуществлен доступ позже в вашем коде, а это не общий тип, определенный ранее. Также недоступна информация о типе во время выполнения.

0
ответ дан 7 December 2019 в 01:15
поделиться
Другие вопросы по тегам:

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