[英]Accessing a Java generics stored in a Map
我正在尝试访问存储在地图中的自定义Java通用,如下所示。
不幸的是我得到了类型错误匹配错误。
现在,我可以将它转换为我想要的类型,但这对我来说似乎很混乱。
有没有干净的工作方式?
谢谢
public interface BusinessObject {
}
public class SalesItemA implements BusinessObject {
}
public interface BusinessRuleSuite<T extends BusinessObject> {
public void fire(T shell);
}
public abstract class BusinessRuleSuiteCommon<T extends BusinessObject>
implements BusinessRuleSuite<T> {
public synchronized void fire(T bo) {
// do something with bo;
}
}
public class SalesBusinessRuleSuite extends
BusinessRuleSuiteCommon<SalesItemA> {
}
public class SalesProcessor {
private final Map<Class<? extends BusinessObject>, BusinessRuleSuite<? extends BusinessObject>> businessRules;
public SalesProcessor(Map<Class<? extends BusinessObject>, BusinessRuleSuite<? extends BusinessObject>> businessRules) {
this.businessRules = businessRules;
}
public void processItem(SalesItemA sia) {
/// This assignment doesn't work??? Why?
BusinessRuleSuite<SalesItemA> p = this.businessRules.get(sia.getClass());
p.fire(sia);
}
}
}
因为get()
的返回类型是BusinessRuleSuite<? extends BusinessObject>
BusinessRuleSuite<? extends BusinessObject>
。
这意味着它将接受在put()
期间从BusinessObject
继承的任何内容。 但是当你在赋值的右侧使用它时,Java无法做出假设。 它必须安全,所以get()
行为就像你使用了BusinessRuleSuite<BusinessObject>
(没有extends
)。
有两种方法可以达到你想要的效果:
在地图声明中使用BusinessRuleSuite<SalesItemA>
使用演员
因为businessRules是一个
private final Map<Class<? extends BusinessObject>, BusinessRuleSuite<? extends BusinessObject>> businessRules
而不是
BusinessRuleSuite<SalesItemA> p = this.businessRules.get(sia.getClass());
做
BusinessRuleSuite<? extends BusinessObject> p = this.businessRules.get(sia.getClass());
Map
没有为每个密钥( Class<K>
, BusinessRuleSuite<V>
), K=V
服务员,我认为你的代码是真的。
public class RuleProcessor<T extends BusinessObject> {
private final Map<Class<T>, BusinessRuleSuite<T>> businessRules;
public SalesProcessor(Map<Class<T>, BusinessRuleSuite<T>> businessRules) {
this.businessRules = businessRules;
}
// - or have a blank constructor, and add them one by one
public void add(Class<T> c, BusinessRuleSuite<T> rs) {
businessRules.add(c, rs);
}
public void processItem(T sia) {
BusinessRuleSuite<T> p = this.businessRules.get(sia.getClass());
p.fire(sia);
}
}
看起来您正在尝试创建单个SalesProcessor
类,并更改其processItem
方法以接受BusinessObject
任何实现。
Neal Gafter试图通过使用“超级型代币”来扩展Josh Block的“类型安全的异类容器”模式, 但它有一些缺陷 。
您的地图不包含SalesItemA类型的项目,但类型为<? 扩展BusinessObject>
更改
BusinessRuleSuite<SalesItemA> p = this.businessRules.get(sia.getClass());
至
BusinessRuleSuite<BusinessRuleSuite<? extends BusinessObject>> p = this.businessRules.get(sia.getClass());
......没有经过实际测试,所以这可能根本不起作用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.