1. Java的 long 类型的最大值是什么?
Java的 long 类型的最大值是 9223372036854775807。
它被定义为常量 Long.MAX_VALUE。
首先,让我们确认这个结论。
public class Main {
public static void main(String[] args) {
System.out.println(Long.MAX_VALUE);
}
}
输出:
9223372036854775807
换句话说,这就是你在 Java long 中可以存储的最大正数值。
1.1 long 最大值是 “9223372036854775807”
这个值可以用下面的公式表示:
2^63 - 1
关键点是为什么是 “63”。
long类型是 64 位整数。- 1 位用于符号(正/负)。
- 剩余的 63 位表示数值。
因此,
maximum value = 2^63 - 1
成为最大值。
*“位”是表示 0 或 1 的最小数据单元。
1.2 为什么它不是 2^64 − 1,尽管它是 64 位?
这是最容易让初学者困惑的点。
Java 的 long 是 有符号整数。
“有符号”意味着它可以表示正数和负数。
64 位的划分:
- 1 位 → 符号
- 63 位 → 数值
因此,最大的正数值是:
2^63 - 1
这就是原因。
“2^64 – 1” 适用于 无符号整数。
Java 没有 unsigned long 类型。
⚠ 常见误解
- × long 最大值是 18446744073709551615
- ○ 正确:9223372036854775807
1.3 也检查一下 long 的最小值
最小值是与最大值一起必须记住的另一个重要项。
System.out.println(Long.MIN_VALUE);
输出:
-9223372036854775808
以公式形式:
-2^63
绝对值比最大值大 1,因为 Java 使用 二进制补码 来管理整数。
*二进制补码是计算机用来表示负数的标准机制。
常见陷阱与注意事项
- 把它误认为
2^64-1 - 认为存在无符号 long
- 直接记忆数值时记错数字
- 与 int(32 位)混淆
尤其是,把它与 int 的最大值 (2147483647) 混淆 是非常常见的。
2. 在 Java 中获取 long 的最大值
在处理 long 的最大值时,规则是:不要直接写出数字——使用常量。
下面我们将解释获取它的安全且实用的方法。
2.1 使用 Long.MAX_VALUE(推荐)
在 Java 中,最大值在 java.lang.Long 类中定义。
long max = Long.MAX_VALUE;
System.out.println(max);
输出:
9223372036854775807
为什么要使用常量?
- 防止数字/拼写错误
- 提高可读性
- 明确类型
- 对未来的更改更具鲁棒性(规范更改不太可能,但更安全)
不需要特殊导入。
java.lang 包会自动导入。
2.2 直接写数字时的注意事项
你也可以直接写出最大值。
long max = 9223372036854775807L;
这里重要的部分是 结尾的 “L”。
为什么需要 “L”?
在 Java 中,整数字面量(数值字面量)默认被视为 int,除非后面追加了其他标识。
这意味着:
long max = 9223372036854775807; // Error
这会导致编译时错误。
原因:
- 超出了 int 的范围
- 未明确表明它是 long
正确写法:
long max = 9223372036854775807L;
⚠ 小写的 l 与数字 1 难以区分,建议使用 大写 L。
2.3 硬编码的风险
“硬编码”指的是直接写出数值。
if (value == 9223372036854775807L) {
// Processing
}
问题:
- 含义不明确
- 可维护性低
- 其他开发者难以理解
推荐做法:
if (value == Long.MAX_VALUE) {
// Processing
}
这使得代码的意图更加清晰。
Common Mistakes
- 忘记在数值后添加
L,导致编译错误 - 尝试将其赋值给
int类型的变量 - 写成
Long max = Long.MAX_VALUE;,但未考虑可能的空值处理(在使用包装类时) - 尝试使用
Math.pow(2,63)进行计算(会得到 double 并引入精度问题)
*Math.pow() 返回 double,因此不适合精确的整数计算。
3. 当 long 超过最大值会发生什么?(Overflow)
long 类型只能处理有限的范围。
所以如果超过最大值,它不会抛出错误——其值会环绕(循环)。
这称为“溢出”。
3.1 实际的溢出示例
让我们在实践中验证一下。
public class Main {
public static void main(String[] args) {
long max = Long.MAX_VALUE;
long overflow = max + 1;
System.out.println("Max value: " + max);
System.out.println("Max value + 1: " + overflow);
}
}
输出:
Max value: 9223372036854775807
Max value + 1: -9223372036854775808
你可以看到 max + 1 变成了最小值。
这并不异常——这是 Java 规范定义的行为。
3.2 为什么它不会变成错误?
Java 整数类型(int / long)在数值超出范围时不会抛出异常。
原因:
- 位数固定(long 为 64 位)
- 由于二进制补码表示,数值会环绕
从概念上讲:
Max value → +1 → Min value
Min value → -1 → Max value
计算机只是对位进行运算,因此没有“超出范围”的概念。
⚠ 常见的初学者困惑
- 认为“会报错”
- 符号突然翻转,导致 bug
3.3 如何检测溢出
普通的加法无法检测到溢出。
方法 1:使用 Math.addExact()(推荐)
try {
long result = Math.addExact(Long.MAX_VALUE, 1);
} catch (ArithmeticException e) {
System.out.println("Overflow occurred");
}
Math.addExact() 在结果超出范围时会抛出 ArithmeticException。
还有:
Math.subtractExact()Math.multiplyExact()
等。
3.4 如何进行范围检查
你也可以在加法前进行检查。
if (value > Long.MAX_VALUE - addValue) {
System.out.println("Adding will overflow");
}
在实践中,addExact() 通常比这种方法更安全。
3.5 使用 BigInteger(无上限)
如果 long 不足,可使用 BigInteger。
import java.math.BigInteger;
BigInteger a = new BigInteger("9223372036854775807");
BigInteger b = BigInteger.ONE;
BigInteger result = a.add(b);
System.out.println(result);
BigInteger 没有位数限制。
但请注意:
- 比 long 更慢
- 占用更多内存
- 不是基本类型(而是对象类型)
Common Mistakes and Notes
- 在货币计算中使用 long 而未注意溢出
- 生成 ID 时未考虑上限
- 使用 Math.pow 并引入精度误差
- 转换为 double 再返回(精度损失)
这可能导致致命错误,尤其在金融处理时。
4. 与其他整数类型的最大值比较
要正确理解 long 的最大值,还需要了解它与其他整数类型的区别。在 Java 中,每种整数类型都有基于位宽的明确范围。
4.1 与 int 的区别
int 是 32 位有符号整数。
System.out.println(Integer.MAX_VALUE);
输出:
2147483647
比较:
| Type | Bit width | Maximum value |
|---|---|---|
| int | 32-bit | 2,147,483,647 |
| long | 64-bit | 9,223,372,036,854,775,807 |
long 的取值范围约是 int 的 43 亿倍。
⚠ 常见错误
- 认为 int 足够,后因增长导致溢出
- 将数据库的 BIGINT 映射为 int
4.2 与 short 和 byte 的比较
让我们也检查一下更小的整数类型。
System.out.println(Short.MAX_VALUE); // 32767
System.out.println(Byte.MAX_VALUE); // 127
| Type | Bit width | Maximum value |
|---|---|---|
| byte | 8-bit | 127 |
| short | 16-bit | 32767 |
| int | 32-bit | 2147483647 |
| long | 64-bit | 9223372036854775807 |
典型的使用场景:
- byte → 数据压缩的使用场景
- short → 小规模数值
- int → 常规整数处理
- long → 大型 ID 和时间戳
4.3 何时应该使用 long?
使用 long 的典型情况:
- UNIX 时间戳(毫秒)
- 数据库的 BIGINT 列
- 大型顺序 ID
- 文件大小(字节)
示例:
long timestamp = System.currentTimeMillis();
System.currentTimeMillis() 返回一个 long。
这是因为毫秒级的数值无法放入 int。
4.4 不必要使用 long 的风险
long 占用 8 字节。
int 占用 4 字节。
在处理大量数据时:
- 内存使用增加
- 缓存效率下降
- 性能影响(取决于运行环境)
因此,
如果范围明显适合 int,就使用 int。
这是基本原则。
常见错误与注意事项
- 数据库是 BIGINT,但 Java 使用 int
- 将 JSON 数值接收为 int,尽管它们假设为 long
- 隐式类型转换导致精度丢失
- 直接将
Math.pow的结果赋给 long
类型不匹配导致的 bug 在 API 集成中尤为常见。
5. 处理 long 最大值的实际场景
long 的最大值不仅是理论知识——在实际开发中它非常重要。
理解它至关重要,尤其是在数值溢出可能致命的流程中。
5.1 UNIX 时间戳
在 Java 中获取当前时间:
long now = System.currentTimeMillis();
System.out.println(now);
System.currentTimeMillis() 返回自 1970 年 1 月 1 日以来的毫秒数。
如果将其存入 int:
int now = (int) System.currentTimeMillis(); // Dangerous
数值会被破坏(仅保留低 32 位)。
⚠ 注意
- 强制转换导致截断
- 2038 年问题(基于 int 的时间戳限制)
- 将秒误当作毫秒
使用 long 可避免 2038 年问题。

