Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In guava, why is just "T" used where "? super T" would be possible?

Why do the utility factory methods often use a specific generic parameter (like T) instead of a bounded wildcard parameter (like ? super T)?

For instance, the signature of Functions#forPredicate is:

public static <T> Function<T, Boolean> forPredicate(Predicate<T> predicate)

Why not use:

public static <T> Function<T, Boolean> forPredicate(Predicate<? super T> predicate)

Which would make something like the following possible?

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>

Is it because consumers of Function and Predicate are expected to have the necessary bounded wildcard parameters to make this unnecessary? For example, the generic bounds on Iterables#find would allow a Predicate<Number> to be used on a Iterable<Integer>:

public static <T> T find(Iterable<T> iterable,
                         Predicate<? super T> predicate)

Are there other reasons?

like image 994
matts Avatar asked Jan 31 '13 17:01

matts


1 Answers

Yes, it's absolutely accurate that we expect the consumers to have the right bounded wildcard parameters, but a couple additional reasons spring to mind:

  • In general, we don't widen the types of generic methods until we have a specific reason to. This policy has paid off several times.
  • Java's type inference isn't always up to figuring out more advanced generics automatically, so keeping the narrower generics reduces the number of users who need to explicitly specify T.
like image 74
Louis Wasserman Avatar answered Oct 16 '22 09:10

Louis Wasserman