Java:编译时解析和“最具体的方法”,因为它适用于变量arity
作者:互联网
有人能帮我理解section 15.12.2.5 of the JLS re: most specific method吗?
(随后是来自JLS的大胆剪切和粘贴)
In addition, one variable arity member method named m is more specific than another variable arity member method of the same name if either:
- One member method has n parameters and the other has k parameters, where n >= k. 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 p1, be its formal type parameters, let Bl be the declared bound of Rl, 1lp, let A1 … Ap be the actual type arguments inferred (§15.12.2.7) for this invocation under the initial constraints Ti << Ui,1ik-1, Ti << Uk, kin and let Si = Ui[R1 = A1, …, Rp = Ap] 1ik; otherwise let Si = Ui, 1ik. Then:
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], 1lp.- One member method has k parameters and the other has n parameters, where n >= k. The types of the parameters of the first method are U1, . . . , Uk-1, Uk[], the types of the parameters of the other method are T1, . . ., Tn-1, Tn[]. If the second method is generic then let R1 … Rp p1, be its formal type parameters, let Bl be the declared bound of Rl, 1lp, let A1 … Ap be the actual type arguments inferred (§15.12.2.7) for this invocation under the initial constraints Ui << Ti, 1ik-1, Uk << Ti, kin and let Si = Ti[R1 = A1, …, Rp = Ap] 1in; otherwise let Si = Ti, 1in. Then:
for all j from 1 to k-1 , Uj <: Sj, and,
for all j from k to n , Uk <: Sj, and,
If the second method is a generic method as described above then Al <: Bl[R1 = A1, …, Rp = Ap], 1lp.
忽略问题泛型,这是否意味着varargs比子类型更重要,或者在确定一种方法是否比另一种更具体时,子类型比varargs更重要?我无法弄清楚.
具体示例:根据JLS,以下哪个compute()方法“更具体”?
package com.example.test.reflect;
class JLS15Test
{
int compute(Object o1, Object o2, Object... others) { return 1; }
int compute(String 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));
}
}
我无法弄清楚哪个是“更具体”;输出打印
1
2
我很困惑如何解释结果.当第一个参数是String时,编译器选择具有更具体子类型的方法.当第一个参数是Object时,编译器选择具有较少可选varargs的方法.
注意:如果您没有阅读JLS的这一部分,并且您给出的答案取决于参数的类型,那么您并没有帮助我.如果你仔细阅读JLS,除了与泛型相关的部分,“更具体”的定义取决于声明的参数,而不是实际的参数 – 这在JLS的其他部分发挥作用(找不到)它此刻).
例如对于固定的arity方法,compute(String s)将比compute(Object o)更具体.但我试图理解JLS的相关部分:变量arity方法.
解决方法:
> int compute(String s1,Object … others)在调用compute(“hi”,y,y)时更具体,因为String是Object的子类.
> int compute(Object o1,Object o2,Object … others)是compute(y,y,y)的唯一匹配,因为第二个方法接收String作为第一个参数,而JLS15Test不是String的子类
编辑
我的答案取决于具体方法的基础知识,但您的代码只能编译,因为编译器能够以上述方式区分方法.
以下示例甚至不会编译,因为它的含糊不清:
情况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));
}
案例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"));
}
更多编辑
前两次我没有得到你的问题(我希望我这次做:)).
您正在谈论的实际案例将如下所示:
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; }
}
在这种情况下,compute(Object s1,Object others)确实比compute(String s,Object … others)更具体(参数更少),因此输出确实是2.
标签:java,variadic-functions,jls 来源: https://codeday.me/bug/20190531/1187409.html