参数化方法调用何时有用?

时间:2010-05-06 14:08:58

标签: java generics parameters methods call

Java方法调用可以参数化,如下面的代码所示:

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

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

我发现这可以从Eclipse Java Formatter设置对话框中找到,并且想知道是否存在任何有用或必需的情况。


修改

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

此行为在Java语言规范第三版第8.4.4和15.12.2.7段中定义,但不容易理解。

4 个答案:

答案 0 :(得分:15)

我从来没有在实践中使用过这个,但你可以设想用它来保证类型安全。请考虑以下方法:

<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,不限于特定的接口或类。

答案 1 :(得分:13)

当您想要允许不同类型而不进行强制转换时,参数化方法调用很有用。例如,Collections助手类广泛使用参数化方法调用。当您想使用其中一种辅助方法创建一个新的泛型集合时,请举几个例子:

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

因此,当您希望能够在其他地方使用泛型类型时,您希望使用这些方法调用。它们在使用泛型时会阻止编译器警告。

答案 2 :(得分:8)

当您收集某种类型的集合并返回该集合的某些子集时,它可能最有用。

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

编辑:

更一般地说,只要您希望返回特定类型,或者想要以一般方式链接两个或更多参数的类型,它就很有用。

答案 3 :(得分:1)

例如,当您需要一些通用方法进行比较时:

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