Попытка № 3: Невозможно сформировать выражение требуемого типа с двумя вопросительными знаками в Java
Мой предыдущий SSCCE был неверным сам по себе. Я пытался написать еще один, но это тоже было неправильно. Итак, на данный момент я не понимаю проблему и, следовательно, не могу написать пример на чистом Java и поэтому публикую пример с библиотечными классами:
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.util.Callback;
public class DoubleQuestionMark3 {
public static class MyClass {
}
public static void main(String[] args) {
TableColumn<MyClass, ?> column = new TableColumn();
Callback<TableColumn<MyClass, ?>, TableCell<MyClass, ?>> callback = new Callback<TableColumn<MyClass, ?>, TableCell<MyClass, ?>>() {
@Override
public TableCell<MyClass, ?> call(TableColumn<MyClass, ?> param) {
return null;
}
};
column.setCellFactory(callback);
}
}
Вопрос такой же: как приготовить callback
соответствующего класса?
Если это невозможно, то, во-первых, пожалуйста, укажите, что это действительно невозможно, и, во-вторых, объясните, ПОЧЕМУ, это невозможно.
ОБНОВИТЬ
Определение Object
для обратного вызова не помогает:
Callback<TableColumn<MyClass, Object>, TableCell<MyClass, Object>> callback = new Callback<TableColumn<MyClass, Object>, TableCell<MyClass, Object>>() {
@Override
public TableCell<MyClass, Object> call(TableColumn<MyClass, Object> param) {
return null;
}
};
1 ответ
Когда вы объявляете переменную с типом TableColumn<MyClass, ?>
, ?
обозначает неизвестный тип, поэтому невозможно определить соответственно типизированный Callback
переменная, потому что это относится к неизвестному типу.
Если у вас есть универсальный код, который может работать с произвольным типом, вы должны написать этот код в классе или методе, имеющем переменную типа, давая неизвестному типу имя, например, вы можете использовать ссылку на метод:
public class DoubleQuestionMark3 {
public static void main(String[] args) {
TableColumn<MyClass, ?> column = new TableColumn();
column.setCellFactory(DoubleQuestionMark3::call);
}
static <T> TableCell<MyClass, T> call(TableColumn<MyClass, T> param) {
// fill with life...
return new TableCell<>();
}
}
Это работает, как код, работающий с произвольным типом T
, может использоваться, даже если вызывающий не знает тип, как с TableColumn<MyClass, ?>
,
Кроме того, вы можете переместить весь код инициализации в общий метод:
public class DoubleQuestionMark3 {
public static void main(String[] args) {
TableColumn<MyClass, ?> column = new TableColumn();
initialize(column);
}
static <T> void initialize(TableColumn<MyClass, T> column) {
Callback<TableColumn<MyClass, T>, TableCell<MyClass, T>> cellFactory
= new Callback<TableColumn<MyClass, T>, TableCell<MyClass, T>>() {
@Override
public TableCell<MyClass, T> call(TableColumn<MyClass, T> param) {
// fill with life
return new TableCell<>();
}
};
column.setCellFactory(cellFactory);
}
}
Проще говоря, когда у вас есть неизвестный тип, который появляется в нескольких местах, и вы должны убедиться, что эти вхождения неизвестного типа относятся к одному и тому же типу, вам нужна переменная именованного типа.