2010-10-23 20 views
27

dado:¿Por qué obtengo "Tipo genérico ilegal para instanceof"?

public class C<T> { 
    private class D { 
     public boolean equals(Object o) { 
      if (!(o instanceof D)) // line 4 
       return false; 
      D other = (D)o;    // line 6 
      return i == other.i; 
     } 
     int i; 
    } 
} 

me sale:

C.java:4: illegal generic type for instanceof 
      if (!(o instanceof D)) 
          ^

también me sale un "molde sin control" de advertencia acerca de la línea 6. ¿Por qué? El o es no un tipo genérico - es simplemente Object. ¿Cómo puedo implementar correctamente equals() comprobando y lanzando a una instancia de D?

Nota: Obviamente, este ejemplo de código es una versión simplificada de mi código actual. Las clases reales para C y D son mucho más grandes y D es una clase interna private de C utilizada por su implementación.

FYI: El D real hace uso del parámetro genérico T.

+7

¿Has probado * instanceof C.D * en lugar de * D * instanceof? –

+0

Solo voy a notar que el ejemplo dado * está * roto. –

+0

@Evan: Eso funciona. Pero, ¿por qué es necesaria la calificación? –

Respuesta

30

El O no es un tipo genérico - es sólo un objeto plano.

Ese no es el problema. El problema ... y la causa raíz de ambos errores de compilación ... es que D es una clase genérica. Y es genérico porque es una clase anidada no estática en una clase genérica. Su nombre completo sería some.pkg.C<T>.D.

FYI: La verdadera D hace uso del parámetro T. genérica

Y el hecho de que podría hacer uso de T es lo que hace D una clase genérica.

El motivo por el que no puede usar instanceof D o (D) es un borrado de tipo genérico. Básicamente, el tiempo de ejecución no puede distinguir entre los tipos de (digamos) C<String>.D y C<Integer>.D. Y como no puede hacer eso, no puede determinar si instanceof D debe devolver true o false o si (D) debe tener éxito o arrojar ClassCastException.

Una solución sería declarar D como estático. Pero eso no funcionará con su "D real" porque una clase estática no puede hacer uso de un parámetro de tipo genérico de la (s) clase (s) adjunta (s). Su "FYI" dice que hace eso.

Otra solución es crear una instancia de la clase externa C pasándole el tipo real de T como una instancia java.lang.Class<T>. A continuación, utilice esta instancia Class para implementar los controles y conversiones del tipo de tiempo de ejecución según sea necesario. Esto es probable que sea desordenado.

La tercera solución es cuidadosamente analizar el código y determinar si es seguro para una @SuppressWarning anotaciones para suprimir las advertencias de "lanzamiento inseguro", etc.

¿Qué tipo de borrado? 'o' es de tipo Objeto directamente.

En realidad Object es el tipo declarado de la variable o. Es muy probable que el objeto real tenga algún otro tipo, y es el tipo que (si es una instancia D por ejemplo) se habrá sometido a borrado de tipo.

7

Si hace que la clase interna sea estática, el código compila bien.

Ex:

private static class D{...} 

Leer here por la diferencia.

También puede probar o.getClass() != D.class (después de la protección contra o ser nula, por supuesto)

+0

Sé que la diferencia entre las clases anidadas no estáticos y estáticas. En este caso, lo necesito no estático. Si hago la clase anidada estática, no puedo hacer uso del parámetro genérico T. –

+1

¿Qué pasa con las comparaciones de o.getClass() y D.class? No sabrá que son del mismo tipo parametrizado, pero no estoy seguro de que pueda hacer eso de manera confiable con el borrado de tipo. –

+0

¿Qué tipo de borrado? 'o' es de tipo Objeto directamente. –

3
D.class.isInstance(o) 

parece que funciona aquí.

6

@StephenC es justo en que el problema es que D significa C<T>.D, que es un tipo parametrizado. La solución es utilizar el tipo crudo o del tipo comodín parametrizada:

if (!(o instanceof C.D)) 

o

if (!(o instanceof C<?>.D)) 
Cuestiones relacionadas