Java integer 常量_java中Integer常量池

我们先看一个关于Integer的例子

public static void main(String[] args) {

// TeODO Auto-generated method stu

Integer i1 = 40;

Integer i2 = 40;

Integer i3 = 0;

Integer i4 = new Integer(40);

Integer i5 = new Integer(40);

Integer i6 = new Integer(0);

System.out.println("i1=i2\t" + (i1 == i2));

System.out.println("i1=i2+i3\t" + (i1 == i2 + i3));

System.out.println("i4=i5\t" + (i4 == i5));

System.out.println("i4=i5+i6\t" + (i4 == i5 + i6));

System.out.println();

}

}

结果:

i1=i2  true

i1=i2+i3  true

i4=i5  false

i4=i5+i6  true

再看一个例子

public static void main(String[] args) {

// TeODO Auto-generated method stu

Integer i1 = 400;

Integer i2 = 400;

Integer i3 = 0;

Integer i4 = new Integer(400);

Integer i5 = new Integer(400);

Integer i6 = new Integer(0);

System.out.println("i1=i2\t" + (i1 == i2));

System.out.println("i1=i2+i3\t" + (i1 == i2 + i3));

System.out.println("i4=i5\t" + (i4 == i5));

System.out.println("i4=i5+i6\t" + (i4 == i5 + i6));

System.out.println();

}

}

结果

i1=i2  false

i1=i2+i3  true

i4=i5  false

i4=i5+i6  true

比较上面两个例子,我们发现:两个例子代码几乎一样,就是值不一样,40和400的区别怎么会造成如此大的结果差别呢??

我们用上篇博客的方法,用javap看他们的反编译结果

public class com.study.main.Test extends java.lang.Object{

public com.study.main.Test();

Code:

0: aload_0

1: invokespecial #1; //Method java/lang/Object."":()V

4: return

public static void main(java.lang.String[]);

Code:

0: sipush 400 //40时我们用cipush(下同) cipush(char 类型)的值范围是-128——127,sipush(short 类型)的值范围是2^15——2^15-1,

3: invokestatic #2; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Int

eger;

6: astore_1

7: sipush 400

10: invokestatic #2; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Int

eger;

13: astore_2

14: iconst_0

15: invokestatic #2; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Int

eger;

18: astore_3

19: new #3; //class java/lang/Integer

22: dup

23: sipush 400

26: invokespecial #4; //Method java/lang/Integer."":(I)V

29: astore 4

31: new #3; //class java/lang/Integer

34: dup

35: sipush 400

38: invokespecial #4; //Method java/lang/Integer."":(I)V

41: astore 5

43: new #3; //class java/lang/Integer

46: dup

47: iconst_0

48: invokespecial #4; //Method java/lang/Integer."":(I)V

51: astore 6

53: getstatic #5; //Field java/lang/System.out:Ljava/io/PrintStream;

56: new #6; //class java/lang/StringBuilder

59: dup

60: invokespecial #7; //Method java/lang/StringBuilder."":()V

63: ldc #8; //String i1=i2\t

65: invokevirtual #9; //Method java/lang/StringBuilder.append:(Ljava/lang/

String;)Ljava/lang/StringBuilder;

68: aload_1

69: aload_2

70: if_acmpne 77

73: iconst_1

74: goto 78

77: iconst_0

78: invokevirtual #10; //Method java/lang/StringBuilder.append:(Z)Ljava/la

ng/StringBuilder;

81: invokevirtual #11; //Method java/lang/StringBuilder.toString:()Ljava/l

ang/String;

84: invokevirtual #12; //Method java/io/PrintStream.println:(Ljava/lang/St

ring;)V

87: getstatic #5; //Field java/lang/System.out:Ljava/io/PrintStream;

90: new #6; //class java/lang/StringBuilder

93: dup

94: invokespecial #7; //Method java/lang/StringBuilder."":()V

97: ldc #13; //String i1=i2+i3\t

99: invokevirtual #9; //Method java/lang/StringBuilder.append:(Ljava/lang/

String;)Ljava/lang/StringBuilder;

102: aload_1

103: invokevirtual #14; //Method java/lang/Integer.intValue:()I

106: aload_2

107: invokevirtual #14; //Method java/lang/Integer.intValue:()I

110: aload_3

111: invokevirtual #14; //Method java/lang/Integer.intValue:()I

114: iadd

115: if_icmpne 122

118: iconst_1

119: goto 123

122: iconst_0

