第四条:通过私有构造器强化不可实例化的能力

有时可能需要编写只包含静态方法和静态域的类,这样的工具类不希望被实例化,因为实例化对它来说没有意义。

然而,在缺少显式构造器的情况下,系统会自动提供一个缺省构造,但这种类又不能设计为抽象类,因为它不希望被继承,也不希望它的子类能实例化。

所以,可以为其提供一个显式的私有构造器,保证不能从类的外部调用构造,代码如下:

public class UtilityClass{
private UtilityClass(){
throw new AssertionError(); //AssertionError可以避免不小心在类内调用构造
} ...... }

这种习惯做法也有副作用,它使得一个类不能被子类化。

第五条:优先考虑依赖注入来引用资源

第六条:避免创建不必要的对象

当你应该重用现有对象的时候,请不要创建新的对象。

一般来说,最好能重用单个对象,而不是在每次需要的时候就创建一个新对象,如果对象是不可变的(详见17条),它就始终可以被重用。

反面例子如下:

String s = new String("wuhu");

该语句每次执行的时候都创建一个新的String实例,但这是不必要的,若该语句处于循环中,就会创造出成千上万不必要的String实例。

所以,正确的应该这样做:

String s = "wuhu";

这个版本只用了一个String实例,而且可以保证,对于所有在同一台虚拟机中运行的代码,只要字符串相同,该对象就会被重用。

对于同时提供了静态工厂方法和构造器的不可变类,通常优先使用静态工厂方法而不是构造器,以避免创建不必要的对象。例如,静态工厂方法Boolean valueOf(String)几乎总是优先于构造器Boolean(String)(该构造在java9中已被废弃)。构造器每次调用都会创建一个对象,而静态工厂方法不会。除了重用不可变的对象之外,也可以重用那些已知不会被修改的可变对象。

静态工厂方法详见此处关于 Java 的静态工厂方法,看这一篇就够了! - 简书 (jianshu.com)

有些对象创建成本很高,如果需要重复使用,建议将其缓存下来重用。如以下实例:

static boolean isRomanNumeral(String s){
return s,matches(....); //此处为正则表达式
}

String.matches方法虽然最易于查询一个字符串是否与正则表达式相匹配,但并不适合在注重性能的情形下重复使用。原因在于,它在内部为正则表达式创建了一个Pattern实例,却只用了一次,之后就可以进行垃圾回收了。创建Pattern实例的成本很高,因为需要将正则表达式编译为一个有限状态机。

为了提升性能,应显式的将正则表达式编译成一个Pattern实例(不可变),让它成为类初始化的一部分,并将其缓存起来,每当调用isRomanNumeral方法时就重用同一个实例,如下:

public class RomanNumerals{
private static final Pattern ROMAN = Pattern.compile(...);
static boolean isRomanNumeral(String s){
return ROMAN.matcher(s).matches();
}
}

如果一个对象是不变的,那么它显然能够被安全的重用,但其他有些情形则并不这么明显。考虑适配器的情形,有时也叫做视图。

适配器模式详见适配器模式 | 菜鸟教程 (runoob.com)

例如,Map接口的keyset方法返回Map对象的Set视图,其中包含该Map中所有的键,对于给定的Map对象,每次调用keySet实际上都返回同样的Set实例,虽然返回的Set实例一般是可改变的,但是所有返回的对象在功能上都是等同的:其中一个返回对象发生变化时,所有其他的返回对象也要发生变化,因为它们是由同一个Map实例支撑的。

另一种创建多余对象的方法,称为自动装箱。请看如下代码:

private static long sum(){
Long sum = 0L;
for(long i = 0; i <= Integer.MAX_VALUE; i++)
sum += i;
return sum;
}

这段程序算出的答案是正确的,但是比实际情况要更慢一点,因为变量sum被声明为Long而不是long,意味着每次先Long sum中增加一个long时都要构造一个实例,所以:要优先使用基本类型而不是装箱基本类型,要当心无意识的自动装箱。

