单例模式:“一个类有且仅有一个实例,并且自行实例化向整个系统提供。”

单例模式实现方式有多种,例如懒汉模式(等用到时候再实例化),饿汉模式(类加载时就实例化)等,这里用饿汉模式方法实现,也就是类加载就实例化,单例模式应用场景有很多,比如一个应用有一套窗口化界面,Servlet中只有一个实例,应用很广泛

package com.test;

public class Singleton {

    private Singleton() {}
private static final Singleton INSTANCE = new Singleton(); //饿汉模式 public static Singleton getInstance() {
return INSTANCE;
}
}

单例模式基本上是每个java程序员都知道的,effective java第一章讲的是对象创建与销毁,看到单例模式在序列化中会失效时,这个是我之前所不知道的,于是查阅资料,并亲自验证一下,过程很简单,将上面的单例类实现Serializable接口

package com.test;

import java.io.Serializable;

public class Singleton implements Serializable{

    /**
* @Fields serialVersionUID : TODO
*/
private static final long serialVersionUID = -6367362518368424353L; private Singleton() {}
private static final Singleton INSTANCE = new Singleton(); public static Singleton getInstance() {
return INSTANCE;
}
}

是时候来验证一下了

package com.test;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream; public class Test {
public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
Singleton before = Singleton.getInstance(); //序列化,将对象写入到文件
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:\\objectFile"));
oos.writeObject(before);
oos.close(); //反序列化,读取文件,还原成对象
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D:\\objectFile"));
Singleton after = (Singleton) ois.readObject();
ois.close(); //验证结果
System.out.println(before == after);
}
}

输出:false

这说明一旦对象被序列化了,就破坏了单例模式,因为重新读取的对象已经不是之前的对象,它重新生成了一个!

那么问题来了,如何解决单例模式与序列化的矛盾?

effective给出了解决方法,只需添加一个readResolve方法,即

package com.test;

import java.io.Serializable;

public class Singleton implements Serializable{

    /**
* @Fields serialVersionUID : TODO
*/
private static final long serialVersionUID = -6367362518368424353L; private Singleton() {}
private static final Singleton INSTANCE = new Singleton(); public static Singleton getInstance() {
return INSTANCE;
} private Object readResolve() {
return INSTANCE;
}
}

再运行一下之前的测试类,发现结果又变成true了,说明反序列化单例模式没有被破坏!关于其中的原理可以参阅这篇博客 http://www.hollischuang.com/archives/1144

终极解决方法,枚举类!

使用起来极其简单,只需要

package com.test;

import java.io.Serializable;

public enum Singleton implements Serializable{
INSTANCE;
}

然后再测试一下

package com.test;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream; public class Test {
public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
Singleton before = Singleton.INSTANCE; //序列化
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:\\objectFile"));
oos.writeObject(before);
oos.close(); //反序列化
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D:\\objectFile"));
Singleton after = (Singleton) ois.readObject();
ois.close(); //验证结果
System.out.println(before == after);
}
}

输出结果为true

