博客信息

IO流之对象序列化

发布时间:『 2019-06-16 04:56』  博客类别:java基础  阅读(723)

将内存中的对象序列化到硬盘

package com.javaxl.io.other;

import java.io.*;

/**
 * @author 小李飞刀
 * @site www.javaxl.com
 * @company
 * @create  2019-06-16 8:51
 *
 * 常见错误
 *  没有实现Serializable接口
 *      java.io.NotSerializableException: com.javaxl.io.other.Person
 *  对象序列化前后唯一标识不匹配(这里我把person 的name的修饰符由private改成protected)
 *      java.io.InvalidClassException: com.javaxl.io.other.Person; local class incompatible: stream classdesc serialVersionUID = 1519549123738465531, local class serialVersionUID = 2130208101218075637
 */
public class ObjectStreamDemo {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
//        writeObj();
        readObj();
    }

    /**
     * 将内存中的数据写入硬盘(对象序列化)
     * @throws IOException
     * @throws ClassNotFoundException
     */
    public static void writeObj() throws IOException, ClassNotFoundException {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("C:\\obj.txt"));
        oos.writeObject(new Person("zs",22));
        oos.close();
    }

    /**
     * 将硬盘中的数据加载进内存(对象反序列化)
     * @throws IOException
     * @throws ClassNotFoundException
     */
    public static void readObj() throws IOException, ClassNotFoundException {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("C:\\obj.txt"));
        Person p = (Person)ois.readObject();
        System.out.println(p);
        ois.close();
    }
}

class Person implements Serializable{
    private final static long serialVersionUID = 1519549123738465531L;
    private String name;
    transient int age;
    static String country = "cn";

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public static String getCountry() {
        return country;
    }

    public static void setCountry(String country) {
        Person.country = country;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}


图解内存中对象序列化过程

 

小李飞刀_IO流

 

1、jvm虚拟机加载Person.class

2、当具体代码中使用了Person.class创建了对象,那么在堆内存中开辟空间存放对象实例;

这时的对象实例会随着方法执行结束而消失;

 

3、而序列化的操作是将,内存中的类实例持久化到硬盘,以便下次程序运行时使用;

 

 

注意:

Serializable作为一个标记接口,它是根据类的成员而计算出一个唯一标识,用来序列化的;

这也就意味着,当序列化前与序列化后类成员一定要保持一致,才能进行反序列化;否者反序列化失败,原因在于类成员发生改变,唯一标识也会发生改变;两次的唯一标识不一致,自然反序列化失败;

如果想要类成员发生改变后,依然反序列化成功,我们可以将唯一标识写死即可;

 

从上图中可以看出,对象序列化只跟jvm中堆内存有关;

所以当class文件中的 属性被static所修饰,那么该属性是不会被序列化的,因为static修饰的成员都在静态区/方法区;

另外,被transient修饰的属性,也不会被序列化;







关键字:     Java基础       IO流       对象序列化  

备案号:湘ICP备19000029号

Copyright © 2018-2019 javaxl晓码阁 版权所有