Effective Java读书笔记

第2章 创建和销毁对象

1.考虑用静态工厂方法代替构造函数-->静态工厂模式。

2.使用私有构造函数强化singleton属性-->单例模式。

3.通过私有构造函数强化不可实例化的能力:

  a.企图通过将一个类做成抽象类来强制该类不可被实例化,是行不通的。

  b.只要让该类包含单个显示的私有构造函数,则它就不可被实例化了。

4.避免创建重复的对象。

5.消除过期的对象引用。

6.避免使用finalizer函数。

 

内存泄漏问题:

扫描二维码关注公众号,回复: 90599 查看本文章

如果一个栈显示增长,然后再收缩,那么,从栈中弹出来的对象将不会被当做垃圾回收,即使使用栈的客户程序不再引用这些对象,它们也不会被回收。这是因为,栈内部维护着对这些对象的过期引用。

问题修复:

一旦对象引用过期,就清空这些引用。(比如 当一个单元被弹出栈,就把它的引用设置为null)。这样的好处是,如果它们在以后又被错误地解除引用,则程序会立即抛出空指针异常,而不是悄悄地错误运行下去。

场景:

  1.只要一个类自己管理它的内存。

  2.缓存。

 

第3章 对于所有对象都通用的方法

7.在改写equals的时候请遵守通用约定:

当一个类有自己特有的“逻辑相等”概念(而不是它们是否指向同一个对象),而且超类也没有改写equals以实现期望的行为,这时我们需要改写它。

这通常适合于“值类”的情形,比如Integer或者Date。

通用约定:

  a.自反性;对于任意的引用值x,x.equals(x)一定为true。

  b.对称性;对于任意的引用值x和y,并且仅当y.equals(x)返回true时,x.equals(y)也一定返回true。

  c.传递性;对于任意的引用值x、y和z,如果x.equals(y)返回true,并且y.equals(z)也返回true,那么x.equals(z)也一定返回true。

  d.一致性;对于任意的引用值x和y,如果equals比较的对象信息没有被修改的话,那么,多次调用x.equals(y)要么一致地返回true,要么一致地返回false。

  e.非空性;对于任意的非空引用值x,x.equals(null)一定返回false。

实现高质量equals方法的一个“处方”:

  1.使用==操作符检查“实参是否为指向对象的一个引用”;

  2.使用instanceof操作符检查“实参是否为正确的类型”;

  3.把实参转换到正确的类型;

  4.对于该类中每一个“关键(significant)”域,检查实参中的域与当前对象中对应的域值是否匹配。

  5.当你编写完后,检查它是否对称的、传递的、一致的。

  8.改写equals时总是要改写hashCode相等的对象必须具有相等的hash码。

  9.总是要改写toString。默认返回的是类名+@+16位进制的hash码。

 

第6章 方法

23.检查参数的有效性-->做校验。

24.需要时使用保护性拷贝:

Java是安全的语言,对缓冲区溢出、数组越界、非法指针以及其他的内存破坏错误自动免疫。

25.谨慎设计方法的原型:

  a.遵循标准的命令习惯。

  b.不要过于追求提供便利的方法,只有一个操作被用得非常频繁时候,才提供快捷方法。

  c.避免长长的参数列表,三个视为实践中的最大值。

  d.对于参数类型,优先使用接口而不是类。例如,没有理由在编写一个方法时使用Hashtable作为输入,相反,应该使用Map。这使得你可以传入一个Hashtable、HashMap、TreeMap的子映射表。如果你使用一个类而不是一个接口,则限制了客户只能传入一个特定的实现。

  e.谨慎地使用函数对象。

26.谨慎地使用重载:

永远不要导出两个具有相同参数数目的重载方法。

27.返回零长度的数值而不是null。

 

第7章 通用程序设计

31.如果要求精确的答案,避免使用float和double-->不适合用作货币计算。

33.了解字符串连接的性能:

使用StringBuffer的append方法。

34.通过接口引用对象

尽量这样声明:

List subs=new ArrayList();

而不是这样的声明:

ArrayList subs=new ArrayList();

如果没有合适的接口存在的话,那么,用类来引用一个对象,是合适的。

 

第8章 异常

40.对于可恢复的条件使用被检查时异常,对于程序错误使用运行时异常。

46.努力使失败保持原子性:

一个失败的方法调用应该使对象保持“它在被调用之前的状态”。

47.不要忽略异常:

catch块也应该包含一条说明,用来解释为什么忽略掉这个异常是合适的。

 

第9章 线程

51.不要依赖于线程调度器(thread schcduler):

  1.任何依赖于线程调度器而达到正确性或性能要求的程序,很有可能是不可移植的。

  2.不要企图通过调用Thread.yield来“修正”程序。

  3.线程优先级是Java平台上最不可移植的特征。

  4.Thread.yield的唯一用途是在测试期间人为地增加一个程序并发性。

53.避免使用线程组。

 

第10章 序列化

54.谨慎地实现Serializable:

  1.实现它的最大代价是,一旦一个类被发布,则“改变这个类的实现”的灵活性将大大降低。

  2.第二个代价是,增加了bug和安全漏洞的可能性。

  3.第三个代价是,随着一个类的新版本的发行,相关的测试负担增加了。

55.考虑使用自定义的序列化形式。

56.保护性地编写readObject方法。

57.必要时提供一个readResolve方法。

 

猜你喜欢

转载自www.cnblogs.com/kz2017/p/8971571.html