Aquí hay una buena trampa que acabo de encontrar. Considere una lista de enteros:
List<Integer> list = new ArrayList<Integer>();
list.add(5);
list.add(6);
list.add(7);
list.add(1);
¿Alguna conjetura sobre lo que sucede cuando ejecutas list.remove(1)
? ¿Qué hay de list.remove(new Integer(1))
? Esto puede causar algunos errores desagradables.
¿Cuál es la forma correcta de diferenciar entre remove(int index)
, que elimina un elemento de un índice dado y remove(Object o)
, que elimina un elemento por referencia, cuando se trata de listas de enteros?
El punto principal a considerar aquí es el mencionado por @Nikita : la coincidencia exacta de parámetros tiene prioridad sobre el auto-boxeo.
java
collections
overloading
Yuval Adam
fuente
fuente
Respuestas:
Java siempre llama al método que mejor se adapte a su argumento. El boxeo automático y la conversión implícita solo se realizan si no hay un método al que se pueda llamar sin conversión / boxing automático.
La interfaz de Lista especifica dos métodos de eliminación (tenga en cuenta la denominación de los argumentos):
remove(Object o)
remove(int index)
Eso significa que
list.remove(1)
elimina el objeto en la posición 1 yremove(new Integer(1))
elimina la primera aparición del elemento especificado de esta lista.fuente
Integer.valueOf(1)
es mejor práctica quenew Integer(1)
. El método estático puede hacer almacenamiento en caché y demás, por lo que obtendrá un mejor rendimiento.new Integer(1)
, pero estoy de acuerdoInteger.valueOf(1)
o(Integer) 1
equivalente.Puedes usar casting
y
No importa si n es int o Integer, el método siempre llamará al que espera.
Usar
(Integer) n
oInteger.valueOf(n)
es más eficiente quenew Integer(n)
los dos primeros puede usar el caché Integer, mientras que el segundo siempre creará un objeto.fuente
No sé sobre la forma 'adecuada', pero la forma en que sugirió funciona bien:
elimina el elemento en la posición dada y
elimina el objeto dado de la lista.
Esto se debe a que VM al principio intenta encontrar el método declarado con exactamente el mismo tipo de parámetro y solo luego intenta el autoboxing.
fuente
list.remove(4)
es una coincidencia exacta delist.remove(int index)
, por lo que se llamará. Si desea llamarlist.remove(Object)
hacer lo siguiente:list.remove((Integer)4)
.fuente
(Integer)
elenco simple como el que escribiste anteriormente parece ser el enfoque más fácil para mí.No hay necesidad de adivinar. Se llamará al primer caso
List.remove(int)
y1
se eliminará el elemento en la posición . El segundo caso resultará enList.remove(Integer)
ser llamado, y el elemento cuyo valor es igual aInteger(1)
será eliminado. En ambos casos, el compilador de Java selecciona la sobrecarga coincidente más cercana.Sí, existe la posibilidad de confusión (y errores) aquí, pero es un caso de uso bastante poco común.
Cuando los dos
List.remove
métodos se definieron en Java 1.2, las sobrecargas no fueron ambiguas. El problema solo surgió con la introducción de genéricos y autoboxing en Java 1.5. En retrospectiva, hubiera sido mejor si uno de los métodos de eliminación hubiera recibido un nombre diferente. Pero ya es demasiado tarde.fuente
Tenga en cuenta que incluso si la máquina virtual no hizo lo correcto, lo que hace, aún podría garantizar un comportamiento adecuado utilizando el hecho de que
remove(java.lang.Object)
opera en objetos arbitrarios:fuente
equals
método, específicamente (del Javadoc) "Es simétrico: para cualquier valor de referencia no nulo x e y, x.equals (y) debe devolver verdadero si y solo si y.equals ( x) devuelve verdadero ". Como tal, no se garantiza que funcione en todas las implementaciones deList
, porque cualquier implementación de Lista puede intercambiar la x y la yx.equals(y)
a voluntad, ya que el Javadoc deObject.equals
dice que esto debería ser válido.Simplemente me gustó seguir como lo sugirió #decitrig en el primer comentario de respuesta aceptada.
Esto me ayudo. Gracias de nuevo #decitrig por tu comentario. Puede ayudar a alguien.
fuente
Pues aquí está el truco.
Tomemos dos ejemplos aquí:
Ahora echemos un vistazo a la salida:
Ahora analicemos el resultado:
Cuando se elimina 3 de la colección, llama al
remove()
método de la colección que tomaObject o
como parámetro. Por lo tanto, elimina el objeto3
. Pero en el objeto arrayList está anulado por el índice 3 y, por lo tanto, se elimina el cuarto elemento.Por la misma lógica de eliminación de objetos, se elimina nulo en ambos casos en la segunda salida.
Entonces, para eliminar el número
3
que es un objeto, explícitamente tendremos que pasar 3 como anobject
.Y eso se puede hacer fundiendo o ajustando usando la clase wrapper
Integer
.P.ej:
fuente