杰瑞科技汇

Java中int和Integer有何本质区别?

int 是基本数据类型,而 Integerint 的包装类

Java中int和Integer有何本质区别?-图1
(图片来源网络,侵删)

下面我们从多个维度进行详细对比。


核心区别一览表

特性 int Integer
类型 基本数据类型 引用数据类型 (包装类)
默认值 0 null
存储位置 栈内存 堆内存
用途 用于数值计算,高效、直接 用于面向对象场景,如泛型、集合、可以为null
示例 int age = 30; Integer age = Integer.valueOf(30);
方法 无方法 有很多方法,如 parseInt(), toString(), compareTo()
自动装箱/拆箱 不参与 参与 (Java 1.5+ 特性)

详细解释

基本数据类型 vs. 引用数据类型

这是最根本的区别。

  • int (基本数据类型)

    • Java 语言内置的、最简单的数据类型。
    • 它本身不包含任何复杂的行为或方法,只是一个纯粹的值。
    • 它直接存储在栈内存中,访问速度非常快。
  • Integer (引用数据类型)

    Java中int和Integer有何本质区别?-图2
    (图片来源网络,侵删)
    • 它是一个类,位于 java.lang 包下。
    • 它是 int 的“包装器”,将一个 int 值包装在一个对象中。
    • 作为对象,它存储在堆内存中,栈中只保存指向这个对象的引用。

默认值

这个区别在处理类或数组的成员变量时至关重要。

  • int: 当一个 int 类型的成员变量被声明但没有初始化时,它的默认值是 0
  • Integer: 当一个 Integer 类型的成员变量被声明但没有初始化时,它的默认值是 null

示例代码:

public class DefaultValueExample {
    // int 类型的成员变量,默认值为 0
    private int primitiveInt;
    // Integer 类型的成员变量,默认值为 null
    private Integer wrapperInteger;
    public static void main(String[] args) {
        DefaultValueExample example = new DefaultValueExample();
        System.out.println("primitiveInt 的默认值: " + example.primitiveInt); // 输出 0
        System.out.println("wrapperInteger 的默认值: " + example.wrapperInteger); // 输出 null
        // 尝试对 wrapperInteger 进行算术运算,会抛出 NullPointerException
        // example.wrapperInteger = example.wrapperInteger + 1; // 这行代码会崩溃!
    }
}

最佳实践:当你需要一个变量可以表示“无数字”或“未知”状态时(数据库中的字段可能为空),必须使用 Integer,因为 null 可以明确地表示这种状态。

与集合和泛型的关系

这是 Integer 不可替代的另一个重要场景。

  • Java 的集合框架(如 ArrayList, HashMap)只能存储对象,不能存储基本数据类型。
  • 泛型(Generics)也不支持基本数据类型。

如果你想把一个 int 类型的数字放进 ListMap 的键/值中,你必须使用 Integer

示例代码:

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class CollectionExample {
    public static void main(String[] args) {
        // List<int> list = new ArrayList<>(); // 编译错误!泛型不支持基本类型
        // 正确用法:使用包装类
        List<Integer> list = new ArrayList<>();
        list.add(10); // 自动装箱:10 -> Integer(10)
        list.add(20);
        System.out.println("List 中的元素: " + list); // 输出 [10, 20]
        Map<String, Integer> map = new HashMap<>();
        map.put("age", 25); // 自动装箱
        map.put("score", 98);
        System.out.println("Map 中的值: " + map); // 输出 {score=98, age=25}
    }
}

自动装箱与自动拆箱

为了简化 intInteger 之间的转换,Java 1.5 引入了自动装箱自动拆箱机制。

  • 自动装箱: 将 int 类型自动转换为 Integer 对象。

    • Integer i = 10; 等同于 Integer i = Integer.valueOf(10);
  • 自动拆箱: 将 Integer 对象自动转换为 int 类型。

    • int j = i; 等同于 int j = i.intValue();

这个特性让开发者可以像使用基本类型一样方便地使用包装类,但背后 JVM 仍然在执行转换操作。

示例代码:

public class AutoBoxingUnboxingExample {
    public static void main(String[] args) {
        // 自动装箱
        Integer integerObj = 100;
        // 自动拆箱
        int primitiveInt = integerObj;
        System.out.println("integerObj: " + integerObj);
        System.out.println("primitiveInt: " + primitiveInt);
        // 在表达式中混合使用
        Integer a = 10;
        Integer b = 20;
        int sum = a + b; // a 和 b 都会自动拆箱为 int,然后相加
        System.out.println("sum: " + sum); // 输出 30
    }
}

注意: 自动拆箱有一个潜在的风险。Integer 对象的值为 null,尝试进行自动拆箱会抛出 NullPointerException,这就是为什么理解默认值的区别非常重要。

缓存机制

Integer 类有一个非常重要的特性:缓存

为了提高性能和节省内存,Integer 类在内部维护了一个 Integer 对象池,范围是 -128 到 127

当你使用 Integer.valueOf(int i) 方法(或者直接使用 Integer i = 10; 这种字面量赋值,JVM 会调用 valueOf)创建一个 Integer 对象时:

  • i 的值在 -128127 之间,valueOf 方法会直接从缓存池中返回一个已经存在的对象,而不是创建新的。
  • i 的值不在这个范围内,则会创建一个新的 Integer 对象。

示例代码:

public class IntegerCacheExample {
    public static void main(String[] args) {
        Integer a = 127;
        Integer b = 127;
        System.out.println(a == b); // true,指向缓存池中的同一个对象
        Integer c = 128;
        Integer d = 128;
        System.out.println(c == d); // false,指向堆中两个不同的新对象
        // 使用 new 关键字创建,永远都是新对象
        Integer e = new Integer(127);
        Integer f = new Integer(127);
        System.out.println(e == f); // false
    }
}

注意: 比较的是两个引用是否指向同一个对象,对于基本类型 int, 比较的是值是否相等。


总结与选择

场景 推荐使用 原因
简单的数学计算 int 速度更快,内存占用更小,没有对象开销。
需要为 null Integer null 可以明确表示“无值”或“未知”状态。
作为集合或泛型的元素 Integer 集合框架只能存储对象。
调用 Integer 类的静态方法 Integer Integer.parseInt("123")
作为方法参数,需要传递 null Integer 方法无法区分 int0 和未传入的情况。

核心思想

  • 追求性能和内存效率,使用 int
  • 需要面向对象的特性、null 值支持或与集合框架集成,使用 Integer

在 Java 1.5 之后,自动装箱/拆箱机制让两者之间的切换变得非常平滑,但开发者仍然需要理解它们背后的区别,以避免 NullPointerException 等潜在问题,并写出更符合 Java 设计思想的代码。

分享:
扫描分享到社交APP
上一篇
下一篇