본문 바로가기

Dev Book Review/Effective Java

[Effective Java] item30. 이왕이면 제네릭 메서드로 만들라

1. 제네릭 메서드 만들기

메서드도 제네릭으로 만들 수 있다. ex ) Collections의 '알고리즘' 메서드

  • 메서드 선언에서 원소타입을 타입 매개변수로 지정한다.
  • 메서드 안에서 이 타입 매개변수를 사용하게 수정한다.
  • 타입 매개변수 목록은 메서드의 제한자와 반환타입 사이에 온다.
  • 한정적 와일드 카드 타입을 사용하면, 반환타입 입력타입 등을 좀더 유연하게 개선할 수 있다.
public static <E> Set<E> union(Set<E> s1, Set<E> s2){
  Set<E> result = new HashSet<>(s1);
  result.addAll(s2);
  return result;
}

 

2. 제네릭 : 불변 객체를 여러 타입으로 활용할 수 있게 만드는 방법

불변객체가 제네릭 타입일 때 여러 타입으로 활용이 가능하다. 요청 타입 변수에 맞게 객체의 타입을 바꾸어주는 "제네릭 싱글턴 팩터리"가 필요하다.

 

a. 함수객체 : 함수 내부에 들어가는 객체

List<String> str = Arrays.asList("a","b","c");
str.sort(Collectioins.reverseOrder());

제네릭 싱글턴 팩터리 패턴을 띄고있다.

reverseComparator를 형변환하는 코드로 비검사 형변환 경고가 발생하여, @SuppressWarning 애너테이션을 추가하여 경고 없이 컴파일되도록 숨겼다.

 

b. 재귀적 타입 한정 (recursive type bound)

자기 자신이 들어간 표현식을 사용하여 타입 매개변수의 허용범위를 한정한다.

public static <E extends Comparable<E>> E max(Collection<E> c);

모든 타입 E는 자기 자신과 같은 타입인 원소 모두와 비교 가능하다

cf) 시뮬레이트한 셀프타입 관용구 - [아이템 2]

- 관련 자바봄 이슈) 

재귀적 타입 한정을 이용하는 제네릭타입이다.

추상메서드 self 를 지원하여 하위클래스에서 형변환 하지 않고도 메서드 연쇄를 지원할 수 있으며. self 타입이 없는 자바를 위한 우회방법을 이야기 한다.

public abstract class PayCard {
    public enum Benefit {
        POINT("포인트"), SALE("할인"), SUPPORT("연회비지원");
        Benefit(String benefit) {
        }
    }

    final Set<Benefit> benefits;

    abstract static class Builder<T extends Builder<T>> { // 재귀적 타입한정
        EnumSet<Benefit> benefits = EnumSet.noneOf(Benefit.class);

        public T addBenefit(Benefit benefit) {
            this.benefits.add(benefit);
            return self();
        }

        abstract PayCard build();

        protected abstract T self();
    }

    PayCard(Builder<?> builder) {
        benefits = builder.benefits.clone();
    }
}
public static class Builder extends PayCard.Builder<Builder>{
        private final Sale sale;

        public Builder(Sale sale) {
            this.sale = sale;
        }

        @Override
        NaverPayCard build() {
            return new NaverPayCard(this);
        }

        @Override
        protected Builder self() {
            return this;
        }
    }

재귀적 타입 한정을 사용함으로 인해서, PayCard의 하위타입인 NaverPayCard에서 상위 클래스의 메서드를 호출 할 수 있게 된다.

https://github.com/Java-Bom/ReadingRecord/issues/75

 

 

[아이템 30] 시뮬레이트한 셀프 관용구 · Issue #75 · Java-Bom/ReadingRecord

180p 시뮬레이트한 셀프관용구에 대한 설명이 나오는데, 이게 2장의 Builder패턴 pizza를 상속받은 nypizza 빌더패턴에 대한 이야기야, 이거 한번 구현해보고 실제로 왜 재귀적 타입한정을 써야 이런 ��

github.com