kun*_*ard 6 java overloading compiler-errors variadic-functions ambiguous
我试图理解方法重载,我有这些方法.
public void method(int a){
System.out.println("int a");
}
//implementing interface method
@Override
public void method() {
System.out.println("interface");
}
//varargs
public void method(int ... a){
System.out.println("int ... a");
}
Run Code Online (Sandbox Code Playgroud)
用这些参数调用它们之后,
int[] a = new int[5];
stack.method();
stack.method(1);
stack.method(5,6);
stack.method(null);
stack.method(a);
Run Code Online (Sandbox Code Playgroud)
我有这些结果:
interface
int a
int ... a
int ... a
int ... a
据我所知,该程序不应该编译,因为模糊不清,但无论如何它都可以.编译器不应该抛出错误吗?
null伊兰和芭丝谢芭已经说过为什么选择了各种不使用的。
剩下的问题是:为什么stack.method(null);还要编译?
答案是它与 varargs 签名匹配,因为method(int...)从编译器的角度来看,varargs 实际上与method(int[]). 由于数组是通过引用来引用的,因此可以在需要nullan 的地方使用。int[]
所以:
Run Code Online (Sandbox Code Playgroud)stack.method();
method()与界面中的签名完全匹配。没有歧义,method(int...)因为只有当其他参数不匹配时才会考虑可变参数。
Run Code Online (Sandbox Code Playgroud)stack.method(1);
火柴method(int)。出于与上述相同的原因,没有歧义。
Run Code Online (Sandbox Code Playgroud)stack.method(5,6);
匹配是method(int...)因为没有一个非可变参数匹配,但可变参数匹配。
Run Code Online (Sandbox Code Playgroud)stack.method(null);
参见前面的解释。
Run Code Online (Sandbox Code Playgroud)stack.method(a);
匹配match(int...)原因相同method(null0:因为对于编译器来说match(int...)实际上是相同的。match(int[])
方法重载解析分为三个阶段。第一和第二阶段不将带有可变参数的方法(也称为变量参数方法)视为候选方法,因此仅当找不到不带可变参数的匹配方法时,编译器才会将带有可变参数的方法视为候选方法。
\n\n因此,在第一个和第二个方法调用中,yourvoid method(int ... a)被忽略,并且不存在歧义。
\n \n\n\n第二步在上一步中确定的类型中搜索成员方法。此步骤使用方法名称和参数表达式来定位可访问且适用的方法,即可以在给定参数上正确调用的声明。
\n\n可能有不止一种这样的方法,在这种情况下,选择最具体的一种。最具体方法的描述符(签名加返回类型)是运行时用于执行方法分派的描述符。
\n\n如果方法适用于严格调用\n (\xc2\xa715.12.2.2)、松散调用 (\xc2\xa715.12.2.3) 或变量参数\n 调用 (\xc2\xa715) 之一,则该方法适用。 .12.2.4)。
\n\n适用性测试将忽略某些包含隐式类型 lambda\n 表达式 (\xc2\xa715.27.1) 或不精确方法引用 (\xc2\xa715.13.1) 的参数表达式,因为\n 无法确定它们的含义,直到选择目标类型。
\n\n尽管方法调用可能是多表达式,但只有其参数表达式(而不是调用的目标类型)影响适用方法的选择。
\n\n确定适用性的过程首先确定\n 可能适用的方法 (\xc2\xa715.12.2.1)。
\n\n该过程的其余部分分为三个阶段,以确保与 Java SE 5.0 之前的 Java 编程语言版本兼容。这些阶段是:
\n\n\n
\n- \n
第一阶段 (\xc2\xa715.12.2.2) 执行重载解析,不允许装箱或拆箱转换,或使用变量 arity\n 方法调用。如果在此阶段没有找到适用的方法\n,则处理将继续到第二阶段。\n 这保证了在 Java SE 5.0 之前的 Java 编程语言中有效的任何调用都不会被视为不明确\n,因为引入的结果变量数量方法、隐式装箱和/或拆箱。但是,变量 arity 方法 (\xc2\xa78.4.1) 的声明可以更改为给定方法调用表达式选择的方法,因为变量 arity 方法在第一阶段。例如,在已声明 m(Object) 的类中声明 nm(Object...) 会导致某些调用表达式(如 m(null))不再选择 nm(Object),如 m (Object[]) 更具体。
- \n
第二阶段 (\xc2\xa715.12.2.3) 执行重载解析,同时允许装箱和拆箱,但仍然阻止使用变量方法调用。如果在此阶段没有找到适用的方法,则处理将继续到第三阶段。这可确保如果某个方法可通过固定数量方法调用适用,则永远不会通过可变数量方法调用来选择该方法。
- \n
第三阶段(\xc2\xa715.12.2.4)允许重载与可变参数方法相结合允许重载与可变数量方法、装箱和拆箱