ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Java] 제네릭(Generic) - 제네릭 타입
    CSE/Java 2015. 9. 20. 09:47

    제네릭은 여러 절로 구성되어 있습니다.


    Intro

    제네릭 타입

    멀티 타입 파라미터

    제네릭 메소드

    제한된 타입 파라미터 & 와일드카드 타입

    제네릭 타입의 상속과 구현







    제네릭 타입(class<T>, interface<T>)

     제네릭 타입은 타입을 파라미터로 가지는 클래스와 인터페이스를 말합니다.


     제네릭 타입은 클래스 또는 인터페이스 이름 뒤에 "<>" 부호가 붙고, 사이에 타입 파라미터가 위치합니다.


     아래 코드에서 타입 파라미터의 이름은 T 입니다.



    1
    2
    3
    4
    public class className<T> { ... }
     
    public interface interfaceName<T> { ... }
     
    cs





     타입 파라미터는 변수명과 동일한 규칙에 따라 작성할 수 있지만, 일반적으로 대문자 알파벳 한 글자로 표현합니다. 


     제네릭 타입을 실제 코드에서 사용하려면 타입 파라미터에 구체적인 타입을 지정해야 합니다.


     그렇다면 왜 이런 타입 파라미터를 사용해야 할까요? 그 이유를 알기 위해 다음 Box 클래스를 살펴보도록 합시다.





    1
    2
    3
    4
    5
    6
    public class Box {
        private Object object;
        public void set(Object object) { this.object = object; }
        public Object get() { return object; }
    }
     
    cs





     Box 클래스의 필드 타입이 Object 인데, Object 타입으로 선언한 이유는 필드에 모든 종류의 객체를 저장하고 싶어서 입니다.


     Object 클래스는 모든 자바 클래스의 최상위 조상 클래스입니다.


     따라서 자식 객체는 부모 타입에 대입할 수 있다는 성질 때문에 모든 자바 객체는 Object 타입으로 자동 타입 변환되어 저장됩니다.




    1
    2
    Object object = All Object in java
     
    cs



     

     set() 메소드는 파라미터 타입으로 Object를 사용함으로써 파라미터로 자바의 모든 객체를 받을 수 있게 했고, 받은 파라미터를 Object 필드에 저장시킵니다.


     반대로 get() 메소드는 Object 필드에 저장된 객체를 Object 타입으로 리턴합니다.


     만약 필드에 저장된 원래 타입의 객체를 얻으려면 다음과 같이 강제 타입 변환을 해야 합니다.





    1
    2
    3
    4
    5
    Box box = new Box();
     
    box.set("Hi");
     
    String str = (String) box.get();
    cs





      * Box.java


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    package generic;
     
    public class Box {
        private Object object;
     
        public Object getObject() {
            return object;
        }
     
        public void setObject(Object object) {
            this.object = object;
        }
     
    }
     
    cs





     * Apple.java


    1
    2
    3
    4
    5
    6
    7
     
    package generic;
     
    public class Apple {
     
    }
     
    cs








     * BoxExam.java



    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
     
    package generic;
     
    public class BoxExam {
     
        public static void main(String[] args) {
            Box box = new Box();
     
            box.setObject("Jackie Chan"); // String => Object (자동 타입 변환)
            String name = (String) box.getObject(); // Object => String (강제 타입 변환)
     
            System.out.println(name);
     
            box.setObject(new Apple()); // Apple => Object (자동 타입 변환)
            Apple apple = (Apple) box.getObject(); // Object => Apple (강제 타입 변환)
     
            System.out.println(apple.getClass().getName());
        }
     
    }
     
     
    cs






     이와 같이 Object 타입을 사용하면 모든 종류의 자바 객체를 저장할 수 있다는 장점은 있지만, 저장할 때 타입 변환이 발생하고, 읽어올 때도 타입 변환이 발생합니다.


     이러한 타입 변환이 빈번해지면 전체 프로그램 성능에 좋지 못한 결과를 가져올 수 있습니다.


     그렇다면 모든 종류의 객체를 저장하면서 타입 변환이 발생하지 않도록 하는 방법이 없을까요?


     해결책은 제네릭에 있습니다. 다음은 제네릭을 이용해서 Box 클래스를 수정한 것입니다.



    1
    2
    3
    4
    5
    6
    7
    public class Box<T> {
        private T t;
     
        public T get() { return t; }
        public void set(T t) { this.t = t; }
    }
     
    cs




     타입 파라미터 T를 사용해서 Object 타입을 모두 T로 대체했습니다. T는 Box 클래스로 객체를 생성할 때 구체적인 타입으로 변경됩니다.


     예를 들어 다음과 같이 Box 객체를 생성했다고 가정해봅시다.



    1
    2
    Box<String> box = new Box<String>();
     
    cs




     타입 파라미터 T는 String 타입으로 변경되어 Box 클래스의 내부는 다음과 같이 자동으로 재구성 됩니다.




    1
    2
    3
    4
    5
    6
    7
    public class Box<String> {
        private String t;
     
        public String get() { return t; }
        public void set(String t) { this.t = t; }
    }
     
    cs














     필드 타입이 String으로 변경되었고, set() 메소드도 String 타입만 파라미터로 받을 수 있게 변경 되었습니다.


     

     다음은 위 예제를 제네릭을 적용시켜서 수정하였습니다.



     * Box.java



    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    package generic;
     
    public class Box<T> {
        private T t;
     
        public T get() {
            return t;
        }
     
        public void set(T t) {
            this.t = t;
        }
     
    }
     
    cs








     * BoxExam.java




    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
     
    package generic;
     
    public class BoxExam {
     
        public static void main(String[] args) {
     
            Box<String> stringBox = new Box<String>();
            stringBox.set("Hi");
     
            String str = stringBox.get();
            System.out.println(str);
     
            Box<Integer> integerBox = new Box<Integer>();
            integerBox.set(11);
     
            int value = integerBox.get();
            System.out.println(value);
        }
     
    }
     
    cs













     * 이 포스트은 서적 '이것이 자바다' 를 참고하여 작성한 포스트입니다.

    댓글

Designed by Tistory.