Varargs Java Ambiguous Call

By | August 12, 2019

Question

I’m a little confused about Java’s varargs methods:

public static int sum(int ...a) {
    return 0;
}

public static double sum(double ...a) {
    return 0.0;
}

When I tried to invoke sum() without passing any argument, then the int version of method was invoked. I don’t understand why; normally the compiler must raise an error.

By contrast, the following piece of code generates a compiler error when I try to invoke sum without any argument:

public static int sum(int ...a) {
    return 0;
}

public static boolean sum(boolean ...a) {
    return true;
}

Solution

The general rule that applies here is this: if one method signature is strictly more specific than the other, then Java chooses it without an error.

Intuituively, a method signature is more specific if you could delete it entirely and the other, less specific one would be applicable to each existing invocation.

When presented with a choice between the signatures sum(int... args) and sum(double... args), the signature sum(int... args) is more specific because any invocation of that method could also be passed on to sum(double... args) by applying a widening conversion. The same does not hold for a sum(boolean... args) method, which cannot be similarly converted.

Java Language Specification, SE 8 version:

15.12. Method Invocation Expressions

15.12.2.5. Choosing the Most Specific Method

The Java programming language uses the rule that the most specific method is chosen.

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 strict or loose invocation, and where m1 has formal parameter types S1, …, Sn and m2 has formal parameter types T1, …, Tn, the type Si is more specific than Ti for argument ei for all i (1 ≤ i ≤ n, n = k).

A type S is more specific than a type T for any expression if S <: T (§4.10).

4.10. Subtyping

4.10.1. Subtyping among Primitive Types

double >1 float

float >1 long

long >1 int

Rate this post

Leave a Reply

Your email address will not be published. Required fields are marked *