美文网首页
装箱与拆箱详解笔记

装箱与拆箱详解笔记

作者: Timor小先生 | 来源:发表于2020-04-27 15:09 被阅读0次

    1、什么是自动装箱与拆箱

    //自动装箱

    Integer integer = 100;

    //自动拆箱

    int i = integer;

    装箱:自动将基本类型转化为包装类

    拆箱:自动将包装类转化为基本类型

    2、基本原理

    (1)、自动装箱,valueOf()

    Integer integer = 100  时系统自动执行了  Integer integer = Integer.valueOf(100);

    Integer.valueOf  源码

    static final int low = -128;

    static final int high;

    static final Integer cache[];

    public static Integer valueOf(int i) {

        if (i >= IntegerCache.low && i <= IntegerCache.high)

              return IntegerCache.cache[i + (-IntegerCache.low)];

        return new Integer(i);

    }

    首先判断i大小,是否在low (-128) 与high (默认127) 之间,不在就新创建一个Integer对象,否则返回cache数组。

    这里注意:

    a、在某个范围内的整型数值的个数是有限的,而浮点数却不是。所以Double Float不会有数组出现。

    b、cache 是一个静态的Integer数组,也就是说如果在low与high之间,返回的都是一个integer对象。

    c、装箱过程会创建相应的对象,会消耗内存,影响性能。

    (2)、自动拆箱,intValue()

    int i = integer  时系统自动执行了  int i = integer.intValue();

    intValue 源码

    public int intValue() {

        return value;

    }

    3、相关问题

    (1)、自动装箱 ==  问题

    a、Integer在 (-127,128] 有限个数

    Integer integer1 = 100;

    Integer integer2 = 100;

    Integer integer3 = 200;

    Integer integer4 = 200;

    System.out.println(integer1 == integer2); //true

    System.out.println(integer3 == integer4); //false

    这里都会进行自动装箱,但是 integer1、integer2 因为在-127到128 范围内,所以返回了同一个Integer对象,所以他们是相等的

    integer3、integer4也会进行自动封箱,但是因超出范围,都会返回 new Integer(200) ,所以不相等。

    b、Double类型

    Double aDouble1 = 100.0;

    Double aDouble2 = 100.0;

    Double aDouble3 = 100.0;

    Double aDouble4 = 100.0;

    System.out.println(aDouble1 == aDouble2); //false

    System.out.println(aDouble3 == aDouble4); //false

    这里和Integer不太一样,因为valueOf的实现不一样,对于Integer在某个范围内个数有限,所以为避免多次创建对象,java8会直接创建好一个大小为256的Integer数组,如果在这个范围内,直接返回这个对象。

    但是Double,在这个范围内是无限的,所以只能每次都新创建一个对象。类似的还有Float。

    c、Boolean

    对于Boolean类型,只有两种情况,所以都是提前创建好的,这样也是为了避免创建过多对象。

    (2)、Integer.equals(int) 问题

    Integer i1 = 10;

    int i2 = 10;

    System.out.println(i1 == i2); //true

    System.out.println(i1.equals(i2)); //true

    对于 == 操作,i1会进行自动拆箱

    对于 equals 操作,传入的是int,但源码参数是Object类型,所以会进行自动封箱,返回 true 是因为比较的是对象里的值,这里是重写了Object里面的 equals 方法,若不重写 equals 方法则比较的是引用对象的对象地址。

    public boolean equals(Object obj) {

        if (obj instanceof Integer) {

            return value == ((Integer)obj).intValue();

        }

        return false;

    }

    (3)、不同类型数值 == 与 equals 问题

    Integer num1 = 1;

    int num2 = 1;

    Long num3 = 2l;

    System.out.println(num1 + num2); //2

    System.out.println(num3 == (num1 + num2)); //true

    System.out.println(num3.equals(num1 + num2)); //false

    首先进行+ - * / == 运算会进行拆箱,进行基本数据类型之间运算、比较。

    equals 返回 false 是因为在比较 equals 时会进行自动封箱,只有当类型相同、内容相同时才返回true。

    (4)、不同类型不涉及基本类型比较 == 

    Integer num1 = 100;

    Ingeger num2 = 200;

    Long num3 = 300l;

    System.out.println(num3 == (num1 + num2)); //true

    进行 == 时 num3 进行拆箱,num1 + num2 进行拆箱

    (5)、基本类型测试

    int num1 = 100;

    int num2 = 200;

    long mum3 = 300;

    System.out.println(num3 == (num1 + num2)); //true

    对 (4) 的解释,基本类型比较的是数值

    所以,当 “==”运算符的两个操作数都是 包装器类型的引用,则是比较指向的是否是同一个对象,而如果其中有一个操作数是表达式(即包含算术运算)则比较的是数值(即会触发自动拆箱的过程)。

    (6)、包装类可以初始化为null,在进行拆箱时会报空指针异常

    Integer integer = null;

    int i = integer;

    所以有拆箱操作的时候要注意是否为null。

    4、总结一下:

    拆箱:包装类型 ----> 基本类型 ----> ==、运算

    装箱:基本类型 ----> 包装类型 ----> equals

    相关文章

      网友评论

          本文标题:装箱与拆箱详解笔记

          本文链接:https://www.haomeiwen.com/subject/dwtywhtx.html