JavaFX中的ChangeListener:如何使这些泛型参数不那么难看?

时间:2016-01-12 01:08:22

标签: java generics javafx

关于泛型,我被告知铸造是坏的,并且通常有一些方法可以完全消除铸造,因为编译器在检查程序时能够做到最好。在ChangeListener添加ReadOnlyDoubleProperty似乎打败了这个理想。这是API中的缺陷,还是规则的例外,还是实际上有一些方法可以使代码看起来很好?

nodeA.heightProperty().addListener(new ChangeListener<Number>() {
    @Override
    public void changed(ObservableValue< ? extends Number > observable,
                        Number oldValue,
                        Number newValue ) {
        final double ov = oldValue.doubleValue();
        final double nv = newValue.doubleValue();
        @SuppressWarnings("unchecked")
        final ObservableValue<Double> ob = ( ObservableValue< Double > ) observable;
        // do stuff
    }
});

首先,我可以在ChangeListener上使用的最具体的类型参数是Number。我应该可以使用Double!它是DoubleExpression!由于这个问题,我必须将参数解包为changed方法。请帮助减少这里的行数。 Lambdas可以减少行数,但我特别询问泛型。

1 个答案:

答案 0 :(得分:5)

tl; dr:使用asObject

首先请注意,在您发布的示例中,根本没有理由引用observable参数,因为它必须与nodeA.heightProperty()具有相同的引用。因此,您可以使用

简单地消除向下转发
nodeA.heightProperty().addListener(new ChangeListener<Number>() {
    @Override
    public void changed(ObservableValue< ? extends Number > observable,
                        Number oldValue,
                        Number newValue ) {
        final double ov = oldValue.doubleValue();
        final double nv = newValue.doubleValue();

        // do stuff with nodeA.heightProperty() ...
    }
});

这并不奇怪:事实上我认为我不需要引用传递给此方法的observable,因为我总是使用相同的模式。

至于ReadOnlyDoubleProperty实现ObservableValue<Number>而不是ObservableValue<Double>,这可能是一个便利功能,也可能是设计缺陷,具体取决于您的观点。 (参见讨论here,以及其他地方......)。解决方法是在asObject()上调用ReadOnlyDoubleProperty,该ReadOnlyObjectProperty<Double>会返回与ReadOnlyDoubleProperty双向绑定的ObservableValue<Double>,并实现nodeA.heightProperty().asObject().addListener(new ChangeListener<Double>() { @Override public void changed(ObservableValue< ? extends Double > observable, Double oldValue, Double newValue ) { final double ov = oldValue.doubleValue(); final double nv = newValue.doubleValue(); // do stuff } });

ov

(取消装箱也会使nvnodeA.heightProperty().asObject().addListener((obs, oldValue, newValue) -> { // obs is now an ObservableValue<Double>, if you need it // oldValue is a Double, which can be treated as a double via unboxing // similarly newValue is a Double // do stuff.. }); 在上面变得多余。)

你当然可以用lambdas使这个更好:

formatter
相关问题