在番石榴中,为什么只用"T"就可以使用"?super T"?

mat*_*tts 8 java generics guava bounded-wildcard

为什么实用工厂方法经常使用特定的通用参数(如T)而不是有界通配符参数(如? super T)?

例如,Functions#forPredicate的签名是:

public static <T> Function<T, Boolean> forPredicate(Predicate<T> predicate)
Run Code Online (Sandbox Code Playgroud)

为什么不使用:

public static <T> Function<T, Boolean> forPredicate(Predicate<? super T> predicate)
Run Code Online (Sandbox Code Playgroud)

哪个会产生如下可能的东西?

Predicate<Number> isPositivePredicate = ...
Function<Integer, Boolean> isPositiveInteger = Functions.forPredicate(isPositivePredicate);
// above line is compiler error:
//   Type mismatch: cannot convert from Function<Number,Boolean> to Function<Integer,Boolean>
Run Code Online (Sandbox Code Playgroud)

是不是因为消费者Function,并Predicate预计将有必要界通配符参数,使这种不必要的?例如,Iterables #ref的泛型边界允许Predicate<Number>在以下情况下使用a Iterable<Integer>:

public static <T> T find(Iterable<T> iterable,
                         Predicate<? super T> predicate)
Run Code Online (Sandbox Code Playgroud)

还有其他原因吗?

Lou*_*man 6

是的,绝对准确的是我们希望消费者拥有正确的有界通配符参数,但还有两个额外的原因:

  • 通常,在我们有特定原因之前,我们不会扩展泛型方法的类型.这项政策多次得到了回报.
  • Java的类型推断并不总是自动计算出更高级的泛型,因此保持较窄的泛型会减少需要明确指定的用户数量T.