Java中的序列化(Serializable)

来源:互联网 发布:降低音量软件旧版 编辑:程序博客网 时间:2024/04/29 04:49

我们知道,在jvm中引用数据类型存在于栈中,而new创建出的对象存在于堆中。如果电脑断电那么存在于内存中的对象就会丢失。那么有没有方法将对象保存到磁盘(对象持久化存储)或通过网络传输到远处的其他地方呢?

答案是可以,但是我们必须要求所有支持持久化存储的类实现Serializable接口。原因是,jvm不仅需要考虑对象存储到硬盘等其他介质,还需要考虑将其读取(反序列化)出来。

如果读取在硬盘中的对象不能被创建它的类识别,岂不会产生问题?序列化就是起到告诉JVM,这个对象是由哪个类创建的。
Java源码中的解释:
The serialization runtime associates with each serializable class a version number, called a serialVersionUID, which is used during deserialization to verify that the sender and receiver of a serialized object have loaded classes for that object that are compatible with respect to serialization.
对于jvm来说,要进行持久化的类必须要有个标记,相当于一个通行证,只有持有这个通行证,jvm才让类创建的对象进行持久化。这个通行证就是Serializable接口,这个接口将类与一个称为serialVersionUID的变量关联起来,这个serialVersionUID就是在反序列化中用来确定由哪个类来加载这个对象。

public class SerializableDemo implements Serializable {    // static 静态数据不会被序列化    private static String countryName = "China";    private int id;    private String name;    //如果想对非静态的数据也不想序列化,则需要加入关键字  transient, 身高不存储到文件系统或者数据库中    private transient int height;    // 需要特别注意的是,如果使用默认的serialVersionUID ,那么这个serialVersionUID是和类的字段相关联的,    // 如果修改了类的信息, 那么可能报java.io.InvalidClassException, 因为之前写入的时候的serialVersionUID和    // 现在去读取信息的serialVersionUID已经因为类的信息的修改而不一致了。所以最好使用自定义的serialVersionUID    //private String school;    public static String getCountryName() {        return countryName;    }    public static void setCountryName(String countryName) {        SerializableDemo.countryName = countryName;    }    public int getId() {        return id;    }    public void setId(int id) {        this.id = id;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public int getHeight() {        return height;    }    public void setHeight(int height) {        this.height = height;    }//    public String getSchool() {//        return school;//    }////    public void setSchool(String school) {//        this.school = school;//    }}

public class SerializableDemoTest {    public static void main(String[] args) {        //writeObj();        readObj();    }    public static void writeObj() {        SerializableDemo sd = new SerializableDemo();        sd.setId(1);        sd.setName("kevin");        sd.setHeight(175);        try {            FileOutputStream fos = new FileOutputStream("logs/log1.txt");            ObjectOutputStream oos = new ObjectOutputStream(fos);            oos.writeObject(sd);            oos.close();        }        catch (Exception e) {            e.printStackTrace();        }    }    public static void readObj() {        try {            FileInputStream fis = new FileInputStream("logs/log1.txt");            ObjectInputStream ois = new ObjectInputStream(fis);            Object object = ois.readObject();            SerializableDemo sd = (SerializableDemo)object;            System.out.println(sd.getId() + "--" + sd.getName() + "--" + sd.getHeight());            ois.close();        }        catch (Exception e) {            e.printStackTrace();        }    }}
需要注意的地方是,serialVersionUID不是决定由哪个类加载硬盘文件中的唯一因素,类的包名、类的名称都有关联。如果不一致,也会出现类型转化错误。原因是类的包名,类名已经被写入了文件当中。

原创粉丝点击