前言

《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;
}
}

解释一下为什么这样写:

  1. 我们让一个类仅实例化一次,自然不能让它随便的去做 new 的操作,因此 Singleton 的无参构造方法是私有的。
  2. instance是Singletion的静态成员。
  3. 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;
}

使用单一元素的枚举类是实现单例的最佳方式。因为无偿的提供了序列化机制。

总结

这篇笔记主要说了实现单例的三种方式,它们的优先级如下:

单一元素的枚举类 > 私有构造方法(使用静态工厂模式)> 私有构造方法(使用无参构造方法

我们应该搞清楚的是哪里用单例,这三种创建单例的方法有什么优点

最新文章

  1. 日期格式转换 java 2016-09-03T00:00:00.000+08:00
  2. AS3中 Event 类的target和currentTarget属性
  3. 解决asp.net Core Mvc网页汉字乱码问题
  4. python数据结构之二叉树遍历的实现
  5. Linux(9.28-10.4)学习笔记
  6. [leetcode]_Remove Nth Node From End of List
  7. iOS定位 (一) 地图定位
  8. phpExcel导出excel的类,每步都有说明
  9. CocoaPods容易出现的问题;
  10. web 电子商务网站开发笔记整理
  11. [iOS]C语言技术视频-17-指针变量高级用法练习二(使用堆内存完成链表结构的存储)
  12. C++ 常量类型 const 详解
  13. 似是而非的JS - 异步调用可以转化为同步调用吗?
  14. 题解 P1601 【A+B Problem(高精)】
  15. js原生倒计时
  16. Java 多线程之自旋锁
  17. InnoDB和MyISAM的区别
  18. OpenStack实践系列④计算服务Nova
  19. Leetcode 863. 二叉树中所有距离为 K 的结点
  20. AndroidStudio使用偷懒插件Butterknife和GsonFormat

热门文章

  1. openfeign 使用方法和执行流程
  2. 解决tomcat控制台乱码问题
  3. Django组件总结
  4. 集群Session一致性和同步问题
  5. 设备驱动基础学习--/proc下增加节点
  6. 【Vue CLI】从安装到构建项目再到目录结构的说明
  7. 喵星之旅-狂奔的兔子-centos7安装MySQL 5.5
  8. 一周搞定模拟电路P2_二极管介绍_记录
  9. [转]Serverless
  10. python 的集合