2011-01-28 44 views

回答

19

<typearg>methodname是顯式指定類型參數的泛型方法

當您使用泛型類,通常必須指定類型參數(如String)語法:

ArrayList<String> list = new ArrayList<String>(); 

使用通用方法,通常不會傳遞類型參數:

public static <T> void foo(T param) { } 
... 
String s = ...; 
MyClass.foo(s); 

您會注意到我們沒有在代碼中明確指定我們需要String版本foo,即沒有明確的類型參數,就像我們在使用泛型類時所看到的那樣(List<String>)。

編譯器正在做一些編譯器魔術來推斷基於上下文的泛型類型參數。這是一件偉大的事情,而且非常強大。

但是,偶爾的編譯器不能自動推斷類型參數:

public static <T> void bar() { T myLocalVar = ...; ... } 
MyClass.bar(); 

我們試圖調用哪些具體版本的bar,即什麼是該呼叫的類型參數?不知道?那麼,編譯器也不會。我們必須明確說明類型參數,就像我們使用泛型類時,通常做的:

MyClass.<String>bar(); 

另見:


旁白:它可能是值得一提的是,Java 7中會加入所謂的鑽石運營商,使我們能夠讓編譯器使用泛型類時,現在也推斷類型參數:

ArrayList<String> list = new ArrayList<String>(); 

ArrayList<String> list = new ArrayList<>(); 

What is the point of the diamond operator in Java 7?

8

這就是你如何顯式指定泛型方法的類型參數。在大多數情況下,編譯器可以推斷它,但有時需要明確說明。

+0

對於我自己的好奇心 - 是否需要明確說明,因爲這些方法是靜態的? – christophmccann 2011-01-28 15:04:10

1

上面差不多的回答解決你的問題,但如果你想的情況下的一個具體例子,其中Java的泛型類型推斷失敗和expli citly說明它以這種方式節省了一天,考慮下面的類定義:

public class A { } 
public class B extends A { } 
public class C extends A { } 

然後將下面的代碼工作只是罰款(即Java的類型推斷成功):

List<Class<? extends A>> list = ImmutableList.of(B.class, C.class); 

但以下,它無法編譯:

List<Class<? extends A>> list = ImmutableList.of(B.class); 

是的;奇怪的是,通過去除一個參數,我們迷惑的類型推理系統,因爲B.class的「最近的共同後裔」和C.classA.class,但B.class本身,它只是B.class,這(在Java的泛型協變性缺乏)不符合List<Class<? extends A>>。在這種情況下,你沒有選擇,只能使用:

List<Class<? extends A>> list = ImmutableList.<Class<? extends A>>of(B.class); 

由於B確實延長A,該編譯(並運行)就好了。

我希望這個演示強調操作者的實用性。