[英]Java Generics incompatible types in Supplier accept method
我有一個帶有泛型參數的方法:
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
它編譯。
遞歸 generics 的樂趣... 在UpdatableRecord
類型層次結構中使用它們可以看作是 jOOQ 的設計缺陷。 您應該在方法的泛型類型變量中捕獲通配符。 雖然它在使用時可能會在某種程度上起作用? extends UpdatableRecord<?>
? 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
是逆變的。 這個答案很好地解釋了它。 這解釋了你觀察到當你有一個不變的消費者時突然編譯的東西。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.