作者: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):
-------------------
源码1:
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);
}
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() {}
}
本文编写时间仓促,若有描述不妥或论证有问题的地方,欢迎各位交流、指正。
标签:lang,cache,java,valueOf,static,new,Integer,public From: https://blog.51cto.com/u_16245757/7350796