Integer和int相比较
一、 Integer类
在Java中,”万物皆对象“,但是八种基本数据类型是个例外,出于性能等方面的考虑,八种基本数据类型没有类和对象的概念,相应的变量值直接在栈内存中存放。但这带来了一些问题,特别是对于集合类的使用,使用集合类时要求泛型必须是类类型,因此,引入了Integer类。Integer是Java中的一个封装类,用于表示整数。它是int的封装类,可以将int类型的数据转换为Integer类型的数据。
有以下三种方法实例化Integer对象:
1.1 构造函数
new Integer(int value)
构造函数,用于实例化一个Integer类的对象。与普通类通过new实例化对象的过程相同,声明的对象引用存放在栈中,该对象引用指向堆中的某块内存区域,该内存区域存放new出的具体数据。比如执行完语句Integer i1 = new Integer(123);
后,栈以及堆中的内存将按以下方式分配:
注意:
从Java9之后,该构造函数已经被废弃,因此对于Java9及其之后的版本不能再使用构造函数实例化Integer对象。
1.2 静态方法
Integer.valueOf(int i)
静态方法,返回指定值的Integer对象,推荐使用该方法实例化Integer对象。下面是该方法的具体实现:
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
IntegerCache.cache是一个用于存放Integer对象的数组,该数组用于缓存区间[IntegerCache.low, IntegerCache.high]内的整数。当通过静态方法valueOf(i)
实例化Integer对象时:
- 若 i∈[IntegerCache.low, IntegerCache.high],直接从数组IntegerCache.cache中取对象以节省内存空间(这也是推荐使用该方法实例化Integer对象的重要原因)
- 若 i∉[IntegerCache.low, IntegerCache.high],通过构造函数实例化一个新的对象
- [IntegerCache.low, IntegerCache.high]的默认值为**[-128, 127]**
- IntegerCache.high的值可以通过 -XX:AutoBoxCacheMax 设置,IntegerCache.high = max(127, -XX:AutoBoxCacheMax)
比如:
public class Main {
public static void main(String[] args) {
Integer i1 = Integer.valueOf(127);
Integer i2 = Integer.valueOf(127);
Integer i3 = Integer.valueOf(130);
Integer i4 = Integer.valueOf(130);
}
}
对于上面这段代码,栈以及堆中的内存将按以下方式分配:
1.3 直接赋值
Integer i1 = 127;
这种方法适用于JDK 1.5及以后的版本,JDK 1.5增加了自动装箱、拆箱的功能,JVM可以完成基本类型和它们对应的包装类之间的自动转换(但并不意味着可以通过基本类型调用它们的包装类才具有的方法),上述代码等价于:
Integer i1 = Integer.valueOf(127);
二、 Integer对象之间的比较
对象之间的比较有两种方式:
-
== :比较两个对象指向的内存区域是否一致
-
equals():Integer对equals()方法进行了重写,比较对象的整数值是否相等
// Integer 类对 equals 方法进行了重写 public boolean equals(Object obj) { if (obj instanceof Integer) { return value == ((Integer)obj).intValue(); } return false; }
对于下面代码:
public class Main {
public static void main(String[] args) {
Integer i1 = Integer.valueOf(127);
Integer i2 = Integer.valueOf(127);
Integer i3 = 127; // 等价于 Integer.valueOf(127);
System.out.println(i1 == i2); // true
System.out.println(i1 == i3); // true
System.out.println(i1.equals(i2)); // true
Integer i4 = Integer.valueOf(130);
Integer i5 = Integer.valueOf(130);
Integer i6 = 130; // 等价于 Integer.valueOf(130);
System.out.println(i4 == i5); // false
System.out.println(i4 == i6); // false
System.out.println(i4.equals(i5)); // true
Integer i7 = new Integer(1); // 只适用于JDK8及之前的版本
Integer i8 = new Integer(1);
System.out.println(i7 == i8); // false
System.out.println(i7.equals(i8)); // true
}
}
栈以及堆中的内存将按以下方式分配:
- i1、i2、i3都是通过静态方法Integer.valueOf得到的Integer对象,由于值127在区间[-128, 127]内,所以得到的都是同一个存放在IntegerCache.cache数组中的对象,即i1、i2、i3指向的内存区域相同,因此相互使用’=='比较时结果为true。而’equals()'比较的是存放在对象中的整数,因此相互使用’equals()'比较时结果为true。
- i4、i5、i6也都是通过静态方法Integer.valueOf得到的Integer对象,但值130不在区间[-128, 127]内,所以得到的都是分别通过构造函数new出的对象,即i4、i5、i6指向的内存区域不同,因此相互使用’=='比较时结果为false。而’equals()'比较的是存放在对象中的整数,因此相互使用’equals()'比较时结果为true。
- i7、i8都是通过构造函数new出的Integer对象,即i7、i8指向的内存区域不同,因此相互使用’=='比较时结果为false。而’equals()'比较的是存放在对象中的整数,因此相互使用’equals()'比较时结果为true。
三、 Integer对象和整型变量之间的比较
- 当使用 == 比较时。无论是通过何种方式实例化的,Integer对象都会自动拆箱为基本类型,然后再去与整型变量比较。因此,Integer对象和整型变量之间的比较就相当于整数值之间的比较,只要整数值相同结果即为true。
- 当Integer对象使用equals()方法与整型变量比较时。整型变量会自动装箱成Integer对象,然后通过equals()方法比较对象所存的整数值是否相同。
- 综上,无论使用哪种方式,Integer对象和整型变量之间的比较都是Integer对象所存的整数值和整型变量之间的比较。
比如:
public class Main {
public static void main(String[] args) {
int i1 = 127;
Integer i2 = 127;
Integer i3 = Integer.valueOf(127);
Integer i4 = new Integer(127); // 只适用于JDK8及之前的版本
System.out.println(i1 == i2); // true
System.out.println(i1 == i3); // true
System.out.println(i1 == i4); // true
System.out.println(i2.equals(i1)); // true
int i5 = 130;
Integer i6 = 130;
Integer i7 = Integer.valueOf(130);
Integer i8 = new Integer(130); // 只适用于JDK8及之前的版本
System.out.println(i5 == i6); // true
System.out.println(i5== i7); // true
System.out.println(i5 == i8); // true
System.out.println(i6.equals(i5)); // true
}
}
注:
各包装类缓存值范围(默认) :
- boolean:true、false
- byte:-128~127
- char:0~127
- short:-128~127
- int:-128~127
- long:-128~127
- float和double:无缓存