In the find()
example, T
can always be inferred unambiguously.
In the forPredicate[1]()
example, T can also be inferred unambiguously.
In the forPredicate[2]()
example, there's uncertainty what T
should be. If the result of the method is assigned to a target type, T
can be determined from the target type. Otherwise it's a little head scratching:
forPredicate(isPositive).apply(42); // T is a subtype of Number, but which one?
In java5/6, it shouldn't compile. (well I tested it on java 6 and it does compile, but it's probably a bug, since java 6 also compiles forPredicate(p).apply("str")
)
Java 7 improved a little bit, and the new rule happens to dictate that T=Number
. It works, but it feels more like an arbitration for the sake of it.
Ideally, we shouldn't need to worry about wildcards. If I need a predicate for my integers, I should declare a Predicate<Integer>
parameter. The fact that a Predicate<Number>
argument would also be acceptable is another story. It should be the compiler's job to convert Predicate<Number>
to Predicate<Integer>
- we can do it without overhauling existing java generics type system, a new conversion rule is all that's needed. One can also provide a conversion library
Predicate<Number> pn = ...;
Predicate<Integer> pi = convert(pn);
Iterable<Integer> iter1 = ...;
Iterable<Number> iter2 = convert(iter1);
All convert()
methods can be generated mechanically.
Java 8 make things a little easier. We still cannot do
Predicate<Number> pn = n -> n.intValue()>0;
Predicate<Integer> pi = pn; // error!
but we can do
Predicate<Integer> pi = pn::test; // ok
// it means pi = (Integer i)->pn.test(i)
also
Function<Integer, Boolean> f = pn::test; // ok
which is equivalent to f = forPredicate[2](pn)
. In java 8 we'll rarely need forPredicate()
etc to convert between functional types.