Java之序列化和反序列化

概念

序列化:把对象转换为字节序列的过程称为对象的序列化。

反序列化:把字节序列恢复为对象的过程称为对象的反序列化。

目的

① 方便进行数据传输。在分布式系统中,需要把对象在网络上传输,所以需要把对象数据转换为二进制形式。

② 节省服务器内存。如果服务器发现某些对象好久没有活动了,那么服务器就会把这些内存中的对象持久化在本地磁盘文件中(Java对象转换为二进制文件);如果服务器发现某些对象需要活动时,先去内存中寻找,找不到再去磁盘文件中反序列化对象数据,将其恢复为Java对象。

实现

① 实现Serializable或者Externalizable接口。Externalizable接口继承自Serializable接口,实现Externalizable接口的类完全由自身来控制序列化的行为,而仅实现Serialzable接口的类可以采用默认的序列化方式。

② 对象序列化

   (1) 创建一个对象输出流ObjectOutputStream,它可以包装一个其他类型的目标输出流,如文件输出流。

   (2) 通过对象输出流的writeObject()方法写对象。

扫描二维码关注公众号,回复: 2821423 查看本文章

③ 对象反序列化

   (1) 创建一个对象输入流ObjectInputStream,它可以包装一个其他类型的源输入流,如文件输入流。

   (2) 通过对象输入流的readObject()方法读取对象。

例子

① 建立一个JavaBean用于序列化和反序列化

/**
 * 定义一个Person类,实现Serializable接口
 * @author N.Y
 *
 */
public class Person implements Serializable{
    /**
     * 序列化ID
     */
    private static final long serialVersionUID = -5809782572943999L;
    private int age;
    private String name;
    private transient String sex;  //transient关键字可以使sex这个变量不能被序列化,拥有static关键词的变量也不可以被序列化和反序列化
//详情可以参考这篇文章:https://blog.csdn.net/qq_27093465/article/details/78544505
public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public static long getSerialversionuid() { return serialVersionUID; } }

② 利用ObjectOutputStream和ObjectInputStream来实现对象的序列化和反序列化

public class TestObjSerializeAndDeserialize {
    public static void main(String[] args) throws IOException, Exception {
        SerializePerson(); //序列化Person对象
        Person p = DeserializePerson(); //反序列化Person对象
        System.out.println(MessageFormat.format("name={0}, age={1}, sex={2}", p.getName(), p.getAge(), p.getSex()));
        
    }
    
    /**
     * 序列化Person对象
     * @throws FileNotFoundException
     * @throws IOException
     */
    private static void SerializePerson()throws FileNotFoundException, IOException{
        Person person = new Person();
        person.setName("Nicole");
        person.setAge(19);
        person.setSex("男");
        //ObjectOutputStream对象输出流,将Person对象存储到person.txt文件中,完成对Person对象的序列化
        ObjectOutputStream oo = new ObjectOutputStream(new FileOutputStream(new File("person.txt")));
        oo.writeObject(person);
        System.out.println("Person对象序列化成功.");
        oo.close();
    }
    
    private static Person DeserializePerson() throws Exception,IOException{
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("person.txt")));
        Person person = (Person)ois.readObject();
        System.out.println("Person对象反序列化成功.");
        return person;
    }
}

serialVersionUID的作用

  固定版本,因为serialVersionUID取值是Java运行时环境根据类的内部细节自动生成的,只要class文件稍有改变其生成的serialVersionUID就截然不同了,而且也有可能换了个编译器它的serialVersionUID也会不同;可以根据版本号来进行反序列化。

  为了提高serialVersionUID的独立性和确定性,建议在一个可序列化类中显式定义serialVersionUID,为它赋予明确的值。一是为了确保类的不同版本具有相同的serialVersionUID,二是即使在某些场合中不希望类的不同版本对序列化兼容,那显式定义serialVersionUID可以确保类的不同版本具有不同的serialVersionUID。

参考:

https://blog.csdn.net/qq_27093465/article/details/78544505

https://www.cnblogs.com/ysocean/p/6870069.html

https://www.cnblogs.com/xdp-gacl/p/3777987.html

猜你喜欢

转载自www.cnblogs.com/NYfor2018/p/9495209.html