如何在Wicket 1.5中将自定义BigDecimal转换器设置为TextField <bigdecimal>?</bigdecimal>

时间:2011-12-29 08:41:08

标签: java compiler-errors wicket wicket-1.5

从1.4升到1.5,除了documented ones之外,似乎还有许多未记录的更改。

在1.4我有:

new TextField<BigDecimal>("capitalInput", 
        new PropertyModel<BigDecimal>(model, "capital")) {
    @Override
    public IConverter getConverter(Class<?> type) {
        return new MonetaryBigDecimalConverter();
    } 
};

使用1.5,我改变了这一点(以匹配现在声明getConverter()的方式):

new TextField<BigDecimal>("capital", 
        new PropertyModel<BigDecimal>(model, "capital")) {
    @Override
    public <C> IConverter<C> getConverter(Class<C> type) {
        return new MonetaryBigDecimalConverter();
    }
};

我的IDE显示为未选中的分配警告。但是然后尝试构建项目它实际上是编译错误

incompatible types
found   : com.company.MonetaryBigDecimalConverter
required: org.apache.wicket.util.convert.IConverter<C>

自定义MonetaryBigDecimalConverter看起来像这样(1.5):

public class MonetaryBigDecimalConverter extends BigDecimalConverter {
    @Override
    public String convertToString(BigDecimal value, Locale locale) {
        // ...
    }
}

如何重新开始这项工作?

3 个答案:

答案 0 :(得分:3)

由于Wicket 1.5转换器具有泛型类型参数:

IConverter<C>

请注意,#getConverter()的类型参数C未绑定到文本字段的type参数,因此您应该测试所请求的类型:

new TextField<BigDecimal>("capital", 
        new PropertyModel<BigDecimal>(model, "capital")) {
    @Override
    public <C> IConverter<C> getConverter(Class<C> type) {
        if (type == BigDecimal) {
            return (IConverter<C>) new MonetaryBigDecimalConverter();
        } else {
            return super.getConverter(type);
        }
    }
};

您必须明确地将转换器转换为请求的IConverter以安静编译器。或者使用您的解决方法,您将陷入原始类型,从而避开问题。

答案 1 :(得分:0)

我不知道为什么,但是getConverter方法中的以下小变化使它编译。

@Override
public <C> IConverter<C> getConverter(Class<C> type) {
    IConverter converter = new MonetaryBigDecimalConverter();
    return converter;
}

我刚刚将MonetaryBigDecimalConverter实例提取为类型为IConverter变量。字段或常量可以类似地工作。 (注意:类型必须IConverter<C>IConverter<BigDecimal>。)此代码仍会生成“未经检查的分配”警告,但至少会编译。

如果有人添加了解释或更好的解决方案,我将不胜感激。当谈到Java泛型奇怪时,我当然不是专家。

答案 2 :(得分:0)

由于返回值是从运行时传递给方法的任何参数派生的,因此Java无法确定返回类型,并且始终需要强制转换。

另一方面,如果在编译时就已经知道返回类型,那么您将能够使用更智能的方法。 (例如,当Component是确定C类型而不是传递给它的参数的泛型类型时):

Component myConverter = new Component<BigDecimal>() {
    @Override
    public IConverter<BigDecimal> getConverter() {
        return new MonetaryBigDecimalConverter();
    }
};

class Component<C> { // <-- Type of C is known at compile time!
    public IConverter<C> getConverter() {
        return null;
    }
}

因为编译器现在知道getConverter方法将返回IConverter<BigDecimal>的事实,所以不需要强制转换。


您自己的变量提取解决方案与强制转换为原始类型IConverter相同,这也是可能的。无需解压缩。

@Override
public <C> IConverter<C> getConverter(Class<C> type) {
    return (IConverter) new MonetaryBigDecimalConverter();
}

当转换为原始类型时,不是说“我返回BigDecimal类型的Converter”(当传递的参数是另一种类型时可能会出错),而是说“我返回任何IConverter”(即当Java 1.5中引入泛型时,由于向后兼容的原因,它成为可能,但是当然可以抛出RuntimeException