Both forms of m are potentially applicable because they have the right name and the right number of
parameters. Both arguments are reference types and neither method has a variable number of parameters, so
only phase 1 for finding the applicable methods will occur. First, the type arguments of the generic method
must be inferred. Attempting to do so, however, requires that String extend Number; it does not, so the
generic form is not applicable. The non-generic form is applicable because it matches in the first argument
type exactly, and in the second a String can be assigned to an Object. Since there is only one applicable
method, it is selected.
Now consider this invocation of m:
m(new Object(), 29);
Again both forms are potentially applicable. The type of the generic method is inferred to be
<Object,Integer> after applying boxing conversion to the argument 29. The non-generic form fails to
match in the first argument because an Object is not compatible with a String, so it is not applicable. The
generic method matches in the first argument exactly, and matches in the second argument after a boxing
conversion (phase 2). Consequently, the generic method is the only applicable method.
In contrast, this invocation of m is ambiguous:
m("hello", Integer.valueOf(29));
Both forms are potentially applicable, and again only phase 1 will come into play. The inferred type of the
generic method call is <String,Integer>. The non-generic form matches exactly in the first argument
type and matches in the second argument because an Integer is an Object. The generic form matches
exactly on both argument types. So there are two applicable methods. The next step is to determine which is
the most specific method. First, we see if the non-generic method is more specific than the generic method.
This is done as follows:
Since our second method is generic, type inference is performed, but this time with the initial
constraint that String is convertible to S and that Object is convertible to T. This infers the types
<String,Object> for the generic method. Note that the bound on T is not considered at this
point.
1.
A check is made to see if each parameter of the first method is a subtype of the (inferred) type of the
corresponding parameter in the second method. In this case the parameter types of the first method
and the inferred parameter types of the second method are the same, so the check passes.
2.
Since the second method is generic, a second check is then made to see if the types of the parameters
of the first method are subtypes of the bounds of the generic type parameters of the second method.
Considering the first parameter, the bound of S is Object and so we are testing whether String is
a subtype of Objectwhich it is. The bound of T, however, is Number and the test is if Object is a
subtype of Numberwhich it is not.
3.
Because the check has failed, the non-generic method is not more specific than the generic method. Now we
must see if the generic method is more specific than the non-generic one. This proceeds as follows:
- The second method is not generic this time, so no type inference occurs.
A check is made to see if each parameter of the first method is a subtype of the type of the
corresponding parameter in the second method. In this case the check is to see whether S is a subtype
of String and T is a subtype of Object. A type variable is a subtype only of its bounds (and their