将通用类型添加到EnumMap

时间:2015-04-14 19:20:42

标签: java

我正在尝试将实例添加到以下EnumMap中:

class ActiveG<D extends GData, T extends GTemplate> {

    EnumMap<GStateType, GState<ActiveG<D,T>> map;
    ..
    ..
}

class TGData extends GData {...}
class TGTemplate extends GTemplate {....}

class ActiveTG extends ActiveG<TGData, TGTemplate> {

    // fails with compilation error
    super.states.put(GStateType.WAITING, new TGWaitingState<ActiveTG>(this));
    ...
    ...
}

我得到的错误:

The method put(GStateType, GState<ActiveG<TGData,TGTemplate>>) in the
type EnumMap<GStateType,GState<ActiveG<TGData,TGTemplate>>> is not 
applicable for the arguments (GStateType, TGWaitingState<ActiveTG>)

任何人都可以尝试帮助我弄清楚缺少什么让它起作用吗? 谢谢!

1 个答案:

答案 0 :(得分:1)

简而言之,Java中的泛型不是协方差。

e.g。如果你有

class Parent {...}

class Child extends Parent {...}

Foo<Child>不是Foo<Parent>

回到你的代码:

ActiveTG中的枚举地图需要GState<ActiveG<TGData,TGTemplate>>作为值,但您要给它TGWaitingState<ActiveTG>,这是GState<ActiveTG>

虽然ActiveTGActiveG<TGData,TGTemplate>,但GState<ActiveTG>不是GState<ActiveG<TGData,TGTemplate>>

为了解决这个问题,你需要在类型参数上做一些改变,比如

class ActiveG<D extends GData, 
              T extends GTemplate, 
              E extends ActiveG<D,T>> {
     EnumMap<GStateType, GState<E>> map;
}

或仅使map类型为EnumMap<GStateType, GState<? extends ActiveG<D,T>>。在某些情况下,这可能效果不佳,例如,您需要将结果检索为GState<ActiveTG>而不是GState<ActiveG<D,T>>