一句话总结
int:是Java的一种基本数据类型,它不是对象,只是一个用来存储整数值的内存空间。Integer:是int的包装类,它是一个真正的对象,在内部封装了一个int类型的值,并提供了一系列有用的方法。
详细对比
| 特性 | int (基本数据类型) |
Integer (包装类) |
|---|---|---|
| 本质 | 不是对象,是语言内置的类型。 | 是一个对象,是 java.lang 包下的一个类。 |
| 内存占用 | 固定大小(在大多数JVM上为4字节)。 | 较大,除了存储 int 值外,还需要对象头信息(约12-16字节),总占用更多内存。 |
| 默认值 | 在方法中定义时没有默认值,必须显式初始化。 | 作为类的成员变量时,默认值为 null。 |
| 功能 | 只能存储数值,不能调用任何方法。 | 可以调用方法,如 toString(), parseInt(), compareTo() 等。 |
| 可以为null | 不可以。int 变量必须有一个有效的整数值。 |
可以。Integer 对象可以被赋值为 null,表示“没有值”。 |
| 性能 | 存储和计算效率更高,因为直接操作内存。 | 创建和操作对象有额外的开销(内存分配、垃圾回收),性能较低。 |
| 使用场景 | 用于数值计算、数组索引、循环计数等所有不需要 null 的纯数值场景。 |
用于需要将 int 作为对象使用的场景,如泛型集合、方法参数/返回值需要表示“无值”时。 |
深入解析
int - 基础中的基础
int 就是我们最熟悉的整数,它高效、直接,是Java程序中进行整数运算的主力军。

// 声明一个int变量
int age = 30;
// 数组
int[] scores = new int[5]; // 创建一个包含5个int的数组,默认值为0
// 循环
for (int i = 0; i < 10; i++) {
// ...
}
// 在方法中,局部变量必须初始化
// int number; // 编译错误!变量 number 可能尚未初始化。
int number = 0; // 正确
Integer - 对象的“外衣”
Integer 类的设计是为了解决一个核心问题:有时我们需要将基本数据类型当作对象来使用。
- 为什么需要对象?
- 泛型集合:Java的集合框架(如
ArrayList,HashMap)只能存储对象,不能存储基本数据类型,如果你想存储一个整数列表,你必须使用ArrayList<Integer>,而不是ArrayList<int>。 - 方法参数和返回值:当一个方法需要返回一个“可能不存在”的数值时,返回
Integer并赋值为null是一个很好的设计模式,根据ID查找用户,如果找不到用户,返回null比返回一个“魔法数字”(如-1)要清晰得多。 - 提供实用方法:
Integer类提供了很多静态方法来处理字符串和整数之间的转换,Integer.parseInt("123")-> 将字符串 "123" 转换为int类型的123。Integer.toString(456)-> 将整数456转换为字符串 "456"。Integer.compare(a, b)-> 比较两个整数的大小。
- 泛型集合:Java的集合框架(如
// 声明一个Integer对象
Integer score = new Integer(100); // 旧式写法,不推荐
Integer score = 100; // 新式写法,Java 5+ 的自动装箱
// 可以是null
Integer nullableScore = null;
// 使用集合
List<Integer> numbers = new ArrayList<>();
numbers.add(10);
numbers.add(null); // 允许添加null
// 使用实用方法
int num = Integer.parseInt("200"); // String -> int
String str = Integer.toString(300); // int -> String
Java 5+ 的关键特性:自动装箱与拆箱
这是理解 int 和 Integer 关系的关键,为了简化开发,Java 5 引入了自动装箱和自动拆箱机制,让编译器在 int 和 Integer 之间自动进行转换。
-
自动装箱:当需要一个
Integer对象时,编译器会自动将一个int值包装成一个Integer对象。Integer a = 10; // 编译器将其转换为: Integer a = Integer.valueOf(10);
-
自动拆箱:当需要一个
int值时,编译器会自动从一个Integer对象中拆出int值。
(图片来源网络,侵删)int b = a; // 编译器将其转换为: int b = a.intValue();
示例:
Integer i = 100; // 自动装箱 int j = i; // 自动拆箱 // 运算 i = i + 20; // 1. i (Integer) 被自动拆箱为 int 2. 执行加法 100 + 20 = 120 3. 结果 120 被自动装箱为 Integer 并赋值给 i
⚠️ 自动拆箱的潜在问题:NullPointerException
因为自动拆箱会调用 intValue() 方法,所以如果 Integer 对象是 null,就会抛出 NullPointerException。
Integer count = null; int realCount = count; // 运行时抛出 NullPointerException! // 因为编译器会尝试执行 count.intValue(),而 null 没有方法。
缓存:Integer.valueOf() 的秘密
你可能注意到上面的自动装箱例子中,编译器使用的是 Integer.valueOf(10) 而不是 new Integer(10),这是因为 Integer 类为了提高性能和节省内存,实现了一个缓存机制。

- 对于
-128到127之间的Integer对象,Integer.valueOf()方法会直接从缓存池中返回一个已经存在的对象,而不是创建新的。 - 对于这个范围之外的值,则会创建新的
Integer对象。
示例:
Integer a = 100; Integer b = 100; System.out.println(a == b); // 输出 true // 因为 a 和 b 都指向缓存池中同一个 Integer 对象 Integer c = 200; Integer d = 200; System.out.println(c == d); // 输出 false // 因为 200 不在缓存池范围内,c 和 d 是两个不同的对象
注意: 比较的是对象的内存地址(引用),对于 Integer 对象,只有在指向同一个对象时才为 true,如果你想比较它们的值是否相等,应该使用 .equals() 方法。
Integer e = 200; Integer f = 200; System.out.println(e.equals(f)); // 输出 true,比较的是内部的int值
何时使用哪个?
| 场景 | 推荐使用 | 理由 |
|---|---|---|
| 纯数值计算、循环、数组索引 | int |
性能高,内存占用少。 |
需要将整数放入集合(如 List, Map) |
Integer |
集合只能存储对象。 |
| 方法参数或返回值,需要表示“无值” | Integer |
可以使用 null 来明确表示“不存在”。 |
需要调用 Integer 类的静态方法(如 parseInt) |
Integer |
int 类型没有这些方法。 |
数据库映射(如JDBC的 Integer 对应 NULL) |
Integer |
数据库的 NULL 值可以完美映射到 Java 的 null。 |
int是值,Integer是对象。int高效,Integer功能丰富但开销大。int不能为null,Integer可以。- 自动装箱/拆箱 让两者之间的转换变得无缝,但也带来了
NullPointerException的风险。 Integer的缓存 使得-128到127之间的Integer对象是单例的,这是一个重要的面试考点和性能优化点。
理解这两者的区别和联系,是写出健壮、高效Java代码的基础。
