Java泛型“捕获?” [英] Java generics "capture of ?"

查看:206
本文介绍了Java泛型“捕获?”的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 TreeTable ,当更改单元格工厂时,我需要传递

 回调< TreeTableColumn< A,捕获?>,TreeTableCell< A,捕获?>> 

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



我试图创建

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

但是IDEA显示警告

像String)而不是?



任何人都可以向我解释如何处理这个问题吗?

谢谢。

编辑:



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



使用原始类型回调起作用。但有没有其他的选择如何解决这个问题?

解决方案

通配符表示未知类型。

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

 列表<?> list = ...; 
shuffle(list);

其中

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

这里,调用<$ c $>时,的未知值绑定到新类型变量 T c> shuffle 方法,允许shuffle方法引用该类型。



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

好的,你的代码有什么问题?您试图调用一个方法

 < S,T> setCellFactory(回调< TreeTableColumn< S,T>,TreeTableCell< S,T>>工厂); 

with

 回叫< TreeTableColumn< S,?>,TreeTableCell< S,>>>厂; 

在方法签名中,类型参数T代表单个类型,必须由呼叫者。为了方便起见,编译器会自动尝试推断出合适的值( - > type inference)。你的编译错误意味着编译器无法做到。



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



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

  setCellFactory(newFactory()); 

其中

 < S,T>回叫< TreeTableColumn< S,T>,TreeTableCell< S,T>> newFactory(){
返回新的回调< TreeTableColumn< S,T>,TreeTableCell< S,T>> {
...
}
}


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

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 ?"

I tried to create

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

but IDEA shows warning

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.

Could anyone explain to me how to work with this?

Thank you.

EDIT:

I gathered a little bit more information.. the CellFactory of 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).

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

解决方案

A wildcard represents an unknown type.

wildcard capture is 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 T upon invocation of the shuffle method, allowing the shuffle method to refer to that type.

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).

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.

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.

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:

setCellFactory(newFactory());

where

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

这篇关于Java泛型“捕获?”的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