通过 Android 中的 Intent 反序列化 Serializable 对象时出现 ClassNotFoundException

Posted

技术标签:

【中文标题】通过 Android 中的 Intent 反序列化 Serializable 对象时出现 ClassNotFoundException【英文标题】:ClassNotFoundException when deserializing Serializable object through Intent from Android 【发布时间】:2019-03-27 20:07:32 【问题描述】:

我有两个 android 应用程序 A 和 B。对于应用程序 A。我有一个可序列化的对象

public class MyObject implements Serializable 
public String[] var1;
public ArrayList<Integer> var2;

public MyObject (String[] var1, ArrayList<Integer> var2) 
    this.var1= var1;
    this.var2= var2;

然后,我通过 Intent 将这个类的实例发送到 App B 中的另一个活动,使用

Intent i= new Intent("appB.component");
i.putExtra("myobject", fc);
startActivity(i);

在 App B 中,我在 App A 中创建了相同的 Serializable 类。我试图得到这个,但我得到了java.lang.RuntimeException: Parcelable encountered ClassNotFoundException reading a Serializable object (name = appA.MyObject )

Bundle b = getIntent().getExtras();               
MyObject o = (MyObject) b.getSerializable("myobject");

我们有没有办法将应用 A 中的类的引用更改为应用 B,或者在不修改应用 A 中的代码的情况下手动解析这个对象。

【问题讨论】:

【参考方案1】:

appA.MyObjectappB.MyObject 不是同一个类。 一个不能反序列化到另一个。

您最好使用 GSON 或类似的库将您的 appA.MyObject 类序列化为 JSON,通过 Intent 发送结果字符串,然后将 JSON 字符串反序列化回 appB.MyObject 类。

或者,您可以尝试同时提供 appA.MyObjectappB.MyObject 一个

private static final long serialVersionUID

字段并将两个 UID 设置为相同的值。但我不确定这是否有效。

来自Android Serializable documentation的忠告:

明智地实现 Serializable

有关序列化 API 的全面介绍,请参阅 Effective Java 的序列化章节。本书解释了如何在不损害应用程序可维护性的情况下使用此接口。

推荐的替代品

JSON 简洁、易读且高效。 Android 包括一个流式 API 和一个树形 API 来读取和写入 JSON。使用 GSON 之类的绑定库直接读写 Java 对象。

【讨论】:

非常感谢您的回复!当我可以使用 JSON 时,问题就很简单了。问题是我只有一些 App A 源代码的快照,我无法修改它。所以,我需要调整我的 App B 来解决这个问题。这听起来很疯狂,但可能是可行的。你觉得 ClassLoader 或者 ObjectOutputStream 能解决这个问题吗? 问题是您的序列化二进制文件不是对象源的一对一精确副本。它只包含字段名称、这些字段的值和元数据,这些元数据告诉 ClassLoader 在哪里查找要实例化的 .class 文件。此元数据将包含序列化对象的类的完全限定名称。因此,在反序列化期间,ClassLoader 将在 appA 包中查找 .class 文件,但不会找到任何内容,因为您的 appB 应用程序中不存在该包。 所以我能想象到的唯一方法是,如果你给你的appB 提供与appA 完全相同的包签名。因此,如果一个对象的包签名是 com.yourcompany.appA.MyObject,您的 appB.MyObject 签名也必须是 com.yourcompany.appA.MyObject。我什至不确定这是否可能。有关序列化对象的二进制格式的更多信息,请参见:javaworld.com/article/2072752/…。在 Android 上可能略有不同,但我怀疑它们改变了核心概念。 你好,方法很简单,你只需在App B中创建与App A中的包同名的第二个包并创建类。然后,在app B的activity中,像往常一样导入使用即可。

以上是关于通过 Android 中的 Intent 反序列化 Serializable 对象时出现 ClassNotFoundException的主要内容,如果未能解决你的问题,请参考以下文章

android activity之间传递对象 对象为啥要序列化

单例模式进阶之Android中单例模式的应用场景

——Parcelable接口的使用(跨进程,Intent传输)

使用 Binder 从 Native cpp 应用程序捆绑 Intent

android intent 可以传递enum 吗

Android :安卓学习笔记之 通过Intent传递类对象(实现Serializable和Parcelable接口)