包装类_自动装箱和拆箱_缓存源码分析
自动装箱和拆箱就是将基本数据类型和包装类之间进行自动的相互切换。JDK1.5之后,Java引入了自动装箱和自动装拆箱。
1.自动装箱
基本数据类型处于需要对象的环境中,会自动转换为对象,
我们Integer为例:在JDK1.5以前,这样的代码Integeri=5是错误的,必须透过integer I= new Integer(5)这样的语句来实现基本数据类型转换成包装类的过程,而在JDK1.5以后, Java提供了自动装箱的功能,因此只需Integer i= 5这样的语句就能实现基本数据类型转换成包装类,这是因为JVM为我们执行了Integer i = Integer.valueOf(5)这样的操作,这就是Java的自动装箱。
2.自动拆箱
每当需要一个值时,对象会自动转成基本数据类型,没必要再去显式调用intValue().doubleValue()等转型方法。如Integeris 5;intj m i:这样的过程就是自动拆箱。自动装箱过程就是通过Java类的valueOf()方法实现的,而自动装箱过程是通过调用包装类的xxxvalue()方法实现的(xxx代表对应的基本数据类型,如intValue(),doubleValue()等)。自动装箱与拆箱事实上是有编译器来帮的忙。编译器在编译时根据我们所编写的语法,决定是否进行拆箱和装箱的操作。
3.实例:
自动装箱:
Integer i = 100; // 自动装箱
// 相当于编译器自动做以下语法编译
Integer i = Integer.valueOf(100); // 调用的是valueOf(100),而不是new Integer(100)
自动拆箱:
Integer i = 100;
int j = i; // 自动装箱
// 相当于编译器自动做以下语法编译
int j = i.intValue();
所以自动装箱和自动拆箱是自动操作的“便民服务”,这个功能虽然很方便,但在程序运行阶段还是的了解以下Java的语义。
4.包装类空指针异常:
public class Test{
public static void main(String []args){
Integer i = null; // 装箱操作,编译器将自动转为Integer i =Integer.valueOf(null);
int j = i; // 拆箱操作,编译器会int j = i.value();
}
}
//会报错,空指针异常
//解决空指针异常
public class Test{
public static void main(String []args){
Integer i = null;
if(i != null){
int j = i;
}
}
}
5.缓存源码分析
public class Test{
public static void main(String []args){
//缓存[-128,127]之间的数字
Integer in1 = Integer.valueOf(-128);
Integer in2 = -128;
System.out.println(in1 == in2);//true因为123在缓存范围内
System.out.println(in1.equals(in2));//true
System.out.println("-------------------------------");
Integer in3 = 1234;
Integer in4 = 1234;
System.out.println(in3 == in4);//false因为123不在缓存范围内
System.out.println(in3.equals(in4));//true
}
}
我们可以打开valueOf源码查看,
缓存[-128,127]之间的数字,实际上就是系统初始的时候,创建了一个[-129,127],当我们调用valueOf的时候,首先检查是否在[-129,127]之间,如果在这个范围,则直接从缓存数组中拿出已经建好的对象,如果不在则创建新的Intefer对象。