2
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上記のコード サンプルで、もしあればを追加せずに、与えられた警告を防ぐ正しい方法は何ですか?

4

1 に答える 1

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、すべてのシナリオでスローされないことを確認してください。

于 2010-12-28T15:01:11.457 に答える