Java Language Specification is pretty clear on that (emphasis mine):
15.12.2 Compile-Time Step 2: Determine Method Signature
[…]
The first phase (§15.12.2.2) performs overload resolution without permitting
boxing or unboxing conversion […] If no applicable method is found during this phase then processing continues
to the second phase. […]The second phase (§15.12.2.3) performs overload resolution while allowing
boxing and unboxing […]The third phase (§15.12.2.4) allows overloading to be combined with variable
arity methods, boxing, and unboxing.
That is, in the first step only print(int)
and print(float)
can be appropriate. The latter matches and no further investigation is made.
The reason for such rules is explained in JLS as well:
This guarantees that any calls that were valid in the Java programming language before Java SE 5.0 are not considered ambiguous as the result of the introduction of variable arity methods, implicit boxing and/or unboxing.
Imagine that your Test
class was compiled against Java 1.4 (before autoboxing). In that case it’s clear: print(float)
must be chosen (assuming we agree why long
to float
is considered safe and can be implicit…) as print(Long)
is completely incompatible with long
argument.
Later you compile the same code against Java 5+. The compiler can:
-
choose
print(Long)
as more “obvious” in this context. Thus after upgrading to Java 5 your program behaves differently… -
yield compilation error as the call is ambiguous. Thus, previously correct code is no longer compiling under Java 5 (which AFAIR is never the case)
-
…or preserve old semantics and call the same method as under Java 1.4
You should now understand why print(float)
is used – because it would have been chosen under Java 1.4. And Java has to be backward compatible.