interfaces - what are generics in java
¿Diferencia entre una API obsoleta y una heredada? (7)
Estaba estudiando las API heredadas en el Collection Framework
HashTable
Java y aprendí que las clases como Vector
y HashTable
han sido reemplazadas por ArrayList
y HashMap
.
Sin embargo, aún NO están en desuso, y se consideran heredados cuando, en esencia, la depreciación se aplica a las funciones del software que se reemplazan y deben evitarse, por lo tanto, no estoy seguro de cuándo se considera que una API es heredada y cuándo está obsoleta.
Del glosario oficial de Sun:
deprecation : se refiere a una clase, interfaz, constructor, método o campo que ya no se recomienda, y puede dejar de existir en una versión futura.
De la guía de cómo y cuándo desaprobar:
Es posible que haya escuchado el término "humor que se autodesprecia" o humor que minimiza la importancia del orador. Una clase o método obsoleto es así. Ya no es importante. De hecho, es tan importante que ya no deberías usarlo, ya que ha sido reemplazado y puede dejar de existir en el futuro.
La anotación @Deprecated
fue un paso más allá y advierte de peligro:
Un elemento de programa anotado
@Deprecated
es uno que se desaconseja a los programadores, por lo general porque es peligroso o porque existe una mejor alternativa.
Referencias
- java.sun.com Glosario
- Guía de idiomas / Cómo y cuándo pretender deducir las API
- API desaprobada del tipo de anotación
Tenga en cuenta que el glosario oficial no define qué significa "legado". Con toda probabilidad, puede ser un término que Josh Bloch usó sin una definición exacta. La implicación, sin embargo, es siempre que una clase heredada nunca debe ser utilizada en un código nuevo, y existe un mejor reemplazo.
Tal vez un código anterior que utiliza una clase heredada pero no desaprobada no requiere ninguna acción, ya que, al menos por el momento, no están en peligro de dejar de existir en la versión futura.
Por el contrario, la obsolescencia advierte explícitamente que pueden dejar de existir, por lo que se deben tomar medidas para migrar al reemplazo.
Citas de Effective Java 2nd Edition
Para comparar cómo se usan estos términos en contexto, estas son citas del libro donde aparece la palabra "desaprobado" :
Elemento 7: Evite los finalizadores : los únicos métodos que afirman garantizar la finalización son
System.runFinalizersOnExit
y su gemela malvadaRuntime.runFinalizersOnExit
. Estos métodos son fatalmente defectuosos y han sido desaprobados.Elemento 66: sincronice el acceso a los datos mutables compartidos : las bibliotecas proporcionan el método
Thread.stop
, pero este método fue desaprobado hace mucho tiempo debido a que es intrínsecamente inseguro ; su uso puede provocar daños en los datos.Elemento 70: seguridad del subproceso de documento : el método
System.runFinalizersOnExit
es hostil a subprocesos y ha quedado obsoleto.Elemento 73: Evitar grupos de hilos : Permiten aplicar ciertas primitivas de
Thread
a un grupo de hilos a la vez. Varias de estas primitivas han quedado obsoletas, y el resto se usan con poca frecuencia. [...] los grupos de hilos están obsoletos.
Por el contrario, estas son las citas donde aparece la palabra "legado" :
Ítem 23: No use tipos sin procesar en el nuevo código : se proporcionan para la compatibilidad y la interoperabilidad con el código heredado que es anterior a la introducción de los genéricos.
Elemento 25: Preferir listas a matrices : el borrado es lo que permite que los tipos genéricos interactúen libremente con el código heredado que no usa genéricos.
Elemento 29: Considere contenedores heterogéneos tipo seguro : estos contenedores son útiles para rastrear quién agrega un elemento incorrectamente tipado a una colección en una aplicación que mezcla código genérico y heredado.
Ítem 54: Usar métodos nativos de forma juiciosa : Proporcionan acceso a bibliotecas de código heredado, lo que a su vez podría proporcionar acceso a datos heredados. [...] También es legítimo usar métodos nativos para acceder al código heredado. [...] Si debe usar métodos nativos para acceder a recursos de bajo nivel o bibliotecas heredadas, use el menor código nativo posible y pruébelo a fondo.
Elemento 69: Prefiera las utilidades de simultaneidad para esperar y notificar : Si bien siempre debe usar las utilidades de simultaneidad para
wait
ynotify
, es posible que deba mantener el código heredado que usawait
ynotify
.
Estas citas no se seleccionaron cuidadosamente: son TODAS las instancias en las que aparecen las palabras "desaprobado" y "heredado" en el libro. El mensaje de Bloch es claro aquí:
- Los métodos obsoletos, como
Thread.stop
, son peligrosos y nunca se deben usar. - Por otro lado, por ejemplo,
wait/notify
puede permanecer en el código heredado, pero no debe usarse en el nuevo código.
Mi propia opinión subjetiva
Mi interpretación es que desaprobar algo es admitir que es un error, y nunca fue bueno para empezar. Por otro lado, clasificar que algo es un legado es admitir que fue lo suficientemente bueno en el pasado, pero ha cumplido su propósito y ya no es lo suficientemente bueno para el presente y el futuro.
La anotación desaprobada proporciona una definición formal de una API obsoleta. No creo que exista una definición formal para las clases heredadas. En realidad, ambos significan que la clase no debe usarse en un código nuevo.
La depreciación a menudo denota que hay una intención de eliminar la funcionalidad en algún momento en el futuro, mientras que el legado simplemente implica que no debe usarse en un código nuevo si es posible (aunque puede ser necesario por razones de interoperabilidad).
La depreciación significa que es malo y no debe utilizarse: File.toURL()
es un excelente ejemplo, ya que no crea URL correctas a partir de archivos con espacios en la ruta. Simplemente no está haciendo lo que debería, pero dado que el código existente podría estar utilizando soluciones que se romperían si el error se soluciona
El legado solo significa que es viejo y que hay formas de hacer algo que generalmente, pero no necesariamente, son mejores. Vector
es un buen ejemplo: es una implementación de la List
, pero todavía tiene algunas fea basura de los días previos a la creación de la API de Colecciones (es decir, List
). También está sincronizado, lo que significa que tiene que pagar la tarifa de sincronización incluso cuando la usa en un escenario de subproceso único (excepto en algunas situaciones donde la VM es inteligente). ArrayList
es mejor si desea una implementación de lista respaldada por arreglos ya que no está sincronizada, y Collections.synchronizedList
es más flexible cuando desea una lista sincronizada, ya que es un contenedor que se puede usar con todas las implementaciones de listas (listas enlazadas, listas de Arrays.asList(T...)
, etc.) Sin embargo, si desea una implementación de lista sincronizada y respaldada por arreglos, Vector
está bien.
Mi interpretación es que el código heredado simplemente tiene contrapartes más nuevas que hacen el trabajo mejor. Sin embargo, continuará recibiendo correcciones de errores y otro soporte. El código obsoleto, por otro lado, no es compatible y no recibirá correcciones de errores dedicadas.
Tengo una sugerencia: el legado se refiere al código que se escribió en el pasado, obsoleto se refiere al consejo de no usarlo más. Aún puede usar la API en desuso, pero no puede escribir el código heredado, porque lo está escribiendo en este momento. Sólo en mi humilde opinión
Una interpretación común es que Deprecated significa que se eliminará en el futuro cercano, y Legacy significa que seguirá siendo compatible con versiones anteriores u otras razones.
Ambos significan que no deben ser utilizados por un nuevo código.
En el caso del JDK, incluso el código obsoleto se mantendrá, ya que la compatibilidad con versiones anteriores es muy importante para Java JDK.