为什么与 CheckBoxTableCell 的 setSelectedStateCallback 等效的 lambda 在 JavaFX8 中编译失败?

Why does the lambda equivalent of a CheckBoxTableCell's setSelectedStateCallback fail to compile in JavaFX8?

亲戚Java菜鸟问题

我试图解决 CheckBoxTableCell 遇到的另一个问题,遇到了这个 post:CheckBoxTableCell changelistener not working

在试验用户 James_D 的示例时,我尝试将 setSelectedStateCallback 转换为 lambda 表达式。但是,它没有编译并生成 "incompatible parameter types in lambda expression" 错误。

原始代码如下所示:

cbCell.setSelectedStateCallback(new Callback<Integer, ObservableValue<Boolean>>() {
    @Override
    public ObservableValue<Boolean> call(Integer index) {
        return selected;
    }
});

NetBeans 8.2 将其转换为:

cbCell.setSelectedStateCallback((Integer index) -> selected);

然后我按照用户 fabian 在这个 post 中的回答手动编写了 lambda 并最终得到了同样的结果。

为什么 lambda 表达式无法编译?应该如何编写才能编译?

如果有帮助,这里是一个 MVCE,带有原始和 lambda 等效代码。

我正在使用 JavaFX8 (JDK1.8.0_181)。

package test26;

import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.beans.Observable;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.CheckBoxTableCell;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import javafx.util.Callback;

public class Test26 extends Application {

    private Parent createContent() {

        TableView<TestModel> table = new TableView<>();
        ObservableList<TestModel> olTestModel = FXCollections.observableArrayList(testmodel -> new Observable[] {
                testmodel.checkboxProperty()
        });
        olTestModel.add(new TestModel(false));
        table.setItems(olTestModel);

        TableColumn<TestModel, Boolean> colCheckbox = new TableColumn<>("checkbox");

        colCheckbox.setCellValueFactory(cellData -> cellData.getValue().checkboxProperty());

        colCheckbox.setCellFactory((TableColumn<TestModel, Boolean> cb) -> {

            final CheckBoxTableCell cbCell = new CheckBoxTableCell<>();
            final BooleanProperty selected = new SimpleBooleanProperty();

            //Original code ...
            cbCell.setSelectedStateCallback(new Callback<Integer, ObservableValue<Boolean>>() {
                @Override
                public ObservableValue<Boolean> call(Integer index) {
                    return selected;
                }
            });

            //... and lambda equivalent that doesn't compile
            cbCell.setSelectedStateCallback((Integer index) -> selected);

            return cbCell;
        });

        table.getSelectionModel().setCellSelectionEnabled(true);
        table.setEditable(true);
        table.getColumns().add(colCheckbox);
        BorderPane content = new BorderPane(table);

        return content;

    }

    public class TestModel {

        private BooleanProperty checkbox;
        public TestModel() {
            this(false);
        }
        public TestModel(
            boolean checkbox
        ) {
            this.checkbox = new SimpleBooleanProperty(checkbox);
        }
        public Boolean getCheckbox() {
            return checkbox.get();
        }
        public void setCheckbox(boolean checkbox) {
            this.checkbox.set(checkbox);
        }
        public BooleanProperty checkboxProperty() {
            return checkbox;
        }

    }

    @Override
    public void start(Stage stage) throws Exception {
        stage.setScene(new Scene(createContent()));
        stage.setTitle("Test");
        stage.setWidth(500);
        stage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }

}

这里的问题是您在此声明中使用了原始类型,因此它期望 Object 而不是 Integer。但是您在此处明确传递了导致错误的 Integer

final CheckBoxTableCell cbCell

一个快速而肮脏的修复方法是

cbCell.setSelectedStateCallback(index -> selected);

在上述情况下,编译器会将类型推断为 Object,因为它没有明确给出。但这会给你一个未经检查的警告。所以在 long 运行 中使用通用类型而不是原始类型。

参数化您的 CheckBoxTableCell 声明,如下所示,它将修复代码中所有未检查的警告。所以这将是一个救命恩人。

final CheckBoxTableCell<TestModel, Boolean> cbCell = new CheckBoxTableCell<>();

然后将您的代码改回您使用的初始版本,

cbCell.setSelectedStateCallback((Integer index) -> selected);

请注意,现在没有任何编译错误。然后删除类型 Integer 让编译器推断它。