串行化

什么是串行化?
  • 其实Java序列化和Java串行化都是一样的,都对应英文中的Serializable。
  • 一个对象随着创建而存在,随着程序结束而结束。那如果我要保存一个对象的状态呢?Java序列化能够将对象的状态写入byte流存储起来,也从其他地方将byte流读取出来,重新构造一个新的对象。这种机制允许你将对象通过网络进行传播,并且可以随时把对象持久化到数据库、文件系统中。简而言之,序列化就是将一个对象的状态保存起来,而反序列化就是将已经保存的流对象恢复成原来的对象。
如何实现序列化?
  • 实现序列化有一个条件,即实现序列化的类必须实现java.io.Serializable接口。之后可以利用ObjectInputStream的readOjbect()方法和OjbectOutputStream的writeObject()方法进行对象的读和写,即反序列化和序列化。
  • 串行化只能保存对象的非静态成员变量,不能保存任何的成员方法和静态的成员变量,而且串行化保存的只是变量的值,对于变量的任何修饰符都不能保存。
  • serialVersionUID 是对每个对象生成一个唯一id,一旦对象被改动,serialVersionUID 也应该随之改动。
public class User implements Serializable {
    private static final long serialVersionUID = -7456133723670163623L;
    private String name;
    private int age;
    private String color;
    private String partner;
    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 getColor() {
        return color;
    }
    public void setColor(String color) {
        this.color = color;
    }
    public String getPartner() {
        return partner;
    }
    public void setPartner(String partner) {
        this.partner = partner;
    }
}

public class TestSeria {
    /**
     * 串行化user对象
     * @throws Exception
     */
    @Test
    public void test1() throws Exception{
        FileOutputStream fos = new FileOutputStream("F:/serializable/user.dat");
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        User dog = new User();
        oos.writeObject(dog);
        oos.close();
        fos.close();
    }

    /**
     * 反串行化user对象
     * @throws Exception
     */
    @Test
    public void test2() throws Exception {
        FileInputStream fis = new FileInputStream("F:/serializable/user.dat");
        ObjectInputStream ois = new ObjectInputStream(fis);
        User d = (User)ois.readObject();
        d.setName("aaa");
        d.setColor("bbb");
        d.setAge(33);
        System.out.println(d.getName());
        System.out.println(d.getAge());
        System.out.println(d.getColor());
        ois.close();
        fis.close();
    }
}
串行化和深度拷贝
  • java 对象序列化不仅保留一个对象的数据,而且递归保存对象引用的每个对象的数据。可以将整个对象层次写入字节流中,可以保存在文件中或在网络连接上传递。利用 对象序列化可以进行对象的“深复制”,即复制对象本身及引用的对象本身。序列化一个对象可能得到整个对象序列。
transient在串行化中的作用
  • 将不需要序列化的属性前添加关键字transient,序列化对象的时候,这个属性就不会序列化到指定的目的地中。
  • transient关键字只能修饰变量,而不能修饰方法和类。注意,本地变量是不能被transient关键字修饰的。变量如果是用户自定义类变量,则该类需要实现Serializable接口。
  • 一个静态变量不管是否被transient修饰,均不能被序列化
其它
  • 不是每个类都可序列化,有些类是不能序列化的, 例如涉及线程的类与特定JVM有非常复杂的关系。