I would know what is the use case of @NamedArg annotation in JavaFX 8
The javadoc does not give us more details, Javadoc : Annotation that provides information about argument's name.
And no more information, documentation, examples on the internet.
Maybe someone could help ?
Regards.
The
@NamedArg
annotation allows anFXMLLoader
to instantiate a class that does not have a zero-argument constructor.Technical Background:
The
FXMLLoader
creates objects using reflection. Typically, if you use a tag corresponding to a class with a constructor taking no arguments, an object is created from that class by callingClass.newInstance()
, which invokes the no-argument constructor.If a class is defined only with constructors that take parameters, then this is problematic. The main issue is that the Java Language Specification does not require the names of parameters (to methods or constructors) to be retained at runtime. This means there's no direct, guaranteed, way for the
FXMLLoader
to determine which parameter has a given name.To make this concrete, suppose we define a
Person
class as follows:In FXML we might try to create a
Person
as follows:This won't work, because the FXML loader has no guarantee that the runtime representation of the
Person
class retains the information as to which constructor parameter isfirstName
and which islastName
.Historical background
Java 2.2 defined "Builder" classes corresponding to each control. These builder classes follow the standard builder pattern. When the
FXMLLoader
encounters a tag referencing a class with no zero-argument constructor, it would use the corresponding builder to create the instance.Unfortunately, the implementation of the builder classes was flawed, and they were deprecated in JavaFX 8, and will be removed in a later version (probably JavaFX 9). This left a problem for the
FXMLLoader
, which would no longer have builder classes to rely on for instantiating classes with no zero-argument constructor. A real example is theColor
class, which has no zero-argument constructor and will have its builder class removed.@NamedArgs
The fix for this was to introduce an annotation that is used to retain a name of a method (or constructor) argument at runtime. By reflection, we can query the parameter list of a constructor/method, and get the type (but not the name) of each parameter. It is also possible to query each parameter for any annotations, and get the value of those annotations. So the
@NamedArg
annotation was introduced specifically for the purpose of retaining a name of a parameter at runtime.Example
For an example, use the
Person
class we introduced above:If you try to load this using FXML:
Person.fxml:
Main.java:
then you see an error at runtime:
indicating the
FXMLLoader
is looking for a constructor taking no arguments (Person.<init>()
).In JavaFX 8, you can fix the problem by specifying the name of the parameters with the
@NamedArg
annotation:This will allow the
FXMLLoader
to load the class as required.Note that you can also fix the issue by defining a builder class, and that this also works in JavaFX 2.0 and later. The JavaFX team decided (probably correctly) that using this approach in a way that didn't suffer from the bugs that existed in the initial implementation of the builders would add too much bloat to the codebase of the framework.
Clearly if you are using JavaFX 8, the constructor annotation approach is much less work.
References:
@NamedArg
)