第四十九条 基本类型优先于装箱基本类型

本文深入探讨Java中装箱类型的特性,包括其与基本类型的差异、自动装箱和拆箱的功能,以及在实际编程中可能导致的陷阱,如比较时的引用地址误判和性能消耗问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Java系统数据方面,分两种类型,一种是八大基本类型,包括 int long short 等,另一种是对象引用类型,如 String List 自定义的对象等等。八大基本类型都有一个对应的引用类型,称为装箱基本类型,例如 int double boolean 对应的装箱类型是 Interger Double Boolean。 Java 1.5 版本后,增加了自动装箱和自动拆箱功能,比如List里不能直接add() int类型,但自动装箱后, add(0)时,会自动把 int 装箱为 Interger ,0 由int类型变为了对象0,装进了List集合。基本类型和装箱基本类型有几点区别: 基本类型只有值,装箱基本类型不但有基本类型的值,它还有一个引用地址值,所以相同值的两个装箱基本类型的引用值可能不一样;装箱类型由于是对象,所以可能为 null;基本类型比装箱基本类型节省时间与空间。使用的时候一定要小心。举个例子,平常用于比较数据大小而进行排序,会用到Comparator,如果把 Interger 传进去,那么

    void test(){
        Comparator<Integer> naturalOrder = new Comparator<Integer>() {
            public int compare(Integer first, Integer second) {
                return first < second ? -1 : (first == second ? 0 : 1);
            }
        };

        int compare = naturalOrder.compare(new Integer(42), new Integer(42));
        System.out.println(compare);
    }

猛一看,没问题,测试一下,发现打印的compare 值为1而非0,说明第一个Integer大于第二个Integer。为什么呢,first < second 这个比较比的是int值,但 first == second 这个比较的就不是 int 值了,而是比较的对象引用的地址值,由于这是两个不同的对象所以返回了false导致 compare 返回的是1,可见,装箱类型可以认为是对象,不同的对象有不同的地址值。上面代码修改,把Integer值转换为int值,再进行比较,就正确了。

    void test1(){
        Comparator<Integer> naturalOrder2 = new Comparator<Integer>() {
            public int compare(Integer first, Integer second) {
                int i = first;
                int j = second;
                return i < j ? -1 : (i == j ? 0 : 1);
            }
        };
        int compare = naturalOrder2.compare(new Integer(42), new Integer(42));
        System.out.println(compare);
    }

由此引发另一个问题,如果说装箱基本类型有引用的话,如果没有赋值,直接使用会是什么情况呢?

    static Integer i;

    void test2(){
        if(42 == i)
            System.out.println("Unbelievable");
    }

它没打印出Unbelievable,而是直接NullPointException了,为什么String和List等对象没初始化,进行 == 操作都没事,而这个出问题了呢? 原来 Integer 没有初始化,但 (i == 42) 时,会自动拆箱, 把 Integer 变为 int 类型进行比较,结果这时候对 null 做了拆箱,当然就 Exception in thread "main" java.lang.NullPointerException了。

之前提到一个性能问题,自动装箱比基本类型操作要消耗大得多

    void test3(){
        Long sum = 0L;
        for(long i = 0; i < Integer.MAX_VALUE; i++) {
            sum += i;
        }
        System.out.println(sum);
    }

运行比较慢,是因为初始值 sum 为 Long类型,之后相加,都会自动装箱,所以明显的性能下降,因为反复的被装箱和拆箱。所以,慎用装箱基本类型。
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值