web-dev-qa-db-ja.com

JavaのSuppressWarnings( "unchecked")とは何ですか?

コードを調べてみると、多くのメソッドがアノテーションを指定しているのを目にすることがあります。

@SuppressWarnings("unchecked")

これは何を意味するのでしょうか?

403
jojo

時々Javaジェネリックはあなたがしたいことをさせないことがあり、あなたが本当にやっていることをコンパイラに効果的に伝える必要がありますwill実行時に合法である。

一般的なインターフェイスをモックしているとき、私は通常これを苦痛に感じますが、他の例もあります。通常、警告を抑制するのではなく回避する方法を試す価値があります(ここでは Java Generics FAQ が役立ちます)が、場合によってはis可能な場合、コードを非常に曲げて、警告を抑えるのがより適切です。その場合は常に説明的なコメントを追加してください!

同じジェネリックFAQには、このトピックに関するいくつかのセクションがあります ""未チェックの警告とは? " -読む価値があります。

393
Jon Skeet

キャストなど、チェックされていない一般的な操作(例外ではない)に関するコンパイルの警告を抑制するアノテーションです。これは本質的に、プログラマーがこれらについて知らされることを望んでいなかったことを意味しています。これは、コードの特定の部分をコンパイルするときに知っています。

あなたはここでこの特定の注釈についてもっと読むことができます:

SuppressWarnings

さらに、オラクル社では、注釈の使用方法に関するチュートリアルのドキュメントをいくつか提供しています。

注釈

彼らが言うように、

「「未チェック」の警告は、ジェネリック医薬品の出現以前に作成されたレガシーコードとやり取りするときに発生する可能性があります(「ジェネリックス」というタイトルのレッスンで説明されています)。

48
Ben Lakey

それはまた、現在のJavaの型システムのバージョンがあなたのケースには十分ではないことを意味するかもしれません。いくつかの JSR命題 /これを修正するためのハックがありました:タイプトークン、 スーパータイプトークン 、Class.cast()。

あなたが本当にこの抑制を必要とするならば、できるだけそれを絞り込んでください(例えば、それをクラス自体の上や長いメソッドの上に置かないでください)。例:

public List<String> getALegacyListReversed() {
   @SuppressWarnings("unchecked") List<String> list =
       (List<String>)legacyLibrary.getStringList();

   Collections.reverse(list);
   return list;
}
19
akarnokd

SuppressWarning 注釈は、注釈付き要素に対するコンパイラの警告を抑制するために使用されます。具体的には、uncheckedカテゴリを使用すると、未チェックの型キャストの結果として生成されるコンパイラ警告を抑制できます。

9

簡単に言うと、これは型の安全性を保証できないことをコンパイラが示す警告です。

JPAサービス方法の例:

@SuppressWarnings("unchecked")
public List<User> findAllUsers(){
    Query query = entitymanager.createQuery("SELECT u FROM User u");
    return (List<User>)query.getResultList();
}

ここで@SuppressWarnings( "unchecked")に注釈を付けなかった場合、ResultListを返したいlineに問題があります。

ショートカットでの安全性の意味:エラーや警告なしにコンパイルされ、実行時に予期しないClassCastExceptionが発生しない場合、プログラムは安全であると見なされます。

http://www.angelikalanger.com/GenericsFAQ/FAQSections/Fundamentals.htmlに基づいて構築します

8
Daniel Perník

Javaでは、総称は型消去によって実装されます。たとえば、次のようなコードです。

List<String> hello = List.of("a", "b");
String example = hello.get(0);

以下にまとめられています。

List hello = List.of("a", "b");
String example = (String) hello.get(0);

そしてList.ofは、と定義されています。

static <E> List<E> of(E e1, E e2);

型消去後になるもの。

static List of(Object e1, Object e2);

コンパイラは実行時にジェネリック型が何であるかわからないので、あなたがこのような何かを書くなら。

Object list = List.of("a", "b");
List<Integer> actualList = (List<Integer>) list;

