Java 8 이후 디폴트 메서드를 사용할 수 있게 되었지만, 여전히 주의해야 할 점이 있다.
디폴트 메서드를 선언하면 해당 인터페이스를 구현한 후 디폴트 메서드를 재정의하지 않은 모든 클래스에서 디폴트 구현이 사용된다.
기존 인터페이스에 메서드를 추가할 수 있게 되었지만 모든 기존 구현체들과 연동되리라는 보장은 없다.
[ JAVA 8에서 Collection Interface에 추가된 removeIf 메서드 ]
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 구현체와 잘 어울리는건 아니다.
ex) org.apache.commons.collections4.collection.SynchronizedCollection
- SynchroizedCollection을 사용했을 때 RemoveIf를 사용하게 되면 ConcurrentModificationException가 발생되거나 , 예상하지 못한 다른 결과를 보내준다.
이러한 문제의 예방법
- 구현한 인터페이스의 디폴트 메서드를 재정의하고, 다른 메서드에서는 디폴트 메서드(구현)를 호출하기 전에 필요한 작업을 수행하면 된다.
- 그러나 여전히 수정될 기회도 없고, 수정되지 않는 것들이 존재한다.
디폴트 메서드는 컴파일에 성공하더라도 기존 구현체에 런타임 오류를 일으킬 수 있다.
그럼 어떻게 해야하나?
-> 기존 인터페이스에 디폴트 메서드로 새 메서드를 추가하는 일은 꼭 필요한 경우가 아니면 피하자.
-> 추가하려는 디폴트 메서드가 기존 구현체들과 충돌하지는 않을지 심사숙고하자.
디폴트 메서드는 인터페이스로부터 메서드를 제거하거나 기존 메서드의 시그니처를 수정하는 용도가 아니다.
디폴트 메서드라는 도구가 존재하지만, 인터페이스를 설계할 때는 여전히 세심한 주의를 기울여야 한다.
- Default Method로 기존 interface에 새로운 method를 추가하면 커다란 위험도 딸려온다.
새로운 인터페이스라면 릴리스 전에 반드시 테스트를 거쳐야 한다.
- 최소한 3가지로 구현을 해봐야 한다.
- 각 인터페이스의 인스턴스를 다양한 작업에 활용하는 클라이언트도 여러 개 만들어봐야 한다.
'JAVA > Effective Java' 카테고리의 다른 글
item 23. 태그 달린 클래스보다는 클래스 계층 구조를 활용하라 (0) | 2022.05.07 |
---|---|
item 22. 인터페이스는 타입을 정의하는 용도로만 사용하라 (0) | 2022.05.03 |
item 20. 추상 클래스보다는 인터페이스를 우선하라 (0) | 2022.05.03 |
item 19. 상속을 고려해 설계하고 문서화하라. 그러지 않았다면 상속을 금지해라 (0) | 2022.05.03 |
item 18. 상속보다는 컴포지션을 사용해라 (0) | 2022.04.26 |
댓글