[이펙티브 자바] 21. 인터페이스는 구현하는 쪽을 생각해 설계하라

노을·2023년 3월 6일
0

이펙티브 자바

목록 보기
14/14
post-thumbnail
post-custom-banner

이미 만들어진 인터페이스에 디폴트 메서드를 추가하는 것은 위험하다.

136p. 디폴트 메서드는 구현 클래스에 대해 아무것도 모른 채 합의 없이 무작정 ‘삽입’될 뿐이다.

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;
}
  • 동기화와 관련된 코드가 전혀 없다.
  • Collection를 구현하는 (동기화를 제공하는) SynchronizedCollection 에서 디폴트 메서드 removeIf가 제대로 동작하지 않는다.
    • Concurrentmodificationexception 발생할 수 있다. 한 스레드가 어떤 Collection을 반복자(iterator)를 이용하여 순회하고 있을때, 다른 한스레드가 해당 Collection에 접근하여 변경을 시도하는 경우이다. 하지만 꼭 멀티스레드 환경에서만 발생 하는것은 아니다. 싱글 스레드 환경에서도 발생할 수 있는데, 위와 같이 어떤 Collection을 순회하고 있는 반복문 안에서, 순회되고 ****있는 Collection에 대한 변경이 시도 될 때 또한 해당 Exception이 발생 하게 된다.





138p. 디폴트 메서드는 (컴파일에 성공하더라도) 기존 구현체에 런타임 오류를 일으킬 수 있다. 흔한 일은 아니지만, 나에게는 일어나지 않으리라는 보장도 없다.

Allow default methods to override Object's methods

상속과 구현의 작동에 적용되는 규칙

Rule #1: Classes win over interfaces.  If a class in the superclass
chain has a declaration for the method (concrete or abstract), you're
done, and defaults are irrelevant.

Rule #2: More specific interfaces win over less specific ones (where
specificity means "subtyping").  A default from List wins over a default
from Collection, regardless of where or how or how many times List and
Collection enter the inheritance graph.
  1. 클래스가 인터페이스보다 우선한다.
  2. 구체적인 인터페이스가 덜 구체적인 인터페이스보다 우선한다.

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

    public static void main(String[] args) {
        SubClass subClass = new SubClass();
        subClass.hello();
    }
}
  • SubClass는 클래스 SuperClass 상속받는다.
  • SubClass는 인터페이스 MarkerInterface 를 구현한다.

subClass.hello()hello()는 어떤 메서드일까? → SuperClass 의 hello()IllegalAccessError 발생

post-custom-banner

0개의 댓글