춤추는 개발자

[Java] 제네릭(generic)이란? 본문

Developer's_til/그외 개발 공부

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

Heon_9u 2021. 12. 29. 23:56
728x90
반응형

 

✅ Generic

 자바에서 제네릭(generic)이란, 데이터의 타입을 일반화(generalize)한다는 것을 의미한다. 쉽게 설명하자면 '데이터 형식에 의존하지 않고, 하나의 값이 여러 다른 데이터 타입들을 가질 수 있도록 일반화하는 방법'이다.

 이렇게 컴파일 시에 미리 타입 검사를 수행하면 다음과 같은 장점이 있다.

 

1. 클래스나 메서드 내부에서 사용되는 객체의 타입 안정성을 높일 수 있다.

2. 반환값에 대해 타입 변환 및 타입 검사에 들어가는 노력을 줄일 수 있다.

 

 JDK 1.5 이전에서는 여러 타입을 사용하는 대부분의 클래스나 메서드에서 인수나 반환값으로 Object 타입을 사용해왔다. 하지만 반환된 Object 객체를 다시 원하는 타입으로 변환해야 하며, 이러한 상황에서 오류가 발생할 가능성도 존재한다.

 이제 JDK 1.5 이후부터 도입된 제네릭(generic)은 클래스나 메서드에서 사용할 내부 데이터 타입을 컴파일 시에 미리 지정한다. 그래서 타입 검사나 타입 변환과 같은 번거로운 작업을 생략할 수 있게 되었다.

 

 

 [ 제네릭의 선언 및 생성 ]

class ExArray<T> {
    T element;
    void setElement(T element) { this.element = element; }
    T getElement() { return element; }
}

 

 자바에서 제네릭은 위와 같은 방법으로 클래스와 메서드에만 선언할 수 있다. 위 코드에서 사용된 'T'를 타입 변수(type variable)라고 하며, 임의의 참조형 타입을 의미한다. 타입 변수는 클래스뿐만 아니라 메서드의 매개변수나 반환값으로도 사용할 수 있다.

 'T'뿐만 아니라 어떤 문자를 사용해도 상관없으며, 2개 이상의 타입 변수를 쉼표로 구분한다. 다만, 아래와 같이 타입에 따라 문자를 구분하여 사용하고 있다.

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

 

 위처럼 선언된 제네릭 클래스를 생성할 때에는 아래 코드처럼 타입 변수 자리에 사용할 실제 타입을 명시해야 한다.

ExArray<Integer> exArr = new ExArray<Integer>();

 

 이처럼 클래스를 생성할 때 사용할 실제 타입을 명시하면, 내부적으로는 정의된 타입 변수가 명시된 실제 타입으로 변환되어 처리된다.

 

 이번에는 제네릭에서 적용되는 타입 변수의 다형성을 보여주는 예제다.

class Avengers {
    public void attack() { System.out.println("assemble"); }
}

class IronMan extends Avengers {
    public void attack() { System.out.println("fire"); }
}

class Hulk extends Avengers {
    public void attack() { System.out.println("smash"); }
}

class Thanos {
    public void attack() { System.out.println("snab"); }
}

class HeroList<T> {
    ArrayList<T> heros = new ArrayList<>();

    void add(T hero) { heros.add(hero); }
    T get(int index) { return heros.get(index); }
    boolean remove(T hero) { return heros.remove(hero); }
    int size() { return heros.size(); }
}

public class Generic {

    public static void main(String[] args) {
        HeroList<Avengers> avengers = new HeroList<>();

        avengers.add(new Avengers());
        avengers.add(new IronMan());
        avengers.add(new Hulk());
        // avengers.add(new Thanos());

        for (int i = 0; i < avengers.size(); i++) {
            avengers.get(i).attack();
        }
    }
}

// 결과
assemble
fire
smash

 

 위 코드에서 IronManHulk 클래스는 Avengers 클래스를 상속받은 자식 클래스이므로 HeroList<Avengers>에 추가할 수 있다. 하지만, Thanos 클래스는 Avengers 클래스를 상속받지 않아 다른 타입으로 간주되어 추가할 수 없다.

 

 

 

 

728x90
반응형