简体   繁体   English

访问存储在Map中的Java泛型

[英]Accessing a Java generics stored in a Map

I'm trying to access a custom Java generic stored in a map as below. 我正在尝试访问存储在地图中的自定义Java通用,如下所示。
Unfortunately I get a type mis-match error. 不幸的是我得到了类型错误匹配错误。
Now, I can cast it to the type I want because but this seems messy to me. 现在,我可以将它转换为我想要的类型,但这对我来说似乎很混乱。
Is there a clean way of doing the assignment? 有没有干净的工作方式?
Thanks 谢谢

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);
        }
    }
}

Because the return type of get() is a BusinessRuleSuite<? extends BusinessObject> 因为get()的返回类型是BusinessRuleSuite<? extends BusinessObject> BusinessRuleSuite<? extends BusinessObject> . BusinessRuleSuite<? extends BusinessObject>

This means it will accept anything that inherits from BusinessObject during put() . 这意味着它将接受在put()期间从BusinessObject继承的任何内容。 But when you use it on the right hand side of an assign, Java can't make assumptions. 但是当你在赋值的右侧使用它时,Java无法做出假设。 It has to play safe, so the get() behaves as if you had used BusinessRuleSuite<BusinessObject> (without the extends ). 它必须安全,所以get()行为就像你使用了BusinessRuleSuite<BusinessObject> (没有extends )。

There are two ways to achieve what you want: 有两种方法可以达到你想要的效果:

  1. Use BusinessRuleSuite<SalesItemA> in the map declaration 在地图声明中使用BusinessRuleSuite<SalesItemA>

  2. Use a cast 使用演员

because businessRules is a 因为businessRules是一个

private final Map<Class<? extends BusinessObject>, BusinessRuleSuite<? extends BusinessObject>> businessRules

so instead of 而不是

BusinessRuleSuite<SalesItemA> p = this.businessRules.get(sia.getClass());

do

BusinessRuleSuite<? extends BusinessObject> p = this.businessRules.get(sia.getClass());

the Map places no garuantees that for each key ( Class<K> , BusinessRuleSuite<V> ), K=V , which i assume is true in your code. Map没有为每个密钥( Class<K>BusinessRuleSuite<V> ), K=V服务员,我认为你的代码是真的。

alternatively: 或者:

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);
  }
}

It looks like you are trying to create a single SalesProcessor class, and change its processItem method to accept any implementation of BusinessObject . 看起来您正在尝试创建单个SalesProcessor类,并更改其processItem方法以接受BusinessObject任何实现。

Neal Gafter tried to make this work by using a "super type tokens" to expand Josh Block's "typesafe heterogenous container" pattern, but it has some flaws . Neal Gafter试图通过使用“超级型代币”来扩展Josh Block的“类型安全的异类容器”模式, 但它有一些缺陷

Your map does not contain items of type SalesItemA but of type <? 您的地图不包含SalesItemA类型的项目,但类型为<? extends BusinessObject> 扩展BusinessObject>

change 更改

BusinessRuleSuite<SalesItemA> p = this.businessRules.get(sia.getClass());

to

BusinessRuleSuite<BusinessRuleSuite<? extends BusinessObject>> p = this.businessRules.get(sia.getClass());

... not actually tested, so this might not work at all. ......没有经过实际测试,所以这可能根本不起作用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM