정보공간_1

[4기 광주 박주연] Java Generic 이해 본문

IT 놀이터/Elite Member Tech & Talk

[4기 광주 박주연] Java Generic 이해

알 수 없는 사용자 2013. 12. 4. 00:55

Java Generic 이해


Java Generic에 대해서 간단히 알아보고자 합니다.

우리는 Java나 여러 언어들을 사용해서 프로그래밍을 합니다. 이 과정에서 모듈, 라이브러리 등 많은 것들을 만들게 됩니다. 이 때 우리는 재사용성, 범용성과 같은 이슈를 생각하면서 내가 만든 모듈이 범용적으로 사용되었으면 좋겠다.” 라는 생각을 해보게 됩니다.

 그렇다면 이야기의 방향을 구체적으로 바꿔서 A라는 모듈을 만들고 이 모듈을 소스의 여러 부분에서 사용하게 될 때 우리는 최대한 일반적인 내용들을 모듈이 갖도록 하고 세부적인 사항은 실제 모듈을 사용하는 쪽에서 데이터를 채우거나 동작을 설정하도록 합니다. 그렇다면  동작에 대한 일반화를 넘어서 모듈에 전달되는 데이터 자체에 대해서도 사용하는 쪽에서 결정할 수 있도록 일반화 시키고자 한다면 어떻게 해야 할까요?

“generic”의 사용입니다.

 

Generic을 왜 사용하느냐에 대한 대답은 Oracle Tutorial 페이지[1] 에서 간단 명료하게 설명하고 있습니다. Generic을 사용함으로써 강력한 타입 체크가 가능하며 구현하는 모듈에(또는 기능에) Generic을 사용해 generic 알고리즘을 구현할 수 있습니다.

Generic 사용시의 이점[1]

1.     강력한 타입체크

A.     소스 컴파일 과정에서 동적으로 설정되는 데이터들에 대해 컴파일러가 타입을 체크해줍니다.

2.     캐스팅 과정의 생략

A.     List와 같은 Collection 타입에 데이터를 넣고 가져오는 과정에서 타입 캐스팅 과정이 필요 없습니다.

3.     Generic 을 사용해 generic 알고리즘의 구현이 가능함.

 

캐스팅 과정이 생략은 generic 을 사용하지 않았을 경우 모든 데이터가 Object 로 처리되기 때문에 사용자가 Collection에 추가한 데이터 타입에 맞게 다시 Object 타입을 타입 캐스팅 해야 하지만 Generic를 사용하도록 한 경우 이 과정이 필요 없게 됩니다. 그림 1은 캐스팅 과정 생략에 대한 예를 보여줍니다.


그림 1. Generic 사용 코드 비교


  Generic 을 사용하지 않았을 경우 ArrayList String 데이터 타입의 데이터를 넣었지만 꺼내서 사용할 경우 반환되는 데이터는 Object 타입이므로 이것을 사용자가 직접 타입 캐스팅 후 사용해야 합니다. 하지만 Generic을 사용할 경우 ArrayList에 추가되는 데이터와 추출되는 데이터를 컴파일러가 처리하므로 실제 사용할 때는 타입 캐스팅 과정 없이 바로 사용할 수 있습니다.

Generic 을 지원하는 코드는 주로 자료 구조 (Collections 관련 데이터 타입) 를 사용할 때 볼 수 있으며 소스 코드를 작성할 때 명시적으로 사용되는 자료 구조에 추가할 데이터를 정의해 줄 수 있기 때문에 매우 편리합니다. (데이터를 추가하고, 꺼낼 때 데이터 타입을 명시적으로 확정할 수 있다는 측면에서)

 

이제는 서두에서 이야기 했었던 모듈을 제작할 때 외부 인터페이스와 함께 사용하는 데이터 타입 자체에 대해서도 명시적으로 결정하고 사용될 수 있도록 Generic을 사용하여 간단히 모듈을 구현하는 방법을 살펴 보겠습니다.

기존의 경우 모듈을 제작하는 사용자가 “AA 데이터 타입을 추가해라”, “BB 데이터 타입을 메소드의 파라미터로 전달해야한다.” 와 같은 내용을 따라 사용되는 쪽의 코드는 작성되었습니다.

이 경우 사용되는 목적(데이터 타입이 달라짐)에 따라서 모듈이 인터페이스를 통해 데이터 타입을 받거나 혹은 추상 클래스를 통해서 상,하위 개념으로 나뉘어진 데이터 타입을 전달 받아야 했습니다. 하지만 모듈의 내부 동작은 동일하고 데이터 타입에 대한 형식만 다른 경우라면 Generic를 사용하면 각 데이터 타입에 맞는 모듈을 추가로 작성하지 않아도 됩니다. 그림 2는 동일한 구현을 갖지만 전달되는 사용되는 소스 부분에서 전달되는 데이터가 다를 경우의 예를 보여줍니다.


그림 2. 동일 모듈에 대한 전달 데이터의 예


그림 2와 같이 모듈에 대한 데이터만 달라질 경우 Generic을 지원하도록 MyStack 모듈을 구현하면 동일한 내용을 데이터 타입에 맞게 중복 구현해야 하는 문제를 해결할 수 있습니다.

다음은 Generic을 지원하도록 하는 MyStack 모듈의 간단한 구현 예제입니다.


    /**
     * MyStack 모듈 
     */
    class MyStack<T> {
        
        /**
         * List Collection
         */
        ArrayList<T> values = new ArrayList<T>();
        
        /**
         * 데이터 삽입
         * @param value
         */
        public void push(T value) {
            values.add(value);
        }
        
        /**
         * 데이터 꺼내기
         * @return
         */
        public T pop() {
            return values.get(values.size() - 1);
        }
        
        // something codes.. 
    }
    
    interface Command {
        
    }
    
    class InsertCommand implements Command {
        
    }
    
    class DeleteCommand implements Command {
        
    }

  MyStack 모듈의 함수를 통해 전달되는 데이터를 T 타입으로 정의하였으며 이를 통해 실제 소스코드에서 사용될 때 정의되는 데이터 타입에 따라서 모듈에 전달될 수 있는 데이터가 달라지게 됩니다. 그림 3은 위 코드에 대한 호출 부분의 소스 코드 예제 입니다. 기존에는 각 데이터 타입에 따라 Stack 모듈의 중복 구현을 두었지만 Generic를 사용하여 MyStack 모듈 하나로 모든 타입에 대응하여 사용될 수 있도록 한 것을 알 수 있습니다.


그림 3. Generic을 사용하는 MyStack


  지금까지 java에서 generic을 사용할 때의 장점과 개발하는 모듈에 generic을 사용할 수 있도록 구현한 간단한 Stack 모듈에 대한 예제를 살펴 보았습니다. 이것을 통해 우리는 동일한 구현에 데이터 타입이 다른 경우에 Generic을 유용하게 사용할 수 있으며 Data Collection 들에서 Generic을 사용하면 데이터의 타입 체크를 컴파일러를 통해 이루어질 수 있기 때문에 타입 캐스팅 과정에서 발생할 수 있는 런터임 오류를 쉽게 확인할 수 있는 것을 알 수 있었습니다.

이상으로 글을 마치겠습니다. 감사합니다. ^.^

 

참고문헌

[1] Why Use Generics?, http://docs.oracle.com/javase/tutorial/java/generics/why.html, Oracle 20013.