自动装箱与自动拆箱

一、前言

提到自动装箱与自动拆箱就要先说对象包装器

指路个人博客

对象包装器

Java 有八种基本类型,可以简单地进行数据处理。但是由于 Java 是面向对象语言,而八种基本数据类型不支持面向对象编程,比如使用集合时,是无法将 int 这种基本类型放进去的,为了方便开发,Java 针对每个基本类型设计了对应的对象包装器(wrapper)。

基本数据类型对象包装器
byteByte
shortShort
intInteger
longLong
floatFloat
doubleDouble
charCharacter
booleanBoolean

我们要注意:

  • 一旦构造了包装器,不允许更改包装器中的值。
  • 对象包装器类不能定义子类。

可以简单看一下 Integer 源码找一下原因:

public final class Integer extends Number implements Comparable<Integer> {

可以看到 Integer 类使用 final 修饰,所以不能被继承,也就不能有子类。

我们继续看 Integer 的构造器:

    public Integer(int value) {
        this.value = value;
    }

看到包装器中的值使用 value 存储的,我们再看一下 value 的定义:

    private final int value;

可以看到 value 是使用 final 修饰的,所以包装器类一旦创建对象,里面的值不能改变。

二、自动装箱与自动拆箱

基本类型比如 int 自动的转化为包装器类型比如 Integer 称为自动装箱(autoboxing)

相反的,将包装器类型比如 Integer 自动转化为 int 类型,称为自动拆箱(autounboxing)

那么什么时候会发生自动拆箱与自动装箱呢?

自动装箱与自动装箱何时发生

将一个基本类型赋值给对象包装器对象,就会发生自动装箱。比如:

        List<Integer> list = new ArrayList<>();
        // 此处发生自动装箱:相当于 list.add(Integer.valueOf(3))
        list.add(3);

将一个包装器对象赋值给基本类型,就会发生自动拆箱。比如:

        List<Integer> list = new ArrayList<>();
        // 此处发生自动装箱:相当于 list.add(Integer.valueOf(3))
        list.add(3);
        // 此处发生自动拆箱:相当于 list.get(0).intValue();
        list.get(0);

算术表达式也可以发生自动装箱与自动拆箱操作,比如自增与自减操作:

		Integer n = 3;
        // n 先自动拆箱,做完减法后,自动装箱
        n--;

如果在一个条件表达式中混合使用 Integer 和 Double 类型,Integer 值就会自动拆箱,转化为 double,再自动装箱提升为 Double 值。

        Integer a = 1;
        Double b = 2.0;
        // 1.0
        System.out.println(true? a : b);

三、对象包装器对象之间的比较

由于自动装箱和自动拆箱,使我们觉得对象包装器对象之间的比较,好像使用 == 运算符也可以,== 运算符运用在对象之间,实际是比较对象是否指向同一个内存区域。那么我们猜测一下,下面代码运行的结果是多少:

        Integer i1 = 100;
        Integer i2 = 100;
        System.out.println(i1 == i2);

        Integer i3 = 300;
        Integer i4 = 300;
        System.out.println(i3 == i4);


        Integer i5 = new Integer(100);
        Integer i6 = new Integer(100);
        System.out.println(i6 == i5);

程序的运行结果为:

true
false
false

那么为什么是这样的结果呢?

自动装箱规范要求 boolean、byte、char <= 127,介于 -128 ~ 127 之间的 short 和 int 被包装到固定的对象中。(此句话出自 Java 核心技术卷 1 的 185 页)

所以 i1 和 i2 其实指向的是一个对象,所以为 true。i3 与 i4 指向的是两个对象,所以为 false。而 i5 和 i6 不是自动装箱,属于手动装箱,所以不遵守自动装箱规范,也是两个对象,所以为 false。

所以还是推荐使用 equals() 来对对象包装器对象进行比较,equals() 在 Integer 中被重写,作用是比较包装器对象中的值,我们可以看一下源码:

    public boolean equals(Object obj) {
        // 当前对象与 obj 是否为同一类型,不是同一类型无法比较,返回 false
        if (obj instanceof Integer) {
            // obj 强转为 Integer 后进行手动拆箱转化为 int 值,与 value(前面分析过了,value 是包装器对象实际存储值的地方)进行比较
            return value == ((Integer)obj).intValue();
        }
        return false;
    }

所以只要对象包装器对象中的值相同,则 equals()

四、Integer 类常用 API

方法作用
int intValue()以 int 的形式返回 integer 对象的值
static String toString(int i, int radix)以一个新的 String 对象形式返回给定数值 i 的十进制表示
static int parseInt(String s)返回字符串表示的整型数值,十进制数
static int parseInt(String s, int radix)返回字符串表示整型数值,radix 参数类型的数
static Integer valueOf(String s)返回用 s 表是的整型数值进行初始化的一个新 Integer 对象,十进制数
static Integer valueOf(String s, int radix)返回用 s 表是的整型数值进行初始化的一个新 Integer 对象,radix 参数进制数
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值