Ошибка компилятора при использовании универсального интерфейса Java. Интерфейс с JavaFX Collection.

1

Я пытаюсь использовать интерфейс с JavaFX ListView, чтобы можно было отображать несколько типов объектов в списке в разных точках приложения (разные типы объектов на разных графических интерфейсах GUI. Я определил ListView в моем классе контроллера JavaFX как:

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

и ListDisplayObj - это простой интерфейс:

public interface ListDisplayObj
{
    public String getListDisplayString();
}

У меня есть метод уровня базы данных, который получает список объектов, которые будут отображаться на основе заданного ключа, - метод определяется как:

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

Позже в обработчике событий контроллера (или в методе initialize()) я пытаюсь инициализировать ListView с помощью ObservableList следующим образом:

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

Какие-либо предложения? Я не уверен, как это решить. Я пробовал варианты использования raw Object (который реализует ListDisplayObj) вместо <? extends ListDisplayObj> <? extends ListDisplayObj>, просто вернув <ListDisplayObj> vs <? extends ListDisplayObj> <? extends ListDisplayObj> и т.д. не повезло.

Теги:
generics
collections
interface
observablelist

1 ответ

0

Когда у вас есть список, чей тип элемента X, вы можете сохранить любой объект, тип которого является X или подклассом X.

ListView<? extends ListDisplayObj> lvLeftBarItems;

Это объявление означает, что lvLeftBarItems - это ListView, содержимое которого является некоторым неуказанным подклассом ListDisplayObj, позволяет называть его CAP # 1 (я знаю, что это не допустимое имя класса, но позволяет передать его, например, для целей).

Вы пытаетесь добавить элемент, тип которого также является технически неопределенным подклассом ListDisplayObj, но позволяет называть его CAP # 2.

Теперь предположим, что CAP # 1 расширяет ListDisplayObj и CAP # 2 расширяет ListDisplayObj, поэтому очевидно, что вы не можете использовать экземпляр CAP # 1 для CAP # 2 или наоборот, и из этого следует, что вы не можете использовать список CAP # 1 в список CAP # 2, и это именно то, что означает компилятор, когда говорится, что "ObservableList не может быть преобразован в ObservableList" - эти списки имеют другой несовместимый тип, потому что элементы списка имеют другой несовместимый тип.

Проверка GenericsFAQ: какие методы и поля доступны/недоступны через ссылочную переменную подстановочного параметра для более подробного объяснения.

Что касается вашего кода, просто замените объявление lvLeftBarItems на lvLeftBarItems общий:

ListView<ListDisplayObj> lvLeftBarItems;
  • 0
    Спасибо за предложение, к сожалению, именно так я и начал (использование перед подстановочными знаками), и это не сработало. Я определил ListView<ListDisplayObj> lvLeftBarItems; и попытался использовать ObservableList<ListDisplayObj> = MyObjectManager.getListObjectsForKey(selectedKey); который возвращает ObservableList <ConcreteObject>, где ConcreteObject implements ListDisplayObj . Обратите внимание, что это интерфейс (реализует, а не расширяет). В этом случае компилятор отклоняет присвоение коллекции из служебного метода, говоря, что типы несовместимы. Возможно, я должен опубликовать этот вопрос отдельно.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню