아이템 28. 배열보다는 리스트를 사용하라

weekbelt·2022년 11월 20일
0

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

package me.whiteship.chapter05.item28.erasure;

import java.util.ArrayList;
import java.util.List;

public class IntegerToString {

    public static void main(String[] args) {
        // 공변
        Object[] anything = new String[10];
        anything[0] = 1;
        
        // 불공변
        List<String> names = new ArrayList<>();
        List<Object> objects = names;

    }
}

anything배열을 보면 오른쪽 타입은 Object배열이고 왼쪽은 String타입입니다. Object와 String의 상속관계는 String이 Object를 상속하고 있습니다. 따라서 String타입을 Object타입으로 변환이 가능합니다. 하지만 제네릭은 불공변 입니다. anything은 Object배열 타입을 참조하고는 있지만 실제 인스턴스는 String의 배열입니다. 하지만 이 부분이 아무 문제 없어보이지만 분명히 문제가 있는 코드입니다. anything이라고 참조하고 있는 배열은 문자열의 배열입니다. 그럼에도 불구하고 위와같이 숫자를 넣는거는 잘못된 코딩입니다. 하지만 List는 String의 List를 Object의 리스트로 참조할 수 없습니다. 이 둘은 그냥 다른타입 입니다. 따라서 컴파일시점에 오류가 납니다. 이것이 불공변입니다.

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

package me.whiteship.chapter05.item28.erasure;

import java.util.ArrayList;
import java.util.List;

public class IntegerToString {

    public static void main(String[] args) {
        // 공변
        Object[] anything = new String[10];
        anything[0] = 1;
        
        // 불공변
        List<String> names = new ArrayList<>();
        List<Object> objects = names;

    }
}

실체화라는건 코딩을 할 때 작성한 타입이 런타임에 유지가 되는지입니다. List같은 경우 String타입의 리스트이지만 컴파일은하면 String이 사라집니다. 실체화 되지 않는다는 뜻입니다. 그 이유는 하위버전의 호환성 때문입니다.

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

package me.whiteship.chapter05.item28.erasure;

import java.util.ArrayList;
import java.util.List;

public class IntegerToString {

    public static void main(String[] args) {

       // 제네릭과 배열을 같이 사용할 수 있다면...
       List<String>[] stringLists = new ArrayList<String>[1];
//        List<Integer> intList = List.of(42);
//        Object[] objects = stringLists;
//        objects[0] = intList;
//        String s = stringLists[0].get(0);
//        System.out.println(s);
    }
}

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

profile
백엔드 개발자 입니다

0개의 댓글