Java unchecked:varargsパラメータの未チェックのジェネリック配列の作成


111

Javaコードでチェックされていない警告を表示するようにNetbeansを設定しましたが、次の行のエラーを理解できません。

private List<String> cocNumbers;
private List<String> vatNumbers;
private List<String> ibans;
private List<String> banks;
...
List<List<String>> combinations = Utils.createCombinations(cocNumbers, vatNumbers, ibans);

与える:

[unchecked] unchecked generic array creation for varargs parameter of type List<String>[]

メソッドソース:

/**
 * Returns a list of all possible combinations of the entered array of lists.
 *
 * Example: [["A", "B"], ["0", "1", "2"]]
 * Returns: [["A", "0"], ["A", "1"], ["A", "2"], ["B", "0"], ["B", "1"], ["B", "2"]]
 *
 * @param <T> The type parameter
 * @param elements An array of lists
 * @return All possible combinations of the entered lists
 */
public static <T> List<List<T>> createCombinations(List<T>... elements) {
    List<List<T>> returnLists = new ArrayList<>();

    int[] indices = new int[elements.length];
    for (int i = 0; i < indices.length; i++) {
        indices[i] = 0;
    }

    returnLists.add(generateCombination(indices, elements));
    while (returnLists.size() < countCombinations(elements)) {
        gotoNextIndex(indices, elements);
        returnLists.add(generateCombination(indices, elements));
    }

    return returnLists;
}

コードにチェックされていない警告を残すのは良い考えではないので、正確に何がうまくいかず、どうすれば修正できますか?

言及を忘れましたが、私はJava 7を使用しています。

編集:また、メソッドには次のものが含まれていることもわかります。

[unchecked] Possible heap pollution from parameterized vararg type List<T>
  where T is a type-variable:
    T extends Object declared in method <T>createCombinations(List<T>...)

17
他に何をするにせよ、Javaでは、新しく作成されたint配列を0で初期化する必要はありません...
Thomas Mueller

1
@ThomasMuellerグッドキャッチ
2014年

回答:


165

上で述べたjanoh.janohのように、Javaのvarargsは、配列の構文上の糖衣であり、呼び出しサイトでの暗黙的な配列の作成です。そう

List<List<String>> combinations =
    Utils.createCombinations(cocNumbers, vatNumbers, ibans);

実際に

List<List<String>> combinations =
    Utils.createCombinations(new List<String>[]{cocNumbers, vatNumbers, ibans});

しかし、ご存じかもしれnew List<String>[]ませんが、他の多くの質問で取り上げられている理由のため、Javaでは許可されていませんが、主に配列が実行時にコンポーネントタイプを認識し、実行時に追加された要素がそのコンポーネントと一致するかどうかを確認する必要があります型ですが、このチェックはパラメーター化された型では不可能です。

とにかく、コンパイラは失敗するのではなく、配列を作成します。これは次のようなものです。

List<List<String>> combinations =
    Utils.createCombinations((List<String>[])new List<?>[]{cocNumbers, vatNumbers, ibans});

これは潜在的に安全ではありませんが、必ずしも安全ではありません。ほとんどのvarargsメソッドは、単にvarargs要素を反復処理して読み取るだけです。この場合、配列の実行時のタイプは関係ありません。これはあなたの方法の場合です。Java 7を使用しているので@SafeVarargs、メソッドに注釈を追加する必要があります。この警告は表示されなくなります。このアノテーションは基本的に、このメソッドは配列のタイプではなく、要素のタイプのみを対象としています。

ただし、配列のランタイム型を使用するいくつかのvarargsメソッドがあります。この場合、それは潜在的に安全ではありません。それが警告が出ている理由です。


16
SafeVaragsについて言及しただけでなく、いつ使用できるかを教えてくれてありがとう。
KitsuneYMG 2014年

12
誰にもすぐに分からない場合(私には分からないように)、Javadocに@SafeVarargsは、安全でないメソッドの例がありますdocs.oracle.com/javase/7/docs/api/java/lang/SafeVarargs .html
michiakig

3
だから、@SafeVarargsあなたの方法をするときに使用することができるだけ消費配列の要素をしていない(と決して)農産物ん配列に入れての要素?他のメソッドによって操作される可能性のあるフィールドに配列引数を割り当てる場合は、安全でない操作が行われていないと判断するのは簡単ではないため、特別な注意が必要です。
ネクサス2017年

13

Javaコンパイラはvarargsに暗黙的な配列の作成を使用し、javaは一般的な配列の作成を許可しないためです(型の引数がreifiableでないため)。

以下のコードは正しい(これらの操作は配列で許可されている)ため、チェックされていない警告が必要です。

public static <T> List<List<T>> createCombinations(List<T> ... lists) {
    ((Object[]) lists)[0] = new ArrayList<Integer>();
    // place your code here
}

ここで包括的な説明を参照してください

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.