Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java 10 var and capture variable

Tags:

java

java-10

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?

like image 664
xdevel2000 Avatar asked Aug 01 '18 10:08

xdevel2000


People also ask

Does Java 11 have var?

Core Java bootcamp program with Hands on practiceJava 11 allows to use var in a lambda expression and it can be used to apply modifiers to local variables.

Is it OK to use VAR in Java?

In Java, var can be used only where type inference is desired; it cannot be used where a type is declared explicitly. If val were added, it too could be used only where type inference is used. The use of var or val in Java could not be used to control immutability if the type were declared explicitly.

Can we declare a variable as VAR in Java?

var can be used in a local variable declaration.

Does Java have a VAR equivalent?

You can take a look to Kotlin by JetBrains, but it's val. not var. Kotlin has val and var. val is equivelent to declaring a variable final in java, var allows reassignment.


1 Answers

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

like image 81
Jorn Vernee Avatar answered Oct 20 '22 17:10

Jorn Vernee