1. ホーム
  2. java

[解決済み] チェックされていないキャストの警告に対処するにはどうすればよいですか?

2022-03-15 21:32:55

質問

Eclipseで以下のような警告が表示されます。

型安全です。ObjectからHashMapへのキャストがチェックされていません。

これは、私がコントロールできない、Objectを返すAPIへの呼び出しによるものです。

HashMap<String, String> getItems(javax.servlet.http.HttpSession session) {
  HashMap<String, String> theHash = (HashMap<String, String>)session.getAttribute("attributeKey");
  return theHash;
}

Eclipseの警告は、理論的には少なくともコードの問題の可能性を示しているので、できれば避けたいのです。 でも、これをなくすいい方法はまだ見つかっていないんだ。 私は、関係する一行をそれ自体でメソッドに抽出し、そのメソッドに @SuppressWarnings("unchecked") このように、警告を無視するコードブロックがあることの影響を制限することができます。 何か良い方法はないでしょうか? Eclipseでこれらの警告を消したくないのです。

このコードに行き着く前は、もっとシンプルでしたが、それでも警告が発生しました。

HashMap getItems(javax.servlet.http.HttpSession session) {
  HashMap theHash = (HashMap)session.getAttribute("attributeKey");
  return theHash;
}

問題は、ハッシュを使おうとすると、他の場所で警告が出ることでした。

HashMap items = getItems(session);
items.put("this", "that");

Type safety: The method put(Object, Object) belongs to the raw type HashMap.  References to generic type HashMap<K,V> should be parameterized.

解決方法は?

うわー;自分の質問の答えがわかった気がする。 ただ、その価値があるのかどうか!?:)

問題は、キャストがチェックされていないことです。 だから、自分でチェックする必要があるんだ。 パラメータ化された型の情報はコンパイル時に消されてしまっているので、実行時に利用できないからです。

しかし、ハッシュの各項目に対してinstanceofによるチェックを行うことで、型安全な新しいハッシュを構築することができるのです。 そうすれば、型安全な新しいハッシュを構築することができる。そして、警告を引き起こすこともない。

mmyersとEsko Luontolaのおかげで、もともとここに書いたコードをパラメータ化したので、どこかのユーティリティクラスでラップして、パラメータ化した任意のHashMapに使用することができます。 もし、あなたがジェネリックにあまり詳しくないのであれば、この回答の編集履歴を見ることをお勧めします。

public static <K, V> HashMap<K, V> castHash(HashMap input,
                                            Class<K> keyClass,
                                            Class<V> valueClass) {
  HashMap<K, V> output = new HashMap<K, V>();
  if (input == null)
      return output;
  for (Object key: input.keySet().toArray()) {
    if ((key == null) || (keyClass.isAssignableFrom(key.getClass()))) {
        Object value = input.get(key);
        if ((value == null) || (valueClass.isAssignableFrom(value.getClass()))) {
            K k = keyClass.cast(key);
            V v = valueClass.cast(value);
            output.put(k, v);
        } else {
            throw new AssertionError(
                "Cannot cast to HashMap<"+ keyClass.getSimpleName()
                +", "+ valueClass.getSimpleName() +">"
                +", value "+ value +" is not a "+ valueClass.getSimpleName()
            );
        }
    } else {
        throw new AssertionError(
            "Cannot cast to HashMap<"+ keyClass.getSimpleName()
            +", "+ valueClass.getSimpleName() +">"
            +", key "+ key +" is not a " + keyClass.getSimpleName()
        );
    }
  }
  return output;
}

それは大変な作業で、おそらく報酬はほとんどないでしょう......。 使うかどうか迷っています。 使うかどうか迷うところですが、使う価値があるかどうか、ご意見をいただければと思います。 また、改善提案もお願いします。AssertionErrorsを投げる以外に何か良い方法はないでしょうか? AssertionErrorsを投げる以外に何か良い方法はないでしょうか? チェックされたExceptionにした方がいいのでしょうか?