effective java 之避免创建不必要的对象
1、对于对象一般来说,我们最好的做法是重用对象,而不是每次使用都new出一个新的相同功能的对象,
这样做很高效,特别是对于那些不可变类来说。
String s = "123";而不用String s = new String("123")
因为JVM中会有一个常量池,可以保存字符串常量,直接使用"123"可以直接从常量池中返回对象,而不会重新创建新对象。
2、用valueOf()代替new Integer("1")
Integer i1 = new Integer("1");
Integer i2 = new Integer("1");
Integer i3 = Integer.valueOf("1");
Integer i4 = Integer.valueOf("1");
System.out.println(i1 == i2);
System.out.println(i3 == i4);
false
true
可以见用valueOf不会新建一个对象,实际上很多类默认的valueOf方法都不会返回一个新的实例。
3、fianl 一个公用的变量(一个经典的例子):
比如有一个Person对象,对象中有一个字段是生日,生日是个常量,它不能被更改,现在需要完成一个方法,
用这个方法我们可以获取到这个人是否出生在1946到1964年之间(也就是生育高峰期(baby boomer))。
第一种做法:
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
public class Person {
private final Date birthday;
public Person(Date birthday) {
this.birthday = birthday;
}
public boolean isBabyBoomer() {
Calendar c = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
// 将时间设置为1946年1月1日0时0分0秒
c.set(1946, Calendar.JANUARY, 1, 0, 0, 0);
Date boomStart = c.getTime();
c.set(1965, Calendar.JANUARY, 1, 0, 0, 0);
Date boomEnd = c.getTime();
return birthday.compareTo(boomStart) >= 0
&& birthday.compareTo(boomEnd) < 0;
}
}
isBabyBoomer在每次调用的时候都会创建一个Calendar,一个TimeZone和两个Date实例,这是不必要的。
第二种做法:
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
public class Person {
private final Date birthday;
private static final Date BOOM_START;
private static final Date BOOM_END;
public Person(Date birthday) {
this.birthday = birthday;
}
// 静态代码块,初始化器
static {
Calendar c = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
// 将时间设置为1946年1月1日0时0分0秒
c.set(1946, Calendar.JANUARY, 1, 0, 0, 0);
BOOM_START = c.getTime();
c.set(1965, Calendar.JANUARY, 1, 0, 0, 0);
BOOM_END = c.getTime();
}
public boolean isBabyBoomer() {
return birthday.compareTo(BOOM_START) >= 0
&& birthday.compareTo(BOOM_END) < 0;
}
}
Calendar、TimeZone和Date只实例一次,而不是在每次调用时都去创建这些实例。相比上面的程序块了200多倍。
4、减少自动装箱:
Java的int等类型会进行自动装填,特别是在循环调用的时候,我们应该优先使用基本类型,要当心无意识的自动装箱。
如果想要保证性能,则请尽量使用基本数据类型。
每次自动装箱(autoboxing)都会穿件一个多余的对象,
比如:Integer value = 0;
每次这样做都会穿件一个多余的Integer对象。
最后,并不是一定不要创建新的对象,JVM现代虚拟机对于小对象的回收非常快,
如果频繁使用小对象可以大大增加程序的简洁性和可读性的话也是很应该使用的。
每天努力一点,每天都在进步。