Jas*_*n S 4 java variadic-functions jls
有人可以帮助我理解JLS的第15.12.2.5节:最具体的方法吗?
(来自JLS的强行剪切和粘贴如下)
另外,一个名为m的变量arity成员方法比另一个具有相同名称的变量arity成员方法更具体:
- 一个成员方法有n个参数,另一个成员方法有k个参数,其中n> = k.第一个成员方法的参数类型是T1 ,. ..,Tn-1,Tn [],其他方法的参数类型是U1 ,. ..,Uk-1,英国[].如果第二种方法是通用的,那么让R1 ... Rp p1成为它的形式类型参数,让Bl成为Rl的声明边界,1lp,让A1 ... Ap成为推断的实际类型参数(§15.12.2.7)对于这种在初始约束下的调用Ti << Ui,1ik-1,Ti << Uk,kin和let Si = Ui [R1 = A1,...,Rp = Ap] 1ik; 否则让Si = Ui,1ik.然后:对于从1到k-1的所有j,Tj <:Sj,并且对于从k到n的所有j,Tj <:Sk,并且,如果第二种方法是如上所述的通用方法,那么Al <:Bl [R1 = A1,...,Rp = Ap],1lp.
- 一个成员方法具有k个参数,另一个具有n个参数,其中n> = k.第一种方法的参数类型是U1 ,. ..,Uk-1,Uk [],其他方法的参数类型是T1 ,. ..,Tn-1,Tn [].如果第二种方法是通用的,那么让R1 ... Rp p1成为它的形式类型参数,让Bl成为Rl的声明边界,1lp,让A1 ... Ap成为推断的实际类型参数(§15.12.2.7)对于这种在初始约束条件下的调用,Ui << Ti,1ik-1,Uk << Ti,kin和令Si = Ti [R1 = A1,...,Rp = Ap] 1in; 否则让Si = Ti,1in.然后:对于从1到k-1的所有j,Uj <:Sj,并且对于从k到n的所有j,Uk <:Sj,并且,如果第二种方法是如上所述的通用方法,则Al <:Bl [R1 = A1,...,Rp = Ap],1lp.
忽略问题泛型,这是否意味着varargs比子类型更重要,或者在确定一种方法是否比另一种更具体时,子类型比varargs更重要?我无法弄清楚.
具体示例:compute()根据JLS ,以下哪种方法"更具体"?
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));
}
}
Run Code Online (Sandbox Code Playgroud)
我无法弄清楚哪个是"更具体"; 输出打印
1
2
Run Code Online (Sandbox Code Playgroud)
我很困惑如何解释结果.当第一个参数是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));
}
Run Code Online (Sandbox Code Playgroud)
案例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"));
}
Run Code Online (Sandbox Code Playgroud)
更多编辑
我前两次没有得到你的问题(我希望我这次做:)).
您正在谈论的实际案例将如下所示:
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; }
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,compute(Object s1, Object others)确实更具体compute(String s, Object... others)(参数较少),因此输出2确实如此.