`

Iteger int

 
阅读更多
.Java的Integer与int互转 博客分类: java面试题
JavaCacheJ#JDK .
int转Integer

Java代码 
1.int i = 0;  
2.Integer wrapperi = new Integer(i); 
int i = 0;
Integer wrapperi = new Integer(i);


Integer转int

Java代码 
1.Integer wrapperi = new Integer(0);  
2.int i = wrapperi.intValue(); 
Integer wrapperi = new Integer(0);
int i = wrapperi.intValue();




JDK1.5以后的int转Integer
JDK1.5以后,Java为我们提供了更为丰富的转换方法。

其中最值得一提的就是自动装包/自动拆包(AutoBoxing/UnBoxing)。
此功能大大丰富了基本类型(primitive type)数据与它们的包装类(Wrapper Class)
的使用。

由于AutoBoxing的存在,以下代码在JDK1.5的环境下可以编译通过并运行。

Java代码 
1.int i = 0;  
2.Integer wrapperi = i; 
int i = 0;
Integer wrapperi = i;


还有其他方法?
JDK1.5为Integer增加了一个全新的方法:

Java代码 
1.public static Integer valueOf(int i) 
public static Integer valueOf(int i)
以下代码在JDK1.5的环境下可以编译通过并运行。

Java代码 
1.int i = 0;  
2.Integer wrapperi = Integer.valueOf(i); 
int i = 0;
Integer wrapperi = Integer.valueOf(i);


此方法与new Integer(i)的不同处在于:
方法一调用类方法返回一个表示指定的 int 值的 Integer 实例。
方法二产生一个新的Integer对象。

JDK API文档中对这个新的valueOf方法有明确的解释:
如果不需要新的 Integer 实例,则通常应优先使用该方法,而不是构造方法 Integer(int),因为该方法有可能通过缓存经常请求的值而显著提

高空间和时间性能。

但这个解释有点晦涩难懂。为什么该方法有可能通过缓存经常请求的值而显著提高性能?

通过反编译工具查看valueOf方法。

Java代码 
1. /*   
2.  * 返回一个表示指定的 int 值的 Integer 实例。如果不需要新的 Integer 实例,则   
3.  * 通常应优先使用该方法,而不是构造方法 Integer(int),因为该方法有可能通过   
4.  * 缓存经常请求的值而显著提高空间和时间性能。    
5.  * @param  i an <code>int</code> value.   
6.  * @return a <tt>Integer</tt> instance representing <tt>i</tt>.   
7.  * @since  1.5   
8.  */    
9.public static Integer valueOf(int i) {     
10.      final int offset = 128;     
11.      if (i >= -128 && i <= 127) { // must cache      
12.        return IntegerCache.cache[i + offset];     
13.     }     
14.     return new Integer(i);     
15.}   
/* 
  * 返回一个表示指定的 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);  



可以看到对于范围在-128到127的整数,valueOf方法做了特殊处理。
采用IntegerCache.cache[i + offset]这个方法。
从名字,我们可以猜出这是某种缓存机制。

进一步跟踪IntegerCache这个类,此类代码如下

Java代码 
1./*   
2.  * IntegerCache内部类   
3.  * 其中cache[]数组用于存放从-128到127一共256个整数   
4.  */    
5.private static class IntegerCache {     
6.    private IntegerCache(){}     
7.    
8.    static final Integer cache[] = new Integer[-(-128) + 127 + 1];     
9.    
10.    static {     
11.        for(int i = 0; i < cache.length; i++)     
12.        cache[i] = new Integer(i - 128);     
13.    }     
14.}   
/* 
  * 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);  
    }  



这就是valueOf方法真正的优化方法,当-128=<i<=127的时候,返回的是IntegerCache中的数组的值;当 i>127 或 i<-128 时,返回的是

Integer类对象。

再举一个经常被提到的例子

Java代码 
1.Integer i=100;  
2.Integer j=100;  
3.//print true  
4.System.out.println(i==j); 
Integer i=100;
Integer j=100;
//print true
System.out.println(i==j);

此时的 i=IntegerCache.cache[i + 128] = IntegerCache.cache[228],
同样j = IntegerCache.cache[j + 128] = IntgerCache.cache[228]
因此 Integer引用i中存储的是cache数组第228号元素的地址。同理j也是同一个cache数组的第228号元素的地址(因为cache是Integer的static

数组,只有一个)。
i==j比较的是引用地址,因此返回true。


Java代码 
1.Integer i=200;  
2.Integer j=200;  
3.//print false  
4.System.out.println(i==j);  
Integer i=200;
Integer j=200;
//print false
System.out.println(i==j);

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


引入缓存机制的作用何在?

接着上面的例子,假如我们在编程时大量需要值为100(100的范围在-128到127之间)的Integer对象。如果只能通过new来创建,需要在堆中开

辟大量值一样的Integer对象。
这是相当不划算的,IntegerCache.cache很好的起到了缓存的作用。
当我们需要Integer i  = 100的时候,直接从cache中取出第[100+128]号元素的地址赋值给引用i,再次需要Integer j = 100时,还是直接去这

个地址赋值给j。是不是省去了在堆中不停的创建对象的代价了(空间,时间上的消耗都很大)。 这就是valueOf方法真正的提高性能之处。
正如JDK API文档对valueOf(int i)方法的描述,该方法有可能通过缓存经常请求的值而显著提高空间和时间性能。

结论

valueOf(int i)的优化只针对于范围在-128到127的整数。




JDK1.5以后的Integer转int
由于UnBoxing的存在,以下代码在JDK1.5的环境下可以编译通过并运行。

Java代码 
1.Integer wrapperi = new Integer(0);  
2.int i = wrapperi; 
Integer wrapperi = new Integer(0);
int i = wrapperi;








附:AutoBoxing与UnBoxing带来的转变
在JDK1.5之前,我们总是对集合不能存放基本类型而耿耿于怀。

以下代码在JDK1.5中成为了可能,试想下在JDK1.5之前该如何实现这段代码?

Java代码 
1.int x = 1;   
2.Collection collection = new ArrayList();   
3.collection.add(x);//AutoBoxing,自动转换成Integer.   
4.Integer y = new Integer(2);   
5.collection.add(y + 2); //y + 2为UnBoxing,自动转换成int。之后再次转换为Integer。 
int x = 1;
Collection collection = new ArrayList();
collection.add(x);//AutoBoxing,自动转换成Integer.
Integer y = new Integer(2);
collection.add(y + 2); //y + 2为UnBoxing,自动转换成int。之后再次转换为Integer。


此特性同样适用于Map

Java代码 
1.Map map = new HashMap();  
2.int x = 1;  
3.Integer y = new Integer(2);  
4.int z = 3;  
5.map.put(x,y + z);//x自动转换成Integer。y+z自动转换成int。之后再次转换为Integer。 
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics