从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) {
// ...
}
}
我怎样才能使它再次工作?
由于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以静默编译器。或者使用您的变通方法,您可以使用原始类型,从而避开问题。
我不知道为什么,但是getConverter方法中的以下小变化使其编译。
@Override
public <C> IConverter<C> getConverter(Class<C> type) {
IConverter converter = new MonetaryBigDecimalConverter();
return converter;
}
我刚刚将MonetaryBigDecimalConverter实例提取到类型为IConverter
的变量中。字段或常数的工作原理类似。(注意:类型不能为IConverter<C>
或IConverter<BigDecimal>
。)这段代码仍然会产生"未检查的赋值"警告,但至少它可以编译。
因为返回值是从运行时传递给方法的任何参数派生的,所以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
)