307

春のアプリケーション コンテキスト ファイルには、次のようなものがあります。

<util:map id="someMap" map-class="java.util.HashMap" key-type="java.lang.String" value-type="java.lang.String">
    <entry key="some_key" value="some value" />
    <entry key="some_key_2" value="some value" />   
</util:map>

Java クラスでは、実装は次のようになります。

private Map<String, String> someMap = new HashMap<String, String>();
someMap = (HashMap<String, String>)getApplicationContext().getBean("someMap");

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

型の安全性: Object から HashMap<String,String> へのチェックされていないキャスト

何が悪かったのか?

4

10 に答える 10

358

HashMap<String,String>問題は、キャストがランタイム チェックであることです。ただし、型の消去により、実行時に、実際には aとの間に違いはありませHashMap<Foo,Bar>ん。FooBar

@SuppressWarnings("unchecked")鼻を使って押さえます。ああ、Java で具体化されたジェネリックのキャンペーン:)

于 2008-11-04T17:09:19.927 に答える
278

まず第一に、新しいHashMap作成呼び出しでメモリを浪費しています。2 行目は、この作成されたハッシュマップへの参照を完全に無視し、ガベージ コレクターで使用できるようにします。だから、それをしないで、使用してください:

private Map<String, String> someMap = (HashMap<String, String>)getApplicationContext().getBean("someMap");

次に、コンパイラは、オブジェクトが であるHashMapかどうかを確認せずにオブジェクトを にキャストすると不平を言っていますHashMap。ただし、次のことを行う場合でも:

if(getApplicationContext().getBean("someMap") instanceof HashMap) {
    private Map<String, String> someMap = (HashMap<String, String>)getApplicationContext().getBean("someMap");
}

おそらく、この警告は引き続き表示されます。問題は、getBeanreturnObjectであるため、型が不明です。それを直接に変換してもHashMap、2番目のケースでは問題が発生しません(おそらく最初のケースでは警告が表示されないでしょう。JavaコンパイラがJava 5の警告でどれほどペダンティックかはわかりません)。ただし、に変換していHashMap<String, String>ます。

HashMap は実際には、オブジェクトをキーとして取り、オブジェクトを値として持つマップHashMap<Object, Object>です。したがって、返される非ジェネリック表現には任意のオブジェクトを含めることがHashMap<String, String>できるため、Bean を取得したときに として表現できるという保証はありません。HashMap<Date, Calendar>

コードがコンパイルされ、エラーなしで実行できる場合はString value = map.get("thisString");、この警告について心配する必要はありません。ただし、マップが文字列キーから文字列値への完全なマップではない場合ClassCastException、ジェネリックはこの場合の発生をブロックできないため、実行時に を取得します。

于 2008-11-04T16:44:07.763 に答える
109

上記のメッセージが示すように、リストは aList<Object>と aList<String>またはを区別できませんList<Integer>

同様の問題について、このエラー メッセージを解決しました。

List<String> strList = (List<String>) someFunction();
String s = strList.get(0);

次のように:

List<?> strList = (List<?>) someFunction();
String s = (String) strList.get(0);

説明: 最初の型変換では、保持されている型を気にせずに、オブジェクトがリストであることを検証します (リスト レベルで内部型を検証できないため)。コンパイラは List に何らかのオブジェクトが含まれていることしか認識していないため、2 番目の変換が必要になります。これにより、リスト内の各オブジェクトがアクセスされるたびにそのタイプが検証されます。

于 2012-11-14T21:46:20.857 に答える
35

警告はそれだけです。警告。警告は無関係な場合もあれば、そうでない場合もあります。これらは、コンパイラーが問題である可能性があると考えているものの、そうではない可能性があることに注意を喚起するために使用されます。

キャストの場合、この場合は常に警告が表示されます。特定のキャストが安全であると確信している場合は、行の直前に次のような注釈を追加することを検討する必要があります (構文はわかりません)。

@SuppressWarnings (value="unchecked")
于 2008-11-04T16:44:24.970 に答える
9

getBean がオブジェクト参照を返し、それを正しい型にキャストしているため、このメッセージが表示されます。Java 1.5 では警告が表示されます。これが、このように機能するコードで Java 1.5 以降を使用する性質です。Springにはタイプセーフバージョンがあります

someMap=getApplicationContext().getBean<HashMap<String, String>>("someMap");

そのtodoリストに。

于 2008-11-04T16:44:59.460 に答える
6

本当に警告を取り除きたい場合は、ジェネリック クラスから拡張されたクラスを作成することができます。

たとえば、使用しようとしている場合

private Map<String, String> someMap = new HashMap<String, String>();

このような新しいクラスを作成できます

public class StringMap extends HashMap<String, String>()
{
    // Override constructors
}

次に、使用するとき

someMap = (StringMap) getApplicationContext().getBean("someMap");

コンパイラーは、(もはやジェネリックではない) 型が何であるかを認識しており、警告はありません。これは常に完璧な解決策であるとは限りません。この種のジェネリック クラスの目的が無効になると主張する人もいるかもしれませんが、ジェネリック クラスの同じコードをすべて再利用しているため、コンパイル時に型を宣言しているだけです。使用したい。

于 2016-04-13T15:55:31.927 に答える
2

別の解決策として、同じオブジェクトを何度もキャストしていて、コードに を散らかしたくない場合は@SupressWarnings("unchecked")、アノテーションを使用してメソッドを作成することです。このようにして、キャストを集中化し、うまくいけばエラーの可能性を減らします。

@SuppressWarnings("unchecked")
public static List<String> getFooStrings(Map<String, List<String>> ctx) {
    return (List<String>) ctx.get("foos");
}
于 2016-10-20T19:25:17.597 に答える