본문 바로가기

반응형

이번 강의에서는 제네릭 타입에서 사용하는 와일드카드(?)와 상한/하한 제한(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 설계, 프레임워크 개발 등에서 가장 자주 쓰이는 제네릭 패턴 중 하나입니다.

댓글