简体   繁体   中英

Java most specific method subtyping rules

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 m 1 and m 2 we can say m 1 is more specific than m 2 for an invocation with argument expressions e 1 , ..., e k if:

m 2 is not generic, and m 1 and m 2 are applicable by strict or loose invocation, and where m 1 has formal parameter types S 1 , ..., S n and m 2 has formal parameter types T 1 , ..., T n , the type S i is more specific than T i for argument e i for all i (1 ≤ i ≤ n, n = k).

So if the type S i (m 1 ) is more specific than T i (m 2 ) with argument expression e i for all i, then m 1 is more specific than m 2

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:

m 1 : S 1 => Number

m 2 : T 1 => Double

But then if our argument argument expression e 1 is of type Number m 2 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

  • An identity conversion ie. Number to Number
  • A widening primitive conversion ie. byte to short,int,long,float or double
  • A widening reference conversion ie. Double to Number
  • A boxing conversion ie. int to Integer optionally followed by a widening reference conversion
  • An unboxing conversion ie. Integer to int optionally followed by a widening primitive conversion

In my example, I overlooked the fact that a widening reference conversion cannot be applied to Number because Number is not a subtype of Double hence int a(Double a) is not considered an applicable method.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM