zoukankan      html  css  js  c++  java
  • 拆箱与装箱

    一、何为包装类型

    Java是一种面向对象的语言,但是它不是纯面向对象的。Java中存在基本数据类型,谈不上对象。为了向纯面向对象靠拢,Java5的时候推出了基本数据类型的包装类型。

    基本数据类型与包装类型的对应关系如下: 

     


    二、何为装箱与拆箱

    装箱就是将基本数据类型转化为包装类型,那么拆箱就是将包装类型转化为基本数据类型。

    以基本数据类型int为例:

    package day1119;
     
    public class TestBox {
        public static void main(String[] args) {
            //自动装箱,底层其实执行了Integer a=Integer.valueOf(1);
            Integer a = 1;
            //自动拆箱,底层其实执行了int b=a.intValue();
            int b = a;
        }
    }
    

      

    Integer的valueOf(int i)方法可以将一个基本数据类型转化为对应的包装类型,即装箱方法。

    而Integer的intValue()方法则可以将一个包装类型转化为对应的基本数据类型,即拆箱方法。


    三、装箱与自动装箱的区别

    装箱:利用Integer的构造方法Integer(int value),即Integer c=new Integer(1);

    自动装箱:或者叫隐式装箱,直接给Integer赋值,即Integer d=1,在编译的时候,会调用Integer.valueOf()方法完成装箱。

    相比而言,自动装箱可能比装箱具有更高的效率,体现在自动装箱的缓存上,下面从几道题目来讲自动装箱的缓存。


    四、相关面试题目

    第一题:以下代码的输出结果为?(==号两边如果都是引用类型的话,则判断它们是否指向同一个对象。如果都是基本数据类型的话,则判断它们的数值是否相等)

    package day1119;
     
    public class TestBox2 {
        public static void main(String[] args) {
            Integer a = 100;
            Integer b = 100;
            Integer c = 200;
            Integer d = 200;
            System.out.println(a == b);
            System.out.println(c == d);
        }
    }
    

      

    也许有些人认为他们是四个各不相同的对象,两个式子都返回false。

    实际运行后发现输出:

     

    刚才我们知道,Integer a=100这条语句会触发自动装箱,而自动装箱的方法为Integer.valueOf()方法,让我们去寻找这个方法,一探究竟。

    观察Integer类的源码中的valueOf()

        /**
         * Returns an {@code Integer} instance representing the specified
         * {@code int} value.  If a new {@code Integer} instance is not
         * required, this method should generally be used in preference to
         * the constructor {@link #Integer(int)}, as this method is likely
         * to yield significantly better space and time performance by
         * caching frequently requested values.
         *
         * This method will always cache values in the range -128 to 127,
         * inclusive, and may cache other values outside of this range.
         *
         * @param  i an {@code int} value.
         * @return an {@code Integer} instance representing {@code i}.
         * @since  1.5
         */
        public static Integer valueOf(int i) {
            if (i >= IntegerCache.low && i <= IntegerCache.high)
                return IntegerCache.cache[i + (-IntegerCache.low)];
            return new Integer(i);
        }
    

      

    可以看得出,当i的值位于[-128,127]的时候,会直接返回Integer缓存数组中相应对象的引用,如果i大于127或小于-128,会重新创建一个Integer实例,并返回。

    那么第一条式子a和b的值都在缓存范围内,因此他们指向同一个对象,因此返回true。c和d的值不在范围内,都是通过new创建出来的,因此不是同一个对象,返回false。

    注意:Byte、Short、Integer、Long、Character的valueOf()实现机制类似。

    其中相同值的Byte比较永远返回true,因为byte取值范围就是[-128,127]。

    Short、Integer、Long的valueOf()基本一样,i的范围都需要在[-128,127]。

    Character中i的范围只要小于等于127即可,因为char最小值为0,本来就大于等于-128。

    但是Float、Double中的valueOf(),永远返回新创建的对象,因为一个范围内的整数是有限的,但是小数却是无限的,无法保存在缓存中。

    Boolean中只有两个对象,要么是true的Boolean,要么是false的Boolean,只要boolean的值相同,Boolean就相等。


    第二题:以下代码的输出结果为?

    package day1119;
     
    public class TestBox3 {
        public static void main(String[] args) {
            Integer a = 1;
            Integer b = 2;
            Integer c = 3;
            Long d = 2L;
            Long e = 3L;
            int f = 2;
     
            //一旦有包装类型和数值类型判断==时,则触发包装类型的自动拆箱,转为数值类型的比较
            System.out.println(new Integer(300) == 300);//返回true
     
            //一旦有包装类型和数值类型发生运算时,则触发包装类型的自动拆箱,转为数值类型的运算
            System.out.println(c == (a + f));//返回true
     
            //一旦有包装类型和包装类型发生运算时,则触发包装类型的自动拆箱,转为数值类型的运算
            System.out.println(c == (a + b));//返回true
     
            //只有对象类型才有equals方法,因此首先a,b触发包装类型的自动拆箱,转为数值类型的运算。
            //运算完,再将结果3自动装箱,Integer重写了equals,因此可以转为包装类型与包装类型的比较。
            //当两边的包装类型不一致时,必定返回false。
            //当两边的包装类型一致时,再进行拆箱,判断两者代表的数值是否相等。
            System.out.println(c.equals(a + b));//返回true
     
            //不同数据类型的数值进行运算,首先会将低精度的数据类型转化为高精度的数据类型,即自动类型转换。
            //比如现在的int+long,会提升到long+long,再进行运算。
            System.out.println(e == (a + d));//返回true
     
            //==号两边类型不一致时,直接执行自动拆箱,比较之后的数值
            System.out.println(e == (a + b));//返回true
     
            //依次经历自动拆箱,自动类型转换、运算、自动装箱,类型比较,拆箱,数值比较
            System.out.println(e.equals(a + d));//返回true
     
            //依次经历自动拆箱,自动类型转换、运算、自动装箱,类型比较,两边类型不一致,直接返回false
            System.out.println(c.equals(a + d));//返回false
     
     
        }
    }
    

      

  • 相关阅读:
    C语言II作业01
    C语言寒假大作战04
    C语言寒假大作战03
    C语言寒假大作战02
    C语言寒假大作战01
    C语言I博客作业12—学期总结
    第一次作业
    C语言I博客作业02
    C语言I博客作业11
    C语言||作业01
  • 原文地址:https://www.cnblogs.com/xinruyi/p/13592262.html
Copyright © 2011-2022 走看看