2013-01-02 50 views
16

是這兩個(有效)通用界限:有通用邊界「枚舉<T>與富」之間的差值「枚舉<延伸富?>」

<T extends Enum<T> & MyInterface> 
<T extends Enum<? extends MyInterface>> 

一樣嗎?


假設我有一個接口

interface MyInterface { 
    void someMethod(); 
} 

而一些枚舉實現它:

enum MyEnumA implements MyInterface { 
    A, B, C; 
    public void someMethod() {} 
} 

enum MyEnumB implements MyInterface { 
    X, Y, Z; 
    public void someMethod() {} 
} 

我想要求的實現不僅使用MyInterface而且它是一個枚舉。 「標準」 的方式是結合一個路口:

static class MyIntersectionClass<T extends Enum<T> & MyInterface> { 
    void use(T t) {} 
} 

但我發現,這也適用:

static class MyWildcardClass<T extends Enum<? extends MyInterface>> { 
    void use(T t) {} 
} 

通過以上,這編譯:

public static void main(String[] args) throws Exception { 
    MyIntersectionClass<MyEnumA> a = new MyIntersectionClass<MyEnumA>(); 
    a.use(MyEnumA.A); 
    MyWildcardClass<MyEnumB> b = new MyWildcardClass<MyEnumB>(); 
    b.use(MyEnumB.X); 
} 

而且這兩種情況下的約束按照上面的意圖和要求工作。

這兩個界限之間有什麼區別嗎?如果是這樣的話,哪一個比另一個「更好」?

+1

如果他們是真正的理智,我寧願交點,因爲它不」 t使用通配符,我個人發現「不潔」 – Bohemian

回答

4

在這個特定情況下,沒有區別,因爲枚舉形式類型參數實際上是自我類型。這是因爲一個不能枚舉繼承像這樣:

class MyEnumA extends Enum<MyEnum2> {} 
class MyEnumB implements MyInterface {} 

所以,是的,在語義上它們是相同的束縛,但只是因爲它的枚舉。

+0

+1用於回答問題的建設性部分,並且不浪費時間在「更好」的語法上,因爲它們相同。 –

+0

+1,但你也不能擴展'java.lang.Enum',可以嗎? – Saintali

1

他們會做同樣的事情,但我會說T extends Enum<? extends MyInterface>是一個更標準,因此更好,如果只是因爲它更常見和快速識別。許多人甚至不知道泛型的&部分。

你也可以爭辯說他們的讀法略有不同。 T extends Enum<T> & MyInterface我會讀作「一個枚舉,它也恰好是MyInterface。」 T extends Enum<? extends MyInterface>我會讀作「實現MyInterface的枚舉」。所以就這一點而言,這是個人喜好的問題。我更喜歡後者。

+0

-1對不起,但第一個子句後面的所有內容都是主觀的,並不具有建設性。 –

+2

@PaulBellora OP的問題包括這樣一個問題,「比另一個更好」。這本質上是一個主觀問題,因此讓人們回答這個問題似乎是不公平的。你的降薪當然是你的分配,但是我認爲你的推理會導致SO [downvotes的建議](http://stackoverflow.com/privileges/vote-down),因爲它沒有明確的或者也許是危險的不正確的,我我認爲這不是草率或不費力的擴展。 – yshavit

+0

這是我第一次貶低你,我保證我考慮過。不要拿它親自:) –

2

因爲第二個依賴於Java枚舉被實現爲MyEnum extends Enum<MyEnum>的特殊事實,所以我寧願使用第一個,它不會依賴這樣的假設並明確說明您的約束。

3

正如其他人所指出的那樣,兩種語法實現同樣的界限 - 僅僅因爲枚舉,我們知道在Enum<T>T必須立即延長enum類型的特殊情況。所以在限制什麼T可以解決,沒有區別。

There isT的可能用法的差異,但它可能是這樣一個細微差別,它是無關緊要的。考慮到下面的語句在MyIntersectionClass.use編譯但不MyWildcardClass.use

T t2 = t.getDeclaringClass().newInstance(); 

只有這將編譯後:

MyInterface t2 = t.getDeclaringClass().newInstance(); 
Enum<? extends MyInterface> t3 = t.getDeclaringClass().newInstance();