2015-11-12 24 views
5

前言:我明白仿製藥以及它們如何在類級別(例如class MyClass<T>)宣佈,但我從來沒有見過它的靜態方法的級別上聲明,並沒有任何明確的綁定(例如class MySubclass<String> extends MyClass)。什麼是通用方法,在這種情況下<T>是如何綁定的?

我發現這個代碼片段在我正在工作的應用程序(我沒有寫這部分)。我從來沒有見過用這種方式聲明的方法。 <T>而不是定義在班級的其他地方。 Intent.getExtras().get()返回Object,其實際上可能是String,Boolean等。

private static <T> T getItemExtra(final Intent intent, final String extraName) { 
    T item = null; 

    if(intent != null && intent.getExtras() != null) { 
     item = (T) intent.getExtras().get(extraName); 
    } 

    return item; 
} 

使用範例:

String s1 = getItemExtra(someIntent, "some_string_extra"); 
Uri u1 = getItemExtra(someIntent, "some_uri_extra"); 

如何在JVM知道使用什麼類型<T>? (是的這種方法編譯和執行成功)。

+3

不能遠程重複其他問題。 –

+0

@Nilish我在問泛型方法,而不是泛型類。我已經更新了這個問題來反映這一點。 –

+0

@OliverGondža是的,我得承認這是重複的。 –

回答

1

這就是Java中已知的generic method。 T in表示一種您通常會指定的類型。然後編譯器會用您替換的類型替換T的任何實例。如果您不這樣做,編譯器會嘗試從可用信息中推斷出正確的類型。

您應該查看Java Generics教程以獲得更深入的解釋。

1

T是所謂的類型界面。在這種情況下,返回類型是一個類型接口,所以簡單地說getItemExtra(...)將返回StringUri就足以讓編譯器知道此方法將返回該對象。這就是說,這不是介紹輸入接口的最好例子,所以這裏是一個更簡單的例子。

ArrayList使用類型的接口,除了你說的是ArrayList中會包含哪些對象類型實現的,除了沒有T他們正在使用E,這是很好的,因爲角色是任意的,只要你一直使用的是相同的字符你的實現。

下面是從實際implementation相關片段:

public class ArrayList<E> extends AbstractList<E> 
     implements List<E>, RandomAccess, Cloneable, java.io.Serializable 
{ 

所以,如果你聲明ArrayList<String>編譯器在編譯時將與String更換EArrayList<YourCustomObject>同樣會在整個實施中取代EYourCustomObject

+0

我的問題是關於泛型方法,而不是泛型類。 –

+0

這是一樣的東西,你在構造函數中指定了你在調用方法時指定的那個。 – CodyEngel

3

JVM如何知道<T>的類型?

基本的答案是,它沒有。在Java中,泛型類型在編譯時由類型檢查器使用,但在程序實際運行時從程序中刪除。舉例來說,在item = (T) intent.getExtras().get(extraName)中投射到T實際上並沒有在運行時做任何事情:無論調用者期望T是什麼類型,它總是對Object進行強制轉換。(這是從鑄造到正常的類型像String,在那裏,如果你嘗試投錯東西的程序將立即失敗,異常不同。)

,你可以轉換爲T未經檢查的事實是Java類型系統中的漏洞可能導致怪異的類別轉換異常。舉例來說,如果你說

String s = getItemExtra(...); 
s.toLowerCase(); 

getItemExtra不會返回一個字符串,那麼你會得到第二行的異常告訴你,s不是字符串,即使沒有投上線。因此,當Java編譯器看到一個轉換爲T時,它會生成一個未經檢查的轉換警告,告訴你它不能檢查你的類型轉換是否合法,並且你可能會遇到這樣的問題。

+1

事實上,你在第一行會得到一個異常,因爲第一行變成了'String s =(String)getItemExtra(...);'。 –

相關問題