Попытка № 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);
    }
}

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

Другие вопросы по тегам