2011-06-08 79 views
3

由於密鑰持有者接口,比如以下:Java泛型:推斷和引用類的實例化使用的類

public interface KeyHolder<K extends Key> { 
    K getKey(); 
} 

我想創建這樣一個類:

public KeyHolderSet<H extends KeyHolder<K extends Key>> extends HashSet<H> { 
    public Set<K> getKeySet() { 
     Set<K> keySet = new HashSet<K>(); 
     for (H keyHolder : this) { 
      keySet.add(keyHolder.getKey()); 
     } 
     return keySet; 
    } 
} 

但是,這是行不通的,我能得到的最接近的是:

public KeyHolderSet<H extends KeyHolder<? extends Key>> extends HashSet<H> { 
    public <K extends Key> Set<K> getKeySet() { 
     Set<K> keySet = new HashSet<K>(); 
     for (H keyHolder : this) { 
      // Explicit cast to K 
      keySet.add((K)keyHolder.getKey()); 
     } 
     return keySet; 
    } 
} 

任何方法都可以解決這個問題嗎?

回答

2

你需要把它寫這樣的:

public KeyHolderSet<K extends Key, H extends KeyHolder<K>> extends HashSet<H> { 
    public Set<K> getKeySet() { 
     ... 
    } 
} 

不幸的是,你必須首先聲明K的類型,它無法推斷。

+0

AARGH,是的,我應該補充說,作爲另一種選擇,但它是令人眼花繚亂的痛苦必須單獨申報重點:( – Zecrates 2011-06-08 16:48:43

+0

另一種選擇是使用通配符界('?延伸...' ),但你最終會添加禁止警告,以檢查未經檢查的轉換... – Finbarr 2011-06-08 22:57:18

+0

嗨Finbarr,請你提供一個例子,你的意思是使用有界通配符嗎?它不同於我的第二個解決方案嗎? – Zecrates 2011-06-09 05:17:11

1

也許

public class KeyHolderSet<K extends Key, H extends KeyHolder<K>> extends 
     HashSet<H> { 
    public Set<K> getKeySet() { 
     ... 
    } 
} 

,如果你不介意的參數化KeyHolderSet兩次。

3

假設實現類存儲在一組密鑰持有者並不重要,你可以嘗試這樣的事:

public class KeyHolderSet<K extends Key> extends HashSet<KeyHolder<K>> { 
    public Set<K> getKeySet() { 
     ... 
    } 
} 
+0

謝謝塞巴斯蒂安。不幸的是,在我的情況下,KeyHolder的實現很重要,但希望這種解決方案可以爲其他人服務。 – Zecrates 2011-06-09 05:15:57

0

鑑於KeyHolder<K extends Key>似乎沒有必要使用KeyHolderSet<H extends KeyHolder<K extends Key>>只是堅持:

public class KeyHolderSet<H extends KeyHolder<?>> 

你應該沒問題。

編輯:我看到你的問題getKeySet()。這個方法應該返回H而不是K. H將被輸入你在KeyHolderSet(變量,而不是類)聲明中輸入的內容。

public class KeyHolderSet<H extends KeyHolder<?>> extends HashSet<H> { 

    private H theKeySet; 

    public void setKeySet(H keyset) { 
    theKeySet = keyset; 
    } 

    public H getKeySet() { 
    return theKeySet; 
    } 
} 

-

class betterKey extends Key { 
} 

-

public static void main(String[] args) { 
    KeyHolder<betterKey> kh = new KeyHolder<betterKey>() { 
    }; 
    KeyHolderSet<KeyHolder<betterKey>> khs = new KeyHolderSet<KeyHolder<betterKey>>(); 
    khs.setKeySet(kh); 

    KeyHolder<Key> kh2 = khs.getKeySet(); // Type mismatch 
    } 

正如你可以看到khs.getKeySet()回報KeyHolder<betterKey>預期。

EDIT2: 你可以建立起來的一套KeyHolderSet類的外部:

public static void main(String[] args) { 
    KeyHolderSet<KeyHolder<betterKey>> khs = new KeyHolderSet<KeyHolder<betterKey>>(); 
    Set<betterKey> bks = new HashSet<betterKey>(); 
    for (KeyHolder<betterKey> kh : khs) { 
     bks.add(kh.getKey()); 
    } 
    } 

一個替代的解決方案,我想出了返回一個完全通用的設置,記住所有類型檢查會丟失這種方式。

public class KeyHolderSet<H extends KeyHolder<?>> extends HashSet<H> { 
    public <K extends Key> Set<K> getKeySet() { 
    Set<K> s = new HashSet<K>(); 
    for (H keyHolder : this) { 
     s.add((K) keyHolder.getKey()); // Unchecked cast 
    } 
    return s; 
    } 

    public static void main(String[] args) { 
    KeyHolderSet<KeyHolder<betterKey>> khs = new KeyHolderSet<KeyHolder<betterKey>>(); 
    Set<Key> ks = khs.getKeySet(); // No problem 
    Set<betterKey> bks = khs.getKeySet(); // No problem 
    Set<evenBetterKey> ss = khs.getKeySet(); // No problem 
    } 
} 

class betterKey implements Key { 
} 

class evenBetterKey extends betterKey { 
} 
+0

嗨Dorus。也許意圖不明確。我不希望getKeySet返回一個KeyHolder,我期望它返回一個Set 。我已經更新了這個問題,以清楚地表明預期的行爲。 – Zecrates 2011-06-09 05:11:56

+0

我唯一能想到的就是返回Set ,然後在集合中的項目上調用getKey。建立一個集合時可能。我更新我的答案,但我懷疑這是你在找什麼。 – Dorus 2011-06-10 09:17:04

+0

我意識到返回一個'Set '沒有用處,這正是'KeyHolderSet >'本身。你可以遍歷它並檢索Keys。但是我不能把它放在一個返回正確類型的函數中。 – Dorus 2011-06-10 09:32:29