effective java笔记之单例模式与序列化的更多相关文章

  1. Effective Java笔记一 创建和销毁对象

    Effective Java笔记一 创建和销毁对象 第1条 考虑用静态工厂方法代替构造器 第2条 遇到多个构造器参数时要考虑用构建器 第3条 用私有构造器或者枚举类型强化Singleton属性 第4条 ...

  2. Effective java笔记(二),所有对象的通用方法

    Object类的所有非final方法(equals.hashCode.toString.clone.finalize)都要遵守通用约定(general contract),否则其它依赖于这些约定的类( ...

  3. effective java笔记之java服务提供者框架

    博主是一名苦逼的大四实习生,现在java从业人员越来越多,面对的竞争越来越大,还没走出校园,就TM可能面临失业,而且对那些增删改查的业务毫无兴趣,于是决定提升自己,在实习期间的时间还是很充裕的,期间自 ...

  4. Effective java笔记(十),序列化

    将一个对象编码成字节流称作将该对象「序列化」.相反,从字节流编码中重新构建对象被称作「反序列化」.一旦对象被「序列化」后,它的编码就可以从一台虚拟机传递到另一台虚拟机,或被存储到磁盘上,供以后「反序列 ...

  5. Effective java笔记(一),创建与销毁对象

    1.考虑用静态工厂方法代替构造器 类的一个实例,通常使用类的公有的构造方法获取.也可以为类提供一个公有的静态工厂方法(不是设计模式中的工厂模式)来返回类的一个实例.例如: //将boolean类型转换 ...

  6. Effective java笔记(六),方法

    38.检查参数的有效性 绝大多数方法和构造器对于传递给它们的参数值都会有限制.如,对象引用不能为null,数组索引有范围限制等.应该在文档中指明所有这些限制,并在方法的开头处检查参数,以强制施加这些限 ...

  7. effective java 笔记1--序言

    一.序言 程序设计的几条基本原则: 1.清晰性和简洁性最为重要,模块的用户永远也不应该被模块的行为所迷惑,所以写良好的注释是必需的. 2.模块要竟可能小,但也不能太小,好一个深奥的哲学问题. 3.代码 ...

  8. Effective Java笔记

    chapter 1 java支持四种类型:interface,class,array,primitive(基本类型) chapter 2 创建对象方式: ①构造器 ②静态工厂方法代替构造器:名称可以按 ...

  9. Effective Java 笔记

    1. 静态工厂 静态工厂的第 5 个优点是,在编写包含该方法的类时,返回的对象的类不需要存在.他的意思是面向接口编程??就是说我们只需知道接口,具体实现类是否存在没有关系?? 只提供静态工厂方法的主要 ...

随机推荐

  1. centos7安装python3和Django后,ModuleNotFoundError: No module named '_sqlite3'

    1.准备安装环境 yum groupinstall 'Development Tools' yum install zlib-devel bzip2-devel openssl-devel ncurs ...

  2. 能自学成为WEB前端工程师吗?

    自学是大家学习一门it技术的时候,都会首先考虑的一种学习方式,web前端开发学习也是一样,但是自学web前端也是让大家充满疑问的一种学习方 自学是大家学习一门it技术的时候,都会首先考虑的一种学习方式 ...

  3. .Net中各种不同的对象创建方式的速度差异

    在.Net中,微软给我们提供了很多不同的创建对象实例的方法,它们的速度又各有不同,以下一一列举. 使用new关键字 这在.Net中是最常见,也是速度最快的方式:                     ...

  4. C#中SQL语句参数写法

    OracleConnection oc=new OracleConnection("data source=osserver;User Id=****;password=**"); ...

  5. [转载] Java NIO与IO

    原文地址:http://tutorials.jenkov.com/java-nio/nio-vs-io.html 作者:Jakob Jenkov   译者:郭蕾    校对:方腾飞 当学习了Java ...

  6. oracle一些基本命令

    Oracle安装配置 设置四个账户及对应的密码 No. 用户名 口令 1 sys change_on_install 2 system manager 3 scott tiget 4 sh sh 上面 ...

  7. Javascript中prototype属性

    prototype作为JS相对比较难理解的一个知识点,在这里发表下自己的理解. 本文将包含以下几部分内容: 1.js prototype的简单介绍, 2.js构造函数的介绍, 3.prototype的 ...

  8. Shodan在渗透测试及漏洞挖掘中的一些用法

    渗透测试中,第一阶段就是信息搜集,这一阶段完成的如何决定了你之后的进行是否顺利,是否更容易.而关于信息收集的文章网上也是有太多.今天我们来通过一些例子来讲解如何正确使用Shodan这一利器. 想要利用 ...

  9. 关于svg

    动画:css3动画,canvas(js动画),svg(html动画). svg基本元素 version: 表示 <svg> 的版本,目前只有 1.0,1.1 两种 xmlns:http:/ ...

  10. 杭电ACM题单

    杭电acm题目分类版本1 1002 简单的大数 1003 DP经典问题,最大连续子段和 1004 简单题 1005 找规律(循环点) 1006 感觉有点BT的题,我到现在还没过 1007 经典问题,最 ...