java中什么是手动装箱、手动拆箱、自动装箱和自动拆箱以及128陷阱

一、手动装箱和手动拆箱

  1. 手动装箱(Manual Boxing):指的是程序员通过调用包装类的构造函数或静态工厂方法,将基本数据类型转换为对应的包装类对象的过程。例如,通过调用Integer类的构造函数或valueOf()方法实现整数类型的装箱。
    // 手动装箱示例
    int intValue = 10;
    Integer integerValue = new Integer(intValue); // 使用构造函数进行装箱
    // 或者
    Integer integerValue = Integer.valueOf(intValue); // 使用静态工厂方法进行装箱
    
  2. 手动拆箱(Manual Unboxing):指的是程序员通过调用包装类的方法,将包装类对象转换为对应的基本数据类型的过程。例如,通过调用xxxValue()方法实现包装类对象到基本数据类型的拆箱。
    // 手动拆箱示例
    Integer integerValue = 10;
    int intValue = integerValue.intValue(); // 使用intValue()方法进行拆箱
    

    手动装箱和手动拆箱与自动装箱和自动拆箱相对应,区别在于手动操作需要程序员显式地调用相应的方法来进行类型转换,而自动操作则是由编译器自动完成的。通常情况下,推荐使用自动装箱和自动拆箱,因为它们可以减少代码的冗余和提高代码的可读性。

二、自动装箱和自动拆箱

  1. 自动装箱(Autoboxing):将基本数据类型自动转换为对应的包装类对象。例如,将int转换为Integer、double转换为Double等。在源码中,当我们将基本数据类型赋值给对应的包装类对象时,编译器会自动调用valueOf()方法进行装箱操作。
    // 自动拆箱示例
    Integer integerValue = 10;
    int intValue = integerValue; // 自动拆箱
    

    在源码中,自动拆箱的实现主要通过调用包装类的xxxValue()方法来完成,例如Integer类的intValue()方法:

    public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }
    
  2. 自动拆箱(Unboxing):将包装类对象自动转换为对应的基本数据类型。例如,将Integer转换为int、Double转换为double等。在源码中,当我们将包装类对象赋值给基本数据类型时,编译器会自动调用xxxValue()方法进行拆箱操作。
    // 自动拆箱示例
    Integer integerValue = 10;
    int intValue = integerValue; // 自动拆箱
    

    在源码中,自动拆箱的实现主要通过调用包装类的xxxValue()方法来完成,例如Integer类的intValue()方法:

    public int intValue() {
        return value;
    }
    

    总的来说,自动装箱和自动拆箱使得在基本数据类型和包装类之间的转换更加便捷,编码更加简洁。这些特性的实现是通过编译器在编译期间自动插入相应的装箱和拆箱代码来实现的。

三、128陷阱

        128陷阱 是指在 Java 中,当比较 Integer 类型的数据时,有时候会发现两个明明相同的值,最后比较的结果为 false 。这是因为在 Java 中, Integer 是数据类型 int 的封装类。Java 设计者认为大家对数的使用大多在100以内,因此规定在-128至127之间的 Integer 类型的变量,直接指向常量池中的缓存地址,不会 new 开辟出新的空间。

下面提供一个示例,展示 128陷阱 :

public class IntegerComparisonExample {
    public static void main(String[] args) {
        Integer a = 127;
        Integer b = 127;
        Integer c = 128;
        Integer d = 128;
        Integer cc = 1000;
        Integer dd = 1000;
        System.out.println((a == b));
        System.out.println((c == d));
        System.out.println((cc == dd));
        System.out.println("----------------");
        System.out.println((a.equals(b)));
        System.out.println((c.equals(d)));
        System.out.println((cc.equals(dd)));
    }
}

        在上述代码中,定义了六个 Integer 类型的对象,分别是 a 、 b 、 c 、 d 、 cc 和 dd 。通过 == 运算符比较它们的值,可以发现 a 和 b 的值相等,返回 true 。而 c 和 d 的值相等,返回 false 。这是因为 c 和 d 的值为128,自动装箱时超出了常量池的范围,创建了新的对象,因此它们的地址不同。使用 equals() 方法比较它们的值,结果都是 true ,因为 equals() 方法比较的是对象的值,而不是对象的地址。

        这是因为,在Integer的valueOf()方中,当数值在-128-127之间时,数值都存储在有一个catch数组当中,该数组相当于一个缓存,当我们在-128-127之间进行自动装箱的时候,我们就直接返回该值在内存当中的地址,所以在-128-127之间的数值用==进行比较是相等的。

如何避免128陷阱

       为了避免 Integer 128陷阱 ,推荐使用 equals 方法进行比较,因为 equals 方法比较的是对象的内容,而不是引用。下面提供一个具体示例:

public class IntegerComparisonExample {
    public static void main(String[] args) {
        Integer a = 127;
        Integer b = 127;
        Integer c = 128;
        Integer d = 128;
        System.out.println((a == b));
        System.out.println((c == d));
        System.out.println("----------------");
        System.out.println((a.equals(b)));
        System.out.println((c.equals(d)));
    }
}

        在上述代码中,定义了四个 Integer 类型的对象,分别是 a 、 b 、 c 和 d 。通过 == 运算符比较它们的值,可以发现 a 和 b 的值相等,返回 true 。而 c 和 d 的值相等,返回 false 。这是因为 c 和 d 的值为128,自动装箱时超出了常量池的范围,创建了新的对象,因此它们的地址不同。使用 equals() 方法比较它们的值,结果都是 true ,因为 equals() 方法比较的是对象的值,而不是对象的地址。

  • 26
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值