The answers above pretty much address your question, but if you want a specific example of a case where Java's generic type inference fails and explicitly stating it in this way saves the day, consider the following class definitions:
public class A { }
public class B extends A { }
public class C extends A { }
Then the following code works just fine (i.e., Java's type inference succeeds):
List<Class<? extends A>> list = ImmutableList.of(B.class, C.class);
But for the following, it fails to compile:
List<Class<? extends A>> list = ImmutableList.of(B.class);
That's right; strangely enough, by removing a parameter, we confuse the type inference system, since the 'nearest common descendant' of B.class
and C.class
is A.class
, but for B.class
by itself, it's just B.class
, which (by lack of covariance in Java's generics) does not match List<Class<? extends A>>
. In this case, you have no choice but to use:
List<Class<? extends A>> list = ImmutableList.<Class<? extends A>>of(B.class);
Since B
does indeed extend A
, this compiles (and runs) just fine.
I hope this demonstration emphasizes the usefulness of the operator.