《Effective Java中文版》-第1章、第2章
《Java编程思想》已基本过了一遍,在双十一的前后又买了几本Java进阶相关的书,大致方向是代码规范、并发、虚拟机以及敏捷开发。大方向是架构,手头的项目正是一个很好的实践,实践之余,先把Java的功底拔高再谋其他。
闲话少说,开始正题。
序言中提及了一个观点是,掌握一门语言需要掌握三个方面,语言的结构如何(语法)、如何命名想谈论的事物(词汇)、以及如何惯用和高效的方式来表达日常的事物(用法)。想想其实和学英语的方式大体相似。回归到Java上就是,Java核心是面向对象的,所以先探寻面向对象牵扯到的词汇(关键字),实现面向对象编程步骤的写法(语法定义),以及如何更高效的组织这种思维结构下的写法(用法、框架)。本书解决的是第三种需求:习惯和高效的用法。采取的方式是归纳总结写对象各个环节的一些要点,指出怎么做、以及为什么。
本书大部分规则都是源于少数的几条基本原则。
1.清晰性和简洁性最为重要:模块的用户永远也不应该被模块的行为所迷惑
2.模块(Module)要尽可能小,但又不能太小
3.代码应该被重用,而不是被拷贝
4.模块之间的依赖性应该尽可能降到最小
5.错误应该尽早被检测出来,最好是在编译时刻
本书是通过
2.创建和销毁对象
3.对于所有对象都通用的方法
4.类和接口
5.泛型
6.枚举和注解
7.方法
8.通用程序设计
9.异常
10.并发
11.序列化
十一个章节展开。
第2章 创建和销毁对象
1.考虑用静态工厂方法代替构造器
优势在于可以构造含义更清晰的实例,不必每次都创建一个新对象,可以返回子类型对象
服务提供者框架是指多个服务提供者实现一个服务,系统为服务提供者的客户端提供多个实现,并把他们从多个实现中解耦出来(JDBC就是一个典型代表)
缺点在于如果类不包含公开的的构造器,就不能被子类化(也就说这种情况下写静态工厂方法的同时还要写公开构造器)。其次它与静态方法没有任何定义上的区别(也就是说它本身就可能给人误导~)
2.多个构造器参数时要考虑用构建器。(与我写createTable时的优化不谋而合,只是我没有采取链式写法,直接用的JavaBean参数)。Builder模式的优势在于清晰,不足在于性能上其实没有构造器优秀,因为每次构造对象前需要构建一个构造器。是否要使用,依赖于可读性和性能间的权衡。
3.用私有构造器或枚举类型强化Singleton
枚举是作者提出的单例的终极方案,相对于私有构造器,它不能通过反射修改(私有构造器方式下,可以通过AccessiableObject.setAccessible方法调用私有构造器。抵御方法是检测是创建第二个构造器时抛出异常)
4.构造器抛异常可以让类不能被实例化
5.避免创建不必要的对象。(如装箱对象等)
小对象的创建和回收动作是非常廉价的,特别是在现代JVM的实现上。所以是静态化还是采取创建对象的方式并没有一个绝对的答案,比较好的策略是权衡创建当前对象付出的性能代价与静态化它时提供的简洁性。当然,在大批量运算时,要尽量减少创建对象。而对于实现频次十分低的对象,则可以考虑是否值得付出内存静态化存储。
维持自己的对象池来避免创建对象并不是一种好的做法。
6.消除过期的对象引用
数组情况下可能存在过期引用不会被主动回收。
7.避免使用终结方法(finalize)
实际使用finalize的情况也很少,因为它是不确定回收的。
好的策略是,在要做终结时,写一个手动终结的方法手动调用,结合try-finally结构直接回收。在重写实现了finalize的方法时,记得要调用super.finalize()。或者把重写的实现了finalize方法的类,直接写成一个静态的对象。这样回收静态对象时,会触发内部的finalize保证回收。