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

时间:2013-10-14 18:04:33

标签: java constructor variadic-functions

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

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

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

是什么给出了?

2 个答案:

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

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