我想这样做:
<T extends java.util.Date> T a(@Nonnull T... dates) {
return b(dates); // compile error
}
<T extends Comparable<T>> T b(T... comparables) {
return comparables[0];
}
但是除非我在
a
中插入强制类型转换,否则它无法编译:<T extends java.util.Date> T a(@Nonnull T... dates) {
return (T) b(dates); // warning about unsafe cast in IntelliJ
}
<T extends Comparable<T>> T b(T... comparables) {
return comparables[0];
}
有趣的是,如果我从
a
中删除了泛型,它将起作用:java.util.Date a(java.util.Date... dates) {
return b(dates);
}
<T extends Comparable<T>> T b(T... comparables) {
return comparables[0];
}
而且,如果我将原始代码移植到Kotlin,它也可以工作(这使我认为这是Java的限制,而不是根本上不可知的东西):
fun <T: java.util.Date> a(dates: Array<T>): T {
return b(dates);
}
fun <T: Comparable<T>> b(comparables: Array<T>): T {
return comparables[0];
}
我的问题是:Java的类型系统有什么特殊之处可阻止此类型的编译?在我看来,Java编译器可以只在后台插入强制类型转换(据我了解,这就是在其他情况下实现泛型的方式)。
最佳答案
无需强制转换即可将其编译。相反,当指定T
必须扩展Comparable<T>
时,可以使用有界通配符:
<T extends java.util.Date> T a(T... dates) {
return b(dates); // compiles fine
}
<T extends Comparable<? super T>> T b(T... comparables) {
return comparables[0];
}
注意
Comparable<? super T>
而不是Comparable<T>
。正如Johannes Kuhn在其comment中指出的那样,
Date
的子类将隐式实现Comparable<Date>
而不是Comparable<DateSubclass>
,因此需要Comparable<? super T>
。有关更多信息,请参见:What is PECS (Producer Extends Consumer Super)?