任何人都可以用简单的术语解释为什么在下面的类中,当我传入String,Integer或UUID时,只使用以Object作为参数的方法重载?
public final class SkuHydratingConverter implements Converter<Object, Sku> {
@Autowired
private SkuService skuService;
/**
* Default implementation, that errs as we don't know how to convert from
* the source type.
*/
public Sku convert(Object source) throws IllegalArgumentException {
throw new IllegalArgumentException("Could not convert to Sku");
}
public Sku convert(String source) throws IllegalArgumentException {
return convert(Integer.valueOf(source));
}
public Sku convert(Integer source) throws IllegalArgumentException {
return skuService.get(source);
}
public Sku convert(UUID source) throws IllegalArgumentException {
return skuService.get(source);
}
}
最初我想在一堂课中实施三次Converter<?, ?>
,但我很快发现这是不可能的。
答案 0 :(得分:4)
重载机制在编译时工作,也就是说,在编译类时决定调用哪个方法,而不是在运行程序时。
由于运行时类型(通常)在编译时不能知道,所以像这样的代码片段
Object o = "some string";
method(o);
将调用以method
为参数的Object
,因为Object
是o
的{{3}}。
(这与类型擦除或泛型无关。)
答案 1 :(得分:1)
您实际为Converter实现的方法只是转换(对象源),因为您在:
中提供了类型参数ObjectConverter<Object, Sku>
另外两个带有String和UUID参数的转换方法只有在直接使用实例(而不是通过接口)时才能调用。这两种方法不会覆盖任何东西,它们会超载。
Converter con = new SkuHydratingConverter();
con.convert(new String());//calls convert(Object), it does not know about any other method
SkuHydratingConverter con2 = new SkuHydratingConverter();
con2.convert(new String()); //calls convert(String), because it is one with best matching type of argument.
答案 2 :(得分:0)
正如其他人所解释的那样,这与擦除无关,而是convert(Object source)
在编译时受到约束的事实。如果你在每个之前放置一个@Override
,你将在其余部分得到错误,表明只有那个方法覆盖了超类方法。
您需要的是运行时检查实际类型:
public Sku convert(Object source) throws IllegalArgumentException
{
if (source instanceof String) {
return convert((String) source);
} else if (source instanceof ...) {
} else // none match, source is of unknown type
{
throw new IllegalArgumentException("Could not convert to Sku, unsuported type " + source.getClass());
}
}
}
其他convert
方法应为private
。