美文网首页
Serializable 序列化

Serializable 序列化

作者: gczxbb | 来源:发表于2019-05-22 23:15 被阅读0次

序列化,即把一个对象内容,转换成字节序列。反序列化,将字节序列恢复成一个对象的过程。若一个对象需要序列化,实现 Serializable 接口。一个例子。

public class SerializableMain {
    public static void main(String[] args) {
        User user=new User("name_one","age_one","height_one");
        try {
            File file=new File("C:\\Users\\name\\Desktop\\DemoFile");
            if(!file.exists()) {
                file.createNewFile();
            }
            //序列化
            ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));
            oos.writeObject(user);
            oos.close();
            //反序列化
            ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
            User userTemp=(User)ois.readObject();
            System.out.println(userTemp.toString());
        }catch(Exception e) {
            e.printStackTrace();
        }
    }
}

User对象,实现Serializable接口才可以将该对象序列化和反序列化。将对象序列化输出到文件流时,如果未实现Serializable接口,将抛出异常。

java.io.NotSerializableException: User
    at java.io.ObjectOutputStream.writeObject0(Unknown Source)
    at java.io.ObjectOutputStream.writeObject(Unknown Source)
    at SerializableMain.main(SerializableMain.java:19)

从文件中反序列化一个对象时,(先实现接口完成序列化写入,再去掉接口),如果未实现Serializable接口,将抛出异常。

java.io.InvalidClassException: User; class invalid for deserialization
    at java.io.ObjectStreamClass$ExceptionInfo.newInvalidClassException(Unknown Source)
    at java.io.ObjectStreamClass.checkDeserialize(Unknown Source)
    at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
    at java.io.ObjectInputStream.readObject0(Unknown Source)
    at java.io.ObjectInputStream.readObject(Unknown Source)
    at SerializableMain.main(SerializableMain.java:24)

transient修饰的属性,不会被序列化和反序列化。序列化时,忽略该属性写入字节数组,反序列化时,不会读取属性。在User类的age属性加上该修饰。反序列化时,打印结果将是null。

User [name=name_one, age=null, height=height_one]

静态字段不会被序列化。在User类加上一个静态字段address=shanghai,先进行一次User对象序列化输出,然后,将该字段改为beijing,注释掉序列化部分,只进行反序列化。这时,反序列化address值并不是shanghai,而是beijing。说明第一次序列化时,并没有将静态字段写入。
serialVersionUID的作用。不加该项时,序列化,将会采用Java自动生成的值,正常情况下,序列化和反序列化是没问题的。如果在User类新增一个字段weight,注释掉序列化的代码,直接进行反序列化,将抛出异常。

java.io.InvalidClassException: User; local class incompatible: 
        stream classdesc serialVersionUID = 4765874944071207273, 
        local class serialVersionUID = -4975271451414878760
    at java.io.ObjectStreamClass.initNonProxy(Unknown Source)
    at java.io.ObjectInputStream.readNonProxyDesc(Unknown Source)
    at java.io.ObjectInputStream.readClassDesc(Unknown Source)
    at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
    at java.io.ObjectInputStream.readObject0(Unknown Source)
    at java.io.ObjectInputStream.readObject(Unknown Source)
    at SerializableMain.main(SerializableMain.java:21)

反序列化serialVersionUID和当前User对象的serialVersionUID不同,因为我该值是Java自动生成的,根据该类属性计算生成,保存文件的内容是没有weight属性的,因此,生成的serialVersionUID不同。User类中加上serialVersionUID字段。对字段属性的修改再反序列化将不会报错。

private static final long serialVersionUID = 1L;

这次不改属性,当serialVersionUID=1L序列化完成后,注释掉序列化代码,改serialVersionUID=2344,进行反序列化,同样将报serialVersionUID不相等的异常,

java.io.InvalidClassException: User; local class incompatible: 
        stream classdesc serialVersionUID = 1, 
        local class serialVersionUID = 2344
    at java.io.ObjectStreamClass.initNonProxy(Unknown Source)

因此,serialVersionUID值一定要自己写上,且不要随便改变,不要让Java自动生成。否则,在更新对象属性(Java自动生成会改变),再去进行反序列化时,将无法识别出老数据。


任重而道远

相关文章

网友评论

      本文标题:Serializable 序列化

      本文链接:https://www.haomeiwen.com/subject/zjwpzqtx.html