首页 > 解决方案 > 具有可变参数参数的多个构造函数

问题描述

给定这两个构造函数:

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

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

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

SomeClass foo = new SomeClass();

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

我做了一些基本的测试,发现如果定义了一个没有参数的构造函数,那么它将被调用。否则,似乎调用了一个模棱两可的。

标签: javaclassconstructorvariable-length-array

解决方案


根据下面“Java 中方法重载中的可变参数”问题中的这个非常好的答案,Java 编译器用于选择要调用的方法签名的规则。它们基于JLS 5.3。方法调用转换文档。

  1. 原始扩展使用可能的最小方法参数
  2. Wrapper 类型不能扩展到另一个 Wrapper 类型
  3. 您可以从 int Box 到 Integer 并扩大到Object但不扩大到Long
  4. 扩大击败拳击,拳击击败 Var-args。
  5. 你可以 Box 然后加宽(一个int可以成为Objectvia 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中解释了规则 1 中使用的基元类型之间的精确子类型关系。原始类型之间的子类型化

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

  • 双 > 1浮点数

  • 浮动 > 1

  • 长 > 1 个整数

  • 整数 > 1 个字符

  • int > 1

  • 短 > 1字节


推荐阅读