java包装类相关知识总结

java包装类相关知识总结

1、什么是包装类

封装了操作对应基本数据类型方法的类

2、装箱和拆箱

装箱:将基本数据类型转换成对应的包装类 public static Integer valueOf(int i)
拆箱:将包装类转化成对应的基本数据类型 public int intValue()

int、Integer、String三者之间的转换关系图:
这里写图片描述

3、相同类型包装类变量之间的比较

Boolean boolean1 = false;
Boolean boolean2 = false;
Character character1 = '0';
Character character2 = '0';
Byte byte1 = 18;
Byte byte2 = 18;
Short short1 = 18;
Short short2 = 18;
Integer integer1 = 18;
Integer integer2 = 18;
Long long1 = 18L;
Long long2 = 18L;
Float float1 = 18f;
Float float2 = 18f;
Double double1 = 18d;
Double double2 = 18d;

if (boolean1 == boolean2) {
    System.out.println("boolean1 == boolean2");
}
if (character1 == character2) {
    System.out.println("character1 == character2");
}
if (byte1 == byte2) {
    System.out.println("byte1 == byte2");
}
if (short1 == short2) {
    System.out.println("short1 == short2");
}
if (integer1 == integer2) {
    System.out.println("integer1 == integer2");
}
if (long1 == long2) {
    System.out.println("long1 == long2");
}
if (float1 == float2) {
    System.out.println("float1 == float2");
}
if (double1 == double2) {
    System.out.println("double1 == double2");
}

输出结果为:
boolean1 == boolean2
character1 == character2
byte1 == byte2
short1 == short2
integer1 == integer2
long1 == long2

原因:在以上变量的赋值过程中,都会发生自动装箱,自动装箱过程会调用各个包装类的valueOf函数,可以通过查看各个包装类源码来理解。

对于Boolean:

public static final Boolean TRUE = new Boolean(true);
public static final Boolean FALSE = new Boolean(false);

public static Boolean valueOf(boolean b) {
    return (b ? TRUE : FALSE);
}

这个比较好理解,每次装箱返回的都是常量,所以输出结果是两个变量相等。

对于Character:

private static class CharacterCache {
    private CharacterCache(){}
    static final Character cache[] = new Character[127 + 1];
    static {
       for (int i = 0; i < cache.length; i++)
           cache[i] = new Character((char)i);
   }
}
public static Character valueOf(char c) {
   if (c <= 127) { // must cache
       return CharacterCache.cache[(int)c];
   }
   return new Character(c);
}

我们从源码中可以看出Character内部实现了缓存机制,会缓存从数值从0-127的字符,如果元素在这个范围内则直接使用缓存中的元素,否则需要重新实例化,对于代码中的‘0’字符,两个变量指向的是同一段内存,所以用“==”进行比较的结果也相等。

对于表示整形的数值类型(以Integer为例):

public static Integer valueOf(int i) {
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
}
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() {}
}

我们可以看出Integer中同样使用了缓存机制,缓存的是从-128到127之间的元素,对于18正好在这个范围内,所以两个变量指向的是同一段内存,所以用“==”进行比较的结果也相等,其它包装类中原理也类似。

然而对于Float和Double(以Double为例):

public static Double valueOf(double d) {
    return new Double(d);
}

很明显,Double中每次调用valueOf函数时都会实例化一个新元素,所以用“==”进行比较是不能得到相等的结果的,当然这也是可以理解的,因为在一个区间内整数的个数是有限的,但是浮点型数据的个数是无限的,所以不能通过一个数组来缓存一个区间内的元素,这也就是为什么Float和Double没有输出相等的结果。

4、不同类型包装类对象之间的比较

相同类型包装类对象之间的比较我们已经基本了解了,那么不同类型之间的比较又是什么样子的呢?
看下面这个例子:

Short short3 = new Short((short)18);
Long long3 = new Long(18);
if (short3.equals(long3)) {
    System.out.println("short3.equals(long3)");
}else {
    System.out.println("!short3.equals(long3)");
}

输出结果:!short3.equals(long3)
有人可能认为equals不是用来比较值是否相等的吗?为什么结果不相等,其实原因很简单,看源码一目了然:

public boolean equals(Object obj) {
    if (obj instanceof Short) {
        return value == ((Short)obj).shortValue();
    }
    return false;
}

这是Short中的equals方法,方法的第一句就是判断要比较的对象是不是一个Short实例,因为long3是Long的对象,很明显条件不成立,会直接返回false。

5、基本类型和包装类之间的比较

基本数据类型间的比较不用说,包装类之间的比较也了解了,那么有没有想过基本类型和包装类之间的比较是什么样的一个过程呢?
包装类型和基本类型进行比较的时候其实是包装类型进行拆箱以后再和基本类型进行比较的。
我们可以通过以下代码进行验证:

int i = 200;
Integer integer5 = 200;
if (integer5 == i) {
    System.out.println("发生拆箱");
}else {
    System.out.println("发生装箱");         
}

输出结果为:发生拆箱
根据上面的分析我们知道,假设是基本数据类型发生了装箱操作,那么就应该变成两个包装类对象通过“==”进行比较,200是大于127的,所以应该是两个不同对象进行比较,应该输出的是“发生装箱”才对,所以通过反证法我们可知,基本类型和包装类之间的比较是包装类发生拆箱然后再和基本类型的数据进行比较的。

猜你喜欢

转载自blog.csdn.net/qq_30496695/article/details/75349364