2009-07-24 14 views
5

tengo una interfazgenéricos de Java: Advertencia necesita un molde sin marcar para ajustarse a <InterfaceName>

interface x { 
    A getValue(); 
} 

y la implementación

class y implements x { 
    public B getValue() { return new B();} 
} 

B es una subclase de A. Esto funciona gracias a las covariantes anulando, supongo.

Pero si vuelvo a escribir la interfaz como

interface x{ 
    <T extends A> T getValue(); 
} 

recibo una advertencia de que en la ejecución

Advertencia necesita un molde sin marcar para ajusta a A.getValue()

¿Cuál es la diferencia entre 2 versiones de la interfaz? Estaba pensando que son lo mismo.

+0

Curiosamente, cuando lo cambio a "' interfaz x {T getValue();} '", la advertencia desaparece. –

+0

Sí, creo que en este caso el compilador tiene una forma de averiguar qué es T de la declaración de clase. Pero en otro caso no hay forma de que descubra qué es T. – Surya

Respuesta

4

La segunda versión de la interfaz es incorrecta. Dice que getValue devolverá cualquier subclase que solicite; el tipo de devolución se deducirá en función de la expresión en su mano izquierda.

Por lo tanto, si usted obtiene una referencia a un x (vamos a llamarlo obj), puede legalmente hacer la siguiente llamada sin advertencias del compilador:

x obj = ...; 
B b = obj.getValue(); 

que es probablemente incorrecta en su ejemplo, porque si añadir otra clase C que también se extiende A, también puede legalmente realizar la llamada:

C c = obj.getValue(); 

Esto se debe a T no es una variable de tipo perteneciente a la interfaz, solo para el método en sí.

+0

Ahh ..so T se infiere desde el lado izquierdo. Tiene sentido . Entonces, en un lenguaje que no infiere el tipo de asignación como C#, ¿qué ocurre? – Surya

3

Básicamente, cuando usted está haciendo un <T extends A> que está diciendo que quiere una subclase específica de A, no cualquier A, porque entonces usted podría hacer:

A getValue(); 

El compilador le advierte que puede' t garantizar que se devuelve una subclase específica definida de A, solo A sí mismo.

EDITAR: Para tratar de explicar esto mejor, B es una subclase de A, pero no necesita ser la única subclase de A. Considere la siguiente jerarquía.

B se extiende Un C parte A, pero no b

Ahora tengo un método:

public void someMethod(x value) { 
    C c = x.getValue(); 
} 

Siguiendo los genéricos, que debe compilar y garantizar ninguna excepción clase en tiempo de ejecución fundido (puede haber otra problemas con las interfaces aquí, pero ciertamente hay casos que podrían usarse para demostrar esto de manera adecuada, estoy siguiendo su ejemplo).

¿Pero qué pasa si pasa en una instancia de y a este método?

Bueno, ahora obtengo una B en lugar de una C. El compilador te advierte que esto podría suceder.

+0

B es una subclase de A, no estoy seguro de lo que quiere decir con la subclase específica – Surya

+1

Si 'clase C' era una subclase de' A', entonces podría escribir 'anX. getValue() ', lo cual es claramente incorrecto para' y'. –

+0

(BTW: mala elección de los nombres de tipo.) –

0

Por lo tanto, para construir sobre las dos respuestas de AlbertoPL y Yishai, intente esto:

class y implements x { 
    A getValue(){ return new B();} 
} 

B parte A, por lo que está muy bien. La persona que llama no necesita saber qué subclase de A se devuelve, solo que se extiende A. Entonces, vamos :)

+0

El código original realmente funcionó (con público). –

1

Lo que el compilador le dice es que no hay forma de resolver el genérico. T no se define en ningún lugar excepto como salida, ¿de qué estás hablando? Si la interfaz se generified ser un tipo T:

interface x <T extends A> { 
    T getValue() 
} 

entonces esto quiere trabajar, o si el método tuvo un valor que defina qué tipo de retorno que quería:

interface x { 
    <T extends A> T getValue(T someArgument) 
} 

o

interface x { 
    <T extends A> T getValue(Class<T> someArgument) 
} 

Entonces no habría ninguna advertencia.

editar: Consulte la publicación de waxwing para obtener una explicación de por qué NO debe utilizar genéricos para este problema en particular. Simplemente estoy mostrando cómo los genéricos serían apropiados.

Cuestiones relacionadas