2011-03-05 59 views
77

我想知道什麼是以下兩個方法聲明之間的區別:Java泛型牛逼VS對象

public Object doSomething(Object obj) {....} 

public <T> T doSomething(T t) {....} 

有什麼你可以/將與一個做而不是其他?我在這個網站的其他地方找不到這個問題。

回答

65

從上下文分離 - 沒有區別。在tobj上,您只能調用Object的方法。

但與語境 - 如果你有一個泛型類:

MyClass<Foo> my = new MyClass<Foo>(); 
Foo foo = new Foo(); 

然後:

Foo newFoo = my.doSomething(foo); 

相同的代碼與對象

Foo newFoo = (Foo) my.doSomething(foo); 

兩個優點:

  • 不需要鑄造(編譯器隱藏了這個)
  • 編譯時間安全性有效。如果使用Object版本,則不能確定該方法始終返回Foo。如果它返回Bar,則在運行時您將擁有ClassCastException
1

你不需要做額外的類轉換。在第一種情況下,你總是會得到一個類java.lang.Object的對象,你需要將它轉換爲類。在第二種情況下,T將替換爲通用簽名中定義的類,不需要類別轉換。

2

在運行時,什麼都沒有。但是在編譯時,第二個會執行類型檢查,以確保參數的類型和返回值的類型匹配(或者是子類型),無論T類型解析爲什麼類型(第一個示例也進行類型檢查,但每個對象都是Object的子類型,因此每個類型都將被接受)。

2

T是一個通用類型。這意味着它可以在運行時被任何合格的對象替代。您可以按照以下方式調用該方法:

String response = doSomething("hello world");

OR

MyObject response = doSomething(new MyObject());

OR

Integer response = doSomething(31);

正如你所看到的,有多態性在這裏。

但是,如果它被聲明爲返回對象,你不能這樣做,除非你輸入的東西。

7

這裏的區別在於,第一,我們指定調用者必須傳遞一個Object實例(任何類),並且它將取回另一個Object(任何類,不一定是相同類型)。

在第二,正如所定義的類時,鑑於返回將是相同的類型的類型。

Example ex = new Example<Integer>(); 

這裏我們指定什麼類型的T將允許我們對類或方法實施更多的約束。例如,我們可以實例化一個LinkedList<Integer>LinkedList<Example>,我們知道當我們調用其中一個方法時,我們將返回一個Integer或Example實例。

主要在這裏的目標是調用代碼可以指定什麼類型的對象的類將在運行,而不是依賴型鑄造強制執行此。

Java Generics *從Oracle。

*更新的鏈接。

0
在第一種情況下

它需要的任何類型的e.g.string的參數,並且返回一個類型FOO。在第二種情況下,它採用foo類型的參數並返回foo類型的對象。

5

不同的是,與一般的方法我不需要投,我得到一個編譯錯誤,當我做錯了:

public class App { 

    public static void main(String[] args) { 

     String s = process("vv"); 
     String b = process(new Object()); // Compilation error 
    } 

    public static <T> T process(T val) { 

     return val; 
    } 
} 

使用對象,我總是需要強制轉換,我沒有得到任何錯誤,當我做錯了:

public class App { 

    public static void main(String[] args) { 

     String s = (String)process("vv"); 
     String b = (String)process(new Object()); 
    } 

    public static Object process(Object val) { 

     return val; 
    } 
}