1. 引言
在 Java 语言中有两大类数据。第一类是基本类型:int、char、double、boolean 等。它们简单且速度快:值直接存储在内存单元中。第二类是引用类型,即对象:变量保存的是对象在内存中的位置(引用)。
有时需要把基本类型当作对象来使用。但基本类型本身并不是对象。此时就需要特殊的 包装类。
包装类是将基本类型的值封装在对象内部、从而可以按对象方式操作的类。例如,对于 int — 类 Integer,对于 double — Double,对于 char — Character,对于 boolean — Boolean。这些类提供了方法:Integer.parseInt()、Double.isInfinite()、Character.isLetter()、Boolean.parseBoolean() 等。
从 int 基本类型获取 Integer 对象的示例:
// 基本类型
int a = 10;
// 包装类对象
Integer b = Integer.valueOf(10);
变量 a 中保存的是数字 10 本身。而变量 b 则保存对一个对象的引用,该对象内部包含 10。
2. 为什么需要包装类
基本类型始终是具体的值,不能赋为 null。对象则可以不存在并保存空值——这在需要表示“未知”或“缺失”时很方便。
基本类型没有方法。不能对一个数字调用类似 x.toString() 的方法。包装类提供了这类能力:Integer.parseInt("123") 能把字符串转换为数字,而数字也可以通过 toString() 转换为字符串。
总结:在需要对象的场景中就需要包装类——例如需要能保存 null、需要调用方法、或要把值传给只接受对象的 API(例如,类型为 List<Integer> 的集合)。
包装类完整列表
| 基本类型 | 包装类 |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3. 装箱与拆箱
当你手动创建包装类对象时,你是把基本类型的值“装箱”到对象里:
int primitive = 42;
Integer wrapper = Integer.valueOf(primitive); // 装箱
要取回基本类型的值——“拆箱”——可以使用例如 intValue():
Integer wrapper = Integer.valueOf(42);
int primitive = wrapper.intValue(); // 拆箱
自动装箱 (Autoboxing)
当你把基本类型赋给包装类变量时,编译器会自动插入对 valueOf() 的调用:
int a = 10;
Integer b = a; // 自动装箱 (Integer.valueOf(a))
自动拆箱 (Unboxing)
反过来——当在需要基本类型的地方使用包装类对象时:
Integer c = 20;
int d = c; // 自动拆箱 (c.intValue())
int a = 10; // 基本类型
Integer b = a; // 自动装箱
Integer c = Integer.valueOf(20);
int d = c; // 自动拆箱
4. 潜在陷阱
比较包装类。 运算符 == 对于对象比较的是引用,而不是值:
Integer m = 200;
Integer n = 200;
System.out.println(m == n); // false,因为它们是不同的对象
Java 会缓存数值包装类在 -128 到 127 范围内的对象,因此有时 == 会返回 true,而有时会返回 false。要比较数值,请始终使用 equals():
Integer x = 100;
Integer y = 100;
System.out.println(x == y); // true,命中缓存
System.out.println(x.equals(y)); // true,按值比较
自动拆箱时的 NullPointerException。 如果包装类为 null,而你尝试拆箱——将抛出异常:
Integer value = null;
int primitive = value; // 错误!NullPointerException
性能与内存。 包装类比基本类型更慢且占用更多内存。在热点代码以及处理大型数字数组时,应优先选择基本类型。
5. 示例
Integer 与 Double 的示例
将字符串转换为数字:
String text = "123";
int number = Integer.parseInt(text);
System.out.println(number); // 123
检查浮点数的特殊值:
double d = 1.0 / 0;
System.out.println(Double.isInfinite(d)); // true
double nan = 0.0 / 0.0;
System.out.println(Double.isNaN(nan)); // true
Character 的示例
char 保存一个字符;包装类 Character 提供了便捷的检查方法:
char ch = 'A';
Character wrapper = ch; // 自动装箱
System.out.println(Character.isLetter(ch)); // true
System.out.println(Character.isDigit(ch)); // false
System.out.println(Character.toLowerCase(ch)); // 'a'
Boolean 的示例
基本类型 boolean 只有 true/false。包装类 Boolean 还可以表示 null:
Boolean flag = null; // 允许
flag = Boolean.TRUE; // 特殊常量
System.out.println(flag); // true
将字符串转换为布尔值:
String s1 = "true";
String s2 = "false";
boolean b1 = Boolean.parseBoolean(s1);
boolean b2 = Boolean.parseBoolean(s2);
System.out.println(b1); // true
System.out.println(b2); // false
GO TO FULL VERSION