I\'m reading the JEP 286 but I don\'t understand this part:
Capture variables, and types with nested capture variables, are projected to supertypes that
var
allows you to infer a non-denotable type:
var x = new Object() {
int i = 10;
};
System.out.println(x.i); // works; `x` has the non-denotable type of the annonymous class
So theoretically that would allow you to infer a wildcard type. But what this text is saying is that that is not possible, because the wildcard is replaced by it's upper bound, or by a new capture variable in the inferred type.
Take for instance this snippet of code:
List<String> l1 = new ArrayList<>();
l1.add("Hello");
List<?> l2 = l1;
var x = l2.get(0);
l2.add(x); // error
Here, instead of the type of x
being inferred to the exact type of the wild card, which would make the last line compile. Instead it is inferred to it's upper bound, which is Object
, and you get the (Eclipse) error message:
The method add(capture#2-of ?) in the type List<capture#2-of ?> is not applicable for the arguments (Object)
Where you can see that the type of x
is Object
.
That is the part
This mapping replaces capture variables with their upper bounds
The second part
... and replaces type arguments mentioning capture variables with bounded wildcards
Is talking about a situation like this:
List<String> l1 = new ArrayList<>();
l1.add("Hello");
List<?> l2 = l1;
var l3 = l2; // type of 'l3' is List<?>, but not the same '?' as 'l2'
l3.add(l2.get(0)); // error
This doesn't compile either, because the type of l3
is not the exact same type as the type of l2
, which means that the type returned from l2.get(0)
is not the same type as required by l3.add(...)
. The error here is:
The method add(capture#2-of ?) in the type List<capture#2-of ?> is not applicable for the arguments (capture#3-of ?)
And you see that both of the capture variables are distinct, meaning that the type of l3
is not exactly the type of l2
, but the capture variable of the type of l2
in the inferred type is replaced by a wildcard with the same bound, for which a new capture variable is then created.
So for a type List<capture#1-of ?>
the inferred type is List<?>
, and then the compiler creates a new capture variable for that wildcard, yielding List<capture#2-of ?>
(though the numbering might work differently in practice, the key is that the 2 capture variables are different).