我正在使用类似于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
检查来填充我的代码,但我更喜欢一种不那么繁琐的方法(即检查给定对象是否实现了三个接口之一)。
答案 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
时,您将只对象特定的方法,因为编译器事先并不知道收藏夹将在地图中放入哪个对象