ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Java - 제네릭(Generic)의 특성
    Language/Java 2022. 12. 28. 09:50

    제네릭(Generic)의 특성

    복수의 제네릭 사용
    class EmployeeInfo {
        public int rank;
        EmployeeInfo(int rank) { this.rank = rank };
    }
    
    class Person<T, S> {
        public T info;
        public S id;
        Person (T info, S id) {
            this.info = info;
            this.id = id;
        }
    }
    
    public class GenericDemo {
        public static void main(String[] args) {
            Person<EmployeeInfo, int> p = new Person<EmployeeInfo, int>(new EmployeeInfo(1), 1);        
        }
    }

    클래스 내에서는 여러 개의 제네릭을 필요로 하는 경우가 있을 것이다. 위 코드는 이러한 경우의 예이다.

    위 코드는 컴파일 에러를 발생시키지만, 형식을 살펴보겠다. 복수의 제네릭을 사용할 때는 <T, S>와 같은 형식을 사용한다. T와 S는 서로 다른 데이터 타입으로 구분된다.

    여기서 T와 S 대신 다른 문자를 사용해도 되지만, 개발자들 사이에서 암묵적으로 약속된 형식이다.

     

    타입 설명
    <T> Type
    <E> Element
    <K> Key
    <V> Value
    <N> Number

    보통 제네릭은 위 표의 타입들이 많이 사용된다.

     

    기본 데이터 타입과 제네릭

    제네릭에서 특정 데이터 타입을 지정할 때는 레퍼런스 타입만 가능하다. int, char, double 등 기본 데이터 타입을 지정할 수 없다. 앞서 살펴보았던 소스코드가 컴파일 에러를 발생시킨 이유는 기본 타입인 int로 데이터 타입을 지정했기 때문이다.

     

    class EmployeeInfo {
        public int rank;
        EmployeeInfo(int rank) { this.rank = rank; }
    }
    
    class Person<T, S> {
        public T info;
        public S id;
        Person (T info, S id) {
            this.info = info;
            this.id = id;
        }
    }
    
    public class GenericDemo {
        public static void main(String[] args) {
            Person<EmployeeInfo, Integer> p = new Person<EmployeeInfo, Integer>(new EmployeeInfo(1), 1);
        }
    }

    위 코드를 살펴보면 기본 타입인 int가 Integer로 변경된 것을 확인할 수 있다. Integer는 기본 타입인 int를 레퍼런스 타입으로 변환해 주는 역할을 하며, 이러한 클래스를 래퍼(wrapper) 클래스라고 한다.

     

    래퍼 클래스의 종류

    기본 타입(Primitive Type) 래퍼 클래스(Wrapper Class)
    byte Byte
    char Character
    int Integer
    float Float
    double Double
    boolean Boolean
    long Long
    short Short

     

    제네릭의 생략

    우리는 지난 게시글에서 제네릭을 사용하기 위해서는 특정 클래스를 인스턴스화할 때, 클래스 내부적으로 사용하는 데이터 타입들을 '<>' 안에 매개 변수와 같이 지정을 해야 한다고 배웠다.

    하지만, 자바는 생성자를 통해서 어떠한 데이터 타입이 들어오는지 알 수 있기 때문에, 명시적으로 지정하기 않고 생략이 가능하다.

     

    EmployeeInfo e = new EmployeeInfo(1);
    Integer i = new Integer(10);
    
    Person<EmployeeInfo, Integer> p01 = new Person<EmployeeInfo, Integer>(e, i);   // 제네릭 명시
    Person p02 = new Person(e, i);   // 제네릭 생략

    위 코드의 p01과 p02는 정확히 동일하게 동작한다. e와 i의 데이터 타입을 알고 있기 때문이다.

     

    제네릭 메서드의 사용

    지금까지 살펴보았던 제네릭은 전부 클래스 레벨에서 사용하는 제네릭이 었다. 꼭 제네릭은 클래스 레벨에서만 사용할 수 있는 것이 아닌, 메서드 레벨에서도 사용이 가능하다.

     

    class EmployeeInfo {
        public int rank;
        EmployeeInfo(int rank) { this.rank = rank; }
    }
    
    class Person<T, S> {
        public T info;
        public S id;
        Person (T info, S id) {
            this.info = info;
            this.id = id;
        }
        public <U> void printInfo(U info) {
            System.out.println(info);
        }
    }
    
    public class GenericDemo {
        public static void main(String[] args) {
            Person<EmployeeInfo, Integer> p = new Person<EmployeeInfo, Integer>(new EmployeeInfo(1), 1);
        
            String info = "Hello";
            p.<String>printInfo(info);   // 제네릭 명시
            p.printInfo(info);   // 제네릭 생략
        }
    }

    위 코드는 메서드 레벨에서 제네릭을 사용한 예이다. Person 클래스 내부에 printInfo() 메서드를 선언한다. 해당 메서드의 접근 제어자와 리턴 타입 사이에 '<>'를 이용해 특정 데이터 타입을 지정할 수 있다는 것을 알 수 있다. 또한, 자바는 메서드의 매개변수가 어떠한 타입인지 알 수 있기 때문에, 생략이 가능하다는 것을 확인할 수 있다.


    출처

     https://opentutorials.org/module/516/6237

     

    728x90

    댓글

Designed by Tistory.