《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. DeepID_V2解读

    港中文汤晓鸥团队在DeepID_v1基础上提出的新版本架构,发表于NIPS2014 一.Architecture 网络架构基本上与DeepId_v1一致. 二.Pipeline 图片被分成20regi ...

  2. Mybatis之日志工厂

    思考:我们在测试SQL的时候,要是能够在控制台输出 SQL 的话,是不是就能够有更快的排错效率? 如果一个 数据库相关的操作出现了问题,我们可以根据输出的SQL语句快速排查问题. 对于以往的开发过程, ...

  3. Android NDK 学习之接受Java传入Object数组

    本博客主要是在Ubuntu 下开发,且默认你已经安装了Eclipse,Android SDK, Android NDK, CDT插件. 在Eclipse中添加配置NDK,路径如下Eclipse-> ...

  4. {T4模板}C# Net MVC+SqlServer=T4模板生成实体类并操作数据(DbHelper+DBManage)

    1.ConnectionString,数据库链接 Web.config <configuration> <connectionStrings> <!-- 数据库 SQL ...

  5. Harbor高可用理论及实践(汇聚篇)

    目录 一.理论概述 什么是harbor harbor要解决的问题 有了docker自带的registry为什么还要用harbor harbor的架构组件 Harbor工作原理 二.部署harbor及其 ...

  6. zabbix server搭建遇到的问题

    环境 CentOS 6.3 server nginx-1.6.3 MySQL-5.6.25 安装nginx遇到的问题 启动nginx时候提示错误“/usr/local/nginx/sbin/nginx ...

  7. VMware网络配置三种网络模式(桥接、NAT、Host-only)

    VMware网络配置三种网络模式(桥接.NAT.Host-only) 一.虚拟安装后三种网络模式显示 当安装好后,的“虚拟网络编辑器”中也存在三种模式,分别对应:桥接-VMnet0.Host-only ...

  8. TestNG并发执行用例详解和范例

    前言 TestNG有多种并发方式支持,方法的并发,class级的并发,test级的并发等:根据实际应用可以灵活的配置和使用,下面分别对几种并发方法进行说明: 一.方法级并发 方法级并发即method级 ...

  9. Python标准库3.4.3-urllib.request-21.6

    21.6. urllib.request — Extensible library for opening URLs 翻译:Z.F. The urllib.request module defines ...

  10. C语言二级指针底层实现

    C语言中,Pointers to Pointers,即二级指针. 一级指针和二级指针的值都是指向一个内存单元: 一级指针指向的内存单元存放的是源变量的值, 二级指针指向的内存单元存放的是一级指针的地址 ...