对于java1.5引入的自动装箱拆箱,之前只是知道一点点,最近在看一篇博客时发现自己对自动装箱拆箱这个特性了解的太少了,所以今天研究了下这个特性。以下是结合测试代码进行的总结。

测试代码:

        int a = 1;
        Integer b = 1;
        Integer c = 1;
        Integer d = 2;
        Integer e = 3;
        Integer f = 128;
        Integer g = 128;
        Long h = 3L;
        Double m = 4.0;
        Double n = 4.0;
        Float p = 5f;
        Float q = 5f;
        System.out.println("a == b : " + (a == b));  //true
        System.out.println("b ==c : " + (b == c));  //true
        System.out.println("e == (c + d) : " + (e == (c + d)));  //true
        System.out.println("e.equals(c + d) : " + (e.equals(c + d)));  //true
        System.out.println("h == (c + d) : " + (h == (c + d))); //true
        System.out.println("h.equals(c + d) : " + (h.equals(c + d)));  //false
        System.out.println("f == g : " + (f == g)); //false
        System.out.println("m == n : " + (m == n)); //false
        System.out.println("p == q : " + (p == q)); //false
        System.out.println("m == d * 2 : " + (m == d * 2)); //true
        System.out.println("p == (d + e) : " + (p == (d + e))); //true

测试输出结果与说明:


 1. a == b : true
     当基本类型包装类与基本类型值进行==运算时,包装类会自动拆箱。即比较的是基本类型值。
     具体实现上,是调用了Integer.intValue()方法实现拆箱。
     可以在测试代码处打断点,使用F5快捷键step
    into至每一步执行方法,会看到调用了Integer.intValue()方法实现了拆箱。
 2. b == c : true
    b和c类型均为Integer包装类,故对基本类型进行自动装箱后赋值给b和c。
    在进行==运算时不会触发拆箱操作。所以比较的是引用地址,说明b和c是同一个对象。
    java中自动装箱调用的是Integer.valueOf()方法实现的,可以像例1一样打断点验证。
    为什么b和c 会是同一个对象呢?查看Integer.valueOf()方法实现即可知道,如下:
    下面的代码中可以看到,对于-128至127这256个值,直接获取的IntegerCache中的值。
    而IntegerCache是Integer中的一个静态内部类,
    里面将-128至127(即一个字节所能表示的所有带符号值 -2^7至2^7-1)的包装类存在了一个数组中。
    对于-128到127之间的数,直接从数组中获取,其他的数则使用new生成。所以此处输出true。

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

    private static class IntegerCache {
        static final int high;
        static final Integer cache[];

        static {
            final int low = -128;

            // high value may be configured by property
            int h = 127;
            if (integerCacheHighPropValue != null) {
                // Use Long.decode here to avoid invoking methods that
                // require Integer's autoboxing cache to be initialized
                int i = Long.decode(integerCacheHighPropValue).intValue();
                i = Math.max(i, 127);
                // Maximum array size is Integer.MAX_VALUE
                h = Math.min(i, Integer.MAX_VALUE - -low);
            }
            high = h;

            cache = new Integer[(high - low) + 1];
            int j = low;
            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++);
        }

 3. e == (c + d) : true
    包装类在执行加减乘除求余等运算时,会触发拆箱操作,故c、d拆箱后相加,
    结果为基本类型;然后e与基本类型进行==运算,触发拆箱操作。
 4. e.equals(c + d) : true
    首先,c + d 拆箱运算得到基本类型值;然后当进行equals运算时,
    会触发基本类型值的装箱操作,c + d 的结果会自动装箱为包装类;最后与e进行equals运算。
 5. h == (c + d) : true
    运算顺序与上面例3中一致,唯一区别是h自动拆箱是调用了Long.longValue()实现。
 6. h.equals(c + d) : false
    运算顺序与上面例4中一致,为false的原因在于c + d的运算结果自动装箱后类型为Integer,
    而h的类型为Long,类型不一样,equals的结果为false。
 7. f == g : false
     请参考上面例2中的解释。
     超出了-128至127的缓存范围,故在valueOf()方法中使用new生成了新对象。

 8. m == n : false
    p == q : false
    与上面例子1、2中的结果不同,对于Boolean、Byte、Character、Short、Integer、Long六种基本类型,
    对于一个字节以内的值-128到127(Boolean只有true和false)都实现了缓存机制。
    不在此范围的数才在对应的valueOf()方法中new出一个新的对象。
    但是对于Double和Float类型的浮点数据,在-128到127之间除了256个整数外还有无数的小数,
    故java中没有实现Double和Float中一些数的缓存。
    所以,对于Double和Float的自动装箱,都是new出新的对象。故此两例均输出false。

 10. m == d * 2 : true
     p == (d + e) : true
     请参考例3和例5。

