何时使用JavaFX属性setter和getter,而不是直接使用该属性

vew*_*ert 9 java getter setter javafx properties

我熟悉Java,但刚刚开始学习JavaFX,并专门了解JavaFX属性.我理解Oracle的以下示例中显示的基本设计模式:

package propertydemo;

import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;

class Bill {

    // Define a variable to store the property
    private DoubleProperty amountDue = new SimpleDoubleProperty();

    // Define a getter for the property's value
    public final double getAmountDue(){return amountDue.get();}

    // Define a setter for the property's value
    public final void setAmountDue(double value){amountDue.set(value);}

     // Define a getter for the property itself
    public DoubleProperty amountDueProperty() {return amountDue;}

}
Run Code Online (Sandbox Code Playgroud)

我不明白的是何时/为什么我会使用getter和setter方法,而不是直接使用Property?

我在想的是你可能想要一些getter和/或setter中的自定义代码,它们可以对数据进行一些操作前/操作/验证,但是如果你创建一个自定义的getter和/或setter,你会得到不同的结果那么,取决于你是否直接使用getter/setter或属性,对我来说,这看起来很危险.

如果getter/setter只是调用Property的get和set方法,那么为什么要使用它们呢?

任何有关这方面的见解将不胜感激.

Jam*_*s_D 14

JavaFX属性模式旨在扩展旧的标准JavaBean模式.因此,在你的榜样,根据JavaBean的惯例,你有型(读写)属性doubleamount.这由两种方法决定

public double getAmount() ;
public void setAmount(double amount);
Run Code Online (Sandbox Code Playgroud)

JavaBean模式通过"绑定属性"允许一些有限的"可观察性",其中bean支持注册a PropertyChangeListener.UI工具包通常需要观察属性并响应更改.例如,Label有一个text属性是有道理的.如果text属性发生变化,则Label需要通知,以便它知道重新绘制自己.乍一看,使用具有绑定属性的JavaBeans将是一种方法.但是,在UI工具箱中使用此机制会产生性能问题,因为如果不立即计算值,则无法通知值不再有效.这意味着,例如,对属性的每次更改都会重新计算布局.

JavaFX团队显然希望做的是定义一种模式

  1. 符合标准的JavaBean模式,和
  2. 支持的可观察属性,可以跟踪无效,而无需在每次更改值时重新计算相关值("延迟可观察值")

因此,JavaFX解决方案是创建支持ChangeListeners的属性,这些属性在值更改时通知,InvalidationListeners 和s在值不再有效时通知.这意味着,例如,布局机制可以跟踪它当前是否有效,而不会在它变为无效时强制重新计算.布局将仅在实际屏幕脉冲(即渲染场景时)上重新计算,并且仅在其无效时才重新计算.

(作为快速概念验证,请考虑以下事项:

DoubleProperty width = new SimpleDoubleProperty(3);
DoubleProperty height = new SimpleDoubleProperty(4);
ObservableDoubleValue area = Bindings.createDoubleBinding(() -> {
    double a = width.get() * height.get();
    System.out.println("Computed area: "+a);
    return a ;
}, width, height);
System.out.println("Area is "+area.getValue());
width.set(2);
height.set(3);
System.out.println("Area is "+area.getValue());
Run Code Online (Sandbox Code Playgroud)

请注意,中间值,当width为2且height仍为4时,从不计算.)

因此,JavaFX中的值由这些observable表示,它们Properties同时支持失效侦听器和更改侦听器,这意味着它们基本上是"懒惰地可观察".通过属性访问器方法(amountProperty()在您的示例中)公开属性本身就足以支持此功能.

但是,在语义上,暴露一个DoubleProperty意味着bean具有类型的值double.为了保持与旧JavaBean约定的兼容性,此bean应通过公开相应的getset方法来宣传这一事实.因此,JavaFX Property模式既需要"属性访问器"(amountProperty()),也需要标准的JavaBean方法(getAmount()setAmount(...)).这意味着遵循JavaFX模式的bean可以在使用标准JavaBean模式的任何地方使用,例如在JPA中.

请注意,要使模式正常工作,应该始终如此,amountProperty().get() == getAmount()并且amountProperty().set(x)具有与之相同的效果setAmount(x).通过创建getset方法可以保证(即使bean类是子类)final,如示例所示.

如果您自己调用方法来检索或更改属性的值,则调用哪个并不重要,因为它们可以保证具有相同的效果.由于JavaFX Property模式是JavaBean模式的扩展,因此调用getset方法可能会有一点点偏好:在某种意义上,访问该值只需要JavaBean功能,而不是完整的JavaFX属性功能,因此它可能会产生一些语义意义只依赖于那个功能.然而,在实践中,你使用它没有任何区别.