【问题标题】:ClassNotFoundException when deserializing Serializable object through Intent from Android通过 Android 中的 Intent 反序列化 Serializable 对象时出现 ClassNotFoundException
【发布时间】: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 中的代码的情况下手动解析这个对象。

【问题讨论】:

    标签: java android serialization serializable


    【解决方案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中,像往常一样导入使用即可。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-23
    • 1970-01-01
    • 2011-08-26
    • 1970-01-01
    • 2013-03-08
    • 1970-01-01
    相关资源
    最近更新 更多