对于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. java利用poi来读取execl表格返回对象

    利用poi来读取execl表格,返回一个对象(可能有点不完善,但是应该能满足平常的所用),用到了反射等等; 使用的jar包有: commons-collections4-4.1.jar poi-3.1 ...

  2. [USACO 04OPEN]MooFest

    Description 约翰的N 头奶牛每年都会参加“哞哞大会”.哞哞大会是奶牛界的盛事.集会上的活动很多,比如堆干草,跨栅栏,摸牛仔的屁股等等.它们参加活动时会聚在一起,第i 头奶牛的坐标为Xi,没 ...

  3. [ZJOI2008]瞭望塔

    题目描述 致力于建设全国示范和谐小村庄的H村村长dadzhi,决定在村中建立一个瞭望塔,以此加强村中的治安. 我们将H村抽象为一维的轮廓.如下图所示 我们可以用一条山的上方轮廓折线(x1, y1), ...

  4. hdu 5445 多重背包

    Food Problem Time Limit: 3000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)To ...

  5. hdu 5266 pog loves szh III(lca + 线段树)

    I - pog loves szh III Time Limit:6000MS     Memory Limit:131072KB     64bit IO Format:%I64d & %I ...

  6. ●BZOJ 1042 [HAOI2008]硬币购物

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=1042 题解: 容斥原理,dp预处理首先跑个无限物品的背包dp求出dp[i]表示在四种物品都有 ...

  7. [bzoj4883][Lydsy2017年5月月赛]棋盘上的守卫

    来自FallDream的博客,未经允许,请勿转载, 谢谢. 在一个n*m的棋盘上要放置若干个守卫.对于n行来说,每行必须恰好放置一个横向守卫:同理对于m列来说,每列 必须恰好放置一个纵向守卫.每个位置 ...

  8. bzoj2339[HNOI2011]卡农 dp+容斥

    2339: [HNOI2011]卡农 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 842  Solved: 510[Submit][Status][ ...

  9. C++ 二分法求解方程的解

    二分法是一种求解方程近似根的方法.对于一个函数 f(x)f(x),使用二分法求 f(x)f(x) 近似解的时候,我们先设定一个迭代区间(在这个题目上,我们之后给出了的两个初值决定的区间 [-20,20 ...

  10. shell基本命令

    linux基本命令和shell基本命令,好多人傻傻分不清. linux基本命令积累如下: pwd:显示当前工作目录 cd:改变当前目录 ls:显示当前目录中所有目录文件和文本文件 ls -F:显示当前 ...