在 Java 中,**包装类(Wrapper Class)和泛型(Generics)**是两个非常重要的语言特性,它们经常一起使用,特别是在集合框架、类型安全和自动装箱拆箱等场景中。下面从 基础概念 → 包装类原理 → 泛型机制 → 二者结合应用 → 常见面试点进行系统讲解。
一、Java 包装类(Wrapper Class)
Java 是 强类型语言,基本数据类型(primitive type)不能直接当作对象使用,因此 Java 提供了对应的 包装类。
基本类型与包装类对应关系
| 基本类型 | 包装类 |
|---|---|
| byte | Byte |
| short | Short |
| int | Integer |
| long | Long |
| float | Float |
| double | Double |
| char | Character |
| boolean | Boolean |
这些类都位于:
java.lang
示例:
Integer num = Integer.valueOf(10);
int x = num.intValue();
二、自动装箱与自动拆箱
从 Java 5 开始引入 自动装箱(Autoboxing) 与 自动拆箱(Unboxing)。
自动装箱
Integer a = 10;
等价于:
Integer a = Integer.valueOf(10);
自动拆箱
Integer a = 10;
int b = a;
等价于:
int b = a.intValue();
三、包装类的常见方法
以 Integer 为例:
Integer.parseInt("123"); // 字符串转int
Integer.valueOf("123"); // 字符串转Integer
Integer.toString(10); // 转字符串
示例:
int num = Integer.parseInt("100");
四、包装类缓存机制
Integer 存在 缓存池:
范围:
-128 到 127
示例:
Integer a = 100;
Integer b = 100;
System.out.println(a == b);
结果:
true
但:
Integer a = 200;
Integer b = 200;
结果:
false
原因:
缓存只覆盖 -128 ~ 127。
五、Java 泛型(Generics)
泛型是 参数化类型(Parameterized Type)。
目的是:
- 提高类型安全
- 避免类型转换
- 提升代码复用
示例:
List<String> list = new ArrayList<>();
集合来自:
java.util
六、泛型的基本语法
泛型类
class Box<T> {
private T value;
public void set(T value) {
this.value = value;
}
public T get() {
return value;
}
}
使用:
Box<Integer> box = new Box<>();
泛型方法
public static <T> void print(T value) {
System.out.println(value);
}
调用:
print("Hello");
print(123);
七、泛型通配符
Java 提供三种通配符:
1 无界通配符
List<?> list
表示:
任何类型。
2 上界通配符
List<? extends Number>
表示:
Number 或其子类。
3 下界通配符
List<? super Integer>
表示:
Integer 或其父类。
八、包装类与泛型结合使用
泛型 不能使用基本类型,只能使用引用类型。
错误示例:
List<int> list;
正确写法:
List<Integer> list;
原因:
Java 泛型 不支持 primitive type。
九、集合中的包装类应用
例如:
List<Integer> list = new ArrayList<>();
list.add(10);
过程:
10 -> 自动装箱 -> Integer对象
取值:
int x = list.get(0);
过程:
Integer -> 自动拆箱 -> int
十、泛型的类型擦除(Type Erasure)
Java 泛型在编译后会 擦除类型信息。
例如:
List<String>
List<Integer>
编译后:
List
这就是:
类型擦除(Type Erasure)
原因:
Java 为了保持向下兼容。
十一、泛型擦除示例
List<String> list = new ArrayList<>();
编译后等价:
List list = new ArrayList();
并自动添加:
类型检查
强制转换
十二、泛型的优点
1 类型安全
编译时检查类型。
2 消除强制转换
String s = list.get(0);
无需:
(String)
3 提高代码复用
同一逻辑适用于多种类型。
十三、常见面试问题
1 为什么泛型不能使用基本类型?
因为:
泛型只支持引用类型
所以必须使用 包装类。
2 Java 泛型什么时候生效?
编译期
运行期已经被擦除。
3 List 与 List<?> 的区别?
| 类型 | 含义 |
|---|---|
| List | Object 类型列表 |
| List<?> | 任意类型列表 |
4 Integer 和 int 的区别?
| int | Integer |
|---|---|
| 基本类型 | 对象 |
| 无方法 | 有方法 |
| 不可为null | 可以为null |
十四、实际开发示例
import java.util.*;
public class Demo {
public static void main(String[] args) {
List<Integer> numbers = new ArrayList<>();
numbers.add(10);
numbers.add(20);
for (Integer n : numbers) {
System.out.println(n);
}
}
}
运行过程:
10 -> Integer
20 -> Integer
取出 -> 自动拆箱
总结
Java 中 包装类与泛型的关系非常紧密:
| 特性 | 作用 |
|---|---|
| 包装类 | 让基本类型变成对象 |
| 泛型 | 提供类型安全 |
| 自动装箱 | 基本类型 → 包装类 |
| 自动拆箱 | 包装类 → 基本类型 |
| 类型擦除 | 泛型只在编译期存在 |
一句话总结:
Java 泛型不能使用基本类型,因此必须借助包装类来实现类型参数化。
如果你愿意,我可以继续给你整理一份 Java 面试高频 30 题(包装类 + 泛型 + 集合框架深度版),里面有很多 大厂面试非常喜欢问的底层问题。