From Java Generics and Collections
,
List<Integer> ints = Lists.<Integer>toList(); // first example
List<Object> objs = Lists.<Object>toList(1, "two"); // second example
In the first example
, without the type parameter there is too little information for
the type inference algorithm used by Sun's compiler to infer the correct type. It infers
that the argument to toList is an empty array of an arbitrary generic type rather than
an empty array of integers, and this triggers the unchecked warning described earlier.
(The Eclipse compiler uses a different inference algorithm, and compiles the same line
correctly without the explicit parameter.)
In the second example
, without the type parameter there is too much
information for the type inference algorithm to infer the correct
type. You might think that Object is the only type that an integer
and a string have in common, but in fact they also both implement
the interfaces Serializable and Comparable. The type inference
algorithm cannot choose which of these three is the correct type.
In general, the following rule of thumb suffices:
In a call to a generic method, if there
are one or more arguments that correspond to a type parameter and they all have the
same type then the type parameter may be inferred; if there are no arguments that
correspond to the type parameter or the arguments belong to different subtypes of the
intended type then the type parameter must be given explicitly.
Some points for passing type parameter
When a type parameter is passed to a generic method invocation, it appears in angle
brackets to the left, just as in the method declaration.
The Java grammar requires that type parameters may appear only in method invocations that use a dotted form. Even
if the method toList is defined in the same class that invokes the code, we cannot
shorten it as follows:
List<Integer> ints = <Integer>toList(); // compile-time error
This is illegal because it will confuse the parser.