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

Joh*_*cob 16 java generics parameters methods call

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

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

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

我发现这可以从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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

Arn*_*sch 16

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

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

你可以这样称呼它:

o.<Object>method("Blah", new Long(0));
o.<Number>method(new Integer(100), new Long(0));
Run Code Online (Sandbox Code Playgroud)

但这会引发编译器错误:

o.<Number>method("String", new Long(0));
Run Code Online (Sandbox Code Playgroud)

因此,您有一个类型安全的通用方法,可以用于每个Object,不限于特定的接口或类.


jus*_*tkt 13

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

List<String> anEmptyStringList = Collections.<String>emptyList();
Set<Integer> unmodifiableCopy = Collections.<Integer>unmodifiableSet(originalSet);
Run Code Online (Sandbox Code Playgroud)

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

  • 是不是从变量声明中推断出的集合类型? (3认同)

ILM*_*tan 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;
}
Run Code Online (Sandbox Code Playgroud)

编辑:

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

  • 你没有在该代码中的任何地方进行参数化方法调用 (2认同)