Menu
Coddy logo textTech

제네릭 소개

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

값을 저장하고 나중에 검색하는 class를 만들어야 한다고 상상해 보세요. 제네릭이 없다면 각 타입마다 별도의 클래스를 작성해야 합니다. 즉, Integer용 하나, String용 하나, Double용 하나 등을 작성해야 합니다. 이는 코드 중복과 유지 관리의 어려움으로 이어집니다.

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

// 제네릭 없이 - 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>는 타입 parameter를 나타냅니다. List<String>이라고 작성하면, 이 list에는 문자열만 포함된다고 컴파일러에 알리는 것입니다. 정수를 추가하려고 하면 컴파일러가 런타임에 실패할 때까지 기다리지 않고 즉시 오류를 catch합니다.

Generics는 두 가지 핵심 이점을 제공합니다. 명시적인 casting이 필요하지 않으며, 런타임이 아니라 compile 시점에 타입 errors를 감지합니다. 이를 통해 코드를 더 안전하고 깔끔하게 작성할 수 있습니다. 다음 레슨에서는 자신만의 제네릭 클래스와 메서드를 만드는 방법을 살펴보겠습니다.

challenge icon

챌린지

쉬움

캐스팅을 사용하는 기존 방식(Object 사용)과 새로운 방식(타입 안전성을 갖춘 제네릭 사용)을 비교하여 제네릭의 강력한 기능을 보여 주는 간단한 저장 시스템을 만들어 보겠습니다.

차이를 직접 확인할 수 있도록 세 개의 파일을 만듭니다.

  • OldBox.java: pre-generics 방식으로 값을 저장하는 class를 Create합니다. OldBox에는 Object 타입의 private field content가 있어야 합니다. Object를 accepts하여 저장하는 constructor와 Object를 반환하는 getContent() method를 포함합니다. 이 approach는 작동하지만 값을 가져올 때 casting이 requires됩니다.
  • GenericBox.java: 이제 generics를 사용하는 modern하고 type-safe한 버전을 Create합니다. GenericBox는 선언부에서 type parameter T를 사용해야 합니다. T 타입의 private field content, T 값을 accepts하는 constructor, 그리고 T 타입을 반환하는 getContent() method가 needed합니다. 이 class를 사용할 때는 casting이 필요하지 않습니다!
  • Main.java: 두 approach를 나란히 보여 줍니다. 두 개의 입력을 받습니다. 하나는 단어(String)이고, 다른 하나는 숫자(integer)입니다.

    먼저 old approach를 사용합니다. 단어를 저장하는 OldBox를 Create한 다음, String으로 cast하여 가져오고 다음을 Print합니다: OldBox (with cast): [value]

    다음으로 generic approach를 사용합니다. 같은 단어를 저장하는 GenericBox<String>을 Create하고, casting 없이 가져온 다음 다음을 Print합니다: GenericBox (no cast): [value]

    그런 다음 integer에서 generics가 작동하는 모습을 보여 줍니다. 숫자를 저장하는 GenericBox<Integer>를 Create하고, 값을 가져온 다음 다음을 Print합니다: GenericBox Integer: [value]

    마지막으로 blank line을 Print한 다음 다음을 Print합니다: Type safety: Generics catch errors at compile time!

입력은 다음 순서로 두 개를 받습니다. 단어(String)와 숫자(String으로 입력되며, 이를 parse해야 하는 integer)입니다.

핵심 차이점에 주목하세요. OldBox를 사용하면 (String) box.getContent()로 cast하고 올바른 type을 얻었기를 바라야 합니다. GenericBox를 사용하면 compiler가 type을 알고 있으므로 casting이 필요하지 않습니다. 이것이 generics의 핵심 이점입니다. casting의 번거로움 없이 type safety를 얻을 수 있습니다!

직접 해보기

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: 단어를 저장하는 OldBox 생성
        // Retrieve with cast to String and print: "OldBox (with cast): [value]"
        
        // TODO: 단어를 저장하는 GenericBox<String> 생성
        // Retrieve without casting and print: "GenericBox (no cast): [value]"
        
        // TODO: Create a GenericBox<Integer> storing the number
        // Retrieve and print: "GenericBox Integer: [value]"
        
        // TODO: 빈 줄을 출력한 다음 출력:
        // "Type safety: Generics catch errors at compile time!"
    }
}
quiz icon실력 점검

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

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

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