본문 바로가기
Java/기본 문법

제네릭(Generic)

by 정구정구 2026. 5. 20.

 

제네릭(Generic)

타입을 미리 지정하지 않고 사용 시점에 유연하게 결정할 수 있는 문법

  • 코드 재사용성과 타입 안정성 보장
  • 과도하게 사용하면 코드가 복잡해짐

 

 

제네릭이 없는 경우

함수 재사용 불가능

public class Box {
    private Integer item; // ⚠️ Integer 타입으로 고정

    public Box(Integer item) { // ⚠️ Integer 타입으로 고정
        this.item = item;
    }

    public Integer getItem() {
        return this.item;
    }
}
public class Main {
    public static void main(String[] args) {
        // ✅ Integer 타입 박스
        Box box1 = new Box(100);

        // ❌ String 타입을 저장하려면 새로운 클래스를 만들어야 함
        Box box2 = new Box("ABC"); 

    }
}

 

위와 같이 제네릭 없이 구현하면 String 타입의 item을 받는 새로운 Box 클래스를 만들어야함.

 

타입 안정성이 낮아짐

public class ObjectBox {
    private Object item; // ⚠️ 다형성: 모든 타입 저장 가능 (하지만 안전하지 않음)

    public ObjectBox(Object item) {
        this.item = item;
    }

    public Object getItem() {
        return this.item;
    }
}
public class Main {
    public static void main(String[] args) {
        // ✅ ObjectBox 사용
        ObjectBox objBox = new ObjectBox("Hello");
        String str = (String) objBox.getItem(); // 형변환 필요
        System.out.println("objBox 내용: " + str); // Hello

        // ⚠️ 실행 중 오류 발생 (잘못된 다운 캐스팅: ClassCastException)
        objBox = new ObjectBox(100); // 정수 저장
        String error = (String) objBox.getItem(); // ❌ 오류: Integer -> String 
        System.out.println("잘못된 변환: " + error);
    }
}

 

위와 같이, 형 변환이 필요하지만 안 된 경우, 예외가 발생

 

 

제네릭 활용

T (타입매개변수) : 실제 데이터 타입으로 대체

타입소거(Erasure) : 컴파일 시점에 자동으로 다운캐스팅 코드가 삽입됨

public class GenericBox<T> { // ✅ 제네릭 클래스
    private T item;

    public GenericBox(T item) {
        this.item = item;
    }

    public T getItem() {
        return this.item;
    }
}

 

 

 

제네릭 메서드

메서드 내부에서 사용할 타입을 유연하게 지정하는 기능

메서드 선언부에 <T>가 선언된 메서드

public class GenericBox<T> {

    // 속성
    private T item;

    // 생성자
    public GenericBox(T item) {
        this.item = item;
    }

    // 기능
    public T getItem() {
        return this.item;
    }

		// ⚠️ 일반 메서드 T item 는 클래스의 <T> 를 따라갑니다.
    public void printItem(T item) {
        System.out.println(item);
    }
    
    // ✅ 제네릭 메서드 <S> 는 <T> 와 별개로 독립적이다.
    public <S> void printBoxItem(S item) { 
        System.out.println(item);
    }
}
public class Main {

    public static void main(String[] args) {
        GenericBox<String> strGBox = new GenericBox<>("ABC");
        GenericBox<Integer> intGBox = new GenericBox<>(100);
        
        // ⚠️ 일반메서드: 클래스 타입 매개변수를 따라갑니다.
        // String 데이터 타입 기반으로 타입소거가 발생.
        // String 타입의 다운캐스팅 코드 삽입!
        strGBox.printItem("ABC"); // ✅ String 만 사용가능
        strGBox.printItem(100);   // ❌ 에러 발생 
        
        // ✅ 제네릭 메서드: 독립적인 타입 매개변수를 가집니다.
        // String 타입 정보가 제네릭 메서드에 아무런 영향을 주지 못함.
        // 다운캐스팅 코드 삽입되지 않음.
        strGBox.printBoxItem("ABC"); //✅ 모든 데이터 타입 활용 가능
        strGBox.printBoxItem(100);   //✅ 모든 데이터 타입 활용 가능
        strGBox.printBoxItem(0.1);   //✅ 모든 데이터 타입 활용 가능
    }
}

'Java > 기본 문법' 카테고리의 다른 글

인터페이스(interface)  (0) 2026.06.04
람다(Lambda)  (0) 2026.05.21
Collection  (0) 2026.05.20
Optional  (0) 2026.05.20
예외(Exception)와 예외 처리(try-catch)  (0) 2026.05.20