应根据数据范围、内存压力、运算逻辑和JVM行为选择int或long:int为32位(±21.4亿),long为64位(±9.2×10¹⁸);超范围会导致静默溢出,时间戳、bigint主键、高值计数器必须用long;百万级数组中long比int多占4MB内存;避免盲目“宁大勿小”,小范围值可用byte/short;运算需用Math.addExact()等防溢出;注意Long缓存范围及JVM字段对齐影响。

Java 中整数(int)和长整型(long)看似简单,但选错类型可能引发溢出、内存浪费甚至隐性性能问题。关键不在“能不能用”,而在“该不该用”——这取决于数据范围、内存压力、运算逻辑和 JVM 行为。
整数与长整型的存储边界必须清楚
int 是 32 位有符号整型,取值范围是 -2,147,483,648 到 2,147,483,647;long 是 64 位,范围达 ±9.2×10¹⁸。超出 int 范围却硬用 int,会导致静默溢出(如 Integer.MAX_VALUE + 1 变成负数),而非报错。
- 时间戳(毫秒级)必须用 long:自 1970 年以来的毫秒数早已远超 int 上限
- 数据库主键若为 bigint 类型,Java 端对应字段应声明为 long,避免截断或转换异常
- 计数器类场景(如 PV/UV 统计)若预期峰值超 20 亿,int 就不够用,需提前升为 long
内存占用差异直接影响大规模数组性能
一个 int 占 4 字节,long 占 8 字节。在百万级元素的数组中,差别显著:
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
-
int[1_000_000]占约 4MB;long[1_000_000]占约 8MB —— 翻倍不是数字游戏,而是 GC 压力与缓存行利用率的实际负担 - 若业务仅需存 0–65535 的 ID(如设备编号),用 short 更省空间;但注意:short 运算会自动提升为 int,不会节省 CPU 运算开销
- 避免“宁大勿小”惯性:比如日志中的 HTTP 状态码(0–999)、协议版本号(通常 ≤ 10),用 byte 完全足够且更紧凑
运算与溢出检测不能依赖直觉
Java 不做运行时溢出检查,+、-、* 等运算溢出后结果错误但不抛异常。尤其要注意:
立即学习“Java免费学习笔记(深入)”;
- 不要用
==比较两个 long 值是否相等?可以——但别用==比较包装类Long,除非值在 -128~127 缓存范围内(参考 Integer 缓存池机制,Long 同样有缓存,但默认只缓存 -128~127) - 涉及累加、乘法等易溢出操作,优先使用
Math.addExact()、Math.multiplyExact()等方法,它们会在溢出时明确抛出ArithmeticException - 对用户输入或外部接口返回的数值做校验时,应主动判断是否在目标类型范围内,而非等到计算出错才暴露问题
JVM 层面对齐与 CPU 效率的隐藏影响
现代 CPU 对 64 位数据读写更友好,但前提是数据自然对齐。JVM 对 long 和 double 的字段默认按 8 字节对齐,而 int 是 4 字节。混用不同大小字段可能导致填充字节(padding),间接增加对象体积。
- 定义 POJO 时,把 long 字段集中放在前面或后面,有助于减少因对齐产生的内存浪费
- 使用
-XX:+UseCompressedOops(默认开启)可压缩对象引用,但 long 字段不受此优化影响,其固定占 8 字节 - 高吞吐场景下(如高频交易、实时风控),批量处理 long 数组时,考虑使用
ByteBuffer.allocateDirect()或Unsafe直接内存,绕过堆 GC 压力(需谨慎管理生命周期)


















