brunch

You can make anything
by writing

C.S.Lewis

by 이승현 Apr 24. 2018

제네릭(Generics)

#26 제네릭 타입을 애용하자

Effective Java - 제네릭(Generics)


#26 제네릭 타입을 애용하자


#01 Stack class


이 클래스는 Object를 기반으로 한 Stack 클래스입니다.

pop 메서드를 통해 꺼낸 Object 객체를 캐스팅해야 하는데 이 과정에서 런타임 에러가 발생할 수 있습니다.

이러한 클래스들이 제네릭화(generification)의 우선 대상입니다.

제네릭화 : 제네릭 타입을 이용할 수 있도록 개선하는 것


제네릭화에 대해서 알아보겠습니다.




제네릭화(generification)


#02 Generic Stack class

Object를 기반으로 한 Stack 클래스를 일단 제네릭화한 GenericStack 클래스입니다.

클래스를 제네릭화 하기 위한 여러 단계를 살펴보겠습니다.


#01 클래스 선언부에 하나 이상의 타입 매개변수를 추가

수정 전 : public class Stack 
수정 후 : public class GenericStack<E>


#02 모든 Object 타입을 타입 매개변수로 변경 후 컴파일

수정 전 : private Object[] elements
수정 후 : private E[] elements


E[] 배열을 만드는 과정에서 아래와 같이 컴파일 에러가 발생합니다.

이전 글에서 설명했듯이, 배열(구체화)과 E(비 구체화) 간에는 타입 안정성 측면에서 문제가 발생할 수 있기 때문에 같이 이용할 수 없습니다.

구체화 : 컴파일 시보다 런타임 시에 더 많은 정보를 가지고 있음
비 구체화 : 런타임 시보다 컴파일 시에 더 많은 정보를 가지고 있음


#03 비구체화 배열 생성


이를 해결하기 위한 두 가지 방법이 있습니다.


1. 생성자에서 Object 배열을 생성하고, 이를 제네릭 타입으로 캐스팅


이 과정에서 당연히 ClassCastException 경고가 뜨는데, 캐스팅이 안전하다고 밝혀지면 @SuppressWarnings 주석을 통해 해결할 수 있습니다.

#04 Object 배열 생성 후, Generic 배열 타입으로 캐스팅


2. Object 배열을 선언하고, 이를 제네릭 타입으로 캐스팅 반환


이 과정에서도 ClassCastException 경고가 뜨는데, 캐스팅이 안전하다고 밝혀지면 @SuppressWarnings 주석을 통해 해결할 수 있습니다.

#05 Object 배열 선언 후,  Generic 배열 타입으로 캐스팅 반환


두 가지 방법은 Object 배열을 언제 선언, 생성하고 또 이를 Generic 배열로 언제 캐스팅하는지에 따른 차이점이 있습니다.

둘 중 어떤 방법을 이용할지는 상황이나 취향에 달려있는데, 첫 번째 방법은 한 번만 제네릭 타입으로 캐스팅하면 되기 때문에 좀 더 보편적으로 이용되고 있습니다.




GenericStack 클래스를 이용하는 코드입니다.

String 요소들을 Stack 내부에 push 하고, 이를 다시 pop 해서 대문자로 변환할 때 별도의 명시적인 캐스팅 과정이 필요 없습니다.

컴파일러에서 자동으로 생성한 캐스트 코드가 이를 대신해주기 때문입니다.


#06 no casting


이처럼 제네릭 타입은 별도의 캐스팅 과정이 필요한 코드보다 더 안전하고 편리합니다.

따라서 새로운 타입을 설계할 때 캐스팅 없이 이용할 수 있다면 제네릭하게 만드는 게 더 낫습니다.




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