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

2022-09-02 08:57:18

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 段中定义,但不容易理解。


答案 1

我从未在实践中使用过它,但你可以想象用它来确保类型安全。请考虑以下方法:

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

因此,您有一个类型安全的泛型方法,可用于每个对象,而不限于视接口或类。


答案 2

当您希望允许不同的类型而不进行强制转换时,参数化方法调用非常有用。例如,集合帮助程序类广泛使用参数化方法调用。如果要使用其帮助程序方法之一创建新的泛型集合,请举几个例子:

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

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