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

Tom*_*ear 24 java serialization android parcelable android-intent

// 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
Run Code Online (Sandbox Code Playgroud)

为什么投给Uri[]打破,当UriParcelable

sol*_*olo 29

使用这种方法,它适合我.

Parcelable[] ps = getIntent().getParcelableArrayExtra();
Uri[] uri = new Uri[ps.length];
System.arraycopy(ps, 0, uri, 0, ps.length);
Run Code Online (Sandbox Code Playgroud)


Osc*_*mez 22

不幸的是,没有办法为数组投射Java.您将不得不迭代您的数组并单独转换每个对象.

原因是类型Safety,JVM简单地无法确保数组的内容可以转换为Uri,而不必通过它们进行迭代,这就是为什么你必须迭代它们并单独转换它们.

基本上因为Parcelable可以被其他对象继承,所以不能保证Array只包含Uri对象.然而,铸造到超类型将起作用,因为那时类型安全是可以的.


Zso*_*any 10

数组具有多态行为 - 只有泛型类型没有.

也就是说,如果Uri实现Parcelable那么

你可以说:

Parcelable[] pa = new Uri[size];
Uri[] ua = (Uri[]) pa;
Run Code Online (Sandbox Code Playgroud)

你不能说:

List<Parcelable> pl = new ArrayList<Uri>();
Run Code Online (Sandbox Code Playgroud)

如你所见,我们可以pa回击Uri[].那有什么问题呢?ClassCastException当您的应用程序被终止并稍后重新创建保存的数组时会发生这种情况.当它被重新创建时,运行时不知道它是什么类型的数组(Uri[]),所以它只是创建一个Parcelable[]并将元素放入其中.因此,ClassCastException当你试图把它投射到Uri[].

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

我只是想弄清楚它为什么会发生.如果你想要一个解决方案@solo提供一个体面的解决方案.

干杯