关于使用new Integer还是Integer.valueOf的研究

来源:互联网 发布:淘宝有商家可以套现吗 编辑:程序博客网 时间:2024/05/22 13:38

作者:fbysss
msn:jameslastchina@hotmail.com  
blog:blog.csdn.net/fbysss
声明:本文由fbysss原创,转载请注明出处

前言:

最近看到这样的说法:使用Integer.valueOf代替new Integer更有效率,原因是研究了Integer源码,发现有一个缓存可以利用。

对此我也一探究竟。发现这其实与Java的自动装箱拆箱有关,直接使用Integer i =数值的方式即可。

通过字节码研究是比较有效的方式。那我们来看看吧:


-------------------
Integer.valueOf源码:
-------------------


   public static Integer valueOf(int i) {
final int offset = 128;
if (i >= -128 && i <= 127) { // must cache 
    return IntegerCache.cache[i + offset];
}
        return new Integer(i);
    }


-------------------
IntegerCache 源码(jdk1.6.0_12):
-------------------
    private static class IntegerCache {
private IntegerCache(){}


static final Integer cache[] = new Integer[-(-128) + 127 + 1];//注意这个cache是final的


static {
    for(int i = 0; i < cache.length; i++)
cache[i] = new Integer(i - 128);
}



源码1:

public class TestInt {


/**
* @param args
*/
public static void main(String[] args) {
int i =200;
i ++;
}
}
---------------------
javap -c TestInt
---------------------
public class com.sss.newage.test.TestInt extends java.lang.Object{
public com.sss.newage.test.TestInt();
  Code:
   0:   aload_0
   1:   invokespecial   #8; //Method java/lang/Object."<init>":()V
   4:   return


public static void main(java.lang.String[]);
  Code:
   0:   sipush  200
   3:   istore_1
   4:   iinc    1, 1
   7:   return


}



源码2:
public class TestInt {


/**
* @param args
*/
public static void main(String[] args) {
Integer i =200;
i ++;
}
}
---------------------
javap -c TestInt
---------------------
public class com.sss.newage.test.TestInt extends java.lang.Object{
public com.sss.newage.test.TestInt();
  Code:
   0:   aload_0
   1:   invokespecial   #8; //Method java/lang/Object."<init>":()V
   4:   return


public static void main(java.lang.String[]);
  Code:
   0:   sipush  200
   3:   invokestatic    #16; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
   6:   astore_1
   7:   aload_1
   8:   invokevirtual   #22; //Method java/lang/Integer.intValue:()I
   11:  iconst_1
   12:  iadd
   13:  invokestatic    #16; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
   16:  astore_1
   17:  return


}

我们可以看到:

1.第3行(行标为3)调用了Integer.valueOf,一旦数字在缓存窗口中,则能够提高效率,那么我们可以认为,缓存不用白不用,的确比new Integer要好。

2..第8行(行标为8)进行了自动拆箱(intValue),目的是进行数字的加1运算

3.注意第13行,运算完毕之后,再次进行装箱(valueOf),这些运算都不影响cache本身,所以cache设计成只读即可,也不存在线程安全问题。



源码3:修改Integer i =200;为Integer i =Integer.valueOf(200);
public class TestInt {


/**
* @param args
*/
public static void main(String[] args) {
Integer i =Integer.valueOf(200);
i ++;
}
}


public class com.sss.newage.test.TestInt extends java.lang.Object{
public com.sss.newage.test.TestInt();
  Code:
   0:   aload_0
   1:   invokespecial   #8; //Method java/lang/Object."<init>":()V
   4:   return


public static void main(java.lang.String[]);
  Code:
   0:   sipush  200
   3:   invokestatic    #16; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
   6:   astore_1
   7:   aload_1
   8:   invokevirtual   #22; //Method java/lang/Integer.intValue:()I
   11:  iconst_1
   12:  iadd
   13:  invokestatic    #16; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
   16:  astore_1
   17:  return


}

可以看到,使用Integer i = 200;与Integer i = Integer.valueOf(200);是等价的,从程序员读写习惯来看,使用Integer i = 200;的形式更好




------------------------

注意一点:

------------------------

最新版本的Jdk,Integer有改写,IntegerCache 的缓存窗口可以配置(通过JVM参数 -XX:AutoBoxCacheMax设置)。

JDK1.6.0_27相关源码

 /**
     * Cache to support the object identity semantics of autoboxing for values between 
     * -128 and 127 (inclusive) as required by JLS.
     *
     * The cache is initialized on first usage. During VM initialization the
     * getAndRemoveCacheProperties method may be used to get and remove any system
     * properites that configure the cache size. At this time, the size of the
     * cache may be controlled by the vm option -XX:AutoBoxCacheMax=<size>.
     */


    // value of java.lang.Integer.IntegerCache.high property (obtained during VM init)

    static void getAndRemoveCacheProperties() {
        if (!sun.misc.VM.isBooted()) {
            Properties props = System.getProperties();
            integerCacheHighPropValue =
                (String)props.remove("java.lang.Integer.IntegerCache.high");
            if (integerCacheHighPropValue != null)
                System.setProperties(props);  // remove from system props
        }
    }


    private static class IntegerCache {
        static final int high;
        static final Integer cache[];


        static {
            final int low = -128;


            // high value may be configured by property
            int h = 127;
            if (integerCacheHighPropValue != null) {
                // Use Long.decode here to avoid invoking methods that
                // require Integer's autoboxing cache to be initialized
                int i = Long.decode(integerCacheHighPropValue).intValue();
                i = Math.max(i, 127);
                // Maximum array size is Integer.MAX_VALUE
                h = Math.min(i, Integer.MAX_VALUE - -low);
            }
            high = h;


            cache = new Integer[(high - low) + 1];
            int j = low;
            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++);
        }


        private IntegerCache() {}
    }

本文编写时间仓促,若有描述不妥或论证有问题的地方,欢迎各位交流、指正。

原创粉丝点击