Java拆箱和装箱

Java拆箱装箱深入解析


学而不思则罔,思而不学则殆

定义

【装箱】把基本类型用它们相应的引用类型包装起来,使其具有对象的性质。int包装成Integer、float包装成Float;装箱是将值类型转换为引用类型

【拆箱】和装箱相反,将引用类型的对象简化成值类型的数据;拆箱是将引用类型转换为值类型

可拆装箱的类型

对应关系:

  1. byte 《==》Byte
  2. short 《==》Short
  3. int 《==》Integer
  4. long 《==》 Long
  5. char 《==》 Character
  6. double《==》Double
  7. float《==》Float
  8. boolean《==》Boolean

研究

为了测试拆箱和装箱,我定义一些打印结果的方法,如下:

        byte b = 1;
        Byte bb = 1;
        char c = 65;
        Character cc = 'A';
        short s = 1;
        Short ss = 1;
        int i = 1;
        Integer ii = 1;
        long l = 1L;
        Long ll = 1L;
        float f = 1F;
        Float ff = 1F;
        double d = 1D;
        Double dd = 1D;

    private static void show(Object object) { System.out.println("" + object.getClass()); }
    private static void show(byte object) { System.out.println("byte:" + object); }
    private static void show(Byte object) { System.out.println("Byte:" + object); }    
    private static void show(char object) { System.out.println("char:" + object); }
    private static void show(Character object) { System.out.println("Character:" + object); }   
    private static void show(short object) { System.out.println("short:" + object); }
    private static void show(Short object) { System.out.println("Short:" + object); }    
    private static void show(int object) { System.out.println("int:" + object); }
    private static void show(Integer object) { System.out.println("Integer:" + object); }
    private static void show(long object) { System.out.println("long:" + object); }
    private static void show(Long object) { System.out.println("Long:" + object); }
    private static void show(float object) { System.out.println("float:" + object); }
    private static void show(Float object) { System.out.println("Float:" + object); }
    private static void show(double object) { System.out.println("double:" + object); }
    private static void show(Double object) { System.out.println("Double:" + object); }

测试相同类型的运算

测试byte和Byte

让byte和Byte之间相互相加,看看最终的结果是什么,

        show(b + bb); //int:2  当我只保留show(Object object)这个方法时:class java.lang.Integer
        show(b + b);  //int:2                                         class java.lang.Integer
        show(bb + bb);//int:2                                         class java.lang.Integer

结论:byte和Byte运算,默认会是int类型(拆箱运算),当只有show(Object object)的方法时,自动装箱为Integer类型,而不是Byte类型

测试char和Character

让char和Character 之间相互相加,看看最终的结果是什么,

        show(c + cc);   //int:130  只保留show(Object object)方法: class java.lang.Integer
        show(c + c);    //int:130                                 class java.lang.Integer
        show(cc + cc);  //int:130                                 class java.lang.Integer

结论:char和Character,默认会是int类型(拆箱运算),当只有show(Object object)的方法时,自动装箱为Integer类型,而不是Character 类型

测试short 和Short

        show(s + s);   //int:2  只保留show(Object object)方法: class java.lang.Integer
        show(s + ss);  //int:2                                 class java.lang.Integer
        show(ss + ss); //int:2                                 class java.lang.Integer

结论:short 和Short 运算,默认会是int类型(拆箱运算),当只有show(Object object)的方法时,自动装箱为Integer类型,而不是Short 类型

测试int 和Integer

        show(i + i);   //int:2  只保留show(Object object)方法: class java.lang.Integer
        show(i + ii);  //int:2                                 class java.lang.Integer
        show(ii + ii); //int:2                                 class java.lang.Integer

结论:int 和Integer 运算,默认会是int类型(拆箱运算),当只有show(Object object)的方法时,自动装箱为Integer类型

测试long 和Long

        show(l + l);   //long:2 只保留show(Object object)方法: class java.lang.Long
        show(l + ll);  //long:2                                class java.lang.Long
        show(ll + ll); //long:2                                class java.lang.Long

结论:long 和Long 运算,默认会是long 类型(拆箱运算),当只有show(Object object)的方法时,自动装箱为Long类型

测试float 和Float

        show(f + f);   //float:2.0  只保留show(Object object)方法: class java.lang.Float
        show(f + ff);  //float:2.0                                 class java.lang.Float
        show(ff + ff); //float:2.0                                 class java.lang.Float

