迭代异构容器

Woj*_*zak 6 java generics

我正在使用类似于这个的异构容器.我可以轻松地从容器中放置和接收对象:

Favorites f = new Favorites();
f.putFavorite(String.class, "Java");
String someString = f.getFavorite(String.class);
Run Code Online (Sandbox Code Playgroud)

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

public Set<Class<?>> keySet() {
  return favorites.keySet();
}
Run Code Online (Sandbox Code Playgroud)

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

for (Class<?> klass : f.keySet()) {
   // f.getFavorite(klass).<SOME_METHOD_SPECIFIC_TO_THE_CLASS-KEY>
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

Mar*_*ers 5

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

如果你知道的话,你可以使用Class#asSubclass输入klassClass<? extends KnownSuper>使getFavorite然后将返回的一个子类KnownSuper(并因此暴露方法):

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

但是,如果其中一个键类没有扩展,这显然会产生运行时异常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()
    }
}
Run Code Online (Sandbox Code Playgroud)