一尘不染

自定义枚举也是可序列化的吗?

java

我了解Enum是可序列化的。因此,这样做是安全的。(selectedCountry是enum Country

没有客户成员变量的原始枚举

public enum Country {
    Australia,
    Austria,
    UnitedState;
}

分段

@Override
public void onActivityCreated (Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    if (savedInstanceState != null) {
        selectedCountry = (Country)savedInstanceState.getSerializable(SELECTED_COUNTRY_KEY);
    }
}

@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
    savedInstanceState.putSerializable(SELECTED_COUNTRY_KEY, selectedCountry);
}

但是,如果我在自定义枚举类中有不可序列化的成员,该怎么办?例如,

原始枚举客户成员变量

package org.yccheok;

import org.yccheok.R;

/**
 *
 * @author yccheok
 */
public enum Country {
    Australia(R.drawable.flag_au),
    Austria(R.drawable.flag_at),
    UnitedState(R.drawable.flag_us);

    Country(int icon) {
        this.icon = icon;
        nonSerializableClass = new NonSerializableClass(this.toString());
    }

    public int getIcon() {
        return icon;
    }

    public static class NonSerializableClass {
        public NonSerializableClass(String dummy) { this.dummy = dummy; }
        public String dummy;
    }

    private final int icon;

    public NonSerializableClass nonSerializableClass;
}

我测试了 有用。(我通过在序列化之前和之后打印出所有成员变量的值进行了测试。它们在前后均相同)

但是,我不明白为什么会起作用?
由于我没有提供适当的readObjectwriteObject,因此需要Serializable界面提供。

如有效Java 项目75:考虑使用自定义序列化表格所述
,如果我的枚举中有自定义成员变量,是否需要提供自己的readObjectwriteObject


阅读 659

收藏
2020-09-08

共1个答案

一尘不染

之所以起作用,是因为的序列化过程Enum不同于其他类的序列化过程。从官方文档中

1.12枚举常量的序列化

枚举常量的序列化与普通的可序列化或可外部化的对象不同。枚举常量的序列化形式仅由其名称组成;常量的字段值不存在于表单中。为了序列化枚举常量,ObjectOutputStream写入枚举常量的name方法返回的值。为了反序列化枚举常量,ObjectInputStream从流中读取常量名称。然后,通过调用java.lang.Enum.valueOf方法,将常量的枚举类型与接收到的常量名称作为参数传递,来获得反序列化的常量。像其他可序列化或可外部化的对象一样,枚举常量可以用作随后出现在序列化流中的反向引用的目标。

这意味着您所有的自定义字段 都不会 被序列化。在你的情况一切正常,因为你的应用程序仍在运行,并且您得到 相同的
Enum,你传递给实例savedInstanceState.putSerializable

但是,想象一下您的应用因为Android没有足够的内存而被杀死的情况。下次用户打开应用程序时,您将获得一个
Enum实例,并且所有自定义字段都将丢失,并由构造方法重新初始化。因此,枚举中的可变字段始终有效transient

2020-09-08