本文共 4572 字,大约阅读时间需要 15 分钟。
int转Integerint i = 0;Integer wrapperi = new Integer(i);Integer转int
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的环境下可以编译通过并运行。
int i = 0;Integer wrapperi = i;还有其他方法? JDK1.5为Integer增加了一个全新的方法:
public static Integer valueOf(int i)以下代码在JDK1.5的环境下可以编译通过并运行。
int i = 0;Integer wrapperi = Integer.valueOf(i);此方法与new Integer(i)的不同处在于: 方法一调用类方法返回一个表示指定的 int 值的 Integer 实例。 方法二产生一个新的Integer对象。 JDK API文档中对这个新的valueOf方法有明确的解释: 如果不需要新的 Integer 实例,则通常应优先使用该方法,而不是构造方法 Integer(int),因为该方法有可能通过缓存经常请求的值而显著提高空间和时间性能。 但这个解释有点晦涩难懂。为什么该方法有可能通过缓存经常请求的值而显著提高性能? 通过反编译工具查看valueOf方法。
/* * 返回一个表示指定的 int 值的 Integer 实例。如果不需要新的 Integer 实例,则 * 通常应优先使用该方法,而不是构造方法 Integer(int),因为该方法有可能通过 * 缓存经常请求的值而显著提高空间和时间性能。 * @param i an int
value. * @return a Integer instance representing i. * @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这个类,此类代码如下 /* * 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类对象。 再举一个经常被提到的例子
Integer i=100;Integer j=100;//print trueSystem.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。
Integer i=200;Integer j=200;//print falseSystem.out.println(i==j);此时的 i=new Integer(200); 同样j=new Integer(200) 。 两次都在堆中开辟了Integer的对象。
i 和 j 中存储的堆的对象地址是完全不同的。i==j 自然返回false。
Integer wrapperi = new Integer(0);int i = wrapperi;附:AutoBoxing与UnBoxing带来的转变 在JDK1.5之前,我们总是对集合不能存放基本类型而耿耿于怀。 以下代码在JDK1.5中成为了可能,试想下在JDK1.5之前该如何实现这段代码?
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