I am trying to create a generic type that implements that Map
interface.
public class CountingMap<K> implements Map<K, Double> {
...
/**
* @see java.util.Map#containsKey(java.lang.Object)
*/
@Override
public boolean containsKey(Object key) {
return backingMap.containsKey(key);
}
...
But this gives me an error "Unlikely argument type Object for containsKey(Object) on a Map<K,Double>". (I know this is usually just a warning, but I have my IDE configured to call this an error, because it often is (for me) and I don't want to change that setting.)
I cannot do this...
@Override
public boolean containsKey(Object key) {
if ( key instanceof K) {
return backingMap.containsKey((K) value);
} else {
return false;
}
}
Because the type of K is erased at runtime.
The best I can do is:
/**
* @see java.util.Map#containsKey(java.lang.Object)
*/
@Override
public boolean containsKey(Object key) {
@SuppressWarnings("unchecked")
K keyVal = (K) key;
return backingMap.containsKey(keyVal);
}
Does anyone have anything better? Something that doesn't require the @SuppressWarnings
? I mean, it really will fail at runtime if someone calls containsKey
with an object of the wrong type. I guess I could catch ClassCastException
?
Is there an idiomatic way to do this in Java?
No, it won't. That cast does nothing. That whole 'generics are erased' thing cuts both ways, the compiler doesn't know what K is.
The correct action, as always, is to never have compiler errors, only compiler warnings, and consider all warnings as violations that must never make it to production. Exactly for reasons like this (It's also convenient when halfway through writing and e.g. wanting to run the test suite).