当谈到从字符串中解析带有小数分隔符的数字时,Wicket 的 BigDecimalConverter 的行为不同于 BigDecimal 的 (String val) 构造函数。
让我们尝试使用美国语言环境解析一个以逗号作为小数点分隔符的数字。 (顺便说一句,我使用的是 Wicket 1.4.14。)
new BigDecimalConverter().convertToObject("1,3", Locale.US)
返回 13
,
但是
Locale.setDefault(Locale.US);
new BigDecimal("1,3")
抛出 NumberFormatException
。
在这种情况下,为什么 BigDecimalConverter 的行为方式与 BigDecimal 不同?数字“1,3”对于美国语言环境没有意义。
最佳答案
BigDecimal
类在输入上实现了自己的验证算法,该算法会抛出 NumberFormatException
。
BigDecimalConverter
将 1,3
解析为 13
的原因是它使用了原始 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 !
更新
DecimalFormat
忽略 ,
字符的原因是因为它在美国语言环境的 DecimalFormatSymbols
中被定义为分组分隔符。
它是允许的,并且是合法的,就像在 1,300.5
中一样。
如果您想避免将 1,3
转换为 13
,并抛出无效的格式转换异常,您可以覆盖 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);
注意:谨慎使用上面的示例,为 Converter 创建一个类,这样它就不会在每次调用 getConverter()
时被实例化,也不要修改 NumberFormat
实例 BigDecimalConverter.getNumberFormat()
返回,它可能是一个全局共享实例。
补充一下,这是忽略作为组分隔符的 ,
字符的确切代码:DecimalFormat.subparse()
branch in line 1522 .输入 1,3
时,逗号将被忽略,isGroupingUsed()
为真。
关于java - BigDecimal 语言环境特定解析 - Wicket 的 BigDecimalConverter 和 java.math.BigDecimal 之间的不一致,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8010288/