重温《Effective Java》

news/2024/9/23 14:35:55/

如果忘掉其他的数据结构, 只留下一种,或许会是哈希表;

如果忘掉其他的安全技术,只留下一种,或许会是访问控制;

如果扔掉手中其他的Java 手册,只留下一本,对于期望写出高效而优雅代码的工程师而言,那或许就是《Effective Java》。

“大道易得,小术难求”, 如果一本书中道与术兼备,很可能会成为经典之作,而《Effective Java》一书则可能是经典中的经典。作者Joshua Bloch是美国卡内基-梅隆大学(Carnegie Mellon University,CMU)教授,曾担任Google公司首席 Java 架构师、Sun 公司杰出工程师和 Transarc 公司高级系统设计师,在20多年前凭借《Effective Java》一书获得了 Jolt 大奖。

《Effective Java》第三版的译者是臧秀涛老师,具有多年研发经验,曾在InfoQ担任会议内容总监,后在涛思数据负责开源项目TDengine的社区运营。当时,经传奇人物波姐介绍,我和秀涛老师相识于Qcon,大家尊秀涛老师为“半山老师”,可能引自红花会三当家“千手如来”吧,后来也没有和波姐求证,只有在波姐在场的时候,我才敢这样称呼,一般还是叫“秀涛老师”。他翻译出版过《Java性能权威指南》和《On Java 中文版》等技术图书,几乎每一本都是经典之作,《Effective Java》延续了这一特点。

3517460a1d921c363beb7d7aa493d70a.jpeg

重温经典,常温常新。《Effective Java》在描述编程方法和技巧的时候采用了一种轻量级的方法论,采用“招式”的特点进行描述,招式之间可以交叉引用,由点及线进而形成编程技能的网络。在第三版中,增加了 Lambda 表达式、流、Optional 类、接口默认方法、try-with-resources、@SafeVarargs 注解、模块等 Java 7 及后续版本所引入的新特性,已经发展成为11招90式:

一招——创建和销毁对象

1. 用静态工厂方法代替构造器

2. 当构造器参数较多时考虑使用生成器

3. 利用私有构造器或枚举类型强化Singleton属性

4. 利用私有构造器防止类被实例化

5. 优先考虑通过依赖注入来连接资源

6. 避免创建不必要的对象

7. 清除过期的对象引用

8. 避免使用终结方法和清理方法

9. 与try-finally相比,首选try-with-resources

二招——对所有对象都通用的方法

10. 在重写equals方法时要遵守通用约定

11. 重写equals方法时应该总是重写hashCode方法

12. 总是重写toString方法

13. 谨慎重写clone方法

14. 考虑实现Comparable接口

三招——类和接口 

15. 最小化类和成员的可访问性 

16. 在公有类中,使用访问器方法,而不使用公有的字段 

17. 使可变性最小化 

18. 组合优先于继承 

19. 要么为继承而设计并提供文档说明,要么就禁止继承

20. 与抽象类相比,优先选择接口

21. 为传诸后世而设计接口 

22. 接口仅用于定义类型

23. 优先使用类层次结构而不是标记类 

24. 与非静态成员类相比,优先选择静态成员类 

25. 将源文件限制为单个顶层类

四招 ——泛型

26. 不要使用原始类型 

27. 消除unchecked类型的警告 

28. 列表优先于数组 

29. 首选泛型类型 

30. 首选泛型方法

31. 使用有限制的通配符增加API的灵活性

32. 谨慎混用泛型和可变参数 

33. 考虑类型安全的异构容器

五招——枚举和注解

34. 使用enum代替int常量 

35. 使用实例字段代替序号

36. 使用EnumSet代替位域

37. 不要以序号作为索引,使用EnumMap代替

38. 使用接口模拟可扩展的枚举

39. 与命名模式相比首选注解

40. 始终使用Override注解

41. 使用标记接口来定义类型

493bc3c3db6940d3205edb04cca3c3ca.png

六招——Lambda表达式和流

42. 与匿名类相比,优先选择Lambda表达式

43. 与Lambda表达式相比,优先选择方法引用

44. 首选标准的函数式接口

45. 谨慎使用流

46. 在流中首选没有副作用的函数

47. 作为返回类型时,首选Collection而不是Stream 

48. 将流并行化时要谨慎 

七招 ——方法

49. 检查参数的有效性 

50. 必要时进行保护性复制 

51. 仔细设计方法签名

52. 谨慎使用重载

53. 谨慎使用可变参数

54. 返回空的集合或数组,而不是null

55. 谨慎返回Optional

56. 为所有导出的API元素编写文档注释 

 八招——通用编程 

57. 最小化局部变量的作用域 

58. 与传统的for循环相比,首选for-each循环

59. 了解并使用类库

60. 如果需要精确的答案,避免使用float和double

61. 首选基本类型,而不是其封装类 

62. 如果其他类型更适合,就不要使用字符串

63. 注意字符串拼接操作的性能 

64. 通过接口来引用对象

65. 与反射相比,首选接口

66. 谨慎使用本地方法

67. 谨慎进行优化

68. 遵循普遍接受的命名惯例

九招——异常 

69. 异常机制应该仅用于异常的情况

70. 对于可恢复的条件,使用检查型异常;对于编程错误,使用运行时异常

71. 避免不必要地使用检查型异常

72. 优先使用标准异常

73. 抛出适合于当前抽象的异常

