Reputation: 120848
Suppose I want to have such a method:
private static <T> Collection<T> filter(Collection<T> initial, Predicate<T> predicate){
//....
}
This is trivial.
But, for some reason, I want to take as input not a simple Collection
, but one that implements RandomAccess
. So I change the definition to:
private static <T, M extends Collection<T> & RandomAccess> Collection<T> filter(M initial, Predicate<T> predicate){
return initial.stream()
.filter(predicate)
.collect(Collectors.toList());
}
this works on the declaration, but it would fail for callers. That is:
filter(List.of(1,2,3), x -> x > 1); // fails
What I find a bit awkward is that the compilation (and thus the resolution of T
) works if I remove the & RandomAccess
part:
private static <T, M extends Collection<T>> Collection<T> filter(M initial, Predicate<T> predicate){
....
}
I would understand if the failure would occur if RandomAccess
would take a type parameter. But it does not, so (at least in my understanding) it should not influence the resolution of T
.
Is there a way to have such a compile time constraint at all?
Upvotes: 1
Views: 43
Reputation: 45309
I would understand if the failure would occur if RandomAccess would take a type parameter. But it does not, so (at least in my understanding) it should not influence the resolution of T.
It does not. The problem with filter(List.of(1,2,3), x -> x > 1);
is that the static type of the expression List.of(1,2,3)
is not a subtype of RandomAccess
, and that's rejected because it does not meet the extends RandomAccess
constraint.
Both of the following compile with no problem, with the inference of T
remaining unaffected
filter(new ArrayList<>(List.of(1, 2, 3)), x -> x > 1);
filter(new ArrayList<>(List.of("a", "b", "c")), x -> x.length() > 1);
Simply because ArrayList
is both a Collection
and RandomAccess
subtype. I guess, however, that depending on your compiler implementation, you have one of many flavors of unhelpful error messages (like The method filter(M, Predicate<T>) in the type Main is not applicable for the arguments (List<Integer>)
on filter(...)
and Type mismatch: cannot convert from List<Integer> to M
on List.of(...)
in Eclipse)
Upvotes: 1