Java 无法从ArrayList强制转换<;可包裹>;到ArrayList<;ClSprite>;

Java 无法从ArrayList强制转换<;可包裹>;到ArrayList<;ClSprite>;,java,casting,Java,Casting,在我编写的一段代码中,我有这样一行: AllSprites = (ArrayList<ClSprite>) savedInstanceState.getParcelableArrayList("AllSprites"); AllSprites=(ArrayList)savedInstanceState.getParcelableArrayList(“AllSprites”); 我从ArrayList到ArrayList的转换无效时出错。为什么这不合法?强制转换在

在我编写的一段代码中,我有这样一行:

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

我从
ArrayList
ArrayList
的转换无效时出错。为什么这不合法?

强制转换在Java中是非法的;父列表不能强制转换为子列表。此外,对
ArrayList
的强制转换是危险的,而且限制过多。您可以通过将
AllSprites
的类型设置为
List
来解决这两个问题。将
ArrayList
强制转换为
ArrayList
从根本上讲是不安全的,反之亦然。这样做会在类型系统中打开一个漏洞,如果您尝试这样做,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!
ArrayList<ClSprite> AllSprites; // declaration somewhere
                                // ClSprite implements Parcelable
...

AllSprites = savedInstanceState.getParcelableArrayList("AllSprites");
public ArrayList<ClSprite> getParcelableArrayList(String key)
public ArrayList<Parcelable> getParcelableArrayList(String key)
ArrayList派生=新的ArrayList();
ArrayList基=(ArrayList)派生;//不合法!
base.add(新的base());//只需在列表中添加一个基,但它只包含派生的!
派生的.get(0).doSomethingOnlyInDerived();//错误!这不是一个真正的衍生产品!

顺便说一下,这就是Java在数组之间的隐式转换被破坏的原因,也是出现
ArrayStoreException
的原因。并非所有情况下,此强制转换都是安全的。

其他人已经解释了这个问题,但在这种情况下,有一个非常简单的解决方案只需离开强制转换,代码就会编译。:):

它是一个泛型方法,其类型参数必须是
Parcelable
的子级。如果直接将其分配给如下变量:

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!
ArrayList<ClSprite> AllSprites; // declaration somewhere
                                // ClSprite implements Parcelable
...

AllSprites = savedInstanceState.getParcelableArrayList("AllSprites");
public ArrayList<ClSprite> getParcelableArrayList(String key)
public ArrayList<Parcelable> getParcelableArrayList(String key)
ArrayList AllSprites;//某处申报
//ClSprite实现了可包裹
...
AllSprites=savedInstanceState.getParcelableArrayList(“AllSprites”);
编译器可以推断类型参数,因此根本不需要强制转换!推导后,签名如下所示:

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!
ArrayList<ClSprite> AllSprites; // declaration somewhere
                                // ClSprite implements Parcelable
...

AllSprites = savedInstanceState.getParcelableArrayList("AllSprites");
public ArrayList<ClSprite> getParcelableArrayList(String key)
public ArrayList<Parcelable> getParcelableArrayList(String key)
public ArrayList getParcelableArrayList(字符串键)
很明显,我们不必从
ArrayList
转换到
ArrayList
:)

但是你为什么会犯这个错误呢?如果执行强制转换而不将变量直接赋给此方法的返回值,编译器将无法推断类型参数,它只知道返回的类型是
ArrayList
。在这种情况下,错误发生在其他人已经解释过的地方

此外,如果该方法不是泛型的,而是如下所示:

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!
ArrayList<ClSprite> AllSprites; // declaration somewhere
                                // ClSprite implements Parcelable
...

AllSprites = savedInstanceState.getParcelableArrayList("AllSprites");
public ArrayList<ClSprite> getParcelableArrayList(String key)
public ArrayList<Parcelable> getParcelableArrayList(String key)
public ArrayList getParcelableArrayList(字符串键)
无法将返回值分配给
AllSprites
,因为根本没有类型推断,并且无法从
ArrayList
转换为
ArrayList

尽管这是有道理的,但Java使用泛型,并使这些东西在运行时变得不安全。

一个简单的解决方案是像这样设置返回的元素类型


ArrayList AllSprites=savedInstanceState.getParcelableArrayList(“AllSprites”)

。。。好的,那么你的问题是什么?可能会重复查看标题,无法从ArrayList强制转换到ArrayList您的ArrayList应该更改为ArrayList,因为我需要自定义类ClSprites中的函数。您可以在使用时强制转换
列表中的每个对象,或者,您可以创建一个新的
列表
,并在
for
循环中从另一个列表中移动对象。这两种解决方案似乎都不理想,但恐怕没有更干净的办法。这是解决这个问题最简单、最聪明的办法。我想这应该是公认的答案,而且它与javac编译器(AndroidStudio使用)兼容。我使用的通用类型转换在eclipse中有效,但在Android Studio中无效。应该是可接受的答案。实际上,在
getParcelableArrayList
方法中不需要类型参数。有关详细信息,请参阅。感谢这个bug,我永远爱你谢谢你的精彩解释,我尝试使用三元运算符设置ArrayList的值,但这不起作用。这个答案很好地解释了这一点。谢谢这个虫子,我永远爱你