Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java generics "capture of ?"

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?

like image 894
kotycheese Avatar asked Oct 24 '16 11:10

kotycheese


People also ask

What does capture of mean Java?

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

What is wildcard capture in Java?

In some cases, the compiler infers the type of a wildcard. For example, a list may be defined as List<?> but, when evaluating an expression, the compiler infers a particular type from the code. This scenario is known as wildcard capture.

What is Java generics with examples?

Generics add that type of safety feature. We will discuss that type of safety feature in later examples. Generics in Java are similar to templates in C++. For example, classes like HashSet, ArrayList, HashMap, etc., use generics very well.

What is the use of wildcard in generics?

In generic code, the question mark (?), called the wildcard, represents an unknown type. The wildcard can be used in a variety of situations: as the type of a parameter, field, or local variable; sometimes as a return type (though it is better programming practice to be more specific).


1 Answers

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>> {         ...     } } 
like image 176
meriton Avatar answered Sep 24 '22 06:09

meriton