Java Virtual Machineはプログラムの実行中にジェネリック型が何であるかわからないので、これはコンパイルおよび実行されます。JavaVirtual Machineに関しては、これはList型へのキャストです(これが唯一の検証可能なので、検証のみです)。 。

しかし今、この行を追加してください。

Integer hello = actualList.get(0);

Javaコンパイラが暗黙のキャストを挿入したため、JVMは予期しないClassCastExceptionをスローします。

Java.lang.ClassCastException: Java.base/Java.lang.String cannot be cast to Java.base/Java.lang.Integer

unchecked警告は、キャストによってプログラムが他の場所で例外をスローする可能性があることをプログラマに伝えます。 @SuppressWarnings("unchecked")で警告を抑制することは、プログラマーがコードが安全であり、予期しない例外を引き起こさないと信じていることをコンパイラに伝えます。

なぜあなたはそれをしたいのですか? Javaの型システムは、すべての可能な型使用パターンを表現するのに十分ではありません。キャストが安全であることを知っているかもしれませんが、Javaはそう言う方法を提供していません - このような警告を隠すために、プログラマが本当の警告に集中できるように@SupressWarnings("unchecked")を使うことができます。たとえば、Optional.empty()は値を格納しない空のオプションの割り当てを避けるためにシングルトンを返します。

private static final Optional<?> EMPTY = new Optional<>();
public static<T> Optional<T> empty() {
    @SuppressWarnings("unchecked")
    Optional<T> t = (Optional<T>) EMPTY;
    return t;
}

空のオプションに格納されている値は取得できないため、このキャストは安全です。予期しないクラスキャスト例外が発生する危険性はありません。

6
Konrad Borowski

あなたはコンパイラの警告を抑制し、あなたが書いたコードがそれに従って合法であることを総称に伝えることができます。

例:

@SuppressWarnings("unchecked")
public List<ReservationMealPlan> retreiveMealPlan() {
     List<ReservationMealPlan> list=new ArrayList<ReservationMealPlan>();
    TestMenuService testMenuService=new TestMenuService(em, this.selectedInstance);
    list = testMenuService.getMeal(reservationMealPlan);
    return list;
 }
5
s.k.sumaprakash

1つのトリックは、一般的な基本インターフェースを拡張するインターフェースを作成することです。

public interface LoadFutures extends Map<UUID, Future<LoadResult>> {}

それからキャストの前にinstanceofでそれをチェックすることができます...

Object obj = context.getAttribute(FUTURES);
if (!(obj instanceof LoadFutures)) {
    String format = "Servlet context attribute \"%s\" is not of type "
            + "LoadFutures. Its type is %s.";
    String msg = String.format(format, FUTURES, obj.getClass());
    throw new RuntimeException(msg);
}
return (LoadFutures) obj;
5
Brian Edwards

私が知っている限りでは、今のところ、ジェネリックスに関する警告を抑制することに関係しています。総称は、JDK 5より前のJDKバージョンではサポートされていない新しいプログラミング構造です。したがって、古い構造と新しい構造を混在させると、予期しない結果が生じる可能性があります。

コンパイラはそれについてプログラマに警告しますが、プログラマがすでに知っている場合は、SuppressWarningsを使用してそれらの恐ろしい警告をオフにすることができます。

3
BakerTheHacker

コンパイラが型の安全性を保証できないことを示す警告です。 「未チェック」の警告という用語は誤解を招く可能性があります。警告がチェックされていないという意味ではありません。 「チェックされていない」という用語は、コンパイラとランタイムシステムが、型の安全性を保証するために必要なすべての型チェックを実行するのに十分な型情報を持っていないという事実を意味します。この意味で、特定の操作は「未チェック」です。 「未チェック」の警告の最も一般的な原因は、生の型の使用です。生の型はすべての必要な型チェックを実行するのに十分な型情報を提供しないため、生の型変数を介してオブジェクトにアクセスすると、「未チェック」の警告が発行されます。

例(生の型と関連した未チェックの警告の場合):

