2011-01-28 19 views
23

Existen varias otras preguntas de SO que hablan sobre la compilación de genéricos OK con el compilador de Eclipse, pero no javac (es decir, Java: Generics handled differenlty in Eclipse and javac y Generics compiles and runs in Eclipse, but doesn't compile in javac); sin embargo, esto parece ser ligeramente diferente.error de javac: tipos inconvertibles con genéricos?

tengo una clase enum:

public class LogEvent { 
    public enum Type { 
     // ... values here ... 
    } 
    ... 
} 

y tengo otra clase con un método que toma en objetos arbitrarios de tipos descendido de Enum:

@Override public <E extends Enum<E>> void postEvent(
    Context context, E code, Object additionalData) 
{ 
    if (code instanceof LogEvent.Type) 
    { 
     LogEvent.Type scode = (LogEvent.Type)code; 
    ... 

Esto funciona bien en Eclipse, pero cuando hago una construcción limpia con ant, obtengo un par de errores, uno en la línea instanceof, el otro en la línea de fundición:

443: inconvertible types 
    [javac] found : E 
    [javac] required: mypackage.LogEvent.Type 
    [javac]   if (code instanceof LogEvent.Type) 
    [javac]   ^

445: inconvertible types 
    [javac] found : E 
    [javac] required: com.dekaresearch.tools.espdf.LogEvent.Type 
    [javac]    LogEvent.Type scode = (LogEvent.Type)code; 
    [javac]            ^

¿Por qué sucede esto, y cómo puedo evitar este problema para que se compile correctamente?

Respuesta

32

No sé por qué está sucediendo, pero una solución es fácil:

@Override public <E extends Enum<E>> void postEvent(
    Context context, E code, Object additionalData) 
{ 
    Object tmp = code; 
    if (tmp instanceof LogEvent.Type) 
    { 
     LogEvent.Type scode = (LogEvent.Type)tmp; 
    ... 

Es feo, pero funciona ...

+0

gracias. ¿Por qué es eso feo? Es simple y tiene un bajo costo de tiempo de ejecución. –

+3

@Jason S: es feo porque no puedo ver por qué es obligatorio. –

+0

Este es un error conocido, IIRC. En realidad, hay docenas de errores relacionados, ninguno de ellos reparado aún. – maaartinus

0

Para utilizar instanceof ambos operadores han de heredar/implementar la misma clase/interfaz.
E simplemente no se puede convertir en LogEvent.Type

No sé cómo se ve su método completo, pero esto debería resolver su problema mediante el uso de interfaces y no genéricos.

public interface EventType { } 
public class LogEvent { 
    public enum Type implements EventType {} 
} 

public void postEvent(Context context, EventType code, Object additionalData) { 
    if(code instanceof LogEvent.Type) { 
    } 
} 
+0

Pero quiero que Enum sea el tipo base, no EventType. Necesito que mi método acepte valores arbitrarios de Enum. –

+0

¿Pero por qué E no se puede convertir a LogEvent.Type? E es una subclase de Enum, y LogEvent.Type también es una subclase de Enum. Entiendo que la parte del problema es que no es solo Enum, sino Enum , simplemente no puedo entender lo que eso significa exactamente. –

+0

Las otras preguntas de SO sobre este tema parecen indicar que 'javac' tiene un error conocido con límites genéricos recursivos, por lo que puede confundirse. Con respecto a '>', si no lo ha visto antes: http://www.angelikalanger.com/GenericsFAQ/FAQSections/TypeParameters.html#FAQ106 –

8

Tal vez sea porque se ha declarado E como algo que se extiende Enum <E>. No puedo decir que lo entiendo completamente, pero parece que limita el conjunto de tipos a algún subconjunto que no puede incluir LogEvent.Type por algún motivo. O tal vez solo sea un error en el compilador. Sería feliz si alguien podría explicar con más claridad, pero esto es lo que puede hacer:

public <E extends Enum<?>> void postEvent(E code) 
{ 
    if (code instanceof LogEvent.Type) 
    { 
     LogEvent.Type scode = (LogEvent.Type)code; 
     ... 
    } 
    ... 

Esto funciona y es más elegante que simplemente echando a un objeto.

+1

funciona porque "E se extiende Enum "se refiere a alguna subclase específica de Enum (que puede no ser compatible con LogEvent.Type). mientras que "E extiende Enum " hace referencia a cualquier clase que extienda Enum, de la cual LogEvent.Type es una posibilidad válida. – jtahlborn

+0

@jtahlborn: El 'E se extiende Enum ' es un estándar para cualquier clase que extienda adecuadamente Enum, que todas las clases 'enum' hacen, y' LogEvent.Type' es una clase 'enum', por lo que debería funcionar también, pero parece que hay un error en 'javac'. –

+0

@jtahlborn, sí, piense en ello: ¿LogEvent.Type extiende Enum ? Sin duda lo hace. Pero es exactamente a lo que nos referimos cuando escribimos "E extiende Enum ", con E = LogEvent.Type. Así que estoy de acuerdo con que parece un error en javac. De hecho, "E extiende Enum " y "E extiende Enum " debe significar exactamente lo mismo porque cualquier tipo de enumeración E solo puede extender Enum y nada más. –

4

Tuve un problema similar y me actualicé de jdk1.6.0_16 a jdk1.6.0_23 y desapareció sin ningún cambio de código.