首先看一段代码(使用JDK 5),如下:
- public class Hello
- {
- public static void main(String[] args)
- {
- int a = 1000, b = 1000;
- System.out.println(a == b);
- Integer c = 1000, d = 1000;
- System.out.println(c == d);
- Integer e = 100, f = 100;
- System.out.println(e == f);
- }
- }
输出结果:
- true
- false
- true
The Java Language Specification, 3rd Edition 写道:
- 为了节省内存,对于下列包装对象的两个实例,当它们的基本值相同时,他们总是==:
- Boolean
- Byte
- Character, \u0000 - \u007f(7f是十进制的127)
- Integer, -128 — 127
查看jdk源码,如下:
- /**
- * Cache to support the object identity semantics of autoboxing for values between
- * -128 and 127 (inclusive) as required by JLS.
- *
- * The cache is initialized on first usage. During VM initialization the
- * getAndRemoveCacheProperties method may be used to get and remove any system
- * properites that configure the cache size. At this time, the size of the
- * cache may be controlled by the vm option -XX:AutoBoxCacheMax=<size>.
- */
- // value of java.lang.Integer.IntegerCache.high property (obtained during VM init)
- private static String integerCacheHighPropValue;
- static void getAndRemoveCacheProperties() {
- if (!sun.misc.VM.isBooted()) {
- Properties props = System.getProperties();
- integerCacheHighPropValue =
- (String)props.remove("java.lang.Integer.IntegerCache.high");
- if (integerCacheHighPropValue != null)
- System.setProperties(props); // remove from system props
- }
- }
- 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() {}
- }
- /**
- * Returns a <tt>Integer</tt> instance representing the specified
- * <tt>int</tt> value.
- * If a new <tt>Integer</tt> instance is not required, this method
- * should generally be used in preference to the constructor
- * {@link #Integer(int)}, as this method is likely to yield
- * significantly better space and time performance by caching
- * frequently requested values.
- *
- * @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) {
- if(i >= -128 && i <= IntegerCache.high)
- return IntegerCache.cache[i + 128];
- else
- return new Integer(i);
- }
这儿的IntegerCache有一个静态的Integer数组,在类加载时就将-128 到 127 的Integer对象创建了,并保存在cache数组中,一旦程序调用valueOf 方法,如果i的值是在-128 到 127 之间就直接在cache缓存数组中去取Integer对象。
再看其它的包装器:
- Boolean:(全部缓存)
- Byte:(全部缓存)
- Character(<= 127缓存)
- Short(-128 — 127缓存)
- Long(-128 — 127缓存)
- Float(没有缓存)
- Doulbe(没有缓存)
同样对于垃圾回收器来说:
- Integer i = 100;
- i = null;//will not make any object available for GC at all.
这里的代码不会有对象符合垃圾回收器的条件,这儿的i虽然被赋予null,但它之前指向的是cache中的Integer对象,而cache没有被赋null,所以Integer(100)这个对象还是存在。
而如果i大于127或小于-128则它所指向的对象将符合垃圾回收的条件:
- Integer i = 10000;
- i = null;//will make the newly created Integer object available for GC.
如果面试官问Integer与int的区别:估计大多数人只会说道两点,Ingeter是int的包装类,int的初值为0,Ingeter的初值为null。但是如果面试官再问一下Integer i = 1;int ii = 1; i==ii为true还是为false?估计就有一部分人答不出来了,如果再问一下其他的,估计更多的人会头脑一片混乱。所以我对它们进行了总结,希望对大家有帮助。
首先看代码:
1 package com.test; 2 /** 3 * 4 * @author 刘玲 5 * 6 */ 7 public class TestInteger { 8 9 /** 10 * @param args 11 */ 12 public static void main(String[] args) { 13 int i = 128; 14 Integer i2 = 128; 15 Integer i3 = new Integer(128); 16 //Integer会自动拆箱为int,所以为true 17 System.out.println(i == i2); 18 System.out.println(i == i3); 19 System.out.println("**************"); 20 Integer i5 = 127;//java在编译的时候,被翻译成-> Integer i5 = Integer.valueOf(127); 21 Integer i6 = 127; 22 System.out.println(i5 == i6);//true 23 /*Integer i5 = 128; 24 Integer i6 = 128; 25 System.out.println(i5 == i6);//false 26 */ Integer ii5 = new Integer(127); 27 System.out.println(i5 == ii5); //false 28 Integer i7 = new Integer(128); 29 Integer i8 = new Integer(123); 30 System.out.println(i7 == i8); //false 31 } 32 33 }
首先,17行和18行输出结果都为true,因为Integer和int比都会自动拆箱(jdk1.5以上)。
22行的结果为true,而25行则为false,很多人都不动为什么。其实java在编译Integer i5 = 127的时候,被翻译成-> Integer i5 = Integer.valueOf(127);所以关键就是看valueOf()函数了。只要看看valueOf()函数的源码就会明白了。JDK源码的valueOf函数式这样的:
1 public static Integer valueOf(int i) { 2 assert IntegerCache.high >= 127; 3 if (i >= IntegerCache.low && i <= IntegerCache.high) 4 return IntegerCache.cache[i + (-IntegerCache.low)]; 5 return new Integer(i); 6 }
看一下源码大家都会明白,对于-128到127之间的数,会进行缓存,Integer i5 = 127时,会将127进行缓存,下次再写Integer i6 = 127时,就会直接从缓存中取,就不会new了。所以22行的结果为true,而25行为false。
对于27行和30行,因为对象不一样,所以为false。
我对于以上的情况总结如下:
①无论如何,Integer与new Integer不会相等。不会经历拆箱过程,i3的引用指向堆,而i4指向专门存放他的内存(常量池),他们的内存地址不一样,所以为false
②两个都是非new出来的Integer,如果数在-128到127之间,则是true,否则为false
java在编译Integer i2 = 128的时候,被翻译成-> Integer i2 = Integer.valueOf(128);而valueOf()函数会对-128到127之间的数进行缓存
③两个都是new出来的,都为false
④int和integer(无论new否)比,都为true,因为会把Integer自动拆箱为int再去比