《Effective Java》作者是美国的Joshua Bloch,连Gosling都说需要看的书,讨论的是更深层次的Java开发技术,适合于有一定Java基础的人看。

这是一本分享经验于指引您少走弯路的经典著作,针对如何编写高效、设计优良的程序提出了最实用的方针。

Item1 考虑用静态工厂方法代替构造器

1、优点

可读性强。

不会每次调用就通过构造器创建一个新的实例。

可以返回原始类型的任何子类型。

2、缺点

只有私有构造器无法被子类化。

Item 2 遇到多个构造器参数考虑用构建器Builder

1、传统的重叠构造器模式

public class NutritionFacts {
private final int servingSize; // (mL) required
private final int servings; // (per container) required
private final int calories; // (per serving) optional
private final int fat; // (g/serving) optional
private final int sodium; // (mg/serving) optional
private final int carbohydrate; // (g/serving) optional public NutritionFacts(int servingSize, int servings) {
this(servingSize, servings, 0);
} public NutritionFacts(int servingSize, int servings,
int calories) {
this(servingSize, servings, calories, 0);
} public NutritionFacts(int servingSize, int servings,
int calories, int fat) {
this(servingSize, servings, calories, fat, 0);
} public NutritionFacts(int servingSize, int servings,
int calories, int fat, int sodium) {
this(servingSize, servings, calories, fat, sodium, 0);
}
public NutritionFacts(int servingSize, int servings,
int calories, int fat, int sodium, int carbohydrate) {
this.servingSize = servingSize;
this.servings = servings;
this.calories = calories;
this.fat = fat;
this.sodium = sodium;
this.carbohydrate = carbohydrate;
} public static void main(String[] args) {
NutritionFacts cocaCola =
new NutritionFacts(240, 8, 100, 0, 35, 27);
} }

  

如果读者想了解那些值是什么意思,必须很费劲的仔仔细细的数着这些参数来探究。如果客户端不小心颠倒了这些参数的顺序,编译器也不会报错,但是程序在运行时会出现错误行为。

JavaBeans模式

public class NutritionFacts {
// Parameters initialized to default values (if any)
private int servingSize = -1; // Required; no default value
private int servings = -1; // Required; no default value
private int calories = 0;
private int fat = 0;
private int sodium = 0;
private int carbohydrate = 0; public NutritionFacts() { }
// Setters
public void setServingSize(int val) { servingSize = val; }
public void setServings(int val) { servings = val; }
public void setCalories(int val) { calories = val; }
public void setFat(int val) { fat = val; }
public void setSodium(int val) { sodium = val; }
public void setCarbohydrate(int val) { carbohydrate = val; } public static void main(String[] args) {
NutritionFacts cocaCola = new NutritionFacts();
cocaCola.setServingSize(240);
cocaCola.setServings(8);
cocaCola.setCalories(100);
cocaCola.setSodium(35);
cocaCola.setCarbohydrate(27);
}
}

  

这样实例创建很容易,客户端代码读起来很清晰明朗,但是,程序员需要付出额外的努力来确保它的线程安全

Builder模式

public class NutritionFacts {
private final int servingSize;
private final int servings;
private final int calories;
private final int fat;
private final int sodium;
private final int carbohydrate; public static class Builder {
// Required parameters
private final int servingSize;
private final int servings; // Optional parameters - initialized to default values
private int calories = 0;
private int fat = 0;
private int sodium = 0;
private int carbohydrate = 0; public Builder(int servingSize, int servings) {
this.servingSize = servingSize;
this.servings = servings;
} public Builder calories(int val)
{ calories = val; return this; }
public Builder fat(int val)
{ fat = val; return this; }
public Builder sodium(int val)
{ sodium = val; return this; }
public Builder carbohydrate(int val)
{ carbohydrate = val; return this; } public NutritionFacts build() {
return new NutritionFacts(this);
}
} private NutritionFacts(Builder builder) {
servingSize = builder.servingSize;
servings = builder.servings;
calories = builder.calories;
fat = builder.fat;
sodium = builder.sodium;
carbohydrate = builder.carbohydrate;
} public static void main(String[] args) {
NutritionFacts cocaCola = new NutritionFacts.Builder(240, 8)
.calories(100).sodium(35).carbohydrate(27).build();
}
}

  

builder设置方法返回this,形成了链式调用,这个一个流式的API,客户端代码很容易编写,更为重要的是易于阅读。

