[Java 개념] 제네릭, 와일드카드 등 예습

예세림·2024년 7월 22일

Java

목록 보기
5/12

와일드카드와 관련된 제네릭(Generic) 개념을 포괄적으로 이해하려면, 제네릭의 기본 개념, 와일드카드의 종류, 그리고 Object 타입과의 관계를 알아야 합니다. 다음은 이러한 개념들을 포함한 설명입니다.

제네릭(Generic) 기본 개념

제네릭은 자바의 클래스나 메서드를 작성할 때 데이터 타입을 미리 지정하지 않고, 사용할 때 지정할 수 있도록 하는 기능입니다. 제네릭을 사용하면 타입 안정성을 높이고, 코드의 재사용성을 높일 수 있습니다.

// 제네릭 클래스 예시
class Box<T> {
    private T item;

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

    public T getItem() {
        return item;
    }
}

위 예시에서 T는 타입 파라미터로, Box 객체를 생성할 때 실제 타입을 지정합니다. 예를 들어, Box<String>, Box<Integer>처럼 사용할 수 있습니다.

와일드카드(Wildcard) 개념

와일드카드는 제네릭 타입의 파라미터를 유연하게 사용할 수 있도록 합니다. 와일드카드는 ? 기호로 표현되며, 세 가지 주요 형태가 있습니다.

  1. Unbounded Wildcard (<?>): 모든 타입을 허용합니다.
  2. Upper Bounded Wildcard (<? extends T>): 특정 타입 T의 하위 타입만 허용합니다.
  3. Lower Bounded Wildcard (<? super T>): 특정 타입 T의 상위 타입만 허용합니다.

1. Unbounded Wildcard (<?>)

모든 타입을 허용합니다. 예를 들어, List<?>는 어떤 타입의 리스트든 다 받을 수 있습니다.

public void printList(List<?> list) {
    for (Object elem : list) {
        System.out.println(elem);
    }
}

2. Upper Bounded Wildcard (<? extends T>)

특정 타입 T의 하위 타입만 허용합니다. 예를 들어, List<? extends Number>Number와 그 하위 타입 (Integer, Double 등)의 리스트를 받을 수 있습니다.

public double sumOfList(List<? extends Number> list) {
    double sum = 0;
    for (Number num : list) {
        sum += num.doubleValue();
    }
    return sum;
}

3. Lower Bounded Wildcard (<? super T>)

특정 타입 T의 상위 타입만 허용합니다. 예를 들어, List<? super Integer>Integer와 그 상위 타입 (Number, Object 등)의 리스트를 받을 수 있습니다.

public void addNumbers(List<? super Integer> list) {
    list.add(1);
    list.add(2);
}

Object 타입과 제네릭

Object 타입은 자바에서 모든 클래스의 최상위 클래스입니다. 따라서 제네릭을 사용하지 않는 컬렉션은 Object 타입으로 모든 객체를 저장할 수 있습니다. 하지만 제네릭을 사용할 때는 타입 안정성을 위해 명시적으로 타입을 지정해야 합니다.

예를 들어, List<Object>는 모든 타입을 저장할 수 있지만, 제네릭의 타입 안정성을 잃게 됩니다.

List<Object> list = new ArrayList<>();
list.add("Hello");
list.add(1);

이와 달리, 제네릭을 사용하면 다음과 같이 타입을 명시적으로 지정할 수 있습니다.

List<String> list = new ArrayList<>();
list.add("Hello");
// list.add(1); // 컴파일 오류

Object가 안되는 경우

제네릭 타입 파라미터가 명시되어 있는 경우, Object 타입을 사용하는 것이 불가능하거나 제한될 수 있습니다. 이는 타입 안정성을 유지하기 위해서입니다.

List<String> stringList = new ArrayList<>();
List<Object> objectList = stringList; // 컴파일 오류

public void process(List<Object> list) {
    // ...
}
process(stringList); // 컴파일 오류

위 예시에서 List<String>List<Object>로 변환하거나, List<String>을 인자로 받는 메서드에 List<Object>를 전달하는 것은 불가능합니다. 이는 타입 안정성을 위해 허용되지 않습니다.

요약

  • 제네릭(Generic): 데이터 타입을 유연하게 지정할 수 있는 기능.
  • 와일드카드(Wildcard): 제네릭 타입 파라미터를 유연하게 사용하기 위한 기법 (<?>, <? extends T>, <? super T>).
  • Object 타입: 자바의 최상위 클래스지만, 제네릭을 사용할 때는 타입 안정성을 위해 명시적으로 타입을 지정해야 하며, 모든 경우에 사용할 수는 없음.

이러한 개념들을 이해하면 제네릭과 와일드카드를 효과적으로 사용할 수 있습니다.

0개의 댓글