web-dev-qa-db-ja.com

Java未チェック:varargsパラメーターの汎用配列作成の未チェック

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>...)
91
skiwi

上記の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});

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

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

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

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

ただし、配列のランタイム型を使用する可変引数メソッドがいくつかあります。この場合、潜在的に安全ではありません。そのため、警告が表示されます。

145
newacct

Javaコンパイラは可変引数に暗黙的な配列作成を使用し、Javaでは汎用配列の作成が許可されていないため(型引数は再構成できないため)。

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

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

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

13
Philip Voronov