我不明白为什么会发生这个 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
当 Uri
是 Parcelable
时,为什么到 Uri[]
的转换会中断?
// 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
Why does the cast to Uri[]
break, when Uri
is Parcelable
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
使用这个方法,它对我有用。
Use this method, it work for me.
不幸的是,在
Java
中没有办法像这样对数组进行强制转换。您将必须迭代数组并单独转换每个对象。原因是类型安全,
JVM
根本无法确保数组的内容可以转换为 Uri,而无需迭代它们,这就是为什么您必须迭代它们并转换它们单独。基本上,因为
Parcelable
可以被其他对象继承,所以不能保证数组仅包含Uri
对象。然而,转换为超类型是可行的,因为这样类型安全就可以了。Unfortunately there is no way to cast like that for arrays in
Java
. You will have to iterate your array and cast each object individually.The reason for this is type Safety, the
JVM
simply cannot ensure that the contents of your array can be casted to Uri, without having to iterate thru them, which is why you have to iterate them and cast them individually.Basically because
Parcelable
could be inherited by other Objects, there is no guarantee that the Array contains onlyUri
objects. However casting to a supertype would work since then type safety would be ok.数组确实具有多态行为——只有泛型类型没有。
也就是说,如果
Uri
实现Parcelable
那么你可以说:
你不能说:
正如你所看到的,我们可以将
pa
转换回Uri []
。那么问题出在哪里呢?当您的应用程序被终止并且稍后重新创建保存的数组时,会发生此ClassCastException
。重新创建它时,运行时不知道它是什么类型的数组 (Uri[]
),因此它只是创建一个Parcelable[]
并将元素放入其中。因此,当您尝试将其转换为Uri[]
时,会出现ClassCastException
。请注意,当进程未终止且最初创建的数组 (
Uri[]
) 在状态保存/恢复轮次之间重用时,异常不会发生(理论上)。就像当你改变方向时一样。我只是想弄清楚为什么会这样。如果你想要一个解决方案,@solo 提供了一个不错的解决方案。
干杯
Arrays do have polymorphic behaviour - only generic types don't have.
That is, if
Uri
implementsParcelable
thenyou CAN say:
you CANNOT say:
As you see we can cast
pa
back toUri[]
. Then what is the problem? ThisClassCastException
happens when your app is killed and later the saved array is recreated. When it is recreated the runtime does not know what kind of array (Uri[]
) it was so it just creates aParcelable[]
and puts elements into it. Hence theClassCastException
when you try to cast it toUri[]
.Note that the exception does not happen (theoretically) when the process is not killed and the originally created array (
Uri[]
) is reused between state save/restore rounds. Like when you change the orientation.I just wanted to make clear WHY it happened. If you want a solution @solo provided a decent one.
Cheers
我认为发生的事情如下:
如果场景如上所述,那么以下内容将在运行时失败:
如下所示的内容不会引发异常:
I think what's happening is something as follows:
If the scenario is something as above then the following will fail at runtime:
Something as follows does not raise the exception:
https://stackoverflow.com/a/8745966/72437 和 https://stackoverflow.com/a/20073367/72437 对为什么会这样有很好的解释发生崩溃。
https://stackoverflow.com/a/14866690/72437 还有一个示例说明我们如何解决此问题。
我想提供代码示例,以帮助更好地理解。
让我举一个例子来说明为什么此类事件有时会失败。
演示为什么会发生此类崩溃的示例
演示如何解决此问题的示例
https://stackoverflow.com/a/8745966/72437 and https://stackoverflow.com/a/20073367/72437 have well explanation on why such crash happens.
https://stackoverflow.com/a/14866690/72437 also has a example on how we can workaround with this.
I would like to provide code examples, to help better understanding.
Let me demonstrate an example on why such incident fails sometimes.
An example to demonstrate why such crash happens
An example to demonstrate on how we can fix this