java接口Serializable源码分析

目录

 

简介

类的注释


简介

实现了Serializable接口的类,可以进行序列化和反序列化;没有实现这个接口的类的任何(state)状态/域或者属性值不能被序列化

可以看到这是一个空接口

类的注释


package java.io;

/**
 * <p>实现java.io.Serializable接口的类支持类的序列化。
 * 没有实现这个接口的类的状态不会被序列化或者反序列化。
 * 一个可序列化的类的所有子类都是可序列化的。
 * 序列化接口没有任何方法或属性,而且仅仅用于标识可序列化的语义。
 * 
 * <p>为了让不可序列化的类的子类可序列化,子类可能需要保存和恢复
 *	超类的public,protected,和包字段(如果可以访问)的状态。
 * 只有当父类有一个可访问的无参构造器来初始化这个类的状态,子类才能承担这个责任。
 * 如果不是这种情况,宣称一个类是Serializable是错误的,错误将在运行时被检测到。
 * 
 * <p>在反序列化过程中,不可序列化类的将会使用这个类的public或者protected的无参构造器初始化字段。
 * 一个无参构造器必须可以被可序列化的子类访问。可序列化的子类的字段将从流中恢复。
 * 
 * <p>在遍历一个图时,可能遇到不支持Serializable接口的对象。
 * 这种情况,会抛出NotSerializableException,并且标识不可序列化对象的类。
 * 
 * <p>在序列化和反序列化过程中需要特殊处理的类必须实现具有以下确切标签的特殊方法:
 * writeObject,readObject,readObjectNoData
 * <PRE>
 * private void writeObject(java.io.ObjectOutputStream out)
 *     throws IOException
 * private void readObject(java.io.ObjectInputStream in)
 *     throws IOException, ClassNotFoundException;
 * private void readObjectNoData()
 *     throws ObjectStreamException;
 * </PRE>
 * 
 * <p>writeObject方法负责为特定的类写出对象的状态,从而对应的readObject方法能恢复它。
 * 保存对象的字段的默认机制是调用out.defaultWriteObject.
 * 这个方法不需要关注属于它的父类或子类的状态。
 * 
 * <p>这个方法不需要关注它父类或子类的状态。
 * 通过使用writeObject来将各个字段写入ObjectOutputStream,
 * 或者使用DataOutput支持的方法写入原始数据类型,来保存状态。
 * 
 * <p>readObject方法负责从流中读取,并且恢复类的字段。
 * 它可以调用in.defaultReadObject来调用用于恢复对象的非静态和非transient的字段的默认机制。
 * defaultReadObject方法使用流中的信息来赋值保留在流中对象的字段,并在当前对象中指定对应字段。
 * 当类添加新的字段的时候,这将处理这种情况。这个方法不需要关注它父类或子类的状态。
 * 通过使用writeObject来将各个字段写入ObjectOutputStream,
 * 或者使用DataOutput支持的方法写入原始数据类型,来保存状态。
 * 
 * <p>当序列化流没有表明,给定的类是被反序列化类的父类时,readObjectNoData方法负责为特定类初始化对象的状态。
 * 这可能当接收方使用与发送方不同的被反序列化实例的类的版本时,
 * 并且接收方的版本extends了发送方没有extends的类时,发生。
 * 如果序列化流被干扰了,也可能发生。
 * 因此,readObjectNoData对于正确初始化反序列化的对象很有用,
 * 即使存在有敌意或者不完整的流作为源头。
 *
 * <p>需要指定一个额外对象,在写入一个对象到流时的可序列化类,
 * 需要实现一个有着明确签名的特殊方法:
 * 
 * <PRE>
 * ANY-ACCESS-MODIFIER Object writeReplace() throws ObjectStreamException;
 * </PRE><p>
 *
 * <p>如果这个方法存在,并且可以被正在序列化的对象的类的方法访问,writeReplace方法会被序列化过程调用。
 * 因此,这个方法能有private,protected和包内private的访问权限。
 * 子类遵循java可访问规则来访问这个方法。
 *
 * <p>当一个类的实例从流中被读取时,需要指定一个替代的类,应该实现一个有着明确签名的特殊方法:
 *
 * <PRE>
 * ANY-ACCESS-MODIFIER Object readResolve() throws ObjectStreamException;
 * </PRE><p>
 * 
 * <p>readResolve方法与writeReplace方法有着同样的调用规则和访问规则。
 *
 * <p>serialVersionUID是反序列化期间用于验证,被序列化的对象的发送方和接收方,验证是否为这个对象加载了与序列化兼容的类,
 * 序列化过程运行时与每个可序列化的类关联的一个版本号。
 * 如果接受者已经为这个对象加载了一个类,而且这个类与发送者对应的类有着不同的serialVersionUID,
 * 那么反序列化会导致InvalidClassException。
 * 一个可序列化的类能明确地宣称它自己的serialVersionUID,
 * 通过声明一个必须是static,final,long类型的叫做serialVersionUID的字段。
 *
 * <PRE>
 * ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;
 * </PRE>
 * 
 * <p>如果一个可序列化类没有明确声明一个serialVersionUID,
 * 然后运行时序列化过程会为这个类根据该类的各个方面,计算出一个默认的serialVersionUID,如java序列化规范所述。
 * 然而,强烈建议,所有的可序列化类明确声明serialVersionUID的值,
 * 因为默认的serialVersionUID计算对类的细节高度敏感,
 * 很可能取决于编译器的实现,并且因此在反序列化中发生InvalidClassException。
 * 因此,为了在不同的java编译器实现之间,保证一个一致的serialVersionUID值,
 * 可序列化的类必须声明一个明确的serialVersionUID值。
 * 也强烈建议,如果可能的话,使用private修饰符来声明serialVersionUID,
 * 因为这种声明只适用于马上用它的类--serialVersionUID不能继承。
 * 数组类不能声明一个明确的serialVersionUID值,
 * 所以它们永远有一个默认的计算过的值,但是数组类放弃了匹配serialVersionUID的需求
 * 
 * @author  unascribed
 * @see java.io.ObjectOutputStream
 * @see java.io.ObjectInputStream
 * @see java.io.ObjectOutput
 * @see java.io.ObjectInput
 * @see java.io.Externalizable
 * @since   JDK1.1
 */
public interface Serializable {
}

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值