2010-05-06 11 views
13

de Java llamada al método puede ser parametrizado como en el siguiente código:¿Cuándo es útil una llamada a un método parametrizado?

class Test 
{ 
    <T> void test() 
    { 
    } 

    public static void main(String[] args) 
    { 
     new Test().<Object>test(); 
     //   ^^^^^^^^ 
    } 
} 

descubrí que esto es posible desde el diálogo de configuración de Eclipse Java formateador y se pregunta si hay algún casos en que esto sea útil o necesario.


EDITAR

Sobre la base de una excelente respuesta de Arne me encontré con la siguiente conclusión:

Además de la seguridad tipo mejorado como ejemplo de Arne ilustra una llamada al método con parámetros permite especificar el tipo base común de los métodos argumentos que deberían ser el tipo de los elementos del contenedor. Normalmente, el compilador hace referencia automáticamente a este tipo al tipo de base común más específico. Al parametrizar la llamada al método, este comportamiento puede ser anulado. Una llamada a un método parametrizado puede ser necesaria si el compilador hace referencia a múltiples tipos comunes.

El siguiente ejemplo demuestra que el comportamiento:

import java.util.Arrays; 
import java.util.List; 

class Test 
{ 
    public static void main(String[] args) 
    { 
     Integer a=new Integer(0); 
     Long b=new Long(0); 
     List<Object> listError=Arrays.asList(a, b); 
     //error because Number&Comparable<?> is not Object 
     List<Object> listObj=Arrays.<Object>asList(a, b); 
     List<Number> listNum=Arrays.<Number>asList(a, b); 
     List<Comparable<?>> listCmp=Arrays.<Comparable<?>>asList(a, b); 
    } 
} 

Este comportamiento se define en los párrafos Especificación del lenguaje Java 8.4.4 Tercera Edición y 15.12.2.7 pero no fácil de entender.

+0

¿Soy solo yo el que piensa que es extraño cómo todos en este hilo parecen pensar que un "método parametrizado" debe ser un método genérico? Un método que tiene parámetros declarados es un método "parametrizado". Un método genérico es simplemente otro método parametrizado donde el tipo es uno de esos parámetros. ¿O me he perdido algo? –

+0

¡Es perfecto! En retrospectiva, el título probablemente debería haber sido "¿Cuándo es útil una llamada a un método con argumentos tipo que no pueden inferirse?" –

Respuesta

13

nunca he utilizado esto en la práctica, pero se puede imaginar el uso de este tipo para la seguridad.Considere el siguiente método:

<T> void method(T... items) { 
    List<T> list = new ArrayList<T>(); 
    for (T item : items) 
     list.add(item); 
    System.out.println(list); 
} 

se le puede llamar de esta manera:

o.<Object>method("Blah", new Long(0)); 
o.<Number>method(new Integer(100), new Long(0)); 

Pero esto generará un error del compilador:

o.<Number>method("String", new Long(0)); 

Así que tienes un método genérico que es typesafe y se puede usar para cada Objeto, no limitado a una interfaz o clase paricular.

+0

excelente respuesta, especialmente el uso de varargs –

8

Probablemente sea más útil cuando está tomando una colección de algún tipo y devolviendo algún subconjunto de esa colección.

<T> List<T> filter(Collection<? extends T> coll, Predicate<? super T> pred) { 
    List<T> returnList = new ArrayList<T>(); 
    for(T t : coll) { 
     if(pred.matches(t)){ 
      returnList.add(t); 
     } 
    } 
    return returnList; 
} 

Editar:

De manera más general, es útil siempre que se desee devolver un tipo específico, o si desea enlazar los tipos de dos o más parámetros de una manera general.

+1

no está haciendo una llamada a un método parametrizado en ningún lugar de ese código – newacct

13

Las llamadas a métodos parametrizados son útiles cuando desea permitir diferentes tipos sin conversión. Por ejemplo, la clase de ayuda Collections hace un uso extensivo de llamadas de método parametrizadas. Cuando se quiere hacer una nueva colección genérica usando uno de sus métodos de ayuda, algunos ejemplos:

List<String> anEmptyStringList = Collections.<String>emptyList(); 
Set<Integer> unmodifiableCopy = Collections.<Integer>unmodifiableSet(originalSet); 

lo tanto, cuando usted quiere ser capaz de utilizar el tipo genérico en otro lugar, que desea utilizar esas llamadas a métodos. Evitan las advertencias del compilador cuando usan genéricos.

+1

¿No se ha inferido el tipo de recopilación de la declaración de variables de todos modos? –

+0

Obtendrá una advertencia de lanzamiento del compilador (a menos que los haya desactivado) si lo hace 'List anEmptyStringList = Collections.emptyList()' sin el parámetro de la llamada. De hecho, me enteré de esto por un colega que me estaba mostrando cómo deshacerse de la advertencia. – justkt

+0

No puedo reproducir esa advertencia en mi configuración. Ni siquiera con el parámetro -Xlint. Eso es probablemente causado por las diferencias del compilador. Uso javac 1.6.0_20 de Sun JDK en Linux. –

1

Por ejemplo, cuando se necesita algún método universal para las comparaciones:

public static <T extends Comparable> T max(T one, T two) { 
    if (one.compareTo(two) > 0) { 
     return one; 
    } else { 
     return two; 
    } 
} 
+1

Suponiendo que el método es un miembro del Agregador de clase y el parámetro de tipo genérico T se agrega a Comparable en la declaración, entonces puedo llamarlo simplemente como Agregador.max (nuevo Entero (5), nuevo Entero (10)); No se requieren parámetros en la llamada. –

+0

no está haciendo una llamada a un método parametrizado en ningún lugar de ese código – newacct

+0

Sí, de acuerdo. No es necesario especificar adicionalmente la clase. –

Cuestiones relacionadas