对象的序列化与反序列化

1:对象的序列化就是将Object转换成byte序列,反之叫对象的反序列化。

  序列化流 ObjectOutputStream 是过滤流, writeObject方法,得往文件中写

  反序列化流  ObjectInputStream readObject方法,从文件中读

  序列化接口(Serializable)

    对象必须实现序列化接口,才能进行序列化,否则将抛出异常。这个接口没有任何方法,只是一个标准。

package com.zhao.serializable;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class StudentSerializableDemo {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        File file=new File("demo/obj.txt");
        if (!file.exists()) {
            file.createNewFile();
        }
        
        StudentSerializableDemo demo=new StudentSerializableDemo();
        demo.outputStream(file);
        demo.inputStream(file);
    }
    
    /**
     * 对象的序列化
     * @param file
     * @throws IOException
     * @throws IOException
     */
    public void outputStream(File file) throws IOException{
        ObjectOutputStream outputStream=new ObjectOutputStream(new FileOutputStream(file));
        Student student=new Student("1", "李四", 21);
        outputStream.writeObject(student);
        outputStream.flush();
        outputStream.close();
    }
    /**
     * 对象的反序列化
     * @param file
     * @throws IOException
     * @throws ClassNotFoundException
     */
    public void inputStream(File file) throws IOException, ClassNotFoundException{
        ObjectInputStream inputStream=new ObjectInputStream(new FileInputStream(file));
        Student student=(Student) inputStream.readObject();
        System.out.println(student);
        inputStream.close();
    }
}

2:transient

  transient不会进行jvm默认的序列化,可以自己完成这个元素的序列化

package com.zhao.serializable;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.ConcurrentModificationException;

public class Student implements Serializable {
    private String stuno;
    private String stuname;
    // transient 不会进行jvm默认的序列化,也可以自己完成这个元素的序列化
    private transient int stuage;

    public Student() {
        // TODO Auto-generated constructor stub
    }

    public Student(String stuno, String stuname, int stuage) {
        this.stuno = stuno;
        this.stuname = stuname;
        this.stuage = stuage;
    }

    @Override
    public String toString() {
        return "Student [stuno=" + stuno + ", stuname=" + stuname + ", stuage=" + stuage + "]";
    }

    public String getStuno() {
        return stuno;
    }

    public void setStuno(String stuno) {
        this.stuno = stuno;
    }

    public String getStuname() {
        return stuname;
    }

    public void setStuname(String stuname) {
        this.stuname = stuname;
    }

    public int getStuage() {
        return stuage;
    }

    public void setStuage(int stuage) {
        this.stuage = stuage;
    }

    private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
        //把jvm虚拟机能默认序列化的元素进行序列化操作
        s.defaultWriteObject();
        //自己完成stuage的序列化
        s.writeInt(stuage);
    }
    
    private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
        //把jvm虚拟机能默认反序列化的元素进行反序列化操作
        s.defaultReadObject();
        //自己完成stuage的反序列化操作
        this.stuage=s.readInt();
    }

}

  ArrayList的源码便进行了上述操作,目的在于 对数组的有效长度进行序列化和反序列化,对数组没有数据的元素,不进行此操作,这可以提高系统效率。

3:

  当父类继承Serializable接口时,所有子类都可以被序列化。

  子类实现了Serializable接口,父类没有,父类中的属性不能序列化(不报错,数据会丢失),但是在子类中属性仍能正确序列化。

  如果序列化的属性是对象,则这个对象也必须实现Serializable接口,否则会报错。

  在反序列化是,如果对象的属性有修改或删减,则修改的部分属性会丢失,但不会报错。

  在反序列化是,如果serialVersionUID被修改,则反序列化会失败。

原文地址:https://www.cnblogs.com/zhao307/p/5368494.html