反编译后代码:

使用java反编译工具,对class字节码文件进行反编译,结果如下所示。从下面的反编译代码,我们可以看到java是如何实现自动装箱、拆箱的。

    int a = 1;
    Integer b = Integer.valueOf(1);
    Integer c = Integer.valueOf(1);
    Integer d = Integer.valueOf(2);
    Integer e = Integer.valueOf(3);
    Integer f = Integer.valueOf(128);
    Integer g = Integer.valueOf(128);
    Long h = Long.valueOf(3L);
    Double m = Double.valueOf(4.0D);
    Double n = Double.valueOf(4.0D);
    Float p = Float.valueOf(5.0F);
    Float q = Float.valueOf(5.0F);
    System.out.println("a == b : " + (a == b.intValue()));
    System.out.println("b ==c : " + (b == c));
    System.out.println("e == (c + d) : " + (e.intValue() == c.intValue() + d.intValue()));
    System.out.println("e.equals(c + d) : " + e.equals(Integer.valueOf(c.intValue() + d.intValue())));
    System.out.println("h == (c + d) : " + (h.longValue() == c.intValue() + d.intValue()));
    System.out.println("h.equals(c + d) : " + h.equals(Integer.valueOf(c.intValue() + d.intValue())));
    System.out.println("f == g : " + (f == g));
    System.out.println("m == n : " + (m == n));
    System.out.println("p == q : " + (p == q));
    System.out.println("m == d * 2 : " + (m.doubleValue() == d.intValue() * 2));
    System.out.println("p == (d + e) : " + (p.floatValue() == d.intValue() + e.intValue()));

参考文章:

①Java 自动装箱和拆箱

②Java自动装箱与拆箱及其陷阱

③深入剖析Java中的装箱和拆箱

④四道Java基础题 你能对几道?

