字节序列反序列化问题

对象的字节序列存在硬盘上,更改了类的属性,反序列化时会造成不兼容问题。
“但当serialVersionUID相同时,它就会将不一样的field以type的预设值反序列化
,可避开不兼容问题”这句话什么意思?

serialVersionUID = 1L 是默认的,还是用上面那上面的那个吧,那个是根据类名、接口名、成员方法及属性等来生成一个64位的哈希字段,如果你的类Serialized存到硬盘上面后,可是后来你却更改了类别的field(增加或减少或改名),当你Deserialize时,就会出现 Exception的,这样就会造成不兼容性的问题。 但当serialVersionUID相同时,它就会将不一样的field以type的预设值Deserialize,可避开不兼容性问题。如果都是默认的1L,那么serialVersionUID就都是相同的了。那样就达不到你的目的了

简单来说,Java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体(类)的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常。(InvalidCastException)。
可以编写测试类:

import java.io.Serializable;
public class Serial implements Serializable {
    private static final long serialVersionUID = 6977402643848374753L;
    int id;
    String name;

    public Serial(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public String toString() {
        return "DATA: " + id + " " + name;
    }

}

序列化测试代码:

 import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

public class SerialTest {
    public static void main(String[] args) {
        Serial serial1 = new Serial(1, "song");
        System.out.println("Object Serial" + serial1);
        try {
            FileOutputStream fos = new FileOutputStream("serialTest.txt");
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            oos.writeObject(serial1);
            oos.flush();
            oos.close();
        } catch (FileNotFoundException e) { // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) { // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

反序列化测试代码:

 import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;

public class DeserialTest {
    public static void main(String[] args) { // TODO Auto-generated method stub
        Serial serial2;
        try {
            FileInputStream fis = new FileInputStream("serialTest.txt");
            ObjectInputStream ois = new ObjectInputStream(fis);
            serial2 = (Serial) ois.readObject();
            ois.close();
            System.out.println("Object Deserial" + serial2);
        } catch (FileNotFoundException e) { // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) { // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ClassNotFoundException e) { // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

可以测试待序列化类Serial设置了版本号,分别运行SerialTest和DeserialTest类后,如果修改Serial类添加一个属性int age,那么再执行DeserialTest的时候还是能够正确运行的。但是如果注释掉版本号后,就会报不兼容异常了,因为我们运行SerialTest序列化时类信息没变更之前的版本号是A,然后修改Serial类的版本号后,并修改了类的属性信息。再执行反序列话时发现读取的字节码信息中的序列号与当前类的版本号不同,所以会任务前后类型版本不一样,有变更,所以报运行时异常了。