Невозможно привести из ArrayList <Parcelable>к ArrayList <ClSprite> - PullRequest
12 голосов
/ 05 августа 2011

В фрагменте кода, который я написал, у меня есть эта строка:

         AllSprites = (ArrayList<ClSprite>) savedInstanceState.getParcelableArrayList("AllSprites");

Я получаю сообщение об ошибке при неверном приведении от ArrayList<Parcelable> до ArrayList<ClSprite>.Почему это не законно?

Ответы [ 4 ]

25 голосов
/ 11 октября 2013

Простое решение состоит в том, чтобы установить тип возвращаемого элемента, например, так:

17 голосов
/ 24 июля 2013

Другие уже объяснили проблему, но в этом случае есть очень простое решение для нее. Просто оставьте приведение, и ваш код скомпилируется. :):

ArrayList<ClSprite> AllSprites = savedInstanceState.getParcelableArrayList("AllSprites");

Почему?

Посмотрите на сигнатуру метода getParcelableArrayList:

public <T extends Parcelable> ArrayList<T> getParcelableArrayList(String key)

Это универсальный метод, параметр типа которого должен быть дочерним по отношению к Parcelable.Если вы присваиваете его непосредственно такой переменной:

ArrayList<ClSprite> AllSprites; // declaration somewhere
                                // ClSprite implements Parcelable
...

AllSprites = savedInstanceState.getParcelableArrayList("AllSprites");

, то компилятор может определить параметр типа, поэтому приведение вообще не нужно!После вывода подпись будет выглядеть следующим образом:

public ArrayList<ClSprite> getParcelableArrayList(String key)

Понятно, что нам не нужно разыгрывать от ArrayList<ClSprite> до ArrayList<ClSprite>.:)

Но почему вы получили эту ошибку?Если вы выполняете приведение и не назначаете переменную непосредственно возвращаемому значению этого метода, компилятор не может определить параметр типа, он только знает, что возвращаемый тип равен ArrayList<Parcelable>.И в этом случае ошибка занимает место, как уже объяснили другие.

Также, если метод не будет универсальным, но вот так:

public ArrayList<Parcelable> getParcelableArrayList(String key)

вы не можете присвоить возвращаемое значениев AllSprites, потому что вычитания типов вообще нет, и вы не можете преобразовать из ArrayList<Parcelable> в ArrayList<ClSprite>.Несмотря на то, что это имеет смысл, Java использует стирание типа для шаблонов и делает эти вещи небезопасными во время выполнения.

7 голосов
/ 05 августа 2011

Совершенно небезопасно разыгрывать ArrayList<Derived> на ArrayList<Base> или наоборот. Это открывает дыру в системе типов, и Java, если вы попробуете это, выдаст ClassCastException во время выполнения.

Причина в том, что я мог бы сделать что-то вроде этого:

ArrayList<Derived> derived = new ArrayList<Derived>();
ArrayList<Base> base = (ArrayList<Derived>) derived; // Not legal!
base.add(new Base()); // Just put a Base into the list, but it only holds Derived!
derived.get(0).doSomethingOnlyInDerived(); // Error!  It's not really a Derived!

Это, кстати, причина того, что неявные преобразования Java между массивами нарушены и почему существует ArrayStoreException. Это приведение не безопасно во всех случаях.

5 голосов
/ 05 августа 2011

Это приведение просто недопустимо в Java;список родителей не может быть приведен к списку детей.Кроме того, приведение к ArrayList<X> опасно и чрезмерно ограничительно.Вы можете решить обе проблемы, сделав тип AllSprites be List<Parcelable>.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...