Effective java 读书笔记(2)的更多相关文章

  1. Effective Java读书笔记完结啦

    Effective Java是一本经典的书, 很实用的Java进阶读物, 提供了各个方面的best practices. 最近终于做完了Effective Java的读书笔记, 发布出来与大家共享. ...

  2. Effective java读书笔记

    2015年进步很小,看的书也不是很多,感觉自己都要废了,2016是沉淀的一年,在这一年中要不断学习.看书,努力提升自己 计在16年要看12本书,主要涉及java基础.Spring研究.java并发.J ...

  3. Effective Java 读书笔记(一):使用静态工厂方法代替构造器

    这是Effective Java第2章提出的第一条建议: 考虑用静态工厂方法代替构造器 此处的静态工厂方法并不是设计模式,主要指static修饰的静态方法,关于static的说明可以参考之前的博文&l ...

  4. Effective Java 读书笔记之九 并发

    一.访问共享的可变数据时要同步 1.synchronized关键字既然保证访问的可见性也能保证原子性.而volatile修饰符只能保证变量的线程可见性. 2.增量操作符等不是原子性,多线程操作时可能导 ...

  5. Effective Java 读书笔记之七 通用程序设计

    一.将局部变量的作用域最小化 1.在第一次使用变量的地方声明 2.几乎每个变量的声明都应该包含一个初始化表达式:try-catch语句是一个例外 3.使方法小而集中是一个好的策略 二.for-each ...

  6. Effective Java 读书笔记之一 创建和销毁对象

    一.考虑用静态工厂方法代替构造器 这里的静态工厂方法是指类中使用public static 修饰的方法,和设计模式的工厂方法模式没有任何关系.相对于使用共有的构造器来创建对象,静态工厂方法有几大优势: ...

  7. [Effective Java读书笔记] 第二章 创建和销毁对象(1~7)

    我的技术博客经常被流氓网站恶意爬取转载.请移步原文:http://www.cnblogs.com/hamhog/p/3537576.html,享受整齐的排版.有效的链接.正确的代码缩进.更好的阅读体验 ...

  8. Effective Java读书笔记——第三章 对于全部对象都通用的方法

    第8条:覆盖equals时请遵守通用的约定 设计Object类的目的就是用来覆盖的,它全部的非final方法都是用来被覆盖的(equals.hashcode.clone.finalize)都有通用约定 ...

  9. Effective Java 读书笔记(五):Lambda和Stream

    1 Lamdba优于匿名内部类 (1)DEMO1 匿名内部类:过时 Collections.sort(words, new Comparator<String>() { public in ...

  10. Effective Java 读书笔记(四):泛型

    1 不要使用原始类型 (1)术语 术语 例子 参数化类型(Parameterized type) List<String> 实际类型参数(Actual type parameter) St ...

随机推荐

  1. Jmeter系列(27)- 常用逻辑控制器(6) | 如果(if)控制器If Controller

    如果(if)控制器(If Controller) 在实际工作中,当使用JMeter做性能脚本或者接口脚本时,当遇到需要对不同的条件做不同的操作时,我们可以使用JMeter中if控制器来实现 if控制器 ...

  2. Shell系列(6)- 管道符

    多命令顺序执行 多命令执行符 格式 作用 ; 命令1 ; 命令2 连接命令:多个命令顺序执行,命令之间没有任何逻辑联系:前面命令报错,后面命令照常执行 && 命令1 && ...

  3. ci框架驱动器

    1.驱动器什么是 驱动器是一种特殊类型的类库,它有一个父类和任意多个子类.子类可以访问父类, 但不能访问兄弟类.在你的控制器中,驱动器为你的类库提供了 一种优雅的语法,从而不用将它们拆成很多离散的类. ...

  4. django使用celery搭配redis配置定时任务

    已经安装环境: Python3.6 django==2.1.8(用2.2.2需要升级sqlite3) 项目名称:ceshiproject   APP名称:ceshi 第一步:centos7下首先安装r ...

  5. Centos7 安装 .Net Core2.2

    添加 rpm 源 sudo rpm -Uvh https://packages.microsoft.com/config/centos/7/packages-microsoft-prod.rpm 开始 ...

  6. 【原创】linux mint 17.3 kvm 安装windows7虚拟机

    一.安装windows7虚拟机 linux mint 17.3是一个不错的桌面发行版本,我下载了 linux mint 17.3 for xfce 桌面版本,运行速度没得说,而且安装设置都挺简单,非常 ...

  7. P5445-[APIO2019]路灯【set,树状数组套线段树】

    正题 题目链接:https://www.luogu.com.cn/problem/P5445 题目大意 \(n+1\)个点,\(i\)和\(i+1\)个点之间有一条边,\(q\)个操作 断开/连接第\ ...

  8. 基于SpringBoot+Mybatis plus+React.js实现条件选择切换搜索功能

    笔记/朱季谦 在写React前端逻辑时,经常遇到可以切换不同条件的列表查询功能,例如下边截图这样的,其实,这块代码基本都一个逻辑,可以一次性将实现过程记录下来,待以后再遇到时,直接根据笔记复用即可. ...

  9. 小白学习Python英语基础差怎么办,都帮你想好拉!看这里

    运算符与随机数 1.module:模块 2.sys(system):系统 3.path:路径 4.import:导入 5.from:从- 定义函数与设定参数 1.birthday:出生日期 2.yea ...

  10. 请求既有multipartFile,也有实体的解决方案

    上回书我们说到,我们在发文件上传请求的时候,携带数据 this.fileData.append('trainName', this.dataModel.trainName); // 添加培训名称 然后 ...