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

Java 参数化方法调用何时有用?,java,generics,parameters,methods,call,Java,Generics,Parameters,Methods,Call,Java方法调用可以参数化,如下代码所示: class Test { <T> void test() { } public static void main(String[] args) { new Test().<Object>test(); // ^^^^^^^^ } } 类测试 { 无效测试() { } 公共静态void main(字符串[]args) { 新测试()

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

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

    public static void main(String[] args)
    {
        new Test().<Object>test();
        //         ^^^^^^^^
    }
}
类测试
{
无效测试()
{
}
公共静态void main(字符串[]args)
{
新测试().Test();
//         ^^^^^^^^
}
}
我从EclipseJava格式化程序设置对话框中发现这是可能的,并想知道是否有任何情况下这是有用的或必需的


编辑

根据阿恩出色的回答,我得出以下结论:

除了如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.util.array;
导入java.util.List;
课堂测试
{
公共静态void main(字符串[]args)
{
整数a=新整数(0);
长b=新长(0);
List listError=Arrays.asList(a,b);
//错误,因为数字和可比性不是对象
List listObj=Arrays.asList(a,b);
List listNum=Arrays.asList(a,b);
列表>asList(a,b);
}
}

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

当您获取某种类型的集合并返回该集合的某个子集时,它可能最有用

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

List filter(Collection当您希望允许不同类型而不强制转换时,参数化方法调用非常有用。例如,helper类广泛使用参数化方法调用。当您希望使用其一个helper方法创建新的泛型集合时,有几个示例:

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

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

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

public static <T extends Comparable> T max(T one, T two) {
    if (one.compareTo(two) > 0) {
        return one;
    } else {
        return two;
    }
}
publicstatictmax(t1,t2){
如果(一个与(两个)>0){
返回一个;
}否则{
返回两个;
}
}

我在实践中从来没有使用过这个,但是你可以想象使用它来做类型安全。考虑下面的方法:

<T> void method(T... items) {
    List<T> list = new ArrayList<T>();
    for (T item : items)
        list.add(item);
    System.out.println(list);
}
void方法(T…项){
列表=新的ArrayList();
对于(T项:项)
列表。添加(项目);
系统输出打印项次(列表);
}
你可以这样称呼它:

o.<Object>method("Blah", new Long(0));
o.<Number>method(new Integer(100), new Long(0));
o.method(“Blah”,新长(0));
o、 方法(新整数(100),新长(0));
但这将引发编译器错误:

o.<Number>method("String", new Long(0));
o.method(“String”,新长(0));

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

集合类型不是从变量声明中推断出来的吗?如果您这样做,您将从编译器中得到强制转换警告(除非您关闭了它们)
List anEmptyStringList=Collections.emptyList()
调用中没有参数。事实上,我第一次从一位同事那里了解到这一点,他向我展示了如何消除警告。我无法在我的设置中重现该警告。即使使用-Xlint参数也不行。这可能是由于编译器的差异造成的。我使用的是Linux上Sun JDK的javac 1.6.020。我非常确定如果以这种方式调用“emptyList”,ler将永远不会产生此警告。我已启用泛型的警告,但没有收到警告。请注意,@user1084563引用已通过Java 8修复(通过openjdk-8-jdk-headless_8u111-b14-2~bpo8+1_amd64.deb和zulu8.19.0.1-jdk8.0.112-win_x64.zip确认)。假设该方法是类聚合器的成员,并且在声明中将泛型类型参数T添加到Comparable,那么我可以简单地将其称为Aggregator.max(新整数(5),新整数(10));调用时不需要参数。您没有在该代码中的任何位置执行参数化方法调用是的,同意。不需要另外指定类。您没有在该代码中的任何位置执行参数化方法调用是不是只有我觉得这个线程中的每个人都认为“参数化方法”很奇怪必须是泛型方法?声明了参数的方法是“参数化”方法。泛型方法只是类型为此类参数的另一个参数化方法。或者我遗漏了什么?你说得对!事后看来,标题可能应该是“带有无法推断的类型参数的方法调用何时有用?”