본문 바로가기
Programming/Java

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

by 읽고 쓰는 개발자 2023. 4. 2.

아이템21. 인터페이스는 구현하는 쪽을 생각해 설계하라.

 

핵심정리

  • 기존 인터페이스에 디폴트 메서드 구현을 추가하는 것은 위험한 일이다.
    • 디폴트 메서드는 구현 클래스에 대해 아무것도 모른 채 합의 없이 무작정 "삽입"될 뿐이다.
    • 디폴트 메서드는 기존 구현체에 런타임 오류를 일으킬 수 있다.
    • ex) Collection 클래스의 removeIf 디폴트 메서드
      • Collection 인터페이스를 구현한 synchronizedCollection 입장에서는 매우 위험
      • synchronizedCollection은 동기화를 통해서 한번에 오직 한 쓰레드만 해당 오퍼레이션을 실행해야 하는데, removeIf 메서드 내에는 동기화 관련 로직이 없기 때문에 안전하지 않은 접근이 됨 (CurrentModificationException) 
      • 해당 기능을 Overriding해야 하지만, 디폴트 메서드가 추가되는 걸 주기적으로 트래킹하여 포착하기 어려움
    • 상위클래스는 상위인터페이스를 우선순위에서 이기게 됨 
      • class / Interface에 같은 이름의 메서드가 있다면 (interface에 디폴트 메서드) 해당 메서드를 호출할 때 슈퍼클래스의 메서드가 호출됨( private이더라도, ) 
      • 디폴트 메서드로 인해 컴파일에러 -> 런타임에러로 변경되어 위험이 가중 
  • 인터페이스를 설계할 때는 세심한 주의를 기울여야 한다.
    • 서로 다른 방식으로 최소한 세 가지는 구현을 해보자.

완벽공략

  • CurrentModificationException 
    • 현재 바뀌면 안되는 것을 수정할 때 발생하는 예외
    • 멀티 스레드가 아니라 싱글 스레드 상황에서도 발생할 수 있다.
      • ex) fail-fast 이터레이터를 사용해 콜렉션을 순회하는 중에 콜렉션을 변경하는 경우 : Iterator가 예외를 던짐
      • Collection이 아니라 Iterator객체에 직접 접근해서 순회하며 변경하면 안전. 가능 (removeIf 메소드의 동작로직)

 

출처 : 백기선님 - 이펙티브 자바 완벽 공략 2부