结论:float 和Float 运算,默认会是float 类型(拆箱运算),当只有show(Object object)的方法时,自动装箱为Float 类型

测试double 和Double

        show(d + d);   //double:2.0  只保留show(Object object)方法: class java.lang.Double
        show(d + dd);  //double:2.0                                 class java.lang.Double
        show(dd + dd); //double:2.0                                 class java.lang.Double

结论:double 和Double 运算,默认会是double 类型(拆箱运算),当只有show(Object object)的方法时,自动装箱为Double 类型

整理结论:

  1. 值类型数据和引用型对象之间运算,会默认拆箱为值类型运算,结果也是值类型
  2. 其中byte,char,short运算时会转换为int,在运算,最终结果也是int
  3. long,float,double运算结果是其自身,

测试不同类型之间的运算

Byte

        show(bb + bb);  //int:2 class java.lang.Integer
        show(bb + cc);  //int:66 class java.lang.Integer
        show(bb + ss);  //int:2 class java.lang.Integer
        show(bb + ii);  //int:2 class java.lang.Integer
        show(bb + ll);  //long:2 class java.lang.Long
        show(bb + ff);  //float:2.0 class java.lang.Float
        show(bb + dd);  //double:2.0 class java.lang.Double

Character

        show(cc + bb); //int:66 class java.lang.Integer
        show(cc + cc); //int:130 class java.lang.Integer
        show(cc + ss); //int:66 class java.lang.Integer
        show(cc + ii); //int:66 class java.lang.Integer
        show(cc + ll); //long:66  class java.lang.Long
        show(cc + ff); //float:66.0 class java.lang.Float
        show(cc + dd); //double:66.0 class java.lang.Double

Short

        show(ss + bb); //int:2 class java.lang.Integer
        show(ss + cc); //int:66 class java.lang.Integer
        show(ss + ss); //int:2 class java.lang.Integer
        show(ss + ii); //int:2 class java.lang.Integer
        show(ss + ll); //long:2 class java.lang.Long
        show(ss + ff); //float:2.0 class java.lang.Float
        show(ss + dd); //double:2.0 class java.lang.Double

Integer

        show(ii + bb); //int:2 class java.lang.Integer
        show(ii + cc); //int:66 class java.lang.Integer
        show(ii + ss); //int:2 class java.lang.Integer
        show(ii + ii); //int:2 class java.lang.Integer
        show(ii + ll); //long:2 class java.lang.Long
        show(ii + ff); //float:2.0 class java.lang.Float
        show(ii + dd); //double:2.0 class java.lang.Double

Long

        show(ll + bb); //long:2 class java.lang.Long
        show(ll + cc); //long:66 class java.lang.Long
        show(ll + ss); //long:2 class java.lang.Long
        show(ll + ii); //long:2 class java.lang.Long
        show(ll + ll); //long:2 class java.lang.Long
        show(ll + ff); //float:2.0 class java.lang.Float
        show(ll + dd); //double:2.0 class java.lang.Double

Float

        show(ff + bb); //float:2.0 class java.lang.Float
        show(ff + cc); //float:66.0 class java.lang.Float
        show(ff + ss); //float:2.0 class java.lang.Float
        show(ff + ii); //float:2.0 class java.lang.Float
        show(ff + ll); //float:2.0 class java.lang.Float
        show(ff + ff); //float:2.0 class java.lang.Float
        show(ff + dd); //double:2.0 class java.lang.Double

Double

        show(dd + bb); //double:2.0 class java.lang.Double
        show(dd + cc); //double:66.0 class java.lang.Double
        show(dd + ss); //double:2.0 class java.lang.Double
        show(dd + ii); //double:2.0 class java.lang.Double
        show(dd + ll); //double:2.0 class java.lang.Double
        show(dd + ff); //double:2.0 class java.lang.Double
        show(dd + dd); //double:2.0 class java.lang.Double

结论如下表:

类型ByteCharacterShortIntegerLongFloatDouble
Byteintintintintlongflaotdouble
Characterintintintintlongflaotdouble
Shortintintintintlongflaotdouble
Integerintintintintlongflaotdouble
Longlonglonglonglonglongflaotdouble
Floatflaotflaotflaotflaotflaotflaotdouble
Doubledoubledoubledoubledoubledoubledoubledouble

研究==和equals

