本文参考

本篇文章参考自《Effective Java》第三版第三条"Enforce the singleton property with a private constructor or an enum type"

原文的不足之处

原文给的示例代码比较简单,提供的是一种饿汉式的单例模式

// Singleton with public final field
public class Elvis {
    public static final Elvis INSTANCE = new Elvis();
    private Elvis() { ... }
    public void leaveTheBuilding() { ... }
}

我们也可以将INSTANCE实例的pulice改为private,通过另一个静态方法获取实例

// Singleton with static factory
public class Elvis {
    private static final Elvis INSTANCE = new Elvis();
    private Elvis() { ... }
    public static Elvis getInstance() { return INSTANCE; }
    public void leaveTheBuilding() { ... }
}

构造器的private关键字修饰使得无法通过new关键字创建其它实例,final关键字的修饰使得INSTANCE总是包含相同的对象引用,这两种写法都能保证全局下仅有一个Elvis类的实例化对象

因为饿汉模式下,全局的单例实例在类装载时就进行构建,可能由于初始化的太早,会造成资源的浪费,所以有另一种懒汉式的单例模式,但原文中未做介绍,因为它在多线程下存在实例重复构建的问题,若要解决这个问题,会加大文章篇幅,而且也不是第三条建议的重点,更多关于懒汉式的单例模式可以参考这篇文章:

https://www.jianshu.com/p/eb30a388c5fc

the best way to implement a singleton —— a single-element enum type

Java的枚举类型是一个特殊的class,并继承了Enum<T>类,若Singleton必须扩展一个超类,而不是扩展Enum 时,则不宜使用如下方法

public class Elvis {

  private Elvis() {
  }

  public static Elvis getInstance() {

    return Singleton.INSTANCE.getInstance();
  }

  /**
   *
注意声明为private
   */

  private enum
Singleton {

    INSTANCE;

    private Elvis singleton;

    /**
     *
仅执行一次

     */

    Singleton() {

      singleton = new Elvis();
    }

    public Elvis getInstance() {

      return singleton;
    }
  }
}

因为Enum<T>类实现了Serializable接口,所以为INSTANCE自动提供了序列化机制,并且编译器会为枚举类型的实例自动添加 public static final 修饰,所以枚举类型的无参构造方法仅会被执行一次

原文也指出这种方式能够应对复杂的序列化或者反射攻击的情形

provides the serialization machinery for free, and provides an ironclad guarantee against multiple instantiation, even in the face of sophisticated serialization or reflection attacks.

Effective Java —— 用私有构造器或枚举类型强化单例属性的更多相关文章

  1. 《Effective Java》-——用私有构造器或者枚举类型强化Singleton属性

    Singleton指仅仅被实例化一次的类.Singleton通常被用来代表那些本质上唯一的系统组件,比如窗口管理器或者文件系统.使类成为Singleton会使它的客户端测试变得十分困难,因为无法给Si ...

  2. 用私有构造器或枚举类型强化Singleton

    Singleton指只有一个实例的类,只能被创建一次. 在Java1.5之前实现Singleton有两种方式,都是将构造器设为private并导出公有的静态成员实例. 第一种方式将公有的静态成员实例设 ...

  3. 《effective java》读书札记第三条用私有构造器或者枚举类型强化Singleton属性

    Singleton指只被实例化一次的类.一般用来搞那些创建很耗资源或者要求系统中只能有一个实例的类. 这个很经常使用.记得曾经实习面试的时候就有这个面试题. 一般採用的方法是将构造器私有化,然后提供一 ...

  4. Effective Java 之 --- 用私有构造器或者枚举类型强化Singleton属性

    Singleton指仅仅被实例化一次的类,通常用来代表那些本质上唯一的系统组件,实现Singleton有三种方法: 1)公有静态成员是个final域,享有特权的用户可以调用AccessibleObje ...

  5. 【读书笔记 - Effective Java】03. 用私有构造器或者枚举类型强化Singleton属性

    实现Singleton(代表本质上唯一的系统组件)的三种方法: 1. 保持私有构造器,导出公有的静态成员,客户端访问该类的唯一实例. 2. 保持私有构造器,公有的成员是静态工厂方法. 3. 单元素的枚 ...

  6. 创建和销毁对象——用私有构造器或者枚举类型强化Singleton属性

    参考资料:<Effective Java>.<Java核心技术 卷1>.https://www.cnblogs.com/zhaosq/p/10135362.html 基础回顾 ...

  7. 用私有构造器或者枚举类型强化Singleton属性

    1.Singleton指仅仅被实例化一次的类.Singleton通常被用来代表那些本质上唯一的系统组件,如窗口管理器或者文件系统.使类称为Singleton会使它的客户端调试变的十分困难,因为无法给S ...

  8. 第3条:用私有构造器或者枚举类型强化Singleton属性

    Singleton是指仅仅被实例化一次的类.通过被用来代表那些本质上唯一的系统组件,比如窗口管理器或者文件系统. 在http://www.cnblogs.com/13jhzeng/p/5256424. ...

  9. 第3项:用私有构造器或者枚举类型强化Singleton属性

      Singleton指仅仅被实例化一次的类 [Gamma95].Singleton通常代表无状态的对象,例如函数(第24项)或者本质上唯一的系统组件.使类称为Singleton会使它的客户端测试变得 ...

