Когда вызов параметризованного метода полезен?

Вызов метода Java может быть параметризован как в следующем коде:

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

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

Я узнал, что это возможно от диалогового окна Параметров средства форматирования Java Eclipse и задалось вопросом, существуют ли какие-либо случаи, где это полезно или необходимо.


Править

На основе превосходного ответа Arne я придумал следующее заключение:

В дополнение к улучшенной безопасности типов, поскольку пример Arne иллюстрирует, что вызов параметризованного метода позволяет Вам указать тип общей базы аргументов методов, которые должны быть типом контейнерных элементов. Этот тип обычно заключается автоматически компилятором к самому определенному типу общей базы. Путем параметризации вызова метода может быть переопределено это поведение. Вызов параметризованного метода может требоваться, если существует несколько общих типов, заключенных компилятором.

Следующий пример демонстрирует что поведение:

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

Это поведение определяется в абзацах 8.4.4 и 15.12.2.7 Выпуска Трети Спецификации языка Java, но не понятное.

16
задан Johann-Christoph Jacob 9 May 2010 в 17:17
поделиться

4 ответа

Я никогда не использовал это на практике, но вы можете себе представить, что используете это для безопасности типа. Рассмотрим следующий метод:

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

Вы можете вызвать его следующим образом:

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

Но это вызовет ошибку компилятора:

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

Таким образом, у вас есть универсальный метод, который является типобезоподборным и может использоваться для каждого Object, не ограничиваясь парикулярным интерфейсом или классом.

16
ответ дан 30 November 2019 в 16:36
поделиться

Вызовы параметризованных методов полезны, когда вы хотите разрешить использование различных типов без преобразования типов. Например, вспомогательный класс Collections широко использует вызовы параметризованных методов. Если вы хотите создать новую универсальную коллекцию, используя один из их вспомогательных методов, несколько примеров:

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

Итак, если вы хотите иметь возможность использовать универсальный тип в другом месте, вы хотите использовать эти вызовы методов. Они предотвращают появление предупреждений компилятора при использовании дженериков.

13
ответ дан 30 November 2019 в 16:36
поделиться

Это, вероятно, наиболее полезно, когда вы берете коллекцию определенного типа и возвращаете некоторое подмножество этой коллекции.

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

Изменить:

В общем, это полезно, когда вы хотите вернуть определенный тип или хотите связать типы двух или более параметров общим способом.

8
ответ дан 30 November 2019 в 16:36
поделиться

Например, когда вам нужен какой-то универсальный метод для сравнений:

public static <T extends Comparable> T max(T one, T two) {
    if (one.compareTo(two) > 0) {
        return one;
    } else {
        return two;
    }
}
1
ответ дан 30 November 2019 в 16:36
поделиться
Другие вопросы по тегам:

Похожие вопросы: