Overloading function using varargs

前端 未结 3 603
伪装坚强ぢ
伪装坚强ぢ 2021-01-19 01:20

This will not compile:

public class Methods
{

    public static void method(Integer... i)
    {
        System.out.print(\"A\");
    }

    public static vo         


        
相关标签:
3条回答
  • 2021-01-19 01:21

    The answer is rather difficult. But it is described in the JLS §15.12. Method Invocation Expressions. In these specifications, "variable arity" methods are methods with variable number of arguments, so varargs.

    §15.12.2.4. Phase 3: Identify Applicable Variable Arity Methods

    The method m is an applicable variable-arity method if and only if all of the following conditions hold:

    • For 1 ≤ i < n, the type of ei, Ai, can be converted by method invocation conversion to Si.

    • If k ≥ n, then for n ≤ i ≤ k, the type of ei, Ai, can be converted by method invocation conversion to the component type of Sn.

    • If k != n, or if k = n and An cannot be converted by method invocation conversion to Sn[], then the type which is the erasure (§4.6) of Sn is accessible at the point of invocation.

    • If m is a generic method as described above, then Ul <: Bl[R1=U1...,Rp=Up] (1 ≤ l ≤ p).

    If no applicable variable arity method is found, a compile-time error occurs.

    Otherwise, the most specific method (§15.12.2.5) is chosen among the applicable variable-arity methods.

    So, we should look further to §15.12.2.5.

    §15.12.2.5. Choosing the Most Specific Method

    One variable arity member method named m is more specific than another variable arity member method of the same name if either:

    1. One member method has n parameters and the other has k parameters, where n ≥ k, and:

      • The types of the parameters of the first member method are T1, ..., Tn-1, Tn[].

      • The types of the parameters of the other method are U1, ..., Uk-1, Uk[].

      • If the second method is generic then let R1 ... Rp (p ≥ 1) be its type parameters, let Bl be the declared bound of Rl (1 ≤ l ≤ p), let A1 ... Ap be the type arguments inferred (§15.12.2.7) for this invocation under the initial constraints Ti << Ui (1 ≤ i ≤ k-1) and Ti << Uk (k ≤ i ≤ n), and let Si = Ui[R1=A1,...,Rp=Ap] (1 ≤ i ≤ k).

      • Otherwise, let Si = Ui (1 ≤ i ≤ k).

      • For all j from 1 to k-1, Tj <: Sj, and,

      • For all j from k to n, Tj <: Sk, and,

      • If the second method is a generic method as described above, then
        Al <: Bl[R1=A1,...,Rp=Ap] (1 ≤ l ≤ p).

    (T <: S means T is a subtype of S)

    Your methods do not match these conditions, so there is no "Most Specific" method. So, it says a little bit further:

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

    • If all the maximally specific methods have override-equivalent (§8.4.2) signatures, then:

      • If exactly one of the maximally specific methods is not declared abstract, it is the most specific method.

      • Otherwise, if all the maximally specific methods are declared abstract, and the signatures of all of the maximally specific methods have the same erasure (§4.6), then the most specific method is chosen arbitrarily among the subset of the maximally specific methods that have the most specific return type.

        However, the most specific method is considered to throw a checked exception if and only if that exception or its erasure 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.

    So, the conclusion: your methods are ambiguous following the JLS.

    0 讨论(0)
  • 2021-01-19 01:29

    This is a high-level informal summary of what is going on.

    Firstly varargs syntax is really just syntactic sugaring for passing an array. So method(7) is actually going to pass an array of ... something.

    But an array of what? There are two options here corresponding to the two overloads of the method; i.e an int[] or a Integer[].

    If there are two or more overloads that could work (i.e. right method names, right numbers of arguments, convertible values) then the resolution process will chose the overload that is an exact match over a match that requires conversions, and complain if the only candidates require conversions. (This is a drastic simplification of the rules ... see the JLS section 15.12 for the complete story ... and be prepared for a long / difficult read!)

    So what is happening in your first example is that it is trying to decide between two methods that both require conversions; i.e. int to int[] versus int to Integer[]. Basically it cannot decide which alternative to use. Hence a compilation error that says that the call is ambiguous.

    If you change the varargs call to a call passing an explicit Integer[] or int[], you now get an exact match to one of the two overloads ... and the rules above say that this is not ambiguous.


    I understand it as: 7 is primitive so it should be converted to array - int[].

    The problem is that 7 can also be converted to an Integer[] ... by auto-boxing the int first.

    0 讨论(0)
  • 2021-01-19 01:48

    Multiple arguments must be passed in an array, but the varargs hides the process. In the above varargs method, parameter acts as an int array with a reference name. So if you change it to:

        public static void main(String args[])
        {
            int[] s = {7};
            method(s);
        }
    

    first class will compile and work properly.

    0 讨论(0)
提交回复
热议问题