sirve settitle que para name how java generics name-clash

settitle - Choque de nombres de Java, tiene el mismo borrado, ninguno oculta al otro



set name to jframe (3)

Estoy recibiendo este error de choque de nombre y no sé cómo debo resolver el problema. Tengo dos clases y estoy usando el método sobrecargado "createSensors". Para simplificar aquí está el código que genera el problema:

public abstract class ClassA { public static List<Sensor> createSensors(Collection<? extends ClassA> list) { List<Sensor> sensors = new ArrayList<Sensor>(); for (ClassA s : list) { sensors.add(s.getSensor()); } return sensors; } } public abstract class ClassB extends ClassA { public static List<Sensor> createSensors(Collection<? extends ClassB> list) { List<Sensor> sensors = new ArrayList<Sensor>(); for (ClassB s : list) { sensors.add(s.getSensor()); } return sensors; } }


Respuesta general:

Aparte del problema de la misma implementación aquí, el núcleo del problema es que, de alguna manera bárbaro, el "método A y el método B tienen el mismo borrado".

Lo que lo hace una pregunta complicada es que generalmente no (al menos no esta misma mañana) sabemos mucho acerca de "Type Erasure".

Para hacerlo corto:

Los tipos paramétricos realizan la verificación de tipos en el momento de la compilación (para asegurar la corrección del tipo) pero olvidan sus parámetros de tipo en el tiempo de ejecución (para evitar la generación de métodos subyacentes).

Esto suena a la vez simple y desconcertante. La mejor manera de entenderlo es referirse a la siguiente literatura:

  1. ¿Qué es un tipo confiable?
  2. ¿Cómo y bajo qué condiciones se realiza el borrado?
  3. ¿Tiene alguna idea / ejemplo sobre lo que podría implicar en mi vida de codificación?
  4. Bueno, eso es extraño y realmente no me gusta, pero tengo curiosidad de por qué hicieron eso ...

Espero que te ayude tanto como a mí.

Respuesta específica:

En tu caso

public abstract class ClassA { public static List<Sensor> createSensors(Collection<? extends ClassA> list) { //do stuff } } public abstract class ClassB extends ClassA { public static List<Sensor> createSensors(Collection<? extends ClassB> list) { //do other stuff } }

será "transformado" por javac a

public abstract class ClassA { public static List createSensors(Collection list) { //do stuff } } public abstract class ClassB extends ClassA { public static List createSensors(Collection list) { //do other stuff } }

donde uno claramente no puede anular al otro (no es el mismo tipo de parámetro) pero termina siendo exactamente el mismo en tiempo de ejecución (no hay forma de que su programa elija cuál usar).

Basta ya de este problema, ¿cómo solucionarlo? Puede proceder con uno de los siguientes métodos:

  • Use nombres diferentes: createASensors y createBSensors Este enfoque es el más obvio pero parece un poco menos elegante.

  • Agregue un parámetro: createSensors(Collection<? extends ClassA> list, ClassA typeDefiner) este enfoque puede parecer bárbaro pero es un poco menos elegante pero es el que se usa en java.util.List para el método <T> T[] toArray(T[] a) .


Compruebe la configuración del proyecto y la versión del compilador del proyecto. Haga clic derecho en el proyecto -> Propiedades -> Java Compilador. Asegúrese de que la configuración de cumplimiento esté actualizada. Tuve este problema cuando la configuración de cumplimiento se estableció en 1.4 en lugar de 1.6


La solución general es utilizar nombres diferentes. Estos métodos podrían estar en clases sin una relación de herencia, ya que estos no son métodos de instancia.

Como se señaló, la implementación del método en la pregunta es la misma (salvo error tipográfico).

(Este problema con la sobrecarga a menudo se confunde con el borrado de los tipos de tiempo de ejecución. La sobrecarga es un problema de tiempo de enlace en lugar de dinámico, por lo que podría solucionarse fácilmente en el idioma. Simplemente no es un cambio particularmente útil y no es una buena idea para alentar sobrecarga)