Effective Java之避免创建不必要的对象

Effective Java中有很多值得注意的技巧,今天我刚开始看这本书,看到这一章的时候,我发现自己以前并没有理解什么是不必要的对象,所以拿出来跟大家探讨一下,避免以后犯不必要的错误!
首先书中对不可变的对象(immutable)做了简单解释:不可变对象都是可以重用的。因为String是不可变对象,所以这样创建String是没有必要的:

    String str = new String("abc");

'abc'本身就是一个String实例了,再用实例去包裹他,就属于浪费资源了。这样创建的话,'abc'就可以实现重用了:

    String str = "abc";

如果本身不是不可变对象,JDK中很多类也提供了重用的功能。了解和使用它们,可以避免创建不必要对象。
例如LongInteger等,都提供了valueOf()的静态方法。Calendar等也提供了getInstance()方法。

上面都不是重点,很多人都已经了解他们了。下面探讨一个很有意思的问题,看这段代码:

        Long sum = 0L;
        for (int i = 0; i < Integer.MAX_VALUE; i++) {
            sum += i;
        }
        System.out.println(sum);

JDK1.5支持自动装箱和拆箱,我们不用进行类型转换了。但作者说这里有一个疏忽,导致了计算时间的大大提升,我很是没看出来。其实这个问题还是大标题所讲的:创建了不必要的对象。
sum是一个Long类型的对象,在他本身相加的时候,他会再创建一个Long对象,因为这些对象的不同,决定他们不能重用,而就这样,我们创建了Integer.MAX_VALUELong对象。想想挺恐怖的,虽然创建一个对象的开销很小,但也不能这样玩儿。
解决之道就是把Long sum换成long sum,使用了基本类型,他们是在栈中,也没有创建对象一说,性能提升不止一倍。
在我的计算机上,Long计算花费30秒, long花费了3.1秒左右。
避免创建不必要的对象,注意自动装箱带来的影响,这一点在以后要提高警惕!
当然,不能因噎废食,章中最后的解说,个人感觉也非常精彩:

    当然,我们不要认为创建对象的代价非常昂贵,因为小对象的构造器只做很少量的显式工作,他的创建和回收动作是非常廉价的。通过创建附加的对象,提升程序的清晰性、间接性和功能性,这通常是件好事。  
    反之,使用对象池来创建对象并不是一种好的做法,除非池中的对象是非常重量级的。
posted @ 2013-11-06 10:52  轩辕李  阅读(406)  评论(0编辑  收藏  举报