Java unchecked : varargs 매개 변수에 대해 확인되지 않은 일반 배열 생성


112

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
당신은 자바에서 당신은 0과 새로 만든 int 배열을 초기화 할 필요가 없습니다 않는 다른 무엇이든간에 ...
토마스 뮐러

1
이 @ThomasMueller 좋은 캐치
skiwi

답변:


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

12
누구에게도 당장 분명하지 않은 경우 (나에게 그렇지 않은 것처럼) Javadocs에 @SafeVarargs안전하지 않은 메소드의 예가 있습니다. docs.oracle.com/javase/7/docs/api/java/lang/SafeVarargs .html
michiakig 2015 년

3
그래서 @SafeVarargs당신의 메소드 가 배열의 요소 만을 소비 하고 배열 에 넣을 요소를 생성하지 않을 때 사용할 수 있습니까? 다른 메서드에 의해 조작 될 수있는 필드에 배열 인수를 할당하는 경우에는 안전하지 않은 작업이 수행되지 않는다고 결정하는 것이 사소하지 않을 수 있으므로 특별한주의를 기울여야합니다.
neXus

13

Java 컴파일러는 varargs에 대해 암시 적 배열 생성을 사용하고 java는 일반 배열 생성을 허용하지 않기 때문입니다 (유형 인수를 수정할 수 없기 때문에).

아래 코드는 정확하므로 (이러한 작업은 배열에서 허용됨) 확인되지 않은 경고가 필요합니다.

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.