¿Se pueden evitar las advertencias no verificadas al anular un método con parámetros de tipo sin formato?
-
04-07-2019 - |
Pregunta
Estoy extendiendo una clase definida en una biblioteca que no puedo cambiar:
public class Parent
{
public void init(Map properties) { ... }
}
Si estoy definiendo una clase 'Child' que amplía Parent y estoy usando Java 6 con genéricos, ¿cuál es la mejor manera de anular el método init sin recibir advertencias no controladas?
public class Child extends Parent
{
// warning: Map is a raw type. References to generic type Map<K,V> should be parameterized
public void init(Map properties) { }
}
Si agrego parámetros genéricos, obtengo:
// error: The method init(Map<Object,Object>) of type Child has the same erasure as init(Map) of type Parent but does not override it
public void init(Map<Object,Object>) { ... }
// same error
public void init(Map<? extends Object,? extends Object>) { ... }
// same error
public void init(Map<?,?>) { ... }
Este error se produce independientemente de si uso un tipo específico, un comodín limitado o un comodín ilimitado. ¿Existe una forma correcta o idiomática de anular un método no genérico sin advertencias y sin usar @SuppressWarnings (& Quot; sin marcar & Quot;)?
Solución
Sí, debe declarar el método de anulación con la misma firma que en la clase principal, sin agregar ninguna información genérica.
Creo que su mejor opción es agregar la anotación @SuppressWarnings("unchecked")
al parámetro de tipo sin formato, no el método, para no silenciar otras advertencias genéricas que pueda tener en su propio código.
Otros consejos
Respuesta corta: no hay forma de hacerlo.
Respuesta insatisfactoria: deshabilite las advertencias (específicas) en su IDE / build.xml.
Si no puede cambiar la biblioteca, por desgracia, debe seguir métodos no genéricos.
El problema es que, a pesar de que después del borrado del tipo, ambos init () tienen la misma firma, de hecho pueden ser métodos diferentes, o el mismo (*). El compilador no puede determinar si anula o sobrecarga, por lo que está prohibido.
(*) Supongamos que el desarrollador de la biblioteca quiere decir init (Map & Lt; String, Integer & Gt;). Ahora está implementando init (Map & Lt; String, String & Gt;). Esto es una sobrecarga, y deberían existir dos métodos en la clase vtable de Child.
Pero, ¿qué pasa si el desarrollador de la biblioteca quiere decir init (Map < String, String >)? Entonces se anula, y su método debería reemplazar init original en la clase Child, y solo habría un método en la vtable de Child.
P.S. Odio cómo se implementaron los genéricos en Java :-(
Creo que la respuesta anterior significaba @SuppressWarnings (" rawtypes ") en su lugar.
Debe declarar el método con la misma firma que el padre y, por lo tanto, recibirá advertencias cuando compile. Puede suprimirlos con @SuppressWarnings (& Quot; sin marcar & Quot;)
La razón por la cual no hay forma de deshacerse de esto es que las advertencias están ahí para hacerle saber que es posible crear Colecciones con tipos no válidos en ellas. Las advertencias solo deberían desaparecer cuando se haya eliminado todo el código que podría permitirlo. Como está heredando de una clase no genérica, siempre será posible crear una Colección con contenido no válido.