[Java] Chapter 13. 제네릭

SeungWoo Cha·2025년 9월 12일

[Java] 이것이 자바다

목록 보기
11/17

Chapter 13. 제네릭 (Generics)

13.1. 제네릭 기본 개념

  • 제네릭(Generic): 아직 결정되지 않은 타입을 파라미터로 처리하고, 실제 사용할 때 구체적인 타입으로 대체하는 기능.

  • 타입 파라미터 기호: <T>

    • T는 타입 변수(Type Parameter) → 객체 생성 시점에 실제 타입으로 치환됨.
  • 타입 파라미터는 클래스/인터페이스만 가능 (기본 타입 불가).

    • 기본 타입을 사용하려면 래퍼 클래스(Integer, Double …) 를 활용해야 함.
// 제네릭 클래스 정의
public class Box<T> {
    public T content;
}

// 사용 예제
Box<String> strBox = new Box<>();
strBox.content = "Hello Generics";

Box<Integer> intBox = new Box<>();
intBox.content = 100;

13.2. 제네릭 타입

  • 제네릭 타입(Generic Type): 결정되지 않은 타입을 파라미터로 가지는 클래스/인터페이스.

  • 문법:

    class 클래스명<T, U, ...> { ... }
    interface 인터페이스명<T, U, ...> { ... }
  • 타입을 지정하지 않으면 기본적으로 Object로 취급됨.

// 제네릭 클래스
public class Pair<K, V> {
    private K key;
    private V value;

    public Pair(K key, V value){
        this.key = key;
        this.value = value;
    }

    public K getKey() { return key; }
    public V getValue() { return value; }
}

// 사용
Pair<String, Integer> student = new Pair<>("Alice", 90);
System.out.println(student.getKey() + " : " + student.getValue());

13.3. 제네릭 메소드

  • 제네릭 메소드(Generic Method): 메소드 자체가 타입 파라미터를 가짐.
  • 선언부에 <T> 와 같은 타입 매개변수 명시.
// 제네릭 메소드
public class Util {
    public static <T> Box<T> boxing(T t) {
        Box<T> box = new Box<>();
        box.content = t;
        return box;
    }
}

// 사용
Box<String> strBox = Util.boxing("Hello");
Box<Integer> intBox = Util.boxing(123);

13.4. 제한된 타입 파라미터 (Bounded Type Parameter)

  • 특정 타입 또는 그 하위 타입만 대체 가능하도록 제한.
  • 문법: <T extends 상위타입>
public class CompareUtil {
    public static <T extends Number> boolean compare(T t1, T t2) {
        return t1.doubleValue() == t2.doubleValue();
    }
}

// 사용
System.out.println(CompareUtil.compare(10, 10));       // true
System.out.println(CompareUtil.compare(3.14, 3.14));   // true
// System.out.println(CompareUtil.compare("a", "b"));  // 오류 (Number 타입 아님)

13.5. 와일드카드 타입 파라미터

  • ? (와일드카드): 범위 내 모든 타입 가능.

  • 용도: 제네릭 타입을 매개값이나 리턴 타입으로 사용할 때 유연성 확보.

  • 세 가지 방식:

    1. <?> : 모든 타입 허용
    2. <? extends 상위타입> : 상위 타입 및 하위 클래스 허용
    3. <? super 하위타입> : 하위 타입 및 상위 클래스 허용
public static void printList(List<?> list) {
    for(Object obj : list) {
        System.out.println(obj);
    }
}

List<String> strList = Arrays.asList("A", "B", "C");
List<Integer> intList = Arrays.asList(1, 2, 3);

printList(strList); // 가능
printList(intList); // 가능
profile
한 발자국씩

0개의 댓글