《effective Java 》书中第六条写道避免创建不必要的对象,再次做一个总结
总结如下几点:
1.避免创建不必要的对象,比如字符串的创建不使用new方式
2.通过静态工厂方法可以创建不必要的对象
3.对象的复用 如果一些对象可以被复用
看下面 的一个例子
有下面一个正则校验数据的格式
static boolean isRomanNumeral(String s) {
return s.matches("^(?=.)M*(C[MD]|D?C{0,3})" + "(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$");
}
这样存在的一个问题,如果在临界情况下重复的使用,创建一次实例,并且只是使用一次,之后他就有垃圾回收。 为了提高性能,作为类初始化的一部分,将正则表达式显示的编译为一个Pattenrn实例(不可变),缓存它,并在isRomanNumberal方法的每个调用中重复使用相同的实例。
改成下面的方式
public class Test06 {
private static final Pattern ROMAN = Pattern.compile("^(?=.)M*(C[MD]|D?C{0,3})" + "(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$");
static boolean isRomanNumeral(String s) {
return ROMAN.matcher(s).matches();
}
}
看到这个优化的时候让我想到一个面试题:
gc回收比例远远大于8:1:1为什么?
当时我的回答是说明有大量临时对象产生
面试又问怎么优化?
我记得我当时只答出来来减少对象的创建,控制对象的定义范围,局部变量定义为局部变量,不要随意定义对象的创建范围。
今天看到这个感觉可以把这个补充进去。使用static减少公用对象的创建。
另外一种避免创建不必要的的对象方法是自动装箱
private static long sum() {
Long sum = 0L;
for (long i = 0; i <= Integer.MAX_VALUE; i++) {
sum += i;
}
return sum;
}
这个程序的结果是正确的,但是由于写错了一个字符,运行的结果要比实际慢很多。变量sum被声明成了Long而不是long,这意味着程序构造了大约231不必要的Long实例(每次往Long类型的sum变量中增加一个long类型的构造实例)
* 总结:优先使用基本类型而不是装箱的基本类型,也要注意无意识的自动装箱