본문 바로가기
공부/이펙티브자바

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

by 띵커베르 2023. 2. 6.
728x90
  • 인터페이스에 디폴트 메서드를 선언하면, 해당 메서드를 재정의하지 않은 모든 클래스에서 디폴트 구현이 쓰이게 된다.
    • 자바 8 전에는 기존 구현체를 깨뜨리지 않고 인터페이스에 메서드를 추가할 방법이 없었다.
    • 인터페이스에 새로운 메서드 추가는 절대로 없다라고 가정하였으며
    • 디폴트 메서드로 추가하는 길이 열렸지만 기존 구현체들과 매끄럽게 연동되리라는 보장은 없다.
  • 디폴트 메서드는 구현 클래스에 대해 아무것도 모른 채 합의 없이 무작정 "삽입"될 뿐.
  • 디폴트 메서드는 컴파일이 성공하더라도 기존 구현체에 런타임 오류를 일으킬 수 있다.
interface MarkerInterface {
    default void hello() {
        System.out.println("MarkerInterface.hello");
    }
}

class SuperClass {
    private void hello() {
        System.out.println("SuperClass.Hello");
    }
}

public class SubClass extends SuperClass implements MarkerInterface{
    public static void main(String[] args) {
        SubClass subClass = new SubClass();
        subClass.hello();
    }
}
  • 위코드를 실행하면 IllegalAccessError가 발생하는데, 이는 SubClass 에서 Super 클래스의 hello 메서드에 접근하려 해서이다.
  • 원래 같으면 private 라 접근이 불가능하지만 interface 를 상속받음으로써 버그같은 결과가 발생한다.
  • 기타 - ConcurrentModificationException
    • 런타임 에러로, 리스트나, 맵 이터레이터 순회중 컬렉션에대한 값을 변경하거나 삭제하려할때 나오는 에러이다.
public class ConcurrentModificationExceptionExample {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);

        for (Integer num : list) {
            //list.remove(num); //ConcurrentModificationException
        }

        Iterator<Integer> iterator = list.iterator();
        while (iterator.hasNext()) {
            Integer element = iterator.next();
            //list.remove(element); //ConcurrentModificationException
            iterator.remove();
        }

        //[]
        System.out.println(list);
    }
}
728x90

댓글