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>> {
...
}
}