随机推荐

  1. 通过shell脚本批量操作mysql数据库

    创建建表语句 ============================================= 学生表:Student(Sno,Sname,Ssex,Sage,Sdept) ------(学 ...

  2. EasyUI Datagrid 数据网格

    前端用easyUI开发时,官方给的文档指导太少,网上找的又很慢,因此,我总结了一个后台返回数据后,用easyUI生成表格的方法,可编辑可分页: 1 function paginationTable(i ...

  3. IntelliJ:JUnit单元测试

    0.参考 在Intellij IDEA中添加JUnit单元测试 - 唐啊唐囧囧 - 博客园 1.引言 JUnit是Java中很出名的一个单元测试,关于JUnit的具体介绍,可以看之前写的编写JUnit ...

  4. Pycharm:Python2和3及其的Anaconda的正确设置

    这两天学习需要用到第三方库pyKriging,然而电脑之前下载的是Python2.7,pyKriging只支持Python3.6,尝试了很多方法也无果后,只好重新下载Python3.6,由于在网上查到 ...

  5. Docker-生成镜像、服务搭建(redis集群、kibana、运行项目jar包)、上传镜像至阿里云

    目录 生成自己的镜像 1.下载官方tomcat镜像 2.运行镜像后将webapp目录里新增文件(官方镜像是没有页面的 具体操作见) 3.使用docker ps -a 查看刚刚修改后的容器id 4.执行 ...

  6. Python:pyglet学习(1):想弄点3D,还发现了pyglet

    某一天,我突然喜欢上了3D,在一些scratch教程中见过一些3D引擎,找了一个简单的,结果z轴太大了,于是网上一搜,就发现了pyglet 还是先讲如何启动一个窗口 先看看官网: Creating a ...

  7. tp5 数据库迁移及数据填充

    1:首先通过 composer 安装    原命令加空格 1.* 2:创建 3:填入数据 4:运行,刷新数据库 数据填充: 1:在命令行输入以下命令 composer require fzaninot ...

  8. 如何构建一个PKM系统

    原文链接 这篇文章是个人知识总结相关的第一篇文章,主要目的是为了阐述我们为什么需要一个 PKM 系统,并且简单对自己这几年亲身形成的PKM 系统进行总结. PKM 是什么? PKM 是 Persona ...

  9. Open Babel的安装与使用

    技术背景 Open Babel是化学领域常用的一个文件格式转换工具,它可以支持xyz的坐标格式.SMILES表达式.InChI表达式和mol以及mol2等格式之间的互相转化.比如说,你只有一个甲烷的S ...

  10. java-关于java

    JavaSE(标准版) JavaME(嵌入式)(淘汰) JavaEE(E企业级开发) JavaSE是基础 API端口 JDK Java开发工具 JRE Java运行时环境 JVM 虚拟机 可以在软件和 ...