本文用于阅读effective java代码优化整理(实时更新)
创建与销毁对象
对象是java中占据最大空间的基础单元,对于它的管理我们已经有了jvm和gc,但有些地方他们是鞭长莫及的。
1.用静态工厂方法代替构造器+builder构建器
为什么这样做?因为构造器是一种无法选择也没有标示性的工作,而静态工厂方法可以随意控制参数与返回对象,且可以设置函数名,有标示和灵活性。例子:包装类的valueOf方法。
另外,还可以考虑builder模式来进行参数构造。
2.更好的单例模式
我们熟知的单例模式是双重校验的静态单例方法,但这可能存在序列化生成多个对象问题,可以考虑实现序列化接口和transient 或者 利用单元素枚举类型自带单对象序列化来优化。
3.如何保证类不被实例化?
这种都是只提供静态数据的工具类,比如Collections,很简单,让这个类包含一个私有构造器即可。
4.底层资源类调用推荐
依赖注入优于静态工具类与单例类
5.*避免创建不必要对象
作为类初始化一部分(静态数据)、缓存、特殊场景(适配器只需一个、避免自动拆装箱、合理使用对象池)
6.消除过期对象引用
过期引用例子:使用栈,栈中数据存在内存泄漏(jvm只管这个栈,但栈内数据不置null就无法回收),但这种问题太细小了。有些场景需注意:用弱引用去实现缓存对象、监听器或者回调,可以有效防止过期对象。(注意:如果是String这种常量,或者Object类,放在永久代的,是不会受到gc影响的)
7.避免使用finalize/cleaner方法
这两个方法不可预测,不会保证执行。
8.try-with-resources优于try-finally
多个资源关闭的情况下try-finally就犯难了。
对于Object类通用方法的操作
1.覆盖equals
通常用于覆盖“值类”,比如String、Set、Map等集合或映射,它是需要满足所谓的自反性、对称性、传递性、一致性等条件。
此外注意两点:一起覆盖hashCode方法、不要将参数Object替换(不然就无法覆盖超类了)
2.尽量实现toString
3.合理使用cloneable接口
Object实现的clone方法有问题(实现cloneable接口会改变clone方法行为),具体的,基本类型是值拷贝,String是深拷贝,普通对象是浅拷贝(危险)
4.尽量实现Comparable接口(虽不是Object方法)
当一个类对排序敏感时都应该这样做,可以轻松被分类、搜索。(几乎所有的集合和枚举类都实现了Comparable接口)
类和接口
类和接口可能是我们平常开发中最常接触的东西,它们和它们的数据有多个访问权限,总的来说就是“最小影响范围”,这对于程序的解耦与维护至关重要。
1.类和成员可访问性最小化
类有公有类和包级别类,成员有私有、包级别(默认)、受保护、公有四种访问级别。注意包级别和受保护是访问性大与小的边界线,因为受保护的成员将时类导出api的一部分。特别的,让类具有公有静态final数组域会有严重安全问题,客户端可以修改数组内容。
2.公有类不该暴露可变的域
很简单就是不直接将可变域透出,而是以set、get方法提供访问接口,这可以使得后续维护简单、便于权限控制。比如Point、Dimension类违反了,造成了严重的性能问题。
3.使可变性最小化
可变性最小化最极端的例子就是不可变类,比如String、包装类等,实现很简单,所有域都是private、final的,且无设值方法。这样可以使得代码更安全,在不同类间自由的共享使用;缺点也很明显,修改每次都会生成一个新对象,占空间。这是一个权衡,但是在我们写代码时应该尽可能限制可变性(private、final等等)