Effective第三版 中英 | 第2章 创建和销毁对象 | 用私有构造器或者枚举类型强化 Singleton 属性

news2025/1/6 20:55:58

文章目录

  • Effective第三版
    • 前言
    • 第二章 创建和销毁对象
      • 用私有构造器或者枚举类型强化 Singleton 属性

Effective第三版

前言

大家好,这里是 Rocky 编程日记 ,喜欢后端架构及中间件源码,目前正在阅读 effective-java 书籍。同时也把自己学习该书时的笔记,代码分享出来,供大家学习交流,如若笔记中有不对的地方,那一定是当时我的理解还不够,希望你能及时提出。如果对于该笔记存在很多疑惑,可以先去翻阅《Java核心技术》也欢迎和我交流讨论,最后也感谢您的阅读,点赞,关注,收藏~

前人述备矣,我只是知识的搬运工,effective 书籍源码均在开源项目 java-diary 中的 code-effective-third 模块中

源代码仓库地址: https://gitee.com/Rocky-BCRJ/java-diary.git
在这里插入图片描述

第二章 创建和销毁对象

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

   A singleton is simply a class that is instantiated exactly once [Gamma95]. Singletons typically represent either a stateless object such as a function (Item 24) or a system component that is intrinsically unique. Making a class a singleton can make it difficult to test its clients because it’s impossible to substitute a mock implementation for a singleton unless it implements an interface that serves as its type.

  Singleton 指仅仅被实例化一次的类 [Gamma95]。Singleton 通常代表无状态的对象,例如函数(第 24 项)或者本质上唯一的系统组件。使类成为 Singleton 会使它的客户端测试变得十分困难,因为除非它实现了作为其类型的接口,否则不可能将模拟实现替换为单例。

  There are two common ways to implement singletons. Both are based on keeping the constructor private and exporting a public static member to provide access to the sole instance. In one approach, the member is a final field:

  实现单例的方法有两种。 两者都基于保持构造函数私有并导出公共静态成员以提供对唯一实例的访问。 在一种方法中,该成员是 final 字段:

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

  The private constructor is called only once, to initialize the public static final field Elvis.INSTANCE. The lack of a public or protected constructor guarantees a “monoelvistic” universe: exactly one Elvis instance will exist once the Elvis class is initialized—no more, no less. Nothing that a client does can change this, with one caveat: a privileged client can invoke the private constructor reflectively (Item 65) with the aid of the AccessibleObject.setAccessible method. If you need to defend against this attack, modify the constructor to make it throw an exception if it’s asked to create a second instance.

  私有构造器只调用一次,用来初始化静态变量Elvis.INSTANCE。由于缺少public或者protect属性的构造器,这就保证了Elvis的全局一致性:一旦Evlis类被实例化,只会存在一个Elvis实例,不多也不少。客户端所做的任何事情都无法改变这一点,但有一点需要注意:享有特权的客户端可以借助AccessibleObject.setAccessible方法反射性地调用私有构造函数(第 65 项)。如果你需要防御此攻击,请修改构造函数以使其在要求创建第二个实例时抛出异常。

  In the second approach to implementing singletons, the public member is a static factory method:

  在实现 Singleton 的第二种方法中,公有的成员是个静态工厂方法:

// 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() { ... }
}

  All calls to Elvis.getInstance return the same object reference, and no other Elvis instance will ever be created (with the same caveat mentioned earlier).

  对于静态方法Elvis.getInstance的所有调用,都会返回同一个对象引用,所以,永远不会创建其他的Elvis实例(上述提醒依然适用)。

  The main advantage of the public field approach is that the API makes it clear that the class is a singleton: the public static field is final, so it will always contain the same object reference. The second advantage is that it’s simpler.

  公有域方法的主要好处在于,组成类的成员的声明很清楚地声明了这个类是一个 Singleton:公有的静态域是 final 的,所以该域总是包含同一个对象的引用。第二个好处就是它更加简单。

  One advantage of the static factory approach is that it gives you the flexibility to change your mind about whether the class is a singleton without changing its API. The factory method returns the sole instance, but it could be modified to return, say, a separate instance for each thread that invokes it. A second advantage is that you can write a generic singleton factory if your application requires it (Item 30). A final advantage of using a static factory is that a method reference can be used as a supplier, for example Elvis::instance is a Supplier. Unless one of these advantages is relevant, the public field approach is preferable.

  工厂方法的优势之一在于,它提供了灵活性:在不改变其 API 的前提下,我们可以改变类是否应该为 Singleton 的想法。工厂方法返回唯一实例,但是,它可以很容易被修改,比如改成每个调用该方法的线程返回一个唯一的实例。第二个优点是,如果你的应用需要,你可以编写泛型单例工厂(第 30 项)。使用静态工厂的最后一个优点是一个方法引用可以当成一个提供者,例如Elvis::instance提供的是<Elvis>。除非跟这些优点有所关联,否则使用公有域的方法更可取。

  To make a singleton class that uses either of these approaches serializable(Chapter 12), it is not sufficient merely to add implements Serializable to its declaration. To maintain the singleton guarantee, declare all instance fields transient and provide a readResolve method (Item 89). Otherwise, each time a serialized instance is deserialized, a new instance will be created, leading, in the case of our example, to spurious Elvis sightings. To prevent this from happening, add this readResolve method to the Elvis class:

  为了利用这其中一种方法实现的 Singleton 类变成可序列化的(第 12 章),仅仅在声明中加上“implements Serializable”是不够的。为了维护并保证 Singleton,必须声明所有实例域都是瞬时(transient)的,并提供一个readResolve方法(第 89 项)。否则,每次反序列化时,都会创建一个新的实例,在我们的示例中,会导致“假冒的 Elvis”。为了防止这种情况,要在 Elvis 类中加入下面这个 readResolve 方法:

