It’s not based on the number of types that are convertible to the parameter type – it’s whether any value that’s valid for one overload is valid for another, due to implicit conversions.
For example, there’s an implicit conversion from String
to Object
, but the reverse isn’t true, so String
is more specific than Object
.
Likewise there’s an implicit conversion from B
to A
, but the reverse isn’t true, so B
is more specific than A
.
With A
and E
however, neither is more specific than the other – there no conversion from A
to E
, and no conversion from E
to A
. That’s why overload resolution fails.
The relevant bit of the JLS is actually 15.12.2.5, which includes this that might make it easier for you to understand:
The informal intuition is that one method is more specific than another if any invocation handled by the first method could be passed on to the other one without a compile-time error.
So if you have:
void foo(String x)
void foo(Object x)
every invocation handled by foo(String)
could be handled by foo(Object)
, but the reverse is not the case. (For example, you could call foo(new Object())
and that couldn’t be handled by foo(String)
.)