From Introduction to FXML:
@FXML
Note that, in the previous examples, the controller member fields and event handler methods were declared as public so they can be set or invoked by the loader. In practice, this is not often an issue, since a controller is generally only visible to the FXML loader that creates it. However, for developers who prefer more restricted visibility for controller fields or handler methods, the javafx.fxml.FXML
annotation can be used. This annotation marks a protected or private class member as accessible to FXML. If the class being annotated is in a named module, the module containing that class must open
the containing package to at least the javafx.fxml
module.
In other words, the @FXML
annotation is only required if the field or method is non-public (i.e. is protected, package-private, or private) yet needs to be accessible to FXML. Within the context of FXML, there is no difference between a public field/method with no (or even with an) @FXML
annotation and a non-public field/method with said annotation. The only difference in general is the visibility of the field/method to other code.
That said, it's typically considered good practice to only make something as visible as it needs to be. An FXML-injected field normally has no reason to be public. Neither do event-handler methods nor does the initialize method1. They're all implementation details.
Note the @FXML
annotation doesn't do anything special on a language level. The presence of the annotation simply tells the FXMLLoader
it's okay to try and reflectively access the field or method even though it's not public. It's also a good hint to the developer that the field or method is handled by FXML (for instance, FXML-injected fields should virtually never be manually initialized or reassigned).
1. The no-argument initialize()
method. Not the one you have to override when implementing Initializable
, which of course must be public. Note it's recommended to use the no-argument method instead of implementing that interface, injecting the location and resource bundle the same as other FXML-injected fields if needed. Why the interface hasn't been deprecated yet, I don't know.