FXML - 视图:
....
<GridPane...>
<PersonController... />
</GridPane...>
....
Class PersonController:
public PersonController(Person... personsToExclude) {
FXMLLoader.load("PersonControllerView.fxml")
this.personsToExclude = personsToExclude;
}
此代码示例导致excpetion,因为如果没有默认构造函数(由FXMLLoader),则无法调用该类。现在我的问题:您可以使用此构造函数作为默认构造函数。您可以创建这样的对象:
PersonConstructor pc = new PersonConstructor(); // This calls the upper constructor
为什么反射也不能使用这个构造函数呢? Varargs似乎是内部的数组,如果没有参数被移交,默认情况下它将为null。
这个设计决策是否仅仅是为了降低复杂性(实际上它确实为读者减少了一点),还是有其他原因使得仍然拥有“真正的”默认构造函数很重要?
答案 0 :(得分:2)
如果奥利弗查尔斯沃思是正确的,你的问题确实是:
当类没有零参数构造函数但是构造函数接受单个varargs参数时,为什么
Class#newInstance()
不起作用?
如果是这样,我认为我们不能正确回答它,除非在设计过程中引用了关于向Java添加varargs的内容。
我们可以推测。我的推测是: 简单
newInstance()
比varargs年龄大。在将varargs添加到语言之前,没有歧义:它只能调用nullary(零参数)构造函数。所以他们可能觉得扩展它以处理接受一个varargs参数的构造函数是该方法的代码膨胀和/或范围蠕变。毕竟,如果你真的想这样做,你可以查找相关的构造函数并调用它。
或者,他们可能觉得newInstance
的文档排除了调用这样的构造函数。我们来看看JavaDoc for newInstance()
:
创建此Class对象表示的类的新实例。该类实例化为具有空参数列表的新表达式。如果尚未初始化,则初始化该类。
请注意,此方法传播由Nullary构造函数抛出的任何异常,包括已检查的异常......
第一段支持这样的想法,它只能用一个varargs参数调用构造函数。但是,第二段特别提到了一个“无效”构造函数(虽然顺便说一下)。 “nullary”构造函数是一个零参数构造函数,具体而言,不仅仅是一个可以无需参数调用的构造函数。
这样做会使newInstance()
显着复杂化,因为它不仅仅是寻找不接受任何参数的构造函数,而是需要查看接受单个参数的所有构造函数,其中{{3是真的。
更改newInstance()
以执行您建议的操作会添加新的错误模式:您的PersonConstructor
类完全有可能拥有多个构造函数可以通过new PersonConstructor()
调用:
public class PersonConstructor
{
public PersonConstructor(String... args) {
}
public PersonConstructor(Person... args) {
}
}
那个人应该newInstance
打电话给谁?它无法决定,所以它必须抛出,抛出一个新的错误,它在向语言添加varargs之前没有抛出。
总而言之,如果我在团队中做出决定,我也会让newInstance()
只考虑真正的nullary构造函数而不是构造函数接受单个varargs参数。 (我也会更新JavaDoc来说明。:-))
答案 1 :(得分:1)
变量参数列表完全在编译器中实现。采用vararg数组的数组和方法的方法是相互兼容的 - 例如,你可以使用vararg签名
void foo(String... args)
覆盖非vararg签名
void foo(String[] args)
,反之亦然(demo)。
这个设计决定是否仅仅是为了降低复杂性?
很难猜出为什么做出这个特定的设计决定,但至少部分原因可归因于设计师不愿意对库和JVM进行更改。 Java 5更新(其中引入了变量参数功能)选择了字节码级别的完全向后兼容性,尽管它是一个非常大的更新,它引入了泛型。
如果您想要解决此限制,请实现一个无参数构造函数,该构造函数将调用带有数组的构造函数的路径:
public PersonController(Person... personsToExclude) {
}
public PersonController() {
this(new Person[0]);
}
答案 2 :(得分:0)
Varargs似乎是内部的数组,如果没有移交任何参数,默认为null。
事实并非如此。如果在没有任何参数的情况下调用vararg方法(或构造函数),则方法(或构造函数)仍然是具有一个数组参数的方法。并且不会传递null,而是一个空数组,正如Oliver已经指出的那样。
所以答案是:vararg构造函数肯定有一个参数,因此它不能是默认的构造函数。