Java基础_自动拆装箱你了解多少?

前言

​ 自动拆装箱听起来挺高级的,其实就是基本数据类型和对应包装类型的相互装换的过程。说白了就是为了提高效率、简化开发;至于怎么提高效率,开发过程中有哪些点需要注意的,面试又常问哪些点;我们继续往后看。

基本数据类型和包装类型对应关系

​ 我们知道Java有8种基本数据类型,他们对应的包装类型都是怎么样的呢?下面用一个表格总结一下:

基本数据类型包装类
byteByte
booleanBoolean
shortShort
charCharacter
intInteger
longLong
floatFloat
doubleDouble

在这八个类名中,除了Integer和Character类以后,其它六个类的类名和基本数据类型一致,只是类名的第一个字母大写即可。

为什么要搞一个包装类?

​ 因为Java是一种面向对象语言,很多地方都需要使用对象而不是基本数据类型。比如,在集合类中,我们是无法将int 、double等类型放进去的。因为集合的容器要求元素是Object类型(对象)。

​ 所以为了让基本类型也具有对象的特征,就出现了包装类型,它相当于将基本类型“包装起来”,使得它具有了对象的性质,并且为其添加了属性和方法,丰富了基本类型的操作。

自动装箱与自动拆箱

  1. 装箱:基本数据类型装换为包装类型:称之为装箱(可以理解为对基本类型包装了一下,使之具有对象的性质);
  2. 拆箱:包装类型装为基本类型:称之为拆箱;

​ 那么自动拆箱和自动装箱,就是为了减少开发人员的工作,Java提供了自动拆箱与自动装箱功能。话不多说,直接上代码:

public static  void main(String[]args){
   Integer i = 200;  //自动装箱  就等同于:Integer i = new Integer(10);不用我们开发人员再new一次
   int b = i;       //自动拆箱  又转为了基本数据类型了
}

自动装箱与自动拆箱底层如何实现的呢?

我们直接上上面代码反编译后的代码:

public static void main(String[]args){
    Integer i = Integer.valueOf(10);   
    int b = i.intValue(); 
}

总结如下:

  1. 自动装箱:调的对应包装类型的:valueOf()方法;
  2. 自动拆箱:调的XXValue()方法;

自动拆装箱的实际应用场景有哪些呢?

场景一:包装类型和基本类型的大小比较时

当我们对Integer对象与基本类型进行大小比较的时候,实际上比较的是什么内容呢?看以下代码:

Integer a = 1;
System.out.println(a==1?"等于":"不等于"); //这里一比,实际上会将a自动拆箱再来比较

Boolean bool=false;
System.out.println(bool?"真":"假");     //这里一比,实际上会将bool自动拆箱再来比较

上反编译的代码:

Integer a=1;
System.out.println(a.intValue()==1?"等于":"不等于");  //和上面说的一致,调XXValue()进行拆箱
Boolean bool=false;
System.out.println(bool.booleanValue?"真":"假");    //和上面说的一致,调XXValue()进行拆箱
场景二:往集合里面赋值时
List<Integer> li = new ArrayList<>();
for (int i = 1; i < 50; i ++){
    //这里为什么不会报错呢?不是说只能存对象吗?因为自动装箱了:反编译后就是这样的:li.add(Integer.valueOf(i));
    li.add(i);
}

以上,结论就是:当我们把基本数据类型放入集合类中的时候,会进行自动装箱

场景三:作为方法返回值的时候
//自动拆箱
public int getNum1(Integer num) {
 return num;
}
//自动装箱
public Integer getNum2(int num) {
 return num;
}
场景四:参与运算的时候
//自动装箱
Integer i = 10;
Integer j = 20;
//自动拆箱为基本数据类型,再比较
System.out.println(i+j);

反编译后:

Integer i = Integer.valueOf(10);
Integer j = Integer.valueOf(20);
System.out.println(i.intValue() + j.intValue());
场景五:三目运算符

直接上经典案例:

boolean flag = true;
Integer i = 0;
int j = 1;
int k = flag ? i : j;

简单理解就是:如果flag为true则返回i 否则返回j;那么问题来了,假如这样写呢?

 boolean flag = true;
//可以理解为调后台逻辑查询一个数值,可能为null,所以我们直接测试null的场景
//Integer i = getMoney();
Integer i = null;
int j = 1;
int k = flag ? i : j;    

乍一看也没啥,最后返回不也是null吗?实际上最后一行三目运算时,i会自动拆箱为基本数据类型:反编译后

int k = flag ? i.intValue() : j;

那么就会出大问题,i为null,就会报空指针异常了;自动拆箱导致空指针异常

自动拆装箱与缓存

  1. 我们先看一个场景:

    public static void main(String[] args) {
            Integer a1 = 10;
            Integer a2 = 10;
            //true
            System.out.println(a1==a2);
    
            Integer b1 = 200;
            Integer b2 = 200;
            //false
            System.out.println(b1==b2);
        }
    
  2. 为什么会这样呢?我们常规理解:==比地址,他们都赋值给了两个不同的对象,为什么一个相等,一个不相等呢?

  3. 我们引入阿里编码规范提示的一段话来解释即可:

    image-20220324104555333

    简单的说:为了提高效率:-128-127被定义成了一个数组,被放到缓存中;因为这256个数经常使用,为了避免重复创建;

    为什么double不维护这样一个数据? 。。。范围太大,无法维护

  4. 这里要注意一个点:我们知道自动装箱就是:调用valueOf方法;他和new Integer()是有区别的:

    • valueOf()会从缓存池里取出已有对象;
    • new Integer()每次都是创建一个新对象;

    上代码就知道了:

    public static void main(String[] args) {
            Integer a1 = 10;
            Integer a2 = 10;
            Integer integer1 = new Integer(10);
            Integer integer2 = new Integer(10);
    
            //true 底层a1 a2 都是调用的valueOf,优先从缓存池拿,所以是相等的
            System.out.println(a1==a2);
            //false !!! new Integer每次都是新创建一个对象
            System.out.println(integer1==integer2);
        }
    

开发注意事项

  1. 包装对象的数值比较,不能简单的使用==,虽然-128到127之间的数字可以,但是这个范围之外还是需要使用equals比较。而且阿里编码规范插件也提示:包装类型比较要使用equals;
  2. 三目运算的时候要注意:是否自动拆箱导致空指针异常;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值