본문 바로가기
개발 공부/Java

이펙티브 자바 아이템 21 - 인터페이스는 구현하는 쪽을 생각해 설계하라 - 핵심 정리

by 개발인생 2022. 11. 29.
반응형

아이템 21 - 인터페이스는 구현하는 쪽을 생각해 설계하라 - 핵심 정리

이 글은 백기선 님의 이펙티브 자바 강의와 이펙티브 자바 3 / E 편을 참고하여 작성하였습니다.

인터페이스에 디폴트 메서드를 추가하면 다소 위험한 상황이 벌어질 수도 있다.

인터페이스에 디폴트 메서드를 추가하는 것은 해당 인터페이스를 구현한 모든 클래스에 해당 기능을 강제적으로 삽입하는 것을 의미한다.

이로인해 예기치못한 문제가 발생할 수 있다.

public interface Collection<E> extends Iterable<E> {
   // -- 중간 생략 --
   default boolean removeIf(Predicate<? super E> filter) {
      Objects.requireNonNull(filter);
      boolean removed = false;
      final Iterator<E> each = iterator();
      while (each.hasNext()) {
         if (filter.test(each.next())) {
            each.remove();
            removed = true;
         }
      }
      return removed;
   }
}    

대표적인 예로 컬렉션에 들어있는 removeIf 라는 메서드이다.

인터페이스 관점에서 보면 디폴트 메서드로 추가된 removeIf 에는 아무 문제가 없다.

하지만 이걸 구현한 SynchronizedCollection 입장에서는 굉장히 위험한 기능이 추가된 것이다.

SynchronizedCollection 은 모든 오퍼레이션을 동기화를 통해 멀테 스레드 환경 에서

한번에 한 스레드만 해당 오퍼레이션을 실행하도록 한다.

하지만 인터페이스에 추가된 removeIf 메서드에는 동기화와 관련된 코드가 존재하지 않는다.

즉, 멀티 스레드에서 안전하지 않은 컬렉션이 된다는 뜻이다.

SynchronizedCollection 에서 누군가가 removeIf 메서드를 호출한다면 ConcurrentModificationException 이 발생할 수 있다.

이렇게 인터페이스에 추가된 디폴트 매서드가 해당하는 클래스에 해가 될 수 있거나 예상치 못한 동작이라면

추가된 메서드를 오버라이딩 해야한다.

어디까지나 인터페이스를 우리가 관리하는 라이브러리에서나 가능한 일이다.

제 3의 써드파티에서 어떤 인터페이스에 어떤 디폴트 메서드가 추가되었는지 확인하기는 어렵다.

디폴트 메서드가 추가되었다고 컴파일 오류가 뜨지는 않기 때문이다.

인터페이스에 디폴트 메서드를 심사숙고하여 추가해야한다.


인터페이스에 디폴트 메서드를 추가함으로써 런타임 오류 가 발생할 수 있다.

public class SuperClass {

    private void hello() {
        System.out.println("hello class");
    }
}
public interface MarkerInterface {

    default void hello() {
        System.out.println("hello interface");
    }
}
public class SubClass extends SuperClass implements MarkerInterface {

    public static void main(String[] args) {
        SubClass subClass = new SubClass();
        subClass.hello();
    }
}

위의 코드에서는 에러가 발생한다.

메서드 호출 시에는 클래스가 인터페이스 보다 우선순위가 높으므로 SuperClass 클래스에 있는 hello 메서드를 호출하게 된다.

하지만 hello 메서드는 private 이므로 런타임 오류가 발생한다.

사실 이러한 동작은 버그 에 가깝다.

나중에 언젠가 고쳐질 가능성이 크지만 현재 (자바 17버전) 까지는 에러가 발생한다.

반응형

댓글