最稳方法是遍历字符串用Character.isDigit()逐字符判断:1. 先校验null和空串;2. 再检查每个字符是否为数字;3. 避免异常开销并精确区分非法字符与格式问题。

用 Character.isDigit() 逐字符判断最稳
字符串全数字,不等于“能转成整数”,比如 "000"、"12345678901234567890" 都是合法数字字符串,但可能溢出。直接用 Integer.parseInt() 或 Long.parseLong() 捕获异常,看似简单,实则埋雷:一来抛异常成本高,二来无法区分 "123 "(末尾空格)和 "123a"(非法字符)——它们都抛 NumberFormatException,但语义不同。
真正可控的做法是遍历每个字符,用 Character.isDigit() 判断:
public static boolean isAllDigits(String s) {
if (s == null || s.isEmpty()) return false;
for (int i = 0; i < s.length(); i++) {
if (!Character.isDigit(s.charAt(i))) {
return false;
}
}
return true;
}
- 支持任意长度字符串,无溢出风险
- 空字符串、
null显式处理,避免 NPE - 遇到第一个非数字字符立刻返回
false,短路高效 - 注意:
Character.isDigit()能识别 Unicode 数字(如阿拉伯数字、全角数字),若业务只要 ASCII'0'–'9',改用c >= '0' && c
正则 ^\d+$ 看似简洁,但有陷阱
写 s.matches("^\d+$") 是常见直觉,但它在多数场景下不如手动遍历可靠。
-
\d在 Java 正则中匹配所有 Unicode 数字字符(如印度数字、阿拉伯-Indic 数字),不是仅限 ASCII0–9;若输入含"١٢٣"(阿拉伯数字),它会返回true,但后续解析可能失败 - 空字符串
""返回false,符合预期;但要注意matches()内部每次调用都编译正则,高频调用需预编译Pattern - 开头结尾的
^和$必须写全,漏掉任一都会误判:例如"abc123"对"\d+"也匹配成功 - 如果真要用正则且只要 ASCII 数字,写成
"^[0-9]+$"更明确
用 try-catch 解析数字适合“必须转成数值”的场景
如果你下一步**一定需要这个字符串对应的 int 或 long 值**,那异常捕获就不是兜底方案,而是必要流程。此时判断“是否全数字”和“能否安全转换”应合并为一步。
立即学习“Java免费学习笔记(深入)”;
- 别先用正则或遍历“预检”,再调
parseInt()—— 多一次遍历,纯属冗余 - 直接
try { int x = Integer.parseInt(s); },捕获NumberFormatException即可,语义清晰 - 注意范围:
Integer.parseInt()只接受[-2147483648, 2147483647];超长数字得用BigInteger或Long.parseLong(),但后者仍有上限 - 前导零?
"007"可以正常转成7,但若业务要求保留前导零(如编码、ID),就不能靠解析来判断
边界情况:空格、制表符、全角数字、负号
所谓“全是数字”,默认不含空白和符号。但现实输入常带干扰:
- 首尾空格:用
s.trim()预处理,但注意" 123 "这类也要考虑;若允许中间空格(如"12 34"),那就根本不是“全数字”了 - 负号/小数点:它们不是数字字符,
"-123"或"12.34"应该被isAllDigits()拒绝;若需支持,就得换逻辑(比如先校验格式再解析) - 全角数字(如
"123"):Unicode 中属于Nd类别,Character.isDigit()返回true,但Integer.parseInt()会失败;业务若明确拒绝全角,得额外检查Character.UnicodeBlock.of(c) != Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS
最麻烦的从来不是“怎么写”,而是“业务到底要什么数字”——是 ASCII 数字?是否允许前导零?是否接受全角?这些定义不清,代码越写越像补丁。










