《Effective java 第2版》读书笔记--创建/销毁对象
来源:互联网 发布:mac svn图形化界面 编辑:程序博客网 时间:2024/06/05 20:30
第一章 引言
1.本书共78个条目
2.本书大部分内容不是讨论性能的,而是关心如何编写出清晰、正确、可用、健壮、灵活和可维护的代码。
第二章 创建/销毁对象
第一条:用静态工厂方法代替构造器
1.静态工厂方法比起构造器的优势
(1)它们有名称:
如果构造器的参数不能正确描述正被返回的对象,具有适当名称的静态方法更容易使用。
当一个类需要多个带有相同签名的构造器时,就可以用静态工厂代替构造器
例:BigInterger.probablePrime()
(2)不必每次调用它们的时候都创建新的对象:
静态工厂方法能为重复的调用返回相同的类,有助于类控制在某个时刻哪些实例应该存在,这种类被称为实例受控的类。
(3)他们可以返回原返回类型的的任何子类型的实例:
API可以返回对象,又不会使对象的类变成共有的,适合基于接口的框架。
被返回的对象由相关的借口精确指定。
共有的静态工厂方法所返回的类不仅可以是非公有的,还可以随着每次调用发生
变化,这取决于工厂方法参数值。
„静态工厂方法返回的对象所属的类,在编写该静态方法时可以不必存在(留给开发者实现)
(5)在创建参数化实例的时候,它们使代码更为简单
例:
Map< String, List<String>> m = new Map< String, List<String> >();Map< String, List<String>> m = HashMap.newInstance(); // 减少一次参数
2.静态工厂方法的缺点
(1)类如果不含公有或者受保护的构造器,就不能被子类化。
(2)它们与其他静态方法没有任何区别。
3.静态工厂方法的惯用名称
(1)ValueOf: 类型转换方法
(2)getInstance: 返回唯一的实例
(3)newInstance:保证每个返回的实例都与其他不同
(4)getType/newType:返回工厂对象的类
第二条:遇到多个构造器参数时要考虑构建器(建造者模式)
1.如果类的构造器或者静态工厂中具有多个参数, 设计这种类时, 选择Builder模式. 特别是大多数参数都是可选的时候.
2.与使用传统的重载构造器模式相比, 使用Builder模式既能保证安全性,又能保证可读性。
例:
public class NutritionFacts { private final int servingSize; private final int serving; private final int calories; private final int fat; private final int sodium; private final int carbohydrate; public static class Builder { private int servingSize; private int serving; private int calories; private int fat; private int sodium; private int carbohydrate; public Builder(int servingSize, int serving) { this.servingSize = servingSize; this.serving = serving; } 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); } } public NutritionFacts(Builder builder) { servingSize = builder.servingSize; serving = builder.serving; calories = builder.calories; fat = builder.fat; sodium = builder.sodium; carbohydrate = builder.carbohydrate; } public static void main (String [] args){ NutritionFacts coca = new Builder(240,8).calories(100).fat(5) .sodium(35).carbohydrate(27).build(); }}
第三条:用私有构造器或者枚举类型强化Singleton属性
1.Singleton指仅仅被实例化一次的类
例:
public class Elvis { private static Elvis ourInstance = new Elvis(); public static Elvis getInstance() { return ourInstance; } private Elvis() { }}
2.实现Singleton的方法
公有静态域是个final域
公有的成员是个静态工厂方法
编写一个包含单个元素的枚举类型:更加简洁,无偿提供序列化机制,而且绝对防止多次实例化,是目前最好的方法。
例:
public enum A { INSTANCE; public void invoke(){}}
第四条:通过私有构造器强化不可被实例化的类的特性
1.有时可能需要编写只包含静态方法和静态域的类, 最好给其提供一个私有构造器, 否则编译器会为其生成一个默认无参构造函数.
例:
public class UtilityClass{ private UtilityClass(){ throw new AssertionError(); }}
第五条:避免创建不必要的对象
1.使用静态的初始器(静态块只被执行一次)
例:
public class Person{ private final Date birthDate; public Person(Date birthDate){ this.birthDate = birthDate; } 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 isBadyBoomer(){ return birthDate.compareTo(BOOM_START) >= 0 && birthDate.compareTo(BOOM_END) < 0; }}
2.优先使用基本类型而不是装箱基本类型
(1)装箱基本类型
例1:
Integer i = 10; //装箱过程
自动将基本数据类型转换为包装器类型,自动调用ValueOf(int)方法
例2:
int n = i ; //拆箱过程
自动将包装器类型转换为基本数据类型,自动调用intValue方法
第六条:消除过期对象的引用
1.栈内部维护着对过期对象的过期引用,永远也不会被解除。导致内存泄露
修复方法:清空这些引用(清空引用对象应该是一种例外, 而不是一种规范行为)
例:
public Object pop(){ if(size==0){ throw new EemptyStackException(); } Object result = elements[--size]; elements[size] = null;//Eliminate obsolete reference return result;}
2.只要类自己管理内存,就应该警惕内存泄露。
3.缓存
(1)可以考虑使用WeakHashMap来代表缓存
(2)使用后台线程来定期清理
(3)对于更复杂的缓存,使用java.lang.ref
4.监听器和回调
(1)只保留回调的弱引用
例:只将他们保存成WeakHashMap中的键。
第七条:避免使用终结方法finalize()
1.终结方法不可预测,很危险
(1)不能保证会及时被执行,甚至不能保证执行:
(2)不能保证在所有的JVM上都得到同样的体验
(3)可能随意延迟其实例的回收过程
(4)不应该依赖终结方法来更新重要的持久状态,例如分布式系统的永久锁
(5)不要使用System.gc()等函数
2.如果在终结方法执行时抛出未捕获异常,则此异常会被忽略,终结方法也将终止
3.有非常严重的性能损失
4.使用显式的终止方法,并要求客户端在每个实例不再有用时调用这个方法。
例:InputStream的close函数, Timer的cancel函数等,应该在try-catch块的finally部分调用这个显式终止方法
例:
Foo foo = new Foo( ); try{ } finally{ foo.terminate();//Explicity termination method }
5.终结方法的用途
(1)在对象的所有者忘记调用显式终止方法时,充当安全网函数。
(2)对象的本地对等体:终结方法释放本地对等体的重要资源
子类覆盖终结方法时,需要显式调用父类的终结方法
终结方法守卫者:匿名内部类,终结它的外围实例。
注:对于每一个带有自定义终结方法的非final公有类,都应该考虑使用这个方法。
本人才疏学浅,若有错误,请指出
谢谢!
- 《Effective java 第2版》读书笔记--创建/销毁对象
- effective Java读书笔记:创建和销毁对象
- Effective Java读书笔记(第2章-创建和销毁对象续)
- Effective Java 读书笔记( 2 创建和销毁对象)
- Effective Java 读书笔记之2 创建和销毁对象
- 《Effective Java》第2章 创建和销毁对象
- effective java 第2章 创建和销毁对象笔记
- 第2章.创建和销毁对象[Effective Java 第2版]
- 【读书笔记】《Effective Java》(1)--创建和销毁对象
- Effective Java读书笔记三:创建和销毁对象
- effective java 读书笔记---第二章创建和销毁对象
- 《Effective Java》读书笔记(一)之创建和销毁对象
- Effective Java 读书笔记(一):创建和销毁对象
- Effective Java读书笔记——创建和销毁对象
- Effective Java读书笔记(1-2章-创建和销毁对象)
- Effective Java 第2章 创建和销毁对象 精简总结 (1)
- {Effective Java} Chap 2 创建和销毁对象
- effective java观后感(2)-------创建和销毁对象
- Scrapy用mysql存储的小技巧
- 设计模式之备忘录模式
- 布局css 标签重置以及类的初始化模板
- java 导出Excel
- spring boot (一)快速入门
- 《Effective java 第2版》读书笔记--创建/销毁对象
- C++标准输入输出流控制字符的使用
- 你现在就该学习Python
- 解析./build/tools/caffe train --solver=examples/mnist/lenet_solver.prototxt
- 大数据IMF传奇行动绝密课程第116课:Spark Streaming性能优化:如何在毫秒内处理大吞吐量和数据波动比较大的流计算
- HTTP Status 500
- 详解 ESLint 规则,规范你的代码
- Spring中 @Autowired标签与 @Resource标签 的区别
- 多线程学习笔记(六)之锁对象Lock