Vargar's controversial methods

Here's some sample code that won't compile:

public class Test {
    public static void main(String[] args) {
        method(1);
    }

    public static void method(int... x) {
        System.out.println("varargs");
    }

    public static void method(Integer... x) {
        System.out.println("single");
    }
}

      

Can someone tell me why these methods are ambiguous? Thank you in advance.

+3


source to share


4 answers


Consider the method signatures

public static void foo(int a)

      

and

public static void foo(Integer a)

      



Before boxing and unboxing, the challenge foo(1)

would not be ambiguous. For backward compatibility with earlier Java versions, the call remains unambiguous. Therefore, the first phase of overload resolution does not allow boxing, unboxing, or the arity invocation variable that were entered at the same time. The arity variable call is when you call the varargs method, passing in a sequence of parameters for the last argument (not an array).

However, the resolution method(1)

for your method signatures allows boxing and unboxing, because both methods require a call to the arity variable. Since boxing is allowed, both signatures apply. Typically, when two overloads are applied, the most specific overload is selected. However, none of your signatures are more specific than the other (because neither int

is nor is Integer

it a subtype of the other). Therefore, the challenge is method(1)

ambiguous.

You can make this compiler by going new int[]{1}

.

+4


source


There are 3 phases used in congestion resolution ( JLS 15.2.2 ):

  • The first phase (ยง15.12.2.2) performs overload resolution without allowing boxing conversion or unboxing, or using a method call to the arity variable. If no applicable method is found at this stage, processing continues until the second phase.

  • The second phase (ยง15.12.2.3) performs overload resolution when boxing and unboxing is enabled, but still precludes the use of the arity variable method call. If no applicable method is found at this stage, processing continues until the third phase.

  • The third stage (ยง15.12.2.4) allows you to combine overloading with the arity variable methods, boxing and unboxing.

In your example, both methods are methods of the arity variable, so the third phase is applied.

Now, since we have two methods to choose from, we are looking for a more specific method.

JLS 15.12.2.5. Choosing the most specific method says:

If more than one member method is available and applicable to the method call, you must select it to provide a handle to dispatch at runtime. The Java programming language uses a rule in which the most specific method is chosen.

...

One applicable method m1 is more specific than another applicable method m2, to be called with argument expressions e1, ..., ek if one of the following is true:

...

m2 is not shared, m1 and m2 are applicable when calling the arity variable, and where the first k variable parameters of the arty parameters of m1 are S1, ..., Sk and the first k variable parameters of the arity m2 parameter are T1, ..., Tk, type Si is more specific than Ti for the argument ei for all i (1 โ‰ค i โ‰ค k). In addition, if m2 has k + 1 parameters, then the k + 1'th variable parameter of the arity parameter m1 is a subtype of the k + 1'th variable parameter of the arity parameter of the m2 parameter.



In your case, you have two non-generic methods that are applicable when the arity variable is called (i.e. both have varargs). For one of the methods to be selected when you call method(1)

, one of them must be more specific than the other. In your case, each method only has one parameter and for one of them is more specific than the other, the type of that one parameter must be a subtype of the other parameter of the method.

Since it is int

not a subtype Integer

and Integer

not a subtype int

, none of your methods are more specific than the other. Hence the error The method method(int[]) is ambiguous for the type Test

.

An example that will work:

public static void method(Object... x) {
    System.out.println("varargs");
}

public static void method(Integer... x) {
    System.out.println("single");
}

      

Since it Integer

is a subtype Object

, the second method is selected when called method(1)

.

+3


source


Because they are ambiguous. According to the JLS, you can either expand, box, or box and then expand. There are two methods in your example that could be boxed / unboxed with each other. At compile time although this is not visible due to the varargs which were always not entirely clear in java.

Even Sun advised developers not to overload varargs methods, there were compiler bugs related to it ( see here ).

0


source


The difference between int and Integer is that Integer is an object type. You can use in a situation like finding the maximum number of type int or comparing with integers

Integer object is already associated with methods like comparison method:

public static void method(int x, int y) {
    System.out.println(Integer.compare(x, y));
}

      

Find more at: http://docs.oracle.com/javase/7/docs/api/

-1


source







All Articles