int 是基本数据类型它的值存在于栈中,Integer是int的包装类它的值存在于堆中,这些都是基础概念。
下面代码示例是经常被面到的简单小问题,通过这个问题就可以知道什么是自动装箱什么是自动拆箱。
package base.test;
public class Test1 {
public static void main(String[] args) {
Integer i = 10;
Integer j = 10;
System.out.println(i == j);
Integer a = 128;
Integer b = 128;
System.out.println(a == b);
int k = 10;
System.out.println(i == k);
int kk = 128;
System.out.println(a == kk);
Integer m = new Integer(10);
Integer n = new Integer(10);
System.out.println(m == n);
System.out.println(m+1 == n+1);
Integer s = 126;
Integer d = 1;
int f = 127;
System.out.println(f == (s + d));
Integer r = 126;
Integer x = 1;
Integer g = 127;
System.out.println(g == (r + x));
}
}
下边这一段是反编译后的代码。
package base.test;
import java.io.PrintStream;
public class Test1
{
public static void main(String[] args)
{
Integer i = Integer.valueOf(10);
Integer j = Integer.valueOf(10);
System.out.println(i == j);
Integer a = Integer.valueOf(128);
Integer b = Integer.valueOf(128);
System.out.println(a == b);
int k = 10;
System.out.println(i.intValue() == k);
int kk = 128;
System.out.println(a.intValue() == kk);
Integer m = new Integer(10);
Integer n = new Integer(10);
System.out.println(m == n);
System.out.println(m.intValue() + 1 == n.intValue() + 1);
Integer s = Integer.valueOf(126);
Integer d = Integer.valueOf(1);
int f = 127;
System.out.println(f == s.intValue() + d.intValue());
Integer r = Integer.valueOf(126);
Integer x = Integer.valueOf(1);
Integer g = Integer.valueOf(127);
System.out.println(g.intValue() == r.intValue() + x.intValue());
}
}
从反编译的中可以看到两个方法。Integer.valueOf(int);装箱方法把基本数据类型int封装成Integer。Integer.intValue(int);拆箱方法把Integer拆箱成int基本数据类型。
以下是valueOf的源码,这个源码简单说如果装箱的int大于-128并且小于127就会从IntegerCache这个类的cache取出一个Integer对象。IntegerCache是Integer的一个内部类它通过static方法给数组cache赋值。也就是如果我们从valueOf中返回的Integer只要是在-128~127范围内的使用的都是cache数组中的缓存对象。
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer cache[];
static {
// high value may be configured by property
int h = 127;
String integerCacheHighPropValue =
sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
try {
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
} catch( NumberFormatException nfe) {
// If the property cannot be parsed into an int, ignore it.
}
}
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
// range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
}
private IntegerCache() {}
}
intValue(int)方法则直接返回该Integer对象对应的基本数据类型值。
public int intValue() {
return value;
}
下面我们挨个分析一段代码中的结果。
Integer i = 10;Integer j = 10;System.out.println(i == j);//true
两个基本数据类型10调用valueOf(int)升级成包装对象,10在cache范围内所有返回的是同一个对象。对象使用==判断的是堆内存地址所有为true。
Integer a = 128;Integer b = 128;System.out.println(a == b);//false
这个于上个的区别是128不在cache范围内,所以返回的是两个对象,两个对象的堆内存当然是不同的。
int k = 10;System.out.println(i == k);//true
当包装类型要和基本数据类型做运算包装类会拆箱为基本数据类型两个10是相等的。
int kk = 128;System.out.println(a == kk);//true
和上边一样,包装类型拆箱后就是基本数据类型128两个128是相等的。
Integer m = new Integer(10);Integer n = new Integer(10);
System.out.println(m == n);//false
因为两个都是new出来的没有使用valueOf(int)自然都是在堆空间中有自己的地盘,所以不是同一个对象。
System.out.println(m+1 == n+1);//true
//当包装类型要和具体的数字运算就要拆箱两个11是相等的。
Integer s = 126;Integer d = 1;int f = 127;System.out.println(f == (s + d));//true
两个基本数据类型装箱后是两个对象,但是做加法运算就要在拆箱,127和127是相等的。
Integer r = 126;Integer x = 1;Integer g = 127;System.out.println(g == (r + x));//true
其实是把126,1,127都装箱然后。然后r和x要运算所以拆箱,g要和他俩的结果做运算也要拆箱。