IT/디버깅

java: incompatible types capture#1 of ? extends cannot be converted to 원인 및 해결 wildcard

happy_life 2022. 7. 15. 18:25
문제 코드
public static ArrayList<? extends Product> merge(
            ArrayList<? extends Product> list, ArrayList<? extends Product> list2) {
        ArrayList<? extends Product> newList = new ArrayList<>(list);

        newList.addAll(list2);

        return newList;
    }

 

 

문제분석

 

에러

 

문제 분석

 

 

 

문제 원인

wildcard가 컴파일 시 내부적으로 "capture of "를 콜해서 타입을 지정하는데 위의 예제인 경우, capture of가 콜 되는 시점에 어떤 타입이 들어오는지(예를 들어, 아래 코드처럼, 하나는 Computer, 하나는 Product)을 알 수 없으므로
컴파일 에러가 발생한다. 제네릭은 부모 자식 상관없이 형이 같아야하는데 와일드 카드로 받아봤자 Computer, Product인지는 구체적으로 모르기 때문에 컴파일 에러가 발생하는 것이다..

 

제네릭에서는 상속과 관계 없이 형이 일치해야 한다. Computer면 Computer끼리, Product이면 Product끼리 말이다. 위의 에러난 예제 코드의 경우, 와일드 카드이기 때문에 일단 Computer, Product 형의 ArrayList가 매개변수로 들어갈 수는 있다. 와일드 카드로 선언된 매개변수(<? extends Product>)의 범위 안에 들어가기는 하기 때문이다. 하지만 컴파일 타임에 각각 Computer인지, Product인지는 구체적으로 모른다. 따라서 위의 예제 코드처럼 다른 형이 들어갈 수도 있지만, 형이 달라 addAll메서드의 매개변수로 들어올수 없게 되는 것이다.  (제네릭은 상속에 관계 없이 형이 일치해야 하므로,  Computer형을 가진 ArrayList에 다른 형인 Product를 addAll할 수 없다.)

 

 

 

해결
public static<T extends Product> ArrayList<T> merge(
        ArrayList<T> list, ArrayList<T> list2) {
    ArrayList<T> newList = new ArrayList<>(list);

    newList.addAll(list2);

    return newList;
}

형이 구체적으로 지정되지 않아서 발생한 오류이므로, 형을 확실하게 해주면 된다. 제네릭 메서드를 통해 형을 일치시켜주어 이를 해결할 수 있다.