Java Generics can't use wildcard with generic T

Viewed 60

I have the following, small interface:

public interface EntityController<T> {
    public void update( float elapsed, T applyTo );
}

Which I want to use in the following way:

private Map<Class<? extends GameObject>, EntityController<?>> registeredControllers;
public EntityController<?> getController(GameObject o) {
    return registeredControllers.get(o.getClass());;
}
...
getController(myObj).update(elapsed, myObj);

The last line gives me the error that The method update(float, capture#1-of ?) in the type EntityController<capture#1-of ?> is not applicable for the arguments (float, GameObject)

Why is that? Basically, what I want to achieve is the following: I know that each EntityController is responsible only for handling one specific type of class. Therefore, in the update method of it I will always have to cast my GameObject to the respective type, which is annoying, and I guess also generates some kind of overhead? I thought generics would be a nice way of solving the problem, allowing me to create specific controllers in the following manner:

public class MyController implements EntityController<MyType> {
    public void update(float elapsed, MyType applyTo){}
}

Why isn't that possible?

1 Answers

To put it simply, you cannot assign a value to a wildcard type, because the actual type is unknown. So if the return type is EntityController<?>, you cannot assign to update's 2nd argument.

The easiest (but not 100% type safe) solution would be

private Map<Class<? extends GameObject>, EntityController<? extends GameObject>> registeredControllers;

@SuppressWarnings("unchecked")
public <T extends GameObject> EntityController<T> getController(T o) {
    return (EntityController<T>) registeredControllers.get(o.getClass());
}
Related