对于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. 初学servlet之@WebServlet传参

    package app01a;import java.io.IOException;import java.io.PrintWriter;import javax.servlet.ServletCon ...

  2. hash解密小助手-python版

    今天再看乌云大会的直播,最后一题用到了DEKHash解密,所以上github搜索了一个小工具,名字叫GeneralHashFunctions.py,出处忘记复制了,就复制了有用的代码,下次遇到出处在粘 ...

  3. python学习记录2

    一.两个模块(sys和os) #!/usr/bin/env python # _*_ coding: UTF-8 _*_ # Author:taoke import sys print(sys.pat ...

  4. [LOJ 6249]「CodePlus 2017 11 月赛」汀博尔

    Description 有 n 棵树,初始时每棵树的高度为 H_i,第 i 棵树每月都会长高 A_i.现在有个木料长度总量为 S 的订单,客户要求每块木料的长度不能小于 L,而且木料必须是整棵树(即不 ...

  5. [USACO14DEC]驮运Piggy Back

    题目描述 Bessie 和 Elsie在不同的区域放牧,他们希望花费最小的能量返回谷仓.从一个区域走到一个相连区域,Bessie要花费B单位的能量,Elsie要花费E单位的能量. 如果某次他们两走到同 ...

  6. Topcoder口胡记 SRM 562 Div 1 ~ SRM 599 Div 1

    据说做TC题有助于提高知识水平? :) 传送门:https://284914869.github.io/AEoj/index.html 转载请注明链接:http://www.cnblogs.com/B ...

  7. 【NOIP2013】华容道 广搜+spfa

    题目描述 [问题描述] 小 B 最近迷上了华容道,可是他总是要花很长的时间才能完成一次.于是,他想到用编程来完成华容道:给定一种局面, 华容道是否根本就无法完成,如果能完成, 最少需要多少时间. 小 ...

  8. python常用命令(持续) | Commonly used Python command list (con't)

    ---------------------------------------------------------------------------------------------------- ...

  9. vim配置文件和插件管理

    本文通过总结零碎的资料总结而成,更多是去引导学习vim配置文件及插件使用. .vimrc配置文件,内容如下(备注清晰) "引入插件pathogen使用 execute pathogen#in ...

  10. 如何让Mac、Windows可以互相远程

    您可以通过Mac来远程Windows桌面:也可通过Windows来远程Mac界面:甚至还可以通过iOS或Android来远程Mac或Windows. Windows的操作方法,以Windows XP ...