专注于Jsp开发,为Jsp开发提供源动力 VM主机| 海外空间| 郑州网站建设| 郑州网络公司| 洛阳网站建设
jsp空间

【Java】 Integer 包装器的比较小陷阱

添加时间:[2010-3-15 9:17:04] 

Java代码
  • Integer i=100;  
  • Integer j=100;  
  • System.out.println(i==j);  //(1)  
  •   
  • Integer i=200;  
  • Integer j=200;  
  • System.out.println(i==j);  //(2)  
  • Integeri=100;Integerj=100;System.out.println(i==j);//(1)Integeri=200;Integerj=200;System.out.println(i==j);//(2)

     

    其中(1):true,(2)false。这到底是为什么呢?

     

    我们分两步来说明这个问题:

     

    首先Integeri=100;编译器会自动将int类型常数100包装成Interger,采用的是Integer.valueOf(100);这个方法。

     

    然后我们看看valueOf(int)这个方法的源代码:

    Java代码
  •  /* 
  •   * 返回一个表示指定的 int 值的 Integer 实例。如果不需要新的 Integer 实例,则 
  •   * 通常应优先使用该方法,而不是构造方法 Integer(int),因为该方法有可能通过 
  •   * 缓存经常请求的值而显著提高空间和时间性能。  
  •   * @param  i an <code>int</code> value. 
  •   * @return a <tt>Integer</tt> instance representing <tt>i</tt>. 
  •   * @since  1.5 
  •   */  
  • 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内部类 
  •   * 其中cache[]数组用于存放从-128到127一共256个整数 
  •   */  
  • private static class IntegerCache {  
  •     private IntegerCache(){}  
  •   
  •     static final Integer cache[] = new Integer[-(-128) + 127 + 1];  
  •   
  •     static {  
  •         for(int i = 0; i < cache.length; i++)  
  •         cache[i] = new Integer(i - 128);  
  •     }  
  • }  
  • /**返回一个表示指定的int值的Integer实例。如果不需要新的Integer实例,则*通常应优先使用该方法,而不是构造方法Integer(int),因为该方法有可能通过*缓存经常请求的值而显著提高空间和时间性能。*@paramian<code>int</code>value.*@returna<tt>Integer</tt>instancerepresenting<tt>i</tt>.*@since1.5*/publicstaticIntegervalueOf(inti){finalintoffset=128;if(i>=-128&&i<=127){//mustcache returnIntegerCache.cache[i+offset];}returnnewInteger(i);}/**IntegerCache内部类*其中cache[]数组用于存放从-128到127一共256个整数*/privatestaticclassIntegerCache{ privateIntegerCache(){} staticfinalIntegercache[]=newInteger[-(-128)+127+1]; static{ for(inti=0;i<cache.length;i++) cache[i]=newInteger(i-128); }}

     

    原来如此,当-128=<i<=127的时候,返回的是IntegerCache中的数组的值;当i>127或i<-128时,返回的是Integer类对象。

     

    这就好解释:

     

    Java代码
  • Integer i=100;  
  • Integer j=100;  
  • System.out.println(i==j);  //(1)  
  • Integeri=100;Integerj=100;System.out.println(i==j);//(1)

    此时的i=IntegerCache.cache[228],因此Integer引用i中存储的是cache数组第228号元素的地址。同理j也是同一个cache数组的第228号元素的地址(因为cache是Integer的静态数组,只有一个)。i==j比较的是引用地址,因此相等。

    Java代码
  • Integer i=200;  
  • Integer j=200;  
  • System.out.println(i==j);  //(2)  
  • Integeri=200;Integerj=200;System.out.println(i==j);//(2)

    此时的i=newInteger(200); 同样j=newInteger(200)。两次都在堆中开辟了Integer的对象。i和j中存储的堆得对象地址是完全不同的。i==j自然不相等了。

     

    那么这样做有什么意义呢?我们来看看API的解释:

    Java代码
  • 返回一个表示指定的 int 值的 Integer 实例。如果不需要新的 Integer 实例,  
  • 则通常应优先使用该方法,而不是构造方法 Integer(int),因为该方法有可能  
  • 通过缓存经常请求的值而显著提高空间和时间性能。   
  • 返回一个表示指定的int值的Integer实例。如果不需要新的Integer实例,则通常应优先使用该方法,而不是构造方法Integer(int),因为该方法有可能通过缓存经常请求的值而显著提高空间和时间性能。

    加入我们在编程时大量需要值为100的Integer对象,如果只能通过new来创建的话。是不是需要在堆中开辟大量值一样的Integer对象呢!这是相当不划算的。既然如此,Java中的常量池的想法是不是可以提醒我们点什么呢。是的,IntegerCache.cache就相当于这样一个常量池。当我们需要Integeri=100的时候,直接从cache中取出第[100+128]号元素的地址赋值引用i,再次需要Integerj=100时,还是直接去这个地址赋给j.....是不是省去了再堆中不停的创建对象的代价了(空间,时间上的消耗都很大)。

    关于我们 | 付款方式 | 客户管理 | 网站导航 | 友情连接


    版权所有 2008 三易网络(洛阳)科技开发有限公司 京ICP备06012028号

    服务热线:0371-63653120 63658758(郑州) 0379-63921200   63265368(洛阳)

    QQ在线客服: JSP空间咨询   JSP空间咨询    Email:web@suneasy.cn

    郑州网络公司 郑州网站建设 洛阳网站建设

    总部地址:纱厂南路41号中泰新城泰福苑803室 郑州分公司地址:金水区圣菲城