Java SE 高级开发之Java IO 之 终章——序列化/反序列化 操作

所有的项目开发一定都有序列化的概念存在。

序列化基本概念

对象序列化指的是:将内存中保存的对象变为二进制数据流的形式进行传输,或者是将其保存在文本中。但是并不意味着所有类的对象都可以被序列化,严格来讲,需要被序列化的类对象往往需要传输使用,同时这个类必须实现java.io.Serializable接口。但是这个接口并没有任何的方法定义,只是一个标识而已。

例:定义可以被序列化对象的类

class Person implements Serializable {
    private String name;
    private Integer age;
    public Person(String name, Integer age) {
        super();
        this.name = name;
        this.age = age;
    }

    public String toString() {
        return "Person [name= " + name + ", age= " + age + "]";
    }
}

序列化对象时所需要保存的就是对象中的属性,所以默认情况下对象的属性将被转为二进制数据流存在。

序列化与反序列化操作
如果要想实现序列化与反序列化的对象操作,在java.io包中提供有两个处理类:ObjectOutputStream、ObjectInputStream

首先来观察这两个类的定义结构及其各自的构造方法

ObjectOutputStream类:

类的定义
public class ObjectOutputStream extends OutputStream implements ObjectOutput, ObjectStreamConstants
构造方法
public ObjectOutputStream(OutputStream out) throws IOExection
普通方法
public final void writeObject(Object obj) throws IOExection

ObjectInputStream类:

类的定义
public class ObjectInputStream extends InputStream implements ObjectInput, ObjectStreamConstants
构造方法
public ObjectInputStream(InputStream in) throws IOExection

对象序列化ObjectOutputStream
这里写图片描述

对象反序列化ObjectInputStream
这里写图片描述

例:实现对象序列化

class Person implements Serializable {
    private String name;
    private Integer age;
    public Person(String name, Integer age) {
        super();
        this.name = name;
        this.age = age;
    }

    public String toString() {
        return "Person [name= " + name + ", age= " + age + "]";
    }
}

public class Test {
    public static final File FILE = new File("C:"+File.separator+"Users"+File.separator+"贵军"+
                File.separator+"Desktop"+ File.separator+"hello.txt");
    public static void main(String[] args) throws FileNotFoundException, IOException {
        ser(new Person("zhangsan", 20));
    }
    public static void ser(Object obj) throws FileNotFoundException, IOException {
        ObjectOutputStream objectOutputStream =
                new ObjectOutputStream(new FileOutputStream(FILE));
        objectOutputStream.writeObject(obj);
        objectOutputStream.close();
    }
}

运行结果,将Person类的对象转变为二进制数据流保存在指定路径的文件中
这里写图片描述

例:实现对象反序列化
只需要修改上面的ser(Object obj)方法为 dser()方法

public static void dser() throws FileNotFoundException, IOException, ClassNotFoundException {
    ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(FILE));
    System.out.println(objectInputStream.readObject());
    objectInputStream.close();
}

会将上面文件中序列化的Person对象的内容反序列化,输出为
这里写图片描述

transient关键字(理解)
实际上序列化的处理在java.io包里面有两类,Serializable是使用最多的序列化接口,这种操作采用自动化模式完成,也就是说默认情况下所有的属性都会被序列化下来。
还有一个Externalizable接口是需要用户自己动手来处理序列化,一般很少使用。
但是由于Serializable默认会将对象中所有属性进行序列化保存,如果现在某些属性不希望被保存了,那么就可以使用transient关键字。

例:使用transient

class Person implements Serializable {
    private transient String name;          //使用transient关键字,防止序列化
    private Integer age;
    public Person(String name, Integer age) {
        super();
        this.name = name;
        this.age = age;
    }

    public String toString() {
        return "Person [name= " + name + ", age= " + age + "]";
    }
}

public class Test {
    public static final File FILE = new File("C:"+File.separator+"Users"+File.separator+"贵军"+
                File.separator+"Desktop"+ File.separator+"hello.txt");
    public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
        ser(new Person("zhangsan", 20));        //序列化操作
        dser();                                 //反序列化
    }
    public static void ser(Object obj) throws FileNotFoundException, IOException {
        ObjectOutputStream objectOutputStream =
                new ObjectOutputStream(new FileOutputStream(FILE));
        objectOutputStream.writeObject(obj);
        objectOutputStream.close();
    }
    public static void dser() throws FileNotFoundException, IOException, ClassNotFoundException {
        ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(FILE));
        System.out.println(objectInputStream.readObject());
        objectInputStream.close();
    }
}

将Person对象中name属性使用transient修饰,则属性name不会进行序列化保存,因此序列化出的内容明显比上面例子中少
这里写图片描述

然后反序列化,可以看见属性name的值并没有保存,得到的是String类的缺省值
这里写图片描述

大部分情况下使用序列化往往是在简单java类上,其他类上使用序列化的操作模式相对较少。而如果是简单java类,很少去使用transient关键字了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值