java自动装箱拆箱总结的更多相关文章

  1. JAVA自动装箱拆箱与常量池

    java 自动装箱与拆箱 这个是jdk1.5以后才引入的新的内容,作为秉承发表是最好的记忆,毅然决定还是用一篇博客来代替我的记忆: java语言规范中说道:在许多情况下包装与解包装是由编译器自行完成的 ...

  2. Java 自动装箱/拆箱

    自动装箱/拆箱大大方便了基本类型(8个基本类型)数据和它们包装类的使用 自动装箱 : 基本类型自动转为包装类(int >> Integer) 自动拆箱: 包装类自动转为基本类型(Integ ...

  3. Java自动装箱拆箱

    一.装箱.拆箱定义 如果一个int型量被传递到需要一个Integer对象的地方,那么,编译器将在幕后插入一个对Integer构造方法的调用,这就叫做自动装箱.而如果一个Integer对象被放到需要in ...

  4. 深入理解Java自动装箱拆箱机制

    1.自动装箱与拆箱的定义 装箱就是自动将基本数据类型转换为包装器类型(int-->Integer): 拆箱就是自动将包装器类型转换为基本数据类型(Integer-->int). Java中 ...

  5. 那些年一起踩过的坑 — java 自动装箱拆箱问题

    坑在哪里?   我们都知道Java的八种基本数据类型:int, short, long, double, byte, char, float, boolean   分别有各自对应的包装类型:Integ ...

  6. Java 的自动装箱拆箱

    Java 是面向对象的语言,其基本数据类型也就有了相对应的类,称为包装类.以下是基本数据类型对应的包装类: 基本数据类型 包装类 byte(1字节) Byte short(2字节) Short int ...

  7. Java八种基本数据类型的大小,以及封装类,自动装箱/拆箱的用法?

    参考:http://blog.csdn.net/mazhimazh/article/details/16799925 1. Java八种基本数据类型的大小,以及封装类,自动装箱/拆箱的用法? 原始类型 ...

  8. java基础1.5版后新特性 自动装箱拆箱 Date SimpleDateFormat Calendar.getInstance()获得一个日历对象 抽象不要生成对象 get set add System.arrayCopy()用于集合等的扩容

    8种基本数据类型的8种包装类 byte Byte short Short int Integer long Long float Float double Double char Character ...

  9. Java的自动装箱/拆箱

    概述 自JDK1.5开始, 引入了自动装箱/拆箱这一语法糖, 它使程序员的代码变得更加简洁, 不再需要进行显式转换.基本类型与包装类型在某些操作符的作用下, 包装类型调用valueOf()方法将原始类 ...

随机推荐

  1. mysql sql语句执行时是否使用索引检查方法

    在日常开发中,使用到的数据表经常都会有索引,这些索引可能是开发人员/DBA建表时创建的,也可能是在使用过程中新增的.合理的使用索引,可以加快数据库查询速度.然而,在实际开发工作中,会出现有些sql语句 ...

  2. [LeetCode] Network Delay Time 网络延迟时间

    There are N network nodes, labelled 1 to N. Given times, a list of travel times as directed edges ti ...

  3. pyqt5 动画学习(一) 改变控件大小

    入坑pyqt也有半年了,由于人们对事物的审美,静态界面已经不能满足用户,而动画却给人眼前一亮,so,今天来学习pyqt的动画了 由于资料真的是太少,本人也是有啃外国佬的英文进行摸索学习,可能也是触及皮 ...

  4. Pycharm节能模式

    如题,开启节能模式代码不会自动补全.

  5. [Codeforces 946G]Almost Increasing Array

    Description 题库链接 给你一个长度为 \(n\) 的序列 \(A\) .现在准许你删除任意一个数,删除之后需要修改最小的次数使序列单调递增.问最小次数. \(1\leq n\leq 200 ...

  6. ●UVA 10652 Board Wrapping

    题链: https://vjudge.net/problem/UVA-10652 题解: 计算几何,Andrew求凸包, 裸题...(数组开小了,还整了半天...) 代码: #include<c ...

  7. 51Nod 1331 狭窄的通道

    有一个长为L的狭窄通道,我们假设这个通道在x轴上,其两个出口分别在x=0与x=L处.在这个通道里有N只狼,第i只狼有一个初始位置ai,它想到达位置bi(0<=i=L处空间足够大可以装下任意数量的 ...

  8. hdu 5656 CA Loves GCD(n个任选k个的最大公约数和)

    CA Loves GCD  Accepts: 64  Submissions: 535  Time Limit: 6000/3000 MS (Java/Others)  Memory Limit: 2 ...

  9. 抽象方法不能是static或native或synchroniz

    abstract 是抽象了,只有声明,没有具体的实现方法 static是静态的,是一种属于类而不属于对象的方法或者属性,而我们知道,类其实也是一个对象,他是在class文件加载到虚拟机以后就会产生的对 ...

  10. 两个文件比较之comm命令

    comm命令可用于两个文件之间的比较.它有很多不错的选项可用来调整输出,以便我们执行交集.求差(difference)以及差集操作. 交集:打印出两个文件所共有的行. 求差:打印出指定文件所包含的 ...