brunch

You can make anything
by writing

C.S.Lewis

by 이승현 Jun 18. 2018

제네릭(Generics)

#25 배열보다는 List를 사용하자

Effective Java - 제네릭(Generics)


#25 배열보다는 List를 사용하자


배열(Array)은 두 가지 관점에서 제네릭 타입과 다릅니다.


#01 배열은 공변(convariant)이다.


공변(convariant)이라는 단어를 처음 듣는데 뜻은 아래와 같습니다.

경험적 관계에서 첫 번째 변수의 크기가 두 번째 변수의 크기에 따라 변하는 것을 말한다.
http://terms.naver.com/entry.nhn?docId=1520193&cid=50298&categoryId=50298


예를 들면, 상속 관계인 Super 클래스와 Sub 클래스를 이용해 배열 Super[], Sub[]를 만들면 이 두 배열도 상속 관계라는 의미입니다.

Super 클래스 - Sub 클래스 (상속 관계)
Super[] - Sub[] (상속 관계)


이 와 반대로 제네릭은 불변(invariant)입니다.

예를 들면, 상속 관계인 Super 클래스와 Sub 클래스를 이용해 List<Super>, List<Sub> 만들면 두 List는 상속 관계가 아닙니다.

Super 클래스 - Sub 클래스 (상속 관계)
List<Super> - List<Sub> (아무 관계 아님)


상속 관계를 표현 못하는 제네릭이 어찌 보면 더 안 좋아 보일 수 도 있습니다.


아래 코드는 Object-Long 상속 관계를 이용한 배열과 List(제네릭)입니다.

첫 번째 배열 코드는 컴파일에서는 문제가 없지만 런타임 에러가 발생합니다.

두 번째 List 코드는 컴파일 시에 에러가 발생합니다.


어떤 에러든 런타임 시보다 컴파일 시에서 미리 발견하는 게 더 좋습니다.


#01 Array & Generics




#02 배열은 구체적(reified)이다.


구체적(reified)라는 말은, 런타임 시에 자신의 요소 타입을 체크한다는 의미입니다.


위에서 본 이 코드를 보면, 배열은 컴파일이 아닌 런타임 시에 요소 타입을 체크해 예외를 발생시킵니다.

반대로 제네릭은 컴파일 시에 요소 타입을 체크하고 있습니다.

#02 Array @ Generics


서로 요소 타입을 체크하는 시점이 다르기 때문에 타입 안전성의 문제로 배열과 제네릭은 보통 같이 쓰이지 않습니다.

다른 대안이 있는데 이는 다음에 알아보겠습니다.

#03 Error




배열과 제네릭은 서로 다른 타입 규칙을 가지고 있습니다.

배열 : 공변, 구체적

제네릭 : 불변, 비 구체적


배열은 런타임 시 타입 안전을 체크하지만 제네릭은 컴파일이 타입 안전을 체크하기 때문에, 배열보다는 리스트가 더 안전합니다.




매거진의 이전글 제네릭(Generics)
브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari