개발 공부/Java

이펙티브 자바 아이템 31 - 한정적 와일드카드를 사용해 API 유연성을 높이라 - 완벽 공략

개발인생 2022. 12. 17. 13:53
반응형

아이템 31 - 한정적 와일드카드를 사용해 API 유연성을 높이라 - 완벽 공략

이 글은 백기선 님의 이펙티브 자바 강의와 이펙티브 자바 3 / E 편을 참고하여 작성하였습니다.

타입 추론

타입 추론은 타입을 추론하는 컴파일러의 기능이다.

자바에서는 타입 추론을 여러가지 형태로 지원하고 버전이 올라가면서 지원하는 범위와 용도가 늘고 있다.


public class BoxExample {

    private static <U> void addBox(U u, List<Box<U>> boxes) {
        Box<U> box = new Box<>();
        box.set(u);
        boxes.add(box);
    }

    private static <U> void outputBoxes(List<Box<U>> boxes) {
        int counter = 0;
        for (Box<U> box: boxes) {
            U boxContents = box.get();
            System.out.println("Box #" + counter + " contains [" +
                    boxContents.toString() + "]");
            counter++;
        }
    }

    private static void processStringList(List<String> stringList) {

    }


    public static void main(String[] args) {
        ArrayList<Box<Integer>> listOfIntegerBoxes = new ArrayList<>();
        BoxExample.addBox(10, listOfIntegerBoxes);
        BoxExample.addBox(20, listOfIntegerBoxes);
        BoxExample.addBox(30, listOfIntegerBoxes);
        BoxExample.outputBoxes(listOfIntegerBoxes);

        // Target Type
        List<String> stringlist = Collections.emptyList();
        List<Integer> integerlist = Collections.emptyList();
        BoxExample.processStringList(Collections.emptyList());
    }
}

타입 추론은 자바 컴파일러가 어떤 타입을 쓸지 우리가 명시하지 않아도 알아내는 것이다.

위의 코드에서 ArrayList<Box<Integer>> listOfIntegerBoxes = new ArrayList<>(); 부분을 보자.

타입 추론이 없었다면 ArrayList<Box<Integer>> listOfIntegerBoxes = new ArrayList<<Box<Integer>>(); 이렇게 정의했어야했다.

그러나 타입 추론이 있기 때문에 <> 연산자를 사용해 타입 선언을 생략할 수 있다.

컴파일러가 왼쪽에 정의되어있는 타입을 보고 타입을 추론해준다.

주의할 점은 new ArrayList() 이렇게 정의하면 로 타입 을 사용하게 된다는 것이다.

그러므로 반드시 <> 연산자를 사용해야한다.

이러한 타입 추론은 제네릭 메서드 호출 시에도 동일하게 적용된다.

addBox 를 호출 할 때 리턴타입을 BoxExample<Integer>.addBox(10, listOfIntegerBoxes); 처럼 적어주어야 하지만

타입 추론 덕분에 BoxExample.addBox(10, listOfIntegerBoxes); 로 선언할 수 있다.

List<String> stringlist = Collections.emptyList(); 에서

List<String> stringlist타겟 타입 이다.

타겟 타입 을 보고 Collections.emptyList() 애서 우리가 원하는 타입으로 만들어준다.

// emptyList 내부
 public static final <T> List<T> emptyList() {
        return (List<T>) EMPTY_LIST;
    }

타겟 타입을 보고 T 라는 타입을 추론하게 된다.

타겟 타입의 범위는 자바 8 에서 메서드의 인자 타입까지 확장이 된다.

    private static void processStringList(List<String> stringList) {

    }

processStringList 메서드에서 인자로 받고 있는게 List<String> 타입이기 때문에

자바 7버전 에서는 BoxExample.processStringList(Collections.<String>emptyList()); 처럼 타입을 명시했다.

자바 8버전 부터는 BoxExample.processStringList(Collections.emptyList()); 로 코드를 작성해도 타겟 타입을 보고 타입을 추론하게 된다.

var listOfIntegerBoxes = new ArrayList<Box<Integer>>();

최근에는 위와 같이 변수의 타입 추론도 가능해졌다.

반응형