ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 09. Generics
    멋사 부트캠프/Java 프로그래밍 2025. 3. 14. 16:57

    1. Generics 란? 

     

    제네릭스(Generics)는 컴파일 시 타입을 체크하고, 다양한 데이터 타입을 처리할 수 있도록 도와주는 기능

    • 와일드카드(Generics Wildcard) : 유연한 타입을 허용

          - 기본형 와일드 카드 : List<?>

             => List<?> → "어떤 타입의 리스트인지 모르겠지만 받아들일 수 있음."        

     

          - 상한제한형 와일드 카드 : List<? extends T> T와 T의 하위클래스 허용

             => List<? extends Number> → Number 및 Integer, Double 등 가능

     

          - 하한제한형 와일드 카드 : List<? super T> T와 T의 상위클래스 허용

             => List<? super Integer> → Integer, Number, Object 가능

    😂😂😂

    와일드 카드 사용예시)

    ---------------------------------------------------------------------------------------------

     ?  타입이 정확히 필요하지 않고 모든 리스트를 받아야 할 때

    ? extends T읽기 전용, 리스트에서 값을 가져올 때 사용

    ? super T쓰기 전용, 리스트에 값을 추가할 때 사용

     

     

    2. 제네릭스 활용 예제 및 사용 이유

       1) 제네릭스를 사용하지 않은 클래스 경우 문제점

    class Box {
        private Object value;
    
        public void setValue(Object value) {
            this.value = value;
        }
    
        public Object getValue() {
            return value;
        }
    }
    
    public class Main {
        public static void main(String[] args) {
            Box intBox = new Box();
            intBox.setValue(10);
    
            Box strBox = new Box();
            strBox.setValue("Hello");
    
            // 형변환 필요 (타입 안정성 문제 발생 가능)
            int num = (Integer) intBox.getValue(); // ✅ 가능
            String text = (String) strBox.getValue(); // ✅ 가능
        }
    }

    🚨 문제점: Object 타입이라 형변환이 필요하고, 잘못된 형변환 시 런타임 오류 발생 가능!

     

       2) 제네릭스를 사용한 클래스 경우

    class Box<T> {  // "T"는 타입 파라미터 (임의의 타입을 지정 가능)
        private T value;
    
        public void setValue(T value) {
            this.value = value;
        }
    
        public T getValue() {
            return value;
        }
    }
    
    public class GenericExample {
        public static void main(String[] args) {
            Box<Integer> intBox = new Box<>();  // 정수형 박스
            intBox.setValue(10);
            int num = intBox.getValue();  // 형변환 필요 없음! ✅
    
            Box<String> strBox = new Box<>();  // 문자열 박스
            strBox.setValue("Hello");
            String text = strBox.getValue();  // 형변환 필요 없음! ✅
    
            System.out.println(num);   // 10
            System.out.println(text);  // Hello
        }
    }

    ✅ 타입을 유동적으로 변경하여 사용할 수 있다. 

     

    📌 제네릭 사용 이유!

    ✅ 제네릭은 타입 안전성을 높이고, 코드 중복을 줄이는 강력한 기능!

    ✅ 제네릭 클래스를 사용하면 타입 캐스팅이 필요 없음.

    ✅ 와일드카드(?)를 사용하면 제네릭을 더 유연하게 활용 가능!

     

    3. 제네릭 메서드/인터페이스

         1) 제네릭 메서드

    class Util {
        // 제네릭 메서드 정의
        public static <T> void printArray(T[] array) {
            for (T element : array) {
                System.out.print(element + " ");
            }
            System.out.println();
        }
    }
    
    public class GenericMethodExample {
        public static void main(String[] args) {
            Integer[] intArray = {1, 2, 3};
            String[] strArray = {"Hello", "World"};
    
            Util.printArray(intArray);  // ✅ 가능 (출력: 1 2 3)
            Util.printArray(strArray);  // ✅ 가능 (출력: Hello World)
        }
    }

    메서드에 T를 추가하여 다양한 타입을 받을 수 있도록 설정!
    코드를 재사용할 수 있어 효율적!

     

          2) 제네릭 인터페이스

    // 제네릭 인터페이스 정의
    interface Calculator<T> {
        T add(T a, T b);
    }
    
    // Integer 타입 계산기
    class IntegerCalculator implements Calculator<Integer> {
        public Integer add(Integer a, Integer b) {
            return a + b;
        }
    }
    
    // Double 타입 계산기
    class DoubleCalculator implements Calculator<Double> {
        public Double add(Double a, Double b) {
            return a + b;
        }
    }
    
    public class GenericInterfaceExample {
        public static void main(String[] args) {
            Calculator<Integer> intCalc = new IntegerCalculator();
            System.out.println(intCalc.add(5, 10));  // 15
    
            Calculator<Double> doubleCalc = new DoubleCalculator();
            System.out.println(doubleCalc.add(5.5, 2.2));  // 7.7
        }
    }

    Calculator<T>를 사용해 다양한 타입의 계산기를 만들 수 있음!

     

    🎯 제네릭 정리

    제네릭 클래스 다양한 타입을 지원하는 클래스 class Box<T> { T value; }
    제네릭 메서드 여러 타입을 지원하는 메서드 <T> void printArray(T[] array)
    제네릭 인터페이스 타입에 따라 구현이 달라지는 인터페이스 interface Calculator<T> { T add(T a, T b); }
    와일드카드 (?) 불특정한 타입을 표현 List<?> list
    ? extends T T의 하위 타입만 허용 (읽기 전용) List<? extends Number>
    ? super T T의 상위 타입만 허용 (쓰기 가능) List<? super Integer>
Designed by Tistory.