1

Can someone explain me, why this cast is unchecked. It should be guaranteed that type T is always derived from Base and so the cast from T to Base should not be unchecked.

abstract class Base
{
    private static final Map<Class<? extends Base>, Consumer<Base>> _CONSUMERS = new HashMap<>();

    @SuppressWarnings( "unchecked" )
    public static <T extends Base> void addConsumer( Class<T> clazz, Consumer<T> consumer )
    {
        _CONSUMERS.put( clazz, (Consumer<Base>) consumer );
    }
}
DaRich
  • 937
  • 8
  • 13

1 Answers1

1

The type of consumer is Consumer<T> = Consumer<? extends Base>, while the put expects a Consumer<Base>.

You should probably declare your _CONSUMERS map as of type:

Map<Class<? extends Base>, Consumer<? extends Base>>

Java does not recognize situations where objects of type X<? extends T> (or X<? super T>) can be used in place of X<T>, you have to explicitly indicate type bounds (see here a more thorough discussion about this).

Community
  • 1
  • 1
rrobby86
  • 1,356
  • 9
  • 14
  • I adopted your answer, and now the the put has no more warnings, but when I want to call the consumer, I have to do an unchecked cast `Consumer consumer = (Consumer) _CONSUMERS.get( Concrete.class );`. Otherwise I can not call `accept`. – DaRich Mar 31 '17 at 02:52
  • I forgot... if you are dealing with a `java.util.function.Consumer` (or something similar in concept), I think you should use ` super Base>` in place of than ` extends Base>`: this should let you retrieve a `Consumer super Base>` and call its `accept` method with a `Base`-typed argument without any casting – rrobby86 Mar 31 '17 at 10:32
  • Thank you for your proposal, but I was incapable of solving the problem with `super` and without a suppression of warnings. – DaRich Apr 10 '17 at 08:01