看完这篇文章,相信你一定可以很好的理解包装器类以及有些包装器类的自带缓存机制,也可以反手就给面试官说出为什么,下面代码的输出值为true:
Integer a = 127;
Integer b = 127;
System.out.println(a==b);
//打印结果为true
Java是一门面向对象语言,万物皆可对象,当然基本数据类型也不能例外,所有的基本数据类型都有一个与之对应的类,这些类被称为基本数据类型的包装器类。
基本数据类型 | 包装器类 |
---|---|
short | Short |
int | Integer |
long | Long |
byte | Byte |
float | Float |
double | Double |
char | Character |
boolean | Boolean |
这些包装器类都如同String类一样都是不可变的,查看源码也都能发现都是被final关键字修饰的,当然也是不能继承的。
对应标题,这里我们拿Integer举例,查看下面两行代码:
Integer a = 1; //自动装箱
int b = new Integer(2); //自动拆箱
通过查看其字节码,我们可以发现,自动装箱会调用Valueof()方法,自动拆箱会调用intValue()方法。
缓存可以节省内存、提高速度,Java的许多包装器类都提供了缓存机制,以便在自动装箱过程中,可以直接取出预先缓存的对象,提高效率。
以Integer为例,分析其Valueof源码:
我们再来看一下IntegerCache这个内部类,注意红箭头指向的那段注释,大意为最高值high是可配置的:
总结: 当我们使用自动拆箱来获取Integer类时,如果在[-128,high]范围内,则将返回缓存对象,这里的high默认为127,但是是可配置的。
因此包装类比较时比较的同样是地址,如果在缓存范围内,则为同一对象(相等),否则为不同对象(不相等)。
代码一:
public static void main(String[] args) {
Integer a = 127;
Integer b = 127;
Integer c = 128;
Integer d = 128;
System.out.println(a==b);
System.out.println(c==d);
}
输出结果:
代码二:
public static void main(String[] args) {
Integer a = 127;
Integer b = 127;
Integer c = new Integer(127);
Integer d = new Integer(127);
System.out.println(a==b);
System.out.println(c==d);
}
输出结果:
总结:
因为a,b是使用自动装箱来完成创建的,并且在默认缓存范围[-128,127],则a和b都是指向缓存的同一个对象,所以“==”比较结果为:true
在代码一中,c和d的值为128,也都是使用自动装箱来完成创建的,但是超过了默认缓存范围[-128,127],则调用new方法创建不同的对象,“==”比较结果为:false 在代码二中,c和d的值为127,虽然在默认缓存范围[-128,127]中,但是是通过new方法创建的不同对象,所以为不同对象,“==”比较结果为:false