3

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

在 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) {
        // ...
    }
}

我怎样才能让它再次工作?

4

3 回答 3

3

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

IConverter<C>

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

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 以使编译器安静。或者使用您的解决方法,您将进入原始类型,从而回避问题。

于 2012-01-02T11:31:45.767 回答
0

我不知道为什么,但是 getConverter 方法的以下小改动使它可以编译。

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

我刚刚将 MonetaryBigDecimalConverter 实例提取到type 的变量中IConverter。字段或常量的工作方式类似。(注意:类型不能IConverter<C>or IConverter<BigDecimal>。)这段代码仍然会产生“未经检查的赋值”警告,但至少它可以编译。

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

于 2011-12-29T13:51:23.240 回答
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 类型的转换器”(当传递的参数是另一种类型时,这可能是错误的),而是说“我返回任何类型的 IConverter”(这对于在 Java 1.5 中引入泛型时的向后兼容性原因,但当然可以抛出RuntimeException)

于 2018-06-25T12:46:32.107 回答