2010-05-06 59 views
13

Java方法调用,可以设定参数下面的代码:什么时候参数化方法调用有用?

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

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

我发现这是可能从Eclipse的Java格式化设置对话框,并想知道是否有任何情况下,这是有用的或必需的。


编辑

基于阿恩的出色答卷,我想出了以下结论:

除了改善型安全性阿恩的例子说明了一个参数化方法调用,您可以指定的应该是容器元素类型的方法参数的公共基类型。这种类型通常由编译器自动推断为最具体的通用基本类型。通过参数化方法调用,该行为可能被覆盖。如果编译器推导出多个通用类型,则可能需要参数化方法调用。

下面的示例演示该行为:

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

+0

难道只有我认为这很奇怪吗?这个线程中的每个人似乎都认为“参数化方法”必须是一个通用方法?具有声明参数的方法是“参数化”方法。泛型方法只是另一种参数化方法,其中类型就是这样一个参数。或者我错过了什么? – 2017-09-22 13:24:49

+0

你是在现场!事后看来,标题应该是“什么时候调用类型参数的方法调用不可能推断有用?” – 2017-09-23 16:51:02

回答

13

我从来没有在实践中使用这个,但你能想象使用这种类型的安全性。请看下面的方法:

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

所以,你有一个通用的方法是类型安全并且可以用于每个对象,而不限于特定的接口或类。

+0

优秀的答案,尤其是使用可变参数 – 2010-05-09 17:18:39

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

编辑:

更一般地,只要你想返回一个特定的类型,或者你想在一个通用的方式来链接类型的两个或多个参数是有益的。

+1

您没有在该代码中的任何位置执行参数化方法调用 – newacct 2010-05-06 17:47:10

13

参数化方法调用在您希望允许不需要转换的情况下允许不同类型时非常有用。例如,Collections辅助类大量使用参数化方法调用。当你想使用他们的辅助方法之一,举几个例子一个新的通用集合:

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

所以,当你希望能够在其他地方使用泛型类型,要使用这些方法调用。它们在使用泛型时防止编译器警告。

+1

不是从变量声明中推断的集合类型吗? – 2010-05-06 14:32:40

+0

如果你在列表中没有参数,列出 anEmptyStringList = Collections.emptyList()',你将从编译器得到一个强制性警告(除非你关闭了它们)。事实上,我首先从一位向我展示如何摆脱警告的同事那里了解到这一点。 – justkt 2010-05-06 14:35:43

+0

我无法在我的设置上重现该警告。即使使用-Xlint参数。这可能是由于编译器的差异造成的。我使用Linux上Sun JDK的javac 1.6.0_20。 – 2010-05-06 15:02:21

1

例如,当你需要一些比较普遍方法

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

假设该方法是类聚合的成员,并且一般类型参数T被加入到可比在声明然后我可以调用它简单地称为 Aggregator.max(新的整数(5),新的整数(10)); 通话中不需要参数。 – 2010-05-06 15:08:35

+0

您没有在该代码中的任何地方执行参数化方法调用 – newacct 2010-05-06 17:47:26

+0

是的,同意。不需要另外指定类。 – 2010-05-06 21:46:48

相关问题