Quand est paramétrée appel de méthode utile?

un appel de méthode Java peut être paramétré comme dans le code suivant:

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

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

j'ai découvert que c'est possible à partir de la boîte de dialogue Eclipse Java Formatter settings et je me suis demandé s'il y avait des cas où cela était utile ou requis.


modifier

sur la base de L'excellente réponse D'Arne, je suis arrivé à la conclusion suivante:

en plus pour améliorer la sécurité de type comme L'exemple D'Arne illustre un appel de méthode paramétré vous permet de spécifier le type de base commune des arguments de méthodes qui devraient être le type des éléments de conteneur. Ce type est normalement inféré automatiquement par le compilateur au type de base le plus spécifique commun. En paramétrant l'appel de méthode, ce comportement peut être dépassé. Un appel de méthode paramétrisé peut être requis s'il y a plusieurs types courants inférés par le compilateur.

l'exemple suivant démontre ce comportement:

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);
    }
}

ce comportement est défini dans les paragraphes 8.4.4 et 15.12.2.7 de la troisième édition de la norme Java Language Specification, mais il n'est pas facile à comprendre.

15
demandé sur Johann-Christoph Jacob 2010-05-06 18:08:57

4 réponses

Je ne l'ai jamais utilisé dans la pratique, mais vous pouvez imaginer de l'utiliser pour la sécurité de type. Considérons la méthode suivante:

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

vous pouvez l'appeler ainsi:

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

mais cela va soulever une erreur de compilation:

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

donc vous avez une méthode générique qui est typesafe et peut être utilisé pour chaque objet, non limité à une interface ou classe pariculaire.

15
répondu Arne Deutsch 2010-05-06 14:57:17
Les appels de méthode paramétrés

sont utiles lorsque vous voulez autoriser différents types sans moulage. Par exemple, la classe Collections helper utilise largement les appels de méthodes paramétrisés. Quand vous voulez faire une nouvelle collection générique en utilisant une de leurs méthodes d'aide, quelques exemples:

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

Alors, quand vous voulez être en mesure d'utiliser le type générique ailleurs, vous souhaitez utiliser ces appels de méthode. Ils empêchent le compilateur mises en garde lors de l'utilisation de médicaments génériques.

13
répondu justkt 2010-05-06 14:24:03

il est probablement plus utile quand vous prenez une collection d'un certain type, et en retournant un sous-ensemble de cette collection.

<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;
}

Edit:

Plus généralement, il est utile lorsque vous souhaitez retourner un type spécifique, ou que vous souhaitez lier les types de deux ou plusieurs paramètres d'une manière générale.

8
répondu ILMTitan 2010-05-06 15:56:54

par exemple, quand vous avez besoin de certains universel méthode pour les comparaisons:

public static <T extends Comparable> T max(T one, T two) {
    if (one.compareTo(two) > 0) {
        return one;
    } else {
        return two;
    }
}
1
répondu Aleksejs Mjaliks 2010-05-06 14:19:56