一、什么是自动装箱和自动拆箱?
自动装箱:
- Java自动将基本数据类型封装为对象类型。
- 基本数据类型可以直接赋值给对应的包装类变量。如:
Integer i = 100;
- 本质上是,编译器执行了
Integer i = Integer.valueOf(100);
自动拆箱:
- Java自动将包装类对象转化为基本数据类型
- 包装类对象可以直接赋值给基本类型变量,如:
int a = new Integer(100);
- 本质上是,编译器编译时为我们添加了:
int a = new Integer(100).intValue();
public class Main {
public static void main(String[] args) {
//自动装箱
Integer x = 100;
/*
执行上面代码的时候,系统为我们执行了:
Integer total = Integer.valueOf(100);
*/
//自定拆箱
Integer integer = new Integer(200);
int a = integer;
/*
执行上面那句代码的时候,系统为我们执行了:
int a = y.intValue();
*/
}
}
包装类
由上面可知,直接将八大基本类型的变量表示为对应的类,称为包装类。
二、为什么需要有包装类?
1. Java中万物皆对象,但八大基本数据类型却不是对象。
为了使基本数据类型的变量具有对象的特征,引入包装类。
假设去如下的表中去查询王五的年龄。但是还未录入。如果是int类型的话默认值是0,看起来就有点奇怪,如果是Integer类型的话就为null,表示未录入。
2.为了支持泛型(还有集合)
public static void main(String[] args) {
List<> list1 = new ArrayList<Integer>();//泛型必须是对象类型
List<> list2 = new ArrayList<int>();//报错
}
3.可以提供了丰富的属性和API
public static void main(String[] args) {
System.out.println(Integer.MAX_VALUE);//打印int类型能表示的最大值。输出:2147483647
System.out.println(Integer.MIN_VALUE);//打印int类型能表示的最小值。输出:-2147483648
System.out.println(Integer.max(111,222));//找出传入的最大值。输出:222
System.out.println(Integer.min(111,222));//找出传入的最小值。输出:111
System.out.println(Integer.sum(111,222));//求和。输出:333
System.out.println(Integer.valueOf("123"));//将字符串转换为Integer类型 输出:123
System.out.println(Integer.compare(111,222));//比较大小,第一个参数小于第二个,返回-1。输出:-1
}
三、包装类的缓存问题
什么是包装类的缓存
当通过自动装箱机制创建包装类对象时,首先会判断数值是否在-128—— 127的范围内,如果满足条件,则会从缓存(常量池)中寻找指定数值,若找到缓存,则不会新建对象,只是指向指定数值对应的包装类对象,否则,新建对象。
public static void main(String[] args) {
Integer i1 = 100;
Integer i2 = 100;
Integer i3 = 200;
Integer i4 = 200;
System.out.println(i1==i2); //true
System.out.println(i3==i4); //false
}
使用缓存机制的原因
缓存的这些对象都是经常使用到的(如字符、-128至127之间的数字),避免重复创建同一对象,节省空间开销和时间消耗,提升了性能。而double、float是浮点型的,没有特别的热的(经常使用到的)数据的,缓存效果没有其它几种类型使用效率高。
各个包装类缓存值范围
- boolean:true/false
- char:0~127
- byte:-128~127
- short:-128~127
- int:-128~127
- long:-128~127
特别注意:float和double没有缓存。
public class Main {
public static void main(String[] args) {
Double i1 = 100.0;
Double i2 = 100.0;
Double i3 = 200.0;
Double i4 = 200.0;
System.out.println(i1==i2); //false
System.out.println(i3==i4); //false
}
}
补充:
- 当包装类与基本类型进行“==”运行时,包装类会进行拆箱,拆箱结果与基本类型对比值是否相等;
Integer num1 = 400;
int num2 = 400;
System.out.println(num1 == num2); //true
- 两个包装类进行“==”运行时,对比的是两个对象的地址,也即判断是否两个引用是否指向同一个对象。
Integer x = 200;
Integer y = 200;
System.out.println(x==y);//false