BigDecimal特定于语言环境的解析 - Wicket的BigDecimalConverter和java.math.BigDecimal之间的不一致

pra*_*pes 1 java wicket bigdecimal

当使用字符串中的十进制分隔符解析数字时,Wicket的BigDecimalConverter的行为与BigDecimal的(String val)构造函数不同.

让我们尝试用逗号作为使用美国语言环境的小数分隔符来解析数字.(我正在使用Wicket 1.4.14 BTW.)


new BigDecimalConverter().convertToObject("1,3", Locale.US)
回来13,



Locale.setDefault(Locale.US);
new BigDecimal("1,3")  
Run Code Online (Sandbox Code Playgroud)

抛出NumberFormatException.


在这种情况下,为什么BigDecimalConverter的行为与BigDecimal不同?数字"1,3"对于美国语言环境没有意义.

Xav*_*ica 6

BigDecimal类实现输入,这是抛出了自己的验证算法NumberFormatException.

为什么原因BigDecimalConverter被解析1,313的是,它使用的是原始DecimalFormat的幕后.在AbstractNumberConverter.parse(),getNumberFormat(locale)parse()方法组合归结为以下片段,将Wicket从等式中取出:

NumberFormat format = NumberFormat.getInstance(Locale.US);
format.setParseBigDecimal(true);
BigDecimal bd = format.parseObject("1,3");
System.out.println(bd.toString()); // Prints 13 !
Run Code Online (Sandbox Code Playgroud)

更新DecimalFormat忽略该,字符 的原因是因为它被定义为DecimalFormatSymbols美国语言环境中的分组分隔符.它是允许的,并且是合法的1,300.5.

如果你想避免转换1,313,并抛出一个无效的格式转换的异常,你可以重写BigDecimalConverter.getNumberFormat(Locale),以修改DecimalFormat不使用分组,使用不同的分组符号,或者使用更严格的模式.例如:

TextField<BigDecimal> text = new TextField<BigDecimal>(id, model){
    @Override
    public IConverter getConverter(Class<?> type) {
        return new BigDecimalConverter() {
            @Override
            public NumberFormat getNumberFormat(Locale locale) {
                NumberFormat format = super.getNumberFormat(locale);
                format.setGroupingUsed(false);
                return format;
            }
        };
    }
};
text.setType(BigDecimal.class);
Run Code Online (Sandbox Code Playgroud)

注意:请谨慎使用上面的示例,为Converter创建一个类,这样它在每次调用时都不会被实例化,getConverter()也不会修改NumberFormat实例BigDecimalConverter.getNumberFormat()返回,它可能是一个全局共享实例.

只是要添加,这是忽略,作为组分隔符的字符的确切代码:DecimalFormat.subparse()第1522行中的分支.输入后1,3,逗号被忽略,为isGroupingUsed()真.