Skip to content

Java 包装类(Wrapper Class)详解

一、什么是包装类

包装类是将基本数据类型封装成对象的类,使基本数据类型具备对象的特性。

┌─────────────────────────────────────────────────────────────┐
│                      基本数据类型 vs 包装类                  │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   基本数据类型          包装类                               │
│   ┌─────────┐         ┌─────────────┐                     │
│   │  int    │  ←→     │  Integer    │                     │
│   │  1      │  装箱    │  new Integer │                    │
│   │         │  拆箱    │  (value: 1)  │                     │
│   └─────────┘         └─────────────┘                     │
│                                                             │
│   简单值,无属性无方法         对象,有属性有方法             │
│                                                             │
└─────────────────────────────────────────────────────────────┘

二、八种包装类一览

基本数据类型包装类父类
byteByteNumber
shortShortNumber
intIntegerNumber
longLongNumber
floatFloatNumber
doubleDoubleNumber
charCharacterObject
booleanBooleanObject

对应关系速记

byte    → Byte
short   → Short
int     → Integer     (特殊:不是 Int)
long    → Long
float   → Float
double  → Double
char    → Character   (特殊:不是 Char)
boolean → Boolean

三、继承关系图

                    Object


              ┌─────────┴─────────┐
              │                   │
          Character          Boolean
              │                   │
              │                   │
              ▼                   ▼
         Number ◄────────────┐
              │               │
     ┌────────┴───┬───┬──────┴──────┐
     │           │   │             │
     ▼           ▼   ▼             ▼
   Byte       Short Integer    Long
                           
                         ┌───┬───┘
                         ▼   ▼
                      Float Double

四、创建方式

1. 构造方法创建(已过时,不推荐)

java
// Integer 构造方法
Integer i1 = new Integer(100);      // 已过时 ❌
Integer i2 = new Integer("100");   // 已过时 ❌

// Double 构造方法
Double d1 = new Double(3.14);       // 已过时 ❌
Double d2 = new Double("3.14");     // 已过时 ❌

// Boolean 构造方法
Boolean b1 = new Boolean(true);    // 已过时 ❌
Boolean b2 = new Boolean("true");  // 已过时 ❌
Boolean b3 = new Boolean("abc");   // 已过时 ❌ → false

2. valueOf() 静态方法(推荐)

java
// Integer
Integer i1 = Integer.valueOf(100);       // int → Integer
Integer i2 = Integer.valueOf("100");    // String → Integer
Integer i3 = Integer.valueOf("100", 2); // 二进制字符串 → Integer

// Double
Double d1 = Double.valueOf(3.14);

// Boolean
Boolean b1 = Boolean.valueOf(true);
Boolean b2 = Boolean.valueOf("true");   // "true" → true
Boolean b3 = Boolean.valueOf("TRUE");   // 不区分大小写 → true
Boolean b4 = Boolean.valueOf("abc");   // → false

3. 自动装箱(推荐)

java
// 编译器自动转换:int → Integer
Integer i1 = 100;           // 自动装箱
Integer i2 = 100;           // 自动装箱

Double d1 = 3.14;           // 自动装箱
Boolean b1 = true;          // 自动装箱

五、自动装箱与拆箱

概念

┌─────────────────────────────────────────────────────────────┐
│                                                             │
│   装箱 (Boxing)          拆箱 (Unboxing)                     │
│   ─────────────          ──────────────                     │
│   基本类型 → 对象          对象 → 基本类型                     │
│   int → Integer          Integer → int                      │
│                                                             │
│   100  ────────→  Integer(100)                              │
│         装箱              Integer(100) ────────→ 100        │
│                                                             │
└─────────────────────────────────────────────────────────────┘

自动装箱源码原理

java
// 编译器自动转换
Integer i = 100;

// 实际转换为
Integer i = Integer.valueOf(100);

自动拆箱源码原理

java
// 编译器自动转换
Integer i = 100;
int num = i + 50;

