不能直接(int)system.currenttimemillis(),因为当前时间戳已超int范围,强转会截断高32位导致确定性负数错误;应除1000转秒级或用math.tointexact校验。

System.currentTimeMillis() 返回的是毫秒级时间戳,类型为 long,值在 2026 年约为 178 亿左右(17,800,000,000),远超 int 的最大值(2,147,483,647)。直接强转成 int 必然溢出,结果为负数,比如 -1890658190,完全不可用。
为什么不能 (int) System.currentTimeMillis()
Java 中的强制类型转换 (int) longValue 不做任何检查,只是简单截断高 32 位,保留低 32 位按补码解释。这意味着:
- 只要 long 值 ≥ 2147483648 或 ≤ -2147483649,转换后就是错误的负数或小正数
- 当前时间戳已稳定超过 170 亿,每次强转都必然出错
- 不是“偶尔出问题”,而是“每次必错”——这是确定性行为,不是 bug 而是语言规则
正确处理时间戳单位与类型匹配
多数业务并不真需要毫秒级 int,关键在于明确单位和用途:
- 如需秒级时间戳(例如存数据库、做排序键、传给老接口),先除以 1000 再转:
int sec = (int) (System.currentTimeMillis() / 1000); - 若必须用毫秒且限定在 int 范围内(极少见),需确认时间范围是否严格落在 1970–2038 年之间,并加校验
- 前端传来的毫秒时间戳,后端解析后别直接 cast,先看协议:是秒还是毫秒?再决定是否除 1000
安全转换的两种可靠方式
不依赖隐式截断,用显式逻辑保障数据正确:
-
使用 Math.toIntExact(推荐):
它会在超出 int 范围时抛ArithmeticException,让你立刻发现问题:try { int ts = Math.toIntExact(System.currentTimeMillis() / 1000); } -
手动范围检查(适合需自定义 fallback 的场景):
判断是否在 [Integer.MIN_VALUE, Integer.MAX_VALUE] 内,再转;否则走降级逻辑(如记录告警、返回默认值)
避免中间计算溢出(常被忽略的坑)
不只是最终赋值,连时间运算过程也容易翻车:
- 错误写法:
System.currentTimeMillis() + 30 * 24 * 60 * 60 * 1000
其中30 * 24 * 60 * 60 * 1000是 int 运算,早于 long 加法就已溢出 - 正确写法:
System.currentTimeMillis() + 30L * 24 * 60 * 60 * 1000或System.currentTimeMillis() + TimeUnit.DAYS.toMillis(30) - 所有涉及大常量的算术表达式,建议显式加
L后缀,或用 TimeUnit 等工具类,杜绝隐式类型陷阱











