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

Sea*_*lly 5 java constructor variadic-functions

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

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

public Foo(int id, Bar bar, String... values){
}
Run Code Online (Sandbox Code Playgroud)

是什么赋予了?

rge*_*man 7

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

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!");
   }
}
Run Code Online (Sandbox Code Playgroud)

打印出:

name and description!
values!
values!
values!
Run Code Online (Sandbox Code Playgroud)

...表明如果可以,Java将选择固定的arity方法.