프로그래밍 공부

자바 제네릭 본문

Programming/JAVA

자바 제네릭

khj1999 2024. 10. 9. 13:16

제네릭은 왜 필요한가?

  • 자바 제네릭(Generic)은 클래스, 인터페이스, 메서드에서 사용할 데이터 타입을 매개변수로 받아서
    컴파일 시 타입 안정성을 제공하는 기능.
  • 한 데이터 종류에 묶이지 않은 클래스를 만들기 위해 사용
  • 이를 통해 코드의 재사용성을 높이고, 타입 관련 오류를 런타임이 아니라 컴파일 시점에 발견할 수 있게 해줌

제네릭의 주요 개념

  1. 제네릭 클래스:

     public class Box<T> {
         private T item;
    
         public void setItem(T item) {
             this.item = item;
         }
    
         public T getItem() {
             return item;
         }
     }

    여기서 T는 타입 매개변수로, 실제 사용할 때는 Box<Integer>, Box<String> 등으로
    구체적인 타입을 지정할 수 있음.

  2. 제네릭 메서드:

     public static <T> void printArray(T[] array) {
         for (T element : array) {
             System.out.println(element);
         }
     }

    메서드 선언부에 <T>를 추가하여 제네릭 메서드를 정의할 수 있다.

  3. 제네릭 인터페이스:

     public interface Pair<K, V> {
         public K getKey();
         public V getValue();
     }
  4. 제약 조건:
    제네릭 타입에 제약을 두어 특정 클래스나 인터페이스만 사용할 수 있도록 제한할 수 있다.

     public <T extends Number> void process(T number) {
         // number는 Number의 하위 클래스만 허용
     }
     public class MyGeneric<T extends Number> {
         // 클래스 내용
     }
  5. 와일드카드:
    제네릭에서 특정 타입을 지정하지 않고, 다양한 타입을 허용할 때 사용.

    • ? : 모든 타입을 의미

    • ? extends T : T의 하위 타입만 허용

    • ? super T : T의 상위 타입만 허용

    • 예제*

      import java.util.ArrayList;
      import java.util.List;
      
      public class WildcardDemo {
      
         // 일반 와일드카드
         public static void printList(List<?> list) {
             for (Object element : list) {
                 System.out.println(element);
             }
         }
      
         // 상한 경계 와일드카드
         public static void printNumbers(List<? extends Number> list) {
             for (Number number : list) {
                 System.out.println(number);
             }
         }
      
         // 하한 경계 와일드카드
         public static void addIntegers(List<? super Integer> list) {
             list.add(1);
             list.add(2);
             list.add(3);
         }
      
         public static void main(String[] args) {
             // 일반 와일드카드 예제
             List<String> stringList = new ArrayList<>();
             stringList.add("Hello");
             stringList.add("World");
      
             System.out.println("Printing String List:");
             printList(stringList);
      
             // 상한 경계 와일드카드 예제
             List<Double> doubleList = new ArrayList<>();
             doubleList.add(3.14);
             doubleList.add(2.71);
      
             System.out.println("\nPrinting Double List:");
             printNumbers(doubleList);
      
             // 하한 경계 와일드카드 예제
             List<Number> numberList = new ArrayList<>();
             addIntegers(numberList);
      
             System.out.println("\nPrinting Number List after adding Integers:");
             for (Object obj : numberList) {
                 System.out.println(obj);
             }
         }
      }
      

장점

  • 타입 안전성: 컴파일 시점에 타입 체크가 이루어져, 런타임 오류를 줄일 수 있음.
  • 코드 재사용성: 다양한 데이터 타입에 대해 동일한 코드를 사용할 수 있음.

예제

public class Main {
    public static void main(String[] args) {
        Box<String> stringBox = new Box<>();
        stringBox.setItem("Hello");
        System.out.println(stringBox.getItem());

        Box<Integer> integerBox = new Box<>();
        integerBox.setItem(123);
        System.out.println(integerBox.getItem());
    }
}

'Programming > JAVA' 카테고리의 다른 글

자바 스레드(Thread)  (1) 2024.10.22
JAVA의 함수형 프로그래밍  (1) 2024.10.21
자바 컬렉션 - 객체 정렬  (0) 2024.10.09
자바 컬렉션 - Map  (0) 2024.10.08
자바 컬렉션 - Queue, PriorityQueue  (0) 2024.10.08
Comments