03.使用私有构造方法或枚类实现 Singleton 属性
前言
《Effective Java》中文第三版,是一本关于Java基础的书,这本书不止一次有人推荐我看。其中包括我很喜欢的博客园博主五月的仓颉,他曾在自己的博文《给Java程序猿们推荐一些值得一看的好书》中也推荐过。加深自己的记忆,同时向优秀的人看齐,决定在看完每一章之后,都写一篇随笔。如果有写的不对的地方、表述的不清楚的地方、或者其他建议,希望您能够留言指正,谢谢。
《Effective Java》中文第三版在线阅读链接:https://github.com/sjsdfg/effective-java-3rd-chinese/tree/master/docs/notes
是什么
Singleton :单例,是指仅实例化一次的类,这个类表示无状态对象(无状态对象是指不能保存数据,没有实例变量的对象,线程安全的)。
哪里用
全局使用的类。这时候使用单例可以避免频繁的创建和销毁,并保证内存中对象的唯一,可以节省内存。同时,因为单例公用一个实例,有利于Java的垃圾回收机制。
例如我们实现一个功能:当前某网站在线人数(网站计数器),我们可以使用一个全局对象来记录。
怎么实现
- 私有构造方法
public class Singleton {
//私有无参构造函数
private Singleton() {}
//单例对象
private static final Singleton instance = new Singleton();
//静态工厂方法
public static Singleton getInstance() {
return instance;
}
}
解释一下为什么这样写:
- 我们让一个类仅实例化一次,自然不能让它随便的去做 new 的操作,因此 Singleton 的无参构造方法是私有的。
- instance是Singletion的静态成员。
- getInstance是获取单例对象的方法(我们也可以使用无参构造函数获取单例对象),getInstance是一个静态工厂方法,它相对于使用无参构造函数获取单例对象,有三个优势:更加灵活。比如,我们现在的需求,需要改变为每个调用该方法的线程返回一个唯一的实例(直接在静态工厂方法中 new instance(),但此时需要去掉单例对象中final修饰的关键字)。第二个优势是,如果应用程序需要他,我们可以将它改为一个泛型单例工厂。第三个优势是,可以通过方法引用来使用单例(有名字,第一章读书笔记中已经说明了无参构造方法与静态工厂方法的区别)。
为了防止单例类变成可序列化的,仅仅将添加 implements Serializable 到声明中是不够的。我们必须声明所有的实例字段为 transient,并提供一个 readResolve 方法。否则每当序列化的实例被反序列化时,都会创建一个新的实例,代码实现如下:
public class Singleton implements Serializable {
//私有无参构造函数
private Singleton() {}
//单例对象
private static final Singleton instance = new Singleton();
//静态工厂方法
public static Singleton getInstance() {
return instance;
}
//提供该方法,以便重新指定反序列化得到的对象.
public Object readResolve() {
return instance;
}
}
- 声明单一元素的枚举类,代码实现如下:
public enum Singleton02 {
INSTANCE;
}
使用单一元素的枚举类是实现单例的最佳方式。因为无偿的提供了序列化机制。
总结
这篇笔记主要说了实现单例的三种方式,它们的优先级如下:
单一元素的枚举类 > 私有构造方法(使用静态工厂模式)> 私有构造方法(使用无参构造方法)
我们应该搞清楚的是哪里用单例,这三种创建单例的方法有什么优点。
03.使用私有构造方法或枚类实现 Singleton 属性的更多相关文章
- Effective Java 第三版——3. 使用私有构造方法或枚类实现Singleton属性
Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...
- 【读书笔记 - Effective Java】03. 用私有构造器或者枚举类型强化Singleton属性
实现Singleton(代表本质上唯一的系统组件)的三种方法: 1. 保持私有构造器,导出公有的静态成员,客户端访问该类的唯一实例. 2. 保持私有构造器,公有的成员是静态工厂方法. 3. 单元素的枚 ...
- 《Effective Java》-——用私有构造器或者枚举类型强化Singleton属性
Singleton指仅仅被实例化一次的类.Singleton通常被用来代表那些本质上唯一的系统组件,比如窗口管理器或者文件系统.使类成为Singleton会使它的客户端测试变得十分困难,因为无法给Si ...
- 第3项:用私有构造器或者枚举类型强化Singleton属性
Singleton指仅仅被实例化一次的类 [Gamma95].Singleton通常代表无状态的对象,例如函数(第24项)或者本质上唯一的系统组件.使类称为Singleton会使它的客户端测试变得 ...
- 用私有构造器或者枚举类型强化Singleton属性
1.Singleton指仅仅被实例化一次的类.Singleton通常被用来代表那些本质上唯一的系统组件,如窗口管理器或者文件系统.使类称为Singleton会使它的客户端调试变的十分困难,因为无法给S ...
- 创建和销毁对象——用私有构造器或者枚举类型强化Singleton属性
参考资料:<Effective Java>.<Java核心技术 卷1>.https://www.cnblogs.com/zhaosq/p/10135362.html 基础回顾 ...
- 《effective java》读书札记第三条用私有构造器或者枚举类型强化Singleton属性
Singleton指只被实例化一次的类.一般用来搞那些创建很耗资源或者要求系统中只能有一个实例的类. 这个很经常使用.记得曾经实习面试的时候就有这个面试题. 一般採用的方法是将构造器私有化,然后提供一 ...
- Effective Java 之 --- 用私有构造器或者枚举类型强化Singleton属性
Singleton指仅仅被实例化一次的类,通常用来代表那些本质上唯一的系统组件,实现Singleton有三种方法: 1)公有静态成员是个final域,享有特权的用户可以调用AccessibleObje ...
- 第3条:用私有构造器或者枚举类型强化Singleton属性
Singleton是指仅仅被实例化一次的类.通过被用来代表那些本质上唯一的系统组件,比如窗口管理器或者文件系统. 在http://www.cnblogs.com/13jhzeng/p/5256424. ...
随机推荐
- select id from BS_BU_RULETYPE t start with t.PARENT_ID = 175 connect by t.PARENT_ID = prior t.id
select id from BS_BU_RULETYPE t start with t.PARENT_ID = 175 connect by t.PARENT_ID = prior t.id
- Java - 集合 - List
1.List实现类:ArrayList.LinkedList.Vector ArrayList使用: void test() { //声明 List<String> testlist = ...
- bugku 管理员系统
这一个是伪造ip X-FORWARDED-FOR:127.0.0.1 用到了XFF头 首先打开网站会发现一个登录界面 然后用开发者工具看一下 后台会发现一串用base64加密的密文 用base64解密 ...
- JVM的方法区和永久带是什么关系?
什么是方法区? 方法区(Method Area)是jvm规范里面的运行时数据区的一个组成部分,jvm规范中的运行时数据区还包含了:pc寄存器.虚拟机栈.堆.方法区.运行时常量池.本地方法栈. 方法区存 ...
- 7-8 Left-pad
思路 注意读入和输出格式 如果用fgets读入的话会带上回车,输出的时候一定不要输出了双回车 并且此时的length也会比原始长度多了一,要注意长度比较,这里容易出错 代码 #include < ...
- python+tkinter制作一个可自定义的动态时钟及详细解释,珍藏版
1.效果图 2.完整代码 #第1步:导出模块 from tkinter import * import math,time #第2步:定义窗口的相关设置 root = Tk() root.title( ...
- .net core 删除主表,同时删除子表
前提条件: 代码懒加载, 数据库有外键关联 var entity = context.主表.Include(o => o.子表).FirstOrDefault(p => p.Id == i ...
- 关于ActiveMq的Exception occurred while processing this request, check the log for more information!问题
错误原因:jsp渲染的时候报错了.根本原因在于jdk版本和activemq版本的问题. 两种解决方案: 1.把jdk版本改为jdk1.7 2.activeMQ采用5.15,它依赖于jdk1.8
- collections模块、时间模块、random模块、os模块、sys模块、序列化模块、subprocess模块
一.collections模块 1.其他数据类型 在内置数据类型(str.dict.list.tuple.set)的基础上,collections模块还提供了了几个额外的数据类型:Counter.de ...
- 如何利用wx.request进行post请求
1,method 是 get 方式的时候,会将数据转换成 query string method 为 post 时,header为{"Content-Type": " ...