제네릭(Generic)

제네릭(Generic)

제네릭(Generic) 프로그래밍은 데이터 형식에 의존하지 않고, 하나의 값이 여러 다른 데이터 타입들을 가질 수 있는 기술에 중점을 두어 재사용성을 높일 수 있는 프로그래밍 방식이다.

출처 : 위키백과 - 제네릭 프로그래밍

위키백과의 설명처럼 Generic이란 데이터의 형식에 구애받지 않도록 일반화 하는 것을 말한다. 여기서 데이터의 형식을 일반화 한다는 것은 무슨 의미일까?

사례 : 택배 회사의 고민

택배 회사에서 의뢰받은 배송 물품을 어떻게 포장하는 것이 좋을까?

택배 회사는 사용자가 의뢰한 배송 물품을 파손되지 않도록 목적지까지 운송하는 역할을 수행한다. 이를 위해서 의뢰받은 물품을 포장해야 할 필요가 생기는데, 다양한 물품들을 그에 맞게 포장하려면 매우 많은 종류의 상자들이 필요할 것이다. 또한 종류별로 상자들을 만든다 하더라도 새로운 품목이 언제든지 등장할 수 있는 사정이기 때문에 고민을 하고 있다.

우리는 이미 해결책을 알고 있다. 지금도 우리의 집으로 배송되는 물품들이 어떻게 오는지 알고 있기 때문이다. 결론부터 말하면 상품을 일일이 고려할 필요 없이 일정한 크기의 상자를 준비하여 배송품을 넣고 배송하면 된다. 상품이 들어가지 않으면 들어갈 만한 다른 규격의 상자에 넣으면 된다.

하지만 여기서 문제가 발생한다. 우리는 다양한 상품을 취급하고 있으며, 그중에는 파손 위험이 큰 유리나 가전제품들도 있을 것이다. 하지만 상자만 가지고는 이 제품이 어떤 내용물을 가지고 있는지 알기 어렵다. 상자에 어떠한 물건이 들어있던 우리는 상자로 인식하며, 특별한 표시가 없다면 내용물의 형태를 알기 어렵다는 것이다. 자바로 비유하면 형태를 알 수 없기 때문에 Object라고 생각할 수 밖에 없다는 것이다.

상자 안에 들어있는 물건들은 일반적으로 스티커를 이용하여 표시한다. 스티커에는 형태에 대한 매우 추상적인 정보가 있을 수도 있고, 구체적인 정보가 있을 수도 있다.

물건을 1개만 넣을 수 있는 택배상자는 다음과 같이 정의할 수 있다.

Box.java
public class Box<E> {
	private E item;
	public void setItem(E item) {
		this.item = item;
	}
	public E getItem() {
		return this.item;
	}
}

GenericExample01에서 각각의 객체들의 내용물은 다음과 같이 설정된다.

  • a는 Generic 형태를 지정하지 않았기 때문에 item 형태는은 Object로 설정된다.

  • b는 Generic 형태를 String으로 지정했기 때문에 item 형태는 String으로 설정된다.

  • c는 b의 축약형 표현이며, 우측은 편의상 생략이 가능하다.

  • d는 ?로 지정한 경우 명시적으로 Object라고 작성한것과 동일하게 설정된다.

a, b, c, d는 다 같은 상자이지만 내용물의 형태가 다르기 때문에 동일한 형태로 인식되지 않는다. 또한 a는 명시적으로 Generic 형태가 작성되지 않았기 때문에 경고가 발생한다.

만약 int와 같은 원시형(raw type)을 Generic으로 설정하고 싶다면 int가 아니라 Integer로 설정해야 한다. Generic은 참조형태만 설정할 수 있다.

다음 코드는 오류가 발생한다.

Box<int> e = new Box<>();

원시형은 반복자로 사용할 수 없으며, 다음 코드 형태로 사용해야 한다. 이 부분에 대해서 상세한 설명은 Java Language Specification(JLS) - 4.8. Raw Types 을 참고한다.

Box<Integer> e = new Box<Integer>();

다음과 같이 객체의 우측을 생략하여 표현할 수 있다.

Box<Integer> f = new Box<>();

이처럼 Generic을 클래스에 적용시켜 자료형을 생성 시 결정할 수 있도록 일반화할 수 있다.

Last updated