2、使用构建器的好处。

在多参数时写法优雅,参数具有可读性,保证线程安全,适合类的继承。

3、使用构建器的坏处。

花费会更高,因此在参数有许多的时候建议使用,特别是有很多可选参数时。

Item 3 Singleton的最佳实现方式是枚举类型

1、什么是枚举类

public class EnumTest {
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
System.out.println("put:");
String input=in.next().toUpperCase();
Size size=Enum.valueOf(Size.class,input);
System.out.println(size);
System.out.println(size.getAbbreviation());
System.out.println(Size.SMALL.getAbbreviation());
} }
enum Size{
SMALL("S"),MEDIUM("M"),LARGE("L");
private String abbreviation;
private Size(String abbreviation){this.abbreviation=abbreviation;}
public String getAbbreviation(){return abbreviation;} }

  

2、优点

提供序列化机制,甚至在反射机制下也能确保只有单例。

3、缺点

无法继承自除了Enum之外的超类以及其他子类进行继承。

Item 4 通过私有构造器强化不可实例化的能力

1、优点

在需要创建类似工具类等不需要实例化的类时,将构造器私有化,以保证该类在任何情况下都不会被实例化。

2、缺点

无法被继承

Item 5 使用依赖注入去连接资源

1、依赖注入

public class dependency {
private final String str; public dependency(String str) {
this.str = str;
}
}

  

2、优点

对于一个行为由其他资源所参数化所决定的类来说,使用静态工具类或者单例是不适合的。而是应该当创建一个实例是将资源传入构造器。

Item 6 避免创建不必要的对象

1、优点

对于一些不会发生改变的变量或是常量,使用static块进行初始化,使某些类不会被重复创建,减少开销。例如 new String就是一个不好的习惯。

在构造器中使用静态工厂就是个不错的方法。重点是对静态的使用static(final)。自动装箱也很可能引起巨大的开销。

Item 7消除过期的对象引用

1、优点

例如对于Stack类中的数组当执行pop()操作后,被弹出的元素并不会自动被gc所回收。因此需要手动进行释放。

    public Object pop() {
if (size == 0)
throw new EmptyStackException();
Object result = elements[--size];
elements[size] = null; // Eliminate obsolete reference
return result;
}

  

当一个类自己进行内存的管理时,这种状况就尤其要注意。

进行缓存时也需要注意这个问题。

对于监听器以及回调操作,也需要注意。

Item 8 尽量避免使用Finalizers

1、优点

由于Finalizers的优先级很低,不能保证Finalizers何时会被调用,会导致内存开销的增加,并且会大幅降低程序的性能。

永远不要Finalizers来更新持久状态。

对含有Finalizers方法的类进行子类化会有严重的安全隐患。

使用try-with-resources作为某些资源的结束方法。并且对于其状态是否被关闭需要在私有域中进行记录。这样其他方法调用时可以对状态进行检测。

Finalizers有两种合理的用法:

1、在忘记调用close方法时作为一张安全网,但这也只是一个不得以的备用措施,仍然会造成很大开销,并且不知何时会进行。

2、native peer (?)

Item 9 更偏向使用 try-with-resources 块

1、try-with-resources

在try()中进行一个或多个的资源链接或读取。并且这些资源是必须被关闭的的,使用这个语法将会被自动关闭无需显示调用close方法。

在{}进行实际操作。

同样可以使用catch语句

    static void copy(String src, String dst) throws IOException {
try (InputStream in = new FileInputStream(src);
OutputStream out = new FileOutputStream(dst)) {
byte[] buf = new byte[BUFFER_SIZE];
int n;
while ((n = in.read(buf)) >= 0)
out.write(buf, 0, n);
}
}

  

2、优点

可以同时打开多个资源,并保证被关闭,而无需显式调用close方法。

exception不会被覆盖,可以查看每个exception.

参考:《Effective Java》第3版

参考:https://www.cnblogs.com/WutingjiaWill/p/9139520.html

