IMCAT.DEV
로그인 가입
Java 중급 자료구조

Java 제네릭 (Generics)

Java 제네릭 (Generics) — 중급

제네릭 (Generics)

1. 도입 (왜 배워야 하는가)

제네릭은 Java에서 매우 중요한 개념으로, 타입 안전성을 제공하고 코드의 재사용성을 높여줍니다. 실무에서는 다양한 데이터 타입을 다루는 경우가 많기 때문에, 제네릭을 이용하면 코드에서 발생할 수 있는 타입 관련 오류를 컴파일 타임에 미리 잡아낼 수 있습니다. 만약 제네릭을 사용하지 않는다면, 타입 캐스팅을 수동으로 처리해야 하며, 이로 인해 런타임 시 오류가 발생할 확률이 높아집니다. 예를 들어, 리스트에서 Integer와 String을 혼용하여 저장할 경우, 잘못된 타입을 꺼낼 때 ClassCastException이 발생할 수 있습니다.

2. 핵심 개념 설명

제네릭은 클래스나 메서드가 사용할 데이터 타입을 매개변수화하여 재사용할 수 있도록 하는 기능입니다. 이를 통해 코드의 유연성과 타입 안전성을 높일 수 있습니다.

  • 타입 매개변수: 제네릭 클래스나 메서드에서 사용할 데이터 타입을 나타내는 변수입니다. 예를 들어, T는 흔히 사용되는 타입 매개변수입니다.
  • 타입 안전성: 컴파일 타임에 타입 오류를 검출할 수 있어, 런타임 오류를 예방할 수 있게 해줍니다.
  • 용어설명
    제네릭 클래스타입 매개변수를 가지는 클래스
    제네릭 메서드타입 매개변수를 가지는 메서드
    와일드카드제네릭 타입으로 특정 범위를 지정할 때 사용하는 기호 ?

    3. 기본 코드 예제

    제네릭의 가장 기본적인 사용법을 보여주는 예제입니다.

    // 제네릭 클래스를 정의합니다.
    class Box<T> {
        private T item;
    
        public void setItem(T item) {
            this.item = item;
        }
    
        public T getItem() {
            return item;
        }
    }
    
    public class Main {
        public static void main(String[] args) {
            // Integer 타입을 사용하는 Box를 생성합니다.
            Box<Integer> integerBox = new Box<>();
            integerBox.setItem(10);
            System.out.println(integerBox.getItem()); // 10
    
            // String 타입을 사용하는 Box를 생성합니다.
            Box<String> stringBox = new Box<>();
            stringBox.setItem("안녕하세요");
            System.out.println(stringBox.getItem()); // 안녕하세요
        }
    }

    실행 결과:

    10
    안녕하세요
  • Box<T>: 제네릭 클래스를 정의하며, T는 타입 매개변수입니다.
  • setItem(T item): item을 Box에 저장하는 메서드입니다.
  • getItem(): 저장된 item을 반환하는 메서드입니다.
  • main 메서드에서는 Integer와 String 타입의 Box 객체를 생성하고, 각각의 아이템을 설정하고 출력합니다.
  • 4. 실전 활용 예제

    1. 쇼핑몰 장바구니 구현
    2. 장바구니에 여러 종류의 상품을 담을 수 있도록 제네릭을 사용합니다.

         class Cart<T> {
             private List<T> items = new ArrayList<>();
      
             public void addItem(T item) {
                 items.add(item);
             }
      
             public List<T> getItems() {
                 return items;
             }
         }

      이 코드는 다양한 타입의 상품을 담는 장바구니를 구현할 수 있습니다. 예를 들어, Cart<Product>를 사용하여 제품을 담을 수 있습니다.

    3. 제네릭 메서드
    4. 제네릭 메서드를 정의하여 다양한 타입의 배열을 처리할 수 있습니다.

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

      이 메서드는 어떤 타입의 배열이든 출력할 수 있습니다. printArray(new Integer[]{1, 2, 3})와 같이 호출할 수 있습니다.

      5. 흔한 실수와 주의사항

    5. 제네릭 타입을 사용할 때 타입 매개변수를 생략하는 경우
    6. - 잘못된 코드:

           Box box = new Box(); // 제네릭 타입을 사용하지 않음

      - 올바른 코드:

           Box<Integer> box = new Box<>(); // 타입 매개변수를 지정
    7. 와일드카드를 잘못 사용한 경우
    8. - 잘못된 코드:

           List<?> list = new ArrayList<Integer>();
           list.add(1); // 컴파일 오류

      - 올바른 코드:

           List<? super Integer> list = new ArrayList<Number>();
           list.add(1); // 올바르게 추가됨

      6. 정리

    9. 제네릭을 사용하면 타입 안전성을 확보할 수 있다.
    10. 코드의 재사용성을 높여주며, 다양한 데이터 타입을 처리할 수 있다.
    11. 제네릭 클래스와 메서드를 통해 유연한 프로그래밍이 가능하다.

다음에 학습하면 좋은 주제는 컬렉션 프레임워크입니다. 제네릭과 함께 Java의 컬렉션을 더 깊이 이해하면 실무에 큰 도움이 될 것입니다.