具有可变参数参数的多个构造函数

时间:2019-01-09 19:58:35

标签: java class constructor variable-length-array

给出以下两个构造函数:

SomeClass(int... params)
{
   // Do things
}

SomeClass(long... otherParams)
{
   // Do other things
}

实例化对象foo会发生什么?

SomeClass foo = new SomeClass();

未定义的默认构造函数是否以某种方式被调用?还是那些名为空数组的构造函数之一?如果是这样,先例是什么?

我进行了一些基本测试,发现如果定义了不带参数的构造函数,则会调用该构造函数。否则,会出现一个模棱两可的东西。

2 个答案:

答案 0 :(得分:2)

根据下面的this very good answer in "Varargs in method overloading in Java" question,是Java编译器用于选择要调用的方法签名的规则。它们基于JLS 5.3. Method Invocation Conversion文档。

  1. 原始加宽使用可能的最小方法参数
  2. 包装器类型不能扩展为其他包装器类型
  3. 您可以将Box从int到Integer并加宽到Object,而不能扩到Long
  4. 狂野搏击拳击,搏击击败Var-args。
  5. 您可以装箱然后加宽(int可以通过Object变成Integer
  6. 您不能先加宽然后装箱(int不能成为Long
  7. 您不能将var-args与加宽或装箱结合使用

由于两个构造函数都是var-args(规则7),因此编译器将退回到其他规则,并选择使用最小类型的方法(规则1)。

您可以使用以下代码确认此行为:

static class SomeClass {
  SomeClass(long... value) { System.out.println("Long"); }
  SomeClass(int... value) { System.out.println("Int"); }
  SomeClass(byte... value) { System.out.println("Byte"); }
}

public static void main(String[] args) throws Exception {
  SomeClass o = new SomeClass(); // Byte
}

JLS 4.10.1. Subtyping among Primitive Types中说明了规则1中使用的基本类型之间的精确子类型关系。

  

以下规则定义了原始类型之间的直接超类型关系:

     
      
  • double> 1 浮动

  •   
  • 浮动> 1

  •   
  • long> 1 int

  •   
  • int> 1 字符

  •   
  • int> 1

  •   
  • short> 1 字节

  •   

答案 1 :(得分:0)

只有完全没有任何显式构造函数的类都将获得默认构造函数。对于确实具有一个或多个明确定义的构造函数的类,其Arity(无论变量与否)都不起作用。因此,一个类没有null构造函数是很常见的,实际上就是您的类。

从多个可用的构造函数中进行选择与在重载方法中进行选择的方式相同。首先,确定可用构造函数。然后,确定那些适用于给定参数的参数。最后,在适用的构造函数中选择最具体的。详细信息在JLS10的15.12节中指定。如果该过程没有导致确切地标识一个构造函数,则将导致编译时错误。

在您的示例中,两个可用的构造函数都适用于空参数列表,因此归结为选择最具体的问题。 JLS提供了一个非正式的描述:

  

如果任何方法由处理,则一个方法比另一个方法更具体   第一种方法可以传递给另一个方法而无需   编译时错误。

形式规则围绕形式参数的类型展开,并说明原始类型之间的形式类型/子类型关系,最终结果是,SomeClass(int...)SomeClass(long...)更适用。那么,前者就是您的示例中选择的那个。