// 实际转换为
Integer i = Integer.valueOf(100);
int num = i.intValue() + 50;  // 调用 intValue() 拆箱

完整示例

java
// ┌─────────────────────────────────────────────────────────┐
// │ 自动装箱:基本类型 → 包装类                              │
// └─────────────────────────────────────────────────────────┘

// 写法1:直接赋值(推荐)
Integer i1 = 100;

// 写法2:自动装箱
Integer i2 = Integer.valueOf(100);

// 写法3:显式装箱(已过时)
Integer i3 = new Integer(100);

// ┌─────────────────────────────────────────────────────────┐
// │ 自动拆箱:包装类 → 基本类型                              │
// └─────────────────────────────────────────────────────────┘

Integer i = 100;

// 写法1:直接运算(推荐)
int num1 = i + 50;           // 自动拆箱

// 写法2:显式拆箱
int num2 = i.intValue();    // 调用方法拆箱

// ┌─────────────────────────────────────────────────────────┐
// │ 混合运算                                              │
// └─────────────────────────────────────────────────────────┘

Integer a = 10;
Integer b = 20;
Integer c = a + b;          // a拆箱 → 相加 → 结果装箱 → c

六、面试重点:Integer 缓存机制

核心规则

Integer 缓存范围:-128 ~ 127

java
Integer i1 = 127;
Integer i2 = 127;
System.out.println(i1 == i2);  // true  ← 同一对象

Integer i3 = 128;
Integer i4 = 128;
System.out.println(i3 == i4);  // false ← 不同对象

源码解析

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

// IntegerCache 缓存范围
// low = -128
// high = 127  (可配置)

图解

┌─────────────────────────────────────────────────────────────┐
│                    Integer 缓存池                           │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   IntegerCache.cache[]                                      │
│   ┌─────┬─────┬─────┬─────┬───┬─────┬─────┬─────┐          │
│   │-128 │-127 │-126 │-125 │...│ 126 │ 127 │     │          │
│   └──┬──┴──┬──┴──┬──┴──┬─┘  └──┬──┴──┬──┴─────┘          │
│      │     │     │     │       │     │                    │
│      ▼     ▼     ▼     ▼       ▼     ▼                    │
│   ┌─────┬─────┬─────┬─────┬───┬─────┬─────┐               │
│   │127个│     │     │     │...│     │127个│  复用缓存对象   │
│   │对象 │     │     │     │   │     │对象 │               │
│   └─────┴─────┴─────┴─────┴───┴─────┴─────┘               │
│                                                             │
│   ┌──────────────────────────────────────────┐             │
│   │  i >= -128 && i <= 127  →  返回缓存对象   │             │
│   │  i < -128 || i > 127   →  new Integer()  │             │
│   └──────────────────────────────────────────┘             │
│                                                             │
└─────────────────────────────────────────────────────────────┘

面试题讲解

java
// 题目1
Integer a = 100;
Integer b = 100;
System.out.println(a == b);  // true
// 原因:100 在缓存范围内,使用同一个对象

// 题目2
Integer c = 200;
Integer d = 200;
System.out.println(c == d);  // false
// 原因:200 超出缓存范围,每次创建新对象

// 题目3
Integer e = 100;
int f = 100;
System.out.println(e == f);  // true
// 原因:e 自动拆箱成 int,再与 f 比较

// 题目4
Integer g = new Integer(100);
Integer h = new Integer(100);
System.out.println(g == h);  // false
// 原因:new Integer() 每次都创建新对象

// 题目5
Integer i = 100;
Integer j = Integer.valueOf(100);
System.out.println(i == j);  // true
// 原因:valueOf(100) 返回缓存对象,i 也是缓存对象

其他包装类的缓存

