'How can I avoid unchecked cast with generics like this?

I have defined a executor like this:

public interface StageExecutor<E extends Enum<E>, M extends Message<M>, S extends Stage<E, M>> {
    /**
     * Execute stage.
     * @param stage stage to be executed.
     * @param input input to the executor.
     * @return stage output.
     */
    M execute(S stage, M input);
}

and then I have a method to register stage executors:

public class StageExecutionFactory {
    /**
     * No instantiation.
     */
    private StageExecutionFactory() {}

    private static final Map<Class<? extends Stage<?, ?>>, StageExecutor<?, ?, ?>> EXECUTORS = Maps.newHashMap();

    public static <E extends Enum<E>, M extends Message<M>, S extends Stage<E, M>> void register(
        Class<S> clazz, StageExecutor<E, M, S> executor) {

        EXECUTORS.put(clazz, executor);
    }

}

Then I guess the generics correlation between the clazz and executor is lost when I put them into the map which leads to the unchecked cast warning when I do this:

public class StageExecutionFactory {
    ...

    public static <E extends Enum<E>, M extends Message<M>, S extends Stage<E, M>> void register(
        Class<S> clazz, StageExecutor<E, M, S> executor) {

        EXECUTORS.put(clazz, executor);
    }

    public static <E extends Enum<E>, M extends Message<M>, S extends Stage<E, M>> M execute(S stage, M input) {
        StageExecutor<E, M, S> stageExecutor = (StageExecutor<E, M, S>) EXECUTORS.get(stage.getClass());
        
        return stage.run(input).getMessage();
    }
}

I know I can put @SuppressWarnings("unchecked") there to avoid the noise but I was just wondering is there a better way to implement this?



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source