본 포스트는 책 '이펙티브 자바' 에서 학습한 내용을 기반으로 작성되었습니다.

요약

자바 8부터 디폴트 메서드의 도입으로 기존의 인터페이스를 문제없이 수정할 수 있게 되었지만, 되도록이면 신중하게 디폴트 메서드를 추가하자.

 

디폴트 메서드

디폴트 메서드는 자바 8부터 추가된 내용으로, 기존 인터페이스에 메서드를 추가할 수 있는 새로운 방법이다. 인터페이스의 기존 구현체에서 디폴트 메서드를 재정의 하지 않아도 디폴트 구현이 자동으로 쓰이기 때문에 웬만하면 문제없이 인터페이스에 추가할 수 있다고 한다. (100%는 아님)

자바 8에서는 람다를 활용하기 위한 목적으로 핵심 컬렉션 인터페이스들에 다수의 디폴트 메서드가 추가되었음.

 

예시 : removeIf()

// 예시
arrayList.removeIf('람다?')

// 디폴트 메서드 안에 함수형 인터페이스를 활용해 람다를 사용할 수 있다? 
default boolean removeIf(Predicate<? super E> filter) {
        Objects.requireNonNull(filter);
        boolean result = false;
        for (Iterator<E> it = iterator(); it.hasNext();) {
            if (filter.test(it.next())) {
                it.remove();
                result = true;
            }
        }
        
        return result;
    }
  • 반복자를 이용해 순회하면서 각 원소를 인수로 넣어 프레디키트를 호출
  • 프레디키드가 반환값이 true라면 반복자의 remove 메서드를 호출
  • 해당 원소 제거

 

문제

  • 디폴트 메서드 추가로 문제를 안 일으킨다는 보장이 없음
    • 변경 전 인터페이스를 사용하는 클라이언트에서 문제 발생 가능성 존재
    • 컴파일 에러가 발생하지 않더라도, 런타임 에러의 위험성
    • 예기치 못한 충돌/API 재앙, 사용자 불편 상황 발생 가능성 존재

→ 되도록이면 기존 인터페이스에는 디폴트 메서드를 추가하지 말자.

 

문제 해결 방법

  1. 인터페이스 구현체에서 디폴트 메서드 재정의 강제
  2. 다른 메서드에서는 디폴트 메서드를 호출하기 전에 필요한 작업 강제
  3. 기존 인터페이스에 디폴트 메서드로 새 메서드를 추가하는 일은 꼭 필요한 경우가 아니면 하지 말자
  4. 기존 인터페이스가 아닌 새로운 인터페이스를 설계하는 경우라면 위험성 적음

 

인터페이스 설계 후 해야할 일들

바로 잡을 기회가 아직 남았을 때 결함을 테스트로 찾아내자

  1. 새로운 인터페이스인 경우 릴리스 전에 반드시 테스트를 거쳐야 함
  2. 인터페이스의 서로 다른 구현 케이스를 생각해 테스트 해야함
  3. 인터페이스를 사용하는 다양한 클라이언트도 만들어서 테스트 해야함

+ Recent posts