Reputation: 21
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
}
}
Upvotes: 2
Views: 139
Reputation: 111
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.
Upvotes: 0
Reputation: 40851
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!)
Upvotes: 4