Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

overloading with both widening and boxing

public void add(long... x){}
public void add(Integer... x){}

add(2);

this produces error...why overlaoding is not performed with both widening and boxing?

but overloading without vararg works fine

public void add(long x){}
    public void add(Integer x){}

    add(2);

here add(long x) will be executed that is widening beats boxing...why not same concept with var arguments

like image 435
saravanan Avatar asked Feb 07 '11 12:02

saravanan


2 Answers

Java compiler performs three attempts to choose an appropriate method overload (JLS §15.12.2.1):

  • Phase 1: Identify Matching Arity Methods Applicable by Subtyping
    (possible boxing conversions and methods with varargs are ignored)

  • Phase 2: Identify Matching Arity Methods Applicable by Method Invocation Conversion
    (takes boxing conversion in account, but ignores methods with varargs)

  • Phase 3: Identify Applicable Variable Arity Methods
    (examines all possibilities)

So, with your examples it works as follows:

  • Without varargs: add(long x) is identified as the only applicable method on the 1st phase (this method is applicable by subtyping since int is a subtype of long, §JLS 4.10.1), so that following phases are not executed.

  • With varargs: overload resoltion algorithm goes to phase 3, where both methods are identified as applicable, and compiler can't choose the most specific method of them (choosing the most specific method is yet another complex algorithm), therefore it reports ambiguity.

See also:

  • The Java Language Specification, Seventh Edition
like image 58
axtavt Avatar answered Sep 18 '22 01:09

axtavt


because it is ambiguous.

2 can be Integer as well as long and it can be resolve to both. you made compiler confused whom to invoke :)


5.12.2.2 Choose the Most Specific Method

If more than one method declaration 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 declaration 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 type error.

The precise definition is as follows. Let m be a name and suppose that there are two declarations of methods named m, each having n parameters. Suppose that one declaration appears within a class or interface T and that the types of the parameters are T1, . . . , Tn; suppose moreover that the other declaration appears within a class or interface U and that the types of the parameters are U1, . . . , Un. Then the method m declared in T is more specific than the method m declared in U if and only if both of the following are true:

T can be converted to U by method invocation conversion. Tj can be converted to Uj by method invocation conversion, for all j from 1 to n. A method is said to be maximally specific for a method invocation if it is applicable and accessible and there is no other applicable and accessible method that is more specific. If there is exactly one maximally specific method, then it is in fact the most specific method; it is necessarily more specific than any other method that is applicable and accessible. It is then subjected to some further compile-time checks as described in §15.12.3.

It is possible that no method is the most specific, because there are two or more maximally specific methods. In this case:

If all the maximally specific methods have the same signature, then: If one of the maximally specific methods is not declared abstract, it is the most specific method. Otherwise, all the maximally specific methods are necessarily declared abstract. The most specific method is chosen arbitrarily among the maximally specific methods. However, the most specific method is considered to throw a checked exception if and only if that exception is declared in the throws clauses of each of the maximally specific methods. Otherwise, we say that the method invocation is ambiguous, and a compile-time error occurs.

15.12.2.3 Example: Overloading Ambiguity

Consider the example:
class Point { int x, y; }
class ColoredPoint extends Point { int color; }

class Test {
    static void test(ColoredPoint p, Point q) {
        System.out.println("(ColoredPoint, Point)");
    }
    static void test(Point p, ColoredPoint q) {
        System.out.println("(Point, ColoredPoint)");
    }
    public static void main(String[] args) {
        ColoredPoint cp = new ColoredPoint();
        test(cp, cp);                                           // compile-time error
    }
}

This example produces an error at compile time. The problem is that there are two declarations of test that are applicable and accessible, and neither is more specific than the other. Therefore, the method invocation is ambiguous. If a third definition of test were added:

static void test(ColoredPoint p, ColoredPoint q) {
    System.out.println("(ColoredPoint, ColoredPoint)");
}

then it would be more specific than the other two, and the method invocation would no longer be ambiguous.

  • Read More
like image 33
jmj Avatar answered Sep 20 '22 01:09

jmj