我有两个编译器编译得很好,但我希望Java抱怨模糊的可能性。
public Foo(int id, Bar bar, String name, String description){
}
public Foo(int id, Bar bar, String... values){
}
是什么给出了?
答案 0 :(得分:7)
Java允许这些方法存在,因为它具有关于如果两者都适用将被调用的规则。具体来说,将使用变量arity方法(...
)选择固定arity方法(不...
)。
JLS, Section 15.12.2在确定选择哪种方法时说明如下:
第一阶段(§15.12.2.2)在没有的情况下执行重载决策 允许装箱或拆箱转换,或使用变量arity 方法调用。如果在此阶段没有找到适用的方法 然后处理继续到第二阶段。
这保证了在Java编程中有效的任何调用 Java SE 5.0之前的语言不会被视为不明确的结果 引入变量arity方法,隐式装箱和/或 拆箱。但是,变量arity方法的声明(§8.4.1) 可以更改为给定方法方法调用选择的方法 表达式,因为变量arity方法被视为固定的 第一阶段的arity方法。例如,声明m(对象...) 在已经声明m(Object)的类中导致m(Object)为no 为某些调用表达式(例如m(null))选择更长的时间,如 m(Object [])更具体。
第二阶段(§15.12.2.3)执行重载解析 允许装箱和拆箱,但仍然排除使用变量 arity方法调用。如果在此期间未找到适用的方法 阶段然后处理继续到第三阶段。
这可确保永远不会通过变量arity选择方法 方法调用,如果它适用于固定arity方法 调用强>
第三阶段(§15.12.2.4)允许重载与 变量arity方法,装箱和拆箱。
(强调我的)
示例代码:
class Bar{}
public class Foo{
public static void main (String [] args){
Foo main = new Foo(1, new Bar(), "name", "description");
Foo main2 = new Foo(2, new Bar(), "name");
Foo main3 = new Foo(3, new Bar(), "name", "description", "otherValues");
Foo main4 = new Foo(4, new Bar());
}
public Foo(int id, Bar bar, String name, String description) {
System.out.println("name and description!");
}
public Foo(int id, Bar bar, String... values) {
System.out.println("values!");
}
}
打印出来:
name and description!
values!
values!
values!
...表明如果可以,Java将选择固定的arity方法。
答案 1 :(得分:0)
我同意Sean,以下代码可以调用您定义的两个构造函数中的任何一个:
Foo foo = new Foo(3, new Bar(), "", "");
但是,当java人员引入“变量参数表示法”时,他们认为上面会定义“最特殊的构造函数”。在这种情况下,我有2个String参数,你的第一个构造函数需要2个String参数,因此它将被调用。
仅当存在多于或少于2个String参数时才会调用第二个构造函数,例如:
Foo foo = new Foo(3, new Bar(), "", "", "");
甚至:
Foo foo = new Foo(3, new Bar());
我希望这有助于澄清为什么你不让编译器抱怨它(这只是他们认为它应该工作的方式)。