Java泛型:推断和引用类的实例化使用的类

问题描述:

由于密钥持有者接口,比如以下: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; 
    } 
} 

任何方法都可以解决这个问题吗?

你需要把它写这样的:

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

也许

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

,如果你不介意的参数化KeyHolderSet两次。

假设实现类存储在一组密钥持有者并不重要,你可以尝试这样的事:

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

谢谢塞巴斯蒂安。不幸的是,在我的情况下,KeyHolder的实现很重要,但希望这种解决方案可以为其他人服务。 – Zecrates 2011-06-09 05:15:57

鉴于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