개발/JAVA

Java 제네릭(Generic): 타입을 유연하게 관리하는 방법

예니03 2025. 1. 13. 11:11
반응형

Java에서 제네릭(Generic)은 코드를 더 안전하고 유연하게 작성할 수 있도록 도와주는 중요한 기능입니다. 복잡하게 보일 수 있지만, 한 번 이해하면 코딩이 훨씬 간단해지고 에러를 줄일 수 있답니다. 오늘은 제네릭의 기본 개념과 사용법을 쉽고 간단한 예제로 설명해드릴게요! 😊

1. 제네릭(Generic)란?

Generic이란, 클래스나 메서드를 선언할 때 데이터 타입을 미리 지정하지 않고, 나중에 객체를 생성할 때 결정할 수 있도록 해주는 기능입니다.

왜 제네릭이 필요할까요?

  1. 타입 안정성 보장: 데이터 타입을 미리 지정하므로 잘못된 타입을 넣는 실수를 방지할 수 있습니다.
  2. 캐스팅 불필요: 데이터를 꺼낼 때 타입 변환(casting)을 하지 않아도 됩니다.
  3. 재사용성 증가: 하나의 클래스나 메서드로 다양한 데이터 타입을 처리할 수 있습니다.

 

2. 제네릭이 없는 경우

문제점 1: 타입별로 클래스를 만들어야 함

public class StringBox {
    String content;
    public String getContent() { return content; }
    public void setContent(String content) { this.content = content; }
}

public class IntBox {
    Integer content;
    public Integer getContent() { return content; }
    public void setContent(Integer content) { this.content = content; }
}

사용 예제

StringBox strBox = new StringBox();
strBox.setContent("Generic Example");
System.out.println(strBox.getContent());  // 출력: Generic Example

IntBox intBox = new IntBox();
intBox.setContent(2024);
System.out.println(intBox.getContent());  // 출력: 2024
  • 문제점: 데이터 타입마다 새로운 클래스를 만들어야 하므로 비효율적입니다.

 

문제점 2: Object로 처리하면 타입 에러 발생 가능

public class ObjectBox {
    Object content;  // 모든 객체를 저장 가능
    public Object getContent() { return content; }
    public void setContent(Object content) { this.content = content; }
}

사용 예제

ObjectBox objBox = new ObjectBox();
objBox.setContent("Object Example");  // 문자열 저장
String str = (String) objBox.getContent();  // 캐스팅 필요
System.out.println(str);  // 출력: Object Example

objBox.setContent(2024);  // 정수 저장
Integer num = (Integer) objBox.getContent();  // 캐스팅 필요
System.out.println(num);  // 출력: 2024
  • 문제점:
    1. 캐스팅 필요: 데이터를 꺼낼 때 항상 타입 변환을 해야 합니다.
    2. 타입 에러 가능: 잘못된 타입으로 캐스팅하면 런타임 에러가 발생합니다.
String wrong = (String) objBox.getContent();  // 정수를 문자열로 캐스팅 → 에러 발생!

 

 

3. 제네릭(Generic)으로 해결하기

제네릭 클래스 선언

public class GenericBox<T> {
    T content;  // 내부 데이터 타입은 T
    public T getContent() { return content; }
    public void setContent(T content) { this.content = content; }
}

제네릭 사용 예제

// String 타입 지정
GenericBox<String> strBox = new GenericBox<>();
strBox.setContent("Generic Example");
System.out.println(strBox.getContent());  // 출력: Generic Example

// Integer 타입 지정
GenericBox<Integer> intBox = new GenericBox<>();
intBox.setContent(2024);
System.out.println(intBox.getContent());  // 출력: 2024

제네릭의 장점

  1. 타입 안정성: GenericBox<String>은 문자열만 저장할 수 있어 안전합니다.
  2. 캐스팅 불필요: 데이터를 꺼낼 때 타입 변환이 필요하지 않습니다.

 

4. 제네릭의 동작 원리

템플릿 문자

  • T: Type (데이터 타입)
  • K: Key
  • V: Value
  • R: Return Type

제네릭 클래스 구조

public class GenericBox<T> {  // T는 타입을 나타내는 템플릿
    T content;  // 데이터 저장
    public T getContent() { return content; }
    public void setContent(T content) { this.content = content; }
}

제네릭 동작 방식

  1. 클래스 선언 시: T는 아직 타입이 정해지지 않은 상태입니다.
  2. 객체 생성 시: T의 타입이 결정됩니다.
    • 예: GenericBox<String> → 내부 데이터는 문자열만 저장 가능.

 

5. 제네릭의 활용

제네릭 메서드

public class Util {
    public static <T> void printBoxContent(GenericBox<T> box) {
        System.out.println("Content: " + box.getContent());
    }
}

사용 예제

GenericBox<String> strBox = new GenericBox<>();
strBox.setContent("Hello, Generic!");
Util.printBoxContent(strBox);  // 출력: Content: Hello, Generic!

 

 

6. 제네릭의 장점 요약

  • 코드 재사용성: 한 번 작성하면 다양한 타입에 사용할 수 있습니다.
  • 타입 안전성: 컴파일 시 타입 체크가 이루어져 오류를 줄일 수 있습니다.
  • 유연성: 객체 생성 시 필요한 타입을 지정할 수 있습니다.

 

마무리하며

Java의 제네릭(Generic)은 데이터를 더 안전하고 효율적으로 관리할 수 있도록 도와주는 강력한 도구입니다. 위 예제를 따라 직접 코드를 작성해보며 제네릭의 장점을 체감해보세요! 😊

 

반응형