본문 바로가기

Programming/JAVA

java : 강력한 형 안정성 기술. generic

우선 generic 이란 개념을 사용할 때 저같은 초보자들을 대상으로 설명하자면.
자료구조의 컬렉션을 사용할 때 쓰이는 type 강제성 기술입니다.
  ArrayList<String> al = new ArrayList<String>();
위와 같이 말이죠. 

위처럼 선언한 ArrayList 자료구조는 String type의 객체만 배열의 멤버들로 사용할 수 있습니다.
(멤버라는 표현이 옳은지는 모르겠네요. 요소, element가 더 정확한 표현이겠지만 편의상 멤버라고 할게요 ㅎㅎ;)

변수 al은 generic을 통해 String으로만 이루어진 자료구조라고 선언되어졌습니다.
이렇게 된다면

public class ArrayList<E> extends AbstractList<E>
                                      implements List<E>, RandomAccess, Cloneable, java.io.Serializable 

public E get(int index) {
RangeCheck(index);
return (E) elementData[index];
    }

public boolean add(E e) {
ensureCapacity(size + 1);  // Increments modCount!!
elementData[size++] = e;
return true;
}

public boolean addAll(Collection<? extends E> c) {
Object[] a = c.toArray();
        int numNew = a.length;
ensureCapacity(size + numNew);  // Increments modCount
        System.arraycopy(a, 0, elementData, size, numNew);
        size += numNew;
return numNew != 0;
}

위와 같은 ArrayList 객체들의 메소드들의 E라는 유형매개변수가 String으로 인식하게 되고
그럼 al이 가리키는 ArrayList 자료구조는 String 타입의 객체들만 멤버로(요소로) 가질 수 있게끔 되는 것이죠.
위의 메소드들은 jre에 있는 ArrayList클래스의 원천소스들 중 멤버변화를 주는 것으로 보이는 메소드들만
빼내어 정리한겁니다. 

generic의 이러한 형 안정성을 보장하는 개념은 런타임시에 가져오게 되는
여러가지의 type 불일치 익셉션들을 컴파일타임의 에러로 미리 잡아줍니다.
(런타임시 나는 에러보다는 컴파일 타임시에 맞게되는 에러가 매우매우 반갑죠? ㅎㅎ;)

여기서 주의해야하는 부분은 generic 내에서 extends라는 키워드입니다.
E라는 유형매개변수에 만약 interface를 넣었다면 어떨까요?
예를 들어 ArrayList<Collection> collectionAl = new ArrayList<Collection>();
요렇게 말이죠.

그럼 public boolean addAll(Collection<? extends E> c) 라는 메소드의 extends 키워드가 무척 무안하지 않을까요?
혹여나 addAll 메소드를 호출하는 클라이언트 코드가 자료구조 객체들 중 구상클래스를 썼다면 더 이상하죠.

주의해야하는 부분은 바로 generic에서의 extends 키워드는 extends + implements 개념이라는 것입니다.
따라서 generic을 쓸 때에 extends 키워드 뒤에 꼭 구상클래스만 써야하거나 둘다 인터페이스만 써야하나 하는
고민은 안해도 된다는 것이죠.

굳이 다른 키워드를 추가하지않고 extends 키워드에 저런 기능을 추가한 것은
이미 예측가능한 키워드들은 수많은 개발자들이 쓰고 있을 것이고,
그에 따라 발생할 엄청난 유지보수비용때문에 욕먹기 싫은 철학이 있다는 비하인드 스토리가.....

generic에 대해서 짧게 작성하였는데 E, T 이런건 그냥 식별자라고 보시면 됩니다.
뭐.... 굳이 의미없는 식별자라고 작성하고 싶진 않은데, 아직 내공이 부족해서인지 그냥 Element의 약자와
Type의 약자를 적어놓았고 이는 java를 사용하는 수많은 개발자들도 이용할만한 방법이라고 생각되네요. 

음... 예전 포스팅에 와일드카드라는 용어를 작성하면서 훗날 포스팅하겠다고 하였는데
( <? extends T> )
곧 포스팅하도록 하겠습니다.