FXMLLoader如何加载FXML的控制器?

7

当我在JavaFX中调用FXMLLoader#load()时会发生什么?

假设FXML控制器扩展了一个具有构造函数的类。是否可以确保构造函数将被调用?如果不能,那么如何创建对象的新实例?例如,在下面的代码中,TextField()构造函数会被调用吗?

import java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.Initializable;
import javafx.scene.control.TextField;
public class FXMLController extends TextField implements Initializable {
    @Override
    public void initialize(URL url, ResourceBundle rb) {

    }    
}

我已经尝试搜索了这个问题,但似乎除了从http://docs.oracle.com/javafx/2/api/javafx/fxml/FXMLLoader.html中加载对象层次结构的文档外,没有其他文档。
非常感谢您的回答!
2个回答

15
回答你的问题"FXMLLoader在构建控制器时到底做什么?":
首先,它会尝试获取一个控制器实例:
- 如果FXMLLoader上已经有一个控制器实例设置,它将使用此实例。 - 如果FXMLLoader上没有设置控制器工厂,则使用反射调用类的无参构造函数。如果失败,抛出InstantiationException异常。 - 如果设置了控制器工厂,它将调用此工厂来创建一个新的控制器实例。
获取控制器实例后,它将对其执行以下操作:
- 如果该类实现了Initializable接口,则调用public void initialize(URL url, ResourceBundle resourceBundle)方法。如果没有,则查找是否有名为initialize的零参数方法,并通过反射调用它。如果没有,则不执行任何操作。

哇,谢谢您的及时回复。这个过程听起来很有趣。您能告诉我您的信息来源吗? - damat-perdigannat
您可以轻松测试此行为,并且还可以在openjdk提供的源代码中看到它。 - zhujik
谢谢。我可能会尝试使用OpenJDK。 - damat-perdigannat
你也可以显式地设置控制器(不仅仅是工厂)。 - Puce
谢谢Puce。那么当控制器已经设置好时,FXMLLoader会调用控制器的初始化方法,这样就没问题了吗? - damat-perdigannat

1
我不确定你想做什么,但通常控制器不应该扩展文本字段。
除此之外,这是基础的Java知识:TextField有一个空构造函数,您的控制器没有,因此Java将(默认情况下)调用TextField中可用的空构造函数。即使代码中没有,TextField构造函数也会默认调用它所扩展的类的构造函数,以此类推。在Java中,没有方法可以构建对象而不调用构造函数。

太好了,感谢您的迅速回复。我在思考是否可以有类似文本字段的东西来控制控件。 - damat-perdigannat

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接