Java generics "захват?"

Я работаю с TreeTable, а при смене ячейки factory мне нужно передать

Callback<TreeTableColumn<A, capture of ?>, TreeTableCell<A, capture of ?>>

где A - класс, с которым я работаю, но я понятия не имею, как работать с "захватом?"

Я попытался создать

new Callback<TreeTableColumn<A, ?>, TreeTableCell<A, ?>>

но IDEA показывает предупреждение

setCellFactory(Callback<TreeTableColumn<A, capture<?>>, TreeTableCell<A, capture<?>>>) in TreeTableColumn cannot be applied to (anonymous Callback<TreeTableColumn<A, ?>, TreeTableCell<A, ?>>)

Я пытался использовать определенные классы (например, String) вместо "?" также, но ничего не помогло.

Может ли кто-нибудь объяснить мне, как с этим работать?

Спасибо.

EDIT:

Я собрал немного больше информации. CellFactory of TreeTableColumn<S,T> должен быть Callback<TreeTableColumn<S,T>, TreeTableCell<S,T>>, однако TreeTableColumn, с которым я работаю, создается как необработанный тип (в библиотеке).

Использование обратного вызова обратного вызова. Но есть ли другие варианты, как это можно сделать?

Ответ 1

Подстановочный знак представляет собой неизвестный тип.

подстановочный знак - это процесс привязки значения подстановочного типа к переменной нового типа. Например:

List<?> list = ...;
shuffle(list);

где

<T> void shuffle(List<T> list) {
    ...
}

Здесь неизвестное значение ? привязано к новой переменной типа T при вызове метода shuffle, позволяя методу тасования ссылаться на этот тип.

Компилятор Java внутренне представляет значение подстановочного знака, захватывая его в переменной анонимного типа, которую он вызывает "захват?". (на самом деле, javac называет их "capture # 1 of?", потому что различные применения ? могут относиться к разным типам и, следовательно, иметь разные захваты).

Хорошо, так что не так в коде? Вы пытаетесь вызвать метод

<S,T> setCellFactory(Callback<TreeTableColumn<S,T>, TreeTableCell<S,T>> factory);

с

Callback<TreeTableColumn<S,?>, TreeTableCell<S, ?>> factory;

В сигнатуре метода параметр T обозначает один тип, который должен быть предоставлен вызывающим. В качестве удобства компилятор автоматически пытается вывести подходящее значение (- > вывод типа). Ошибка компиляции означает, что компилятор не смог этого сделать.

В этом случае это не является недостатком вывода типа, поскольку на самом деле невозможно присвоить подходящее значение T, потому что оба ? должны быть подтипами T, но компилятор не может что два ? означают один и тот же тип или даже связанные типы.

Чтобы успешно вызвать этот метод, ваш тип аргумента должен использовать тот же тип для всех вхождений T. Если у вас уже есть такой тип под рукой, используйте его и используйте. В противном случае вы можете ввести один с помощью подстановочного знака:

setCellFactory(newFactory());

где

<S,T> Callback<TreeTableColumn<S,T>, TreeTableCell<S,T>> newFactory() {
    return new Callback<TreeTableColumn<S,T>, TreeTableCell<S,T>> {
        ...
    }
}

Ответ 2

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

EDIT:

DEFAULT_CELL_FACTORY

public static final Callback<TreeTableColumn<?,?>,TreeTableCell<?,?>>

Если в экземпляре TreeTableColumn не указано cellFactory, тогда этот будет использоваться по умолчанию. В настоящее время он просто Свойство элемента TableCell в графическом свойстве, если элемент является Node или просто вызывает toString(), если он не равен NULL, установив результирующая строка внутри свойства text.

и

setCellFactory

public final void setCellFactory(Callback<TreeTableColumn<S,T>,TreeTableCell<S,T>> value)

Устанавливает значение свойства cellFactory. Описание недвижимости: Ячейка factory для всех ячеек в этом столбце. Ячейка factory отвечает за рендеринг данных, содержащихся в каждом TreeTableCell, для одной TreeTableColumn. По умолчанию TreeTableColumn использует ячейку по умолчанию factory, но ее можно заменить на пользовательскую реализацию, например, для отображения данных по-другому или для поддержки редактирования. Существует много документации по созданию пользовательских клеточных фабрик в другом месте (см. например Cell и TreeTableView).

Наконец, в пакете javafx.scene.control.cell имеется ряд готовых клеточных фабрик.

извлечен из Java 8 API Doc.

поэтому что-то вроде этого должно идти в правильном направлении:

public static <S> Callback<TableColumn<S,String>, TableCell<S,String>> forTableColumn() {
   return forTableColumn(new DefaultStringConverter());
}

или что-то в этом роде, в зависимости от того, что вы хотите передать в ячейку.

setCellFactory(TextFieldTableCell.<DataModel, Integer>forTableColumn(new IntegerStringConverter()));

эти фрагменты кода взяты из fooobar.com/info/503907/...

и последняя ссылка может вам помочь: Учебное пособие по TableView Cell

Таким образом, это должно дать вам немного света в темноте о том, что может вызвать проблему.