我写的一段代码中,有这样一行:
AllSprites = (ArrayList<ClSprite>) savedInstanceState.getParcelableArrayList("AllSprites");
我收到了一个关于从 ArrayList<Parcelable>
转换为 ArrayList<ClSprite>
的无效转换错误。为什么这是不合法的?
我写的一段代码中,有这样一行:
AllSprites = (ArrayList<ClSprite>) savedInstanceState.getParcelableArrayList("AllSprites");
我收到了一个关于从 ArrayList<Parcelable>
转换为 ArrayList<ClSprite>
的无效转换错误。为什么这是不合法的?
ArrayList<ClSprite> AllSprites = savedInstanceState.<ClSprite>getParcelableArrayList("AllSprites")
其他人已经解释了这个问题,但在这种情况下,有一个非常简单的解决方案。 只需删除转换,你的代码就可以编译。 :) :
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 在泛型方面使用类型擦除,并使其在运行时不安全。
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中,这种转换是非法的;父类列表不能被转换为子类列表。此外,将其强制转换为 ArrayList<X>
是危险和过于限制性的。您可以通过使 AllSprites
的类型为 List<Parcelable>
来解决这两个问题。
List
中的类型,或者创建一个新的 List<ClSprite>
并在 for
循环中将对象从其他列表中移动。两种解决方案似乎都不是很理想,但恐怕没有更简洁的方法了。 - Ernest Friedman-Hill