본문 바로가기
Java

자바 중급 2편 - 제네릭(2)

by KongJiHoon 2025. 5. 15.

1. 제네릭 사용 예제

 

class DogHospital {
    private Dog dog;
    public void set(Dog dog) { this.dog = dog; }
    public Dog bigger(Dog target) {
        return dog.getSize() > target.getSize() ? dog : target;
    }
}

 

class CatHospital {
    private Cat cat;
    public void set(Cat cat) { this.cat = cat; }
    public Cat bigger(Cat target) {
        return cat.getSize() > target.getSize() ? cat : target;
    }
}

 

문제점

  • 코드 중복 심함 (DogHospital, CatHospital 따로 필요)
  • 타입이 다르면 컴파일 오류로 막힘은 좋지만... 중복이 너무 많음

 

(1) 다형성 활용

class AnimalHospitalV1 {
    private Animal animal;
    public void set(Animal animal) { this.animal = animal; }
    public Animal getBigger(Animal target) {
        return animal.getSize() > target.getSize() ? animal : target;
    }
}

장점

  • 코드 재사용성 UP (동물이면 뭐든 처리 가능)

단점

  • DogHospital.set(cat)처럼 타입을 잘못 넣어도 컴파일 통과 → 런타임 오류 발생 가능
  • 반환 시 다운 캐스팅 필요 → 타입 안정성 ↓

 

(2) 제네릭

class AnimalHospitalV2<T> {
    private T animal;
    public T getBigger(T target) {
        // animal.getSize() ❌ 컴파일 오류
        return null;
    }
}

 

문제점

  • T는 아무 타입이나 들어올 수 있음 (Integer 등도 가능)
  • 자바는 T를 Object로 간주 → getSize(), sound() 불가
  • 결국 Animal의 기능 사용 못함

 

(3) 타입 매개변수 제한(<T extends Animal>)

package com.example.generic.ex3;

import com.example.generic.animal.Animal;

public class AnimalHospitalV3<T extends Animal> {

    private T animal;

    public void set(T animal) {
        this.animal = animal;
    }

    public void checkup() {
        // 상속을 통한 매개변수 제한
        // Animal의 메서드 사용가능
         System.out.println("동물 이름: " + animal.getName());
         System.out.println("동물 크기: " + animal.getSize());
         animal.sound();
    }

    public T bigger(T target) {

        return animal.getSize() > target.getSize() ? animal : target;
    }
}
package com.example.generic.ex3;

import com.example.generic.animal.Animal;
import com.example.generic.animal.Cat;
import com.example.generic.animal.Dog;

public class AnimalHospitalMainV3 {

    public static void main(String[] args) {
        AnimalHospitalV3<Dog> dogHospital = new AnimalHospitalV3<>();
        AnimalHospitalV3<Cat> catHospital = new AnimalHospitalV3<>();


        Dog dog = new Dog("멍멍이1", 100);
        Cat cat = new Cat("냐옹이1", 300);

        // 개 병원
        dogHospital.set(dog);
        dogHospital.checkup();

        // 고양이 병원
        catHospital.set(cat);
        catHospital.checkup();


        // 문제 1: 개병원에 고양이 전달
//        dogHospital.set(cat); // 다른 타입 입력: 컴파일 오류

        // 문제 2: 개 타입 반환 -> 제네릭으로 인해 캐스팅 불필요
        dogHospital.set(dog);
        Dog biggerDog = dogHospital.bigger(new Dog("멍멍이2", 200));
        System.out.println("biggerDog = " + biggerDog);



    }

}

장점

  • T는 반드시 Animal의 자식만 가능
  • getSize(), sound() 등 Animal 기능 사용 가능
  • AnimalHospitalV3<다른 타입> 사용 시 컴파일 오류! ❌

 

 

 

정리

항목 내용
T 타입 매개변수. 어떤 타입이든 들어올 수 있음
<T extends Animal> 타입 제한. Animal 또는 그 자식만 허용
코드 재사용성 제네릭 도입으로 클래스 수 최소화
타입 안전성 다형성 대신 제네릭으로 컴파일 단계에서 오류 포착 가능

'Java' 카테고리의 다른 글

자바 중급 2편 - 제네릭(4)  (0) 2025.06.01
자바 중급 2편 - 제네릭(3)  (0) 2025.05.31
자바 중급 2편 - 제네릭(1)  (0) 2025.05.11
Java 중급 1 - 예외처리(4)  (0) 2025.05.10
Java 중급 1 - 예외처리(3)  (0) 2025.05.05