Stay Hungry Stay Foolish

자바/자바 중급

[자바 중급] 11. Generic 1

dev스카이 2024. 11. 6. 23:18

Generic

자바에서 제네릭(generics)은 클래스, 메소드, 인터페이스를 선언할 때 데이터 타입을 파라미터로 받을 수 있게 해주는 기능이다. 제네릭을 사용하면 코드의 재사용성안정성을 높일 수 있다. 주요 특징은 다음과 같다.

  • 컴파일 타임 타입 체크
    • 제네릭은 컴파일 시점에 타입을 체크하여, 잘못된 타입이 사용되는 것을 방지한다.
    • 예를 들어 List<String>으로 선언하면 이 리스트에는 오직 String 타입만 담을 수 있다.
  • 타입 안정성
    • 제네릭을 사용하면 캐스팅(casting)을 피할 수 있어 타입 안정성을 높일 수 있다.
    • 예를 들어, 제네릭을 사용하지 않는 List에서 객체를 꺼낼 때는 (String)처럼 캐스팅해야 하지만, 제네릭을 사용하면 그런 과정이 필요 없다.
  • 코드 재사용성
    • 여러 타입에서 사용할 수 있는 코드(클래스, 메소드)를 쉽게 작성할 수 있다.
    • 예를 들어 List<T> 같은 제네릭 타입으로, 리스트 내부에 어떤 타입의 객체를 넣어도 동일한 코드를 사용할 수 있다.

 

사용 방법

// T는 타입 파라미터로, 어떤 타입이든 올 수 있음
public class Box<T> {
    private T item;

    public void setItem(T item) {
        this.item = item;
    }

    public T getItem() {
        return item;
    }
}

public class Main {
    public static void main(String[] args) {
        Box<String> stringBox = new Box<>();
        stringBox.setItem("Hello");
        System.out.println(stringBox.getItem()); // "Hello"
        
        Box<Integer> integerBox = new Box<>();
        integerBox.setItem(123);
        System.out.println(integerBox.getItem()); // 123
    }
}
  • <> 를 사용한 클래스를 제네릭 클래스라 한다. 이 기호( <> )를 보통 다이아몬드라 한다.
  • 제네릭 클래스를 사용할 때는 Integer , String 같은 타입을 미리 결정하지 않는다.
  • 대신에 클래스명 오른쪽에 <T> 와 같이 선언하면 제네릭 클래스가 된다. 여기서 T 를 타입 매개변수라 한다. 이
  • 타입 매개변수는 이후에 Integer , String 으로 변할 수 있다.
  • 그리고 클래스 내부에 T 타입이 필요한 곳에 T item 과 같이 타입 매개변수를 적어두면 된다.

 

원하는 모든 타입 사용 가능

제네릭 클래스를 사용하면 다음과 같이 GenericBox 객체를 생성하는 시점에 원하는 타입을 마음껏 지정할 수 있다.

new GenericBox<Double>()
new GenericBox<Boolean>()
new GenericBox<MyClass>()

 

참고로 제네릭을 도입한다고 해서 앞서 설명한 GenericBox<String> , GenericBox<Integer> 와 같은 코드가 실제 만들어지는 것은 아니다. 대신에 자바 컴파일러가 우리가 입력한 타입 정보를 기반으로 이런 코드가 있다고 가정하고 컴파일 과정에 타입 정보를 반영한다. 이 과정에서 타입이 맞지 않으면 컴파일 오류가 발생한다.

 

 

타입 추론

자바가 스스로 타입 정보를 추론해서 개발자가 타입 정보를 생략할 수 있는 것을 타입 추론이라 한다. 타입 추론은 그냥 되는 것이 아니라, 자바 컴파일러가 타입을 추론할 수 있는 상황에서만 가능하다.

 

 

📌 핵심

제네릭의 핵심은 사용할 타입을 미리 결정하지 않는다는 점이다. 클래스 내부에서 사용하는 타입을 클래스를 정의하는 시점에 결정하는 것이 아니라 실제 사용하는 생성 시점에 타입을 결정하는 것이다.


용어 정리

 

1️⃣ 제네릭(Generic) 단어

  • 제네릭이라는 단어는 일반적인, 범용적인이라는 영어 단어 뜻이다.
  • 풀어보면 특정 타입에 속한 것이 아니라 일반적으로, 범용적으로 사용할 수 있다는 뜻이다.

2️⃣ 제네릭 타입 (Generic Type)

  • 클래스나 인터페이스를 정의할 때 타입 매개변수를 사용하는 것을 말한다.
  • 제네릭 클래스, 제네릭 인터페이스를 모두 합쳐서 제네릭 타입이라 한다.
    • 타입은 클래스, 인터페이스, 기본형( int 등)을 모두 합쳐서 부르는 말이다.
  • 예: class GenericBox<T> { private T t; }
  • 여기에서 GenericBox<T> 를 제네릭 타입이라 한다.

3️⃣ 타입 매개변수 (Type Parameter)

  • 제네릭 타입이나 메서드에서 사용되는 변수로, 실제 타입으로 대체된다.
  • 예: GenericBox<T>
  • 여기에서 T 를 타입 매개변수라 한다.

4️⃣ 타입 인자 (Type Argument)

  • 제네릭 타입을 사용할 때 제공되는 실제 타입이다.
  • 예: GenericBox<Integer>
  • 여기에서 Integer 를 타입 인자라 한다.

 

타입 매개변수 키워드

주로 사용하는 키워드는 다음과 같다. 소문자로 사용해도 되지만 일반적으로 대문자를 사용한다.

  • E - Element
  • K - Key
  • N - Number
  • T - Type
  • V - Value
  • S,U,V etc. - 2nd, 3rd, 4th types

 

여러 타입 매개변수 선언 가능

class Data<K, V> {}

 

 

타입 인자로 기본형 사용 불가

제네릭의 타입 인자로 기본형( int , double ..)은 사용할 수 없다. 대신에 래퍼 클래스( Integer , Double )를 사용하면 된다.