从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) {
// ...
}
}
如何重新开始这项工作?
答案 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
)