迭代异构容器

时间:2016-02-24 16:53:31

标签: java generics

我正在使用类似于this one的异类容器。我可以轻松地从容器中放置和接收对象:

Favorites f = new Favorites();
f.putFavorite(String.class, "Java");
String someString = f.getFavorite(String.class);

但似乎没有简单的方法来迭代这样的容器。我可以向keySet()类添加Favorites方法,只需返回内部Map对象的密钥集:

public Set<Class<?>> keySet() {
  return favorites.keySet();
}

现在,我想遍历密钥,使用密钥获取关联的值,并在接收的对象上调用一些方法:

for (Class<?> klass : f.keySet()) {
   // f.getFavorite(klass).<SOME_METHOD_SPECIFIC_TO_THE_CLASS-KEY>
}

我以为我可以通过调用klass.cast(f.getFavorite(klass)).SOME_METHOD()来访问容器中保存的对象的方法,但它也不起作用(意思是,我无法访问除Object之外的任何方法 - 相关方法)。

让我们说,在我的用例中,我想检查我迭代的所有这些对象的接口,并相应地对检测到的接口采取行动。我们还假设我可能有几十个不同类的对象,并且它们都实现了三个接口之一。

我能想到的唯一解决方案是用几十个isinstance检查来填充我的代码,但我更喜欢一种不那么繁琐的方法(即检查给定对象是否实现了三个接口之一)。

2 个答案:

答案 0 :(得分:5)

通过尝试在每个条目上调用特定方法,您基本上是说您比编译器更了解,并且您知道每个条目都有特定的超类。

如果您知道这种情况,可以使用Class#asSubclass键入klass作为Class<? extends KnownSuper>,以便getFavorite将返回KnownSuper的子类1}}(因此公开方法):

Class<KnownSuper> superClass = KnownSuper.class; //class with callMethod()
for (Class<?> klass : f.keySet()) {
    f.getFavorite(klass.asSubClass(superClass)).callMethod()
}

但是,如果其中一个关键类没有扩展KnownSuper,这显然会产生运行时异常。因此,如果上述内容是安全的,您应该将异构容器参数化为仅接受从KnownSuper扩展的关键类。

如果并非所有条目属于此类型,您还可以在迭代时首先检查密钥是否合适:

Class<KnownSuper> superClass = KnownSuper.class; //class with callMethod()
for (Class<?> klass : f.keySet()) {
    if (superClass.isAssignableFrom(klass)) {
        f.getFavorite(klass.asSubClass(superClass)).callMethod()
    }
}

答案 1 :(得分:0)

通过这个简单的例子

假设您有以下收藏夹类定义

public class Favorites  extends HashMap<String, String> {

}

以下是测试类

public class TestGeneric {

    public static void main(String[] args) {

        Favorites  f = new Favorites();
        f.put("test", "test");

        for (String test1 : f.keySet()) {

             f.get("").charAt(index)// you will see all string specific  method as compiler knows in advance what object map going to contain


    }

}

当您将Favorites extends HashMap<String, String>更改为Favorites extends HashMap时,您将只对象特定的方法,因为编译器事先并不知道收藏夹将在地图中放入哪个对象