bigywater.tech
Java 内部原理 · 109

Integer.parseInt() 真实验证:溢出真实抛异常,不像int运算那样静默回绕

系列前面验证过int运算溢出会真实静默回绕成一个诡异的负数,这篇真实对比parseInt()解析超出范围的字符串——结果完全不同:它真实选择了报错,而不是给你一个错误但看起来正常的数字。

MAX_VALUE+1字符串真实抛异常
真实验证:parseInt("2147483648")真实抛出NumberFormatException,不会像int算术那样悄悄变成负数
int运算溢出真实静默回绕
真实对照:Integer.MAX_VALUE+1这个int算术表达式真实结果是-2147483648,完全不报错——和parseInt()形成鲜明对比

上一篇:final字段与clone()真实验证

真实验证:parseInt()支持2到36进制解析

带radix参数的parseInt()重载,真实支持的进制范围有多广?

IntegerParseIntRadixDemo.java Integer.parseInt("1010", 2); Integer.parseInt("ff", 16); Integer.parseInt("z", 36);
真实实测
parseInt("1010", 2) 二进制真实结果: 10
parseInt("ff", 16) 十六进制真实结果: 255
parseInt("777", 8) 八进制真实结果: 511
parseInt("z", 36) 36进制真实结果: 35(36进制z真实代表35,是最大单字符)

真实结果验证了 parseInt(String, int radix) 真实支持从2进制到36进制的解析——36是数字(0-9共10个)加上字母(a-z共26个)能表示的单字符最大基数,这也是为什么 "z" 在36进制下真实代表十进制的 35(字母表里的最后一个,对应最大的单字符数值)。

真实验证:超出int范围时,真实抛异常而不是静默回绕

这是本次实验的核心对比:字符串解析出的值超过Integer.MAX_VALUE,真实会怎样处理?

IntegerParseIntRadixDemo.java Integer.parseInt("2147483648"); // MAX_VALUE + 1 int overflowed = Integer.MAX_VALUE + 1; // 对照:int算术运算
真实实测
parseInt("2147483648") 真实抛出 NumberFormatException: For input string: "2147483648"
Integer.MAX_VALUE 真实是: 2147483647
parseInt("2147483647") 真实结果(刚好是MAX_VALUE): 2147483647

int运算 Integer.MAX_VALUE + 1 真实结果(静默回绕): -2147483648
两种完全不同的"错误处理哲学"。这组真实对比揭示了 Java 里两套截然不同的溢出处理策略:int 类型的算术运算(+、-、* 等)遵循的是"位运算式"的静默回绕——超出 int 能表示的范围时,高位真实被直接截断丢弃,结果变成一个数值上完全错误、但语法上合法的 int(这里真实变成了 Integer.MIN_VALUE),不会有任何异常或警告提醒你出了问题。而 Integer.parseInt() 作为一个"把外部输入转换成内部类型"的边界函数,真实选择了完全相反的策略——一旦发现字符串代表的数值超出 int 能装下的范围,立刻真实抛出 NumberFormatException,拒绝给出一个错误的数字。这个设计差异本质上是"内部运算追求性能、信任调用者"和"外部输入必须校验、不信任来源"这两种不同场景该采用的合理策略。

真实验证:MIN_VALUE边界、非法字符、空字符串的真实处理

真实实测
parseInt("-2147483648") 真实结果(刚好是MIN_VALUE): -2147483648
parseInt("-2147483649") 真实抛出 NumberFormatException: For input string: "-2147483649"
parseInt("12a3") 真实抛出 NumberFormatException: For input string: "12a3"
parseInt("") 真实抛出 NumberFormatException: For input string: ""
parseInt("+123") 真实结果: 123(真实支持显式正号)

真实结果进一步验证了 parseInt() 严格的边界校验:-2147483648(Integer.MIN_VALUE)恰好能被正确解析,但再小一点(-2147483649)就真实越界抛异常——这里有一个隐藏的真实细节:int 的正数范围比负数范围少1(因为0算在正数那一侧),Integer.MIN_VALUE 这个特殊边界值没有对应的正数,parseInt() 内部对这个边界做了真实的特殊处理,不是简单粗暴地先解析出正数再取负。包含非法字符("12a3")、空字符串同样真实统一抛出 NumberFormatException,不会返回0或截断解析出部分结果——这种"宁可失败也不给出可能误导人的结果"的设计,是所有涉及外部输入解析的API都值得借鉴的真实范例。

分步演示:两种溢出处理哲学的真实对照

每一行都是真实运行这段代码得到的结果或异常。

同样是"超出 int 范围",parseInt() 真实抛异常,int 算术运算真实静默回绕
这一步新验证的调用

    参考与说明

    • 本文全部结果均在本机真实运行 Java 17 得到,各类边界和异常场景重复运行完全一致。
    • 和int溢出那篇一起看,能更完整理解Java里"内部算术运算静默溢出"和"外部输入解析严格校验"这两种截然不同、但各自合理的设计取向。
    • 没有涉及:Long.parseLong()/Double.parseDouble()是否遵循同样的严格校验策略(结论是遵循同样的哲学,但浮点数解析对特殊值NaN/Infinity字符串有额外的真实支持)、Integer.parseInt()内部实现是否针对常见的短字符串做了性能优化——这两个话题留给系列后面按需再写。
    京ICP备2026067502号-1京公网安备11010502063487号