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. ...
随机推荐
- 「题解」「JZOJ-4238」纪念碑
题目 在 \(N\times M\) 的网格中,有 \(P\) 个矩形建筑,求一个最大边长的正方形,使得网格中能找到一个放置正方形的地方,不会与建筑重合. 保证 \(N,M\le 10^6,P\le ...
- sqli-libs(23-28a关)
Less_23 首先在php文件中加入echo $sql;echo "<br>"; 方法一: :%00 输入?id=1’,报错,说明存在注入漏洞: 输入?id=1' - ...
- 关于使用阿里云MAVEN镜像仓库
由于国内的某些不可明确的原因 国内连接google的时候十分慢,使得看github上的项目十分慢,这里我们可以修改build.gradle下的文件来使用阿里云仓库同步 会更快: // Top-leve ...
- SpringMVC--提交表单
今天使用AbstractCommandController做一个提交表单的样例 (1)首先,建立一个User.java package com.zk.domain; import java.util. ...
- 3、示例(在java中使用JSON)
教程链接(json-smple1.1.1.jar文件) 链接:http://pan.baidu.com/s/1qXPbYHm 密码:v0f0 如何使用java编程语言编码和解码JSON 首先准备环境以 ...
- Python函数基础进阶
函数参数的另一种使用方式 def print_info(name,age): print("Name: %s" %name) print("age: %d" % ...
- Spring_第一个Spring入门案例IOC
今天我们来写我们的第一个spring 第一步 建立一个java project 第二步 添加我们的五个jar文件 第三步 在项目中建立一个com.zk.spring包 第四步 建立我们的userser ...
- Jekyll本地搭建开发环境以及Github部署流程
转载自: http://www.jianshu.com/p/f37a96f83d51 前言 博客从wordpres迁移到Jekyll上来了,整个过程还是很顺利的.Jekyll是什么?它是一个简单静态博 ...
- C语言:将字符串中的前导*号全部移到字符串的尾部。
//规定输入的字符串中只包含字母和*号,fun函数:将字符串中的前导*号全部移到字符串的尾部. #include <stdio.h> void fun( char *a ) { ]; ch ...
- C语言:把分数最低的学生数据放入数组b所指的数组中,-从键盘输入若干字符串,写入文件myfile4中,用-1作字符输入结束的标志,
//学生记录由学号和成绩组成,N名学生的数据已放入主函数中的结构体数组中,fun函数:把分数最低的学生数据放入数组b所指的数组中,分数最低的学生可能不止一个.人数返回. #include <st ...