Like generic classes, methods and constructors can also have type parameters. These parameters are declared prior to the return type of the method and can be used as return types, argument types, and in the throws clause. For example, see Listing 4.
Listing 4 Generic methodfinds max T
1 public <T extends Comparable> T max(T t1, T t2) { 2 if (t1.compareTo(t2) > 0) 3 return t1; 4 else return t2; 5 }
Here, the method "max(...)" has a single type parameter "T" declared as "<T extends Comparable>". As a result, this method requires two parameters that extend Comparable and returns a value whose type is the nearest shared ancestor type of the two parameters. Listing 5 demonstrates several invocations of this method.
Listing 5 Clients of generic max method
1 Integer iresult = max(new Integer(100), new Integer(200)); 2 String sresult = max("AA", "BB"); 3 Number nresult = max(new Integer(100), "AAA"); // does not compile
Line 1 of Listing 5 shows a typical invocation of our method. Both arguments are of type Integer, so the return type also becomes Integer. Note that the returned value can be assigned to iresult without a type cast.
Line 2 of Listing 5 demonstrates the same functionality, only this time using a different implementor of Comparable, String. Note that again a cast is not required, even if the exact same method is invoked.
Line 3 of Listing 5 generates the following compiler error:
Example.java:10: incompatible types found : java.lang.Object&java.io.Serializable&java.lang.Comparable<?> required: java.lang.Number Number nresult = max(new Integer(100), "AAA");
This error occurs because the effective return type of the method when invoked with a Number and a String would be their nearest common ancestor type: Object. Note that even if the assignment on Line 3 were corrected, our example method would fail at runtime because 'compareTo' generally requires an argument of the same type as the class on which it is invoked.