什么是@NamedArg注解JavaFX中8的目的是什么? [英] What is the purpose of @NamedArg annotation in javaFX 8?

查看:1559
本文介绍了什么是@NamedArg注解JavaFX中8的目的是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我也知道什么是JavaFX中8

I would know what is the use case of @NamedArg annotation in JavaFX 8

该javadoc的不给我们更多的细节,
的Javadoc:注释提供了有关参数的名称信息

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.

也许有人可以帮助?

问候。

推荐答案

@NamedArg 注释允许一个 FXMLLoader 实例不具有一个零参数构造函数的类。

The @NamedArg annotation allows an FXMLLoader to instantiate a class that does not have a zero-argument constructor.

技术背景:

FXMLLoader 创建使用反射的对象。通常情况下,如果使用对应于类构造函数不带参数标签,对象是从类调用创建 Class.newInstance(),它调用无-argument构造。

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 calling Class.newInstance(), which invokes the no-argument constructor.

如果一个类只接受参数的构造函数的定义,那么这是有问题的。主要的问题是,Java语言规范并不要求参数名称(以方法或构造函数)在运行时被保留下来。这意味着对没有直接的,有保障,办法 FXMLLoader 来确定哪些参数有一个给定的名称。

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:

package application;

import javafx.beans.NamedArg;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;

public class Person {
    private final StringProperty firstName ;
    private final StringProperty lastName ;

    public Person(String firstName, String lastName) {
        this.firstName = new SimpleStringProperty(this, "firstName", firstName);
        this.lastName = new SimpleStringProperty(this, "lastName", lastName);
    }

    // methods....

}

在FXML我们可以尝试创建一个如下:

In FXML we might try to create a Person as follows:

<Person firstName="Jacob" lastName="Smith"/>

这是行不通的,因为FXML加载器有没有保证,类的运行时再presentation保留的信息,以构造函数参数是的firstName 和这是的lastName

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 is firstName and which is lastName.

历史背景

Java的2.2对应于每一个控制的定义,生成器类。这些制造商类遵循标准的生成器模式。当 FXMLLoader 遇到一个标签引用的类没有无参数的构造函数,它会使用相应的生成器来创建实例。

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.

不幸的是,制造商类的实现是有缺陷的,并他们被取消$ p $ JavaFX中8 pcated,并会在以后的版本(可能是JavaFX的9)被移除。这留下了一个问题,对 FXMLLoader ,这将不再具有助洗剂类依靠,没有无参数的构造函数实例化类。一个真正的例子是<一个href=\"https://docs.oracle.com/javase/8/javafx/api/javafx/scene/paint/Color.html\"><$c$c>Color类,它有没有零参数的构造函数,将有它的建造类中删除。

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 the Color class, which has no zero-argument constructor and will have its builder class removed.

@NamedArgs

对此问题进行修复是引入用于保留在运行时的方法(或构造函数)参数的名称注释。通过反射,我们可以查询一个构造/方法的参数列表,并获得每个参数的类型(但不是名称)。另外,也可以查询每个参数为任何注解,并获得这些标注的值。因此, @NamedArg 标注是专门介绍了在运行时保持一个参数的名称的目的。

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.

示例

举一个例子,我们使用上面介绍的类:

For an example, use the Person class we introduced above:

package application;

import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;

public class Person {
    private final StringProperty firstName ;
    private final StringProperty lastName ;

    public Person(String firstName, String lastName) {
        this.firstName = new SimpleStringProperty(this, "firstName", firstName);
        this.lastName = new SimpleStringProperty(this, "lastName", lastName);
    }

    public final StringProperty firstNameProperty() { return firstName; }
    public final String getFirstName() { return firstNameProperty().get(); }
    public final void setFirstName(final String firstName) { firstNameProperty().set(firstName); }
    public final StringProperty lastNameProperty() { return lastName; }
    public final String getLastName() { return lastNameProperty().get(); }
    public final void setLastName(final String lastName) { lastNameProperty().set(lastName); }
}

如果您尝试加载此使用FXML:

If you try to load this using FXML:

Person.fxml:

Person.fxml:

<?xml version="1.0" encoding="UTF-8"?>
<?import application.Person?>
<Person firstName="Jacob" lastName="Smith" xmlns:fx="http://javafx.com/fxml/1" />

Main.java

Main.java:

package application;

import java.io.IOException;
import javafx.fxml.FXMLLoader;

public class Main  {

    public static void main(String[] args) throws IOException {     
        Person person = FXMLLoader.load(Main.class.getResource("Person.fxml"));
        System.out.println(person.getFirstName()+" "+person.getLastName());
    }
}

然后就看到一个运行时错误:

then you see an error at runtime:

Caused by: java.lang.NoSuchMethodException: application.Person.<init>()

指示 FXMLLoader 正在寻找一个构造函数不带参数(人物&LT; INIT&GT;()

indicating the FXMLLoader is looking for a constructor taking no arguments (Person.<init>()).

在JavaFX的8,您可以通过指定的 @NamedArg 标注的参数名称解​​决该问题:

In JavaFX 8, you can fix the problem by specifying the name of the parameters with the @NamedArg annotation:

package application;

import javafx.beans.NamedArg;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;

public class Person {
    private final StringProperty firstName ;
    private final StringProperty lastName ;

    public Person(@NamedArg("firstName") String firstName, @NamedArg("lastName") String lastName) {
        this.firstName = new SimpleStringProperty(this, "firstName", firstName);
        this.lastName = new SimpleStringProperty(this, "lastName", lastName);
    }

    public final StringProperty firstNameProperty() { return firstName; }
    public final String getFirstName() { return firstNameProperty().get(); }
    public final void setFirstName(final String firstName) { firstNameProperty().set(firstName); }
    public final StringProperty lastNameProperty() { return lastName; }
    public final String getLastName() { return lastNameProperty().get(); }
    public final void setLastName(final String lastName) { lastNameProperty().set(lastName); }
}

这将允许根据需要 FXMLLoader 来加载类。

This will allow the FXMLLoader to load the class as required.

请注意,您也可以通过定义一个生成器类解决这个问题,并认为这也适用于JavaFX的2.0及更高版本。 JavaFX的团队决定(可能是正确的),使用中这并没有在最初实施的建设者会存在太多的膨胀添加到框架的codeBase的虫子遭受方法这个方法。

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.

package application;

public class PersonBuilder {

    private String firstName ;
    private String lastName ;

    private PersonBuilder() {   }

    public static PersonBuilder create() {
        return new PersonBuilder();
    }

    public PersonBuilder firstName(String firstName) {
        this.firstName = firstName ;
        return this ;
    }

    public PersonBuilder lastName(String lastName) {
        this.lastName = lastName ;
        return this ;
    }

    public Person build() {
        return new Person(firstName, lastName);
    }
}

显然如果你使用JavaFX 8,构造注解方法要少得多的工作。

Clearly if you are using JavaFX 8, the constructor annotation approach is much less work.

参考文献:

  • Proposal to deprecate builders
  • Tweak request to add constructor annotations
  • Builder pattern
  • FXML documentation (discusses builders, but not @NamedArg)
  • Request to add documentation on @NamedArgs to "Introduction to FXML" document

这篇关于什么是@NamedArg注解JavaFX中8的目的是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