effective java笔记之单例模式与序列化
单例模式:“一个类有且仅有一个实例,并且自行实例化向整个系统提供。”
单例模式实现方式有多种,例如懒汉模式(等用到时候再实例化),饿汉模式(类加载时就实例化)等,这里用饿汉模式方法实现,也就是类加载就实例化,单例模式应用场景有很多,比如一个应用有一套窗口化界面,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笔记之单例模式与序列化的更多相关文章
- Effective Java笔记一 创建和销毁对象
Effective Java笔记一 创建和销毁对象 第1条 考虑用静态工厂方法代替构造器 第2条 遇到多个构造器参数时要考虑用构建器 第3条 用私有构造器或者枚举类型强化Singleton属性 第4条 ...
- Effective java笔记(二),所有对象的通用方法
Object类的所有非final方法(equals.hashCode.toString.clone.finalize)都要遵守通用约定(general contract),否则其它依赖于这些约定的类( ...
- effective java笔记之java服务提供者框架
博主是一名苦逼的大四实习生,现在java从业人员越来越多,面对的竞争越来越大,还没走出校园,就TM可能面临失业,而且对那些增删改查的业务毫无兴趣,于是决定提升自己,在实习期间的时间还是很充裕的,期间自 ...
- Effective java笔记(十),序列化
将一个对象编码成字节流称作将该对象「序列化」.相反,从字节流编码中重新构建对象被称作「反序列化」.一旦对象被「序列化」后,它的编码就可以从一台虚拟机传递到另一台虚拟机,或被存储到磁盘上,供以后「反序列 ...
- Effective java笔记(一),创建与销毁对象
1.考虑用静态工厂方法代替构造器 类的一个实例,通常使用类的公有的构造方法获取.也可以为类提供一个公有的静态工厂方法(不是设计模式中的工厂模式)来返回类的一个实例.例如: //将boolean类型转换 ...
- Effective java笔记(六),方法
38.检查参数的有效性 绝大多数方法和构造器对于传递给它们的参数值都会有限制.如,对象引用不能为null,数组索引有范围限制等.应该在文档中指明所有这些限制,并在方法的开头处检查参数,以强制施加这些限 ...
- effective java 笔记1--序言
一.序言 程序设计的几条基本原则: 1.清晰性和简洁性最为重要,模块的用户永远也不应该被模块的行为所迷惑,所以写良好的注释是必需的. 2.模块要竟可能小,但也不能太小,好一个深奥的哲学问题. 3.代码 ...
- Effective Java笔记
chapter 1 java支持四种类型:interface,class,array,primitive(基本类型) chapter 2 创建对象方式: ①构造器 ②静态工厂方法代替构造器:名称可以按 ...
- Effective Java 笔记
1. 静态工厂 静态工厂的第 5 个优点是,在编写包含该方法的类时,返回的对象的类不需要存在.他的意思是面向接口编程??就是说我们只需知道接口,具体实现类是否存在没有关系?? 只提供静态工厂方法的主要 ...
随机推荐
- Wordpress上传文件 “无法建立目录wp-content/uploads/2018/25。有没有上级目录的写权限?”
可能的原因有两个: wp-content/uploads 文件夹权限所限制 解决方法:修改wp-content/uploads 文件夹权限,可以借助ftp等工具: wp_options表中upload ...
- 【基础】Attribute的妙用
一.何为Attribute 下面是微软官方对Attribute的解释: 公共语言运行时允许你添加类似关键字的描述声明,叫做Attributes,它对程序中的元素进行标注,如类型.字段.方法和属性等.A ...
- C#获取存储过程的 Return返回值和Output输出参数值
1.获取Return返回值 程序代码 //存储过程//Create PROCEDURE MYSQL// @a int,// @b int//AS// return @a + ...
- Python小爬虫
网页解析器下载网址: http://www.crummy.com/software/BeautifulSoup/ ...
- 基于SwiperJs的H5/移动端下拉刷新上拉加载更多的效果
最早时,公司的H5项目中曾用过点击一个"加载更多"的DOM元素来实现分页的功能,后来又用过网上有人写的一个上拉加载更多的插件,那个插件是页面将要滚动到底部时就自动请求数据并插入到页 ...
- Winwos Server 2012发布ASP.NET MVC5 项目
一.本文实验环境: Windows Server 2012 R2 Visual Studio 2015 项目为:ASP.NET MVC 5.0,使用的是SQL SERVER 2008 R2数据库 二. ...
- 熟悉的“if __name__ == '__main__':”究竟是啥?
print(__name__) # 直接手动运行,打印"__main__",当做模块导入(别处import)时打印脚本名字即"name_main" if __n ...
- 小随笔:利用Shader给斯坦福兔子长毛和实现雪地效果
0x00 前言 发现最近没有了写长篇大论的激情,可能是到了冬天了吧.所以这篇小文只是简单介绍下如何在Unity中利用shader很简单的实现雪地效果以及毛皮效果,当然虽然标题写在了一起,但其实这是俩事 ...
- ASP.NET没有魔法——ASP.NET Identity 的“多重”身份验证
ASP.NET Identity除了提供基于Cookie的身份验证外,还提供了一些高级功能,如多次输入错误账户信息后会锁定用户禁止登录.集成第三方验证.账户的二次验证等,并且ASP.NET MVC的默 ...
- Pyhton编程(五)之基本数据类型-列表、元组、字典
一:列表(list) 列表是由一系列按特定顺序排列的元素组成,可以创建包含字母表中的所有字母.数字.或中文的列表,也可以将任何东西加入列表中,其中的元素之间可以没有任何关系. 在Python中,用方括 ...