2012-08-09 96 views
2

我知道,如果你想有一個列表(例如)在創建它想:在Java中做什麼<>?

List<String> 

如果你想創建一個通用類型的列表,你可以做到這一點,如:

MyList<T> 

那麼, <>所做的唯一事情是將一個對象與一個容器或列表結合起來?它有其他用途嗎?它實際上做了什麼? 正在閱讀另一篇文章,如何將靜態方法放入泛型類型對於類型安全來說是一件壞事,那麼這種不好的代碼呢?

public class LinkList<T> { 

private final T t; 
private final LinkList<T> next; 

public LinkList(T t, LinkList<T> next){ 
    this.t = t; 

    this.next = next; 
} 
// Creates list from array of T 
public static <T> LinkList<T> getList(T[] t){ 
    if(t == null){ 
     return null; 
    } 
    LinkList linkList = null; 
    for(int i = t.length-1; i >= 0; i--){ 
     linkList = new LinkList(t[i], linkList); 
    } 
    return linkList; 
} 

public T element() { 
    return t; 
} 

public LinkList<T> getNext() { 
    return next; 
} 

}

+0

它指定一種類型的參數。你可以閱讀更多關於泛型的知識[在這裏,在相關的Java教程](http://docs.oracle.com/javase/tutorial/extra/generics/simple.html)。 – oldrinb 2012-08-09 20:43:06

+0

所以...這是不好的代碼,因爲在泛型類型中的靜態方法?在那裏有什麼潛在的危險?是否可以在列表中插入多個類型的問題,還是會給我一個編譯錯誤? – GenericJam 2012-08-09 20:51:44

+1

重複http://stackoverflow.com/questions/31693/what-are-the-differences-between-generics-in-c-sharp-and-java-and-templates-i的? – 2012-08-09 20:53:09

回答

7

<>有助於驗證類型安全的編譯器。

編譯器確保List<MyObj>在編譯時保存類型爲MyObj的對象而不是運行時。

泛型主要用於編譯時類型安全的目的。由於類型擦除,所有通用信息在編譯之後將被替換爲具體類型。

+1

對於容器,您可以將其讀爲「列表」,如列表是一個字符串列表 – 2012-08-09 20:40:59

+0

應該注意的是,它是_only_編譯時指令。由於類型擦除,運行時不知道類型應該在列表中。 – 2012-08-09 20:42:35

+0

@ChrisThompson:你太快了。我正在更新我的答案與這些細節。 – kosa 2012-08-09 20:43:29

0

<>可以與您希望的任何類一起使用,而不僅僅是容器。這些只是最常見的,因爲我們希望能夠在容器中存儲任何類型的對象,並且仍然保持類型安全。要更深入地理解這一點,您應該研究泛型以及它們的用途。

1

當你把<>和一個類型放在內部時,它被用來將什麼是潛在的運行時異常轉換成編譯錯誤。

就拿這個代碼,不使用泛型

ArrayList stringList = new ArrayList(); 
stringList.add("string"); 
stringList.add(3.4); 
String s = (String) stringList.get(1); 

//這將編譯生成一個運行時錯誤,比較字符串翻一番。

如果您添加了泛型,那麼在編寫它時可能會發現這些錯誤。

考慮下面的代碼:

ArrayList<String> stringList = new ArrayList<String>(); // Since Java 7 you can write - new ArrayList<>() 
stringList.add("string"); // OK 
stringList.add(3.4); // Would not compile! 

這樣你就可以趕上編譯時類型相關的錯誤。

編譯器本身並不關心你是否使用泛型。它在編譯時將它們全部刪除,並且就好像你沒有使用泛型一樣。但是,如果首先出現編譯錯誤,它不會讓您編譯。

我也注意到我沒有回答你關於代碼的問題。

當你做這樣的事情

class LinkedList<T> { 
.... 
.... 
} 

你告訴這個類支持泛型的編譯器,在這種情況下,可以做什麼,我說上面

你可以做

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

現在,這裏曾經在你的類,它說T它將充當如果說String,從而只允許添加和mainpu拉丁字符串。

+0

您確定運行時錯誤?我認爲它只是返回'false'......事實上,我認爲這是'equals'合約的一部分,與不同類型的對象相比只是返回'false'。 – cHao 2012-08-09 20:47:36

+0

這是仿製藥如何工作的一個很好的例子。還應該注意的是,泛型不限於容器。這些正好是泛型最常用的用法。 – 2012-08-09 20:48:28

+0

@cHao你說得對。不好的例子。編輯 – 2012-08-09 20:58:04

0

<>用於稱爲泛型的很酷功能。

的Java 5之前,不存在仿製藥。收集像ArrayList返回並操縱Objects。例如,當你知道你只能存儲String時,問題就出在這裏。但是,如果你與Objects在所有的類的工作,你不僅必須使用惱人的鑄造(String blah = (String) list.get(9);),但如果你做了錯誤,把一個Integer在列表中,你的程序將ClassCastException和燃燒。

Java 5的解決了這個泛型,所以現在你可以說ArrayList<String>說,你只會在這個ArrayList使用String秒。但是如果你需要製作ArrayList<Supercalifragilisticexpealidocious>?顯然,鍵入這不是一個愉快的經歷,尤其是當你必須鍵入

ArrayList<Supercalifragilisticexpealidocious> supercaliList = new ArrayList<Supercalifragilisticexpealidocious>(); 

申報的其中之一。此外,它可能導致錯別字,特別是在這種尺寸的類型參數下;在某些時候,你肯定會錯誤地輸入一兩個字母,並使你的程序cannot find symbol和燒傷 - 或更糟的是,靜靜地使用錯誤的類,並導致邏輯錯誤。

爪哇7引入純<>語法。這就是所謂的鑽石操作並使其所以你不必重新輸入賦值運算符右側的類型參數(<>裏面的東西)。因此,

ArrayList<Supercalifragilisticexpealidocious> supercaliList = new ArrayList<Supercalifragilisticexpealidocious>(); 

變得

ArrayList<Supercalifragilisticexpealidocious> supercaliList = new ArrayList<>(); 

這意味着少了很多時間重新鍵入Supercalifragilisticexpealidocious

希望這會有所幫助!