본문 바로가기
스터디/Java

[Java 자바] 제네릭(generic)이란?

by dingwoon 2024. 3. 19.

제네릭(generic)이란

데이터 타입(data type)을 일반화 하는 것으로, 클래스나 메소드에서 사용할 내부 데이터 타입을 컴파일 시에 미리 지정하는 방법이다.

 

제네릭이 있기 전(JDK 1.5 이전)에는 인수를 Object 타입으로 사용했다.

이를 사용하기 위해 원래 타입으로 바꿔야 했고, 컴파일 시에 오류가 있는지 알지 못했다.

하지만 제네릭의 도입으로 컴파일 시에 미리 타입이 정해져서 오류를 줄이고, 번거로운 작업을 안 할 수 있게 됐다.

 

제네릭을 활용해 클래스와 메소드를 정의할 수 있다.

이때 타입명 대신 쓰이는 문자를 타입 변수(type variable)이라고 하고, 원시 타입이 아닌 참조형 타입만을 의미한다.

(그래서 원시 타입을 쓰고 싶을 때는 래퍼(wrapper) 클래스를 사용해야 한다.)

일반적으로 'T'를 쓰고, 다른 문자도 사용할 수 있다.

 

1) 클래스 수준에서의 제네릭

public class MyClass<T> {
    private T variable;
    public T getVariable() {
        return variable;
    }
    public void setVariable(T variable) {
        this.variable = variable;
    }
}

위와 같이 클래스를 정의할 때 제네릭 타입 매개변수를 선언하면 클래스 수준에서 타입 변수(type variable) T를 사용할 수 있다.

2) 메소드 수준에서의 제네릭

public class MyClass {
    public <T> void printItem(T item) {
        System.out.println(item.toString());
    }
    public <T, U> void printItems(T item1, U item2) {
        System.out.println(item1.toString() + ", " + item2.toString());
    }
}

위와 같이 메소드를 정의할 때 메소드의 시그니처에 제네릭 타입 매개변수를 선언하면 메소드 수준에서 타입 변수(type variable) T를 사용할 수 있다.

MyClass myClass = new MyClass();
        
myClass.printItem("print item");
myClass.printItems(123, 45.67f);

3) 메소드 내에서 해당 메소드의 로직에 필요한 타입을 제한하거나 일반화 함

public class MyClass {
    public static <T extends Integer> int sum(T[] array) {
        int result = 0;
        for (T item : array) {
            result += item.intValue();
        }
        return result;
    }
}

위의 함수를 사용할 때 배열의 타입이 Integer를 상속하는 타입이 아닐 경우 컴파일 에러가 난다.

컴파일 에러 발생

(만약 시그니처가 '<T super Integer>'라면 T로 Integer또는 Integer의 상위 클래스만 올 수 있다.)

 

4) 예시

public static <T extends Comparable<? super T>> void sort(T[] array) {
        Arrays.sort(array);
    }

위의 경우는 T 혹은 T의 상위클래스에서 Comparable을 구현한 경우만 T로 들어올 수 있다.

T를 포함해서 가장 가까이에 구현된 compareTo 함수에 따라 정렬된다.

public static <T> void sort(T[] a, Comparator<? super T> c) {
        if (c == null) {
            sort(a);
        } else {
            if (LegacyMergeSort.userRequested)
                legacyMergeSort(a, c);
            else
                TimSort.sort(a, 0, a.length, c, null, 0, 0);
        }
    }

위는 배열의 sort 함수의 정의이다.