콘텐츠로 이동

Default Method

Default Method

Java 8에서 인터페이스에 구현부를 포함할 수 있게 된 메서드. default 키워드를 붙인다.

interface Greeting {
    default void hello() {
        System.out.println("Hello!");
    }
}

왜 쓰는가?

기존 인터페이스에 메서드를 추가하면 구현 클래스 전체가 컴파일 오류가 난다. Default Method는 기존 구현 클래스를 깨지 않고 인터페이스에 새 기능을 추가할 수 있게 해준다.

Java 8에서 Collectionstream(), forEach() 등을 추가할 때 이 방식을 사용했다.

// Collection 인터페이스 내부 (Java 8)
default Stream<E> stream() {
    return StreamSupport.stream(spliterator(), false);
}

특징

항목 내용
선언 위치 인터페이스
구현 여부 구현부 포함
오버라이드 구현 클래스에서 선택적으로 가능
상속 구현 클래스가 자동으로 상속받음
접근 제어자 항상 public (생략 가능)

오버라이드

구현 클래스에서 필요하면 재정의할 수 있다.

interface Greeting {
    default void hello() {
        System.out.println("Hello!");
    }
}

class KoreanGreeting implements Greeting {
    @Override
    public void hello() {
        System.out.println("안녕하세요!");  // 재정의
    }
}

다이아몬드 문제

두 인터페이스가 동일한 시그니처의 default method를 가질 때 충돌이 발생한다. 구현 클래스에서 반드시 명시적으로 해결해야 한다.

interface A {
    default void hello() { System.out.println("A"); }
}
interface B {
    default void hello() { System.out.println("B"); }
}

class C implements A, B {
    @Override
    public void hello() {
        A.super.hello(); // 어느 쪽을 쓸지 명시
    }
}

단점 / 주의할 점

상황 문제
두 인터페이스의 default method 충돌 컴파일 오류 — 구현 클래스에서 반드시 오버라이드
남용 인터페이스가 구현 클래스처럼 비대해져 책임이 불명확해짐
상태(필드) 없음 default method는 인터페이스 필드를 가질 수 없어 상태 기반 로직 구현 불가