Java 10 var and capture variable

  • A+
Category:Languages

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?

 


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<?> l1 = new ArrayList<>();  l1.add("Hello"); // error 1 var l2 = l1; // type is not the same as that of `l1`, but replaces the capture variable l2.add("Hello"); // error 2 

Again, I'm using errors here to make the inferred types visible. The errors are:

The method add(capture#1-of ?) in the type List<capture#1-of ?> is not applicable for the arguments (String) 

And:

The method add(capture#3-of ?) in the type List<capture#3-of ?> is not applicable for the arguments (String) 

And you see that both of the capture variables are distinct, meaning that the type of l2 is not exactly the type of l1, but the capture variable of the type of l1 in the inferred type is replaced by a wildcard with the same bound, for which a new capture variable is then created.

So for List<capture#1-of ?> the inferred type is List<?>, and then the compiler creates a new capture variable for that wildcard, yielding List<capture#3-of ?>.

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: