Java泛型“捕获?”

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/40217285/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 22:31:37  来源:igfitidea点击:

Java generics "capture of ?"

javagenericswildcardcapture

提问by kotycheese

I'm working with a TreeTableand when changing cell factory I am required to pass a

我正在使用一个TreeTable,当改变细胞工厂时,我需要通过一个

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

where A is a class I am working with but I have no idea how to work with the "capture of ?"

其中 A 是我正在使用的类,但我不知道如何使用“捕获 ?”

I tried to create

我试图创造

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

but IDEA shows warning

但 IDEA 显示警告

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

I tried using specific classes (like String) instead of "?" as well, but nothing helped.

我尝试使用特定的类(如 String)而不是“?” 同样,但没有任何帮助。

Could anyone explain to me how to work with this?

谁能向我解释如何处理这个问题?

Thank you.

谢谢你。

EDIT:

编辑:

I gathered a little bit more information.. the CellFactoryof TreeTableColumn<S,T>should be Callback<TreeTableColumn<S,T>,TreeTableCell<S,T>>, however, the TreeTableColumn that I'm working with is created as a raw type (in a library).

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

Using a raw type Callback works. But are there any other options how to work this around?

使用原始类型回调有效。但是还有其他选择可以解决这个问题吗?

采纳答案by meriton

A wildcardrepresents an unknown type.

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

wildcard captureis the process of binding the value of a wildcard type to a new type variable. For example:

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

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

where

在哪里

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

Here, the unknown value of ?is bound to the new type variable Tupon invocation of the shufflemethod, allowing the shuffle method to refer to that type.

在这里,未知值在调用方法时?绑定到新的类型变量,从而允许 shuffle 方法引用该类型。Tshuffle

The Java compiler internally represents the value of a wildcard by capturing it in an anonymous type variable, which it calls "capture of ?" (actually, javac calls them "capture #1 of ?" because different uses of ?may refer to different types, and therefore have different captures).

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

Ok, so what is wrong in your code? You are trying to invoke a method

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

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

with

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

In the method signature, the type parameter T stands for a single type, that must be provided by the caller. As a convenience, the compiler automatically attempts to infer a suitable value (-> type inference). Your compilation error means that the compiler was unable to do so.

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

In this instance, this is not a shortcoming of type inference, as it is actually impossible to assign a suitable value to T, because both ?need to be subtypes of T, but the compiler can not know that the two ?stand for the same type, or even related types.

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

To successfully invoke this method, your argument type must use the same type for all occurrences of T. If you already have such a type at hand, go ahead and use it. Otherwise, you may be able to introduce one using wildcard capture:

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

setCellFactory(newFactory());

where

在哪里

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

回答by Nico

from what I found from what is a capture conversionand oracle capture generic docsit looks like you are facing some problem where the compiler can't find the needed helper class, or tries to place Object in there, but what you give him can not be converted safely.

从我从 捕获转换oracle 捕获通用文档中发现的内容来看,您似乎面临一些问题,编译器找不到所需的帮助程序类,或者尝试将 Object 放在那里,但是您给他的却不能安全转换。

EDIT:

编辑:

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.

DEFAULT_CELL_FACTORY

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

如果未在 TreeTableColumn 实例上指定 cellFactory,则默认情况下将使用该实例。目前,如果项目是一个节点,它只是在图形属性中呈现 TableCell 项目属性,或者如果它不为空,它就简单地调用 toString(),在文本属性中设置结果字符串。

and

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.

设置单元工厂

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

设置属性 cellFactory 的值。属性描述:该列中所有单元格的单元格工厂。单元工厂负责为单个 TreeTableColumn 呈现每个 TreeTableCell 中包含的数据。默认情况下,TreeTableColumn 使用默认的单元工厂,但这可以替换为自定义实现,例如以不同的方式显示数据或支持编辑。在其他地方有很多关于创建自定义单元工厂的文档(例如,请参阅 Cell 和 TreeTableView)。

最后,javafx.scene.control.cell 包中提供了许多预构建的单元工厂。

taken out from Java 8 API Doc.

Java 8 API Doc 中取出。

so something like this should be going more into the right direction:

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

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

or something like this depending on what excactly you want to give into the Cell.

或类似的东西,这取决于您想给 Cell 提供什么。

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

these code snippets are taken from This StackOverflow Thread

这些代码片段取自This StackOverflow Thread

and last this link could help you too: TableView Cell Tutorial

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

So this should give you some more light in the dark about what might be causing the problem.

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