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();
}
}
}
在上面的代码示例中,如果没有添加@SuppressWarnings
,阻止给定警告的正确方法是什么?
答案 0 :(得分:0)
您可以通过以下方式暂时修复代码:
private KeyGenerator<?> generator;
public AutoKeyMap(Class<?> keyType) {
// WARNING: Unchecked cast from AutoKeyMap.IntKeyGen to AutoKeyMap.KeyGenerator<K>
if (keyType == Integer.class) generator = new IntKeyGen();
else throw new RuntimeException("Cannot generate keys for " + keyType);
}
但是如果你需要在AutoKeyMap
中实现一个方法,比如
K generate(){
return generator.generate();
}
然后它会再次破裂。问题是,一旦开始对类类型进行运行时检查(就像在if(keyType == Integer.class)
中那样),那么Java编译器无法静态地确保类型是正确的。因为您可以实例化new AutoKeyMap<Boolean>(Class<Boolean> keyType)
然后编写
if(keyType == Boolean.class){
generator = new IntKeyGen();
}
显然会破坏,因此静态检查泛型类型的整个点将会丢失。
通常所有涉及动态类型转换的问题都超出了泛型,因此您必须使用未经检查的强制转换,并确保编写足够的单元测试并确保代码正常工作并且不会抛出ClassCastException
在所有情况下。