views:

29

answers:

2

I am getting the following compile error "The method putInstance(Class, T) in the type MutableClassToInstanceMap is not applicable for the arguments (Class, Number)" on the putInstance method call. Does anyone know what I am doing wrong?? Thanks!

public class TestMutableClassToInstanceMap {

    public final MutableClassToInstanceMap<Number> identifiers = MutableClassToInstanceMap.create();

    public static void main(String[] args) {
        ArrayList<Number> numbers = new ArrayList<Number>();
        numbers.add(new Integer(5));
        TestMutableClassToInstanceMap test = new TestMutableClassToInstanceMap(numbers);
    }

    public TestMutableClassToInstanceMap(Collection<Number> numbers){
        for (Number number : numbers) {
            this.identifiers.putInstance(number.getClass(), number); //error here
        }
        this.identifiers.putInstance(Double.class, 5.0); // This works
    }

}
+3  A: 

The purpose of the putInstance method, as opposed to the regular put, is to provide compile-time type safety. In this case, you and I can easily reason that number must be of the type given by number.getClass(), but to the compiler, that information is "lost." That is, as far as it knows, maybe number is an Integer and number.getClass() is Long.class; it's not "smart" enough to figure out this is safe.

Solution: just use put()! You still get the runtime checks, and you can still use the typesafe getInstance() method after that, such as in Long l = this.identifiers.getInstance(Long.class);.

(Final tip: watch out, because Long.class and long.class can both exist in a ClassToInstanceMap and be mapped to different values!)

Kevin Bourrillion
A: 

Kevin's answer is great. Besides, you can tell from the method definition that the compiler is not going to allow the call:

  • putInstance requires (in your case) a Class<Number>.
  • number.getClass() provides a Class<? extends Number>

Which is not a direct subclass. Some variance and covariance talk could be useful here.

Andres Rodriguez