《Effective Java》总结

导语

《Effective Java》是和《Thinking in java》齐名的java进阶书籍。做者参与了JDK标准库的编写工做,对于此书的学习,让我收获不少。好记性不如烂笔头,我决定好好总结一下。本书主要内容有11章,分别从各个方面阐述了做者对于java代码编写的体会。我看的是第二版,目前最新版已是第三版了,可是尚未在国内翻译出版。这就是英语很差的局限之处~java

建立和销毁对象

  1. 做者认为,使用构造方法构造对象是不优雅的。咱们应该是用工厂方法来构建对象。一来能够用语义化的静态方法名来避免构造方法重载形成的迷惑性,二来能够在构造对象时进行如懒加载,校验等相关控制,由于构造方法调用后必定会返回一个新的分配了堆内存的对象引用。一般的方法名为:valueOf,of,getInstance,newInstance,getType,newType等。
  2. 做者认为,对象参数过多时,为了不冗长的setter方法调用,应该使用Builder设计模式。同时builder对象能够做为参数传递给相关方法。此处能够配合Lombok
  3. 做者认为构造单例的最好方式是枚举,同时应该注意对象序列化对单例形成的破坏。
  4. 做者认为只包含静态方法和静态域的类应该私有构造器,于是不可实例化,不能被继承(子类实例化时会调用父类构造器)。我的认为也可使用abstarct关键字。
  5. 做者认为避免建立没必要要的对象,如String s =new String("hello"),这里其实就重复定义了字符串,形成了内存浪费和GC压力。还有就是循环语句中的某些对象能够在语句外面建立,在整个循环中重用。避免自动装箱形成的频繁建立对象。1522157122995.png编程

  6. 在咱们本身管理内存时,要注意消除过时对象的引用,让JVM及时回收内存。咱们本身管理内存的典型场景为咱们在全局范围内持有一个数组,咱们本身管理本身的数组内存,进行数据的增删改。咱们要及时的将不用的对象引用从数组中经过置为null去掉。让GC内存回收内存。52215766484
  7. 避免使用finalize方法。在此方法历写业务的最大问题时,该方法的调用时间是不必定的。由于GC线程的优先级很低,因此该方法的调用时机是不可控的,且性能开销很大。只建议在某些特定状况下做为安全网方法,即最后一道捕捉漏网之鱼的方法。
  8. 应该重写equals方法。此处能够配合Lombok
  9. 应该同时重写hasCode方法。此处能够配合Lombok
  10. 应该要覆盖toString方法。便于调试。此处能够配合Lombok
  11. 应该谨慎的使用clone方法。由于存在浅克隆问题。
  12. 对于值对象类,应该合理的实现Comparable方法。此处能够配合guava的Ordering。
  13. 应该使类的成员可见性在可能的状况下最小。由于一旦类的成员暴露,那就成为建立者和调用者之间的约定。那么类的建立者就要对这些暴露的成员的稳定性负责,不能随意修改约定。
  14. 应该经过方法访问域而不是直接访问域。由于能够在方法中进行相关控制。
  15. 应该使对象的可变性最小。即,除非必要,全部的域都应该用final修饰,全部域都应该是私有的,全部类都不能被拓展。被拓展的类可能会被破坏封装性,即,拓展的过程当中,须要去了解被拓展的类的内部实现,而不只仅是被拓展的类暴露出来的API。
  16. 复合优于继承。如上所述,继承破坏了封装性,同时复合更稳定,不会受到被复合的类的结构的改变的影响。经过复合和转发(适配器模式)能够方便的实现继承的效果。同时能够经过asType方法暴露一个被复合的类的视图模拟多态。
  17. 继承是一种约定。要么提供丰富和负责任的文档告知方法的自用性,并测试被继承后的风险,要么就经过final禁止被继承。
  18. 接口优于抽象类。由于单继承的局限性,同时接口之间并不必定和类同样是分层关系。经过mixin接口(如Comparable接口),能够构建功能丰富的类,而且能够灵活的实现多态。为了便捷的实现接口,能够提供一个接口默认实现骨架类(Wapper)。
  19. 接口只用于定义类型,便于实现多态。不该该用来定义常量,常量属于不一样的实现类的内部实现,不该该放在接口中做为API约定。
  20. 经过在类中添加一个type字段来区分不一样类型是不够OOP的,应该经过类的继承来实现层次。将相同的部分抽象成父类,type字段的每个值都做为一个拓展子类。添加本身的字段和方法。52215939417
  21. 用函数对象表示策略,java8以前不支持函数式编程的迂回。
  22. 优先考虑静态内部类。静态内部类时访问权限的最小域。若是一个类只在本类中使用,就能够定义为私有的静态内部类。固然,它实现的接口能够有公开的访问权限。
  23. 不要使用原生类型(raw type)。对于泛型类,都应该使用参数化类型。
  24. 使用SupressWarn()压制编译器警告。前提是必需要了解警告的内容,同时将压制的区域最小化,避免出现诡异的问题。
  25. 列表优于数组。两个缘由,数组是协变的,容易产生类型转换异常。数组不支持泛型。
  26. 使用泛型。避免类型转换异常。
  27. 使用泛型方法。便捷的类型推导可使代码更简洁。
  28. 使用有限制的类型通配符来提升API的灵活性。
  29. Class类是参数化类型,有不少类型相关的方法。如:cast等。注意灵活使用。
  30. 常量推荐使用枚举定义。
  31. 不要在业务中使用枚举的ordinal属性,应该自定义一个实例域。
  32. 使用EnumSet来代替位域。
  33. 使用EnumMap代替序数索引。枚举做为map的key时。
  34. 枚举能够实现接口(由于枚举是一种特殊的类)。
  35. 注解优于命名模式。经过命名约定来指定范围,不如在类或类成员上添加注解标记。
  36. 使用Override注解来进行编译器检查。
  37. 某些只在类上的标记,能够考虑标记接口。如CloneableSerialble
  38. 检查参数,快速失败。
  39. 必要时对参数进行拷贝。若是方法调用者将引用传递给方法后,在方法外对引用指向的对象进行了修改,可能会形成诡异的不可预期的错误。52216079682
  40. 谨慎设计方法签名。这部份内容太多,也很经典。建议时不时翻下这一节。方法名要合乎约定;不要过度追求方法便捷,除非某个功能太经常使用能够提供一个便捷方法,否则的话提供一个功能齐全的方法就好;避免过长的参数列表,若有必要,能够提供一个辅助类;注意方法正交性,即功能不要重复。参数优先使用接口,离散参数如布尔参数优先使用枚举。
  41. 慎用重载。能够定义一个参数相关的方法名。
  42. 慎用可变参数。不安全,代码不美观。建议是一个必要参数加一个可变参数。
  43. 返回空数组或空集合,而不是null。
  44. 为全部公开API编写文档。
  45. 局部变量做用于最小化。
  46. 尽量的使用类库。
  47. 精确计算使用大数类型。
  48. 基本类型优于包装类型。
  49. 尽可能避免使用字符串。
  50. 当心字符串链接的性能。
  51. 接口优于反射机制。反射效率低,没法进行编译期检查。
  52. 谨慎的进行优化。前期能跑就行,不要进行没有目的的优化。
  53. 不要用异常进行分支控制。
  54. 丰富异常信息。
  55. 不要忽略异常。
  56. 优先使用标准的异常。
  57. 并发编程中,尽可能使用并发工具类
  58. 序列化没啥用啊,不说了。设计模式

总结

我感受这本书就是很厉害,尤为是带我理解了Super Type Token这个关于反射和泛型的概念。固然了,那又是一篇博客了,找时间我会娓娓道来的。这本书里关于类和方法的内容很精辟,让我理解了一些关于OOP迷惑。其实值得我多刷好几遍,可是我就匆忙的两三天刷完了。。。心态浮躁。第四章第五章找个午休再翻翻吧。数组

第一次正式的开始用Markdown写博客,感受本身很极客。就是博客园的Markdown主题有点太low了。之后我就用这个来写博客啦。。。安全

后面的博客计划是总结下字节码,反射和泛型。还想着刷一本Zookeeper的书写一写Zookeeper的相关实践。就是心情太浮躁,作事效率过低,拖拖拉拉让我很烦恼。并发

加油吧。app

相关文章
相关标签/搜索