德国locale下DoubleValidator校验"17.12"异常,求Java合规校验方案
原校验器返回异常结果的原因
- 你使用的
org.apache.commons.validator.routines.DoubleValidator核心设计偏向宽松容错,而非严格匹配数字格式规范 - 针对德语区Locale(
Locale.GERMANY),该类内置的规则定义为:.是千位分隔符、,是小数分隔符 - 当传入字符串
"17.12"时,校验器会直接把出现的.作为千位分隔符跳过,拼接剩余内容"1712"后转成1712.0返回,完全不会因为.出现在小数位位置判定格式非法。这就是你遇到的解析结果和预期不符的核心原因。
符合校验规则的替代实现
要实现你要求的严格校验效果,可以使用JDK内置的数字格式化工具做全字符串匹配,完全按照对应Locale的格式规则判定合法性,不会做冗余的容错处理。
实现代码
import java.text.NumberFormat; import java.text.ParsePosition; import java.util.Locale; public class StrictNumberValidator { public static Double validate(String numberStr, Locale locale) { // 空值入参直接返回null if (numberStr == null || numberStr.isBlank()) { return null; } // 获取对应Locale的通用数字格式化实例 NumberFormat numberFormat = NumberFormat.getInstance(locale); ParsePosition parsePos = new ParsePosition(0); Number parseResult = numberFormat.parse(numberStr, parsePos); // 仅当解析有结果、且整个字符串被完全消费无残留时,才返回解析值 if (parseResult != null && parsePos.getIndex() == numberStr.length()) { return parseResult.doubleValue(); } // 其余情况全部判定为格式非法,返回null return null; } }
注意:NumberFormat 实例不具备线程安全性,上述代码在方法内部每次创建格式化实例的写法,可直接在并发场景下安全使用,不会出现线程抢占导致的解析异常。
校验效果匹配验证
基于上述严格匹配逻辑,可完全覆盖你的预期规则:
- 传入
"17.12"搭配Locale.GERMANY:字符串里的.出现在本该是小数分隔符的位置,无法通过全格式匹配,返回null - 传入
"17,12"搭配Locale.GERMANY:完全匹配德语区小数格式规则,返回17.12 - 传入
"1.017,12"搭配Locale.GERMANY:正确识别.为千位分隔符、,为小数分隔符,返回1017.12
内容的提问来源于stack exchange,提问作者Serr
相关产品推荐
相关产品推荐

