[Java] 제네릭 활용

2025. 10. 30. 10:32Dev./Java

728x90
반응형

제네릭(Generics)

 

  • 제네릭은 클래스, 메서드, 인터페이스에서 타입을 파라미터로 사용할 수 있게 해주는 기능
  • 타입 안정성(type-safety) 제공 + 코드 재사용성을 높임

문법

class Box<T> {
    private T value;
    
    public void set(T value) { 
    	this.value = value;
    }
    public T get() { 
    	return value; 
    }
}

 

 

  • <T>는 타입 매개변수(Type Parameter)
  • T 자리에 실제 타입이 들어감

제네릭과 Map/Collection

  • Map<Key, Value> 구조에서 Key와 Value를 일반화 가능
  • K와 V를 제네릭 타입으로 선언하면 다른 타입도 재사용 가능
Map<K, V> map = new HashMap<>();

직접 활용해보기

Cart클래스에 제네릭을 활용해볼 수 있었다.

클래스

public class Cart<K extends MenuItem, V extends CartItem> {}
  • extends키워드는 타입 제한 걸 때 사용하는 키워드
    • Cart<K,V>는 아무 타입이나 다 올수 있지만 Cart에는 MenuItem 기반 CartItem 만 담아야 하기 때문에 타입 제한 사용
    • K는 반드시 MenuItem이거나 그 하위 클래스여야 하고, V는 반드시 CartItem이거나 그 하위 클래스여야 한다
    • 타입제한을 두면 getName()같은 MenuItem 내부 메서드 사용 가능

필드 선언

private final Map<K, V> cart = new HashMap<>();

 

장바구니 아이템 추가

public V addCartItem(K key,  int quantity) {
    cart.compute(key, (k, existedCartItem) -> {
        if (existedCartItem == null) existedCartItem = (V)new CartItem(k);
        existedCartItem.increaseQuantity(quantity);
        return existedCartItem;
    });
    return cart.get(key);
}
  • 제네릭 사용으로 key,value 타입 고정하지 않고 사용 가능하다.
  • (V)new CartItem(k) -> Kiosk 입장에서는 MenuItem과 수량만 전달하면 되기 때문에 Cart가 CartItem을 내부에서 만들어주면 호출이 간단해짐

발견한 문제

existedCartItem = (V) new CartItem(k);

 

  • 이 코드는 컴파일러 순간 CartItem을 V로 변환한다는 의미
    • 문제는, V가 CartItem의 하위 클래스일 수도 있기 때문에 런타임 시 ClassCastException이 발생할 위험 가능성 존재
    • 예를 들어 SpeciaCartItem 타입으로 캐스팅 하면 런타임 오류가 남

해결

제네릭 단순화로 안전하게 리팩토링

CartItem 하위 타입 없기 때문에 제네릭은 Key 하나로만 유지해 리팩토링

public class Cart<K extends MenuItem> {
    private final Map<K, CartItem> cart = new HashMap<>();

    public CartItem addCartItem(K key, int quantity) {
        cart.compute(key, (k, existedCartItem) -> {
            if (existedCartItem == null) existedCartItem = new CartItem(k);
            existedCartItem.increaseQuantity(quantity);
            return existedCartItem;
        });
        return cart.get(key);
    }
}
728x90
반응형