Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Varargs overloading ambiguity?

Tags:

java

The outputs to all the no_min_arg() invocations make sense to me but I'm unable to justify why the 2 invocations to one_min_arg() result in an error and how is it different from the type casting that occurs while invoking no_min_args().

void no_min_args(float... args)
{
    System.out.println("no_min_args 1st function");
}
void no_min_args(double... args)
{
    System.out.println("no_min_args 2nd function");
}

void one_min_arg(float f, double... args)
{
    System.out.println("one_min_arg 1st function");
}

void one_min_arg(double d, float... args)
{
    System.out.println("one_min_arg 2nd function");
}

void driver_func()
{
    no_min_args(1);     //Output: no_min_args 1st function
    no_min_args(1.5f);  //Output: no_min_args 1st function
    no_min_args(1.5);   //Output: no_min_args 2nd function
    one_min_arg(1);    //Output: Error: reference to one_min_arg is ambiguous
    one_min_arg(1.5f); //Output: Error: reference to one_min_arg is ambiguous
    one_min_arg(1.5);  //Output: one_min_arg 2nd function

}
like image 481
Anoushka Avatar asked Sep 02 '25 15:09

Anoushka


1 Answers

For one_min_arg(1.5), only the (double, float...) overload is applicable. 1.5 is a double and so is not compatible with the float parameter of the other overload. So there is no ambiguity.

In other two cases, both overloads are applicable. 1 is an int and so is compatible with either double or float parameter. 1.5f is a float, and is also compatible with either a double or float parameter.

So now Java needs to choose the most specific overload out of the two. The situation is similar to no_min_args(1) and no_min_args(1.5f). In those cases, Java chooses the (float...) overload as the most specific, because float is more specific than double (float is a subtype of double as per JLS §4.10).

In the cases of one_min_arg however, neither overload is more specific than the other. This is because Java considers the types of both of the parameters of each overload, even if you do not pass any arguments corresponding to the variable arity parameter.

The relevant quote from the language specification is:

One applicable method m1 is more specific than another applicable method m2, for an invocation with argument expressions e1, ..., ek, if any of the following are true:

  • [...]
  • [...]
  • m2 is not generic, and m1 and m2 are applicable by variable arity invocation, and where the first k variable arity parameter types of m1 are S1, ..., Sk and the first k variable arity parameter types of m2 are T1, ..., Tk, the type Si is more specific than Ti for argument ei for all i (1 ≤ i ≤ k). Additionally, if m2 has k+1 parameters, then the k+1'th variable arity parameter type of m1 is a subtype of the k+1'th variable arity parameter type of m2.

Although the first parameter type of the first overload (float) is more specific than the first parameter type of the second overload (double), the part after "Additionally" does not hold. In this case, k is 1, and the two overloads both have 2 (k + 1) parameters. The variable arity parameter type of the first overload (double) is not a subtype of the variable arity parameter type of the second overload (float). Therefore, the first overload is not more specific than the second overload.

The second overload is also not more specific than the first overload, because of the types of their first parameters (double is not more specific than float).

So neither overload is more specific than the other, so there is no most specific overload.

like image 95
Sweeper Avatar answered Sep 06 '25 14:09

Sweeper