2012-07-16 25 views
8

Dado el siguiente código no muy útil:métodos genéricos y Tipo Inferencia en Java

package com.something; 

import java.util.ArrayList; 
import java.util.Collection; 

//Not a generic class! 
public class Test { 

    public <T> void plain(T param1, T param2) {} 
    public <T> void fancy(T param1, Collection<T> param2) {} 

    public void testMethod() { 

    //No error 
    fancy("", new ArrayList<String>()); 

    //Compiler error here! 
    fancy("", new ArrayList<Integer>()); 

    //No error 
    plain("", new ArrayList<Integer>()); 

    } 

} 

(Por favor, corrija mi entendimiento si está mal!)

La segunda llamada a fancy() es un error del compilador porque Java no puede deducir cualquier tipo común entre los dos argumentos (no se puede inferir Object desde el segundo parámetro debe ser un Collection.)

la llamada a plain() es no un error del compilador porque Java infiere el tipo común de Object entre los dos argumentos.

Recientemente encontré el código que tenía una firma de método similar a plain().

Mi pregunta es la siguiente:

es la firma plain() 's útil para algo?

Quizás la persona que escribió el código pensó que la firma de plain() haría que ambos parámetros tengan el mismo tipo en tiempo de compilación, lo que obviamente no es el caso.

¿Hay alguna diferencia o beneficio de escribir un método con una firma como plain() en lugar de definir ambos parámetros como Object s?

+0

programación genérica real es simplemente existir en Java. – texasbruce

Respuesta

4

Mientras que el compilador no infiere el tipo genérico que podría querer, hará impone restricciones de tipo que se especifican explícitamente. La siguiente invocación produce un error de tipo.

this.<String>plain("", new ArrayList<Integer>()); /* Compiler error. */ 

El parametrizado método < String> simple (String, String) del tipo de prueba no es aplicable a los argumentos (String, ArrayList < Integer>)

+0

¡Tiene sentido! Esta es la pieza faltante que estaba buscando. ¡Gracias! – segfault

+0

¿Por qué esto no funciona en el método estático? –

+0

¿Y cómo resolver eso? –

3

Supongo que podría decir que sirve como un tipo de documentación, de modo que el usuario sepa que espera que ambos argumentos sean del mismo tipo. Por supuesto, cualquier dos objetos son del mismo tipo hasta cierto punto (son todos Object), por lo que es una afirmación sin sentido.

En resumen, es una firma inútil.

Por supuesto, si plain devolviera un tipo T, esa sería una historia diferente.

+0

Simplemente curioso; ¿Podría por favor elaborar esa historia? –

+0

@KanagaveluSugumar ¿En qué parte específica le gustaría la elaboración? – yshavit

+0

si plain devolvió un tipo T, ¿cuál es el impacto? y si no es así –

1

La segunda llamada a la fantasía() es un error del compilador de Java, porque no se puede inferir cualquier tipo común entre los dos argumentos (no se puede inferir de objetos desde el segundo parámetro debe ser una colección.)

Bueno, no estoy seguro de que esta es la razón, yo diría que la razón es que el tipo genérico T en Collection<T> es un invariante cuyo valor determina el tipo del primer parámetro T.

Por ejemplo, esto es válido:

fancy("", new ArrayList<CharSequence>()); //compiles Ok 

Debido a que todos son StringCharSequences. Se espera que el primer parámetro sea CharSequence una vez que se deduzca el tipo de ArraysList<CharSequence>.

Sin embargo, esto no es válido:

fancy((CharSequence)"", new ArrayList<String>()); //compiler error 

Debido a que se espera que el tipo del primer parámetro sea String, y no podemos garantizar que toda la CharSequences son, de hecho, del tipo String, ¿verdad?

Entonces, AFAIK, la razón por la que los tipos no son compatibles es debido a la naturaleza de los genéricos en este caso, y no al hecho de que el segundo tipo es un Collection.

+0

Tiene sentido. Esto también se me ocurrió a mí, pero no fui lo suficientemente lejos como para producir algo similar al ejemplo "válido" que usted señaló. Muchas gracias por corregir mi entendimiento! – segfault

Cuestiones relacionadas