我不明白为什么发生这种ClassCastException

// Application ... Intent i = new Intent(); i.putExtra(EXTRA_FILE_UPLOAD_URIS, mGalleryAdapter.getItems()); Uri[] getItems() { return mItems; } // Service ... intent.getParcelableArrayExtra(EXTRA_FILE_UPLOAD_URIS); //works, returns Parcelable[] Uri[] uris = (Uri[])intent.getParcelableArrayExtra(EXTRA_FILE_UPLOAD_URIS); // ... Breaks with ClassCastException 

为什么当UriParcelable时候,对Uri[]的演员呢?

  • 为什么可以写一个布尔数组到一个宗地而不是一个布尔?
  • 可传递的inheritance:抽象类 - 哪个CREATOR?
  • 在已签名的应用程序中为包裹写入例外
  • 尝试在自定义对象数组上执行readParcelable时发生ClassCastException
  • 传递ArrayList to Activity
  • 嵌套parcelable对象不读
  • 把一个对象放在Handler消息中
  • Parcel.readStringArray()的参数是什么?
  • 不幸的是,没有办法像Java那样对数组进行转换。 你将不得不遍历你的数组,并单独投射每个对象。

    这样做的原因是安全types, JVM不能确保你的数组的内容可以被转移到Uri,而不必迭代它们,这就是为什么你必须迭代它们并单独施放它们。

    基本上,因为Parcelable可以被其他对象inheritance,所以不能保证Array只包含Uri对象。 然而,铸造到超types将工作,从那时起,types安全就可以了。

    使用这种方法,它为我工作。

     Parcelable[] ps = getIntent().getParcelableArrayExtra(); Uri[] uri = new Uri[ps.length]; System.arraycopy(ps, 0, uri, 0, ps.length); 

    数组有多态行为 – 只有genericstypes没有。

    也就是说,如果Uri实现了Parcelable

    你可以说:

     Parcelable[] pa = new Uri[size]; Uri[] ua = (Uri[]) pa; 

    你不能说:

     List<Parcelable> pl = new ArrayList<Uri>(); 

    正如你所看到的,我们可以回到Uri[] 。 那么问题是什么? 这个ClassCastException发生在你的应用程序被终止并且以后保存的数组被重新创build时。 当它被重新创build时,运行时不知道它是什么types的数组( Uri[] ),所以它只是创build一个Parcelable[]并将元素放入其中。 因此,当您尝试将其转换为Uri[]时, ClassCastException

    请注意,当进程未被终止并且原始创build的数组( Uri[] )在状态保存/恢复轮回之间重用时,exception不会发生(理论上)。 就像当你改变方向一样。

    我只是想澄清为什么发生。 如果你想要一个解决scheme@solo提供了一个体面的。

    干杯

    我认为发生的事情如下:

     class Parent { } class MaleParent extends Parent { } class FemaleParent extends Parent { } 

    如果情况如上所述,则在运行时以下将失败:

     Parent[] parents = new FemaleParent[]{}; MaleParent[] maleParents = (MaleParent[]) parents; 

    下面的东西不会引起exception:

     Parent[] parents = new MaleParent[]{}; MaleParent[] maleParents = (MaleParent[]) parents;