In §15.12.2.5 of the Java Language Specification they describe how Java chooses the most specific method to call from a list of both accessible and applicable methods.
There is one specific remark that I don't understand, namely:
(1) A type S is more specific than a type T for any expression if S <: T
The part that really bothers me is "any expression".
To give an example why, I'll be quoting the previous paragraph that says when given two methods m1 and m2 we can say m1 is more specific than m2 for an invocation with argument expressions e1, ..., ek if:
m2 is not generic, and m1 and m2 are applicable by strict or loose invocation, and where m1 has formal parameter types S1, ..., Sn and m2 has formal parameter types T1, ..., Tn, the type Si is more specific than Ti for argument ei for all i (1 ≤ i ≤ n, n = k).
So if the type Si (m1) is more specific than Ti (m2) with argument expression ei for all i, then m1 is more specific than m2
Now consider this:
int a(Number a) { return 1; } // m1
int a(Double a) { return 2; } // m2
Since Double <: Number
it follows that for any expression Double
is more specific than Number
(from quote 1).
We have:
m1 : S1 => Number
m2 : T1 => Double
But then if our argument argument expression e1 is of type Number
m2 is the most specific method since Double
is most specific for any expression (quote 1).
However, if we pass in a Number
to a()
the result is 1
ie. the method taking a Double
is not chosen. But quote 1 says that if Double
is a subtype of Number
for any expression Double
will be more specific, so how come it chooses a(Number)
?
What am I missing here?
Note:
I know Number
is not assignable to Double
and it wouldn't make sense for the compiler to choose the other one, I'm just trying to see what I'm mis-interpreting from the first quote.
It turns out my misunderstanding was not as part of the quote but as to what an applicable function would be under loose or strict invocation.
More specifically strict/loose invocation contexts allow a set of conversions
Number
toNumber
byte to short,int,long,float or double
Double
toNumber
int to Integer
optionally followed by a widening reference conversionInteger to int
optionally followed by a widening primitive conversionIn my example, I overlooked the fact that a widening reference conversion cannot be applied to
Number
becauseNumber
is not a subtype ofDouble
henceint a(Double a)
is not considered an applicable method.