Java序列化、反序列化和单例模式

学习JAVA的时候,特别是涉及到网络编程时,我们时常让我们的实体类实现一个接口

public class Entity implements Serializable{

}

这样子我们可以通过输入输出流ObjectOutputStream和ObjectInputStream写入或读取该对象。所以,简单来说,序列化就是把对象转换为字节数据流,反序列化就是把字节序列流转成相应的Java对象。使用序列化的最常用的两个场景:

1、需要把对象信息存储到磁盘文件中的时候,比如大量用户登录的Session信息

2、需要把对象信息通过网络传送的时候,需要传送字节流

实现java.io.Serializable接口之后,编辑器会给出警告,让你给出一个属性的定义:

private static final long serialVersionUID = 1L;

我们可以简单的认为,这是一个“类版本”的表示,不同的编辑器可能会对同一个类给出不同的值,类文件的细小改动也可能会产生不同的值,因为这个值在类变更之后起到了代码兼容的作用,一般规则如下:

1、两个不同版本的类,如果serialVersionUID相同,则说明反序列化兼容,以现有版本为模板反序列化

2、两个不同版本的类,如果serialVersionUID不同,说明反序列化不兼容,反序列化会失败

因此,我们的开发过程中,建议显示定义该值,并给以明确的定义,以方便兼容性判断。

下面代码示例,首先定义一个可序列化的实体对象:

package com.minlz.serialize;

import java.io.Serializable;

/**
 *  @author minliangzhi
 *  @date 2016年8月30日
 */
public class Person implements Serializable {

    private static final long serialVersionUID = 20160830001L;

    private String name;

    private int 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;
    }

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

然后给出一个序列化和反序列化的方法:

    public static void main(String[] args) throws Exception {
        Person p1 = new Person();
        p1.setName("Bruce Min");
        p1.setAge(25);
        System.out.println("p1: " + p1.toString());
        /** 序列化 */
        ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
        ObjectOutputStream objOut = new ObjectOutputStream(byteOut);
        objOut.writeObject(p1);

        /** 反序列化 */
        ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());
        ObjectInputStream objIn = new ObjectInputStream(byteIn);
        Person p2 = (Person)objIn.readObject();
        System.out.println("p2: " + p2.toString());
    }

显示的结果是:

p1: Person [name=Bruce Min, age=25]
p2: Person [name=Bruce Min, age=25]

通过上面的实例,大概对序列化和反序列化进行了介绍,需要注意的是,通过反序列获得对象不是原来的对象,即不满足“==”为真的情况,因为,如果我们是序列化一个单例实例的话,就会违反了单例模式的规定(虽然隐藏了单例的构造函数,但是JVM可以通过特殊手段,如反射来构造出对象)。实例如下:

单例类:

package com.minlz.serialize;

import java.io.Serializable;

/**
 *  @author minliangzhi
 *  @date 2016年8月30日
 */
public class Singleton implements Serializable {
    private static final long serialVersionUID = 1L;
    private static Singleton singleton;

    private Singleton() {

    }

    public synchronized static Singleton getInstance() {
        if(null == singleton) {
            singleton = new Singleton();
        }

        return singleton;
    }
}

序列化和反序列化的代码:

    public static void main(String[] args) throws Exception {
        Singleton s1 = Singleton.getInstance();

        System.out.println(s1);
        /** 序列化 */
        ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
        ObjectOutputStream objOut = new ObjectOutputStream(byteOut);
        objOut.writeObject(s1);

        /** 反序列化 */
        ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());
        ObjectInputStream objIn = new ObjectInputStream(byteIn);
        Singleton s2 = (Singleton)objIn.readObject();
        System.out.println(s2);
  }

测试结果:

[email protected]
[email protected]

可以容易看出来,两个对象不是同一个对象,解决方法是什么呢?

我们在Singleton类中增加一个方法:

    public Object readResolve(){
        return getInstance();
    }

发现测试结果是:

[email protected]
[email protected]

两个对象一致了,所以当面临单例模式实例化的时候,需要实现public Object readResolve()方法,并返回单例实例,就能实现序列化和反序列化对象一致。

时间: 2024-11-05 13:35:07

Java序列化、反序列化和单例模式的相关文章

java序列化反序列化深入探究

When---什么时候需要序列化和反序列化: 简单的写一个hello world程序,用不到序列化和反序列化.写一个排序算法也用不到序列化和反序列化.但是当你想要将一个对象进行持久化写入文件,或者你想将一个对象从一个网络地址通过网络协议发送到另一个网络地址时,这时候就需要考虑序列化和反序列化了.另外如果你想对一个对象实例进行深度拷贝,也可以通过序列化和反序列化的方式进行. What---什么是序列化和反序列化: Serialization-序列化:可以看做是将一个对象转化为二进制流的过程 Des

java序列化/反序列化之xml、protobuf、protostuff 的比较与使用例子

