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

标签 java wicket bigdecimal

当谈到从字符串中解析带有小数分隔符的数字时,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

BigDecimalConverter1,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/

相关文章:

java - Wildfly 13 gzip 过滤器属性

java - 结合工厂方法和单例设计模式

Java - 初始化数组后以及使用类方法测试数组时出现 NullPointerException

Wicket 口中的javascript注入(inject)

java - 无法让 Canvas/CanvasLayer 在 Playn 中工作

java - 来自数据库的 validator 消息的自定义 Wicket 口

java - 将外部文件夹挂载为 Wicket 中的资源

java - 如何使用 Streams 平均 BigDecimals?

mysql - 无法将 bigdecimal 分配给模型中的字段

java - 格式化大十进制。 JavaFX