1

我正在尝试使用带有 JavaFX ListView 的接口,以允许在应用程序的不同点的列表中显示多个对象类型(不同 GUI 屏幕上的不同对象类型。我在我的 JavaFX 控制器类中将 ListView 定义为:

@FXML private static ListView<? extends ListDisplayObj> lvLeftBarItems;

并且ListDisplayObj是一个简单的界面:

public interface ListDisplayObj
{
    public String getListDisplayString();
}

我有一个数据库级方法,它根据给定的键获取要显示的对象列表 - 该方法定义为:

public ObservableList<? extends ListDisplayObj> getListObjectsForKey(String selectedKey)
{
    ...
}

稍后在控制器事件处理程序(或 initialize() 方法)中,我尝试使用 ObservableList 初始化 ListView,如下所示:

ObservableList<? extends ListDisplayObj> ol = MyObjectManager.getListObjectsForKey(selectedKey);
lvLeftBarItems.setItems(ol);

lvLeftBarItems.setItems(ol)调用会生成以下编译器错误(在 Netbeans 中):

incompatible types: ObservableList<CAP#1> cannot be converted to ObservableList<CAP#2>
  where CAP#1,CAP#2 are fresh type-variables:
    CAP#1 extends ListDisplayObj from capture of ? extends ListDisplayObj
    CAP#2 extends ListDisplayObj from capture of ? extends ListDisplayObj

有什么建议么?我不确定如何解决这个问题。我尝试过使用原始对象(实现 ListDisplayObj)而不是 的变体<? extends ListDisplayObj>,只是返回<ListDisplayObj>vs<? extends ListDisplayObj>等,但没有运气。

4

1 回答 1

0

当你有一个元素类型为 X 的列表时,你可以存储任何类型为 X 或 X 子类的对象。

ListView<? extends ListDisplayObj> lvLeftBarItems;

这个声明意味着它lvLeftBarItemsListView内容是某个未指定的子类ListDisplayObj,我们将其命名为 CAP#1(我知道它不是一个有效的类名,但让我们传递它以作为示例)。

您正在尝试添加一个元素,其类型在技术上也是未指定的子类ListDisplayObj,但我们将其命名为 CAP#2。

现在假设 CAP#1 扩展 ListDisplayObj 并且 CAP#2 扩展 ListDisplayObj ,所以很明显,您不能将 CAP#1 的实例转换为 CAP#2 或反之亦然,因此您不能将列表转换为CAP#1 到 CAP#2 的列表,这正是编译器说“ObservableList 无法转换为 ObservableList”时的意思——这些列表具有不同的不兼容类型,因为列表项具有不同的不兼容类型。

检查GenericsFAQ:通过通配符参数化类型的引用变量可访问/不可访问哪些方法和字段以获得更详细的说明。

至于您的代码,只需将声明替换lvLeftBarItems为非通配符泛型:

ListView<ListDisplayObj> lvLeftBarItems;
于 2014-04-02T06:07:28.887 回答