[.NET vs JAVA] Boxing VS Generic

닷넷은 2.0부터, 자바는 1.5부터 제네릭을 지원한다.
당연히 그 전까지는 박싱과 언박싱을 써왔다.
그리고 그때당시 개발자들은 이미 그런 방식에 익숙하기 때문에 제네릭을 안쓰기도 한다.
특히 자바개발자는 제네릭 개념이 꽤 늦게 들어왔기 때문에 제네릭 안쓰는 개발자가 더 많다.
심지어는 나처럼 제네릭 쓰지 말라는 이상한 소리를 들을 수도 있다.

자, 그렇다면 이 두 언어별 박싱과 제네릭의 특징을 알아보자.

.NET

닷넷은 닷넷 2.0부터 출연했는데, 시기적으로는 꽤 빨리 들어온 것이다.
어쨌든, 얘네들의 박싱과 언박싱은 C/C++의 단순한 업캐스팅 개념으로 만든 것이 아니다.
일단 닷넷에 있는 모든 객체는 object 클래스에 상속된다. 설령 struct로 정의한다 해도.
근데 이 structnullable이 불가능하다. 물론 Nullable<T>로 가능은 하지만.
얘네들의 박싱 개념을 C/C++로 표현하면 다음과 같다.

int num1 = 123;
object obj = num1;
int num1 = 123;
int *obj = new int;
(*obj) = num1;

즉, 전문적으로 말하자면 힙에 새로운 객체가 생성되면서 값이 복사되는 그런 개념이 되는 것이다.
그걸 Generic 이라는 개념을 도입했는데, 이 방식을 사용하면 Boxing과 Unboxing이 필요 없어진다.
ArrayList를 예로 들어보자.

ArrayList arr1 = new ArrayList();
ArrayList<string> arr2 = new ArrayList();

자. 일단 시니어 닷넷 개발자라면 HashTable 사용에 익숙할 것이다. 어쨌든, 얘네들은 동적 배열을 만드는데,
일정 개수만큼 (보통 16) 자리를 부여한다. 근데 제네릭이 없으니 뭐로 하겠나. 당연히 최상위 객체인 object 자리가 되는 것이다.
그러면 arr1.Add(num1); 을 넣으면 어떻게 되느냐. 싫어도 Boxing 해야 한다. 그럼 반대로 가져올때는? 당연히 강제 Unboxing 이다.
그에 반해 arr2 는 제네릭으로 타입이 명시되어 있다. 그리하여 닷넷 런타임은 일정 개수만큼 자리를 부여하되,
타입이 정해졌으니 object로 할 필요 없고 명시도니 string 자리를 부여한다.
그럼 거기다가 string 값만 넣으면 되니 Boxing 과 Unboxing 이 필요 있겠는가? 당연히 필요 없어지게 되는 것이다.
그래서 닷넷의 제네릭이 괜히 성능 얘기 나오는 게 아니고, 그걸 경험한 닷넷 개발자들은 제네릭에 익숙한 것이다.

Java

자바는 Auto Boxing 이란 개념이 있다. 닷넷 개발자는 생소할 텐데,
이 Autoboxing 개념은 자바 1.5에서 출발했다.
자바는 primitive type, Class, 그리고 null 이 있다.
자바 개발자들은 알 만한 사실이지만 primitive type 에 null 허용되는 건 당연히 아니다.
Auto boxing이 생기는 큰 이유는 바로 primitive type 와 Class 간 처리 때문이다.
숫자 타입으로는 primitive type 인 int 와, Class 인 Integer 가 있다.
이 둘이 오갈 때 당연히 메소드를 호출하는데,
int -> Integer = Integer.valueOf()
Integer -> int = (Integer).intValue()
이 둘을 명시적으로 Boxing 한다면 어떻게 될까? 먼저 primitive type 는 당연히 클래스가 된다.
Object도 클래스기 때문에 primitive type 를 직접 관리할 수 없기 때문이다.

int num1 = 123;
Object obj = num1;
//는 아래와 같다.
Object obj = Integer.valueOf(num1);

그렇다고 클래스라고 해서 그냥 넣는가? 안타깝게도 닷넷과 다를 바 없다.
자바나 닷넷이 Object 업캐스팅 개념이 없으니까.

자, 이제 제네릭으로 간다.
자바는 닷넷 제네릭과 달리 메모리에 관여하는 게 아니라 그저 심볼 역할만 하는 녀석이다.
그래서 ArrayListArrayList<T> 는 같은 클래스다.
닷넷은 ArrayListArrayList<T> 는 엄연히 다른 클래스로 취급하는 것과는 대조적이다.
이것은 당연히 하위 호환성 때문이다. 닷넷은 1.x과의 호환성을 포기하고 제네릭을 도입했으니 가능한 얘기다.

그래서 제네릭을 달아봐야 add() 로 넣을 때 박싱해버리고 get() 할때 언박싱한다.
제네릭 달아봐야 박싱 언박싱 그대로 해버리니… 그래서 닷넷과 달리 성능향상이 없다.
그저 컴파일 타임에서 타입 검증에 대한 강화 용도로 쓰이게 된다.

그래서 자바 개발자들은 제네릭 안써도 잘 한다. 굳이 필요가 없다고 느낄 정도다.
그래도 검증과 무결성 측면에서는 당연히 제네릭이 유리하다.
제네릭 쓴다고 성능 떨어지는것도 향상되는 것도 아니지만, 방어적 코딩이 나중에 장애나 유지보수에 어떻게 빛을 발하는지 겪어본 사람은 알 것이다.

결론

어쨌든 공통적으로 제네릭은 타입에 민감한 닷넷과 자바에게는 신의 한수인 것이다.
그러니 왠만하면 쓰자.

composite / 2015년 4월 8일 / Piss Development
태그:,

답글 남기기

Your email address will not be published / Required fields are marked *