Java包装类

发布于:2025-05-15 ⋅ 阅读:(14) ⋅ 点赞:(0)

一、Java 数据类型概述

在介绍包装类之前先说一下八种基本数据类型和三种引用数据类型:

1. 基本数据类型(8种)

Java中的8种基本数据类型是语言的基础构建块,它们直接存储值而不是引用:
 

数据类型 大小 默认值 取值范围 包装类
byte 8位 0 -128 ~ 127 Byte
short 16位 0 -32768 ~ 32767 Short
int 32位 0 -2³¹ ~ 2³¹-1 Integer
long 64位 0 -2⁶³ ~ 2⁶³-1 Long
float 32位 0.0f IEEE 754标准 Float
double 64位 0.0d IEEE 754标准 Double
char 1位 '\u0000' 0 ~ 65535 Character
boolean 16位 false true/false Boolean

2. 引用数据类型(3种)

  1. 类(Class) - 如String、自定义类等

  2. 接口(Interface)

  3. 数组

 二、包装类的必要性

众所周知,Java号称“万物皆对象”,但是这里我们要清楚,八大数据类型所定义的数据不能叫对象,而三种引用数据类型定义出来的数据是对象,下面举个例子:

int age = 18;
//这里的age是变量;而下面的cat 是对象
Cat cat = new cat();

为了让这些基本类型也能以对象的形式存在,于是有了包装类,包装类就可以看作是对基本数据类型的一个补充。

包装类的出现主要解决了以下问题:

  1. 对象化需求:使基本类型能参与面向对象的操作

  2. 泛型支持:Java泛型不支持基本类型,如List<int>是非法的,必须使用List<Integer>

  3. 功能扩展:为基本类型添加实用方法,如Integer.parseInt()

  4. null值支持:基本类型不能为null,包装类可以表示缺失值

三、基本数据类型与包装类的对应关系

在上面介绍8种基本数据类型中以及提到了每种数据类型对应的包装类,这里单独又拿出来,如下图中,左侧为基本数据类型,右侧为其对应的包装类

下面以int类型的数据为例

Integer b = 10;
int a = b;

我们将它反编译一下 然后来分析:

我们可以看到 首先调用了Integer.valueOf方法,然后调用了Integer.intValue方法。

四、自动装箱与自动拆箱

自动装箱(Autoboxing)和拆箱(Unboxing)是Java 5引入的特性,极大简化了基本类型和包装类之间的转换。
刚才提到了Integer.valueOf方法和Integer.intValue方法,那么它们是用来干嘛的呢?它们是用来做自动装箱自动拆箱的。什么是自动装箱和自动拆箱呢?我们继续来分析:

Integer a = 10; // Integer.valueOf(10); Integer是一个类,类要调用一些方法来存取数据 //自动装箱
int b = a;  //a.intValue(); //自动拆箱

在 Integer a = 10 ; 由于Integer本身是一个类,不能像基本数据类型一样直接定义数据,所以只能调用相关的方法,相当于把当前的变量装进一个箱子里进行存储一样。所以叫自动装箱

而在 int b = a; 当要取走a 这个数据的时候,因为int是可以直接存储数据的,所以此时就需要把变量从箱子里拿出来赋给int类型,所以叫自动拆箱。

五、128陷阱深度解析

下面用一道题来更好地理解自动拆装箱:

1. 现象重现

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

结果是
true
false
那么为什么呢?

2. 原因分析

这里我们要清楚:对基本数据类型而言:==判断值是否相等,引用数据类型:==判断地址是否相同,那么这个结果说明a,b指向了同一块内存空间,cd没有指向同一块内存空间。
Integer a = 100; 其实就等价于Integer.valueOf(100) ,接下来就来到了关键部分:我们看看valueOf方法干了些什么:

public static Integer valueOf(int i) {
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
}

这里其实就是Java出于性能考虑,对-128到127的Integer对象进行了缓存。当自动装箱的值在这个范围内时,直接从缓存中返回已存在的对象;超出这个范围时,则新建Integer对象。所以c和d超出了范围,所以新建了对象,那么新建之后地址肯定就不会相同 所以输出了false。

以上问题呢就是一道经典的面试题:128陷阱。

六、使用注意事项

  1. 性能考虑:包装类对象比基本类型占用更多内存

  2. 空指针风险:包装类可能为null,拆箱时可能抛出NullPointerException

  3. 比较陷阱:==比较的是对象引用而非值

  4. 缓存范围:不同包装类缓存范围不同:

    • Byte: -128~127(全部缓存)

    • Short/Integer/Long: -128~127

    • Character: 0~127

    • Boolean: true/false(全部缓存)