Java自动装箱拆箱浅析

给你一囗甜甜゛ 提交于 2020-02-28 12:57:25

自动装箱拆箱概念

在Java SE 5之后,为基本数据类型提供了自动装箱和拆箱功能,使得将基本类型转换与对象之间的转换变得极其便捷。
| 基本数据类型    | 包装类    |
| int(4字节)     | Integer   |
| byte(1字节)    | Byte      |
| short(2字节)   | Short     |
| long(8字节)    | Long      |
| float(4字节)   | Float     |
| double (8字节) | Double    |
| char(2字节)    | Character |
| boolean(未定)  | Boolean   |

Integer i = 100;(拆箱)
int j = i;(装箱)

自动装箱拆箱的实现

Integer i = 100;(拆箱)
int j = i;(装箱)
//上面两行代码的反编译如下:
Integer i = Integer.valueOf(100);//拆箱
int j = i.intValue();//装箱
对于其他基本类型的装箱和拆箱和int类似。

案例分析

Integer

(1)案例
int a = 100;
int b = 100;
System.out.println(a == b);
int c = 200;
int d = 200;
System.out.println(c == d);
Integer e = new Integer(100);
System.out.println(a == e);
//结果
true
true
true
//反编译
byte a = 100;
byte b = 100;
System.out.println(a == b);
short c = 200;
short d = 200;
System.out.println(c == d);
Integer e = new Integer(100);
System.out.println(a == e.intValue());

如果改为下面的代码呢?
(2)案例
Integer a = 100;
Integer b = 100;
System.out.println(a == b);
//int c = 200;
Integer c = 200;
Integer d = 200;
System.out.println(c == d);//输出true
Integer e = new Integer(100);
System.out.println(a == e);
//结果
true
false
false
//反编译结果
Integer a = Integer.valueOf(100);
Integer b = Integer.valueOf(100);
System.out.println(a == b);
Integer c = Integer.valueOf(200);
Integer d = Integer.valueOf(200);
System.out.println(c == d);
Integer e = new Integer(100);
System.out.println(a == e);

(1)案例和(2)案例为啥不一样呢?

        当 "=="运算符的两个操作数都是包装器类型的引用,则比较的是对象;而如果其中有一个操作数是表达式(即包含算术运算)或是基本类型则比较的是数值。

原因分析:我们查看一下valueOf()源码

public static Integer valueOf(int i) {
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        //这里有个IntegerCache
        return IntegerCache.cache[i + (-IntegerCache.low)];
        //当大于high小于low时才新建
    return new Integer(i);
}
//可以得知low=-128,high=127
private static class IntegerCache {
    static final int low = -128;
    static final int high;
    static final Integer cache[];

    static {
        // high value may be configured by property
        int h = 127;
        String integerCacheHighPropValue =
            sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
        if (integerCacheHighPropValue != null) {
            try {
                int i = parseInt(integerCacheHighPropValue);
                i = Math.max(i, 127);
                // Maximum array size is Integer.MAX_VALUE
                h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
            } catch( NumberFormatException nfe) {
                // If the property cannot be parsed into an int, ignore it.
            }
        }
        high = h;

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

        // range [-128, 127] must be interned (JLS7 5.1.7)
        assert IntegerCache.high >= 127;
    }

    private IntegerCache() {}
}

Boolean

boolean a = true;
boolean b = true;
System.out.println(a == b);

Boolean c = true;
Boolean d = true;
System.out.println(c == d);
//结果
true
true
//反编译
boolean a = true;
boolean b = true;
System.out.println(a == b);
Boolean c = Boolean.valueOf(true);
Boolean d = Boolean.valueOf(true);
System.out.println(c == d);

为什么是true?我们查看valueOf()源码

public static Boolean valueOf(boolean b) {
    return (b ? TRUE : FALSE);
}
//注意TRUE和FALSE为常量
public static final Boolean TRUE = new Boolean(true);
public static final Boolean FALSE = new Boolean(false);

Double

double a = 1.0;
double b = 1.0;
System.out.println(a == b);
Double c = 1.0;
Double d = 1.0;
System.out.println(c == d);
//结果
true
false
//反编译
double a = 1.0D;
double b = 1.0D;
System.out.println(a == b);
Double c = Double.valueOf(1.0D);
Double d = Double.valueOf(1.0D);
System.out.println(c == d);
//valueOf()源码
public static Double valueOf(double d) {//创建了新对象
    return new Double(d);
}

Long

Integer a = 1;
Integer b = 2;
Integer c = 3;
Integer d = 3;
Integer e = 321;
Integer f = 321;
Long g = 3L;
Long h = 2L;
System.out.println(c==d);//-127~128
System.out.println(e==f);//>128
System.out.println(c==(a+b));//自动拆箱
System.out.println(c.equals(a+b));//都是Integer类型
System.out.println(g==(a+b));//自动拆箱,向上转型为long
System.out.println(g.equals(a+b));//类型不匹配
System.out.println(g.equals(a+h));//向上转型为Long
//结果
true
false
true
true
true
false
true
//反编译
Integer a = Integer.valueOf(1);
Integer b = Integer.valueOf(2);
Integer c = Integer.valueOf(3);
Integer d = Integer.valueOf(3);
Integer e = Integer.valueOf(321);
Integer f = Integer.valueOf(321);
Long g = Long.valueOf(3L);
Long h = Long.valueOf(2L);
System.out.println(c == d);
System.out.println(e == f);
System.out.println(c.intValue() == a.intValue() + b.intValue());
System.out.println(c.equals(Integer.valueOf(a.intValue() + b.intValue())));
System.out.println(g.longValue() == (long)(a.intValue() + b.intValue()));
System.out.println(g.equals(Integer.valueOf(a.intValue() + b.intValue())));
System.out.println(g.equals(Long.valueOf((long)a.intValue() + h.longValue())));

//Long的equals
public boolean equals(Object obj) {
    if (obj instanceof Long) {//类型不一样便是false
        return value == ((Long)obj).longValue();
    }
    return false;
}
包装类型的大小比较

包装类型使用时注意点

谨慎包装类型的大小比较

public static void main(String[] args) {
    Integer i = new Integer(100);
    Integer j = new Integer(100);
    // Integer j = 100;(或者如此)
    compare(i,j);
}
//比较两个包装对象大小
public static void  compare(Integer i , Integer j) {
    System.out.println(i == j);
    System.out.println(i > j);
    System.out.println(i < j);
}
//结果
false
false
false
public static void main(String[] args) {
    Integer i = new Integer(100);
    Integer j = new Integer(100);
    // Integer j = 100;(或者如此)
    compare(i,j);
}
//比较两个包装对象大小
public static void  compare(Integer i , int j) {
    System.out.println(i == j);
    System.out.println(i > j);
    System.out.println(i < j);
}
//结果
true
false
false

提防包装类型的null值

public static void main(String[] args) {
    List<Integer> list = new ArrayList<Integer>();
    list.add(1);
    list.add(2);
    list.add(null);
    System.out.println(f(list));
}

public static int f(List<Integer> list) {
    int count = 0;
    for (Integer i : list) {
        //必须对null进行处理
        //count += (i!=null)?i:0;
        count += i;
    }
    return count;
}
//结果
Exception in thread "main" java.lang.NullPointerException


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!