包装类缓存范围说明
Byte-128 ~ 127所有字节都缓存
Short-128 ~ 127同 Integer
Integer-128 ~ 127可通过 -Djava.lang.Integer.IntegerCache.high=xxx 配置
Long-128 ~ 127同 Integer
Float无缓存每次 new
Double无缓存每次 new
Character0 ~ 127ASCII 字符缓存
Booleantrue/false静态常量 TRUE/FALSE
java
// Character 缓存示例
Character c1 = 127;   // 自动装箱,返回缓存对象
Character c2 = 127;
System.out.println(c1 == c2);  // true

Character c3 = 128;   // 超出范围,new 新对象
Character c4 = 128;
System.out.println(c3 == c4);  // false

七、常用方法

1. 类型转换方法

java
// ┌─────────────────────────────────────────────────────────┐
// │ String → 基本类型(推荐)                               │
// └─────────────────────────────────────────────────────────┘

int i = Integer.parseInt("100");      // "100" → 100
long l = Long.parseLong("100");       // "100" → 100L
double d = Double.parseDouble("3.14"); // "3.14" → 3.14
boolean b = Boolean.parseBoolean("true"); // "true" → true

// ┌─────────────────────────────────────────────────────────┐
// │ String → 包装类                                         │
// └─────────────────────────────────────────────────────────┘

Integer i = Integer.parseInt("100");           // 返回基本类型
Integer i2 = Integer.valueOf("100");           // 返回包装类

// ┌─────────────────────────────────────────────────────────┐
// │ 基本类型 → String                                        │
// └─────────────────────────────────────────────────────────┘

String s1 = String.valueOf(100);       // 100 → "100"
String s2 = 100 + "";                  // 100 → "100"
String s3 = Integer.toString(100);     // 100 → "100"

// ┌─────────────────────────────────────────────────────────┐
// │ 包装类 → 基本类型                                        │
// └─────────────────────────────────────────────────────────┘

Integer i = new Integer("100");
int num = i.intValue();        // Integer → int
long l = i.longValue();       // Integer → long
double d = i.doubleValue();    // Integer → double

// ┌─────────────────────────────────────────────────────────┐
// │ 自动拆箱:包装类 → 基本类型(推荐)                       │
// └─────────────────────────────────────────────────────────┘

Integer i = 100;
int num = i;                   // 自动拆箱

2. 进制转换方法

java
// ┌─────────────────────────────────────────────────────────┐
// │ 十进制 → 其他进制                                        │
// └─────────────────────────────────────────────────────────┘

String binary = Integer.toBinaryString(10);   // 10 → "1010"  (二进制)
String octal = Integer.toOctalString(10);     // 10 → "12"    (八进制)
String hex = Integer.toHexString(10);        // 10 → "a"     (十六进制)
String hexUpper = Integer.toHexString(255).toUpperCase(); // "FF"

// ┌─────────────────────────────────────────────────────────┐
// │ 其他进制 → 十进制                                        │
// └─────────────────────────────────────────────────────────┘

int dec1 = Integer.parseInt("1010", 2);      // 二进制"1010" → 10
int dec2 = Integer.parseInt("12", 8);        // 八进制"12" → 10
int dec3 = Integer.parseInt("a", 16);        // 十六进制"a" → 10
int dec4 = Integer.parseInt("A", 16);        // 十六进制"A" → 10

// ┌─────────────────────────────────────────────────────────┐
// │ 其他进制 → 其他进制                                       │
// └─────────────────────────────────────────────────────────┘

// 二进制 → 十六进制
String binToHex = Long.toHexString(Long.parseLong("1010", 2));
// 或
String result = Integer.toHexString(Integer.parseInt("1010", 2));

3. 常用常量

java
// Integer
System.out.println(Integer.MAX_VALUE);  // 2147483647
System.out.println(Integer.MIN_VALUE);  // -2147483648
System.out.println(Integer.SIZE);        // 32 (位数)
System.out.println(Integer.BYTES);        // 4 (字节数)

// Long
System.out.println(Long.MAX_VALUE);     // 9223372036854775807
System.out.println(Long.MIN_VALUE);     // -9223372036854775808