== 比较的值类型大小和引用对象的引用值(可以理解为指针)
equals比较的对象的值时候相等

        Boolean b1 = new Boolean(false);
        Boolean b2 = new Boolean(false);
        System.out.println(System.identityHashCode(true)); //621009875
        System.out.println(System.identityHashCode(true)); //621009875
        System.out.println(System.identityHashCode(false)); //1265094477
        System.out.println(System.identityHashCode(false)); //1265094477
        System.out.println(System.identityHashCode(b1)); //2125039532
        System.out.println(System.identityHashCode(b2)); //312714112

        System.out.println(b1 == b2); //false
        System.out.println(b1.equals(b2)); //true
        System.out.println(b1 == false);   //true
        System.out.println(b2 == false);   //true

这里打印的 System.out.println(System.identityHashCode(true))和System.out.println(System.identityHashCode(false))两个为啥两两相等?因为默认装箱,最终打印的Boolean中的默认的对象,相当于与是同一个对象,它的identityHashCode值当然相等了。

    /**
     * The {@code Boolean} object corresponding to the primitive
     * value {@code true}.
     */
    public static final Boolean TRUE = new Boolean(true);

    /**
     * The {@code Boolean} object corresponding to the primitive
     * value {@code false}.
     */
    public static final Boolean FALSE = new Boolean(false);

那为啥 System.out.println(System.identityHashCode(b1)); 和System.out.println(System.identityHashCode(b2)); //312714112 又不相等?
这两的b1和b2是不同的对象,虽然他们的值相等,但是在内存中并不是同一块区域,所以identityHashCode的值不相等

基本类型的缓存

ByteCache

    [-128,127]
    private static class ByteCache {
        private ByteCache(){}

        static final Byte cache[] = new Byte[-(-128) + 127 + 1];

        static {
            for(int i = 0; i < cache.length; i++)
                cache[i] = new Byte((byte)(i - 128));
        }
    }

CharacterCache

    [0,127]
    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);
        }
    }

ShortCache

    [-128,127]
    private static class ShortCache {
        private ShortCache(){}

        static final Short cache[] = new Short[-(-128) + 127 + 1];

        static {
            for(int i = 0; i < cache.length; i++)
                cache[i] = new Short((short)(i - 128));
        }
    }

IntegerCache

    //range [-128, 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() {}
    }

LongCache

    //[-128,127]
    private static class LongCache {
        private LongCache(){}

        static final Long cache[] = new Long[-(-128) + 127 + 1];

        static {
            for(int i = 0; i < cache.length; i++)
                cache[i] = new Long(i - 128);
        }
    }

Float和Double没有缓存

测试缓存

        Integer i1 = 1;//装箱为引用类型
        Integer i2 = 1;//装箱为引用类型
        Integer i3 = new Integer(1);
        Integer i4 = new Integer(1);
        int i5 = i3;//拆箱为数值类型
        int i6 = i4;//拆箱为数值类型
        System.out.println(System.identityHashCode(i1)); //621009875
        System.out.println(System.identityHashCode(i2)); //621009875       i1 和 i2 相等,装箱复用了Integer中的缓存对象
        System.out.println(System.identityHashCode(i3)); //1265094477
        System.out.println(System.identityHashCode(i4)); //2125039532      i3 和 i4不相等,生成了新对象
        System.out.println(System.identityHashCode(i5)); //621009875
        System.out.println(System.identityHashCode(i6)); //621009875        i1 和 i2 相等,装箱复用了Integer中的缓存对象
        System.out.println(System.identityHashCode(127)); //312714112
        System.out.println(System.identityHashCode(127)); //312714112       相等,装箱复用了Integer中的缓存对象
        System.out.println(System.identityHashCode(128)); //692404036
        System.out.println(System.identityHashCode(128)); //1554874502      装箱,但是不在缓存对象范围内,所以不相等
        System.out.println(System.identityHashCode(-128)); //1846274136
        System.out.println(System.identityHashCode(-128)); //1846274136     相等,装箱复用了Integer中的缓存对象

        System.out.println(System.identityHashCode(-129)); //1639705018
        System.out.println(System.identityHashCode(-129)); //1627674070     装箱,但是不在缓存对象范围内,所以不相等

        System.out.println(i1 == i2); //true     同一对象,应用地址相等
        System.out.println(i1.equals(i2));//true  相等

        System.out.println(i1 == i3);//false     不同对象,false
        System.out.println(i1.equals(i3));//true  比较数值相等
 
        System.out.println(i5 == i6);//true   数值类型,比较数值大小
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值