Effective Java 2

6. 避免创建不必要的对象
最好能重用单个对象,而不是每次需要的时候就创建一个相同功能的新对象;
可以提高效率。
String避免多次创建对象
错误的做法:
1 | String s = new String("It's a text."); |
每次执行的时候都会创建一个String对象,而且参数("It's a text.")
本来就是一个对象,这样使用会影响效率;
如果在一个频繁调用的方法中出现,就会创建成千上万个对象;
正确的做法:
1 | String s= "It's a text."; |
这样就只使用了一个String实例,而不是每次运行都会创建一个示例;
在JVM里这样做,对于不同的String引用,如果它们的字符串是相同的,它们对应对象就是一样的,而不是多个对象。
对于提供了静态工厂方法的类,一般优先使用静态工厂方法而非构造器。
如使用Boolean.valueOf()
而不是Boolean()
。
有些对象创建成本较高,如果内容不变,可以考虑将这些对象缓存下来多次使用。
比如Pattern实例;
Pattern实例创建成本较高,若多次创建对性能影响较大;
可以考虑将正则表达式显式地编译成一个Pattern实例,并让他成为类初始化的一部分;
1 | private final static Pattern pattern = Pattern.compile(">(.*)<\/div>") |
优先使用基本类型而非装箱基本类型
使用基本类型比装箱基本类型效率较高,因为装箱基本类型需要创建对象;
错误的做法:
1 | public class 使用基本数据类型而非装箱基本类型 { |
正确的做法:只需要将Long改为long就可。
1 | public class 使用基本数据类型而非装箱基本类型 { |
7. 消除过期的对象引用
使用栈来学习“无意识的内存泄露”。
1 | public class Stack { |
如果栈内元素先push,然后pop,旧的对象并没有被清理,且由于被引用,不会被gc清理掉。
有概率引发内存泄漏;
解决方法:
1 | public Object pop(){ |
先取出对象,将数组内引用清除,这样就不会引用对象,最后返回对象;
若对象在后续过程中使用结束,对象将会被gc清理,而不是无法被清理。
为缓存设置生命周期
监听器和其他回调
为API回调使用WeakHashMap
如果实现了一个API,客户端在这个API进行注册回调,却没有显式地取消注册,这样的注册会逐渐堆积起来,引发可能的内存泄漏;
确保回调被回收的方法就是只保存他们的弱引用,比如将他们保存成WeakHashMap的键。
评论