装箱与拆箱
JAVA中的自动装箱指的是把基本类型的值转换为对应的包装类对象,自动拆箱则相反。如下代码所示:
Integer i1=100;
int i2=i1;
- 分析如下:
- Integer i1=100实现了
自动装箱,底层调用了调用包装类的valueOf方法,也就是Integer.valueOf(100)。 - int i2=i1实现了
自动拆箱,底层调用包装类的intValue方法。
需要注意的是:自动装箱拆箱是 编译器 帮我们自动转换的,我们不需要手工调用valueOf()和intValue()方法。
Integer的缓存 -128~127
- 自动装箱时的缓存问题:
先看一个问题,对于下面定义的四个变量进行==比较:
Integer a=1;
Integer b=1;
Integer c=200;
Integer d=200;
System.out.println(a==b);//true
System.out.println(c==d);//false
我们都知道“= =”在JAVA里面是比较对象引用的,如果两个对象引用指向堆中的同一块内存就返回true,否则返回false。根据自动装箱规则我们知道Integer a = 1 等价于 Integer a = Integer.valueOf(1);,但是在valueOf方法上,查看源码:
public static Integer valueOf(int i) {
final int offset = 128;
if (i >= -128 && i <= 127) { // must cache
return IntegerCache.cache[i + offset];
}
return new Integer(i);
}
Integer.valueOf()中有个内部类IntegerCache(类似于一个常量数组,也叫对象池),它维护了一个Integer数组cache,长度为(128+127+1)=256。Integer类中还有一个Static Block(静态块)
static {
for(int i = 0; i < cache.length; i++)
cache[i] = new Integer(i - 128);
}
从这个静态块可以看出,Integer已经默认创建了数值[-128,-127]的Integer缓存数据。所以使用Integer a=1时,JVM会直接在该在对象池找到该值的引用。也就是说这种方式声明一个Integer对象时,JVM首先会在Integer对象的缓存池中查找有木有值为1的对象,如果有直接返回该对象的引用;如果没有,则使用New Integer创建一个对象,并返回该对象的引用地址。因为Java中==比较的是两个对象是否是同一个引用(即比较内存地址),a和b都是引用的同一个对象,所以a= =b结果为true;c和d已经超出了缓存的范围,所以重新生成了Integer对象,所以c==d结果为false。
int和Integer的比较== equals()
- 示例代码:
class BoxIntInteger {
public static void main(String[] args) {
Integer a = new Integer(10111);
int b = 10111;
boolean equal1 = a == b;
boolean equal2 = a.equals(b);
System.out.println(equal1);
System.out.println(equal2);
}
}
运行结果:
true
true
- 反编译字节码:
public static void main(String args[])
{
Integer a = new Integer(10111);
int b = 10111;
boolean equal1 = a.intValue() == b;
boolean equal2 = a.equals(Integer.valueOf(b));
System.out.println(equal1);
System.out.println(equal2);
}
- 由实例代码和反编译代码可以看出:
-
可以看出对于Integer与int使用 = = 比较大小的话,优先Integer拆箱。
-
如果使用equals比较大小的话,则int装箱。
提示:对于Integer与int之间大小比较优先使用equals比较,否则容易出现空指针,例如:
Integer c= null;
System.out.println(c==1);
原因:由于Integer需要调用intValue进行拆箱,因而空指针。
Integer与Integer必须使用equals方法比较,这个就不必解释了。但是通常我们可以看先Integer与Integer之间使用==也可以正确比较,原因是:Integer对于-128到127之间的数字在缓存中拿,不是创建新对象。
为什么要用到包装类型?
- 把一个基本类型包装成一个类,
可以使这个类型具有很多可以调用的方法。 - 包装类型
使得Java向面向对象语言的靠近。其实Java还不算是很纯的面向对象的语言。真正的面向对象,是没有基本数据类型的。它只有一种类型,就是对象。 - 在泛型中,
基本类型是不可以做泛型参数的。如:List < int> list = new ArrayList< int> ();这是不合法的。你只能这个样写List< Integer> list = new ArrayList< Integer> ();也就是要用int型的包装类类型来解决基本类型不可以做泛型参数的问题 。
本文详细解析了Java中的自动装箱与拆箱过程,探讨了Integer缓存机制,尤其是在-128至127范围内如何提高效率。通过示例代码展示了int与Integer比较时的不同行为,强调了equals方法的重要性。
322

被折叠的 条评论
为什么被折叠?



