기존에 존재하던 인터페이스에 새로운 메서드를 추가하면 인터페이스를 구현하는 모든 클래스에 메서드 구현을 해줘야한다. 이런 문제를 해결하기 위해 자바 8부터 정적 메서드 사용과 디폴트 메서드 를 사용할 수 있게 되었다. 메서드 구현을 포함하는 인터페이스를 정의할 수 있게 된 것이다. 이 결과 기존 코드에서 추가된 메서드 구현을 강요하지 않고 메서드를 추가할 수 있게 되었다.
List 인터페이스에 sort메서드는 디폴트 메서드이다.
default void sort(Comparator<? super E> c) {
Collections.sort(this, c);
}
이런식으로 default 키워드가 붙어있는 메서드가 디폴트 메서드이다. 디폴트 메서드를 이용하면 자바 API의 호환성을 유지하면서 라이브러리를 바꿀 수 있다.
default라는 키워드로 시작하며 다른 클래스에 선언된 메서드처럼 메서드 바디를 포함한다.공통 상태를 가질 수 있다. 하지만 인터페이스는 인스턴스 변수를 가질 수 없다.default void remove() {
throw new UnsupportedOperationException("remove");
}
다중 상속 을 활용 할 수 있다.디폴트 메서드를 통해 동작 의 다중 상속 을 활용할 수 있다.public interface Rotatable {
void setRotationAngle(int angleInDegrees);
int getRotationAngle();
default void rotateBy(int angleInDegrees) { //디폴트 메서드
setRotationAngle((getRotationAngle() + angleInDegrees) % 360);
}
}
public interface A {
default void hello() {
System.out.println("Hello From A");
}
}
public interface B extends A {
default void hello() {
System.out.println("Hello From B");
}
}
public class C implements B, A {
public static void main(String args[]){
new C().hello();
}
}
클래스가 항상 이긴다. 클래스나 슈퍼클래스에서 정의한 메서드가 디폴트 메서드보다 우선권을 갖는다.서브인터페이스가 이긴다. 상속관계를 갖는 인터페이스에서 같은 시그니처를 갖는 메서드를 정의할 때는 서브인터페이스가 이긴다.명시적으로 디폴트 메서드를 오버라이드하고 호출해야 한다.public interface A {
default void hello() { ... }
}
public interface B {
default void hello() { ... }
}
public class C implements B, A { }
에러를 발생시킨다.public class C implements B, A {
void hello() {
B.super.hello();
}
}
public interface A {
default void hello() { ... }
}
public interface B extends A { }
public interface C extends A { }
public class D implements B, C {
public static void main(String... args) {
new D().hello();
}
}
public interface C extends A {
void hello();
}