供应商接受方法中的 Java 泛型不兼容类型



>我有一个带有泛型参数的方法:

public static void addActionColumnAndSetSelectionListener(Grid<? extends UpdatableRecord<?>> grid,
EditDialog<? extends UpdatableRecord<?>> dialog,
Callback afterSave, Supplier<UpdatableRecord<?>> onNewRecord,
Consumer<? extends UpdatableRecord<?>> insteadOfDelete) {
Button buttonAdd = new Button(grid.getTranslation("Add"));
buttonAdd.addClickListener(event -> dialog.open(onNewRecord.get(), afterSave));
grid.addComponentColumn(record -> {
Button delete = new Button(grid.getTranslation("Delete"));
delete.addThemeVariants(ButtonVariant.LUMO_ERROR);
delete.addClickListener(event -> {
getBean(TransactionTemplate.class).executeWithoutResult(transactionStatus -> {
try {
if (insteadOfDelete != null) {
insteadOfDelete.accept(record);
} else {
getBean(DSLContext.class).attach(record);
}
record.delete();
} catch (DataAccessException e) {
Notification.show(e.getMessage());
}
});
});
HorizontalLayout horizontalLayout = new HorizontalLayout(delete);
horizontalLayout.setJustifyContentMode(FlexComponent.JustifyContentMode.END);
return horizontalLayout;
}).setTextAlign(ColumnTextAlign.END).setHeader(buttonAdd);
grid.addSelectionListener(event -> event.getFirstSelectedItem().ifPresent(record -> dialog.open(record, afterSave)));
}

问题是行insteadOfDelete.accept(record);没有编译:

Error:(47, 52) java: incompatible types: org.jooq.UpdatableRecord<capture#1 of ?> cannot be converted to capture#2 of ? extends org.jooq.UpdatableRecord<?>

我不明白这个问题。如果我改变

Consumer<? extends UpdatableRecord<?>> insteadOfDelete

Consumer<UpdatableRecord<?>> insteadOfDelete

它编译。

递归泛型的乐趣...在UpdatableRecord类型层次结构中使用它们可以被视为jOOQ的设计缺陷。应在方法的泛型类型变量中捕获通配符。虽然在使用? extends UpdatableRecord<?>甚至只是UpdatableRecord<?>时它可能在某种程度上起作用,但我认为使用<R>类型变量,您将获得更干净的代码。

这可能有效(我只更改了参数并添加了<R>类型变量,没有别的(:

public static <R extends UpdatableRecord<R>> void addActionColumnAndSetSelectionListener(
Grid<R> grid,
EditDialog<R> dialog,
Callback afterSave, 
Supplier<R> onNewRecord,
Consumer<R> insteadOfDelete
) {
Button buttonAdd = new Button(grid.getTranslation("Add"));
buttonAdd.addClickListener(event -> dialog.open(onNewRecord.get(), afterSave));
grid.addComponentColumn(record -> {
Button delete = new Button(grid.getTranslation("Delete"));
delete.addThemeVariants(ButtonVariant.LUMO_ERROR);
delete.addClickListener(event -> {
getBean(TransactionTemplate.class).executeWithoutResult(transactionStatus -> {
try {
if (insteadOfDelete != null) {
insteadOfDelete.accept(record);
} else {
getBean(DSLContext.class).attach(record);
}
record.delete();
} catch (DataAccessException e) {
Notification.show(e.getMessage());
}
});
});
HorizontalLayout horizontalLayout = new HorizontalLayout(delete);
horizontalLayout.setJustifyContentMode(FlexComponent.JustifyContentMode.END);
return horizontalLayout;
}).setTextAlign(ColumnTextAlign.END).setHeader(buttonAdd);
grid.addSelectionListener(event -> event.getFirstSelectedItem().ifPresent(
record -> dialog.open(record, afterSave)));
}

此外,我还删除了各个方法参数的协方差,因为我认为您可能不需要它。否则,请记住Supplier是协变的,Consumer是逆变的。这个答案在这里很好地解释了它。这解释了你的观察,当你有一个不变的消费者时,事情突然编译了。

最新更新