336 Part I: The Java Language
Now, notice howisIn( )is called withinmain( )by use of the normal call syntax, without
the need to specify type arguments. This is because the types of the arguments are automatically
discerned, and the types ofTandVare adjusted accordingly. For example, in the first call:
if(isIn(2, nums))
the type of the first argument isInteger(due to autoboxing), which causesIntegerto be
substituted forT. The base type of the second argument is alsoInteger, which makesInteger
a substitute forV, too.
In the second call,Stringtypes are used, and the types ofTandVare replaced byString.
Now, notice the commented-out code, shown here:
// if(isIn("two", nums))
// System.out.println("two is in strs");
If you remove the comments and then try to compile the program, you will receive an error. The
reason is that the type parameterVis bounded byTin theextendsclause inV’s declaration.
This means thatVmust be either typeT, or a subclass ofT. In this case, the first argument is of
typeString, makingTintoString, but the second argument is of typeInteger, which is not a
subclass ofString. This causes a compile-time type-mismatch error. This ability to enforce type
safety is one of the most important advantages of generic methods.
The syntax used to createisIn( )can be generalized. Here is the syntax for a generic method:
<type-param-list>ret-type meth-name(param-list) { // ...
In all cases,type-param-listis a comma-separated list of type parameters. Notice that for
a generic method, the type parameter list precedes the return type.
Generic Constructors
It is also possible for constructors to be generic, even if their class is not. For example, consider
the following short program:
// Use a generic constructor.
class GenCons {
private double val;
<T extends Number> GenCons(T arg) {
val = arg.doubleValue();
}
void showval() {
System.out.println("val: " + val);
}
}
class GenConsDemo {
public static void main(String args[]) {
GenCons test = new GenCons(100);
GenCons test2 = new GenCons(123.5F);