Java 10 var and capture variable

xdevel2000 :

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 do not mention capture variables. This mapping replaces capture variables with their upper bounds and replaces type arguments mentioning capture variables with bounded wildcards (and then recurs). This preserves the traditionally limited scope of capture variables, which are only considered within a single statement.

Can anyone make me a concrete example in Java code of what it meaning?

Jorn Vernee :

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

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=36322&siteId=1