28. 배열보다는 리스트를 사용하라
배열과 리스트를 섞어쓰다 컴파일 오류나 경고를 만나면, 가장 먼저 배열을 리스트로 대체하라!
📌 1. 발표 전 알아야 할 개념
✅ 컴파일과 런타임
1. 컴파일(Compile)
프로그램 소스코드를 기계어(바이너리 코드) 혹은 중간 코드(바이트코드)로 변환하는 과정
컴파일러가 수행
실행 전에 오류를 확인하고 수정할 수 있음
Java, C, C++ 등 컴파일 언어에서 사용
2. 런타임(Runtime)
프로그램이 실제로 실행되는 시점
동적으로 변수 값을 변경하거나, 메모리를 할당하는 과정이 포함
런타임 오류가 발생하는 곳
3. 전체 실행 과정을 알아보자!
소스 코드를 작성한다 (.java / .c 등)
컴파일(Compile) - 컴파일 과정에서 문법 오류가 있으면 실행 안됨
실행 파일 생성 - Java는 .class / C는 .exe 등
런타임(Runtime) - 실행, 변수 값 할당, 메모리 관리, 예외 처리가 이루어짐
✅ classCastException
객체의 타입을 변환(캐스팅)하려고 할 때, 타입이 호환되지 않아 발생하는 런타임 에러러
📕 2. 배열과 제네릭릭의 차이
2-1. 공변 vs 불공변 : 타입 관계계의 차이
공변: (함께 변한다) 하위 타입을 상위 타입에 넣을 수 있다불공변: 하위 타입을 상위 타입에 넣을 수 없다
🔗 배열은 공변
배열은 공변이기에, Car[]에 SportsCar[]를 할당할 수 있음
그러나 타입 오류가 있을 경우
런타임 에러(ArrayStoreException)발생
🔗 제네릭릭는 불공변
리스트는 불공변, 서브타입을 대입할 수 없음
컴파일 단계에서 컴파일 에러 발생!
2-2. 실체화 : 타입 검사의 차이
실체화: 런타임에 타입 정보를 유지하는 것
🔗 배열은 실체화
배열은 생성될 때 요소의 타입 정보를 함께 저장
런타임에서 안전성 검사
🔗 제네릭는 타입 소거
제네릭은 컴파일 시에 타입 정보를 검사하고, 런타임에는 타입 정보를 제거한다
컴파일 시 : List, 런타임 : List
런타임에 타입 정보를 확인할 수 없음
2-3. 배열 vs 리스트
배열 : 런타임 실행 중 검사 → 실행 도중 오류 발생(ClassCastException) → 위험! → 타입 안정성 낮다
리스트 : 컴파일, 코드 작성 시 검사 → 실행 전 오류 발생 → 안전 → 타입 안정성 높다다
➡️ 따라서 배열보다 리스트가 타입 안전성이 더 높다!
🙅🏼♂️ 3. 제네릭과 배열은 잘 어우러지지 않는다
3-1. 제네릭 배열 생성은 불가하다 💥
제네릭 배열
List<String>[]은 생성할 수 없다컴파일 시 타입 정보가 소거되기 때문에, 런타임에서 배열의 타입을 검사할 수 없기 때문
제네릭 배열 생성이 가능하다고 가정하고, 아래 코드를 확인해 봅시다다
List 객체만을 담을 수 있는 starListArr 배열 생성
List 타입의 intList 생성 → 정수 123 리스트에 추가
strListArr 배열을 Object[] 타입의 objArr 변수에 할당함. 배열이 공변이므로, List은 Object의 하위 타입. 할당 가능
objArr는 Objec[] 타입이므로 List 타입 할당 가능. objArr[0]에 intList 할당.
strListArr[0]에서 String을 가져오려고 했으나, List 타입의 intList를 참조하고 있음. ➡️ ClassCastException
따라서 제네릭 배열은 생성할 수 없다!
✨ 4. 배열 대신 리스트를 사용하자
책에서는는
Chooser<T>클래스를 사용하여 제네릭 배열을 사용하면 안 되는 이유 및 리스트를 활용해야 하는 이유에 대해 소개했다이를 좀 더 쉽게 변형해서 알아보자.
1. 제네릭을 사용하지 않은 구현 - Object
Object를 반환하므로 사용자가 매번 형변환을 해야한다
Object로 선언해서 아무 타입이나 저장 가능하다
제네릭을 시급히 적용해야 한다!!
제네릭을 적용한 첫 시도 - 제네릭 배열 사용
3. 리스트를 사용하자. 💥
➡️ 리스트를 사용하자!
💨 향후 확장 포인트
List<?>,Map<?>과 같은 비한정적 와일드카드 타입을 통해 일부 실체화할 수 있다
🤖 최종 결론
배열은 실체화되어 런타임에서도 타입 정보를 유지하지만, 제네릭은 타입 소거를 한다 배열과 제네릭을 함께 사용할 경우 타입 안전성이 위험하다 제네릭 배열을 만들지 말고 리스트를 사용하자!
❗어려웠던 점
제네릭에 대한 개념이 확실하지 않아서 헷갈렸는데, 이 아이템을 통해 이해를 높일 수 있었다!
😶🌫️ 느낀점
제네릭과 배열의 충돌을 이해하는 것이 중요하다!
사용하는 타입, 메서드가 많아지고 프로젝트 볼륨이 커질수록 고려해야되는 부분이 많다.
Last updated