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?
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.
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.
var can be used in a local variable declaration.
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.
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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With