Après avoir lu et parlé de Java 10s nouveau nom de type réservé var
( JEP 286: Inférence de type variable locale ), une question s'est posée au cours de la discussion.
Lorsque vous l'utilisez avec des littéraux comme:
var number = 42;
est number
maintenant un int
ou un Integer
? Si vous l'utilisez simplement avec des opérateurs de comparaison ou en tant que paramètre, cela n'a généralement pas d'importance grâce à l'autoboxing et au -unboxing. Mais en raison des fonctions membres de Integer
s, cela pourrait avoir de l'importance.
Alors, quel type est créé par var
, une primitive int
ou une classe Integer
?
var
demande au compilateur de déduire le type de la variable du type de l'initialiseur et le type naturel de 42
est int
. Donc number
sera un int
. C'est ce que le l'exemple JLS dit :
var a = 1; // a has type 'int'
Et je serais surpris si cela fonctionnait d'une autre manière, quand j'écris quelque chose comme ça, je m'attends définitivement à une primitive.
Si vous avez besoin d'un var
comme primitive encadrée, vous pouvez faire:
var x = (Integer) 10; // x is now an Integer
Selon le changements de spécifications proposés dans 14.4.1 Déclarateurs et types de variables locales :
Si LocalVariableType est
var
, alors laissez [~ # ~] t [~ # ~] être le type de l'expression d'initialisation lorsqu'elle est traitée comme si elle n'apparaissait pas dans un contexte d'affectation, et était donc une expression autonome ( 15.2 ). Le type de la variable locale est la projection vers le haut de [~ # ~] t [~ # ~] par rapport à toutes les variables de type synthétique mentionnées par [~ # ~] t [~ # ~] (4.10.5).
En d'autres termes, le type déduit pour la variable locale est le type que l'expression d'initialisation aurait si elle était utilisée comme expression autonome. 42
comme expression autonome a le type int
, ergo, la variable number
est de type int
.
La projection vers le haut est un terme défini dans les changements de spécifications qui ne s'applique pas à des cas simples comme celui-ci.
Testons-le. Avec jshell:
jshell> Integer boxed1 = 42000;
boxed1 ==> 42000
jshell> Integer boxed2 = 42000;
boxed2 ==> 42000
jshell> System.out.println(boxed1 == boxed2);
false
jshell> var infered1 = 42000;
infered1 ==> 42000
jshell> var infered2 = 42000;
infered2 ==> 42000
jshell> System.out.println(infered1 == infered2);
true
Dans la première comparaison, les deux variables ne sont pas identiques; ce sont des instances différentes. La deuxième comparaison est cependant vraie, donc un int doit avoir été déduit ici.
Remarque: Pour l'essayer à la maison, utilisez des valeurs extérieures à <-128, 128). Les instances entières de cette plage sont mises en cache.
Le compilateur traite var number = 42;
Similaire à int number = 42;
public void method(Integer i) {
System.out.print("Integer method");
}
public void method(int i) {
System.out.print("int method");
}
var n = 42; // n has type 'int'
method(n); // => "int method"
Et la boxe automatique lorsque:
public void method(Integer i) {
System.out.print("Integer method");
}
var n = 42; // a has type 'int'
method(n); // => "Integer method"