미션을 진행하면서 배열과 리스트를 아무 생각 없이 섞어서 썼는데, 배열과 리스트의 차이에 대해서 공부해보라는 리뷰를 받았다..!
배열은 공변이다.
공변이란? 함께 변한다는 뜻이다.
예를 들어 Sub가 Super의 하위 타입이라면, 배열 Sub[]는 배열 Super[]의 하위타입이 된다.
제네릭은 불공변이다. 리스트는 제네릭을 사용하기 때문에 또한 불공변이다.
불공변이란? 공변의 반대 개념이다. Sub가 Super의 하위 타입이라도
List<Sub>는 List<Super>의 하위 자료형이 될 수 없다.
배열과 리스트가 가진 공변과 불공변이라는 성질은 오류가 발생하는 시점을 다르게 한다.
(1) 배열
Object[] objectArray = new Long[1];
array[0] = "문자열";
배열은 공변이라고 했다. 그러면 첫줄에서 Long은 Object의 하위 자료형이므로 Long[]도 Object[]의 하위 자료형이 되고, 컴파일 단계에서 별 문제 없이 넘어가게 된다.
그러면 오류가 난다는 것을 런타임때가 되어서야 알게 된다.
(2) 리스트
List<Object> objectList = new ArrayList<Long>();
objectList.add("문자열");
반면 제네릭 타입은 불공변이기 때문에 첫줄에서 컴파일 에러를 발생시킨다.
(1) 배열
배열은 런타임에 타입이 실체화 된다.
Object[] objectArray = new Long[1];
런타임에 ObjectArray의 타입이 Long 타입으로 바뀌게 되는 것이다.
그러면 배열은 런타임일 때 타입이 안전하지만, 컴파일 할 때는 안전하지 않을 수 있다.
(2) 리스트
리스트는 런타임때에 타입이 소거된다.
List<Integer> list = new ArrayList<Integer>();
->
List list = new ArrayList();
리스트는 컴파일 할 때 타입을 확인하고 런타임에 소거하기 때문에 컴파일 할 때는 타입이 안전하지만 런타임에는 안전하지 않을 수 있다.
따라서 리스트를 쓰면 런타임에 오류를 발견하는 일 없이, 컴파일 때 오류를 발견할 수 있다. 또한 실체화와 소거의 특성때문에 두 타입을 섞어 쓸 경우는 타입의 안정성을 보장해주지 못한다. 그러므로 되도록 리스트로 통일하여 쓰도록 하자!
리스트를 써야할 거 같네요!