【问题标题】:Parcelable encountered IOException writing enum contained methodsParcelable 遇到 IOException 写入枚举包含的方法
【发布时间】:2015-03-02 13:29:55
【问题描述】:

有一个枚举:

public static enum CheckResult {
    NONEEDTOUPDATE, 
    FORCEUPDATE, 
    OPTIONALUPDATE;

    public boolean hasNewVersion() {
        return this != NONEEDTOUPDATE;
    } 
}

并将其放入另一个类:

public static class UpdateData implements Serializable {
    public static final String BUNDLE_KEY = "UpdateData";
    private static final long serialVersionUID = 7956542923164822779L;
    public String apkDownloadUrl;
    public String newVersionName;
    public CheckResult checkResult;
}

并使用捆绑发送它:

Intent intent = new Intent(context, UpdateActivity.class);
Bundle bundle = new Bundle();
bundle.putSerializable(UpdateData.BUNDLE_KEY, data);//data is an UpdateData instance
intent.putExtras(bundle);
context.startActivity(intent);

会引发异常。

Logcat:

java.lang.RuntimeException: Parcelable encountered IOException writing serializable object (name = com.tencent.game3366.update.UpdateChecker$UpdateData)
android.os.Parcel.writeSerializable(Parcel.java:1323)
android.os.Parcel.writeValue(Parcel.java:1271)
android.os.Parcel.writeArrayMapInternal(Parcel.java:618)
android.os.Bundle.writeToParcel(Bundle.java:1692)
android.os.Parcel.writeBundle(Parcel.java:643)
android.content.Intent.writeToParcel(Intent.java:7410)
android.app.ActivityManagerProxy.startActivity(ActivityManagerNative.java:2297)
android.app.Instrumentation.execStartActivity(Instrumentation.java:1437)
android.app.Activity.startActivityForResult(Activity.java:3516)
android.app.Activity.startActivityForResult(Activity.java:3477)
android.support.v4.app.FragmentActivity.startActivityForResult(Unknown Source)
android.app.Activity.startActivity(Activity.java:3719)
android.app.Activity.startActivity(Activity.java:3687)

如果我只是将枚举更改为:

public static enum CheckResult {
    NONEEDTOUPDATE, 
    FORCEUPDATE, 
    OPTIONALUPDATE 
}

一切正常,为什么会这样?

更新

当我重建整个项目时,没有出现异常............我该怎么说......

【问题讨论】:

  • 请给出一个带有相应堆栈跟踪的可重现示例。
  • 为我工作,如果我删除 static 关键字,我可以编译你的枚举。
  • 你能告诉我们你在哪里声明和初始化data吗?我无法重现这个。
  • @zzy 你用的是什么版本的安卓?我正在使用 4.4 并且我没有得到任何版本的 CheckResult 的任何异常。你描述的真的很奇怪。这肯定是一个错误。
  • 可能与这个 Lollipop 问题有关:code.google.com/p/android/issues/detail?id=80880

标签: java android serializable


【解决方案1】:

与 C++ 不同,Java 枚举不是基于整数的值。它本质上是一个类,每个枚举“值”都是这个类的一个单例实例。因此,它不是像 C++ 那样比较底层整数值,而是在执行类似

之类的操作时比较对象身份相等性

A.VALUE_A == A.VALUE_B

当你进行枚举比较时。此外,此类枚举类实例是在初始化阶段构建的,这意味着您将始终拥有可用的实例。

现在,如果枚举是可序列化的,这意味着它可以从流中反序列化,那么您将遇到典型的序列化单例问题。一旦您将枚举实例反序列化到主内存中,您将在内存中拥有该实例的 2 个副本,并且上述比较和所有其他枚举就绪结构,如 EnumMap 等,不再基于实例相等 ( == ) 和系统 hashCode()(如果您使用的是 SUN/Oracle JVM,则本质上是 System.identityHashCode() 的默认实现)。

上述问题是在语言层面要避免的——这就是为什么你不能声明一个Enum来实现Serializable

【讨论】:

  • 所有枚举都实现了可序列化。见developer.android.com/reference/java/lang/Enum.html
  • 我必须承认我也不知道。我在这个问题下的最初评论(现已删除)基本上就是你的答案。
  • 我对此表示怀疑,除非有人能指出 JVM 是如何解决上述问题的。
  • 如果你想知道,那就为它创建一个新问题,但这并不能解决 OPs 问题。
猜你喜欢
  • 1970-01-01
  • 2019-04-26
  • 1970-01-01
  • 2013-08-11
  • 2016-01-25
  • 2014-06-02
  • 2020-02-10
  • 2019-07-21
相关资源
最近更新 更多