Android 不得不知 之 Serializable

概念

  1. 序列化就是将对象转化为字节流。
  2. 反序列化就是将字节流转化为对象。
  3. 默认的序列化是深度系列化(即类中嵌套其他对象引用的对象也会被序列化)。
  4. 静态成员不会被默认序列化,要让一个类支持序列化只要让这个类实现接口 java.io.Serializable 即可
package java.io;
public interface Serializable {
}

以上是 Serializable 的接口定义,且 Serializable 只是一个没有定义任何方法的标记接口。

为什么定义标记接口即可实现序列化了呢?

声明实现 Serializable 接口后保存读取对象就可以使用 ObjectOutputStreamObjectInputStream 流了,ObjectOutputStreamOutputStream 的子类,但实现了 ObjectOutput 接口,ObjectOutputDataOutput 的子接口,增加了一个 writeObject(Object obj) 方法将对象转化为字节写到流中,ObjectInputStreamInputStream 的子类,实现了ObjectInput 接口,ObjectInputDataInput 的子接口,增加了一个 readObject() 方法从流中读取字节转为对象。

序列化和反序列化的实质在于 ObjectOutputStreamwriteObjectObjectInputStreamreadObject 方法实现,常见的 StringDateDoubleArrayListLinkedListHashMapTreeMap 等都默认实现了 Serializable,.

有时候我们对象有些字段的值可能与内存位置(hashcode)、当前时间等有关,所以我们不想序列化他(因为反序列化后的值是没有意义的),或者有时候如果类中的字段表示的是类的实现细节而非逻辑信息则默认序列化也是不适合的,所以我们需要定制序列化,Java 提供的定制主要有transient 关键字方式和实现 writeObjectreadObject 方式及 Externalizable 接口 readResolvewriteReplace 方式,还可以将字段声明为 transient 后通过 writeObjectreadObject 方法来自己保存该字段。

默认情况下 Java 会根据类中一系列信息自动生成一个版本号,在反序列化时如果类的定义发生了变化版本号就会变化,也就与反序列化流中的版本号不匹配导致会抛出异常,所以我们为了更好的控制和性能问题会自定义 serialVersionUID 版本号来避免类定义发生变化后反序列化版本号不匹配异常问题,如果版本号一样时流中有该字段而类定义中没有则该字段会被忽略,如果类定义中有而流中没有则该字段会被设为默认值,如果对于同名的字段类型变了则会抛出 InvalidClassException

虚拟机是否允许反序列化不仅取决于类路径和功能代码是否一致,还取决于另一个非常重要的点是两个类的序列化 ID 是否一致(就是 private static final long serialVersionUID = 1L)。

因为声明实现 Serializable 接口后保存读取对象就可以使用 ObjectOutputStreamObjectInputStream 流了,ObjectOutputStreamwriteObject(Object obj)方法将对象转化为字节写到流中,ObjectInputStreamreadObject() 方法从流中读取字节转为对象,Serializable 虽然是一个空接口,但是在调用 writeObject 方法时却充当了一种健全的校验作用,如果对象没有实现 Serializable 则在调用 writeObject 时就会抛出异常,所以说 Serializable 算是一种接口标识机制。

如下为 ObjectOutputStreamwriteObject(Object obj) 的核心标记判断:

 private void writeObject0 (Object obj, boolean unshared) throws IOException {
        try {
            if(obj instanceof Class) {
                writeClass((Class) obj, unshared);
            } else if(obj instanceof ObjectStreamClass) {
                writeClassDesc((ObjectStreamClass) obj, unshared);
            } else if(obj instanceof String) {
                writeString((String) obj, unshared);
            } else if(cl.isArray()) {
                writeArray(obj, desc, unshared);
            } else if(obj instanceof Enum) {
                writeEnum((Enum) obj, desc, unshared);
            } else if(obj instanceof Serializable) {
                writeOrdinaryObject(obj, desc, unshared);
            } else {
                if(extendedDebugInfo) {
                    throw new NotSerializableException(cl.getName() + "\n" + debugInfoStack.toString());
                } else {
                    throw new NotSerializableException(cl.getName());
                }
            }
        } finally {
        }
    }

    原文作者:老林不跌面儿
    原文地址: https://www.jianshu.com/p/fb5fc5b340c8
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