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

本文深入探讨了Java中使用Integer.valueOf代替new Integer的优化策略,通过剖析Integer源码,揭示了其内部缓存机制如何提高性能。文章还展示了通过字节码研究来验证这一优化的有效性,并对比了不同初始化方式对程序运行的影响,最终得出结论:合理利用缓存可以显著提升程序效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

作者: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() {}
    }

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

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值