Java集合 - 对元素的多态访问

时间:2013-11-13 05:44:51

标签: java collections polymorphism

我有 ThisType LinkedHashSet 值。 ThisType 正在实施 ThatType 界面。

我需要对此集合进行多态使用 - 能够将其指向 LinkedHashSet< ThatType>。

这是怎么做到的?

我知道这是一个天真的问题,但我试过的几件事情都行不通,我想以正确的方式做。

提前致谢。

// ==============================

更新:更多详情:

在以下代码中, ThisType 实现 ThatType - ThatType 是一个界面。

//LinkedHashMap<Integer, ? extends ThatType> theMap = new LinkedHashMap<>();
LinkedHashMap<Integer, ThisType> theMap = new LinkedHashMap<>();
for (Integer key:intArray)  {
    ThisType a = new ThisType();
    if (theMap.containsKey(key))  {
        a = theMap.get(key);    
        a.doStuff();
    } else {
        a.doOtherStuff();
    }
    theMap.put(key, a);
}

最后,我想将 theMap 作为 ThatType **的集合返回,而不是** ThisType

这就是连锁被打破的地方。使用注释行(第一行)进行声明会在 put()&amp;上给出类型不匹配错误哈希的 get()方法。

不确定这是否重要 - 但是, 我将结果返回为 LinkedHashSet&lt; ThatType&gt; 。我正在从 LinkedHashMap 转换为 LinkedHashSet 。但是,对于映射或集合中的集合值的多态引用没有任何作用。到目前为止,我在所有这些操作中使用的所有和唯一类型是 ThisType ThatType 在我尝试的任何地方都给了我一些错误。

3 个答案:

答案 0 :(得分:2)

我认为你想要的是使用通配符。

 LinkedHashSet<? extends ThatType> someFunction(LinkedHashSet<? extends ThatType> set) {
      return set;
 }

正如其他地方所解释的那样LinkedHashSet<ThisType>不是LinkedHashSet<ThatType>的子类,因为LinkedHashSet<ThisType>无法接受ThatType个对象。

LinkedHashSet<? extends ThatType>中的通配符表示某个类的LinkedHastSet(不确定是什么)延伸ThatType

虽然你可能想考虑使用它:

 Set<? extends ThatType> someFunction(Set<? extends ThatType> set) {
      return set;
 }

答案 1 :(得分:1)

当您在

中声明通配符有界类型参数时
LinkedHashMap<Integer, ? extends ThatType> theMap = new LinkedHashMap<>();

您告诉编译器类型参数可以是ThatType子类型的任何类。想象一下这个案例

LinkedHashMap<Integer, ? extends ThatType> theMap = getLinkedHashMap();

其中getLinkedHashMap()定义为

public LinkedHashMap<Integer, OtherType /* which implements ThatType */> getLinkedHashMap();

之前的分配可行,因为OtherTypeThatType的子类型。但是,你不能指望

ThisType a = theMap.get(key);

上班。由于通配符,您只知道地图肯定包含ThatType个实例(称为上限),但它们可以是OtherType或{{1}类型}(或ThatType的其他子类型)。你最多可以做到

ThatType

转换返回值,但随后您将自己打开ThisType a = (ThisType) theMap.get(key);

同样,您无法使用ClassCastException以外的任何内容来呼叫put()

null

编译器不允许您添加任何内容,因为它无法保证地图包含的内容,因为通配符绑定。但是null can be used because

  

null引用总是可以进行扩展引用转换   任何参考类型。

所以theMap.put(someInt, null); // will compile theMap.put(someInt, new ThisType()); // will not compile theMap.put(someInt, new OtherType()); // will not compile 是一个有效的参数,因为它是the lower bound of the wildcard


您处于一种特殊情况,看起来您的方法会在内部创建null并且您知道将要传递给它的内容。因此,您可以执行以下操作

LinkedHashMap

由于public static LinkedHashMap<Integer, ThatType> getTheSet(int[] intArray) { LinkedHashMap<Integer, ThatType> theMap = new LinkedHashMap<>(); for (Integer key : intArray) { ThisType a = new ThisType(); if (theMap.containsKey(key)) { a = (ThisType) theMap.get(key); // cast it because you know they will definitely be `ThisType` references a.doStuff(); } else { a.doOtherStuff(); } theMap.put(key, a); } return theMap; } ThisType的子类型,因此您可以将ThatType的实例放入地图中。您需要注意如何使用此方法的返回值。所有编译器都知道返回值是它包含ThisType个引用。它不知道它们实际上是ThatType

答案 2 :(得分:0)

您需要Set<? super ThisType>的通配符。请看下面的例子

public static void main(String[] args) {
    Set<ThatType> set=new LinkedHashSet<>();
    Set<ThisType> set2=new LinkedHashSet<>();

    someFunction(set);
    someFunction(set2);
}

static void someFunction(Set<? super ThisType> set) {

}

class ThisType implements ThatType{

}
interface ThatType{

}