IT/Programming / / 2023. 4. 27. 09:26

<Effective Java> RULE 28 한정적 와일드카드를 써서 API 유연성을 높여라

반응형

 

형인자 자료형은 불변 자료형으로 List<String>은 List<Object>의 하위 자료형이 될 수 없다.

//와일드 카드를 사용하지 않은 pushAll
public void pushAll(Iterable<E> src){
   for(E e : src){
      push(e);
   }
}
//문제가 있다!
 

* 해당 함수는 Iterable<E> src가 가리키는 원소의 자료형이 스택 원소의 자료형과 일치하면 제대로 동작하지만

스택이 Stack<Number>일 경우.. (Integer는 Number의 하위 자료형이다)

Stack<Number> numberStack = new Stack<Number>();
Iterable<Integer> integers = ..;
numberStack.pushAll(*integers*);
           ^ ERROR!
// 형인자 자료형은 불변 자료형이기 때문에 에러가 나는 현상
 

위와같이 에러가 발생한다. 따라서 한정적 와일드 카드 자료형을 사용해야 한다.

 

E의 Iterable이 아니라 E의 하위 자료형의 Iterable이 되야 한다. (모든 자료형은 자기 자신의 하위 자료형이다.)

· Iterable<? extends E>

//와일드 카드를 적용한 pushAll
public void pushAll(Iterable<? extends E> src){
    for(E e : src){
       push(e);
    }
}
//형 안전성이 보장된다!
 

popAll메서드를 구현!

//popAll 메서드! 
public void popAll(Collection<E> dst){
   while(!isEmpty()){
      dst.add(pop());
   }
}
//문제가 있다!
 

컬렉션 원소가 원소의 자료형이 스택의 자료형과 일치할 때 완벽히 동작한다.

 

Stack<Number> numberStack = new Stack<Number>();
Collection<Obejct> objects = ...;
numberStack.popAll(objects);
           ^ ERROR!!
//Collection<Object>가 Collection<Number>의 하위자료형이 아니기 때문에 발생하는 오류!
 

 

E의 컬렉션이 아니라 E의 상위자료형의 컬렉션이라고 명시해야 한다.(모든 자료형은 자기 자신의 상위 자료형!)

· Collection<? super E>

public void popAll(Collection<? super E>){
    while(!isEmpty())
          dst.add(pop());
}
 

객제 생산자나 소비자 구실을 하는 메서드의 인자의 자료형은 와일드 카드 자료형으로 하는것이다. 만일 메서드 인자가 생산자인 동시에 소비자라면 와일드 카드는 쓸모가 없다.

자료형이 정확하게 일치해야 할 경우는 와일드 카드를 빼야 한다.

 

규칙 27의 Union메소드

public static <E> Set<E> union(Set<E> s1, Set<E> s2)

->
// 와일드 카드 자료형
public static <E> Set<E> union(Set<? extends E> s1, Set<? extends E> s2)
// 반환값은 여전히 E임을 유의!, 반환값에는 와일드 카드 자료형을 쓰면 안된다. 
// (클라이언트 코드에 와일드 카드 자료형을 명시해야 하므로)
 

자료형 유추

Set<Integer> integers = ...;
Set<Double> doubles = ...;
Set<Number> numbers = union(integers, doubles);
                           ^ ERROR!!
 

컴파일러가 자료형을 정확히 유추하지 못할 경우 명시적 형인자를 통해 어떤 자료형을 쓸지 알려줄 수 있다.

Set<Number> numbers = Union.<Number>union(integers, doubles);
 

규칙 27의 max 메서드

public static <T extends Comparable<T>> T max(List<T> list)

->
// 와일드 카드 자료형
public static <T extends Comparable<? super T>> T max(List<? extends T> list)
 

T객체는 생산자 이므로 T를 List<T>에서 List<? extends T>

T에 대한 Coaparable은 T객체를 소비하므로 Comparable<? super T>

 

*Comparable<T>는 언제나 소비자이므로 Comparable<? super T>를 사용해야 한다.

*Comparator<T> 도 마찬가지로 Comparator<? super T>

 

*형인자가 메서드 선언에 단 한군데 나타난다면 해당 인자를 와일드 카드로 바꾸고 비한정적 형인자이면 비한정적 와일드 카드로, 한정적 형인자면 한정적 와일드카드로 바꿔라.

 

반응형
  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유