74. 将每个方法抛出的所有异常都写在文档中

75. 将故障记录信息包含在详细信息中

76. 努力保持故障的原子性

77. 不要忽略异常

十招——并发 

78. 同步对共享可变数据的访问

79. 避免过度同步

80. 与线程相比,首选执行器、任务和流

81. 与wait和notify相比,首选高级并发工具 

82. 将线程安全性写在文档中

83. 谨慎使用延迟初始化

84. 不要依赖线程调度器 

十一招——序列化

85. 优先选择其他序列化替代方案 

86. 在实现Serializable接口时要特别谨慎 

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

88. 保护性地编写readObject方法 

89. 对于实例受控的类,首选枚举类型而不是readResolve 

90. 考虑使用序列化代理代替序列化

没错,这十一招90式就是全书的全部心法,每个招式都有代码演练。老码农没敢对各个招式进行点评,书中的介绍已经简洁而详尽了,再多描述,恐有画蛇添足之嫌,除非用演义的方式重新表达,可是我还没有准备好,或许也不是那块料。

7acc985f461fc26b9aca88b712b4cfdc.jpeg

但是,“独孤九剑”不是以无招胜有招么?如果我没记错的话, 风清扬指点令狐冲的时候提到了一个关键点“料敌机先”。用批判的视角读书可能利大于弊,如果你在读了这本《Effective Java》中十一招90式之后,创造出了“八段锦”或者“沾衣十八跌”,别忘了在下面留个言通知我一声。

【关联阅读】

  • 《基础设施即代码(IaC)》译者序

  • 《精益DevOps》译者序

  • 《语音优先》智能语音技术驱动的交互界面设计与语音机器人设计(译者序)

  • 《一书读懂物联网》前言

  • 《一书读懂物联网》作者序

  • 《 持续架构实践 》译者序

  • 《基于混合方法的自然语言处理》译者序

  • 《神奇的连接组》读后

  • 《深入浅出Embedding》随笔

  • 《机会成本》的阅读札记

  • 阅读札记:创新与思维范式

  • 一文读懂 Data Mesh

  • 一文读懂“语言模型”

  • 华为数据之道:数据分类管理框架和经验

  • Web3.0,区块链后花园的姹紫嫣红

  • 看一点逻辑学,试图理解一点真相

  • 读书:《电路与系统简史》


http://www.ppmy.cn/news/1426971.html

相关文章

CSS3 立体 3D 变换

个人主页:学习前端的小z 个人专栏:HTML5和CSS3悦读 本专栏旨在分享记录每日学习的前端知识和学习笔记的归纳总结,欢迎大家在评论区交流讨论! 文章目录 ✍CSS3 立体 3D 变换💎1 坐标轴💎2 perspective 透视视…

【Linux】详解进程通信中信号量的本质同步和互斥的概念临界资源和临界区的概念

一、同步和互斥的概念 1.1、同步 访问资源在安全的前提下,具有一定的顺序性,就叫做同步。在多道程序系统中,由于资源有限,进程或线程之间可能产生冲突。同步机制就是为了解决这些冲突,保证进程或线程之间能够按照既定…

七月论文审稿GPT第4.5版:通过15K条paper-review数据微调Llama2 70B(含各种坑)

前言 当我们3月下旬微调完Mixtral 8x7B之后(更多详见:七月论文大模型:含论文的审稿、阅读、写作、修订 ),下一个想微调的就是llama2 70B 因为之前积攒了不少微调代码和微调经验,所以3月底apple便通过5K的paper-review数据集成功…

【设计模式】3、builder 建造者模式

文章目录 三、builder 模式(生成器)3.1 build 房屋3.1.1 builder.go3.1.2 director.go3.1.3 director_test.go3.1.4 house.go3.1.5 igloo_builder.go3.1.6 normal_builder.go3.1.7 测试 3.2 option3.2.1 pool_test.go3.3.2 pool.go3.3.3 option.go 3.3 自…

错题记录-华为海思

华为 海思数字芯片 参考 :FPGA开发/数字IC笔试系列(5) 华为海思IC笔试解析 FPGA开发/数字IC笔试系列(6) 华为海思IC笔试解析 SystemVerilog Function与Task的区别 $readmemh与$readmemb这两个系统任务是用来从指定文件中读取数据到寄存器数组或者RAM、ROM中。除了…

eNSP防火墙配置实验(trust、DMZ、untrust)

【拓扑】 设备 接口 IP地址/子网掩码/网关 AR1 G0/0/0 10.1.3.2/24 G0/0/1 100.1.1.2/24 FW1 G0/0/0 192.168.166.254/24 G1/0/0 10.1.1.1/24,trust域 G1/0/1 10.1.2.1/24,DMZ域 G1/0/2 100.1.3.1/24,untrust域 LSW1 G0/0/…

svg模板

创建SvgIcon组件 components/SvgIcon/index.vue <template><div v-if"isExternal" :style"styleExternalIcon" class"svg-external-icon svg-icon" v-on"$listeners" /><svg v-else :class"svgClass" aria…

【Android GUI】FramebufferNativeWindow与Surface

文章目录 显示整体体系FramebufferNativeWindowFramebufferNativeWindow构造函数 dequeueBufferSurface总结参考 显示整体体系 native window为OpenGL与本地窗口系统之间搭建了桥梁。 这个窗口系统中&#xff0c;有两类本地窗口&#xff0c;nativewindow1是能直接显示在屏幕的…