Long.parseLong() 不应处理越界字符串,需预校验:长度筛(≤20位)、字符合规(仅数字和可选负号)、字典序比对边界值;统一封装校验入口;超范围场景直接用 BigInteger。

别让 Long.parseLong() 承担它不该干的活——它只负责解析合法 long 范围内的字符串,超出就抛异常,这不是 bug,是设计。防止溢出的关键,是**不给它解析越界字符串的机会**。
字符串预校验:三步筛掉非法输入
在调用 parseLong() 前,用轻量级静态检查提前拦截。这比抛异常快得多,也更可控:
- 长度初筛:合法 long 十进制字符串最多 19 位(正数)或 20 位(含负号)。长度 > 20 的直接拒绝;长度 = 20 但首字符不是 '-',也拒绝
- 字符合规性检查:除首位可为 '-' 外,其余必须全是 '0'–'9';禁止空格、'+'、小数点、字母、下划线、逗号等
-
边界字典序比对(严格场景用):对长度为 19 或 20 的字符串,和
"9223372036854775807"(Long.MAX_VALUE)或"-9223372036854775808"(Long.MIN_VALUE)逐字符比较。比如"9223372036854775808"字典序大于最大值 → 溢出
统一入口封装:杜绝裸调 parseLong
团队里没人该直接写 Long.parseLong(s)。提供一个工具方法,把校验逻辑收口进去:
- 方法签名明确表达意图,例如
Longs.tryParse(String s)或Longs.requireValid(String s) - 内部整合 trim、长度判断、字符扫描、字典比对(可选),校验失败返回
null或抛自定义业务异常 - 所有上游代码强制走这个入口,避免遗漏或绕过
超范围场景直接用 BigInteger
如果输入本身就可能超 long(比如 ID、订单号、加密标识),那就别硬往 long 里塞:
立即学习“Java免费学习笔记(深入)”;
- 接口层接收时就按
String处理,JSON 反序列化配置 Jackson 的USE_BIG_INTEGER_FOR_INTS,或 Gson 注册BigIntegerTypeAdapter - 解析一步到位:
new BigInteger(s.trim()),它能安全处理任意长度十进制整数,格式非法才抛异常 - 后续所有运算(比较、加减、取模)都用
BigInteger方法,比如a.compareTo(b) > 0判断大小,a.equals(b)判断相等
需要转回 long?只在确认安全时操作
BigInteger 不是过渡工具,而是最终类型。真要转 long,必须显式承担风险:
- 用
bigInt.longValueExact()—— 它在溢出时抛ArithmeticException,语义清晰,比静默截断强百倍 - 不要用
bigInt.longValue(),它会默默丢高位,结果不可信 - 如果只是用于日志、展示或传给下游 API,保留字符串或 BigInteger 更稳妥


















