본문 바로가기
자바프로그래밍

제네릭 클래스 메서드 자바프로그래밍

by aiyoon 2025. 5. 24.
반응형

✅ 1. 제네릭이란? (뜻)


제네릭(Generic)은 클래스나 메서드에서 사용할 데이터 타입을 외부에서 지정할 수 있도록 만든 문법입니다.
즉, **“타입을 변수처럼 사용하는 기능”**입니다.



✅ 2. 제네릭이 왜 필요한가요?


필요 이유 설명

📦 재사용성 하나의 클래스/메서드로 다양한 타입 처리 가능
🔒 타입 안정성 컴파일 시점에 타입 오류 잡기 가능
✂️ 형변환 제거 Object → 원하는 타입 강제 형변환 없이 사용 가능




✅ 3. 제네릭 사용 예시


📌 3-1. 제네릭 클래스 사용 (ArrayList 등)

ArrayList<String> list = new ArrayList<>();
list.add("안녕");
// list.add(123); // ❌ 오류: 정수는 String이 아님



📌 3-2. 사용자 정의 클래스에 제네릭 사용

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



사용:

Box<String> stringBox = new Box<>();
stringBox.setItem("Hello");

Box<Integer> intBox = new Box<>();
intBox.setItem(100);



✅ 제네릭 사용 예시

 

1. 사용자 정의 타입을 넣은 경우

class Book { 
    private String title; 
    public Book(String title) { this.title = title; } 
    public String toString() { return "도서: " + title; } 
} 

// Book 객체를 저장하는 리스트 
ArrayList<Book> bookList = new ArrayList<>(); 
bookList.add(new Book("자바의 정석")); 
bookList.add(new Book("파이썬 완전정복")); 
System.out.println(bookList.get(0)); // 도서: 자바의 정석

2. 제네릭 타입을 생략한 경우 (타입 없음)

ArrayList list = new ArrayList(); // 제네릭 생략 - 비추천 
list.add("문자열"); 
list.add(123); // 정수도 가능 (혼합 가능)

Object obj = list.get(0); // 꺼낼 때 형변환 필요 
System.out.println((String)obj); // 명시적 형변환 필요
  • 단점: 타입 안정성 떨어짐, 형변환 필요, 오류 위험 ↑

3. 타입을 String으로 넣은 경우

ArrayList<String> strList = new ArrayList<>(); 
strList.add("안녕하세요"); 
// strList.add(123); // ❌ 오류! Integer는 넣을 수 없음 

String msg = strList.get(0); // 형변환 없이 사용 가능 
System.out.println(msg); // 안녕하세요
  • 장점: 문자열만 저장 가능, 컴파일 시 타입 체크됨

4. 타입을 Integer로 넣은 경우

ArrayList<Integer> intList = new ArrayList<>(); 
intList.add(100); 
intList.add(200); 

int num = intList.get(0); // 형변환 없이 사용 가능 
System.out.println(num); // 100
  • int는 기본 자료형이지만, 제네릭에는 Integer라는 래퍼 클래스를 사용해야 합니다.

✅ 정리 표


선언 설명 특징
ArrayList<Book> 사용자 정의 타입 사용자 클래스 객체 저장
ArrayList 제네릭 생략 모든 타입 허용, 위험
ArrayList<String> 문자열 전용 타입 안정성 좋음
ArrayList<Integer> 정수 전용 자동 언박싱 지원됨




✅ 4. 제네릭 메서드

public <T> void print(T value) {
System.out.println(value);
}



사용:

print("문자열");
print(123);
print(new Book(...));




✅ 5. 제네릭 와일드카드 (?, extends, super)


문법 의미

<?> //모든 타입 허용 (Object처럼 동작)
<? extends Number>  //Number 또는 그 하위 타입만 허용
<? super Integer> //Integer 또는 그 상위 타입만 허용

✔ ?의 의미: 와일드카드 (Wildcard)

?는 "어떤 타입이든 상관없다" 는 의미의 "알 수 없는 타입" 을 나타냅니다.


✔ 주요 사용 형태와 의미

문법 의미 설명
<?> 아무 타입이나 허용 모든 타입 허용 (Object 비슷하지만 다름)
<? extends T> T와 그 하위 타입 허용 읽기는 안전, 쓰기는 제한적
<? super T> T와 그 상위 타입 허용 쓰기는 안전, 읽기는 제한적
 

✔ 예제 코드로 이해하기

1. <?> — 모든 타입 허용

List<?> list = new ArrayList<String>(); 
list = new ArrayList<Integer>();
  • 타입이 무엇이든 가능 (List<String>, List<Integer> 등)
  • 읽기만 가능, 쓰기는 null 외에 불가

2. <? extends Number> — 하위 타입만 허용

List<? extends Number> numbers = new ArrayList<Integer>(); 
numbers = new ArrayList<Double>(); 
// numbers.add(1); // ❌ 컴파일 오류
  • Integer, Double, Float 등 Number의 자식들만 허용
  • 값을 꺼내서 읽는 것은 가능, 하지만 추가는 제한적

3. <? super Integer> — 상위 타입만 허용

List<? super Integer> nums = new ArrayList<Number>(); 
nums.add(1); // ✅ 가능 
nums.add(100); // ✅ 가능 
// Integer보다 위인 Number, Object 등 가능
  • Integer보다 상위 타입만 허용 (Number, Object)
  • 값을 추가하는 것은 안전, 꺼낼 때는 Object로 나옴

✔ 와일드카드 vs 제네릭 타입 변수


구분 사용 예 특징
일반 제네릭 List<T> 선언부에서 직접 타입 매개변수로 받음
와일드카드 List<?>, List<? extends T> 호출 시 타입의 유연성을 부여




✅ 6. 자주 쓰이는 제네릭 클래스

클래스 설명
ArrayList 동적 배열
HashMap<k, v=""></k,> 키-값 저장 구조
Optional null 안정 처리
Comparator 정렬 기준 설정 인터페이스
Comparable 자기 자신 비교용 인터페이스





📝 정리 요약

항목 내용
정의 클래스나 메서드에서 사용할 타입을 외부에서 지정
장점 재사용성, 타입 안전성, 형변환 없음
기본 문법  class Box, ArrayList, T method(T input)
실전 활용 컬렉션, 사용자 정의 클래스, 도메인 모델 등



 

반응형