变量参数构造函数_may_ conflict,但编译

我有两个编译器编译得很好,但我希望Java抱怨模糊的可能性。

public Foo(int id, Bar bar, String name, String description){ } public Foo(int id, Bar bar, String... values){ } 

是什么赋予了?

Java允许这些方法存在,因为它具有关于如果两者都适用将被调用的规则。 具体来说,固定arity方法(没有... )将选择变量arity方法(带... )。

JLS,第15.12.2节 ,在确定选择哪种方法时说明如下:

第一阶段(§15.12.2.2)执行重载解析而不允许装箱或拆箱转换,或使用变量arity方法调用。 如果在此阶段没有找到适用的方法,则处理继续到第二阶段。

这保证了在Java SE 5.0之前在Java编程语言中有效的任何调用都不会因为引入变量arity方法,隐式装箱和/或取消装箱而被认为是不明确的。 但是,变量arity方法(第8.4.1节)的声明可以更改为给定方法方法调用表达式选择的方法,因为变量arity方法在第一阶段被视为固定arity方法。 例如,在已经声明m(Object)的类中声明m(Object …)会导致不再为某些调用表达式(例如m(null))选择m(Object),因为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方法。

我同意你的看法,下面的代码可以调用你定义的两个构造函数中的任何一个:

 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()); 

我希望这有助于澄清为什么你没有让编译器抱怨它(这只是他们认为应该工作的方式)。