✅ default 메서드란
public interface MyInterface {
void abstractMethod(); // 추상 메서드
default void defaultMethod() {
System.out.println("default method");
}
}
- 인터페이스에서 구현부(메서드 본문)를 가질 수 있도록 허용된 메서드
default 키워드를 붙여서 선언
- 인터페이스를 구현하는 클래스에서 선택적으로 오버라이드 가능
✅ default 메서드의 특징
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 메서드를 상속받으면 구현 클래스에서 직접 오버라이드하여 충돌 해결 필요
✅ 정적 메서드와의 차이
default 메서드는 구현체의 인스턴스를 통해 호출
static 메서드는 인터페이스명으로 호출
✅ default 메서드를 사용하는 이유
- 기존 코드와의 호환성
- Java 8에서 람다 + 스트림 API 추가 시
Collection, List, Iterable 같은 기존 인터페이스에 새로운 메서드를 넣어야 했음
- 만약 다 추상 메서드였다면 기존 모든 구현체가 깨짐
default 메서드 덕분에 기존 구현체 수정 없이 새로운 기능 추가가 가능해짐
- 인터페이스 기능 확장
- 인터페이스에 공통 동작을 제공할 수 있음
- 구현체마다 똑같이 작성할 필요 없이 기본 동작을 재사용 가능
- 다형성 + 유연성 강화
- 기본 동작을 제공하면서도, 필요시 오버라이드로 맞춤 동작 가능
- 인터페이스가 추상 클래스와 유사한 역할을 하면서도 다중 상속 가능성 유지
✅ 언제 사용하는 것이 좋은가
- 공통 로직을 대부분 구현체가 공유하지만, 일부 구현체는 재정의할 수 있는 경우
- 라이브러리/프레임워크 개발 시 인터페이스를 변경하면서도 기존 사용자의 코드를 깨지 않게 하고 싶은 경우
- 유틸 메서드 성격의 기능을 인터페이스에 직접 넣고 싶을 때