web-dev-qa-db-ja.com

未チェックの割り当て警告

私はAndroid Studio 1.1.0を使用しています。

これにより警告は発生しません。

public static class A {
    public Map<Integer, String> getMap() {
        return null;
    }
}

public static class B {
    public void processA(A a) {
        Map<Integer, String> map = a.getMap();
    }
}

ただし、Aをジェネリックにします。

public static class A<T> {
    public Map<Integer, String> getMap() {
        return null;
    }
}

そしてこの行:

Map<Integer, String> map = a.getMap();

警告が表示されます:"Unchecked assignment: 'Java.util.Map to Java.util.Map<Java.lang.Integer, Java.lang.String>'

getMapの署名はTから完全に独立していますが、コードはMapに含まれる型に関して明確です。

次のようにprocessAを再実装することで、警告を取り除くことができることを知っています。

public <T> void processA(A<T> a) {
    Map<Integer, String> map = a.getMap();
}

しかし、なぜ私はそれをしなければならないのでしょうか?ここでTは何を問題にしますか?

だから、質問は-なぜ型消去はT(これは理解できる-Aのインスタンスを渡す場合、Tは不明であるに影響するだけでなく、 )だけでなく、<Integer, String> この場合?

26
Konrad Morawski

あなたの2番目のケースでは:

public void processA(A a)

Aとはどういう意味ですか? A<String>またはA<List<String>>または何を意味しますか? Aのタイプに関連するものを使用していない可能性がありますが、コンパイラーはこの事実を知りません。コンパイラにとって、ただAはパニックの兆候です。

あなたの場合、Aのタイプを特に知る必要はないので、次のことができます。

public void processA(A<?> a) {
    Map<Integer, String> map = a.getMap();
} 

引数タイプがA<?>であるということは、Aのタイプを特に気にせず、ワイルドカードを指定するだけです。あなたにとって、それは:ジェネリック型と同じような型を持つAのオブジェクト。実際には、タイプがわからないことを意味します。 ?は事実上何でもできるため、タイプセーフな方法でAに関連することは何もできないので、それは役に立たない!

しかし、メソッド本体ごとに、A<?>を使用することは世界のすべての理にかなっています。ボディのどこにAの型が実際に必要なのか

18
Jatin

Tの可能性のあるタイプのA<T>を受け入れるが、Tを必要としない場合、これはワイルドカードを使用してA<?>を記述することで正しく表現されます。 。そうすることで、コード内の警告が取り除かれます。

public void processA(A<?> a) {
    Map<Integer, String> map = a.getMap();
}

裸のタイプAを使用することは同等に扱われません。 Java Language Specification で説明されているように、そのような生の型は新しいコードで使用されることを意図していません。

未チェックの変換を使用して、ジェネリック型の導入前に記述されたレガシーコードと、ジェネリティーを使用するために変換されたライブラリ(ジェネリフィケーションと呼ばれるプロセス)との円滑な相互運用を可能にします。そのような状況(特に、Java.utilのCollections Frameworkのクライアント)では、レガシーコードは生のタイプ(Collection <String>ではなくCollectionなど)を使用します。生の型の式は、対応する仮パラメータの型と同じ型のパラメータ化されたバージョンを使用するライブラリメソッドに引数として渡されます。

このような呼び出しは、ジェネリックを使用する型システムでは静的に安全であるとは示されません。このような呼び出しを拒否すると、既存のコードの大部分が無効になり、新しいバージョンのライブラリを使用できなくなります。これは、ライブラリベンダーが汎用性を利用することを妨げます。このような好ましくないイベントの切り替えを防ぐために、生の型は、生の型が参照するジェネリック型宣言の任意の呼び出しに変換できます。変換は不適切ですが、実用性の譲歩として許容されます。このような場合、未確認の警告が発行されます。

9
Dan Getz