# **자바 제너릭(Generic) 쉽게 배우기** ## **1. 제너릭이 뭐야?** 제너릭(Generic)은 **클래스나 메서드에서 사용할 데이터 타입을 미리 지정하지 않고, 나중에 정할 수 있게 해주는 기능**이다. 쉽게 말해 **"박스를 만들되, 안에 뭐가 들어갈지는 나중에 정하는 것"**과 같다. 예를 들어, `List`는 여러 종류의 데이터를 저장할 수 있다. ```java List strList = new ArrayList<>(); List intList = new ArrayList<>(); ``` 여기서 `List`은 문자열만, `List`는 정수만 저장할 수 있다. 이처럼 **제너릭을 사용하면 타입을 강제할 수 있어 코드의 안정성이 높아진다.** --- ## **2. 제너릭을 사용하지 않으면? (비교 예제)** 제너릭을 사용하지 않는 코드: ```java List list = new ArrayList(); list.add("Hello"); list.add(123); // 문자열 리스트인데 숫자가 들어감 String str = (String) list.get(1); // 실행 시 오류 발생 가능! ``` 위 코드에서는 `List`가 **어떤 타입의 데이터를 가질지 정해져 있지 않다.** 따라서 다른 타입의 데이터가 들어와도 **컴파일러가 오류를 잡아주지 못한다.** --- ## **3. 제너릭을 사용한 코드 (안전한 코드!)** ```java List list = new ArrayList<>(); list.add("Hello"); // list.add(123); // 컴파일 오류 발생! (안전성 증가) String str = list.get(0); // 타입 캐스팅 없이 사용 가능 ``` ✅ **제너릭을 사용하면 타입을 제한할 수 있어 실수를 줄이고, 형 변환 없이 안전하게 데이터를 사용할 수 있다!** --- ## **4. 제너릭 클래스 만들기** 제너릭을 직접 만들어 보자! ```java class Box { // T는 타입 매개변수 private T item; public void setItem(T item) { this.item = item; } public T getItem() { return item; } } ``` 이제 `Box`를 다양한 타입으로 사용할 수 있다. ```java Box strBox = new Box<>(); strBox.setItem("Hello"); System.out.println(strBox.getItem()); // Hello Box intBox = new Box<>(); intBox.setItem(100); System.out.println(intBox.getItem()); // 100 ``` ✅ **제너릭을 사용하면 같은 코드로 여러 타입을 지원할 수 있어 코드의 재사용성이 높아진다!** --- ## **5. 제너릭 메서드 만들기** 제너릭은 클래스뿐만 아니라 **메서드에서도 사용할 수 있다.** ```java class Util { public static void printItem(T item) { System.out.println(item); } } Util.printItem("Hello"); // Hello Util.printItem(123); // 123 Util.printItem(3.14); // 3.14 ``` ✅ **제너릭 메서드를 사용하면 여러 타입을 지원하는 함수를 쉽게 만들 수 있다!** --- ## **6. 제너릭 타입 제한하기 (extends 사용)** 어떤 타입이든 받을 수 있는 것도 좋지만, **특정 타입만 허용하고 싶을 때**가 있다. 이럴 때 `extends` 키워드를 사용해 제한할 수 있다. ```java class NumberBox { // Number 또는 그 자식 타입만 가능 private T num; public NumberBox(T num) { this.num = num; } public double getDoubleValue() { return num.doubleValue(); } } ``` 사용 예시: ```java NumberBox intBox = new NumberBox<>(10); System.out.println(intBox.getDoubleValue()); // 10.0 NumberBox doubleBox = new NumberBox<>(5.5); System.out.println(doubleBox.getDoubleValue()); // 5.5 // NumberBox strBox = new NumberBox<>("Hello"); // 오류 발생! ``` ✅ **제너릭에 `extends`를 사용하면 특정 타입만 허용할 수 있어 더 안전한 코드 작성이 가능하다!** --- ## **7. 와일드카드 (`?`) 활용하기** 제너릭을 사용하다 보면 **다양한 타입을 받아야 하지만, 타입을 정확히 모를 때**가 있다. 이럴 때 **와일드카드 (`?`)** 를 사용할 수 있다. ```java public static void printList(List list) { for (Object obj : list) { System.out.println(obj); } } ``` 사용 예시: ```java List strList = Arrays.asList("A", "B", "C"); List intList = Arrays.asList(1, 2, 3); printList(strList); // A, B, C printList(intList); // 1, 2, 3 ``` ✅ **`?`를 사용하면 어떤 타입이든 받을 수 있어 유연한 코드 작성이 가능하다!** --- ## **8. 정리** ✅ **제너릭을 사용하면 코드의 타입 안정성이 증가하고, 불필요한 형 변환을 줄일 수 있다!** ✅ **제너릭 클래스(`Box`)를 사용하면 여러 타입을 지원하는 재사용 가능한 클래스를 만들 수 있다!** ✅ **제너릭 메서드(`printItem(T item)`)를 사용하면 다양한 타입을 처리하는 메서드를 쉽게 작성할 수 있다!** ✅ **`extends`를 사용하면 특정 타입만 허용할 수 있다!** ✅ **`?`(와일드카드)를 사용하면 유연한 코드 작성이 가능하다!** 자바 제너릭을 활용하면 **더 안전하고 재사용 가능한 코드**를 작성할 수 있다!