2010-01-14 16 views
5

Eche un vistazo a estas tres clases. Minatchi se permite extenderse para que también se pueda extender el tipo de devolución de sus métodos. Para ilustrar, utilicé un método estático.genéricos de Java que extienden el tipo de retorno de los métodos

public class Minatchi<T extends Minatchi<?>>{ 

    static public <T extends Minatchi<?>> 
    List<T> listAll(){ 
     return 
     (List<T>) query(); 
    } 
} 

Y por lo que subclase Minatchi en Señora

public class Lady 
extends Minatchi<Lady>{ 

} 

Aquí es donde el comportamiento cuestionable lleva a cabo.

public class HelloMinatchi{ 

    private void listA(){ 
    List<Lady> uvs = Lady.listAll(); 
    for (Lady uv: uvs){ 
     logger.info(uv.getName()); 
    } 
    } 

    private void listB(){ 
    for (Lady uv: Lady.listAll()){ 
     logger.info(uv.getName()); 
    } 
    } 
} 

Los métodos listA y listB son esencialmente los mismos. listA coloca la lista en una variable intermedia uvs, mientras que listB coloca directamente listAll en el encabezado for-loop.

Sin embargo, para listB, el compilador se queja No se puede convertir Minatchi <?> En Lady.

Así que esta pregunta es sobre la integridad del diseño de los genéricos de Java. Sin embargo, otra queja de genéricos.

Se trata de una función deliberada de diseño o una falla de diseño involuntaria que los diseñadores de genéricos de Java no sabían cómo resolver. Si deliberadamente, ¿por qué hicieron eso? Si es un error, ¿están planeando resolverlo?

¿O es este mi problema personal que no conozco una mejor manera de declarar los genéricos? Si es así, dime cómo.

(he usado una clase genérica Minatchi porque he métodos no estáticos de estar expuestos a la extensión de clase también, que me he dejado en la pregunta.)

+0

Utilicé una clase Minatchi genérica porque tengo métodos no estáticos para exponer también a la extensión de clase, que dejé en el pregunta. –

Respuesta

5

El método estático no toma la definición de tipo genérico de la clase. es decir, el método listAll() no conoce el Lady (en extends Minatchi<Lady>).

Su tipo de retorno se infiere por el lado izquierdo de la expresión:

  • en listA() el lado izquierdo define que espera List<Lady>
  • en listB() el bucle forEach parece que también debe espera un Lady, pero parece que el compilador no está correctamente instruido con el ciclo forEach.

La manera de hacer listB() trabajo es para decirle qué tipo genérico de usar:

for (Lady uv : Lady.<Lady>listAll()) {..} 
+0

Gracias bozho. ¿Qué estaba fumando? –

1

Su problema es que deja que el compilador inferir la genérica argumentos a la lista Todo método y en el primer caso infiere lo que quiere porque almacena el resultado en una variable y simplemente puede ver el tipo de la variable. En el segundo no se puede inferir el tipo de "derecho" de forma automática, por lo que es necesario especificar usted mismo:

for (Lady uv: Lady.<Lady>listAll()){ 
    logger.info(uv.getName()); 
} 

Tenga en cuenta que en este ejemplo no hay razón para la clase Minatchi a ser más genérico que no lo hace afectar el método estático en absoluto.

Tenga en cuenta también que llamar a Lady.listAll es exactamente lo mismo que llamar a Minatchi.listAll (es decir, no afecta los tipos que el compilador podría inferir como argumentos genéricos).

+0

Señora. listAll(), no Lady.listAll ();) (corregido por usted) – Bozho

+0

Si el compilador puede inferir de una variable, ciertamente no debería tener ningún problema para inferir el tipo de la variable en el encabezado for-loop. for (Lady uv: Lady.listAll()) Esta pregunta no se trata si DEBO usar una variable intermedia. Más bien, se trata de ¿por qué el diseñador de lenguaje se olvidó de acomodar el for-loop? ¿Por qué no/no pudieron usar la variable for-loop? IOW, ¿qué estaban fumando? –

+0

Gracias. Debería haber probado antes de publicar. – sepp2k

1

Esto está sucediendo debido a la borradura de tipo.

Desde el Java Generic tutorial

Cuando se crea una instancia de un tipo genérico, el compilador traduce esos tipos por una técnica llamada Tipo de borrado - un proceso donde el compilador elimina toda información relacionada con los parámetros de tipo y escriba argumentos dentro de una clase o método .

Debido a que el Lady.ListAll llamada se está realizando en el tipo de prima Minatchi, el compilador no puede saber que el tipo específico es Minatchi se utilizó

Tipo de borrado para los genéricos de manera que los tipos genéricos serían compatibles con las bibliotecas de Java compiladas antes de que los genéricos se agregaran a la Biblioteca. Ha habido algún esfuerzo para tener reification added to Java, pero no está en la hoja de ruta para Java 7.

+0

realmente? Pensé que el borrado de tipos solo ocurre en tiempo de ejecución. Este error viene en tiempo de compilación. – nanda

+0

@nanda: el borrado de tipo está en tiempo de compilación: si el tipo era conocido en tiempo de ejecución, no habría necesidad de borrarlo. –

+0

Es decir, sí, el borrado está en tiempo de compilación, por lo que el tiempo de ejecución no conoce el tipo genérico, pero la comprobación de errores se produce antes de compilar la clase. ¿Cómo se puede compilar si tiene un error? – nanda

Cuestiones relacionadas