Java 仿制药 "capture of ?"

Java generics "capture of ?"

我正在与 TreeTable 合作,在更换细胞工厂时我需要通过

Callback<TreeTableColumn<A, capture of ?>, TreeTableCell<A, capture of ?>>

其中 A 是 class 我正在使用但我不知道如何使用 "capture of ?"

我尝试创建

new Callback<TreeTableColumn<A, ?>, TreeTableCell<A, ?>>

但是 IDEA 显示警告

setCellFactory(Callback<TreeTableColumn<A, capture<?>>, TreeTableCell<A, capture<?>>>) in TreeTableColumn cannot be applied to (anonymous Callback<TreeTableColumn<A, ?>, TreeTableCell<A, ?>>)

我尝试使用特定的 classes(比如字符串)而不是“?”也一样,但没有任何帮助。

任何人都可以向我解释如何使用它吗?

谢谢。

编辑:

我收集了更多信息.. TreeTableColumn<S,T>CellFactory 应该是 Callback<TreeTableColumn<S,T>,TreeTableCell<S,T>>, 然而, 我正在使用的 TreeTableColumn被创建为原始类型(在库中)。

使用原始类型回调有效。但是还有其他解决方法吗?

从我发现的 what is a capture conversion and oracle capture generic docs 看起来您遇到了一些问题,编译器无法找到所需的助手 class,或者试图将 Object 放在那里,但您提供的内容无法安全转换。

编辑:

DEFAULT_CELL_FACTORY

public static final Callback<TreeTableColumn<?,?>,TreeTableCell<?,?>>

If no cellFactory is specified on a TreeTableColumn instance, then this one will be used by default. At present it simply renders the TableCell item property within the graphic property if the item is a Node, or it simply calls toString() if it is not null, setting the resulting string inside the text property.

setCellFactory

public final void setCellFactory(Callback<TreeTableColumn<S,T>,TreeTableCell<S,T>> value)

Sets the value of the property cellFactory. Property description: The cell factory for all cells in this column. The cell factory is responsible for rendering the data contained within each TreeTableCell for a single TreeTableColumn. By default TreeTableColumn uses a default cell factory, but this can be replaced with a custom implementation, for example to show data in a different way or to support editing. There is a lot of documentation on creating custom cell factories elsewhere (see Cell and TreeTableView for example).

Finally, there are a number of pre-built cell factories available in the javafx.scene.control.cell package.

取自Java 8 API Doc.

所以像这样的事情应该朝着正确的方向发展:

public static <S> Callback<TableColumn<S,String>, TableCell<S,String>> forTableColumn() {
   return forTableColumn(new DefaultStringConverter());
}

或类似这样的内容,具体取决于您要向 Cell 提供的内容。

setCellFactory(TextFieldTableCell.<DataModel, Integer>forTableColumn(new IntegerStringConverter()));

这些代码片段来自

最后这个 link 也可以帮助你: TableView Cell Tutorial

所以这应该让您在黑暗中更清楚地了解可能导致问题的原因。

一个通配符表示未知类型。

通配符捕获是将一个通配符类型的值绑定到一个新的类型变量上的过程。例如:

List<?> list = ...;
shuffle(list);

哪里

<T> void shuffle(List<T> list) {
    ...
}

此处,? 的未知值在调用 shuffle 方法时绑定到新类型变量 T,允许 shuffle 方法引用该类型。

Java 编译器通过在匿名类型变量中捕获它来在内部表示通配符的值,它称为 "capture of ?"(实际上,javac 将它们称为 "capture #1 of ?",因为不同的用途? 可能引用不同的类型,因此有不同的捕获)。

好的,你的代码有什么问题?您正在尝试调用方法

<S,T> setCellFactory(Callback<TreeTableColumn<S,T>, TreeTableCell<S,T>> factory);

Callback<TreeTableColumn<S,?>, TreeTableCell<S, ?>> factory;

在方法签名中,类型参数T代表一个类型,必须由调用者提供。为方便起见,编译器会自动尝试推断合适的值(-> 类型推断)。你的编译错误意味着编译器无法这样做。

在这种情况下,这不是类型推断的缺点,因为实际上不可能为T分配一个合适的值,因为?都需要是[=17的子类型=],但是编译器无法知道这两个?代表的是同一个类型,甚至是相关的类型。

要成功调用此方法,您的参数类型必须对所有出现的 T 使用相同的类型。如果您手边已有这样的类型,请继续使用它。否则,您可以使用通配符捕获来引入一个:

setCellFactory(newFactory());

哪里

<S,T> Callback<TreeTableColumn<S,T>, TreeTableCell<S,T>> newFactory() {
    return new Callback<TreeTableColumn<S,T>, TreeTableCell<S,T>> {
        ...
    }
}