Integer 和 int 有什么区别
首先要明白 Integer 是包装类型, int 是基础类型。
拿 Integer 来说其实就是在 int 外面又包装了一下,继承自 Number 接口
public final class Integer extends Number implements Comparable
包装类型和基础类型的区别
- 基础类型直接用=号赋值,包装类型用new关键字创建。
- 基本类型是直接将变量值存储在堆栈中,而包装类型是将对象放在堆中,然后通过引用来使用。
- 基本类型的初始值如int为0,boolean为false,而包装类型的初始值为null。
自动装箱拆箱
Integer a1 = 1;int a = a1;
上面第一行代码会触发装箱的动作,jvm会转换成
Integer a1 = Integer.valueOf(1); 第二行代码会触发拆箱的动作,jvm会转换成 int a = a1.intValue();equals
那么看下面的例子
Integer a1 = 1;int a = 1;Integer b = 1;Integer b1 = 4;Long a2 = 3l;System.out.println("b == a -> " + (b == a));System.out.println("b.equals(a) -> " + (b.equals(a)));System.out.println("b1 == (a + a1) -> " + (b1 == (a + a1)));System.out.println("b1.equals(a + a1) -> " + (b1.equals(a + a1)));System.out.println("b1.equals(a + a2) -> " + (b1.equals(a + a2)));//输出b == a -> trueb.equals(a) -> trueb1 == (a + a1) -> trueb1.equals(a + a1) -> trueb1.equals(a + a2) -> false
上面的前面4个结果都返回 true, 也就是说 当一个基础数据类型与封装类进行==、+、-、*、/运算时,会将封装类进行拆箱,对基础数据类型进行运算。
最后一个返回 false,看下 equals 源代码public boolean equals(Object obj) { if (obj instanceof Integer) { return value == ((Integer)obj).intValue(); } return false;}
通过源代码可以看到是类型不匹配,类型匹配的时候直接用的是 intValue 比较。
valueOf
Integer d1 = 200;Integer d2 = 200;Integer d3 = 100;Integer d4 = 100;System.out.println("d1 == d2 -> " + (d1 == d2));System.out.println("d1.equals(d2) ->" + (d1.equals(d2)));System.out.println("d3 == d4 -> " + (d3 == d4));System.out.println("d3.equals(d4) -> " + (d3.equals(d4)));//输出d1 == d2 -> falsed1.equals(d2) ->trued3 == d4 -> trued3.equals(d4) -> true
d1 == d2 返回false,这是因为包装类常量池的存在
public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i);}// IntegerCache 为 Integer 类中的静态内部类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() {}}
当传入的int值在 IntegerCache.low 和 IntegerCache.high 之间,就在 IntegerCache.cache 数据里面取一个。在 IntegerCache 类中可以看到 IntegerCache.low 的值为 -128,IntegerCache.high 的值为 127,IntegerCache.cache 就是预先初始化的一个数组,当传入的值在 -128 到 127 之间的时候直接从数组取值,否则的话就要 new Integer()
所以,当 d3 == d4 的时候返回的都是同一个对象,结果相等, 当 d1 == d4 的时候,则是返回2个不同的对象(因为值大于128,创建了2个不同的对象),结果必然是不等的。Double.valueOf
Double c1 = 100.0;Double c2 = 100.0;Double c3 = 200.0;Double c4 = 200.0;System.out.println("c1 == c2 -> " + (c1 == c2));System.out.println("c1.equals(c2) ->" + (c1.equals(c2)));System.out.println("c3 == c4 -> " + (c3 == c4));System.out.println("c3.equals(c4) -> " + (c3.equals(c4)));//输出c1 == c2 -> falsec1.equals(c2) ->truec3 == c4 -> falsec3.equals(c4) -> true
当类型是 Double 的时候就没有这个常量池了,因为没有一个确定数量的值。
Integer ==
Integer f = new Integer(100);Integer g = new Integer(100);System.out.println(f == g);//输出false
基本类型100通过包装类Integer包装后生产一个Integer对象的引用 f,而 == 使用来判断两个操作数是否有相等关系。如果是基本类型就直接判断其值是否相等。若是对象就判断是否是同一个对象的引用,显然我们new了两个不同的对象。