目录 1.背景 2.测试 2.1.环境 2.2.工具 2.3.说明 2.4.结果 2.5.结论 3.xml简单教程 3.1.准备 3.2.代码 4.protobuf简单教程 4.1.快速入门 1.下载.exe编译器 2.编写.proto文件 3.利用编译器编译.proto文件生成javabean 4.引用jar包 5.直接使用javabean自带的序列化.反序列化.提取属性等方法 5.protostuff简单教程 5.1.快速入门 1.引用jar包 2.直接使用相关序列化.反序列化语法 1.背景

java序列化之protobuf

package com.book.core.test; import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; import com.book.core.model.Type; import com.book.core.serializable.SerializationUtil; import com.dyuproject.protostuff.LinkedBuffer; import co

Java 序列化与反序列化

1.什么是序列化?为什么要序列化? Java 序列化就是指将对象转换为字节序列的过程,而反序列化则是只将字节序列转换成目标对象的过程. 我们都知道,在进行浏览器访问的时候,我们看到的文本.图片.音频.视频等都是通过二进制序列进行传输的,那么如果我们需要将Java对象进行传输的时候,是不是也应该先将对象进行序列化?答案是肯定的,我们需要先将Java对象进行序列化,然后通过网络,IO进行传输,当到达目的地之后,再进行反序列化获取到我们想要的对象,最后完成通信. 2.如何实现序列化 2.1.使用到JD

Java序列化1:序列化、反序列化和transient关键字的作用

网上讲Java序列化的文章很多,感觉很多都讲得不全,这篇文章希望可以全面地剖析Java的序列化机制.为什么要进行序列化和反序列化?我们写了一个Object,但那是Java虚拟机堆内存里面的东西,利用Object进行网络通信.IO操作的时候怎么会认识Java堆内存里面的东西?所以,需要序列化和反序列化机制的保障. 序列化:将一个对象转换成一串二进制表示的字节数组,通过保存或转移这些字节数据来达到持久化的目的. 反序列化:将字节数组重新构造成对象. 默认序列化 序列化只需要实现java.io.Ser

java序列化和反序列化

一.序列化和反序列化的概念 把对象转换为字节序列的过程称为对象的序列化. 把字节序列恢复为对象的过程称为对象的反序列化. 对象的序列化主要有两种用途: 1) 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中: 2) 在网络上传送对象的字节序列. 在很多应用中,需要对某些对象进行序列化,让它们离开内存空间,入住物理硬盘,以便长期保存.比如最常见的是Web服务器中的Session对象,当有 10万用户并发访问,就有可能出现10万个Session对象,内存可能吃不消,于是Web容器就会把一些s

java序列化与反序列化以及浅谈一下hadoop的序列化

1.什么是序列化和反序列化 神马是序列化呢,序列化就是把内存中的对象的状态信息,转换成字节序列以便于存储(持久化)和网络传输.(网络传输和硬盘持久化,你没有一定的手段来进行辨别这些字节序列是什么东西,有什么信息,这些字节序列就是垃圾). 反序列化就是将收到字节序列或者是硬盘的持久化数据,转换成内存中的对象. 2.JDK的序列化 JDK的序列化只有实现了serializable接口就能实现序列化与反序列化,但是记得一定要加上序列化版本ID serialVersionUID 这个是识别序列化的之前那

10.8-全栈Java笔记:序列化/反序列化的步骤和实例

本节我们详细讲解10.3节中提到的序列化和反序列化操作. 序列化和反序列化是什么 当两个进程远程通信时,彼此可以发送各种类型的数据. 无论是何种类型的数据,都会以二进制序列的形式在网络上传送.比如,我们可以通过http协议发送字符串信息:我们也可以在网络上直接发送JAVA对象.发送方需要把这个Java对象转换为字节序列,才能在网络上传送:接收方则需要把字节序列再恢复为Java对象. 把Java对象转换为字节序列的过程称为对象的序列化.把字节序列恢复为Java对象的过程称为对象的反序列化. 对象序

Java序列化与反序列化学习(三):序列化机制与原理

Java序列化算法透析 Serialization(序列化)是一种将对象以一连串的字节描述的过程:反序列化deserialization是一种将这些字节重建成一个对象的 过程.Java序列化API提供一种处理对象序列化的标准机制.在这里你能学到如何序列化一个对象,什么时候需要序列化以及Java序列化的算法,我们用 一个实例来示范序列化以后的字节是如何描述一个对象的信息的. 序列化的必要性 Java中,一切都是对象,在分布式环境中经常需要将Object从这一端网络或设备传递到另一端.这就需要有一种

Java序列化与反序列化(实践)

Java序列化与反序列化(实践) 基本概念:序列化是将对象状态转换为可保持或传输的格式的过程.与序列化相对的是反序列化,它将流转换为对象.这两个过程结合起来,可以轻松地存储和传输数据. 昨天在一本书上看到了,好好实践了一下,序列化为一般文件,也序列化为XML文件(使用XStream). 用于序列化的实体类Person.java    代码如下(记得需要实现Serializable接口):import java.io.Serializable; @SuppressWarnings("serial&