对于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. [LeetCode] Output Contest Matches 输出比赛匹配对

    During the NBA playoffs, we always arrange the rather strong team to play with the rather weak team, ...

  2. js保留整数

    1.丢弃小数部分,保留整数部分parseInt(5/2) 2.向上取整,有小数就整数部分加1 Math.ceil(5/2) 3,四舍五入. Math.round(5/2) 4,向下取整 Math.fl ...

  3. [ Java学习基础 ] String、StringBuffer、StringBuilder比较学习

    首先讲获得字符串对象的方式有两种,一种是直接使用字符串常量,一种是使用new关键字创建,但它们之间是有一些区别,如下运行实例: String s1 = new String("Hello&q ...

  4. hdu 5724 SG+状态压缩

    Chess Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submi ...

  5. 【bzoj3173-最长上升子序列-一题两解】

    这道题不就是简单的DP吗,BZOJ在水我!不,你是错的. ·本题特点:       不断向不同位置插入数字(按数字1,2,3,4,5,6……),需要求出每一次插入后的最长上升子序列. ·分析      ...

  6. bzoj3309DZY Loves Math

    3309: DZY Loves Math Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1240  Solved: 777[Submit][Statu ...

  7. [bzoj4873]寿司餐厅

    来自FallDream的博客,未经允许,请勿转载,谢谢. Kiana最近喜欢到一家非常美味的寿司餐厅用餐.每天晚上,这家餐厅都会按顺序提供n种寿司,第i种寿司有一个代号ai和美味度di,i,不同种类的 ...

  8. [BZOJ]1047 理想的正方形(HAOI2007)

    真·水题.小C本来是不想贴出来的,但是有一股来自东方的神秘力量催促小C发出来. Description 有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和 ...

  9. java版的类似飞秋的局域网在线聊天项目

    原文链接:http://www.cnblogs.com/wangleiblog/articles/5323305.html 转载请注明 最近在弄一个java版的局域网在线聊天项目,功能跟飞秋差不多.p ...

  10. Android开发Java基础之Java语言基础(1)

    Java中的基本数据类型 整数类型 整数类型用来存储整数数值,既没有小数部分的数值.可以是正数,也可以是负数.整数类型在Java程序中有三种表现形式,分别是十进制,八进制,十六进制. 整型数据根据它所 ...