2012-01-05 99 views
23
// 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 

为什么投给Uri[]休息,当UriParcelable我不明白为什么这会发生ClassCastException异常

+0

发布stacktrace。 – 2012-01-05 16:25:24

+0

Uri从Parcelable继承吗? – fge 2012-01-05 16:25:25

+0

Uri实现Parcelable – 2012-01-05 16:59:55

回答

19

不幸的是,没有办法像Java中那样为阵列进行类似的操作。你将不得不遍历你的数组并单独投射每个对象。

这样做的原因是类型安全的JVM根本无法保证您的阵列中的内容可以被强制转换为开放的,而不必重复通他们,这就是为什么你必须重复他们并分别扮演他们。

基本上,因为Parcelable可以被其他对象继承,所以不能保证该数组仅包含Uri对象。然而,铸造到超类型将起作用,从那时起,类型安全就没问题。

+0

我认为是相同的(因为它在C#中是这样的),所以我查了一下java数组协变,它似乎被支持(并且是类型安全的一个漏洞)。我的引用是否仅仅是当前的JVM过时了? :http://www.angelikalanger.com/Articles/Papers/JavaGenerics/ArraysInJavaGenerics.htm,http://c2.com/cgi/wiki?JavaArraysBreakTypeSafety – 2012-01-05 16:38:01

+1

我认为类型安全性与泛型有关,它只限于编译时。数组不被聚合。他们是参考,你可以做铸造。 – 2012-01-05 16:41:40

+0

是正确的,但是Parcelable []是第一个新的Uri [...],所以即使Uri是Parcelable但Uri []不是Parcelable [] ...] – 2012-01-05 16:48:25

0

我觉得发生了什么东西如下:

class Parent { } 

class MaleParent extends Parent { } 

class FemaleParent extends Parent { } 

如果方案是如上面的东西那么下面会在运行时失败:

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

东西如下不会引发异常:

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

为什么这么多的父母? – Sayka 2015-10-31 08:20:53

26

使用此方法,它适用于我。

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

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

也就是说,如果Uri实现Parcelable然后

你可以说:

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

你不能说:

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

正如你看到的,我们可以投paUri[]。那么问题是什么?此ClassCastException发生在您的应用程序被终止并且稍后重新创建保存的数组时。当它被重新创建时,运行时不知道它是什么类型的数组(Uri[]),它只是创建了Parcelable[]并将元素放入其中。因此ClassCastException当您尝试将其投射到Uri[]

注意异常情况不会发生(理论上)当进程没有中止与最初创建阵列(Uri[])被保存/恢复几轮状态之间重复使用。就像当你改变方向一样。

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

干杯

+1

这是正确的答案。当我的服务试图将Parcelable []从AccountManager的Bundle转换到Account []时,我无意中重新出现了ClassCastException。发生这种情况后很少发生电话,最后 - 这是罪魁祸首! – user1643723 2014-08-15 11:08:50

相关问题