Je lis le JEP 286 mais je ne comprends pas cette partie:
Les variables de capture, et les types avec des variables de capture nestedes, sont projetés dans des supertypes qui ne mentionnent pas les variables de capture. Ce mappage remplace les variables de capture par leurs limites supérieures, ainsi que les arguments de type mentionnant les variables de capture avec des caractères génériques liés (puis se reproduit). Cela préserve la scope traditionnellement limitée des variables de capture, qui ne sont sockets en compte que dans une seule instruction.
Quelqu’un peut-il me donner un exemple concret en code Java de ce qu’il signifie?
var
vous permet d’inférer un type non dénotable:
var x = new Object() { int i = 10; }; System.out.println(xi); // works; `x` has the non-denotable type of the annonymous class
Donc, théoriquement, cela vous permettrait de déduire un type générique. Mais ce que dit ce texte, c’est que ce n’est pas possible, car le caractère générique est remplacé par sa limite supérieure ou par une nouvelle variable de capture dans le type inféré.
Prenons par exemple cet extrait de code:
List l1 = new ArrayList<>(); l1.add("Hello"); List> l2 = l1; var x = l2.get(0); l2.add(x); // error
Ici, au lieu que le type de x
soit inféré au type exact du caractère générique, la dernière ligne serait compilée. Au lieu de cela, il est déduit de sa limite supérieure, qui est Object
, et vous obtenez le message d’erreur (Eclipse):
The method add(capture#2-of ?) in the type List is not applicable for the arguments (Object)
Où vous pouvez voir que le type de x
est Object
.
C’est la partie
Ce mappage remplace les variables de capture par leurs limites supérieures
La seconde partie
… et remplace les arguments de type mentionnant les variables de capture par des caractères génériques liés
Parle d’une situation comme celle-ci:
List 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
Cela ne comstack pas non plus, car le type de l3
n’est pas exactement le même type que le type de l2
, ce qui signifie que le type renvoyé par l2.get(0)
n’est pas du même type que celui requirejs par l3.add(...)
. L’erreur ici est:
The method add(capture#2-of ?) in the type List is not applicable for the arguments (capture#3-of ?)
Et vous voyez que les deux variables de capture sont distinctes, ce qui signifie que le type de l3
n’est pas exactement le type de l2
, mais que la variable de capture du type de l2
dans le type inféré est remplacée par un caractère générique avec la même limite, car une nouvelle variable de capture est ensuite créée.
Donc, pour un type List
Le type inféré est List>
, Puis le compilateur crée une nouvelle variable de capture pour ce caractère générique, générant List
(Bien que la numérotation puisse en pratique, la clé est que les 2 variables de capture sont différentes).