ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 아이템28. 배열보다는 리스트를 사용하라
    Java/이펙티브 자바 2023. 9. 23. 12:28

    핵심 정리1 - 배열과 제네릭은 잘 어울리지 않는다.

    - 배열은 공변(covariant), 제네릭은 불공변

    - 배열은 실체화(reify) 되지만, 제네릭은 실체화 되지 않는다. (소거)

        ㆍ제네릭은 컴파일할 때 타입이 사라진다.

    - new Generic<타입>[배열] 은 컴파일 할 수 없다.

    - 제네릭 소거 : 원소의 타입은 컴파일 타임에만 검사하며 런타임에는 알 수 없다.

    public static void main(String[] args) {
            // 공변 : 같이 변한다.
            Object[] anything = new String[10];
            anything[0] = 1;    // 잘못된 동작이지만 컴파일러가 잡지 못한다. - 런타임 에러
    
            // 불공변 : 같이 변하지 않는다.
            List<String> names = new ArrayList<>();
    //        List<Object> objects = names; // 컴파일 에러.
    }

     

    핵심 정리2

    - 배열기반은 범용적으로 사용하기 어렵다. - 타입 캐스팅을 써야함.

        ㆍ범용적으로  쓸 수 있는 클래스의 타입 형변환 문제 발생 -> 제네릭 사용

     

    완벽 공략 - @SafeVarargs

    : 생성자와 메서드의 제네릭 가변인자에 사용할 수 있는 애노테이션

     

    - 제네릭 가변인자는 근본적으로 타입 안전하지 않다. (가변인자가 배열이니까, 제네릭 배열과 같은 문제)

    - 가변 인자 (배열)의 내부 데이터가 오염될 가능성이 있다.

    - @SafeVarargs를 사용하면 가변 인자에 대한 해당 오염에 대한 경고를 숨길 수 있다.

    - 아이템 32. 제네릭과 가변인수를 함께 쓸 때는 신중하라.

    public class SafeVaragsExample {
    
    //    @SafeVarargs    // Not actually safe!
        static void notSafe(List<String>... stringLists) {  // List<String>[] 이 가능하지만 전달받은 객체가 오염이 될 수 있다.
            Object[] array = stringLists;       // List<String>... => List[], 그리고 배열은 공변이다.
            List<Integer> tmpList = List.of(42);
            array[0] = tmpList;                 // Semantically invalid, but compiles without warnings
            String s = stringLists[0].get(0);   // ClassCastException at runtime!
        }
    
    //    @SafeVarargs
        static <T> void safe(T... values) {
            for (T value: values) {
                System.out.println(value);
            }
        }
    }

     

     

    댓글

Designed by Tistory.