123: invokevirtual #10; //Method java/lang/StringBuilder.append:(Z)Ljava/la

ng/StringBuilder;

126: invokevirtual #11; //Method java/lang/StringBuilder.toString:()Ljava/l

ang/String;

129: invokevirtual #12; //Method java/io/PrintStream.println:(Ljava/lang/St

ring;)V

132: getstatic #5; //Field java/lang/System.out:Ljava/io/PrintStream;

135: new #6; //class java/lang/StringBuilder

138: dup

139: invokespecial #7; //Method java/lang/StringBuilder."":()V

142: ldc #15; //String i4=i5\t

144: invokevirtual #9; //Method java/lang/StringBuilder.append:(Ljava/lang/

String;)Ljava/lang/StringBuilder;

147: aload 4

149: aload 5

151: if_acmpne 158

154: iconst_1

155: goto 159

158: iconst_0

159: invokevirtual #10; //Method java/lang/StringBuilder.append:(Z)Ljava/la

ng/StringBuilder;

162: invokevirtual #11; //Method java/lang/StringBuilder.toString:()Ljava/l

ang/String;

165: invokevirtual #12; //Method java/io/PrintStream.println:(Ljava/lang/St

ring;)V

168: getstatic #5; //Field java/lang/System.out:Ljava/io/PrintStream;

171: new #6; //class java/lang/StringBuilder

174: dup

175: invokespecial #7; //Method java/lang/StringBuilder."":()V

178: ldc #16; //String i4=i5+i6\t

180: invokevirtual #9; //Method java/lang/StringBuilder.append:(Ljava/lang/

String;)Ljava/lang/StringBuilder;

183: aload 4

185: invokevirtual #14; //Method java/lang/Integer.intValue:()I

188: aload 5

190: invokevirtual #14; //Method java/lang/Integer.intValue:()I

193: aload 6

195: invokevirtual #14; //Method java/lang/Integer.intValue:()I

198: iadd

199: if_icmpne 206

202: iconst_1

203: goto 207

206: iconst_0

207: invokevirtual #10; //Method java/lang/StringBuilder.append:(Z)Ljava/la

ng/StringBuilder;

210: invokevirtual #11; //Method java/lang/StringBuilder.toString:()Ljava/l

ang/String;

213: invokevirtual #12; //Method java/io/PrintStream.println:(Ljava/lang/St

ring;)V

216: getstatic #5; //Field java/lang/System.out:Ljava/io/PrintStream;

219: invokevirtual #17; //Method java/io/PrintStream.println:()V

222: return

}

比较后我们惊人的发现,两者其实没有什么区别

只有这里:

0:   sipush  400 //40时我们用cipush(下同)  cipush(char 类型)的值范围是-128——127,sipush(short 类型)的值范围是2^15——2^15-1

我们看到第12行: 3:   invokestatic    #2; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Int

在Integer中是调用Integer.valueOf初始化对象的

Integer.valueOf函数

public static Integer valueOf(int i) {

if(i >= -128 && i <= IntegerCache.high)

return IntegerCache.cache[i + 128];

else

return new Integer(i);

}

IntegerCache

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

}

通过研究发现:Integer.valueOf()中有个内部类IntegerCache(类似于一个常量数组,也叫对象池),它维护了一个Integer数组cache,长度为(128+127+1)=256;Integer类中还有一个Static Block(静态块),如上所示。

从这个静态块可以看出,Integer已经默认创建了数值【-128-127】的Integer缓存数据。所以使用Integer i1=40时,JVM会直接在该在对象池找到该值的引用。

也就是说这种方式声明一个Integer对象时,JVM首先会在Integer对象的缓存池中查找有木有值为40的对象,如果有直接返回该对象的引用;如果没有,则使用New keyword创建一个对象,并返回该对象的引用地址。因为Java中【==】比较的是两个对象是否是同一个引用(即比较内存地址),i2和i2都是引用的同一个对象,So i1==i2结果为”true“;而使用new方式创建的i4=new Integer(40)、i5=new Integer(40),虽然他们的值相等,但是每次都会重新Create新的Integer对象,不会被放入到对象池中,所以他们不是同一个引用,输出false。

对于i1==i2+i3、i4==i5+i6结果为True,是因为,Java的数学计算是在内存栈里操作的,Java会对i5、i6进行拆箱操作,其实比较的是基本类型(40=40+0),他们的值相同,因此结果为True。

但是但为400时,这个时候已经超过了cache的范围,所以都得重新初始化对象

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值