java - characteristics - standard collection interfaces
¿Por qué TreeSet de Java<E> remove(Object) no toma una E (4)
Bueno, cada E es también un Objeto, y tal vez tengas la E no como E en este momento (por ejemplo, de una fuente de Evento), lo que te conviene. De lo contrario, solo tiene que lanzarlo a E solo para eliminarlo.
Desde el punto de vista de la igualdad, esto no importa: la dirección de referencia del objeto dado se prueba si es igual al contenido de un conjunto, por lo que no importa de qué clase se trate.
De la documentación de Java 6 TreeSet<E>
:
boolean remove(Object o):
Removes the specified element from this set if it is present.
¿Por qué esto acepta un Objeto en lugar del tipo genérico E? Los únicos objetos que se pueden agregar son del tipo E, por lo que se deduce que el único tipo extraíble debe ser de tipo E.
Tomando la respuesta del primer comentario publicado:
Mito:
Un mito popular es que es estúpido y malvado, pero fue necesario debido a la compatibilidad con versiones anteriores. Pero el argumento de compatibilidad es irrelevante; la API es correcta independientemente de si considera compatibilidad o no.
Razón real:
Uniformemente, los métodos de Java Collections Framework (y la Biblioteca de colecciones de Google también) nunca restringen los tipos de sus parámetros, excepto cuando es necesario para evitar que la colección se rompa.
Lea más aquí: ¿Por qué Set.contains () toma un objeto, no una E?
Esto es realmente un problema. Si alguien llama a remove(o)
y el tipo de o no es E
, generalmente es un error de programación que intenta eliminar lo incorrecto. La verificación de tipo no pudo protegernos del error.
Aunque un buen IDE (IntelliJ) puede detectar tales problemas y advertirnos, los diseñadores de API deberían haber proporcionado una firma más precisa para utilizar la verificación del tipo de compilador. (IDE hace trampa aquí: conoce el significado de Set.remove()
porque es una API estándar. IDE no brindará la misma ayuda para las API personalizadas)
Para API de consulta como contains()
, está bien aceptar un argumento que no sea E
y devolver un falso trivial. Entonces podemos tener ambos
boolean contains(Object o);
boolean contains2(E o);
Para la API de mutación como remove()
, es discutible si debería aceptar un argumento que no sea E
Sin embargo, el debate va a ser discutible, dada la realidad del borrado: en realidad no hay otra opción que aceptar el argumento no E y guardar silencio al respecto. Todavía podemos tener dos métodos
boolean remove(Object o);
boolean remove2(E o);
En la mayoría de los casos, los programadores pueden llamar a contains2/remove2
para obtener seguridad adicional.
remove()
, como get()
es necesario para trabajar cuando se le da un elemento igual (en términos de .equals()
). En Java, es posible (y en algunos casos, requerido) que los objetos de diferentes clases sean iguales. Por lo tanto, no debe restringir el tipo.