《Effective Java》读书笔记一(创建与销毁对象)
No1 考虑用静态工厂方法代替构造器
静态工厂方法优势:
- 它们有名称,阅读性增强,如:BigInteger.probablePrime;
- 不必每次调用它们的时候都创建一个新对象;
- 它们可以返回原返回类型的任何子类型的对象;
- 在创建参数化类型实例的时候,它们使代码变得更加简洁。
静态工厂方法缺点:
- 类如果不含公有的或者受保护的构造器,就不能被子类化;
- 它们与其他的静态方法实际上没有任何区别。
惯用名称:
- getInstance 返回的实例是通过方法的参数来描述的;
- newInstance 像getInstance一样,但newInstance能够确保返回的每个实例都与所有其它实例不同。
No2 遇到多个构造器参数时要考虑用构建器
2.1多个构造器(缺点:许多参数时,客户端代码难写;不易于阅读);
// Telescoping constructor pattern - does not scale well! - Pages 11-12 public class NutritionFacts {
private final int servingSize; // (mL) required
private final int servings; // (per container) required
private final int calories; // optional
private final int fat; // (g) optional
private final int sodium; // (mg) optional
private final int carbohydrate; // (g) 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);
}
}
2.2 JavaBeans模式(缺点:对象可能处于不一致的状态);
// JavaBeans Pattern - allows inconsistency, mandates mutability - Pages 12-13 public class NutritionFacts {
// Parameters initialized to default values (if any)
private int servingSize = -1; // Required; no default value
private int servings = -1; // " " " "
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);
}
}
2.3 Builder模式(用一个专门的对象来存放参数,形如:new NutritionFacts(Builder builder),所有参数封装在Builder类中)。
// Builder Pattern - Pages 14-15 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 carbohydrate = 0;
private int sodium = 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 carbohydrate(int val)
{ carbohydrate = val; return this; }
public Builder sodium(int val)
{ sodium = 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();
}
}
No5 避免创建不必要的对象
5.1 String对象的使用
String s = new String(“stringetee”); // DON’T DO THIS
String s = “stringetee”; // 正确方式,引用常量池中的对象
5.2 注意某些方法调用频繁生成对象时,应考虑将这些对象放置到类(对象)的局部变量中。
不好的代码如下:
// Creates lots of unnecessary duplicate objects - page 20-21
import java.util.*; public class Person { private final Date birthDate; public Person(Date birthDate) {
// Defensive copy - see Item 39
this.birthDate = new Date(birthDate.getTime());
} // Other fields, methods omitted // DON'T DO THIS!
public boolean isBabyBoomer() {
// Unnecessary allocation of expensive object
Calendar gmtCal =
Calendar.getInstance(TimeZone.getTimeZone("GMT"));
gmtCal.set(1946, Calendar.JANUARY, 1, 0, 0, 0);
Date boomStart = gmtCal.getTime();
gmtCal.set(1965, Calendar.JANUARY, 1, 0, 0, 0);
Date boomEnd = gmtCal.getTime(); return birthDate.compareTo(boomStart) >= 0 &&
birthDate.compareTo(boomEnd) < 0;
}
}
优化后的代码如下:
// Doesn't creates unnecessary duplicate objects - page 21
import java.util.*; class Person { private final Date birthDate; public Person(Date birthDate) {
// Defensive copy - see Item 39
this.birthDate = new Date(birthDate.getTime());
} // Other fields, methods /**
* The starting and ending dates of the baby boom.
*/
private static final Date BOOM_START;
private static final Date BOOM_END; static {
Calendar gmtCal =
Calendar.getInstance(TimeZone.getTimeZone("GMT"));
gmtCal.set(1946, Calendar.JANUARY, 1, 0, 0, 0);
BOOM_START = gmtCal.getTime();
gmtCal.set(1965, Calendar.JANUARY, 1, 0, 0, 0);
BOOM_END = gmtCal.getTime();
} public boolean isBabyBoomer() {
return birthDate.compareTo(BOOM_START) >= 0 &&
birthDate.compareTo(BOOM_END) < 0;
}
}
5.3 JDK1.5之后,自动装箱功能可能导致代码BUG。
如下代码:
// Hideously slow program! Can you spot the object creation?
public static void main(String[] args) {
Long sum = 0L;
for (long i = 0; i < Integer.MAX_VALUE; i++) {
sum += i;
}
System.out.println(sum);
}
这段程序算出的结果是正确的,但是比实际情况要更慢一些,只因为打错了一个字符。变量sum被声明成Long而不是long。要优先使用基本类型而不是装箱基本类型,要当心无意意识的自动装箱。
No7 避免使用终结方法
Java语言规范不仅不保证终结方法会被及时地执行,而且根本就不保证它们会被执行。
显式终止方法的典型盒子是InputStream,OutputStream和java.sql.Connection上的close方法。另一个例子是java.util.Timer上的cancel方法,它执行必须的状态改变,使得与Timer实例相关联的该线程温和地终止自己。
显式的终止方法通常与try-finally结构结合起来使用,以确保及时终止。
《Effective Java》读书笔记一(创建与销毁对象)的更多相关文章
- 【Effective Java读书笔记】创建和销毁对象(一):考虑使用静态工厂方法代替构造器
类可以提供一个静态方法,返回类的一个静态实例,如Boolean包装类的一个获取实例的静态方法 public static Boolean valueOf(boolean b) { return (b ...
- Effective Java 读书笔记之一 创建和销毁对象
一.考虑用静态工厂方法代替构造器 这里的静态工厂方法是指类中使用public static 修饰的方法,和设计模式的工厂方法模式没有任何关系.相对于使用共有的构造器来创建对象,静态工厂方法有几大优势: ...
- Effective Java 学习笔记之创建和销毁对象
一.考虑用静态工厂方法代替构造器 1.此处的静态工厂方法是指返回指为类的对象的静态方法,而不是设计模式中的静态工厂方法. 2.静态工厂方法的优势有: a.使用不同的方法名称可显著地表明两个静态工厂方法 ...
- Effective Java(1)-创建和销毁对象
Effective Java(1)-创建和销毁对象
- effective java 第2章-创建和销毁对象 读书笔记
背景 去年就把这本javaer必读书--effective java中文版第二版 读完了,第一遍感觉比较肤浅,今年打算开始第二遍,顺便做一下笔记,后续会持续更新. 1.考虑用静态工厂方法替代构造器 优 ...
- 《Effective Java》读书笔记 - 2.创建和销毁对象
Chapter 2 Creating and Destroying Objects item 1:Consider static factory methods instead of construc ...
- Effective Java 读书笔记之二 对于所有对象都通用的方法
尽管Object是一个具体的类,但设计它主要是为了扩展.它的所有非final方法都有明确的通用约定.任何一个类在override时,必须遵守这些通用约定. 一.覆盖equals时请遵守通用的约定 1. ...
- Effective Java——(一)创建和销毁对象
第一条 考虑用静态工厂方法代替构造器 什么叫静态工厂方法,就是通过在类中通过静态方法对对象初始化. 比如说 public class StaticFactory { private String na ...
- Effective Java(一)—— 创建和销毁对象
在客户端(调用端)获取自身实例的方法: 公有的构造器: 类的静态工厂方法: 1. 使用静态工厂方法代替构造器 Boolean 是对基本类型 boolean 的包装类: public final cla ...
- Effective Java 读书笔记(二):对象通用方法
1 重写equals方法时请遵守通用约定 (1)无需覆盖equals方法的情况 要求独一无二 不要求逻辑相等 超类已经覆盖equals方法,对其子类也适用 一个类是私有的或者是包私有(可以重写后抛出异 ...
随机推荐
- 基于JDK动态代理实现的接口链式调用(Fluent Interface)工具
什么是链式接口(Fluent Interface) 根据wikipedia上的定义,Fluent interface是一种通过链式调用方法来完成方法的调用,其操作分为终结与中间操作两种.[1] 下面是 ...
- GIS专业书籍、文档、数据、网站、工具等干货
整理.分享一些个人整理的GIS专业书籍.文档.数据.网站.工具等.也希望大家将自己的心得也分享出来,一起交流,共同进步. 如果下载链接失效,请到这里去:地信网 一.原理应用类 GIS基础类 01.地理 ...
- STL - 容器 - Map(二)
把Map用作关联式数组 MapAdvanceTest.cpp #include <map> #include <string> #include <iostream> ...
- JSTL详解(一)
将jstl.jar包导入到工程中 jstldemo1.jsp <%@ taglib prefix="c" uri="http://java.sun.com/jsp/ ...
- 与AQS有关的并发类
ReetrantLock与Condition: 參考 在java.util.concurrent包中.有两个非常特殊的工具类.Condition和ReentrantLock,使用过的人都知道,Reen ...
- Android Bitmap与String互转(转)
/** * 图片转成string * * @param bitmap * @return */ public static String convertIconToString(Bitmap bitm ...
- exception is the version of xbean.jar correct
CreateTime--2018年2月5日09:20:00 Author:Marydon 异常: is the version of xbean.jar correct 情景还原: 在使用Java ...
- navicat ora-28547:connection to server failed
navicat ora-28547:connection to server failed CreationTime--2018年8月9日18点47分 Author:Marydon 1.情景还原 ...
- 〖Linux〗Ubuntu13.10中打开键盘背光灯
刚刚从淘宝上买回一个带有Led背光的键盘(黑爵战神x5 背光升级版): 然后发现在Linux中背光灯并不亮,在Windows中就可以按下Scroll Lock键点亮: 在网上探索了一番,觉得应该可以使 ...
- Adaptive Thresholding & Otsu’s Binarization
Adaptive Thresholding Adaptive Method - It decides how thresholding value is calculated. cv2.ADAPTIV ...