Serializable

什么是serializable接口

一个对象序列化的接口,一个类只有实现了Serializable接口,才可以被序列化

 

什么是序列化

将对象的状态信息转换为可以存储或传输的形式的过程,在序列化期间,对象将其当前状态写入到临时存储区或者持久性存储区,之后,便可以通过从存储区中读取或反序列化 它自动屏蔽了操作系统的差异,字节顺序等。比如,在 Windows 平台生成一个对象并序列化之,然后通过网络传到一台 Unix 机器上,然后可以在这台Unix机器上正确地重构(deserialization)这个对象。 不必关心数据在不同机器上如何表示,也不必关心字节的顺序或者其他任何细节。

 

什么时候需要序列化

当我需要把对象的状态信息通过网络进行传输,或者需要将对象的状态信息持久化,以便将来使用时都需要把对象进行序列化

 

对象的序列化机制

对象的类,类签名,以及非瞬态和非静态字段的值(序列化不保存静态,因为他和类是同级的)

serivalVersionUID

序列化操作的时候系统会把当前类的serialVersionUID写入到序列化文件中,当反序列化时系统会去检测文件中的serialVersionUID,判断它是否与当前类的serialVersionUID一致,如果一致就说明序列化类的版本与当前类版本是一样的,可以反序列化成功,否则失败。

显式声明

private static final long serialVersionUID = xxxxL;

如果没有显式地定义一个serialVersionUID,那么Java会默认根据类信息计算一个serivalVersionUID出来。如果我们不希望通过编译来强制划分软件版本,即实现序列化接口的实体能够兼容先前版本,就需要显式地定义一个名为serialVersionUID,类型为long的变量,不修改这个变量值的序列化实体都可以相互进行串行化和反串行化。

 

Java提供的Serializable是一个空接口,如果一个类实现了Serializable接口

代表这个类及其子类是自动支持序列化和反序列化的

序列化时,只对对象的状态进行保存,而不管对象的方法,如果一个类没有实现Serializable接口,那么默认是不能被序列化的,除非使用其他方式

如果一个类实现了Seralizable接口,而其父类没有实现Serializable接口,那么父类必须有无参的构造器,父类中的字段不参与序列化,只是将其初始化而已。

序列化的实例变量引用其他的对象,则引用的对象也会被序列化

并非所有的对象都可以序列化

一个Serializable(可序列化)对象进行重写装配的过程中,不会调用任何构造器(甚至默认构造器),整个对象都是通过InputStream中取得数据恢复的.

 

 

 

我们可能有特殊的安全问题,不希望对象的某一部分实例化;或者子类对象完全不必实例化,因为对象恢复后,拿一部分需要重新创建

通过实现Externalizable接口,用它代替Serializable,便可以控制序列化的具体过程.

Externalizable接口扩展了Serializable 并增加了两个方法writeExternal()readExternal()

 

Transient 关键字的作用是控制变量的序列化,在变量声明前加上该关键字,可以阻止该变量被序列化到文件中,在被反序列化后,transient 变量的值被设为初始值,如 int 型的是 0,对象型的是 null

 

根据父类对象序列化的规则,我们可以将不需要被序列化的字段抽取出来放到父类中,子类实现 Serializable 接口,父类不实现,根据父类序列化规则,父类的字段数据将不被序列化

 

 谨慎地实现 Serialiable


 为了继承而设计的类应该很少实现 Serialiable, 接口也应该很少会扩展它. 如果违反了这条规则, 则扩展这个类或者实现这个接口的程序员会背上沉重的负担.


若没有认真考虑默认序列化形式是否合适, 则不要接受这种形式


 即使你确定了默认序列化形式是合适的, 通常你仍然要提供一个 readObject方法以保证约束关系和约束性


不管你选择了哪种序列化形式, 你都要为自己编写的每个可序列化的类声明一个显式的序列版本 UID (serialVersionUID)

 

对象实现序列化的步骤

  1) 创建一个对象输出流,它可以包装一个其他类型的目标输出流,如文件输出流;

  2) 通过对象输出流的writeObject()方法写对象。

对象反序列化的步骤如下:

  1) 创建一个对象输入流,它可以包装一个其他类型的源输入流,如文件输入流;

  2) 通过对象输入流的readObject()方法读取对象。

 

 

Externalizable的例子

import java.io.Externalizable;

import java.io.IOException;

import java.io.ObjectInput;

import java.io.ObjectOutput;

 

/**

 * @Description: 学生类 已实现序列化接口

 * @author yuanfy

 * @date 2018111日 上午11:36:37

 * @version 1.0

 */

public class Student implements Externalizable{

 

    private static final long serialVersionUID = 61234L;

 

    private String name;

    

    private transient int age;

    

    private static String sex;

        

    public Student(String name, int age, String sex) {

        this.name = name;

        this.age = age;

        this.sex = sex;

    }

    

    public  String getName() {

        return name;

    }

    public void setName(String name) {

        this.name = name;

    }

    public int getAge() {

        return age;

    }

    public void setAge(int age) {

        this.age = age;

    }

    public String getSex() {

        return sex;

    }

    public void setSex(String sex) {

        this.sex = sex;

    }

    @Override

    public String toString() {

        return "Student [name=" + name + ", age=" + age + ", sex=" + sex + "]";

    }

 

    @Override

    public void writeExternal(ObjectOutput out) throws IOException {

        // TODO Auto-generated method stub

        out.writeUTF(name);

        out.writeInt(age);

        out.writeObject(sex);

    }

 

    @Override

    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {

        this.name = in.readUTF();

        this.age = in.readInt();

        this.sex = (String)in.readObject();

    }

}

 

@Test

    public void test3() throws FileNotFoundException, IOException, ClassNotFoundException{

        Student s1 = new Student("james", 31, "man");

        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("E:\\Student.txt")));

        oos.writeObject(s1);

        oos.close();

        

        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("E:\\Student.txt")));

        Student s2 = (Student)ois.readObject();

        System.out.println(s2);

        ois.close();

}

 

代码转载至https://www.cnblogs.com/yuanfy008/p/8269337.html