Quote from JLS:
The process of determining applicability begins by determining the
potentially applicable methods (§15.12.2.1).
The remainder of the process is split into three phases, to ensure
compatibility with versions of the Java programming language prior to
Java SE 5.0. The phases are:
- The first phase (§15.12.2.2) performs overload resolution without
permitting boxing or unboxing conversion, or the use of variable arity
method invocation. If no applicable method is found during this phase
then processing continues to the second phase.
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. However, the declaration of a variable arity method (§8.4.1)
can change the method chosen for a given method method invocation
expression, because a variable arity method is treated as a fixed
arity method in the first phase. For example, declaring m(Object...)
in a class which already declares m(Object) causes m(Object) to no
longer be chosen for some invocation expressions (such as m(null)), as
m(Object[]) is more specific.
- The second phase (§15.12.2.3) performs overload resolution while
allowing boxing and unboxing, but still precludes the use of variable
arity method invocation. If no applicable method is found during this
phase then processing continues to the third phase.
...
Edit: about choosing float instead of double:
If more than one member method is both accessible and applicable to a
method invocation, it is necessary to choose one to provide the
descriptor for the run-time method dispatch. The Java programming
language uses the rule that the most specific method is chosen.
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.
The first phase of overload resolution will choose two of these four methods
private static void foo(double aDouble)
private static void foo(float aFloat)
because first phase doesn't permit boxing/unboxing (Long
) and you cannot pass long
to method with int
parameter without explicit casting. Than the most specific method will be choosen. In this situation float
method would be interpreted as most specific than double
.