본문 바로가기
프로그래밍/Java

[java] Generic을 이용한 Box Class

by 사바라다 2020. 11. 22.

안녕하세요. 오늘 포스팅은 Java Generic의 4번째 시간입니다. 오늘 여러분들과 공유하고자 하는 내용은 다시 기본으로 돌아가서 Generic을 이용한 Box Class라는 내용입니다. Box Class에 란 아래와 같이 어떠한 타입으로든 받을 수 있는 Class를 말합니다. 아래 예제를 보면 Box class 안에 Object 타입의 변수가 하나있으며 getter, setter 메서드가 각각 있습니다. Object Class는 모든 Class의 부모 클래스이기 때문에 setter 메서든에는 모든 Class가 들어올 수 있게되어 Box Class란 이름으로 사용할 수 있는 것입니다.

public class Box {

    private Object object;

    public void set(Object object) {
         this.object = object;
    }
    public Object get() {
         return object;
    }
}

사용하는 측에서는 아래와 같이 사용하게 됩니다. 이렇게 사용할 경우 현재 코드에서는 문제가 없습니다. 하지만 우리는 공변의 문제점에 대해서 배웠기 때문에 이에대한 문제점이 동알하게 발생하겠다는 생각을 할 수 있습니다. (공변이 생소하시다면 [java] 배열(Array)과 컬렉션 제네릭의 차이을 참조해주세요.)

Box box = new Box();
box.set("hello");
String hello = (String)box.get();
System.out.println(hello);

따라서 제네릭을 통해서 런타임에러가 발생하지 않게 만들 필요가 있습니다. 이러한 Box Class 방식은 대표적으로 List 같은 Collection에서 사용되며 프로젝트에서는 Response DTO를 만들때도 잘 사용됩니다.

Generic을 이용한 Box Class

generic class는 아래와같이 사용할 수 있습니다. T1 ~ Tn은 사용하고자 하는 generic Type이며 T는 type parameter라고 부릅니다. 타입으로는 객체 타입만 가능하며 int, long 과 같은 primitive type은 불가능합니다.

class name<T1, T2, ..., Tn> { /_ ... _/ }

generic을 이용하여 위의 예제를 변환하면 아래와 같이 바꿀 수 있게 됩니다. Box class에 T라는 type parameter를 주고 선언합니다. 멤버변수의 타입역시 T로 봅니다. 그리고 setter 메서드는 해당 타입인 T를 파라미터로 받으며 getter 메서드의 반환 값도 T를 리턴하게 하는것입니다. 이렇게 Class를 구성하게 되면 Class 선언시의 T에 대해서 setter 메서드와 getter 메서드가 제대로 동작하는지 컴파일타임에 검사를 하게됩니다.

public class Box<T> {

    private T object;

    public void set(T object) {
        this.object = object;
    }
    public T get() {
        return object;
    }
}

사용하는 방법은 아래와 같습니다. Box Class를 선언하면서 제네릭을 함께 선언합니다. 아래의 경우 String으로 제네릭 타입을 줬습니다. 따라서 해당 인스턴스는 String에 대한 Box Class가 되며 컴파일러는 String Box Class로 컴파일하게 됩니다. 따라서 해당 컴파일을 통과했다면 런타임에는 공변으로 인한 런타임에러 요소가 없어집니다.

Box<String> box = new Box<>();
box.set("hello");
String hello = box.get();
System.out.println(hello);

만약 String으로 제네릭을 잡고 Integer로 이용하려고 한다면 아래와 같은 컴파일 에러 메시지가 노출되게 됩니다.

groovy spock에서 뜨는 경고문, java에서는 compile 시점에 에러가 발생한다.

Type Parameter 이름 컨벤션

추가적으로 Type Parameter의 이름 컨벤션에 대해서 알아보도록 하겠습니다. 이번 예제에서는 T를 사용했었습니다. 이 T도 오라클 문서의 이름 컨벤션에서 가져온 것입니다. Type Parameter로 여러가지 타입이 올 수 있습니다. 아래는 오라클 문서에 있는 Type Parameter의 컨벤션 리스트입니다.

  • E - 요소 (Collections Framework에서 사용)
  • K - 키
  • N - 숫자
  • T - 타입
  • V - 값
  • S,U,V etc. - 2, 3, 4 번째 types

마무리

오늘 사용한 예제는 oracle의 tutorial 문서에서 가져왔으며, 내용은 제가 스스로 이해한것을 바탕으로 각색하였습니다.

오늘은 이렇게 해서 Generic을 이용한 box Class에 대해서 알아보는 시간을 가졌습니다. Generic도 처음에 사용하면 사용할수록 헷갈리게 되는 컨셉이었습니다. 하지만 이렇게 정리하고나니 어느정도 이해가 되는 것 같습니다. 아직 와일드카드에 대한내용은 함께하지 못했는데요. 이부분은 추후에 다시 정리하는 시간을 가지도록 하겠습니다.

다음번에도 재미있는 주제로 찾아뵙도록 하겠습니다.

감사합니다.

참조

oracle_generics

stackoverflow_oracle-java-generics-tutorial-box-class-explanation

댓글