Как избежать небезопасного приведения к общей ситуации, связанной с прохождением класса во время выполнения - PullRequest
2 голосов
/ 28 декабря 2010
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, если есть?

1 Ответ

0 голосов
/ 28 декабря 2010

Вы можете временно исправить свой код, выполнив это:

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 во всех сценариях.

...