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

单例模式实现方式有多种,例如懒汉模式(等用到时候再实例化),饿汉模式(类加载时就实例化)等,这里用饿汉模式方法实现,也就是类加载就实例化,单例模式应用场景有很多,比如一个应用有一套窗口化界面,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

最新文章

  1. android图像与图像处理系列(一、Bitmap和BitmapFactory)
  2. FreeCodeCamp 高级算法(个人向)
  3. 如何用火车头采集当前页面url网址
  4. UVA-11468 Substring(AC自动机+DP)
  5. C# 把引用的dll嵌入到exe文件中
  6. php中函数不确定参数个数时获取所有参数
  7. How to Design Programs, Second Edition
  8. Python 学习笔记4
  9. 关于li标签之间的间隔如何消除!
  10. Java 连接 MySQL 数据库
  11. 651. 4 Keys Keyboard复制粘贴获得的最大长度
  12. Django之form总结
  13. jasperReport和Ireport
  14. CodeForces ~ 996
  15. iOS 获取沙盒文件路径及 写入/删除 沙盒文件
  16. [ASP.NET Core] 建置x86版本 (workaround)
  17. 本机不装Oracle,使用plsql连接远程Oracle的方法
  18. Object类、常用API
  19. PageHelper 记录总条数不正确问题处理
  20. 兼容性强、简单、成熟、稳定的RTMPClient客户端拉流功能组件EasyRTMPClient

热门文章

  1. 2017年当下最值得你关注的前端开发框架,不知道你就OUT了!
  2. Python之Queue模块
  3. mysql b-tree 索引下联合索引的顺序测试方案
  4. javascript执行机制
  5. 使用Angular Router导航基础
  6. BST 解析 (二)height and deletion
  7. poj2485 highwaysC语言编写
  8. PHP通过ZABBIX API获取主机信息 VS 直接从数据库获取主机信息
  9. MySql的技术规范-企业版(来源于MySql官网)
  10. TensorFlow —— Demo