在我的应用程序中,我有一个基于抽象基本数据类型的特定数据项,具有相应的具体子类型。
我有一个UI组件,显示这些数据项的列表。我想公开基本数据类型的ListProperty(它具有我想要显示的所有公共字段),并且能够将它绑定到提供特定子类型列表的其他组件。但我似乎无法使这些列表兼容。
说明问题的代码示例:
import javafx.beans.property.ListProperty;
import javafx.beans.property.SimpleListProperty;
public class GenericTest
{
static class BaseClass {}
static class SubClass extends BaseClass {}
ListProperty<SubClass> sourceList = new SimpleListProperty<>();
ListProperty<? extends BaseClass> observingList = new SimpleListProperty<>();
{
observingList.bind( sourceList );
}
}
我在bind()调用上遇到编译错误 - 不兼容的类型。我以为我理解Java泛型,但显然不是。
是否可以将列表属性与混合中的泛型绑定,还是应该寻找替代解决方案?
答案 0 :(得分:2)
observingList
的元素类型是“BaseClass
的某个未知子类”。所以基本上你必须绑定到一个列表,其元素类型与那个特定但未知的类型兼容。
从编译器的角度来看,您可以指定observingList
,例如BaseClass
的不同子类,即如果你有
static class AnotherClass extends BaseClass {}
然后
observingList = new SimpleListProperty<AnotherClass>();
完全合法。
现在由于SubClass
的实例不是AnotherClass
的实例,因此应该清楚为什么绑定无法编译。
或许另一种看待此问题的方法是考虑尝试致电observingList.add(...)
。你能合法地将这个方法传递给那个方法吗?虽然你显然不需要自己调用(因为你将它绑定到某些东西上),bind(...)
的实现显然需要在某个时候调用add(...)
:如果你没办法要调用该方法,绑定也无法这样做。
基本上,要使绑定起作用,您需要指定类型(没有通配符)。所以,显然你可以做到
ListProperty<SubClass> observingList = new SimpleListProperty<>();
然后绑定工作,但你也可以参数化类型,例如:
public static <T extends BaseClass> ListProperty<T> createBoundList(ListProperty<T> sourceList) {
ListProperty<T> observingList = new SimpleListProperty<>();
observingList.bind(sourceList);
return observingList ;
}
然后
ListProperty<? extends BaseClass> observingList = createBoundList(sourceList);
将编译。
答案 1 :(得分:0)
这是一种解决方法,而不是直接绑定(James_D的答案看起来像是正确的解决方案),但你也可以这样做......
sourceList.addListener((observable, oldValue, newValue) -> observingList.setAll(newValue));
根据我的具体情况,这对我有用,但你的里程可能会有所不同......