📢编程环境:idea
【java-语法】包装类
先回忆一下Java中的类是啥?
Java中的数据类型分为八大基本数据类型和一些引用数据类型。在Java中,当计算机一次要保存一个数据时,要用基本数据类型向内存申请空间。这一个数据可以是整型(例如10,100,5000等单个整数),浮点型(例如20.5,500.6等单个小数),字符(例如‘d’,‘O’,‘20’等单个字符),真值(true或false),对应的基本数据类型为整型(根据申请的空间从大到小依次有long,int,short,byte),浮点型(float和double),字符型(char),布尔型(boolean)。当计算机一次要保存一组数据时,要用引用数据类型向内存申请空间。这一组数据可以是n个数字(例如1,2,3,4,5),一个字符串(例如“1234bjhkK”),一个对象(例如一个人的姓名,年龄,星座,出生日期,职业)等,对应的引用数据类型为数组array,字符串String,类class等。
每个基本数据类型的变量空间里存的就是对应的每个数据,引用数据类型的变量空间里存的是对应那组数据的地址。
java是一门面向对象的编程语言。对象就是现实中的实体,面向对象就是依靠对象之间的交互解决问题。在Java语言中,一般通过创建一个类来描述现实中的一个对象,对象的产生依赖于类。
Object类是Java中所有类的父类。包装类是Object类的子类。
包装类是啥?
每个基本类型都有一个对应的包装类。
基本数据类型变量向内存申请一个空间,这个空间中就放着这个数据本身。而包装类是引用数据类型,引用类型变量向内存申请空间后,这个空间中放的是数据真正所在空间的地址。也就是:基本数据类型变量存数据,而包装类变量存数据地址,指向数据。
有时,需要把基本数据类型变量转换成引用数据类型变量,例如在有关泛型的代码中,只支持继承了Object类的引用数据类型,所以为了在泛型代码中可以支持基本数据类型,Java给每个基本数据类型都对应了一个包装类型。
要注意的是:包装类默认被final修饰,不能有子类。一旦把基本数据类型转换为包装类,就不能更改数据的值了!
基本数据类型 | 它的包装类 |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
char | Character |
boolean | Boolean |
除了 Integer 和 Character, 其余基本类型的包装类都是首字母大写。
装箱和拆箱
装箱就是把基本数据类型变量转化为包装类变量的过程,拆箱是把包装类变量转化为基本数据类型变量的过程。java中,装箱和拆箱的底层实现源码根据基本数据类型不同都会有所差异,这是由于每个基本数据类型所存数据的范围不同导致的。但是在开发使用层次上,把数据进行装箱和拆箱的指令都是统一的。接下来我们就来看看怎么把数据进行装箱和拆箱。
怎么装箱
装箱就是通过调用包装类的valueOf()方法,例如Integer.valueOf(),Double.valueOf()等
,把基本数据类型的数据转化为包装类的过程。
装箱是编译器认可的。编译器在生成类的字节码文件时,调用包装类.valueOf()等方法
完成装箱。java虚拟机只是执行这些字节码。
装箱有自动装箱和显示装箱两种。
- 自动装箱是编译器默认调用
数据的基本数据类型对应的包装类的valueOf()方法
。自动装箱只能把数据默认装箱为基本数据类型对应的包装类。例如把int类型的数据a自动装箱为包装类a,编译器默认调用Integer.valueOf()方法。
- 显示装箱是程序员在写装箱语句时,根据需求调用需要的包装类的valueOf()方法,把一个基本数据类型的数据装箱为需要的包装类。例如把整型a依次装箱为Integer类的a和Double类的a,编译器根据指令依次调用Integer.valueOf()方法和Double.valueOf()方法。
怎么拆箱
以Integer a = new Integer(10)
为例,其他包装类同理:
拆箱就是通过调用基本数据类型的Value()方法,例如Integer类的a拆箱为int类型,要调用a.intValue()方法
。把包装类的数据变成基本数据类型的过程。
拆箱和装箱一样,都是编译器认可的。编译器在生成类的字节码文件时,调用基本数据类型的Value()方法
完成拆箱,java虚拟机只是执行这些字节码。
拆箱有自动拆箱和显示拆箱两种。
-
例如把Integer类的a依次自动拆箱为整型数据a和浮点型数据a。此时编译器都是默认调用
a.intValue()方法
。- 但把对象a自动拆箱为float类型的数据时,编译器先调用
a.intValue()方法
把对象a拆箱为int类型的数据后,会再把int类型的a(自动)强制类型转换为float类型的数据a。
- 但把对象a自动拆箱为float类型的数据时,编译器先调用
-
显示拆箱是写拆箱语句的时后,根据需求调用需要的基本数据类型的Value()方法,把包装类对象拆箱为所需要的基本数据类型的数据。例如把对象a依次显示拆箱为整型数据a和浮点型数据a,编译器根据指令依次调用a.intValue()方法和a.doubleValue()方法。
一道来自阿里的面试题
问:把a,b自动装箱,然后比较a,b两个对象,输出结果。把a1,b1自动装箱,比较a1,b1两个对象,输出结果。分析为什么a==b的结果为true?为什么a1==b1的结果为false?
解:
我们知道:基本数据类型的变量空间里存的是数据的值,引用数据类型的变量空间里存的是数据的地址,包装类是引用数据类型。
在题目中,a,b,a1和b1都是四个Integer包装类,在java中,int类型的a,b,a1和b1和Integer类型的a,b,a1和b1是不同的。int类型的四个变量a,b,a1和b1,内存空间里分别存的就是a值,b值,a1值和b1值。而他们装箱后,Integer类型的四个变量a,b,a1和b1,内存空间里存的分别是a值的地址,b值的地址,a1值的地址和b1值的地址。
所以为什么a ==b的结果为true? 为什么a1 ==b1的结果为false?
因为变量a和变量装箱后指向同一个空间,存了相同的地址,而变量a1和变量b1装箱后指向不同的空间,存的是不同的地址。
答案更多详情见文章:【java-读装箱源码,解阿里面试题】包装类