导语

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

创建和销毁对象

  1. 作者认为,使用构造方法构造对象是不优雅的。我们应该是用工厂方法来构建对象。一来可以用语义化的静态方法名来避免构造方法重载造成的迷惑性,二来可以在构造对象时进行如懒加载,校验等相关控制,因为构造方法调用后一定会返回一个新的分配了堆内存的对象引用。通常的方法名为:valueOf,of,getInstance,newInstance,getType,newType等。

  2. 作者认为,对象参数过多时,为了避免冗长的setter方法调用,应该使用Builder设计模式。同时builder对象可以作为参数传递给相关方法。此处可以配合Lombok

  3. 作者认为构造单例的最好方式是枚举,同时应该注意对象序列化对单例造成的破坏。

  4. 作者认为只包含静态方法和静态域的类应该私有构造器,因而不可实例化,不能被继承(子类实例化时会调用父类构造器)。个人认为也可以使用abstarct关键字。

  5. 作者认为避免创建不必要的对象,如 String s =new String("hello"),这里其实就重复定义了字符串,造成了内存浪费和GC压力。还有就是循环语句中的某些对象可以在语句外面创建,在整个循环中重用。避免自动装箱造成的频繁创建对象。

  6. 在我们自己管理内存时,要注意消除过期对象的引用,让JVM及时回收内存。我们自己管理内存的典型场景为我们在全局范围内持有一个数组,我们自己管理自己的数组内存,进行数据的增删改。我们要及时的将不用的对象引用从数组中通过置为null去掉。让GC内存回收内存。

  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字段的每一个值都作为一个拓展子类。添加自己的字段和方法。

  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. 必要时对参数进行拷贝。如果方法调用者将引用传递给方法后,在方法外对引用指向的对象进行了修改,可能会造成诡异的不可预期的错误。

  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的相关实践。就是心情太浮躁,做事效率太低,拖拖拉拉让我很烦恼。

加油吧。

《Effective Java》总结的更多相关文章

  1. 《FLASH PROGRAMMING 那些事》总结

    注明来自 http://www.ssdfans.com/?p=5589 以MLC为例: 对FGF(Floating Gate Flash)技术的,MLC programming一般分两步走:先prog ...

  2. Implementation of Serial Wire JTAG flash programming in ARM Cortex M3 Processors

    Implementation of Serial Wire JTAG flash programming in ARM Cortex M3 Processors The goal of the pro ...

  3. [原创] Keil uVision5 下载程序 add flash programming algorithm选项缺少需要的算法解决办法

    MDK开发环境从V4升级到V5后,支持包不再是集成到开发环境当中,而是封装在PACK中,需要自行安装,比较麻烦. 搭建MDK开发环境以及破解的方法,在前面的文章中有详细说明,这里不再赘述,有兴趣的可以 ...

  4. Turtelizer 2 provide JTAG Flash programming and debugging of ARM based boards via USB

    http://www.ethernut.de/en/hardware/turtelizer/ Introducing Turtelizer 2 Overview Turtelizer 2 had be ...

  5. 痞子衡嵌入式:恩智浦i.MX RT1xxx系列MCU硬件那些事(2.3)- 串行NOR Flash下载算法(J-Link工具篇)

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是J-Link工具下i.MXRT的串行NOR Flash下载算法设计. 在i.MXRT硬件那些事系列之<在串行NOR Flash X ...

  6. Programming Internal Flash Over the Serial Wire Debug <SWD> Interface -- EFM32

    1 Debug Interface Overview 1.1 Serial Wire Debug Serial Wire Debug (SWD) is a two-wire protocol for ...

  7. Error:Flash Download Failed-"Cortex-M3"

    Error:Flash Download Failed-"Cortex-M3"出现一般有两种情况: 1.SWD模式下,Debug菜单中,Reset菜单选项(Autodetect/H ...

  8. STM32F4读写内部FLASH【使用库函数】

    STM32F4Discovery开发帮使用的STM32F407VGT6芯片,内部FLASH有1M之多.平时写的代码,烧写完之后还有大量的剩余.有效利用这剩余的FLASH能存储不少数据.因此研究了一下S ...

  9. Flash Download Failed-"Cortex-M3"

    rror:Flash Download Failed-"Cortex-M3"出现一般有两种情况: 1.SWD模式下,Debug菜单中,Reset菜单选项(Autodetect/HW ...

  10. Stm32_调试出现 Error:Flash Download Failed-"Cortex-M3"

    rror:Flash Download Failed-"Cortex-M3"出现一般有两种情况: 1.SWD模式下,Debug菜单中,Reset菜单选项(Autodetect/HW ...

随机推荐

  1. JavaScript——DOM操作

    DOM-(Document Object Model)即文档对象模型. JavaScript可以动态地修改DOM,从而来修改HTML的内容. 查找HTML元素 通过 id 找到 HTML 元素 通过标 ...

  2. 面向对象编程(UDP协议)

    UDP协议 UDP 是User Datagram Protocol的简称, 中文名是用户数据报协议,是OSI(Open System Interconnection,开放式系统互联) 参考模型中一种无 ...

  3. REST架构及其介绍

    概述     REST是英文Representational State Transfer的缩写,中文翻译:表述性状态转移.     他是由Roy Thomas Fielding博士在他的论文 < ...

  4. CF-1328 F. Make k Equal

    F. Make k Equal 题目链接 题意 长度为n的序列,每次可以选择一个最大的数字将其减一或者选择一个最小的数字将其加一,问最少操作多少次可以使得序列中至少存在 k 个一样的数字 分析 官方题 ...

  5. B. Queue

    During the lunch break all n Berland State University students lined up in the food court. However, ...

  6. Codeforces Round #643 (Div. 2) E. Restorer Distance (贪心,三分)

    题意:给你\(n\)个数,每次可以使某个数++,--,或使某个数--另一个++,分别消耗\(a,r,m\).求使所有数相同最少的消耗. 题解:因为答案不是单调的,所以不能二分,但不难发现,答案只有一个 ...

  7. python代理池的构建1——代理IP类的构建,以及配置文件、日志文件、requests请求头

    一.整体结构 二.代理IP类的构建(domain.py文件) ''' 实现_ init_ 方法, 负责初始化,包含如下字段: ip: 代理的IP地址 port:代理IP的端口号 protocol: 代 ...

  8. 7.PowerShell DSC之模式

    DSC两种模式 DSC有两种模式,Push模式和Pull模式 Push模式 基本流程 写配置--编译生成mof--推送到目标服务器,由目标服务器LCM执行mof并进行指定的配置 优点 架构简单.成本低 ...

  9. c#记两个变量进行值交换

    今天腊月二十九啦,无心上班,专注划水.然后就在那里翻帖子消磨时光. 看到了这样一个问题,有人提问为什么   a=b+(b=a)*0  ??? 第一眼看上去,我也有点蒙,仔细推敲了一下,嗯~的确是交换了 ...

  10. VS常用命令

    1.查看Windows文件首部信息 dumpbin/headers 项目名称. 例如:dumpbin/headers test.exe 2.查看CLR首部信息 dumpbin/clrheader 项目 ...