// readResolve method to preserve singleton property
private Object readResolve() {
    // Return the one true Elvis and let the garbage collector
    // take care of the Elvis impersonator.
    return INSTANCE;
}

  实现 Singleton 还有第三种方法。只需要编写一个包含单个元素的枚举类型:

// Enum singleton - the preferred approach
public enum Elvis {
    INSTANCE;
    public void leaveTheBuilding() { ... }
}

  This approach is similar to the public field approach, but it is more concise, provides the serialization machinery for free, and provides an ironclad guarantee against multiple instantiation, even in the face of sophisticated serialization or reflection attacks. This approach may feel a bit unnatural, but a single-element enum type is often the best way to implement a singleton. Note that you can’t use this approach if your singleton must extend a superclass other than Enum(though you can declare an enum to implement interfaces).

  这种方法类似于使用公有域的方法,但它更简洁,免费提供序列化机制,并提供了对多个实例化的铁定保证,即使面对复杂的序列化或反射攻击。这种方法可能会有点不自然,但单元素枚举类型通常是实现单例的最佳方法。请注意,如果你的单例必须扩展Enum以外的超类,则不能使用此方法(尽管你可以声明枚举来实现接口)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/599654.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何在本地配置Github的项目--Python

如何在本地配置Github的项目 0. 引言1. 初步预览2. 配置环境2.1 环境已经给出2.2 环境未曾给出 3. 数据配置4. 依次调试5. 配置完成总结 0. 引言 Github上存在大量的代码。当下载下来后可能会存在疑惑&#xff1a;如何在本地配置对应的项目呢&#xff1f; 为了帮助新手解决这一…

【Android开发基础】购物车代码整理

文章目录 一、数据库设计二、Home界面三、购物车模块四、添加五、源代码 这个月总算忙完了&#xff0c;总算能够抽出时间来&#xff0c;认真写一下博客了。整理一下购物车的代码 一、数据库设计 基于SqLite简单设计一个数据存储逻辑 实体&#xff08;接收数据&#xff09; im…

【数据加密】古典密码Playfair

文章目录 一、引言1、主要任务2、分支3、密码体制分类4、攻击密码系统 二、普莱费厄体制1、构造字母表&#xff0c;设为密钥矩阵2、设立加密方法3、加密解密4、字典集合5、结果 一、引言 1、主要任务 解决信息的保密性和可认证问题&#xff0c;保证信息在生成、传递、处理、保…

Swin-Transformer详解

Swin-Transformer详解 0. 前言1. Swin-Transformer结构简介2. Swin-Transformer结构详解2.1 Patch Partition2.2 Patch Merging2.3 Swin Transformer Block2.3.1 W-MSA2.3.2 SW-MSA 3. 模型配置总结 0. 前言 Swin-Transformer是2021年微软研究院发表在ICCV上的一篇文章&#x…

数据的存储(浮点型)

目录 浮点型存储的规则 1.前面我们已经学过了整形在数据中的存储是以原码&#xff0c;反码&#xff0c;补码的形式在内存中存储的&#xff0c;那么浮点数是以什么样的形式存储的呢&#xff1f; 接下来我们通过一段代码来观察——> int main() {int n 9;float* p (float*…

String AOP的使用

面向切面编程&#xff0c;面向特定方法编程&#xff0c;以方法为对象&#xff0c;在不修改原方法的基础上&#xff0c;对方法进行操作扩展等&#xff0c;底层是通过动态代理实现的 使用开发步骤&#xff1a; 1、创建一个类&#xff0c;加上Aspect声明为一个AOP切面类&#xff…

2023 重新开始

感觉搞 IT 的日子最近都有点不太好过。 早上接到公司电话说今天是一个大日子。 为什么是大日子&#xff0c;相信所有人都是懂的。这次公司将会经历一次非常大的裁员&#xff0c;很不幸也在列表中。不过感觉这个好像也没有什么关系。 因为早就在意料之中的事情&#xff0c;经历…

c语言之结构体(初阶)