// Double
System.out.println(Double.MAX_VALUE);   // 1.7976931348623157E308
System.out.println(Double.MIN_VALUE);   // 4.9E-324

// Character
System.out.println(Character.MAX_VALUE); // '\uffff'
System.out.println(Character.MIN_VALUE); // '\u0000'
System.out.println(Character.isDigit('3'));  // true
System.out.println(Character.isLetter('A')); // true
System.out.println(Character.isUpperCase('a')); // false

4. 比较方法

java
// ┌─────────────────────────────────────────────────────────┐
// │ compareTo(实现 Comparable 接口)                        │
// └─────────────────────────────────────────────────────────┘

Integer a = 10;
Integer b = 20;
System.out.println(a.compareTo(b));  // -1  (a < b)
System.out.println(b.compareTo(a));  // 1   (b > a)
System.out.println(a.compareTo(10)); // 0   (相等)

// ┌─────────────────────────────────────────────────────────┐
// │ compare(静态方法,用于排序)                            │
// └─────────────────────────────────────────────────────────┘

System.out.println(Integer.compare(10, 20));  // -1
System.out.println(Integer.compare(20, 10)); // 1
System.out.println(Integer.compare(10, 10));  // 0

// ┌─────────────────────────────────────────────────────────┐
// │ equals(比较值是否相等)                                 │
// └─────────────────────────────────────────────────────────┘

Integer a = new Integer(100);
Integer b = new Integer(100);
System.out.println(a == b);     // false (引用比较)
System.out.println(a.equals(b)); // true (值比较)

// ┌─────────────────────────────────────────────────────────┐
// │ 特别注意:equals 与 == 在自动装箱时的表现                  │
// └─────────────────────────────────────────────────────────┘

Integer a = 127;
Integer b = 127;
System.out.println(a == b);       // true (缓存)
System.out.println(a.equals(b));  // true (值相等)

Integer c = 128;
Integer d = 128;
System.out.println(c == d);       // false (非缓存)
System.out.println(c.equals(d));  // true (值相等)

八、基本类型 vs 包装类

区别汇总

特性基本数据类型包装类
默认值有默认值(如 0)默认值是 null
存储位置栈(局部变量)堆(对象)
泛型支持不支持支持
方法调用不能调用方法可以调用各种方法
内存效率高(直接存值)低(需要对象开销)
比较方式== 比较值== 比较引用,equals 比较值

代码示例

java
// 1. 默认值
int i = 0;                // 正确,int 默认值就是 0
Integer ii = null;        // 正确,引用类型默认 null
// Integer iii;           // 错误!局部变量必须初始化

// 2. 泛型支持
List<int> list1;          // ❌ 错误!基本类型不能用于泛型
List<Integer> list2;      // ✅ 正确

// 3. 方法调用
int num = 100;
num.toString();           // ❌ 错误!基本类型不能调用方法

Integer n = 100;
n.toString();             // ✅ "100"
n.MAX_VALUE;              // ✅ 可以访问静态常量
n.compareTo(50);         // ✅ 可以调用实例方法

// 4. 集合操作
List<int> nums1 = new ArrayList<>();    // ❌ 编译错误
List<Integer> nums2 = new ArrayList<>(); // ✅ 正确
nums2.add(100);                          // 自动装箱
int value = nums2.get(0);                // 自动拆箱

九、应用场景

1. 集合框架

java
// List:只能存储对象,不能存基本类型
List<Integer> list = new ArrayList<>();
list.add(1);              // 自动装箱:1 → Integer(1)
list.add(2);              // 自动装箱:2 → Integer(2)
int num = list.get(0);    // 自动拆箱:Integer(1) → 1

// Map:键值对
Map<String, Integer> map = new HashMap<>();
map.put("age", 25);       // 自动装箱

// Set:去重
Set<Integer> set = new HashSet<>();
set.add(100);
set.add(100);            // 重复添加无效

2. 类型转换

