1, item 45 局部变量的作用域最小化
2. item 46 for each循环优于传统的for循环
3. 从这两个item看一个常见的错误的说法。
我们会在很多的场合看到说尽量避免在循环中new对象,应该用如下的circleOutside()方式。
public class CircleObject {
public static void main(String args[]) {
circleInside();
circleOutside();
}
private static void circleInside() {
long start = System.currentTimeMillis();
for (long i = 0; i < 2000000000; i++) {
Integer p = new Integer(0);
}
long end = System.currentTimeMillis();
System.out.println("circle inside: " + (end - start));
}
private static void circleOutside() {
long start2 = System.currentTimeMillis();
Integer p=null;
for (long i = 0; i < 2000000000; i++) {
p = new Integer(0);
}
long end2 = System.currentTimeMillis();
System.out.println("circle outside: " + (end2 - start2));
}
}
这是错误的。这错误的支撑理由有两种:
3.1 这会new出很多个无用的对象。毫无疑问,这是错上加错,因为当在循环中new变量不可避免时,这两种方式都会new出同样多的Integer对象。
3.2 这个会有太多的变量声明,性能较低。在代码中我们清楚的看到两种方法的执行时间,在笔者的机器上,circleInside的执行时间为:circle inside: 14859ms。circleOutside的执行时间为:circle outside: 15000ms,
结论是circle inside甚至快一点,但是误差很小,考虑到计算机的波动性,基本认为两者基本相当,所以性能绝对不是问题。
从item45 46中我们可以看到,这种做法不好,一扩大了临时变量的作用域,二是,for each循环中我们可以清楚的看到:for(Object object:objectList) ---对象object在不停的被声明,而没有提到for-each循环外头做声明并初始化为null。其实这些声明都是放在栈空间上的局部变量,可以很快的被回收,无需担心性能问题。
还有一种更为严重的错误,比如:
// 错误的做法
List<InvocationStatInfo> items = new ArrayList<InvocationStatInfo>();
InvocationStatInfo invocationStatInfo = new InvocationStatInfo();
for(StatisticsRecord record:apiInvokedData){
invocationStatInfo.setType("URL");
invocationStatInfo.setName(record.getKeyTwo());
invocationStatInfo.setInvCount((int) record.getCallTimes());
invocationStatInfo.setInvTime(record.getTotalTime());
invocationStatInfo.setSource(record.getKeyOne());
items.add(invocationStatInfo);
}
//正确的做法
List<InvocationStatInfo> items = new ArrayList<InvocationStatInfo>();
for(StatisticsRecord record:apiInvokedData){
InvocationStatInfo invocationStatInfo = new InvocationStatInfo();
invocationStatInfo.setType("URL");
invocationStatInfo.setName(record.getKeyTwo());
invocationStatInfo.setInvCount((int) record.getCallTimes());
invocationStatInfo.setInvTime(record.getTotalTime());
invocationStatInfo.setSource(record.getKeyOne());
items.add(invocationStatInfo);
}
在错误的做法中,items.add(invocationStatInfo);invocationStatInfo会不停的被修改,最后items都是同样的元素。我们总是说尽量避免在循环中创建对象,但是当不可避免时,千万别出娄子。