-
아이템21. 인터페이스는 구현하는 쪽에서 생각해 설계하라.Java/이펙티브 자바 2023. 9. 5. 11:32
핵심 정리
- 기존 인터페이스에 디폴트 메서드 구현을 추가하는 것은 위험한 일이다.
▷ ex) collection의 removeIf - synchronized 관련한 코드가 없기에 멀티쓰레드 환경에서 안전 X
ㆍ디폴트 메서드는 구현 클래스에 대해 아무것도 모른 채 합의 없이 무작정 "삽입" 될 뿐이다.
ㆍ디폴트 메서드는 기존 구현체에 런타임 오류를 일으킬 수 있다.
public class SubClass extends SuperClass implements MarketInterface { public static void main(String[] args) { SubClass subClass = new SubClass(); subClass.hello(); // SuperClass의 hello는 private, MarketInterface의 hello는 디폴트 메서드 // 항상 class가 메서드를 이기게 되어 있다. // 런타임 오류 발생! } }
- 인터페이스를 설계할 때는 세심한 주의를 기울여야 한다.
ㆍ서로 다른 방식으로 최소한 세 가지는 구현해보자.
완벽 공략 - ConcurrentModificationException
: 현재 바뀌면 안되는 것을 수정할 때 발생하는 예외
- 멀티 스레드가 아니라 싱글 스레드 상황에서도 발생할 수 있다. 가령, fail-fast 이터레이터를 사용해 콜렉션을 순회하는 중에 콜렉션을 변경하는 경우
public class FailFast { public static void main(String[] args) { // List<Integer> numbers = List.of(1,2,3,4,5); // of는 수정할 수 없는 컬렉션 - UnsupportedOperationException List<Integer> numbers = new ArrayList<>(); // 변경가능한 컬렉션 - ConcurrentModificationException numbers.add(1); numbers.add(2); numbers.add(3); numbers.add(4); numbers.add(5); // 이터레이터로 콜렉션을 순회하는 중에 Collection의 remove를 사용한다면...exception 발생 for (Integer number : numbers){ if (number == 3) { numbers.remove(number); } } // 1. 이터레이터의 remove 사용하기 - 안전 for (Iterator<Integer> iterator = numbers.iterator(); iterator.hasNext();) { Integer integer = iterator.next(); if(integer == 3) { iterator.remove(); } } // 2. 인덱스 사용하기 - 안전 for (int i = 0; i < numbers.size() ; i++) { if (numbers.get(i) == 3) { numbers.remove(numbers.get(i)); } } // 3. removeIf 사용하기 numbers.removeIf(number -> number == 3); // 출력 numbers.forEach(System.out::println); } }
'Java > 이펙티브 자바' 카테고리의 다른 글
아이템26. 로 타입은 사용하지 말라. (0) 2023.09.18 아이템 22 & 아이템 23 & 아이템 24 & 아이템 25 (0) 2023.09.07 아이템20. 추상 클래스보다 인터페이스를 우선하라. (0) 2023.08.31 아이템19. 상속을 고려해 설계하고 문서화하라. 그러지 않았다면 상속을 금지하라. (0) 2023.08.30 아이템18. 상속보다는 컴포지션을 사용하라 (0) 2023.08.23