Java: compile-time resolution and “most specific method” as it applies to variable arity

旧街凉风 提交于 2019-12-01 08:22:40
  1. int compute(String s1, Object... others) is more specific when you call compute("hi",y,y), since String is a subclass of Object.

  2. int compute(Object o1, Object o2, Object... others) is the only match for compute(y,y,y) because the second method receives String as first param, and JLS15Test is not a subclass of String

EDIT

My answer resides on the basics of specific methods, but your code only compiles because of the ability of the compiler to distinguish between the methods in the way described above.

The following examples will not even compile because of its ambiguity:

case 1:

int compute(Object o1, Object o2, Object... others) { return 1; }
int compute(Object s1, Object... others)            { return 2; }

public static void main(String[] args) 
{
    JLS15Test y = new JLS15Test();
    System.out.println(y.compute(y,y,y));
    System.out.println(y.compute("hi",y,y));
}

case 2:

int compute(String o1, Object o2, Object... others) { return 1; }
int compute(Object s1, String... others)            { return 2; }

public static void main(String[] args) 
{
    JLS15Test y = new JLS15Test();
    System.out.println(y.compute("hi","hi","hi"));
}

More Edit

I didn't get your question well the first two times (and I hope I do this time :) ).

The actual case you are talking about will look like that:

public class Test {
    public static void main(String[] args)
    {
        Test t = new Test();
        int a = t.compute("t", new Test());
        System.out.println(a);
    }

    int compute(String s, Object... others) { return 1; }
    int compute(Object s1, Object others)   { return 2; }
}

In this case, compute(Object s1, Object others) is indeed more specific then compute(String s, Object... others) (has less parameters) so the output will be 2 indeed.

After reading the JLS multiple times, I finally think I understand this section.

What they are saying is that if there are two variable-arity methods, for the purposes of deciding which is "more specific", you can consider the one with the shorter argument list to be extended so that is of equal length to the longer one. e.g.

int compute(Object o1, Object o2, Object... others)
int compute(String s1, Object... others)

can be considered (only for the purposes of "more specific") to be equivalent to

int compute(Object o1, Object o2, Object... others)
int compute(String s1, Object,    Object... others)

and then the argument types are compared, one by one, with the latter method being more specific.

(more rigorously, the first one has n = 3, k = 2, n >= k, with String <: Object [String is a subtype of Object] and the JLS dictates comparing the types directly of each parameter for j between 1 and k-1 [one less than the shorter length], comparing the vararg type of the shorter method signature with the remaining parameters of the longer method.)

In the following case:

int compute(Object o1, Object o2, String... strings)
int compute(Object o1, String... strings)

these would be equivalent (only for the purposes of "more specific") to

int compute(Object o1, Object o2, String... strings)
int compute(Object o1, String,    String... strings)

and the latter more specific.

So variable-arity never trumps subtyping for the purposes of comparing "more specific" methods which are both of variable arity.

However, fixed-arity methods are always considered first (JLS 15.12.2.2 and 15.12.2.3) before variable-arity methods.

The second compute call prints 2 because the literal "hi" is known to be a String at compile time, so the compiler choses the second method signature because String is more specific than Object.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!