16.1 제네릭이란? (Generic Types)


1. 이름표가 없는 상자 vs 있는 상자 📦

자바에서 Object 타입은 모든 객체를 담을 수 있는 ‘만능 상자’입니다. 하지만 이 상자에는 치명적인 단점이 있습니다. 안에 뭐가 들었는지 꺼내보기 전에는 알 수 없고, 꺼낼 때마다 “이건 사과인가?”하고 확인(형변환)해야 한다는 점입니다.

제네릭(Generics)은 이 상자에 <String>, <Integer> 같은 이름표를 붙이는 기술입니다.

Generic Box Concept

  • Non-Generic: “뭐든지 담는 박스”. (꺼낼 때 불안함, 캐스팅 필요)
  • Generic: “사과 전용 박스”. (사과만 담김, 꺼낼 때 안심)



2. 제네릭 클래스 선언 (<T>)

클래스 이름 뒤에 <T>를 붙이면 됩니다. T는 Type의 약자입니다.

// 제네릭 클래스 선언
public class Box<T> {
    private T content; // 내용물의 타입이 T가 됨

    public T get() { 
        return content; 
    }
    
    public void set(T content) {
        this.content = content;
    }
}

이제 Box를 생성할 때 T가 무엇인지 알려주면 됩니다.

// 1. 문자열 전용 박스
Box<String> box1 = new Box<>();
box1.set("Hello");
String str = box1.get(); // 형변환 필요 없음!

// 2. 숫자 전용 박스
Box<Integer> box2 = new Box<>();
box2.set(100);
int value = box2.get();  // 형변환 필요 없음!

만약 box1.set(100);을 시도하면? 컴파일 에러(빨간 줄)가 뜹니다. 즉, 실행하기도 전에 실수를 잡아줍니다. 이것이 제네릭의 가장 큰 장점인 “컴파일 시점의 강력한 타입 체크”입니다.



3. 멀티 타입 파라미터 (<K, V>)

두 개 이상의 이름표가 필요할 때도 있습니다. 대표적으로 Map 같은 자료구조는 ‘키(Key)’와 ‘값(Value)’ 두 가지 타입을 관리합니다.

public class Product<K, M> {
    private K kind;
    private M model;

    public void setKind(K kind) { this.kind = kind; }
    public void setModel(M model) { this.model = model; }
}
// TV객체와 String 모델명 저장
Product<Tv, String> product1 = new Product<>();
product1.setKind(new Tv());
product1.setModel("스마트TV");

// Car객체와 String 모델명 저장
Product<Car, String> product2 = new Product<>();
product2.setKind(new Car());
product2.setModel("SUV");

자주 쓰는 타입 파라미터 약어

  • T: Type
  • E: Element (리스트 요소)
  • K: Key
  • V: Value
  • N: Number
서브목차