5.2 与数据库的集成(BIGINT)
在许多数据库中,BIGINT 是 64 位整数。
示例:
CREATE TABLE users (
id BIGINT PRIMARY KEY
);
在 Java 端:
long id;
如果将其接收为 int:
- 数据损坏
- 达到上限时抛出异常
- 缺乏未来可扩展性
⚠ 常见的真实错误
- 起初认为 int 足够 → 后期位数不足
- ORM 中类型映射错误
- JSON 转换期间的数值精度问题(JavaScript 仅安全到 53 位)
5.3 ID 生成与上限
分布式 ID(例如 Snowflake 风格)通常使用 long。
示例:
long id = generateId();
原因:
- 64 位空间足够大
- 可以将序列、时间戳和机器 ID 分割为不同的位段
然而,从理论上讲,long 也有上限。
示例检查:
if (currentId == Long.MAX_VALUE) {
throw new IllegalStateException("ID upper limit reached");
}
在实际中很少会达到该上限,但在系统设计时应予以考虑。
5.4 文件大小计算
获取文件大小:
File file = new File("example.txt");
long size = file.length();
对于大文件,int 并不够用。
⚠ 注意
- 不要将 long 转换为 int
- 数组索引是 int(这就是限制所在)
常见的真实错误
- 在 JSON 中处理 long 时 JavaScript 会出现精度丢失
- 更改数据库列类型后未同步更新 Java 代码
- 使用 long 进行货币计算导致溢出
- 设计持久化 ID 时未考虑上限
6. 关于 long 最大值的常见误解
long 的最大值是一个在搜索结果中存在许多误解的话题。
在这里,我们整理了最令人困惑的点。
6.1 Java 中没有 unsigned long
这对于有 C/C++ 经验的开发者来说尤其令人困惑。
Java 没有:
an unsigned long type
long 始终是一个 64 位有符号整数。
因此,最大正值是:
2^63 - 1
这就是极限。
从 Java 8 开始,添加了以下方法:
Long.compareUnsigned(a, b);
Long.divideUnsigned(a, b);
然而,这些只是用于无符号操作的辅助方法——仍然没有 unsigned long 类型。
6.2 最大值不是 2^64 − 1
网上经常出现的错误信息:
18446744073709551615
这是无符号 64 位整数的最大值。
由于 Java 的 long 是有符号的:
The maximum value is 9223372036854775807
这才是正确的值。
差异总结:
| Type | Maximum value |
|---|---|
| Signed 64-bit | 2^63 – 1 |
| Unsigned 64-bit | 2^64 – 1 |
Java 使用前者。
6.3 BigInteger 和 long 是不同的
BigInteger 表示几乎没有上限的整数。
差异:
| Type | Upper limit | Nature |
|---|---|---|
| long | Fixed 64-bit | Primitive type |
| BigInteger | Virtually unlimited | Object type |
BigInteger:
- 使用更多内存
- 计算更慢
- 比较需要使用 equals()
long:
- 快速
- 轻量级
- 固定范围
根据您的用例选择。
6.4 使用 Math.pow 计算最大值很危险
不正确的示例:
long max = (long) Math.pow(2, 63) - 1;
问题:
- Math.pow 返回 double
- double 具有 53 位精度
- 大整数会出现精度错误
正确方法:
long max = Long.MAX_VALUE;
常见困惑总结
- 认为 unsigned long 存在
- 将其误认为是 2^64 – 1
- 尝试使用 Math.pow 计算它
- 通过 double 转换破坏精度
- 将 BigInteger 与 long 混淆
7. 总结(快速复习)
这里是您在实践中需要的关键点的简洁总结。
7.1 最终答案:long 最大值
- 最大值:9223372036854775807
- 常量:Long.MAX_VALUE
- 公式:2^63 – 1
- 类型:64 位有符号整数
验证代码:
System.out.println(Long.MAX_VALUE);
7.2 您必须遵循的基本规则
- 不要硬编码数字最大值——使用
Long.MAX_VALUE - 编写 long 字面量时添加
L - 不要将其与 int 混淆
- 溢出不会自动抛出异常
7.3 如何防止溢出
安全加法:
Math.addExact(a, b);
如果值可能超过极限:
- 使用 BigInteger
- 实现范围检查
7.4 实践中的重要点
- 将 DB BIGINT 值作为 long 接收
- 使用 long 处理 UNIX 时间戳
- 在 JSON 集成中注意精度
- 设计 ID 系统时考虑上限
7.5 最重要的检查清单
- 您是否错误地使用了 2^64 – 1?
- 您是否假设 unsigned long 存在?
- 您是否使用 Math.pow 计算它?
- 您是否将 long 转换为 int?
- 您是否理解溢出时会发生什么?
long 的最大值不仅仅是需要记忆的东西——它是一个 影响您对整数类型整体理解的核心概念。
FAQ
Q1. Java 的 long 的最大值是什么?
9223372036854775807。
您可以使用 Long.MAX_VALUE 获取它。
Q2. long 有多少位?
它是一个 64 位有符号整数。
1 位用于符号,其余 63 位表示值。
Q3. 如果超过 Long.MAX_VALUE 会发生什么?
不会发生错误。
它会环绕到最小值 (-9223372036854775808)。
System.out.println(Long.MAX_VALUE + 1);
Q4. Java 有 unsigned long 吗?
没有,作为一种类型。
Java 8 及更高版本提供了用于无符号操作的辅助方法,但类型本身始终是有符号的。
Q5. 有一种安全的方式来计算最大值吗?
不要直接计算它。始终使用:
Long.MAX_VALUE
Math.pow() 返回 double,因此对大整数不准确。
Q6. 我应该使用 int 还是 long?
- 如果范围在约 21 亿以内 → 使用 int
- 如果可能超过 → 使用 long
对数据库 BIGINT 列和时间戳使用 long。
Q7. long 能处理多少位数字?
最大值有 19 位数字:
9223372036854775807
Q8. long 与 BigInteger 有何区别?
- long → 固定 64 位,速度快
- BigInteger → 实际上无限制,较慢
如果范围适合 long,使用 long 是标准做法。


