Java泛型方法不能调用另一个约束更宽松的泛型方法并返回其值

2024-04-30

我想这样做:

<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>.

As 约翰内斯·库恩 https://stackoverflow.com/users/845414/johannes-kuhn在他的书中指出comment https://stackoverflow.com/questions/57974748/java-generic-method-cannot-call-another-generic-method-with-looser-constraint-an/57975038#comment102360015_57975038,一个子类Date将隐式实现Comparable<Date>代替Comparable<DateSubclass>,因此需要Comparable<? super T>.

有关更多信息,请参阅:什么是 PECS(生产者扩展消费者超级)? https://stackoverflow.com/questions/2723397/what-is-pecs-producer-extends-consumer-super

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java泛型方法不能调用另一个约束更宽松的泛型方法并返回其值 的相关文章

随机推荐