public class AutoKeyMap<K,V> {
public interface KeyGenerator<K> {
public K generate();
}
private KeyGenerator<K> generator;
public AutoKeyMap(Class<K> keyType) {
// WARNING: Unchecked cast from AutoKeyMap.IntKeyGen to AutoKeyMap.KeyGenerator<K>
if (keyType == Integer.class) generator = (KeyGenerator<K>) new IntKeyGen();
else throw new RuntimeException("Cannot generate keys for " + keyType);
}
public void put(V value) {
K key = generator.generate();
...
}
private static class IntKeyGen implements KeyGenerator<Integer> {
private final AtomicInteger ai = new AtomicInteger(1);
@Override public Integer generate() {
return ai.getAndIncrement();
}
}
}
In the code sample above, what is the correct way to prevent the given warning, without adding a @SuppressWarnings
, if any?
You can fix your code temporarily by doing this:
But if you need to implement a method in
AutoKeyMap
likethen it will break again. The problem is as soon as you start doing runtime checking of class types (like you do in
if(keyType == Integer.class)
) then Java compiler has no way of statically ensuring that type will be correct. Because you can instantiatenew AutoKeyMap<Boolean>(Class<Boolean> keyType)
and then writewhich will obviously break, and therefore the whole point of statically checked generic types will be lost.
Usually all problems like yours that involve dynamic type casting are beyond generics, so you have to live with unchecked casts, and just make sure you write enough unit tests and make sure your code works and does not throw
ClassCastException
in all scenarios.