Pregunta

Autoboxing es bastante miedo. Aunque comprendo plenamente la diferencia entre == y .equals ya no puedo mas ayuda tener el error de seguimiento a la mierda de mí:

    final List<Integer> foo = Arrays.asList(1, 1000);
    final List<Integer> bar = Arrays.asList(1, 1000);
    System.out.println(foo.get(0) == bar.get(0));
    System.out.println(foo.get(1) == bar.get(1));

que imprime

true
false

¿Por qué hacerlo de esta manera? Es algo que ver con los números enteros en caché, pero si ese es el caso ¿por qué no simplemente almacenar en caché todos los enteros utilizados por el programa? O ¿por qué no la JVM siempre automática unbox a primitivo?

La impresión falsa falsa o verdadera manera habría sido cierto mejor.

Editar

No estoy de acuerdo acerca de la rotura de código antiguo. Al tener retorno foo.get(0) == bar.get(0) cierto que ya se rompió el código.

¿No puede esto ser resuelto a nivel del compilador mediante la sustitución de enteros con int en el código de bytes (siempre que no se asigna null)

¿Fue útil?

Solución

  • ¿Por qué lo hacen de esta manera?

Todo entero entre -128 y 127 se almacena en caché por java. Ellos hicieron esto, supuestamente, para el beneficio de rendimiento. Aunque quisieran dar marcha atrás en esta decisión ahora, es poco probable que lo harían. Si alguien código incorporado en función de esto, su código se rompería cuando fue sacada. Para la afición de codificación, esto quizás no importa, pero por código de la empresa, la gente se molesta y demandas suceda.

  • ¿Por qué no acaba de caché de todos los enteros utilizados por el programa?

Todos los enteros no puede ser almacenado en caché, debido a las implicaciones de memoria sería enorme.

  • ¿Por qué no la JVM siempre automática unbox a primitivo?

Debido a que la JVM no puede saber lo que quería. Además, este cambio podría fácilmente romper el código heredado no construido para manejar este caso.

Si la JVM de forma automática sin caja de primitivas en las llamadas a ==, este problema se convierta en realidad más confuso. Ahora tiene que recordar que == compara siempre referencias a objetos, a menos que los objetos pueden ser sin embalaje. Esto causaría aún más raro confundir casos como el que se ha señalado anteriormente.

En lugar de preocuparse demasiado sobre esto, sólo recuerda esta regla en su lugar:

Nunca los objetos comparar con == menos que vaya a ser la comparación de ellos por sus referencias. Si lo hace, no puedo pensar en un escenario en el que se había encontrado con un problema.

Otros consejos

¿Se imagina lo mal desempeño sería si cada Integer lleva a gastos generales para el internamiento? Tampoco funciona para new Integer.

El lenguaje Java (JVM no es un problema) no siempre se puede auto unbox porque un código diseñado para pre-1.5 de Java aún debe trabajar.

Integers en el rango de bytes son el mismo objeto, ya que se almacenan en caché. Integers fuera del rango de bytes no lo son. Si todos los números enteros debían ser almacenado en caché, la memoria requiere imaginar.

Y a partir de aquí

  

El resultado de todo esto es que la magia puede pasar por alto en gran medida la distinción entre int y Integer, con algunas advertencias. Una expresión entera puede tener un valor nulo. Si el programa intenta nula autounbox, lanzará una NullPointerException. Las comparaciones de identidad de referencia realiza operador == en expresiones enteras y las comparaciones de igualdad de valor sobre las expresiones int. Por último, hay costes de funcionamiento asociados con el boxeo y unboxing, incluso si se hace de forma automática

Si se salta autoboxing por completo, sigue recibiendo este comportamiento.

final List<Integer> foo =
  Arrays.asList(Integer.valueOf( 1 ), Integer.valueOf( 1000 ));
final List<Integer> bar =
  Arrays.asList(Integer.valueOf( 1 ), Integer.valueOf( 1000 ));

System.out.println(foo.get(0) == bar.get(0)); // true
System.out.println(foo.get(1) == bar.get(1)); // false

Sé más explícito si quieres un comportamiento específico:

final List<Integer> foo =
  Arrays.asList( new Integer( 1 ), new Integer( 1000 ));
final List<Integer> bar =
  Arrays.asList( new Integer( 1 ), new Integer( 1000 ));

System.out.println(foo.get(0) == bar.get(0)); // false
System.out.println(foo.get(1) == bar.get(1)); // false

Esta es una razón, ¿por qué Eclipse ha autoboxing como una advertencia por defecto.

Una gran cantidad de personas que tienen problemas con este tema, incluso las personas que escriben libros sobre Java.

En Pro Programación Java , meras pulgadas por debajo eran el autor habla de problemas con el uso de automóviles enteros en caja como una llave en una IdentityHashMap, que utiliza claves enteras de auto-encajonado en un WeakHashMap. Los valores de ejemplo que utiliza son mayores que 128, por lo que su llamada tiene éxito la recolección de basura. Si alguien fuera a usar su ejemplo y utilizar valores inferiores a 128, sin embargo, su ejemplo podría fallar (debido a la clave es perma-caché).

Cuando se escribe

foo.get(0)

el compilador no importa cómo se creó la lista. Que sólo se basa en el tipo de tiempo de compilación de la lista de foo. Por lo tanto, si eso es un List , este será tratado que, como List , ya que se supone que debe hacer, y una List 's get () siempre devuelve un entero. Si desea utilizar el == entonces usted tiene que escribir

System.out.println(foo.get(0).intValue() == bar.get(0).intValue());

no

System.out.println(foo.get(0) == bar.get(0));

debido a que tiene un significado totalmente diferente.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top