给出以下两个构造函数:
SomeClass(int... params)
{
// Do things
}
SomeClass(long... otherParams)
{
// Do other things
}
实例化对象foo会发生什么?
SomeClass foo = new SomeClass();
未定义的默认构造函数是否以某种方式被调用?还是那些名为空数组的构造函数之一?如果是这样,先例是什么?
我进行了一些基本测试,发现如果定义了不带参数的构造函数,则会调用该构造函数。否则,会出现一个模棱两可的东西。
答案 0 :(得分:2)
根据下面的this very good answer in "Varargs in method overloading in Java" question,是Java编译器用于选择要调用的方法签名的规则。它们基于JLS 5.3. Method Invocation Conversion文档。
Object
,而不能扩到Long
int
可以通过Object
变成Integer
)int
不能成为Long
)由于两个构造函数都是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...)
更适用。那么,前者就是您的示例中选择的那个。