zoukankan      html  css  js  c++  java
  • 基本类型和装箱基本类型的区别

          上篇博文int和Integer之间的区别和联系,是试验的结果,当我看了一下《Effective Java 中文版第2版》中的介绍之后,我发现自己写漏了一些东西,为了加深印象,提高自己的认知,我又做了一下试验,在此记上一笔,以备后用。另外,我发现将编译以后的例子,对照起来看,更加容易明白为什么是这样而不是那样,所以,我们就将编译后的代码栗子也贴出来对照看看吧!

    1:此例用来表明——基本类型和装箱基本类型具有的属性有所不同,基本类型只有值,而装箱基本类型则具有与他们的值不同的同一性。

    import java.util.Comparator;
    
    /**
     * Created by qianyingjie1 on 2017/2/13.
     */
    public class IntegerComparator {
        public static void main(String[] args){
            Comparator<Integer> naturalOrder = new Comparator<Integer>(){
                public int compare(Integer first,Integer second){
                    return first<second ? -1 :(first == second ? 0 : 1);
                }
            };
            //1,注意,这里是错误的,原因是因为对于装箱基本类型运用==操作符几乎总是错误的
            System.out.println(naturalOrder.compare(new Integer(99),new Integer(99)));
    
            Comparator<Integer> naturalOrder_ = new Comparator<Integer>(){
                public int compare(Integer first,Integer second){
                    int f=first;//自动拆箱
                    int s=second;//自动拆箱
                    System.out.println("first==f is : "+(first==f));//当基本类型和装箱基本类型使用==比较的时候会做拆箱处理的
                    return f<second ? -1 :(f == s ? 0 : 1);
                }
            };
            //0,我们做了自动拆箱的处理,只比较我们关心的整数值之间的大小关系
            System.out.println(naturalOrder_.compare(new Integer(99),new Integer(99)));
            /**
             * 结论1:
             * 基本类型只有值,而装箱基本类型则具有与他们的值不同的同一性。简单点讲就是,基本类型只有值,是什么值就是什么值没有别的
             * 即使声明的时候没有赋值,系统也会默认的给他一个默认值0。而装箱基本类型不同,两个装箱基本类型可以具有相同的值,并且还
             * 可以有不同的同一性,比:他们的引用地址不同。
             */
        }
    }
    当基本类型和装箱基本类型使用==比较的时候会做拆箱处理的
    import java.util.Comparator;
    
    public class IntegerComparator {
        public IntegerComparator() {
        }
    
        public static void main(String[] args) {
            Comparator naturalOrder = new Comparator() {
                public int compare(Integer first, Integer second) {
                    return first.intValue() < second.intValue()?-1:(first == second?0:1);
                }
            };
            System.out.println(naturalOrder.compare(new Integer(99), new Integer(99)));
            Comparator naturalOrder_ = new Comparator() {
                public int compare(Integer first, Integer second) {
                    int f = first.intValue();
                    int s = second.intValue();
                    System.out.println("first==f is : " + (first.intValue() == f));//看这里上面的结论是不是很好理解了
                    return f < second.intValue()?-1:(f == s?0:1);
                }
            };
            System.out.println(naturalOrder_.compare(new Integer(99), new Integer(99)));
        }
    }

    上面代码段执行的输出结果

    "C:Program FilesJavajdk1.7.0_71injava" -Didea.launcher.port=7533 "-Didea.launcher.bin.path=C:Program Files (x86)JetBrainsIntelliJ IDEA 2016.1.3in" -Dfile.encoding=UTF-8 -classpath "C:Program FilesJavajdk1.7.0_71jrelibcharsets.jar;C:Program FilesJavajdk1.7.0_71jrelibdeploy.jar;C:Program FilesJavajdk1.7.0_71jrelibextaccess-bridge-64.jar;C:Program FilesJavajdk1.7.0_71jrelibextdnsns.jar;C:Program FilesJavajdk1.7.0_71jrelibextjaccess.jar;C:Program FilesJavajdk1.7.0_71jrelibextlocaledata.jar;C:Program FilesJavajdk1.7.0_71jrelibextsunec.jar;C:Program FilesJavajdk1.7.0_71jrelibextsunjce_provider.jar;C:Program FilesJavajdk1.7.0_71jrelibextsunmscapi.jar;C:Program FilesJavajdk1.7.0_71jrelibextzipfs.jar;C:Program FilesJavajdk1.7.0_71jrelibjavaws.jar;C:Program FilesJavajdk1.7.0_71jrelibjce.jar;C:Program FilesJavajdk1.7.0_71jrelibjfr.jar;C:Program FilesJavajdk1.7.0_71jrelibjfxrt.jar;C:Program FilesJavajdk1.7.0_71jrelibjsse.jar;C:Program FilesJavajdk1.7.0_71jrelibmanagement-agent.jar;C:Program FilesJavajdk1.7.0_71jrelibplugin.jar;C:Program FilesJavajdk1.7.0_71jrelib
    esources.jar;C:Program FilesJavajdk1.7.0_71jrelib
    t.jar;D:workspace_testhello-worldoutproductionhello-world;C:Program Files (x86)JetBrainsIntelliJ IDEA 2016.1.3libidea_rt.jar" com.intellij.rt.execution.application.AppMain com.jd.test.autoInteger.IntegerComparator
    1
    first==f is : true
    0
    
    Process finished with exit code 0

    2:此例表明——装箱基本类型的默认值是null,但是int的默认值是0,并且int类型的变量不能赋值为null

    /**
     * Created by qianyingjie1 on 2017/2/13.
     */
    public class IntegerAutoUnboxing {
        static Integer i;
        static int i_;
        public static void main(String[] args){
            /**
             * i_默认是0,所以能够进入并且打印 99!=i_ is true
             */
            if(99!=i_){
                System.out.println("99!=i_ is true");
            }
            /**
             * i默认是null,按照预想的应该可以进入并且打印 99!=i is true,但是没有而且抛出来了一个空指针异常
             * 原因是因为:当在一项操作中混合使用基本类型和装箱基本类型时,装箱基本类型就会自动拆箱。如果null对象
             * 引用被自动拆箱,就会得到一个NullPointerException异常。修正的方式如上所示,声明i是个int而不是Integer
             */
            if(99!=i){
                System.out.println("99!=i is true");
            }
            /**
             * 结论2:
             *基本类型只有功能完备的值,而每个装箱基本类型除了它对应的基本类型的所有功能之外,还有一个非功能值null
             */
        }
    }
    当基本类型和装箱基本类型使用!=比较的时候也会做拆箱处理的,但是装箱基本类型的默认值是null,所以当心会报空指针异常的
    public class IntegerAutoUnboxing {
        static Integer i;
        static int i_;
    
        public IntegerAutoUnboxing() {
        }
    
        public static void main(String[] args) {
            if(99 != i_) {
                System.out.println("99!=i_ is true");
            }
    
            if(99 != i.intValue()) {//看这里,报空指针异常是不是挺好理解的
                System.out.println("99!=i is true");
            }
    
        }
    }

    上面代码段执行的输出结果

    "C:Program FilesJavajdk1.7.0_71injava" -Didea.launcher.port=7535 "-Didea.launcher.bin.path=C:Program Files (x86)JetBrainsIntelliJ IDEA 2016.1.3in" -Dfile.encoding=UTF-8 -classpath "C:Program FilesJavajdk1.7.0_71jrelibcharsets.jar;C:Program FilesJavajdk1.7.0_71jrelibdeploy.jar;C:Program FilesJavajdk1.7.0_71jrelibextaccess-bridge-64.jar;C:Program FilesJavajdk1.7.0_71jrelibextdnsns.jar;C:Program FilesJavajdk1.7.0_71jrelibextjaccess.jar;C:Program FilesJavajdk1.7.0_71jrelibextlocaledata.jar;C:Program FilesJavajdk1.7.0_71jrelibextsunec.jar;C:Program FilesJavajdk1.7.0_71jrelibextsunjce_provider.jar;C:Program FilesJavajdk1.7.0_71jrelibextsunmscapi.jar;C:Program FilesJavajdk1.7.0_71jrelibextzipfs.jar;C:Program FilesJavajdk1.7.0_71jrelibjavaws.jar;C:Program FilesJavajdk1.7.0_71jrelibjce.jar;C:Program FilesJavajdk1.7.0_71jrelibjfr.jar;C:Program FilesJavajdk1.7.0_71jrelibjfxrt.jar;C:Program FilesJavajdk1.7.0_71jrelibjsse.jar;C:Program FilesJavajdk1.7.0_71jrelibmanagement-agent.jar;C:Program FilesJavajdk1.7.0_71jrelibplugin.jar;C:Program FilesJavajdk1.7.0_71jrelib
    esources.jar;C:Program FilesJavajdk1.7.0_71jrelib
    t.jar;D:workspace_testhello-worldoutproductionhello-world;C:Program Files (x86)JetBrainsIntelliJ IDEA 2016.1.3libidea_rt.jar" com.intellij.rt.execution.application.AppMain com.jd.test.autoInteger.IntegerAutoUnboxing
    Exception in thread "main" java.lang.NullPointerException
        at com.jd.test.autoInteger.IntegerAutoUnboxing.main(IntegerAutoUnboxing.java:21)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:606)
        at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
    99!=i_ is true
    
    Process finished with exit code 1

    3:此例表明——基本类型通常比装箱基本类型更节省时间和空间,当变量被反复的装箱和拆箱,会导致明显的性能下降。

    public class IntegerAutoBoxing {
        public static void main(String args []){
            //定义求和的变量
            Long sum = 0L;
            long sum_ = 0;
            //定义循环的次数,方便比较各个循环量的差异
            long cycleCount = Integer.MAX_VALUE;
            //计算的开始计算
            long startTime = System.currentTimeMillis();
    
            //变量被反复的装箱和拆箱是的效率
            for(long i=0;i<cycleCount;i++){
                sum+=i;
            }
            System.out.println("sum  is : "+ sum +"   此次循环"+cycleCount+"次,所用的时间为:"+(System.currentTimeMillis()-startTime));
    
            //变量没被反复的装箱和拆箱是的效率
            startTime = System.currentTimeMillis();
            for(long i=0;i<cycleCount;i++){
                sum_+=i;
            }
            System.out.println("sum_ is : "+ sum_ +"   此次循环"+cycleCount+"次,所用的时间为:"+(System.currentTimeMillis()-startTime));
            /**
             * 结论3:
             * 基本类型通常比装箱基本类型更节省时间和空间,当变量被反复的装箱和拆箱,会导致明显的性能下降。
             * 因为当程序装箱了基本类型的值是,导致高的开销和不必要的对象创建
             */
        }
    }

    基本类型和装箱基本类型之间,自动的拆箱和装箱是需要消耗性能的

    public class IntegerAutoBoxing {
        public IntegerAutoBoxing() {
        }
    
        public static void main(String[] args) {
            Long sum = Long.valueOf(0L);
            long sum_ = 0L;
            long cycleCount = 2147483647L;
            long startTime = System.currentTimeMillis();
    
            long i;
            for(i = 0L; i < cycleCount; ++i) {
                sum = Long.valueOf(sum.longValue() + i);//看这里,输出的性能有差异,从这里是不是得到了充分的理解了
            }
    
            System.out.println("sum  is : " + sum + "   此次循环" + cycleCount + "次,所用的时间为:" + (System.currentTimeMillis() - startTime));
            startTime = System.currentTimeMillis();
    
            for(i = 0L; i < cycleCount; ++i) {
                sum_ += i;
            }
    
            System.out.println("sum_ is : " + sum_ + "   此次循环" + cycleCount + "次,所用的时间为:" + (System.currentTimeMillis() - startTime));
        }
    }

    上面代码段执行的输出结果,同时我们也看到,他们的性能差别还是挺大的

    "C:Program FilesJavajdk1.7.0_71injava" -Didea.launcher.port=7533 "-Didea.launcher.bin.path=C:Program Files (x86)JetBrainsIntelliJ IDEA 2016.1.3in" -Dfile.encoding=UTF-8 -classpath "C:Program FilesJavajdk1.7.0_71jrelibcharsets.jar;C:Program FilesJavajdk1.7.0_71jrelibdeploy.jar;C:Program FilesJavajdk1.7.0_71jrelibextaccess-bridge-64.jar;C:Program FilesJavajdk1.7.0_71jrelibextdnsns.jar;C:Program FilesJavajdk1.7.0_71jrelibextjaccess.jar;C:Program FilesJavajdk1.7.0_71jrelibextlocaledata.jar;C:Program FilesJavajdk1.7.0_71jrelibextsunec.jar;C:Program FilesJavajdk1.7.0_71jrelibextsunjce_provider.jar;C:Program FilesJavajdk1.7.0_71jrelibextsunmscapi.jar;C:Program FilesJavajdk1.7.0_71jrelibextzipfs.jar;C:Program FilesJavajdk1.7.0_71jrelibjavaws.jar;C:Program FilesJavajdk1.7.0_71jrelibjce.jar;C:Program FilesJavajdk1.7.0_71jrelibjfr.jar;C:Program FilesJavajdk1.7.0_71jrelibjfxrt.jar;C:Program FilesJavajdk1.7.0_71jrelibjsse.jar;C:Program FilesJavajdk1.7.0_71jrelibmanagement-agent.jar;C:Program FilesJavajdk1.7.0_71jrelibplugin.jar;C:Program FilesJavajdk1.7.0_71jrelib
    esources.jar;C:Program FilesJavajdk1.7.0_71jrelib
    t.jar;D:workspace_testhello-worldoutproductionhello-world;C:Program Files (x86)JetBrainsIntelliJ IDEA 2016.1.3libidea_rt.jar" com.intellij.rt.execution.application.AppMain com.jd.test.autoInteger.IntegerAutoBoxing
    sum  is : 2305843005992468481   此次循环2147483647次,所用的时间为:10338
    sum_ is : 2305843005992468481   此次循环2147483647次,所用的时间为:1033
    
    Process finished with exit code 0

    总结论

            /**
             * 总结论:
             * 1:基本类型优于装箱基本类型,因为,基本类型更简单、更快速。
             *
             * 2:下面的情况下,才优先使用装箱基本类型
             * 2-1:当作为集合中的元素、键、值时
             * 2-2:在进行反射的方法调用时
             *
             * 3:当必须使用装箱基本类型的时候需要注意一下几点
             * 3-1:比较对象的值是否相等,不能使用==一定要使用equals
             * 3-2:当程序进行涉及装箱和拆箱基本类型的混合类型计算是,它会进行拆箱,当程序进行拆箱时,可能会抛出空指针异常。
             * 3-3:当程序装箱了基本类型值时,会导致高开销和不必要的对象创建。
             */
  • 相关阅读:
    C# 根据主窗体的位置弹窗信息窗体一直保持在主窗体中间
    c# winForm父子窗口 通过委托进行信息传递
    使用devexpress插件 消除运行时弹窗
    C# 获取当前时间戳
    WinForm实现Loading等待界面
    转载 C#设置控件 Enabled 为 false 时背景色不改变
    DEV gridView中加入加载条显示进度,必须为圆角型
    winfrom 圆角化
    列表元素的反转、排序——python
    使用for循环和while循环打印九九乘法表——python
  • 原文地址:https://www.cnblogs.com/godtrue/p/6413195.html
Copyright © 2011-2022 走看看