Effective Java 3的更多相关文章

  1. Effective java笔记(二),所有对象的通用方法

    Object类的所有非final方法(equals.hashCode.toString.clone.finalize)都要遵守通用约定(general contract),否则其它依赖于这些约定的类( ...

  2. 《Effective java》-----读书笔记

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

  3. 《Effective Java》学习笔记——积累和激励

    从一个实际案例说起 国庆长假前一个礼拜,老大给我分配了这么一个bug,就是打印出来的报表数量为整数的,有的带小数位,有的不带,毫无规律. 根据短短的两个多月的工作经验以及猜测,最终把范围缩小到以下这段 ...

  4. Effective Java笔记一 创建和销毁对象

    Effective Java笔记一 创建和销毁对象 第1条 考虑用静态工厂方法代替构造器 第2条 遇到多个构造器参数时要考虑用构建器 第3条 用私有构造器或者枚举类型强化Singleton属性 第4条 ...

  5. effective java 读后感

    think in java  , effective java  这两本书一直都在java的生态圈中经久不衰.本来想着先翻过 think in java 这本大山,但是读到一半就放弃了.过长的篇幅,让 ...

  6. Effective java读书笔记

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

  7. effective java —— 终结方法守卫者

    目录: effective java —— 终结方法守卫者 effective java 第2章:创建和销毁对象.第7条 : 避免使用终结方法.最后的“终结方法守卫者 (finalizer guard ...

  8. Effective Java 创建和销毁对象

    <Effective Java>阅读笔记,用适合自己理解的方式提炼该书内容.<Effective Java>是一本很实用的书,阅读方法应该是快速的领会,总结,然后应用.而非,一 ...

  9. Effective Java

    Effective Java 创建和销毁对象---考虑用静态工厂方法代替构造器 构造器是创建一个对象实例最基本也最通用的方法,大部分开发者在使用某个class的时候,首先需要考虑的就是如何构造和初始化 ...

  10. Effective Java Index

    Hi guys, I am happy to tell you that I am moving to the open source world. And Java is the 1st langu ...

随机推荐

  1. Dijkstra+Heap模板

    普通Dijkstra: void DijkstraPath(int v0,int vis[],int dist[],int path[]) { int onePath[maxn]; int d; in ...

  2. ios9 字符串与UTF-8 互相转换

    在数据网路请求或其他情况下,需要将字符串转换成UTF-8编码 ios9后对其方法进行了修改 NSString *str = @"北京"; 把这个转成UTF8以前我们使用的是 NSS ...

  3. iOS音频学习笔记三:音频会话管理

    ​      使用Audio Session API ,可以指定App需要的音频行为,比如,当播放音频时,使得其他应用App静音或者混和在一起,也可以指定当App的音频被中断(例如被电话)时的行为,还 ...

  4. javascript_14-对象

    什么是对象 生活中的对象,一个车.一个手机 对象具有特性和行为 面向对象和基于对象 面向对象:可以创建自定义的类型.很好的支持继承和多态.面向对象的语言有 c++ .Java. C# ... 面向对象 ...

  5. JSON【1】

    http://repo1.maven.org/maven2/com/fasterxml/jackson/core/    JSON[jar]包下载 JSON是什么? 是一种轻量级的数据交换格式,完全独 ...

  6. Spring 的 @Primary 注解

    简单的说,就是当Spring容器扫描到某个接口的多个 bean 时,如果某个bean上加了@Primary 注解 ,则这个bean会被优先选用,如下面的例子: @Component public cl ...

  7. Vue 中的Vue Router一级路由,二级路由,三级路由以及跳转

    今天编写了一下Vue中的路由 先用命令行新建一个空的项目,并且我知道要用路由,就下载了路由的相关依赖 vue init webpack demo5 完毕之后进入所在的项目 cd demo5 之后用vs ...

  8. IDEA实用教程(二)

    2. 基础设置 1) 进入全局设置 2) 更改主题 3) 修改主题字体 4) 修改代码编辑区字体 5) 修改控制台字体 图中3处修改控制台字体 图中4处修改控制台字体 6) 文件编码的设置 图中4处建 ...

  9. MySQL 主从复制 详细实例讲解 与 常见错误解决方法

    一.主机ip 192.168.0.128 ,从机ip:192.168.0.130 分别测试是否能ping通对方,如果不能,请关闭防火墙或开放对应端口 二.主服务器配置 1.备份主服务器的数据 mysq ...

  10. Selenium常用API的使用java语言之8-模拟鼠标操作

    通过前面例子了解到,可以使用click()来模拟鼠标的单击操作,现在的Web产品中提供了更丰富的鼠标交互方式, 例如鼠标右击.双击.悬停.甚至是鼠标拖动等功能.在WebDriver中,将这些关于鼠标操 ...