TreeSet se t = new TreeSet(); set.add("abc"); // unchecked warning set.remove("abc");

warning:未チェックの生の型のメンバとしてのadd(E)の呼び出し未チェックJava.util.TreeSet set.add( "abc");
^ addメソッドが呼び出されると、コンパイラーはStringオブジェクトをコレクションに追加しても安全かどうかわかりません。 TreeSetがString(またはそのスーパータイプ)を含むコレクションである場合は安全です。しかし、生の型TreeSetによって提供される型情報からは、コンパイラはそれを認識できません。そのため、呼び出しは安全ではない可能性があり、「未チェック」の警告が発行されます。

コンパイラが、ターゲット型がパラメータ化型または型パラメータのいずれかであるキャストを見つけると、「未チェック」の警告も報告されます。

例(パラメータ化された型または型変数へのキャストに関連した未チェックの警告の場合):

class Wrapper<T> { private T wrapped ; public Wrapper (T arg) {wrapped = arg;} ... p ublic Wrapper <T> clone() { Wrapper<T> clon = null; try {
clon = (Wrapper<T>) super.clone(); // unchecked warning } catch (CloneNotSupportedException e) {
throw new InternalError();
} try {
Class<?> clzz = this.wrapped.getClass(); Method meth = clzz.getMethod("clone", new Class[0]); Object dupl = meth.invoke(this.wrapped, new Object[0]); clon.wrapped = (T) dupl; // unchecked warning } catch (Exception e) {} return clon; } }

warning: [unchecked] unchecked cast found : Java.lang.Object required: Wrapper <T> clon = ( Wrapper <T>)super.clone();
^ warning: [unchecked] unchecked cast found : Java.lang.Object required: T clon. wrapped = (T)dupl;

実行時の動的型チェックが必要な場合、ターゲット型が(具象または境界ワイルドカード)パラメータ化型または型パラメータのいずれかであるキャストは安全ではありません。実行時には、消去可能な型のみが使用可能であり、ソースコードに表示される正確な静的型は使用できません。その結果、キャストのランタイム部分は、正確な静的型ではなく型の消去に基づいて実行されます。この例では、Wrapperへのキャストで、super.cloneから返されたオブジェクトがWrapperであるかどうかがチェックされ、特定の種類のメンバーを持つラッパーであるかどうかはチェックされません。同様に、型パラメータTへのキャストは実行時にObject型にキャストされ、おそらく完全に最適化されます。型が消去されているため、ランタイムシステムは実行時により有用な型チェックを実行できません。

ある意味では、ソースコードは誤解を招く可能性があります。実際のキャストの動的部分はターゲットタイプのタイプの消去に対してのみチェックを行いながら、それぞれのターゲットタイプへのキャストが実行されることを示唆しています。 「未チェック」の警告は、キャストの静的側面と動的側面の間のこの不一致にプログラマーの注意を引くために発行されます。

参照してください: "未チェック"の警告は何ですか?

1
Raghu K Nair

@SuppressWarningsアノテーションは、JDKで利用可能な3つの組み込みアノテーションの1つであり、Java 1.5で@Overrideおよび@Deprecatedとともに追加されます。

@SuppressWarningsは、注釈付き要素およびその要素内のすべてのプログラム要素で指定されたコンパイラ警告を無視または抑制するようにコンパイラに指示します。たとえば、特定の警告を抑制するためにクラスに注釈が付けられている場合、そのクラス内のメソッドで生成された警告も分離されます。

@SuppressWarningsアノテーションの最も一般的な例の2つである@SuppressWarnings( "unchecked")と@SuppressWarnings( "serial")を見たことがあるかもしれません。前者は未チェックのキャストによって生成される警告を抑制するために使用され、後の警告はSerializableクラスにSerialVersionUIDを追加することを思い出させるために使用されます。

詳細: https://javarevisited.blogspot.com/2015/09/what-is-suppresswarnings-annotation-in-Java-unchecked-raw-serial.html#ixzz5rqQaOLUa

0
Majid Roustaei