随着泛型的引入,我不愿意尽可能地执行instanceof或者casting。但在这种情况下,我没有看到解决方法:
for (CacheableObject<ICacheable> cacheableObject : cacheableObjects) {
ICacheable iCacheable = cacheableObject.getObject();
if (iCacheable instanceof MyObject) {
MyObject myObject = (MyObject) iCacheable;
myObjects.put(myObject.getKey(), myObject);
} else if (iCacheable instanceof OtherObject) {
OtherObject otherObject = (OtherObject) iCacheable;
otherObjects.put(otherObject.getKey(), otherObject);
}
}
在上面的代码中,我知道我的ICacheables应该只是MyObject或OtherObject的实例,并且根据这一点,我想将它们放入2个单独的映射中,然后再进行一些处理。
如果没有我的检查实例,我还有其他方法可以做到这一点。
由于
答案 0 :(得分:2)
您可以使用双重调用。没有承诺它是一个更好的解决方案,但它是另一种选择。
import java.util.HashMap;
public class Example {
public static void main(String[] argv) {
Example ex = new Example();
ICacheable[] cacheableObjects = new ICacheable[]{new MyObject(), new OtherObject()};
for (ICacheable iCacheable : cacheableObjects) {
// depending on whether the object is a MyObject or an OtherObject,
// the .put(Example) method will double dispatch to either
// the put(MyObject) or put(OtherObject) method, below
iCacheable.put(ex);
}
System.out.println("myObjects: "+ex.myObjects.size());
System.out.println("otherObjects: "+ex.otherObjects.size());
}
private HashMap<String, MyObject> myObjects = new HashMap<String, MyObject>();
private HashMap<String, OtherObject> otherObjects = new HashMap<String, OtherObject>();
public Example() {
}
public void put(MyObject myObject) {
myObjects.put(myObject.getKey(), myObject);
}
public void put(OtherObject otherObject) {
otherObjects.put(otherObject.getKey(), otherObject);
}
}
interface ICacheable {
public String getKey();
public void put(Example ex);
}
class MyObject implements ICacheable {
public String getKey() {
return "MyObject"+this.hashCode();
}
public void put(Example ex) {
ex.put(this);
}
}
class OtherObject implements ICacheable {
public String getKey() {
return "OtherObject"+this.hashCode();
}
public void put(Example ex) {
ex.put(this);
}
}
这里的想法是 - 而不是强制转换或使用instanceof
- 而是调用iCacheable
对象的.put(...)
方法,该方法将自身传递回Example
对象的重载方法。调用哪种方法取决于该对象的类型。
另见Visitor pattern。我的代码示例闻起来是因为ICacheable.put(...)
方法不完整 - 但使用访问者模式中定义的接口可以清除这种气味。
this.put(iCacheable)
类调用Example
?在Java中,覆盖总是在运行时绑定,但重载稍微复杂一点:动态调度意味着将在运行时选择方法的实现,但方法的签名仍然在编译时确定。 (查看Java Language Specification, Chapter 8.4.9了解更多信息,并查看益智广告“制作哈希”(第37页){C. 3}}。
答案 1 :(得分:1)
是否无法将每个地图中的缓存对象合并为一个地图?它们的键可以将它们分开,这样您就可以将它们存储在一个地图中。如果你做不到那么你可以有一个
Map<Class,Map<Key,ICacheable>>
然后这样做:
Map<Class,Map<Key,ICacheable>> cache = ...;
public void cache( ICacheable cacheable ) {
if( cache.containsKey( cacheable.getClass() ) {
cache.put( cacheable.getClass(), new Map<Key,ICacheable>() );
}
cache.get(cacheable.getClass()).put( cacheable.getKey(), cacheable );
}
答案 2 :(得分:0)
您可以执行以下操作:
ICachableInterface
接口添加一个方法,该方法将处理将对象放入两个地图中的一个,作为方法的参数给出。instanceof
个检查,并使用对步骤1中定义的新方法的调用替换put
方法。然而,这不是一个好的设计,因为如果你有另一个实现这个接口的类和第三个地图,那么你需要将另一个Map传递给你的新方法。