java
// 字符串解析为数字
String input = "123";
int num = Integer.parseInt(input);
double price = Double.parseDouble("19.99");

// 数字转字符串
int age = 25;
String s1 = String.valueOf(age);
String s2 = age + "";
String s3 = Integer.toString(age);

// 进制转换
String bin = Integer.toBinaryString(10);
int dec = Integer.parseInt("1010", 2);

3. 方法返回值

java
// 返回 null 表示特殊情况
public Integer findAge(String name) {
    if ("Tom".equals(name)) {
        return 25;
    }
    return null;  // 基本类型 int 无法表示"未找到"
}

// 区别于
public int findAge2(String name) {
    if ("Tom".equals(name)) {
        return 25;
    }
    return -1;  // 必须返回一个"特殊"值
}

4. 反射和泛型

java
// 反射获取字段值(返回 Object,需强转)
Field field = person.getClass().getDeclaredField("age");
Object value = field.get(person);
int age = (Integer) value;

// 泛型必须用包装类
class Result<T> {
    private T data;
    
    public T getData() {
        return data;
    }
    
    public void setData(T data) {
        this.data = data;
    }
}

Result<Integer> intResult = new Result<>();  // ✅
Result<int> intResult2;                        // ❌

5. 数据库操作

java
// MyBatis / Hibernate 查询结果
// 数据库 NULL → 包装类 null
Integer age = jdbcTemplate.queryForObject(
    "SELECT age FROM user WHERE id = ?", 
    Integer.class, 
    userId
);

if (age == null) {
    System.out.println("用户未设置年龄");
} else {
    System.out.println("年龄: " + age);
}

十、常见面试题

题目1:Integer 缓存

java
Integer a = 1;
Integer b = 2;
Integer c = 3;
Integer d = 3;
Integer e = 321;
Integer f = 321;
Long g = 3L;
Long h = 2L;

// 问:下面表达式的结果?
System.out.println(c == d);        // ?
System.out.println(e == f);        // ?
System.out.println(c == (a + b));  // ?
System.out.println(c.equals(a + b)); // ?
System.out.println(g == (a + b));  // ?
System.out.println(g.equals(a + b)); // ?

答案:

java
System.out.println(c == d);          // true (缓存)
System.out.println(e == f);          // false (超出缓存)
System.out.println(c == (a + b));    // true (运算时自动拆箱)
System.out.println(c.equals(a + b)); // true (equals 比较值)
System.out.println(g == (a + b));    // true (类型提升,结果是 long)
System.out.println(g.equals(a + b)); // false (类型不同,false)

题目2:运算时的自动拆箱

java
Integer i = new Integer(1);
i = null;

int j = i;  // NullPointerException!
// 等价于:int j = i.intValue();
// i 是 null,无法调用方法

题目3:Double vs Integer

java
Double d1 = 0.1;
Double d2 = 0.1;
System.out.println(d1 == d2);  // false (Double 无缓存)

Integer i1 = 0;
Integer i2 = 0;
System.out.println(i1 == i2);  // true (Integer 有缓存)

十一、总结

一句话记忆

包装类 = 基本类型 + 对象特性(可以 null、可以调用方法、可以用于泛型)

使用建议

场景推荐原因
集合存储包装类基本类型不能存集合
数据库映射包装类支持 NULL
数值运算基本类型性能更好,无空指针风险
泛型包装类基本类型不支持泛型
方法参数可为空包装类用 null 表示特殊情况

速查表

需求代码
String → intint i = Integer.parseInt("100");
int → StringString s = String.valueOf(100);
String → IntegerInteger i = Integer.valueOf("100");
int → IntegerInteger i = 100;Integer.valueOf(100)
Integer → intint i = i1;i1.intValue()
判断是否为数字Character.isDigit(ch)
获取最大值Integer.MAX_VALUE

相关标签

#Java #包装类 #Integer #自动装箱 #自动拆箱 #缓存机制

Knowledge4J — Java 知识库