반응형
이번 강의에서는 제네릭 타입에서 사용하는 와일드카드(?)와 상한/하한 제한(extends, super)을
수강 등록 시스템을 예로 들어 실습합니다.
registerCourse1, registerCourse2, registerCourse3 각각은 등록 가능한 대상의 타입을 다르게 제한하고 있으며,
이를 통해 유연하지만 안전한 타입 필터링이 가능해집니다.
📌 예제 코드 요약
📦 클래스 구조
class Person {}
class Worker extends Person {}
class Student extends Person {}
class HighStudent extends Student {}
class MiddleStudent extends Student {}
📦 Applicant 클래스
public class Applicant<T> {
public T kind;
public Applicant(T kind) {
this.kind = kind;
}
}
📦 Course 클래스 – 제네릭 메서드 정의
public class Course {
public static void registerCourse1(Applicant<?> applicant) {
System.out.println(applicant.kind.getClass().getSimpleName() + "이(가) Course1을 등록함.");
}
public static void registerCourse2(Applicant<? extends Student> applicant) {
System.out.println(applicant.kind.getClass().getSimpleName() + "이(가) Course2을 등록함.");
}
public static void registerCourse3(Applicant<? super Worker> applicant) {
System.out.println(applicant.kind.getClass().getSimpleName() + "이(가) Course3을 등록함.");
}
}
✅ 메인 실행 예제
public class GenericExample {
public static void main(String[] args) {
// 모든 사람이 수강 가능한 일반 강좌
Course.registerCourse1(new Applicant<>(new Person()));
Course.registerCourse1(new Applicant<>(new Worker()));
Course.registerCourse1(new Applicant<>(new Student()));
Course.registerCourse1(new Applicant<>(new HighStudent()));
Course.registerCourse1(new Applicant<>(new MiddleStudent()));
System.out.println();
// 학생만 수강 가능한 강좌
Course.registerCourse2(new Applicant<>(new Student()));
Course.registerCourse2(new Applicant<>(new HighStudent()));
Course.registerCourse2(new Applicant<>(new MiddleStudent()));
System.out.println();
// 근로자 또는 그 상위 클래스만 수강 가능한 강좌
Course.registerCourse3(new Applicant<>(new Person()));
Course.registerCourse3(new Applicant<>(new Worker()));
}
}
💻 실행 결과
Person이(가) Course1을 등록함.
Worker이(가) Course1을 등록함.
Student이(가) Course1을 등록함.
HighStudent이(가) Course1을 등록함.
MiddleStudent이(가) Course1을 등록함.
Student이(가) Course2을 등록함.
HighStudent이(가) Course2을 등록함.
MiddleStudent이(가) Course2을 등록함.
Person이(가) Course3을 등록함.
Worker이(가) Course3을 등록함.
💬 코드 설명
🔹 Applicant<?>
- registerCourse1은 모든 타입의 지원자 허용
- 와일드카드 <?>는 타입 제한 없이 모든 객체 허용함
🔹 Applicant<? extends Student>
- registerCourse2는 Student와 그 자식 클래스만 허용
- 즉, Student, HighStudent, MiddleStudent만 수강 가능
- Person, Worker는 Student의 하위 클래스가 아니므로 불가
🔹 Applicant<? super Worker>
- registerCourse3는 Worker 또는 그 상위 클래스만 허용
- 즉, Worker, Person은 가능
- Student 및 그 하위 클래스는 불가 (상위 타입 아님)
💡 포인트 정리
선언 형태 | 의미 |
<?> | 모든 타입 허용 |
<? extends T> | T와 그 자식들만 허용 (상한 제한) |
<? super T> | T와 그 부모들만 허용 (하한 제한) |
- extends는 데이터를 꺼낼 때(read) 적합
- super는 데이터를 넣을 때(write) 적합
- 제한을 통해 타입 안전성과 코드 유연성을 동시에 확보할 수 있음
📌 정리하자면, 와일드카드와 extends, super 제한을 활용하면
"누가 수강할 수 있는가?" 같은 조건을 제네릭으로 명확하게 표현할 수 있습니다.
이는 컬렉션, API 설계, 프레임워크 개발 등에서 가장 자주 쓰이는 제네릭 패턴 중 하나입니다.
'프로그래밍 > JAVA' 카테고리의 다른 글
128. 이번엔 상속으로 – Thread 직접 상속하기 (0) | 2025.05.15 |
---|---|
127. 동시에 소리와 출력 실행하기 – Thread로 병렬 처리 (0) | 2025.05.15 |
126. 소리와 글자를 번갈아 출력해보자 – Toolkit.beep()와 Thread.sleep() (0) | 2025.05.15 |
124. 숫자만 비교하자! – 제한된 제네릭(T extends Number) (0) | 2025.05.15 |
123. 메서드에도 제네릭을? – 제네릭 메서드 Boxing() (0) | 2025.05.15 |
122. 제네릭 객체도 비교할 수 있다 – 같은 타입끼리의 compare() 메서드 (0) | 2025.05.15 |