0

I'm trying to add instances to the following 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 error I get:

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

Can anyone try to help me figure out what's missing to make it work?? Thanks!

3
  • 1
    EnumMap<Long, ...>? What are you trying to do? Do you have some enum Long {} somewhere or are you trying to use java.lang.Long as a key in an EnumMap? Actually the code example doesn't make any sense because you are calling super.states.put but you've shown us the declaration for EnumMap<...> map. Please clarify and post correct code that reproduces the error. stackoverflow.com/help/mcve Commented Apr 14, 2015 at 19:23
  • Sure...your map is not a GStateType, TGWaitingState<ActiveTG> type :). You've defined your map as a Long, GState<...>, where's GStateType and what is TGWaitingState<> ? Commented Apr 14, 2015 at 20:08
  • Sorry, did a bad copy paste - look at it now. by the way, TGWaitingState inherits GState. Commented Apr 15, 2015 at 0:52

1 Answer 1

1

In brief, Generics in Java is not covariance.

e.g. if you have

class Parent {...}

class Child extends Parent {...}

Foo<Child> is NOT a Foo<Parent>

Go back to your code:

your enum map in ActiveTG is expecting GState<ActiveG<TGData,TGTemplate>> as value, but you are giving it a TGWaitingState<ActiveTG>, which is a GState<ActiveTG>.

Although ActiveTG is-a ActiveG<TGData,TGTemplate>, GState<ActiveTG> is NOT a GState<ActiveG<TGData,TGTemplate>>.

In order to solve it, you will need quite some change in the type params, like

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

or simply make map with type EnumMap<GStateType, GState<? extends ActiveG<D,T>>. This may not work very well in some situation, for example, you need to retrieve the result as a GState<ActiveTG> instead of GState<ActiveG<D,T>>

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for the detailed answer!! I learned something new from you !

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.