什么是包装类型
将基本类型包装进了对象中得到的类型
基本类型和包装类型有什么区别
- 用途不同:基本类型一般用于局部变量,包装类型用于其他地方
- 存储方式不同:用于局部变量的基本类型存在虚拟机栈中的局部变量表中,用于成员变量的基本类型存在虚拟机堆中;包装类型一般都存在堆中(没有进行JIT优化时)
- 占用空间大小不同:基本类型占空间小,包装类型占空间大
- 默认值不同:基本类型有默认值,包装类型不赋值就是null
- 比较方式不同:基本数据类型用==比较的是值,包装类型用==比较的是地址,而包装类型比较值的话需要用equals
为什么要有包装类型
笼统来说:Java是面向对象语言,所以应该尽可能使用对象
具体来说:
- 包装类型可以用于泛型,因为其继承于Object
- 包装类型没有默认值,这是业务场景需要的,许多业务场景要求对象的属性在不赋值的情况下是null而不是具有迷惑性的默认值
什么是自动拆装箱,本质是什么?
定义:当把一个包装类型赋值给基本类型时,编译器自动取出包装类型其中的基本数据进行赋值;当把一个基本类型赋值给一个包装类型时,编译器自动将其包装成包装类型后再赋值
本质:本质体现在字节码上,其实是调用了valueof和value方法,是编译器提供的语法糖
自动拆箱引发的NPE问题
场景1:
数据库查询可能返回一个null,是包装类型,这时用基本类型接收就会发生自动拆箱,调用不存在的valueOf方法从而引发NPE(空指针异常)
场景2:
三目运算符的类型对齐可能导致自动拆箱从而引发NPE问题
包装类型的常量池技术,及其作用
定义:对包装类型提前创建并缓存了一部分的对象在常量池中
作用:程序可能直接拿这些对象来使用,不需要再new对象了,节省了new对象的开销
补充:
Integer i = 3;
i++;
字节码为
0行:iconst_3定义了一个int类型的3
1行:调用valueOf方法装箱,取得包装类型常量池中值为3的那个Integer对象
8行:使用intValue拆箱
11行:创建int类型的1
12行:让int类型的3和int类型的1相加
13行:调用valueOf方法装箱,取得包装类型常量池中值为4的那个Integer对象