Notice
Recent Posts
Recent Comments
«   2026/04   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30
Tags
more
Archives
Today
Total
관리 메뉴

Spring & Java

제네릭 ( Generic ) 본문

JAVA 개념 확장

제네릭 ( Generic )

dev.hyuck 2025. 12. 15. 16:02

예외 ( Exception )과 예외처리 (try-catch)

Optional - null을 다루는 법

제네릭 ( Generic )

컬렉션 ( Collection )

 

 

학습 키워드 점검

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

타입 소거 - 컴파일 시점에 제네릭 타입 정보를 제거하는 과정

제네릭 클래스 - 클래스 선언 시 < T > 타입매개변수를 사용해 다양한 데이터 타입을 안전하게 처리할 수 있는 구조

제너릭 메서드 - 클래스의 타입 매개변수와 별개로 독립적인 타입 매개변수를 가진 메서드

 

제네렉 ( Generic ) 이란?

제네릭이 무엇인지 학습해 봅시다.

● 제네릭은 클래스, 메서드 등에 사용되는 < T > 타입 매개변수를 의미합니다.

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

● 제네릭을 활용하면 코드 재사용성과 타입 안정성을 보장받을 수 있습니다.

● 하지만 과도하게 사용하면 오히려 복잡해질 수 있으므로 주의해야 합니다.

[ 1 ] 코드 재사용성

● 다양한 타입에서 동일한 코드로 재사용이 가능합니다.

[ 2 ] 타입 안정성

● 잘못된 타입 사용을 컴파일 시점에 방지합니다.

 

제네릭이 없는 경우

Box 클래스를 예시로 아래의 두 케이스를 살펴봅시다.

[ 1 ] 제네렉이 없는 경우 재사용 불가

[ 2 ] 제네릭이 없는 경우 타입 안정성 보장 불가

 

제네릭이 없는 Box 클래스 - 재사용 불가

● 이 클래스는 특정 타입 ( Integer)으로 고정되어 있어 재사용이 어렵습니다.

ㄴ ○ String 타입 전용 박스가 필요하다면 다시 만들어야 합니다.

● 다시 사용하려면 타른 클래스를 만들어야 합니다 ( 낮은 유연성 )

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"); 

    }
}

 

 제네릭이 없는 Box 클래스 - 낮은 타입 안전성 

● 다형성을 활용하면 다양한 타입을 저장 가능하지만 실행 중 오류가 발생할 가능성이 높습니다.

● 사용 시 형 변환이 필요하고 실수로 잘못된 타입을 사용하면 런타임 오류가 발생합니다.

> 잘못된 다운케스팅 활용 시 : ClassCastException

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 > ( 타입 매개변수 )

● < T > (타입 매개 변수 )는 제네릭에서 타입을 의미하는 자리입니다.

● 실제 데이터 타입으로 대체되어 활용됩니다.

 

클래스에서 제네릭을 활용해 재사용성과 타입안전성을 보장받을 수 있습니다.

● 제네릭 클래스는 클래스 선언부에 < T > 가 선언된 클래스 입니다.

● 제네릭 클래스는 클래스 선언시 타입 매개변수를 사용해 다양한 데이터 타입을 안전하게 처리할 수 있는 구조 입니다.

● GenericBox<T> 를 활용해서 String, Integer, Double 등 다양한 타입 저장 가능 합니다.

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

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

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

타입소거(Erasure) 
타입 소거는 컴파일 시점에 제네릭 타입 정보를 제거하는 과정입니다.
<T> 타입 매개변수 부분은 Object 로 대체됩니다.
필요한 경우 컴파일러가 자동으로 강제 다운 캐스팅(cast) 코드를 삽입하여 타입 안전성을 보장합니다.

public class Main {
    public static void main(String[] args) {
    
        // 1. ✅ 재사용 가능(컴파일시 타입소거: T -> Object)
        GenericBox<String> strGBox = new GenericBox<>("ABC");
        GenericBox<Integer> intGBox = new GenericBox<>(100);
        GenericBox<Double> doubleGBox = new GenericBox<>(0.1);

        // 2. ✅ 타입 안정성 보장(컴파일시 타입소거: 자동으로 다운캐스팅)
        String strGBoxItem = strGBox.getItem();
        Integer intGBoxItem = intGBox.getItem();
        Double doubleGBoxItem = doubleGBox.getItem();
        System.out.println("strGBoxItem = " + strGBoxItem);
        System.out.println("intGBoxItem = " + intGBoxItem);
        System.out.println("doubleGBoxItem = " + doubleGBoxItem);
    }
}

 

제네렉 메서드 ( Generic Method )

제네릭 메서드는 메서드 내부에서 사용할 타입을 우연하게 지정하는 기능입니다.

● 제네릭 메서드는 메서드 선언부에  < 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);   //✅ 모든 데이터 타입 활용 가능
    }
}

 

제네릭이 활용된 곳

자바에서 < T > 제네릭이 활용된 곳

● optional < T > 와 ArrayList<T> 컬렉션 클래스 등은 제네릭 클래스 입니다.

● 여기서 < T > 는 실제 데이터 아입으로 대체되어 활용 됩니다.

 

'JAVA 개념 확장' 카테고리의 다른 글

스트림 ( Stream )  (0) 2025.12.18
람다 (Lambda)  (0) 2025.12.17
컬렉션 ( Collection )  (0) 2025.12.15
Optional - null을 다루는 법  (0) 2025.12.12
예외 ( Exception )과 예외처리 (try-catch)  (0) 2025.12.12