美文网首页笔试&&面试经验Java学习笔记
Java装箱与拆箱—Autoboxing and Unboxin

Java装箱与拆箱—Autoboxing and Unboxin

作者: 程田 | 来源:发表于2017-02-28 19:22 被阅读88次

    本文将介绍Java的自动装箱与拆箱
    翻译自Java官方文档:Autoboxing and Unboxing
    CSDN地址:http://blog.csdn.net/myterabithia/article/details/58626273

    什么是自动装箱与拆箱?

    Java编译器将原始数据类型自动转换为对应的包装类的过程成为自动装箱,例如,把一个int转换为Integer,一个double转换为Double等。相应的,将包装类自动转换为相应的原始数据类型的过程称为自动拆箱

    一个自动装箱的例子:

    Character ch = 'a';
    

    再看下下面的代码:

    List<Integer> li = new ArrayList<>();
    for (int i = 1; i < 50; i += 2)
        li.add(i);
    

    li是Integer类型的List,虽然往li里添加的是一个int,而不是Integer,但是编译器却没有报错,这是因为编译器创建了一个值为i的Integer对象,并把这个Integer对象添加进了li,在运行时就相当于下面的代码:

    List<Integer> li = new ArrayList<>();
    for (int i = 1; i < 50; i += 2)
        li.add(Integer.valueOf(i));
    

    什么时候自动装箱?

    • 当原始数据类型被当做参数传到了一个参数要求是包装类的方法里
    • 当原始数据被赋值给包装类对象

    看下面的代码:

    public static int sumEven(List<Integer> li) {
        int sum = 0;
        for (Integer i: li)
            if (i % 2 == 0)
                sum += i;
            return sum;
    }
    

    Integer对象是不用应用操作符%和+=的,编译器没报错是因为在运行时自动调用Integer的intValue方法将Integer转换为了int,相当于运行下面的代码:

    public static int sumEven(List<Integer> li) {
        int sum = 0;
        for (Integer i : li)
            if (i.intValue() % 2 == 0)
                sum += i.intValue();
            return sum;
    }
    

    什么时候自动拆箱?

    • 当包装类被当做参数传到了一个参数要求是原始类型的方法里
    • 当包装类被赋值给原始数据类型

    看下面的例子:

    import java.util.ArrayList;
    import java.util.List;
    
    public class Unboxing {
    
        public static void main(String[] args) {
            Integer i = new Integer(-8);
    
            // 1. Unboxing through method invocation
            int absVal = absoluteValue(i);
            System.out.println("absolute value of " + i + " = " + absVal);
    
            List<Double> ld = new ArrayList<>();
            ld.add(3.1416);    // π is autoboxed through method invocation.
    
            // 2. Unboxing through assignment
            double pi = ld.get(0);
            System.out.println("pi = " + pi);
        }
    
        public static int absoluteValue(int i) {
            return (i < 0) ? -i : i;
        }
    }
    

    上面程序打印结果:
    absolute value of -8 = 8
    pi = 3.1416

    自动装箱与拆箱能让开发人员写出更优雅更易读的代码,下面列出原始数据类型与包装类之间的对应关系:

    原始类型 包装类
    boolean Boolean
    byte Byte
    char Character
    float Float
    int Integer
    long Long
    short Short
    double Double

    注意

    以下内容来自另一篇官方文档:Autoboxing

    1. Integer是对象类型,可以为null,如果这个时候拆箱,会报NullPointerException异常
    2. Integer a,b,a==b比较的是a,b的引用,而不是值。但是由于Integer默认在-128到127之间有缓存(详见Integer源码),所以在这个区间使用==和equals的结果一样。
    3. 自动装箱与拆箱有性能损耗,只有在包装类和基本类型之间出现“阻抗不匹配(impedance mismatch)”时才使用,如,当需要将一个数值放到集合里面时。对性能要求很严格的地方谨慎使用。
    4. 原始数据类型和包装类之间的界限很模糊(blur),但谁都不能消灭(eliminate)对方。

    相关文章

      网友评论

        本文标题:Java装箱与拆箱—Autoboxing and Unboxin

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