이번 규칙은 들어가기 전에 알아야 할 개념들이 있습니다.
저도 잘 몰라서 조사하고, 테스트 해보니 천천히 설명해볼게요.
배열과 제네릭(List)의 차이 중 하나로
배열은 공변 자료형(covariant)이고, 제네릭는 불변 자료형(invariant) 입니다.
영어에 익숙하신 분들은 co 접두사를 보고 금방 눈치를 채질 수도 있으신데요.
A와 B의 자료가 있을 때
공변 자료형은 A가 B의 하위 자료형이라면, A의 배열도 B의 하위 자료형이 됩니다.
반대로 불변 자료형은 상위나 하위의 자료형이 될 수 없고요.
밑의 코드를 한번 볼까요.
Object 배열과, Object List를 만들어 봤습니다.
둘 다 실행이 안되는 코드입니다.
하지만 8번 라인의 코드는 런타임 중에 에러가 나고
11번 라인의 코드는 컴파일 과정에서 에러가 나죠.
배열은 실체화(refication) 되는 자료형입니다.
배열에 들어가 있는 자료들의 형은 런타임 과정 중에 결정됩니다.
그래서 컴파일 과정을 패스하고, 런타임 중에 에러가 나는 것입니다.
반면 제네릭은 삭제(erasure) 과정을 통해 구현됩니다.
자료형 조건은 컴파일 과정에서 검사를 합니다.
그리고 맞지 않으면 위의 코드처럼 에러를 내버리죠.
그리고 런타임에 들어가면 자료형 정보는 삭제해버립니다.
컴파일 과정에서 한번 체크를 했으니 자료형 정보는 더 이상 필요없는 정보겠죠?
런타임에 들어가게 되면 자료형 정보를 사용하지 않는 삭제(erasure) 덕분에
제네릭 자료형은 오래된 코드와도 쉽게 연동합니다.
이런 차이점 때문에 제네릭의 배열 형태는 생성되기가 어렵습니다.
생성하게 된다면, 형 안전성이 보장되지 않기 때문이죠.
이해를 돕기위한 예제 코드입니다.
Arrays.asList 메소드는 일반 배열을 ArrayList로 전환해주는 메소드입니다.
이 코드는 첫째 줄에서 generic array creation 에러가 납니다.
하지만 컴파일이 된다고 가정을 해보죠.
그러면 제네릭 배열이 만들어 질 것입니다.
2번째 라인에서 integer 데이터형을 보관하는 리스트를 만들었습니다.
그리고 Object를 보관하는 배열을 만들어 lists를 넣습니다.
배열은 공변 자료형(covariant)이기 때문에 가능합니다.
4번째 라인에서 오브젝트의 배열에 List<Integer> 자료형을 넣습니다.
아까 제네릭의 형은 삭제를 통해 구현된다고 말씀드렸죠?
즉, 현재 integers 리스트는 자료형에 대한 정보가 없습니다.
자료형은 그냥 List[] 입니다. 내용물이 비어있죠.
그러니 objects 배열에 들어갈 수 있게 됩니다.
그리고 5번째 라인에서 문제가 발생합니다.
string만 저장한다고 선언한 lists 배열에서 값을 꺼내서 String s 변수에 넣어야 하는데
꺼내고 나니 정작 int 데이터인 것입니다.
그래서 ClassCastException이 발생할 것입니다.
이러한 일이 생기는 것을 막기 위해
첫번째 라인의 컴파일 시 에러를 내버리는 것입니다.
이렇게 List<>는 런타임 때보다 컴파일 시 더 많은 정보를 요구합니다.
164 page 뒷부분에 List 동기화에 대한 페이지도 두 장 정도 할애하고 있는데
지금 읽어봐도 이해가 안된다..
체크 해놓고 나중에더 공부하여 수정하여 정리해야겠다.
'프로그래밍 > Java' 카테고리의 다른 글
이펙티브 자바 규칙 26 - 가능하면 제네릭 자료형으로 만들 것 (0) | 2018.04.07 |
---|---|
이펙티브 자바 규칙 24 - 무점검 경고를 제거하라 (0) | 2018.03.09 |
이펙티브 자바 규칙 23 - 새 코드에는 무이자 제네릭 자료형을 사용하지 마라 (0) | 2018.03.08 |