Java中int跟Integer的区别

时间:2022-09-03 16:56:58

在了解int跟Integer的区别与联系之前需要先了解Java的自动装箱跟拆箱机制,可以看我的另一篇文章Java中自动装箱与拆箱详解

Integer是int的包装类。Java为每一种基本数据类型都配备了相应的包装类,如下表所示:

基本数据类型 byte short int long float double char boolean
对应的包装类 Byte Short Integer Long Float Double Character Boolean

我们通过一个示例来看一下二者之间的区别:

public class IntAutoUnboxing {
public static void main(String[] args) {
int i = 13;

Integer iObject1 = 13;
Integer iObject2 = 13;

Integer iObject3 = 129;
Integer iObject4 = 129;

Integer iObject5 = new Integer(13);
Integer iObject6 = new Integer(129);

System.out.println(iObject1 == i);//1.输出为true

System.out.println(iObject1 == iObject2);//2.输出为true

System.out.println(iObject3 == iObject4);//3.输出为false

System.out.println(iObject1 == iObject5);//4.输出为false

System.out.println(iObject3 == iObject6);//5.输出为false
}

对上面的输出结果,我们进行逐个分析:
1.基本数据“==”是比较数值大小是否相等;引用类型“==”是比较是否指向同一个引用。
在输出语句1中,iObject1跟i进行比较,输出结果为true。当Integer类型跟int类型比较时,其中包含的过程是Integer类型首先会自动拆箱成int类型的数值,然后再进行数值大小的比较。iObject1首先自动拆箱成int类型的数值13,然后跟i进行比较,二者数值相同,所以输出为true。

2.都是对两个Integer类型的比较,为什么输出语句2输出为true,而输出语句3却输出为false?这还得从Integer的源码进行解释:
Integer iObject1=13这个赋值过程中包含了自动装箱:将int类型的13自动装箱成了Integer类型的13。Integer iObject1=13实质上是Integer iObject1=Integer.valueOf(13),编译器帮我们自动调用了valueOf()这个方法,所以需要从valueOf()这个方法的源码入手,看一下它的源码:

   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() {}
}

两段源码简单解释就是:如果Integer赋值字面量的值在-128到127之间,那么不会new新的Integer对象,而是直接引用常量池中的Integer对象,如果不在这个范围内,则每次赋值都会产生一个新的Integer对象。
输出语句2中Integer的值都是13,13在-128到127这个范围内,iObject3跟iObject4会指向常量池中同一个对象,所以输出为true。而输出语句3中Integer的值都是129,已经超出了-128到127这个范围,因此会创建两个Integer对象,两个独立的对象肯定不会指向同一个引用,所以输出为flase。

3.iObject1跟iObject5都是13,在-128到127这个范围内,为什么输出为false?原因很简单,因为iObject5使用了关键字new创建了一个新的对象,iObject1是常量池中的Integer对象,iObject5是使用关键字new新创建的对象,两个对象相互独立,肯定不会指向同一个引用,因此输出为false 。

以上1、2、3点就是int跟Integer的区别跟联系。