Java中的序列化(Serializable)

我们知道,在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不是决定由哪个类加载硬盘文件中的唯一因素,类的包名、类的名称都有关联。如果不一致,也会出现类型转化错误。原因是类的包名,类名已经被写入了文件当中。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值