zoukankan      html  css  js  c++  java
  • 自动拆装箱

    前言

    我们知道Java共有8种基本数据类型int、byte、short、long、float、double、char、boolean,对应的包装类分别为Integer、Byte、Short、Long、Float、Double、Character、Boolean。既然有了基本数据类型,那么为什么还需要包装类呢。主要因为Java是一种面向对象的语言,很多地方需要使用对象而不是基本数据类型。比如在集合类中,我们无法将int、double等类型放进去,因为集合的容器要求元素是Object类型。为了让基本数据类型也具有对象的特征,就出现了包装类型,相当于将基本数据类型"包装起来",使得基本数据类型具有对象的性质,并且为其添加了属性和方法,丰富了基本数据类型的操作。

    什么是自动拆装箱

    • 装箱: 就是把基本数据类型转化成对应的包装类
    • 拆箱: 就是把包装类型转化成对应的基本数据类型
    • 自动装箱: 就是将基本数据类型自动转换成对应的包装类
    • 自动拆箱:就是将包装类自动转换成对应的基本数据类型

    Java SE5之前如果要生成一个值为1的对象需要以下操作

    Integer i = new Integer(1);
    

    Java SE5之后,提供了自动拆装箱的功能,只需要以下操作

    Integer i = 1;#自动装箱
    int j =i;#自动拆箱
    

    自动拆装箱的实现原理

    举个例子

    public class Demo {
        public static void main(String[] args) {
            Integer i = 1;
            int j = i;
        }
    }
    

    字节码如下

    从以上的字节码来看,Java自动装箱调用了Integer.valueof()方法,自动拆箱调用了Integer.intValue()方法,其他包装类的自动拆装箱类似

    什么时候会用到自动拆装箱

    1.赋值
    Integer i = 1;#自动装箱,调用 Integer.valueOf()
    int j =i;#自动拆箱,调用 Integer.intValue()
    

    2.逻辑、算术运算

    Integer i = 1;
    int j = 2;
    int z = i + j;
    Boolean flag = i > j ? true : false;
    

    反编译后

    Integer i = Integer.valueOf(1);
    int j = 2;
    int z = i.intValue() + j;
    Boolean flag = Boolean.valueOf(i.intValue() > j);
    

    3.将基本数据类型放到集合里面

    ArrayList<Integer> list = new ArrayList<>();
    list.add(1);
    

    反编译后

    ArrayList<Integer> list = new ArrayList();
    list.add(Integer.valueOf(1));
    

    4.函数调用

        public static void main(String[] args) {
            sum(2);
        }
        public static Integer sum(Integer i){
            return 0;
        }
    

    反编译后

      public static void main(String[] args)
      {
        sum(Integer.valueOf(2));
      }
      public static Integer sum(Integer i)
      {
        return Integer.valueOf(0);
      }
    

    自动拆装箱的问题

    我们来看下面的代码

    Integer i = 128;
    Integer j = 128;
    
    Integer x = 1;
    Integer y = 1;
    System.out.println(i==j);#false
    System.out.println(x == y);#true
    

    上面为什么会出现这样的结果,主要是由于Integer的缓存机制,我们来看一下Integer的源码

        public static Integer valueOf(int i) {
            if (i >= IntegerCache.low && i <= IntegerCache.high)
                return IntegerCache.cache[i + (-IntegerCache.low)];
            return new Integer(i);
        }
    
    

    Integer默认的缓存范围是 -128~127,当在这一范围时,不会生成新的对象;当超过这一范围后,才生成新的Integer对象。当然缓存机制不只有Integer有,比如:

    • Boolean,缓存了true/false对应实例,确切的说,返回两个常量实例Boolean.TRUE/FALSE
    • Short,缓存了 ~128-127的数值
    • Byte,数值有限,全部被缓存
    • Character,缓存范围‘ u0000 ' 到 ’ u007F '

    参考

    https://juejin.im/post/5b8de48951882542d63b4662

    https://www.cnblogs.com/dolphin0520/p/3780005.html

  • 相关阅读:
    js字符串数组['1','2','3']转number
    antd-vue中给table表格整行加点击事件
    vue中路由在新的标签页打开
    antd中的form表单 initialValue导致数据不更新问题
    vue中computed的作用以及用法
    gitlab新增ssh
    CentOS7安装配置ActiveMQ
    利用已有的缓存地图文件发布ArcGIS Server瓦片服务
    CentOS7上使用源码安装物联网大数据平台TDengine
    一些可以使用的在线地图服务
  • 原文地址:https://www.cnblogs.com/my12/p/10537173.html
Copyright © 2011-2022 走看看