1. 引言

本文将探讨在 Java 中验证字符串是否为有效数字的多种方法。我们将覆盖内置解析方法、正则表达式以及第三方库等不同技术方案。

2. 使用字符遍历法

一种简单粗暴的验证方法是遍历字符串中的每个字符,检查是否为数字:

boolean isNumeric(String str) {
    if (str == null || str.isEmpty()){
        return false;
    }

    int decimalCount = 0;
    boolean hasDigits = false;
    for (char c : str.toCharArray()) {
        if (c == '.') {
            decimalCount++;
            if (decimalCount > 1) {
                return false;
            }
        } else if (Character.isDigit(c)) {
            hasDigits = true;
        } else {
            return false;
        }
    }
    return hasDigits && decimalCount <= 1;
}

这段代码通过逐个字符检查来验证数字字符串:

  • 遇到数字字符继续检查
  • 遇到小数点时计数,超过一个直接返回 false
  • 任何非数字或非小数点字符都会导致验证失败

测试用例验证:

assertTrue(isNumeric("123"));
assertTrue(isNumeric("123.45"));
assertFalse(isNumeric("123a"));
assertFalse(isNumeric("123.45.67"));
assertFalse(isNumeric(""));
assertFalse(isNumeric("."));
assertFalse(isNumeric(null));

⚠️ 这种方法仅能处理基础十进制数(如 123.45),无法识别科学计数法(如 1.23E3)或负数(如 -123)。

3. 使用 Integer.parseInt() 和 Double.parseDouble()

利用 Integer.parseInt()Double.parseDouble() 进行数字转换验证是常见方案:

boolean isInteger(String str) {
    if (str == null) {
        return false;
    }
    try {
        Integer.parseInt(str);
        return true;
    } catch (NumberFormatException e) {
        return false;
    }
}

boolean isDouble(String str) {
    if (str == null){
        return false;
    }
    try {
        Double.parseDouble(str);
        return true;
    } catch (NumberFormatException e) {
        return false;
    }
}

测试用例验证:

assertTrue(isInteger("123"));
assertFalse(isInteger("123.45"));
assertFalse(isInteger("abc"));

assertTrue(isDouble("123.45"));
assertTrue(isDouble("123"));
assertFalse(isDouble("12a"));

✅ 优点:实现简单
❌ 缺点:仅能处理特定数值类型(int/double)且受数值范围限制

4. 使用 BigDecimal

BigDecimal 能处理更大范围的数字格式,是精确数字验证的理想选择:

boolean isBigDecimal(String str) {
    if (str == null) {
        return false;
    }
    try {
        new BigDecimal(str);
        return true;
    } catch (NumberFormatException e) {
        return false;
    }
}

测试用例验证:

assertTrue(isBigDecimal("123.45"));
assertTrue(isBigDecimal("123"));
assertTrue(isBigDecimal("1.23E3"));
assertFalse(isBigDecimal("123abc"));
assertFalse(isBigDecimal(null));

✅ 优势:支持整数、小数和科学计数法
💡 特别适合金融应用等需要高精度计算的场景

5. 使用正则表达式

正则表达式提供灵活的数字格式验证能力:

static final Pattern NUMBER_PATTERN = 
    Pattern.compile("^[-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?$");

boolean isValidNumberRegex(String str) {
    return str != null && NUMBER_PATTERN.matcher(str).matches();
}

正则表达式解析:

  • ^[-+]?:可选正负号
  • [0-9]*:零个或多个数字
  • \\.?:可选小数点
  • [0-9]+:一个或多个数字
  • ([eE][-+]?[0-9]+)?:可选科学计数法部分

测试用例验证:

assertTrue(isValidNumberRegex("123"));
assertTrue(isValidNumberRegex("-123.45"));
assertTrue(isValidNumberRegex("+123.45"));
assertTrue(isValidNumberRegex("1.23E3"));
assertFalse(isValidNumberRegex("123a"));
assertFalse(isValidNumberRegex("123..45"));

✅ 优点:可自定义精确的数字格式
❌ 缺点:复杂模式(如货币格式)会增加维护难度

6. 使用 Apache Commons NumberUtils

Apache Commons Lang 库的 NumberUtils 提供强大的数字验证能力:

首先添加依赖:

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.17.0</version>
</dependency>

使用 NumberUtils.isCreatable() 方法:

assertTrue(NumberUtils.isCreatable("123"));
assertTrue(NumberUtils.isCreatable("123.45"));
assertTrue(NumberUtils.isCreatable("-123.45"));
assertTrue(NumberUtils.isCreatable("1.23E3"));
assertFalse(NumberUtils.isCreatable("123a"));
assertFalse(NumberUtils.isCreatable("12.3.45"));

✅ 优势:一站式支持整数、小数、科学计数法等多种格式
🚀 生产环境推荐方案

7. 总结

本文系统性地探讨了 Java 中验证字符串是否为数字的多种方法:

  • 字符遍历法:基础但功能有限
  • 原生解析方法:简单但类型受限
  • BigDecimal:高精度场景首选
  • 正则表达式:灵活但需维护复杂模式
  • Apache Commons:功能全面的生产级方案

根据具体需求选择合适方案,避免重复造轮子。所有示例代码可在 GitHub 获取。


原始标题:Check if the Given String Is a Valid Number | Baeldung