sencillo revisar programacion probar paiza net linea con compiladores compilador codigos codigo aplicaciones java generics collections interface compiler-errors

revisar - programacion en java en linea



Error del compilador en la interfaz genérica de Java con un método List<> (3)

El error parece estar aquí:

Task task = new MyTask();

Has olvidado agregar genéricos después de Task . Debería funcionar si lo cambia a uno de estos:

Task<Boolean> task = new MyTask(); Task<?> task = new MyTask();

No entiendo el error del compilador resultante del siguiente código. Defino una interfaz genérica, vea Tarea, con dos métodos: U doSomething(String value) y List<Integer> getIDs() . El método doSomething () realmente usa el tipo genérico como el tipo de su valor de retorno, pero no parece estar causando problemas. El método getIDs() devuelve una lista, que no está relacionada con el tipo de tarea, pero está causando problemas cuando se usa para ... cada instrucción para iterar sobre el valor de retorno. Se produce el siguiente error de compilación.

error: incompatible types for (Integer value : task.getIDs()){ required: Integer found: Object

Parece que el borrado de tipos en la interfaz hace que el compilador olvide el tipo declarado en el segundo método, que no está relacionado con el tipo genérico. O, en otras palabras, ¿por qué el tipo genérico de la interfaz afecta la forma en que el compilador entiende el valor de retorno en el método getIDs() y específicamente en el contexto de un para ... cada declaración?

Aparentemente, si obtengo una referencia de la lista fuera del ... para cada uno, no hay problema, pero no directamente.

public class InterfaceTest { public static void main(String[] args) { Task task = new MyTask(); // no complaints about the type here List<Integer> values = task.getIDs(); // getting a compiler error for this line for (Integer value : task.getIDs()){ } } } interface Task<U>{ U doSomething(String value); List<Integer> getIDs(); }

La implementación de la interfaz no es necesaria para demostrar el punto, pero no quería dejar la referencia Task task = null; y tener respuestas diciéndome que ese es el problema.

class MyTask implements Task<Boolean>{ @Override public Boolean doSomething(String value) { System.out.println(value); return false; } @Override public List<Integer> getIDs() { return Arrays.asList( 1, 2, 3, 4 ); } }


Lo que está sucediendo es cuando el uso usa una clase (o interfaz) con un parámetro genérico <T> pero se refiere e instancia del sin <T> (es decir, ese tipo sin raw ) el compilador borra toda la información de tipo genérico de la clase. Es probable que esto se deba a la compatibilidad con el código fuente anterior a la 1.5, en el que no podría utilizar la información de tipo genérico.

Considere la situación en la que está escribiendo código y compilando en un compilador Java 1.4. Desea utilizar una biblioteca que hace uso de genéricos. Cuando se refiere a un tipo de esa biblioteca que tiene parámetros genéricos como tipo sin formato, el compilador impone el uso de parámetros genéricos.

EDITAR:

El JLS-4.8-210 alude a esto cuando menciona (crédito: zhong-j-yu ):

El tipo de un constructor (§8.8), el método de instancia (§8.4, §9.4) o el campo no estático (§8.3) M de un tipo C sin procesar que no se hereda de sus superclases o superinterfaces es el tipo bruto que le corresponde a la eliminación de su tipo en la declaración genérica correspondiente a C.

Esto todavía se siente como un gotcha, pero es probable que por alguna razón.


Si interpreto correctamente la Especificación del lenguaje Java (§4.6. Tipo de borrado), esto es un "gotcha" del lenguaje:

La borradura de tipo también asigna la firma (§8.4.2) de un constructor o método a una firma que no tiene tipos parametrizados o variables de tipo. El borrado de una firma de constructor o método s es una firma que consta del mismo nombre que sy las eliminaciones de todos los tipos de parámetros formales dados en s.

Creo que esto indica que si declaras un tipo ( Task ) que se declara con un parámetro genérico ( Task<U> ) sin dicho parámetro genérico, todas sus funciones también pierden sus tipos genéricos, estén o no relacionados. Por lo tanto, su task.getIDs() es interpretado por el compilador como devolver una List simple, no una List<Integer> . El iterador para eso, por supuesto, produce Objects , no Integers , causando el error del compilador que ves.

La razón de esto es la compatibilidad con el código producido antes de Java 1.5, cuando se introdujeron los genéricos.