目录 1&#xff1a;结构体类型的声明 2&#xff1a;结构体初始化 3&#xff1a;结构体成员访问 4&#xff1a;结构体传参 1&#xff1a;结构体类型的声明 1&#xff1a;为啥要有结构体&#xff0c;因为当我们描述一个复杂对象的时候&#xff0c;可能平时我们的一个类型不能…

常见的五种排序

&#x1f436;博主主页&#xff1a;ᰔᩚ. 一怀明月ꦿ ❤️‍&#x1f525;专栏系列&#xff1a;线性代数&#xff0c;C初学者入门训练&#xff0c;题解C&#xff0c;C的使用文章&#xff0c;「初学」C &#x1f525;座右铭&#xff1a;“不要等到什么都没有了&#xff0c;才下…

批量提取某音视频文案(二)

牙叔教程 简单易懂 之前写过一篇 批量提取某音视频文案 , 在之前的教程中, 我用的是微软的语音转文字功能, 今天我们换个方法, 使用 逗哥配音 的 文案提取 功能 准备工作 下载视频和音频 我在github找到的是这个仓库 https://github.com/Johnserf-Seed/TikTokDownload 注意一…

VLANIF虚接口案例实践

1&#xff09;拓扑 2&#xff09;需求&#xff1a; -所有PC能够ping通自己的网关 -实现vlan间互通&#xff0c;实现所有的PC互通 3&#xff09;配置步骤&#xff1a; 第一步&#xff1a;给pc配置IP地址 第二步&#xff1a;交换机创建vlan,做access和trunk -所有的交换机都配…

传统图形学对nerf的对比与应用落地

作者今年参加了China3DV的盛会&#xff0c;大会的发表、线下讨论、学者、工业界等等的交流着实对于Nerf有了更深的思考&#xff0c;以下是作者的抛砖引玉&#xff0c;如有不当之处敬请指出~ 传统图形学与nerf的简介&#xff1a; 传统图形学&#xff1a;显示表达几何表达方式&…

【CloudCompare教程】010:点云的裁剪功能(分段、裁剪、筛选)

本文讲解CloudCompare点云的裁剪功能(分段、裁剪、筛选)。 文章目录 一、点云的分段二、点云的裁剪三、点云的筛选一、点云的分段 加载案例点云数据,如下图所示: 选中图层点云,点击工具栏中的【分割】工具。 点击【激活线状选择】工具: 在需要裁剪的点云上绘制现状裁剪范…

使用免费的SSL证书将nginx配置的普通网站修改为HTTPS网站

一、需求说明 已经在Centos8系统中使用nginx搭建了网站;但是该网站没有实现HTTPS协议不安全;现需要将网站升级为HTTPS站点。 Linux环境对Nginx开源版源码下载、编译、安装、开机自启https://blog.csdn.net/xiaochenXIHUA/article/details/130265983?spm=1001.2014.3001.5501

chatgpt赋能python:Python交易接口简介

Python交易接口简介 Python作为一种高级编程语言&#xff0c;被广泛用于各种不同的领域&#xff0c;其中包括金融市场交易。Python交易接口提供了一种优雅而简单的方式&#xff0c;使得交易者能够方便地执行自己的交易策略。 什么是Python交易接口&#xff1f; Python交易接…

Effective第三版 中英 | 第2章 创建和销毁对象 | 考虑静态工厂方法而不是构造函数

文章目录 Effective第三版第2章 创建和销毁对象前言考虑静态工厂方法而不是构造函数 Effective第三版 第2章 创建和销毁对象 前言 大家好&#xff0c;这里是 Rocky 编程日记 &#xff0c;喜欢后端架构及中间件源码&#xff0c;目前正在阅读 effective-java 书籍。同时也把自己…

基于SSM的人才招聘网站

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

模拟实现库函数:strcpy

目录 通过cplusplus网站了解函数功能&#xff1a; 断言assert的使用&#xff1a; 关于const&#xff1a; 本篇你最应该了解的内容&#xff1a; 通过cplusplus网站了解函数功能&#xff1a; 要模拟实现库函数&#xff0c;首先我们需要了解这个函数的参数&#xff0c;函数的…

主机加固介绍

最近公司做服务器安全&#xff0c;开始在市场了解产品&#xff0c;对这一块算是短暂的研究了一段时间&#xff0c;有一点心得给大家分享一下。 主机加固 最近主机加固的概念被炒得火热&#xff0c;主机加固的功能也正在被致力于服务器安全的相关人士所关注。 那么究竟什么是主…

【CVPR2022】CSWin Transformer详解

【CVPR2022】CSWin Transformer详解 0. 引言1. 网络结构2. 创新点2.1 Cross-Shaped Window Self-Attention2.2 Locally-Enhanced Positional Encoding(LePE) 3. 实验总结 0. 引言 Transformer设计中一个具有挑战性的问题是&#xff0c;全局自注意力的计算成本非常高&#xff0…