2011-08-04 161 views
2

在簽名表達<T extends Comparable<T>>「<T extends Comparable <T>>」和「<T extends Comparable <Comparable <T> >>」之間的區別?

public static <T extends Comparable<T>> foo(T x) { ... } 

T描述遞歸取決於Comparable<T>

如果T延伸Comparable<T>Comparable<T>延伸Comparable<Comparable<T>>,是不是遵循T延伸Comparable<Comparable<T>>

IOW,是extends的關係傳遞?

如果是這樣,爲什麼不等同於

public static <T extends Comparable<T>> int compare(T x, T y) { 
    return x.compareTo(y); 
} 

public static <T extends Comparable<Comparable<T>>> int compare(T x, T y) { 
    return x.compareTo(y); 
} 

?事實上,最後的定義編譯,而它上面的一個無法編譯,並顯示錯誤

comp.java:7: compareTo(java.lang.Comparable<T>) in 
java.lang.Comparable<java.lang.Comparable<T>> cannot be applied to (T) 
      return x.compareTo(y); 

謝謝!

+0

我認爲你有一個語法錯誤'可比>'應該是'可比>' – dfb

回答

1

要記住的根本問題是Java泛型的範圍是編譯單元和編譯時間。 它只是語法糖!(多少次我忘記了這一點,並最終推理正是這樣做的方式,彷彿 Java泛型其實隱含通用類型系統在運行時

the spec

The scope of a class' type parameter is the entire declaration of the class 
including the type parameter section itself. 

Therefore, type parameters can appear as parts of their own bounds, or as 
bounds of other type parameters declared in the same section. 

沒有遞歸,也沒有定義新的類型。

機智:

package so_6949760; 

import java.util.HashMap; 

public class SweetCompilingGenerics { 

    @SuppressWarnings("serial") 
    public static class Sweet<X> extends HashMap<X, Sweet<X>> {} 

    public static void main(String[] args) { 
     Sweet<String> sweetStr = new Sweet<String>(); 
     Sweet<Sweet<Integer>> whatever = new Sweet<SweetCompilingGenerics.Sweet<Integer>>(); 

     assert sweetStr.getClass().equals(whatever.getClass()) : "who made generics a runtime mechanism?"; 
     assert sweetStr.getClass() == whatever.getClass() : "who made generics a runtime mechanism?"; 

     System.out.format("Is %s a Sweet<String> ?\n", sweetStr.getClass().getCanonicalName()); 
     System.out.format("Is %s a Sweet<Sweet<Integer>> ?\n", whatever.getClass().getCanonicalName()); 
    } 
} 

將輸出甜祕密:

Is so_6949760.SweetCompilingGenerics.Sweet a Sweet<String> ? 
Is so_6949760.SweetCompilingGenerics.Sweet a Sweet<Sweet<Integer>> ? 

我會很期待提供一個建議,一個老鄉怪胎? 請務必閱讀說明書

[帖子接受編輯]:剛剛發現這個highly informative article by IBM。這非常符合OP的所有問題。 (推薦的)。

+0

感謝很有啓發的響應;你對規範的建議是有針對性的,而且這通常是我所做的,但在這種情況下,我不明白規範(即你所引用的內容)的含義。未註釋的規格有時可能接近無用。我在運行時得到了有關參數信息丟失的部分(例如代碼中的assert),但我仍不明白爲什麼'extends'關係不是傳遞的,而'isAssignableFrom因爲我認爲前者意味着後者... – kjo

+0

另外,通過「語法糖」,我理解爲一種「方便但無關緊要的簡寫」,它總是可以由一個(可能更麻煩的)表達式替換「基本」的句法成分。如果這或多或少是您將泛型描述爲「語法糖」時所考慮的,那麼它的糖是什麼?即什麼是相應的去糖語法? – kjo

+1

@kjo:在'類型擦除'上進行閱讀。 'Foo afoo =(Foo)list.get(n);'將是最終結果,但是當然涉及編譯器和類型系統(@compile time),所以它不僅僅是文本替換。當然聽到你的規格,特別是有關部分。但是請注意,「討論」部分是元討論(ala「註釋」),並且能夠很好地消除最初的錯誤想法,例如該運行時代碼的代碼段非常豐富,不是嗎? – alphazero

1

Comparable<T> extends Comparable<Comparable<T>>

也許我誤會你是什麼輸送的關係,但這種說法是不真實的。 Comparable<T>不包含任何內容。

1

沒有什麼特別之處

<T extends Comparable<T>> 

考慮

public class Foo implements Comparable<Foo>{ 
    int compareTo(Foo x); 
} 

我甚至不認爲我們可以說,它的遞歸定義,它只是自我指涉。

4

我想這裏你做了一個錯誤的邏輯跳轉。

T extends Comparable<T> 

暗示

Comparable<T> extends Comparable<Comparable<T>> 

短比喻

假設一個岩石破碎機是可以粉碎岩石任何材料,並搖滾只是碰巧能夠粉碎自己。所以搖滾是一個搖滾破碎機。這是否意味着岩石可以粉碎任何能夠壓碎岩石的物質?顯然不是:也可能是岩石破碎機,而岩石可能不會粉碎鋼。


龍(碼型)類比

假設我有一個接口,Additive<T>,其可以用於描述任何類型的,其可能會一個T對象進行add操作和找回T

現在,讓我們說,我有其簽名看起來像這樣一些方法:

public static <T extends Additive<T>> add(T x, T y) { ... } 

由於x必須是一個類型的,而我可以添加一個T,這種方法可以實現如下:

return x.add(y); 

有意義嗎?太好了;但現在讓我們假設你已經在你的問題中作出了這樣的假設:Additive<T>必須延伸Additive<Additive<T>>;如果是這種情況,那麼我可以假設我可以添加到x的實例任何類型實現Additive<T>

這是假設失效的地方。我可能有一個類型,說...

// A 32-bit integral number supporting addition 
public class Int32 implements Additive<Int32> { ... } 

這將是有道理的,對嗎?我也能有這樣的事情:

// A list of 32-bit integral numbers supporting appending 
public class Int32List implements Additive<Int32> { ... } 

現在,如果T extends Additive<T>暗示Additive<T> extends Additive<Additive<T>>那麼我應該能夠做到這一點:

Additive<Int32> x = new Int32(5); 
Additive<Int32> y = x.add(new Int32List()); 

這有任何意義嗎?

+0

尼斯類比瓦特/岩石.. – dfb

+0

@Kevin:謝謝你的更正:) –

0

Comparable<T>不延長Comparable<Comparable<T>>以同樣的方式(只是因爲T延伸Comparable<T>),其List<String>不擴展List<Object>(只是因爲String延伸Object)。

請參閱Oracle的this document以瞭解有關泛型和繼承的更多信息。

相關問題