業務開發中頻繁需要校驗字符串是否為合法數字。本文對比正則、異常捕獲、工具類三種方案,給出生產環境推薦選型。
public static boolean isNumeric(String str) {
if (str == null || str.isEmpty()) return false;
try {
Double.parseDouble(str); // 或 Float.parseFloat / Long.parseLong
return true;
} catch (NumberFormatException e) {
return false;
}
}
// 整數(含正負)
private static final Pattern INT_PATTERN = Pattern.compile("^[-+]?\\d+$");
// 浮點數(含科學計數法)
private static final Pattern DOUBLE_PATTERN = Pattern.compile("^[-+]?(\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?$");
public static boolean isNumericRegex(String str) {
return str != null && DOUBLE_PATTERN.matcher(str).matches();
}
org.apache.commons
commons-lang3
3.13.0
// 使用
NumberUtils.isCreatable(str); // 可解析為 Number(含 0xFF, 1L, 1.0F 等)
NumberUtils.isParsable(str); // 可直接 parse(不含前綴)
// 或 Hutool
StrUtil.isNumber(str);
isCreatable/isParsable 區分度高)| 方法 | 平均耗時 (ns/op) | 相對性能 |
|---|---|---|
| Double.parseDouble + try-catch | ~1200 | 1x (基準) |
| 正則 Pattern.matches | ~800 | 1.5x |
| NumberUtils.isParsable | ~300 | 4x |
| 手寫字符遍歷 (最優) | ~150 | 8x |
public static boolean isNumericFast(String str) {
if (str == null || str.isEmpty()) return false;
int i = 0, len = str.length();
if (str.charAt(0) == '-' || str.charAt(0) == '+') {
if (len == 1) return false; // 只有符號
i = 1;
}
boolean hasDigit = false;
for (; i < len; i++) {
char c = str.charAt(i);
if (c >= '0' && c <= '9') {
hasDigit = true;
} else if (c == '.' && !hasDigit) { // 簡化:僅允許一個小數點,且前面有數字
// 實際需更複雜邏輯處理科學計數法等
return false;
} else {
return false;
}
}
return hasDigit;
}
Double.parseDouble + try-catch,零依賴、語義最清晰Patterncommons-lang3 使用 NumberUtils.isParsable()null → false
"" → false
"123" → true
"-123" → true
"+123" → true
"12.34" → true
"1.23e-4" → true (parseDouble/NumberUtils 支持)
"0xFF" → true (NumberUtils.isCreatable) / false (isParsable)
"123L" → true (isCreatable) / false (isParsable)
" 123 " → false (需先 trim)
"12 34" → false
"abc" → false