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
Таким образом, это должно дать вам немного света в темноте о том, что может вызвать проблему.