integer.parseint("ff", 16) 抛 numberformatexception 的主因是字符串含不可见字符或空格,而非进制错误;java 要求输入严格无空白、无前缀、无非十六进制字符,需先 trim() 再解析。

Integer.parseInt("FF", 16) 为什么抛 NumberFormatException
核心问题不是进制写错了,而是字符串里混入了不可见字符或空格。Java 的 Integer.parseInt 对输入极其严格:开头结尾不能有空白,不能有前缀(如 "0x" 或 "0X"),也不能含非十六进制字符(包括全角字母、中文符号、BOM 头)。
常见错误现象:NumberFormatException: For input string: " FF" 或 "ff " —— 看似正常,实则首尾有空格;又或者从文件/HTTP 响应读出的字符串带 UTF-8 BOM("\uFEFFFF"),直接解析必挂。
- 务必先调用
str.trim(),再检查是否为空 - 若来源不可控(如用户输入、日志提取),建议用正则预清洗:
str.replaceAll("[^0-9a-fA-F]", "")(慎用,会删掉所有非十六进制字符,仅适用于纯数据提取场景) - 遇到
"0x"前缀?别手动截取,改用Integer.decode(str),它原生支持"0xFF"、"#FF"、"FF"三种格式
超过 int 范围的十六进制字符串怎么转
Integer.parseInt 只能处理 32 位有符号整数,即最大到 0x7FFFFFFF(2147483647)。一旦字符串表示的值 ≥ 0x80000000(比如 "FFFFFFFF"),就会因溢出抛异常,而不是返回负数——它根本不会尝试“补码解释”,而是直接拒绝。
使用场景:解析网络协议里的无符号 32 位字段、哈希摘要片段、内存地址等,这些本就不该被当“有符号 int”看待。
立即学习“Java免费学习笔记(深入)”;
- 用
Long.parseLong(str, 16)替代,只要不超过0x7FFFFFFFFFFFFFFF都安全 - 若确定是 32 位无符号值(如
"FFFFFFFF"→ 4294967295),用Integer.parseUnsignedInt(str, 16)(JDK 8+),它返回int类型但按无符号逻辑解析 - 极端情况(如 64 位以上十六进制),必须用
BigInteger:new BigInteger(str, 16)
大小写敏感吗?a-f 和 A-F 有区别吗
没区别。Integer.parseInt(str, 16) 内部对字母 a–f 和 A–F 一视同仁,全部映射为 10–15。这不是“兼容模式”,而是规范定义的行为。
但要注意:如果你后续要做字符串比较、缓存 key 或写入日志,大小写不统一可能引发隐性 bug。比如 "ab" 和 "AB" 解析结果相同,但作为 Map key 就是两个不同键。
- 若需标准化输出,解析后再用
String.format("%02X", value)转成大写定长形式 - 避免用原始字符串做 equals 判断,优先比数值结果
- 注意 locale:
String.toUpperCase()在土耳其语环境下可能把'i'转成特殊字符,不要用它来“统一大小写”再解析
性能差异:parseInt vs decode vs valueOf
三者底层几乎一样,但语义和边界行为不同。Integer.valueOf(str, 16) 和 Integer.parseInt(str, 16) 在数值解析阶段完全共用同一套逻辑,区别只在最后一步:前者装箱,后者返基本类型。而 Integer.decode(str) 多一层前缀识别开销,但对不含前缀的字符串,它会 fallback 到 parseInt,实际差距可忽略。
真正影响性能的是字符串本身:长度越长、内容越不规则(如大量无效字符),失败路径越慢(异常构造成本高)。
- 已知格式干净(如固定 8 位 hex),直接用
parseInt最直白 - 输入格式不确定(可能带
"0x"、"#"),选decode,别自己写前缀判断 - 不需要装箱对象,就别用
valueOf,徒增 GC 压力 - 高频调用时,考虑缓存常用 hex 字符串的解析结果,避免重复计算
十六进制解析看着简单,但真实环境里最常栽在不可见字符、无符号边界和前缀处理上。别假设输入“应该”合规,先 trim,再判空,再 decode 或 parseUnsignedInt —— 这三步加起来不到十行,省去半夜查 log 的时间。










