• Serializable


    Serializable:可序列化接口

    序列化:将对象转换为字节流。

    反序列化:将字节流转换为对象。

    定义实体类会实现Serializable接口,目的就是为了把对象持久化存储或者网络比特流传输。

    Serializable相当于转换层,把对象转换成字节流,传字节流比传比对象实例 更方便机器的存取。传输之前就之后转成字节流,以免传输时进行判断或者占用其他空间、时间 进行 字节流转换。

    Serializable内部结构:

     接口中没有内容,可以看做一个标识接口。引一段百度知道的举例:比如在课堂上有位学生遇到一个问题,于是举手向老师请教,这时老师帮他解答,那么这位学生的举手其实就是一个标识,自己解决不了问题请教老师帮忙解决。

     

    在Java中的这个Serializable接口其实就是告诉JVM,你要帮我做序列化的工作。

    Serializable中关于serialVersionUID是的说明

    在接口的说明对version number做出了详细的解释,大概意思是在序列化时会给每个实体类关联一个version号叫做serialVersionUID,类型为静态的static final 的 long。

    serialVersionUID有两种显示的生成方式:        
    一是默认的1L,比如:private static final long serialVersionUID = 1L;        
    二是根据类名、接口名、成员方法及属性等来生成一个64位的哈希字段

    作用是用来验证 对象的发送方和接收方是否已经加载。什么意思:在反序列化时,JVM会将传输过来的serialVersionUID与本地实体类的对比,如果相同,反序列化成功,若不同则反序列化失败。

    因为Java对象是保存在JVM的堆内存中的,也就是说,如果JVM堆不存在了,那么对象也就跟着消失了。

    而序列化提供了一种方案,可以让你在即使JVM停机的情况下也能把对象保存下来的方案。就像我们平时用的U盘一样。把Java对象序列化成可存储或传输的形式(如二进制流),比如保存在文件中。这样,当再次需要这个对象的时候,从文件中读取出二进制流,再从二进制流中反序列化出对象。

    虚拟机是否允许反序列化,不仅取决于类路径和功能代码是否一致,一个非常重要的一点是两个类的序列化 ID 是否一致,这个所谓的序列化ID,就是我们在代码中定义的serialVersionUID

    /**
     * Serializability of a class is enabled by the class implementing the
     * java.io.Serializable interface. Classes that do not implement this
     * interface will not have any of their state serialized or
     * deserialized.  All subtypes of a serializable class are themselves
     * serializable.  The serialization interface has no methods or fields
     * and serves only to identify the semantics of being serializable. <p>
     *
     * To allow subtypes of non-serializable classes to be serialized, the
     * subtype may assume responsibility for saving and restoring the
     * state of the supertype's public, protected, and (if accessible)
     * package fields.  The subtype may assume this responsibility only if
     * the class it extends has an accessible no-arg constructor to
     * initialize the class's state.  It is an error to declare a class
     * Serializable if this is not the case.  The error will be detected at
     * runtime. <p>
     *
     * During deserialization, the fields of non-serializable classes will
     * be initialized using the public or protected no-arg constructor of
     * the class.  A no-arg constructor must be accessible to the subclass
     * that is serializable.  The fields of serializable subclasses will
     * be restored from the stream. <p>
     *
     * When traversing a graph, an object may be encountered that does not
     * support the Serializable interface. In this case the
     * NotSerializableException will be thrown and will identify the class
     * of the non-serializable object. <p>
     *
     * Classes that require special handling during the serialization and
     * deserialization process must implement special methods with these exact
     * signatures:
     *
     * <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>The writeObject method is responsible for writing the state of the
     * object for its particular class so that the corresponding
     * readObject method can restore it.  The default mechanism for saving
     * the Object's fields can be invoked by calling
     * out.defaultWriteObject. The method does not need to concern
     * itself with the state belonging to its superclasses or subclasses.
     * State is saved by writing the individual fields to the
     * ObjectOutputStream using the writeObject method or by using the
     * methods for primitive data types supported by DataOutput.
     *
     * <p>The readObject method is responsible for reading from the stream and
     * restoring the classes fields. It may call in.defaultReadObject to invoke
     * the default mechanism for restoring the object's non-static and
     * non-transient fields.  The defaultReadObject method uses information in
     * the stream to assign the fields of the object saved in the stream with the
     * correspondingly named fields in the current object.  This handles the case
     * when the class has evolved to add new fields. The method does not need to
     * concern itself with the state belonging to its superclasses or subclasses.
     * State is saved by writing the individual fields to the
     * ObjectOutputStream using the writeObject method or by using the
     * methods for primitive data types supported by DataOutput.
     *
     * <p>The readObjectNoData method is responsible for initializing the state of
     * the object for its particular class in the event that the serialization
     * stream does not list the given class as a superclass of the object being
     * deserialized.  This may occur in cases where the receiving party uses a
     * different version of the deserialized instance's class than the sending
     * party, and the receiver's version extends classes that are not extended by
     * the sender's version.  This may also occur if the serialization stream has
     * been tampered; hence, readObjectNoData is useful for initializing
     * deserialized objects properly despite a "hostile" or incomplete source
     * stream.
     *
     * <p>Serializable classes that need to designate an alternative object to be
     * used when writing an object to the stream should implement this
     * special method with the exact signature:
     *
     * <PRE>
     * ANY-ACCESS-MODIFIER Object writeReplace() throws ObjectStreamException;
     * </PRE><p>
     *
     * This writeReplace method is invoked by serialization if the method
     * exists and it would be accessible from a method defined within the
     * class of the object being serialized. Thus, the method can have private,
     * protected and package-private access. Subclass access to this method
     * follows java accessibility rules. <p>
     *
     * Classes that need to designate a replacement when an instance of it
     * is read from the stream should implement this special method with the
     * exact signature.
     *
     * <PRE>
     * ANY-ACCESS-MODIFIER Object readResolve() throws ObjectStreamException;
     * </PRE><p>
     *
     * This readResolve method follows the same invocation rules and
     * accessibility rules as writeReplace.<p>
     *
     * The serialization runtime associates with each serializable class a version
     * number, called a serialVersionUID, which is used during deserialization to
     * verify that the sender and receiver of a serialized object have loaded
     * classes for that object that are compatible with respect to serialization.
     * If the receiver has loaded a class for the object that has a different
     * serialVersionUID than that of the corresponding sender's class, then
     * deserialization will result in an {@link InvalidClassException}.  A
     * serializable class can declare its own serialVersionUID explicitly by
     * declaring a field named <code>"serialVersionUID"</code> that must be static,
     * final, and of type <code>long</code>:
     *
     * <PRE>
     * ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;
     * </PRE>
     *
     * If a serializable class does not explicitly declare a serialVersionUID, then
     * the serialization runtime will calculate a default serialVersionUID value
     * for that class based on various aspects of the class, as described in the
     * Java(TM) Object Serialization Specification.  However, it is <em>strongly
     * recommended</em> that all serializable classes explicitly declare
     * serialVersionUID values, since the default serialVersionUID computation is
     * highly sensitive to class details that may vary depending on compiler
     * implementations, and can thus result in unexpected
     * <code>InvalidClassException</code>s during deserialization.  Therefore, to
     * guarantee a consistent serialVersionUID value across different java compiler
     * implementations, a serializable class must declare an explicit
     * serialVersionUID value.  It is also strongly advised that explicit
     * serialVersionUID declarations use the <code>private</code> modifier where
     * possible, since such declarations apply only to the immediately declaring
     * class--serialVersionUID fields are not useful as inherited members. Array
     * classes cannot declare an explicit serialVersionUID, so they always have
     * the default computed value, but the requirement for matching
     * serialVersionUID values is waived for array classes.
     *
     * @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 {
    }

    如有差错,请各位指正
  • 相关阅读:
    Hugo搭建的博客删除文章事宜
    [GIT] Git学习笔记
    VS Code: 解决安装code-runner扩展run后无法在只读编辑器下编辑
    c/c++结构体总结
    恢复U盘做启动盘后的容量
    Manjaro安装Mysql
    win10环境下安装manjaro kde(双系统)
    IDEA设置编辑区主题
    IDEA设置主体、窗体及菜单的字体大小
    IDEA设置项目文件编码
  • 原文地址:https://www.cnblogs.com/Timeouting-Study/p/15392734.html
Copyright © 2020-2023  润新知