1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
|
A method's type parameters should always be referenced in the declaration of one
or more formal parameters. Type parameters that are only used in the return type
are a source of type-unsafety. First, operations on the type will be unchecked
after the type parameter is erased. For example:
static <T> T doCast(Object o) {
return (T) o; // this will always succeed, since T is erased
}
The 'doCast' method would be better implemented as:
static <T> T doCast(Class<T> clazz, Object o) {
return clazz.cast(o); // has the expected behaviour
}
Second, this pattern causes unsafe casts to occur at invocations of the method.
Consider the following snippet, which uses the first (incorrect) implementation
of 'doCast':
this.<String>doCast(42); // succeeds
String s = doCast(42); // fails at runtime
Finally, relying on the type parameter to be inferred can have surprising
results, and interacts badly with overloaded methods. Consider:
<T> T getThing()
void assertThat(int a, int b)
void assertThat(Object a, Object b)
This invocation will be ambiguous:
// both method assertThat(int,int) and method assertThat(Object,Object) match
assertThat(42, getThing());
|