이펙티브자바 아이템 30

한주영·2024년 1월 18일
0

이펙티브자바

목록 보기
22/33

이왕이면 제네릭 메서드로 만들라

클래스와 마찬가지로 메서드도 제네릭으로 만들수있다
매개변수화 타입을 받는 정적 유틸리티 메서드는 보통 제네릭
Collections의 알고리즘 메서드는 모두 제네릭

컴파일은 되지만 경고가 발생한 경우?

1)메서드 타입을 안전하게 만들어야한다.
->메서드 선언에서의 세집합(입력2개,반환1개)의 원소타입을 타입 매개변수로 명시하고 메서드안에서도 타입 매개변수만 사용하게 하면 됨

public static <E>Set<E> union(Set<E> s1, Set<E> s2){
        
        Set<E> result= new HashSet<>(s1);
        result.addAll(s2);
        return result;
    }

단순한 제네릭메서드

    public static void main(String[] args) {

        Set<String>  guys= Set.of("톰","딕","해리");
        Set<String>  stooges= Set.of("래리","모에","컬리");
        Set<String>  aflCio= union(guys,stooges);
        System.out.println(aflCio);



        //System.out.println("Hello world!");
    }

제네릭 메서드를 활용하는 간단한 프로그램

union 메서드는 집합 3개(입력2개,반환1개)의 타입이 모두 같아야한다.

때때로 불변객체를 여러 타입으로 활용할수있게 만들어야할때가있다
제네릭은 런타임에 타입 정보가 소거되므로 하나의객체를 어떤 타입으로든 매개변수화 할수 있다.
->요청한 타입매개변수에 맞게 매번 그 객체의 타입을 바꿔주는 정적 팩터리를 만들어야 한다.
-> 이 패턴을 제네릭 싱글턴 팩터리라 부른다
Collections.reverseOrder같은 함수 객체나
Collections.emptySet과 같은 컬렉션용으로 사용

2)항등함수를 담은 클래스 생성을 가정

제네릭 싱글턴 팩터리패턴

   private static UnaryOperator<Object> IDENTITY_FN=(t)->t;

    @SuppressWarnings("unchecked")
    public static <T> UnaryOperator<T> identityFunction(){
        return (UnaryOperator<T>) IDENTITY_FN;
    }

항등함수란 입력값을 수정없이 그대로 반환하는 특별한 함수
T가 어떤 타입이든 UnaryOperator< T >를 사용해도 타입은 안전하다.

UnaryOperator < String >과 UnaryOperator < Number >로 사용하는 모습

제네릭 싱글턴을 사용하는 예

public static void main(String [] args){
   
   String [] strings={"삼베","대마","나일론"};
   UnaryOperator<String> sameString= identifyFunction();
   for(String s: strings)
        System.out.println(sameString.apply(s));
    
    Number[] numbers={1,2.0,3L};
   UnaryOperator <Number> sameNumber= identifyFunction();
   
   for(Number n: numbers)
        System.out.println(sameNumber.apply(n));
   
}

재귀적 타입한정
주로 타입의 자연적 순서를 정하는 Comprable인터페이스와 함께쓰임

public interface Comaprable<T>{
    int compareTo(T o);
}

Comparable을 구현한 원소의 컬렉션을 입력받는 메서드들은
주로 그원소들을 정렬,검색 하거나 최소,최댓값을 구하는 방식으로 사용

다음은 이 제약을 코드로 표현한 모습

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

타입 한정인 <E extends Comaprable> 는 모든 타입E는 자신과 비교 할 수 있다 라고 읽을수있음.
->상호 비교가능하다

방금 선언한 메서드 구현
컬렉션에 담긴 원소의 자연적 순서를 기준으로 최댓값을 계산
컴파일오류,경고는 발생하지 않는다.

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

      if(c.isEmpty())
          throw new IllegalArgumentException("컬렉션이 비어있습니다");

      E result=null;
      for(E e: c)
          if(result==null || e.compareTo(result)>0)
              result=Objects.requireNonNull(e);
      
      return  result;
  }

핵심정리
1.클라이언트에서 입력매개변수와 반환값을 명시적으로 형변환 해야 하는 메서드보다 제네릭메서드가 더 안전하며 사용하기 쉽다.
2.타입과 마찬가지로 형변환없이 사용할수있는 편이 좋다.
3.형변환을 해줘야하는 기존메서드는 제네릭하게 만드는것이 좋다.
(기존클라이언트는 그대로 둔 채 새로운 사용자의 삶을 훨씬 편하게 만들어줌.)

profile
백엔드개발자가 되고싶은 코린이:)

0개의 댓글