long:是 Java 的原始数据类型(Primitive Type)。Long:是long对应的包装类(Wrapper Class)。
下面我们从多个维度进行详细的对比。

核心区别对比表
| 特性 | long (原始类型) |
Long (包装类) |
|---|---|---|
| 类型 | 原始数据类型 | 引用类型 (Object) |
| 默认值 | 0 |
null |
| 用途 | 存储数值,用于计算 | 可以表示“无值”状态,用于泛型、集合、反射等 |
| 内存占用 | 固定大小 (8 bytes) | 较大,包含对象头和值 |
| 可为 null | 否 | 是 |
| 示例用法 | long id = 12345L; |
Long id = null; 或 Long id = 12345L; |
| 自动装箱/拆箱 | 支持 | 支持 |
| 继承关系 | - | 继承自 Number 类,实现了 Comparable 接口 |
详细解释
long - 原始数据类型
long 是 Java 八种原始数据类型之一,专门用于存储整数。
- 本质:它只是一个值的容器,直接存储在内存的栈(Stack)上。
- 大小:占用 64 位(8 字节)的内存空间。
- 范围:可以表示的数值范围是
-2^63到2^63-1(即 -9,223,372,036,854,775,808 到 9,223,372,036,854,775,807)。 - 默认值:当一个
long类型的成员变量没有被初始化时,它的默认值是0。 - 不能为 null:
long类型必须有一个有效的整数值,不能是null,如果你尝试将null赋值给一个long变量,编译器会报错。
示例:
public class PrimitiveLongExample {
// 成员变量,默认值为 0
long defaultLong;
public static void main(String[] args) {
// 局部变量必须显式初始化
long myLong = 10000000000L; // 注意:字面量需要加 L 或 l 后缀
System.out.println("myLong 的值: " + myLong);
System.out.println("defaultLong 的值: " + defaultLong); // 输出 0
// 以下代码会编译错误!
// long anotherLong = null;
}
}
Long - 包装类
Long 是一个类,属于 java.lang 包,它被称为 long 的“包装类”,因为它将一个 long 原始类型的值“包装”进了一个 Long 对象中。
- 本质:它是一个对象,存储在堆(Heap)上,对象中包含一个
long类型的字段来存储实际的值。 - 大小:比
long原始类型大得多,因为它包含了对象头(如哈希码、锁信息等)。 - 可以为 null:
Long对象可以是null,这非常有用,可以用来表示“没有值”、“未知值”或“缺失值”。 - 提供实用方法:
Long类提供了很多有用的静态方法,Long.parseLong(String s): 将字符串解析为long值。Long.valueOf(long l): 将long�量转换为Long对象。Long.toString(long l): 将long值转换为字符串。
示例:

public class LongWrapperExample {
// 成员变量,默认值为 null
Long nullableLong;
public static void main(String[] args) {
// 局部变量必须显式初始化
Long myLongObj = 10000000000L; // 这里发生了自动装箱
System.out.println("myLongObj 的值: " + myLongObj);
// 可以是 null
Long anotherLongObj = null;
System.out.println("anotherLongObj 的值: " + anotherLongObj); // 输出 null
System.out.println("nullableLong 的值: " + nullableLong); // 输出 null
// 使用 Long 类的静态方法
String numStr = "123456";
long parsedLong = Long.parseLong(numStr);
System.out.println("解析后的 long 值: " + parsedLong);
}
}
自动装箱与拆箱
为了方便在原始类型和包装类之间转换,Java 5 引入了自动装箱和自动拆箱机制。
-
自动装箱:当 Java 需要将一个
long值赋给一个Long引用时,会自动将其转换为一个Long对象。Long myLong = 10L; // 编译器自动将其转换为: Long myLong = Long.valueOf(10L);
-
自动拆箱:当 Java 需要将一个
Long对象用在需要long值的地方(如数学运算)时,会自动将其拆箱为long值。Long a = 10L; long b = a + 5; // 编译器自动将其转换为: long b = a.longValue() + 5;
⚠️ 自动装箱/拆箱的陷阱(NPE - NullPointerException)

自动拆箱时,Long 对象是 null,程序会抛出 NullPointerException。
Long count = null; // 以下代码会抛出 NullPointerException int total = count + 1; // 因为 count 是 null,无法调用 .longValue() 方法
何时使用 long,何时使用 Long?
这是一个非常实际的问题,选择哪个取决于你的具体需求。
使用 long 的情况:
-
基本计算:当你只需要进行纯粹的数值计算,不关心“空值”概念时,这是最常见的情况。
long sum = 0; for (int i = 0; i < 1000; i++) { sum += i; } -
性能要求高:在性能极其敏感的循环或算法中,使用原始类型可以避免自动装箱/拆箱带来的开销,减少内存占用(因为对象在堆上,GC 会回收)。
-
数组:当你需要存储大量数值时,使用
long[]比Long[]更节省内存。
使用 Long 的情况:
-
需要表示“空”或“缺失”:这是使用
Long最重要、最正当的理由,数据库中的字段可能为NULL,对应的 Java 实体类字段就应该用Long。public class User { private Long id; // 用户ID可能不存在,所以用 Long private String name; // name 必须存在,用 String(String 本身可以为 null) // getters and setters... } -
泛型:Java 的泛型(如
List<T>)不能使用原始类型,如果你需要一个long类型的列表,你必须使用Long。// 错误用法 // List<long> ids = new ArrayList<>(); // 正确用法 List<Long> ids = new ArrayList<>(); ids.add(1L); ids.add(null); // 可以添加 null
-
集合框架:
HashMap、HashSet等集合的键或值如果是long类型,必须使用Long。Map<Long, String> userMap = new HashMap<>(); userMap.put(1001L, "Alice");
-
反射和 API 调用:很多 Java API(如反射、框架)的方法参数或返回值是
Object类型,当你需要处理long时,必须使用Long。
| 场景 | 推荐类型 | 理由 |
|---|---|---|
| 简单数学运算、循环计数器 | long |
性能更高,内存开销小 |
| 数组存储大量数值 | long[] |
比 Long[] 更节省内存 |
| 数据库字段可为 NULL | Long |
可以准确映射数据库的 NULL 值 |
| 需要表示“无值”或“未知” | Long |
null 是一个完美的语义表达 |
使用泛型(如 List<T>) |
Long |
泛型不支持原始类型 |
作为 Map 的键或值 |
Long |
Map 的键值对必须是对象 |
记住这个核心原则:如果你需要一个单纯的数值,用 long;如果你需要一个可能为“空”的数值,或者需要一个对象,就用 Long。
