有人可以帮我理解JLS re: most specific method 的第 15.12.2.5 节吗?
(来自 JLS 的大棒剪切和粘贴如下)
此外,一个名为 m 的变量 arity 成员方法比另一个同名的变量 arity 成员方法更具体,如果:
- 一个成员方法有 n 个参数,另一个有 k 个参数,其中 n >= k。第一个成员方法的参数类型为 T1, 。. . , Tn-1 , Tn[], 其他方法的参数类型为 U1, . . . , Uk-1, Uk[]。如果第二种方法是泛型的,则令 R1 ... Rp p1 为其形式类型参数,令 Bl 为 Rl、1lp 的声明边界,令 A1 ... Ap 为推断的实际类型参数(第 15.12.2.7 节)对于初始约束下的此调用 Ti << Ui,1ik-1, Ti << Uk, kin 并让 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。
忽略泛型问题,这是否意味着在决定一种方法是否比另一种方法更具体时,可变参数比子类型更重要,或者子类型比可变参数更重要?我想不通。
具体示例: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));
}
}
我不知道哪个“更具体”;输出打印
1
2
我很困惑如何解释结果。当第一个参数是字符串时,编译器会选择具有更具体子类型的方法。当第一个参数是一个对象时,编译器选择具有较少数量的可选可变参数的方法。
注意:如果您没有阅读 JLS 的这一部分,并且您给出的答案取决于参数的类型,那么您就没有帮助我。如果您仔细阅读 JLS,除了与泛型相关的部分之外,“更具体”的定义取决于声明的参数,而不是实际的参数——这在 JLS 的其他部分(找不到此刻)。
例如,对于固定数量的方法,compute(String s)
将比compute(Object o)
. 但我试图了解 JLS re: variable arity methods 的相关部分。