주의

  • 본 게시글은 Claude로 작성되었습니다. 잘못된 정보가 있을 수 있습니다.

개요

제네릭스는 Java 5부터 도입된 기능으로, 다양한 타입의 객체들을 다루는 메서드나 컬렉션 클래스에 컴파일 시의 타입 체크를 해주는 기능입니다. 제네릭스를 사용하면 타입 안정성을 제공하고, 불필요한 타입 변환을 줄일 수 있어 코드의 재사용성과 안정성을 높일 수 있습니다.

상세

1. 제네릭스의 기본 사용법

제네릭스는 클래스나 인터페이스, 메서드를 정의할 때 타입을 파라미터로 사용할 수 있게 해줍니다.

// 제네릭 클래스 정의
public class Box<T> {
    private T content;
 
    public void set(T content) {
        this.content = content;
    }
 
    public T get() {
        return content;
    }
}
 
// 사용 예
Box<String> stringBox = new Box<>();
stringBox.set("Hello Generics!");
String content = stringBox.get();

위 예제에서 T는 타입 파라미터로, 실제 Box 객체를 생성할 때 구체적인 타입으로 대체됩니다.

2. 와일드카드

제네릭스에서 와일드카드 ?를 사용하면 알 수 없는 타입을 표현할 수 있습니다.

public void printBoxContent(Box<?> box) {
    System.out.println("Box contains: " + box.get());
}

3. 상한 경계 와일드카드와 하한 경계 와일드카드

  • 상한 경계 와일드카드 (<? extends T>): T와 그 자손들만 가능
  • 하한 경계 와일드카드 (<? super T>): T와 그 조상들만 가능
public void addNumbers(List<? extends Number> numbers) {
    // Number의 하위 클래스만 받을 수 있음
}
 
public void addIntegers(List<? super Integer> integers) {
    // Integer의 상위 클래스만 받을 수 있음
}

4. 제네릭 메서드

메서드 레벨에서도 제네릭을 사용할 수 있습니다.

public <T> void printArray(T[] array) {
    for (T element : array) {
        System.out.print(element + " ");
    }
    System.out.println();
}

5. 타입 소거

자바의 제네릭은 컴파일 타임에만 타입 체크를 하고, 런타임에는 타입 정보가 소거됩니다. 이를 타입 소거라고 합니다.

List<String> stringList = new ArrayList<>();
List<Integer> integerList = new ArrayList<>();
 
// 런타임에는 두 리스트의 타입이 동일함
System.out.println(stringList.getClass() == integerList.getClass()); // true

예상 면접 질문/답변

  1. Q: 제네릭스를 사용하는 이유는 무엇인가요? A: 제네릭스는 컴파일 시점에 타입 안정성을 제공하고, 불필요한 타입 캐스팅을 줄여 코드의 안정성과 재사용성을 높입니다. 또한, 컬렉션 등에서 다양한 타입을 다룰 수 있게 해줍니다.

  2. Q: 제네릭스의 와일드카드는 무엇이며, 어떤 경우에 사용하나요? A: 와일드카드 ?는 알 수 없는 타입을 나타냅니다. 주로 메서드 파라미터에서 유연성을 제공하기 위해 사용됩니다. 예를 들어, List<?>는 어떤 타입의 List든 받을 수 있습니다.

  3. Q: 상한 경계 와일드카드와 하한 경계 와일드카드의 차이점은 무엇인가요? A: 상한 경계 와일드카드 <? extends T>는 T와 그 자손 클래스만 허용하며, 주로 데이터를 읽을 때 사용됩니다. 하한 경계 와일드카드 <? super T>는 T와 그 조상 클래스만 허용하며, 주로 데이터를 쓸 때 사용됩니다.

  4. Q: 제네릭 메서드란 무엇이며, 어떻게 정의하나요? A: 제네릭 메서드는 매개변수의 타입이 메서드 호출 시점에 결정되는 메서드입니다. public <T> void method(T t) { ... }와 같이 반환 타입 앞에 타입 파라미터를 선언하여 정의합니다.

  5. Q: 타입 소거에 대해 설명해주세요. A: 타입 소거는 컴파일 시 제네릭 타입 정보를 검사한 후, 런타임에는 해당 정보를 제거하는 과정입니다. 이는 제네릭스가 도입되기 전의 레거시 코드와의 호환성을 위해 사용됩니다. 예를 들어, List<String>List<Integer>는 런타임에 동일한 타입으로 취급됩니다.

스스로 찾아보면 좋은 연관 주제

  1. 제네릭스와 배열의 관계 및 제약사항
  2. 제네릭스의 타입 추론과 다이아몬드 연산자 (<>)
  3. 제네릭스를 활용한 디자인 패턴 (e.g., 팩토리 패턴)
  4. Java 컬렉션 프레임워크에서의 제네릭스 활용
  5. 제네릭스의 한계와 주의사항