Menu
CoddyTech

제네릭 소개

Coddy Java 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨. 87개 중 53번째.

값을 저장했다가 나중에 가져오는 클래스를 만들어야 한다고 생각해 보세요. 제네릭을 사용하지 않으면 각 자료형에 대해 별도의 클래스를 작성해야 합니다. Integer용 클래스 하나, String용 클래스 하나, Double용 클래스 하나 등을 작성해야 하죠. 그러면 코드가 중복되고 유지 관리가 어려워집니다.

제네릭을 사용하면 모든 타입에 적용되는 클래스와 메서드를 작성하면서도 타입 안전성을 유지할 수 있으므로 이 문제를 해결할 수 있습니다. 자리 표시자(이를 타입 매개변수라고 합니다)를 정의하면, 클래스를 사용할 때 실제 타입으로 대체됩니다:

// 제네릭 없이 - Object를 사용하므로 캐스팅이 필요함
List list = new ArrayList();
list.add("Hello");
String s = (String) list.get(0);  // 수동 캐스팅이 필요함

// 제네릭 사용 - 타입 안전성이 보장되며 캐스팅이 필요 없음
List<String> list = new ArrayList<String>();
list.add("Hello");
String s = list.get(0);  // 캐스팅이 필요 없음

꺾쇠괄호 <T>는 타입 매개변수를 나타냅니다. List<String>이라고 작성하면 이 리스트에는 문자열만 포함된다고 컴파일러에 알리는 것입니다. 정수를 추가하려고 하면 런타임에 실패하는 대신 컴파일러가 즉시 오류를 잡아냅니다.

제네릭은 두 가지 주요 이점을 제공합니다. 명시적인 형 변환이 필요하지 않고, 런타임이 아닌 컴파일 시점에 타입 오류를 찾아냅니다. 따라서 코드를 더 안전하고 깔끔하게 작성할 수 있습니다. 다음 레슨에서는 제네릭 클래스와 메서드를 직접 만드는 방법을 살펴보겠습니다.

challenge icon

챌린지

쉬움

Object를 사용하고 형변환하는 기존 방식과 제네릭을 사용해 타입 안정성을 보장하는 새로운 방식을 비교하여, 제네릭의 강력함을 보여 주는 간단한 저장 시스템을 만들어 봅시다.

차이를 직접 확인할 수 있도록 파일 세 개를 만들겠습니다.

  • OldBox.java: 제네릭 이전 방식으로 값을 저장하는 클래스를 만드세요. OldBox에는 Object 타입의 private 필드 content가 있어야 합니다. Object를 받아 저장하는 생성자와 Object를 반환하는 getContent() 메서드를 포함하세요. 이 방식도 작동하지만 값을 가져올 때 형변환이 필요합니다.
  • GenericBox.java: 이제 제네릭을 사용해 현대적이고 타입이 안전한 버전을 만드세요. GenericBox 선언에 타입 매개변수 T를 사용해야 합니다. T 타입의 private 필드 content, T 값을 받는 생성자, 그리고 T 타입을 반환하는 getContent() 메서드가 필요합니다. 이 클래스를 사용하면 형변환이 필요하지 않습니다!
  • Main.java: 두 방식을 나란히 보여 주세요. 입력 두 개, 즉 단어(String)와 숫자(정수)를 받습니다.

    먼저 기존 방식을 사용하세요. 단어를 저장하는 OldBox를 만들고, String으로 형변환하여 값을 가져온 다음 출력하세요: OldBox (with cast): [value]

    다음으로 제네릭 방식을 사용하세요. 같은 단어를 저장하는 GenericBox<String>을 만들고, 형변환 없이 값을 가져온 다음 출력하세요: GenericBox (no cast): [value]

    그런 다음 정수에도 제네릭이 작동하는 모습을 보여 주세요. 숫자를 저장하는 GenericBox<Integer>를 만들고, 값을 가져온 다음 출력하세요: GenericBox Integer: [value]

    마지막으로 빈 줄을 출력한 뒤 다음을 출력하세요: Type safety: Generics catch errors at compile time!

순서대로 입력 두 개를 받습니다. 단어(String)와 숫자(문자열로 입력되는 정수이며, 파싱해야 합니다)입니다.

핵심 차이에 주목하세요. OldBox에서는 (String) box.getContent()로 형변환한 뒤 올바른 타입을 가져왔기를 바라야 합니다. GenericBox에서는 컴파일러가 타입을 알고 있으므로 형변환이 필요하지 않습니다. 이것이 제네릭의 핵심적인 이점인, 번거로운 형변환 없이 타입 안정성을 보장하는 것입니다!

직접 해보기

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String word = scanner.nextLine();
        int number = Integer.parseInt(scanner.nextLine());
        
        // TODO: word를 저장하는 OldBox를 생성하세요
        // String으로 형변환하여 값을 꺼내고 출력하세요: "OldBox (with cast): [value]"
        
        // TODO: word를 저장하는 GenericBox<String>을 생성하세요
        // 형변환 없이 값을 꺼내고 출력하세요: "GenericBox (no cast): [value]"
        
        // TODO: number를 저장하는 GenericBox<Integer>를 생성하세요
        // 값을 꺼내고 출력하세요: "GenericBox Integer: [value]"
        
        // TODO: 빈 줄을 출력한 다음 출력하세요:
        // "Type safety: Generics catch errors at compile time!"
    }
}
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

객체 지향 프로그래밍의 모든 레슨

직접 연습해 보세요: 온라인 Java 컴파일러