Integer Cache, the interview question to switch to Java constant pool

A very annoying Java interview question. It doesn't seem like it's a topic for fresh students, but it's good to know some of it.

My partner asked me a Java question that gave him a headache today, and asked for the output:

 
   
  1. /** 
  2.  *  
  3.  * @author DreamSea 2011-11-19 
  4.  */ 
  5. publicclass IntegerTest {  
  6.     publicstaticvoid main(String[] args) {       
  7.         objPoolTest (); 
  8.     } 
  9.  
  10.     public static void  objPoolTest() {   
  11.         Integer i1 = 40
  12.         Integer i2 = 40
  13.         Integer i3 = 0
  14.         Integer i4 = new Integer(40); 
  15.         Integer i5 = new Integer(40); 
  16.         Integer i6 = new Integer(0); 
  17.          
  18.         System.out.println("i1=i2\t" + (i1 == i2)); 
  19.         System.out.println("i1=i2+i3\t" + (i1 == i2 + i3)); 
  20.         System.out.println("i4=i5\t" + (i4 == i5)); 
  21.         System.out.println("i4=i5+i6\t" + (i4 == i5 + i6));     
  22.          
  23.         System.out.println();         
  24.     } 

Output result:

i1=i2true
i1=i2+i3   true
i4=i5false
i4=i5+i6true

It seems to be an easy problem, but the Result output by the Console is exactly the opposite of what we thought, and we are puzzled. Why is this?

Finally, through online search, we learned that Java provides the same object pool mechanism as String class in order to improve performance. Of course, Java's eight basic types of packaging classes (Packaging Type) also have object pool mechanism.

Integer i1=40; Java will execute the encapsulation of the code into Integer i1=Integer.valueOf(40) when compiling; by looking at the Source Code, it is found that:

There is an inner class IntegerCache (similar to a constant array, also called an object pool) in Integer.valueOf(), which maintains an Integer array cache with a length of (128+127+1)=256, and there is another Integer class 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。

好了,我想说道这里大家应该都会对Integer对象池有了更进一步的了解了吧,我在诺诺的问一句如果把40改为400猜猜会输出什么?

i1=i2false
i1=i2+i3true
i4=i5false
i4=i5+i6true

这是因为Integer i1=400,Integer i2=400他们的值已经超出了常量池的范围,JVM会对i1和i2各自创建新的对象(即Integer i1=new Integer(400)),所以他们不是同一个引用。


上述运行结果,经测试,是OK的,

转自:http://developer.51cto.com/art/201111/302748.htm


Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326071004&siteId=291194637