今天看啥  ›  专栏  ›  江湖非良人

对象序列化

江湖非良人  · 简书  ·  · 2019-07-31 13:20

  几乎只要是Java开发,就一定会存在有序列化的概念,而正因为序列化的概念逐渐发展,慢慢也有了更多的序列化标准。

序列化简介 Serializable

  所谓的对象序列化指的是将内存中保存的对象以二进制数据流的形式进行处理,可以是实现对象的保存和网络传输。

对象序列化

然而并不是所有的对象都可以被序列化,在Java中有有一个强制性的要求:一个对象如果要进行序列化,那么这个对象所在的类一定要实现java.io.Serializable父接口,作为序列化的标记,这个接口并没有任何的方法,因为它描述的是一种类的能力。
范例:定义一个可以被序列化的类

import java.io.Serializable;
@SuppressWarnings("serial")
class Person implements Serializable {//Person类可以被序列化
    private String name;
    private int age;
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    @Override
    public String toString() {
        return "姓名:" + name + "、年龄:" + age;
    }
}

此时Person类产生的每个对象都可以实现二进制的数据传输,属于可以被序列化的程序类。

序列化ObjectOutputStream

反序列化ObjectInputStream

  有了序列化的支持类后,如果想要实现序列化和反序列化就可以利用以下两个类:

  • ObjectOutputStream:
public class ObjectOutputStream extends OutputStream implements ObjectOutput, ObjectStreamConstants

  构造方法:
    public ObjectOutputStream​(OutputStream out) throws IOException
  操作方法:
    public final void writeObject​(Object obj) throws IOException

  • ObjectOutputStream:
public class ObjectInputStream extends InputStream implements ObjectInput,ObjectStreamConstants

  构造方法:
    public ObjectInputStream​(InputStream in) throws IOException
  操作方法:
    public final Object readObject() throws IOException, ClassNotFoundException
范例:实现序列化与反序列化

import java.io.*;
@SuppressWarnings("serial")
class Person implements Serializable {//Person类可以被序列化
    private String name;
    private int age;
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    @Override
    public String toString() {
        return "姓名:" + name + "、年龄:" + age;
    }
}
public class JavaApiDemo {
    private static final File SAVE_FILE=new File("/Users/fzc/Documents/mydir/mldn_serial.person");
    public static void main(String[] args) throws Exception {
        Object person=new Person("张三",21);
        System.out.println(person);//姓名:张三、年龄:21
        saveObject(person);
        Object p2= loadObject();
        System.out.println(p2);//姓名:张三、年龄:21
    }
    public static void saveObject(Object object)throws Exception{
        ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream(SAVE_FILE));
        oos.writeObject(object);//序列化
        oos.close();
    }
    public static Object loadObject()throws Exception{
        ObjectInputStream oos=new ObjectInputStream(new FileInputStream(SAVE_FILE));
        Object object= oos.readObject();
        oos.close();
        return object;
    }
}

在Java中的对象序列化与反序列化必须使用内部提供的对象操作流,因为这里面涉及到了二进制数据的格式,所以不能自定义处理,另外如果想要实现一组对象的序列化,则可以使用对象数组完成。
在大多数实际项目开发中,很少能见到ObjectOutputStream、ObjectInputStream类的直接操作,因为会有一些容器帮助开发者自动实现。

transient关键字

  默认情况下当执行了对象的序列化时,会将类中的全部属性的内容进行全部的序列化,但是很多情况下,有一些属性可能并不需要进行序列化的处理,这个时候就可以在属性定义上使用transient关键字来完成了。

private transient Integer age;
在进行序列处理时,age属性的内容是不会被保存下来的,换言之,读取的数据age将时其对应数据类型的默认值”null“。如果假设类中有一些是需要计算保存的属性内容往往是不需要被序列化的,这时就可以使用transient,但是在实际开发中,大部分需要被序列化的雷往往都是java的简单类,所以这个关键字的出现频率并不高。




原文地址:访问原文地址
快照地址: 访问文章快照