1. 概要

このクイックチュートリアルでは、@SafeVarargsアノテーションを見ていきます。

2. @SafeVarargsアノテーション

Java 5では、varargsの概念、または可変長のメソッドパラメータ、およびパラメータ化された型が導入されました。

これらを組み合わせると、問題が発生する可能性があります。

public static <T> T[] unsafe(T... elements) {
    return elements; // unsafe! don't ever return a parameterized varargs array
}

public static <T> T[] broken(T seed) {
    T[] plant = unsafe(seed, seed, seed); // broken! This will be an Object[] no matter what T is
    return plant;
}

public static void plant() {
   String[] plants = broken("seed"); // ClassCastException
}

これらの問題はコンパイラが確認するのが難しいため、安全でない場合のように、2つが組み合わされるたびに警告が表示されます:

warning: [unchecked] Possible heap pollution from parameterized vararg type T
  public static <T> T[] unsafe(T... elements) {

このメソッドを誤って使用すると、 broken の場合のように、は意図したタイプbではなくObject[]配列をヒープに汚染します。

この警告を潰すために、finalまたはstaticメソッドとコンストラクター@SafeVarargsアノテーションを追加できます。

@SafeVarargs は、特定のコンパイラ警告が誤検知であることを宣言できるという点で@SupressWarningsに似ています。 アクションが安全であることを確認したら、次のアノテーションを追加できます。

public class Machine<T> {
    private List<T> versions = new ArrayList<>();

    @SafeVarargs
    public final void safe(T... toAdd) {
        for (T version : toAdd) {
            versions.add(version);
        }
    }
}

varargsの安全な使用は、それ自体がトリッキーな概念です。 詳細については、JoshBlochが著書EffectiveJavaで優れた説明をしています。

3. 結論

この簡単な記事では、Javaで@SafeVarargsアノテーションを使用する方法を説明しました。

例の完全なソースコードは、GitHubにあります。