java type-inference local-variables java-10

java - ¿Usar var con un resultado literal en una primitiva o primitiva clase contenedora?



type-inference local-variables (4)

Después de leer y hablar sobre el nuevo nombre de tipo var reservado de Java 10 ( JEP 286: Inferencia de tipo de variable local ), surgió una pregunta en la discusión.

Al usarlo con literales como:

var number = 42;

¿El number ahora es un int o un Integer ? Si solo lo usa con operadores de comparación o como parámetro, generalmente no importa gracias a la función de autoboxing y -unboxing. Pero debido a las funciones de miembros de Integer , podría importar .

Entonces, ¿qué tipo es creado por var , una primitiva int o clase Integer ?


De acuerdo con los cambios de especificación propuestos en 14.4.1 Declaradores y tipos de variables locales :

Si LocalVariableType es var , entonces deje que T sea ​​el tipo de expresión del inicializador cuando se trata como si no apareciera en un contexto de asignación, y por lo tanto fuera una expresión independiente ( 15.2 ). El tipo de la variable local es la proyección hacia arriba de T con respecto a todas las variables de tipo sintético mencionadas por T (4.10.5).

En otras palabras, el tipo inferido para la variable local es el tipo que tendría la expresión del inicializador si se usara como una expresión independiente. 42 como una expresión independiente tiene tipo int , ergo, el number variable es de tipo int .

La proyección hacia arriba es un término definido en los cambios de especificaciones que no se aplica a casos simples como este.


El compilador trata var number = 42; de manera similar al 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"

Y auto-boxing cuando:

public void method(Integer i) { System.out.print("Integer method"); } var n = 42; // a has type ''int'' method(n); // => "Integer method"


Vamos a probarlo. Con 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

En la primera comparación, las dos variables no son lo mismo; son instancias diferentes. La segunda comparación es, sin embargo, cierta, por lo tanto, se debe haber ingresado aquí.

Nota: Para probarlo en casa, use valores fuera de <-128, 128). Las instancias de enteros en ese rango están en caché.


var le pide al compilador que infiera el tipo de la variable del tipo del inicializador, y el tipo natural de 42 es int . Entonces el number será un int . Eso es lo que dice el ejemplo de JLS :

var a = 1; // a has type ''int''

Y me sorprendería si funcionara de otra manera, cuando escribo algo como esto, definitivamente espero un primitivo.

Si necesita una var como primitiva en caja, podría hacer:

var x = (Integer) 10; // x is now an Integer