인터페이스는 한마디로 말하자면 일종의 추상 클래스다. 추상 클래스처럼 추상메서드를 갖지만, 추상 클래스보다 추상화 정도가 높아서 추상 클래스와 달리 추상 메서드와 상수만을 멤버로 가질 수 있다.
추상 클래스를 부분적으로만 완성된 미완성 설계도라고 한다면 인터페이스는 밑그림만 그려져 있는 기본 설계도라고 할 수 있다.
inerface MyInterface {
public static final int number = 0;
public abstract method();
}
이런 식으로 인터페이스의 모든 멤버변수는 public static final이고, 모든 메서드는 public abstract이다.
이렇게 전체적인 틀을 짜준 후, 실제 구현 클래스에서 메서드 내용 부분을 채워넣어 구현(implements)을 해주는 것이다.
일단 인터페이스와 구현 클래스를 나누어서 작업하면, 인터페이스만 먼저 작성해놓으면 이 틀을 사용해서 프로그램을 작성할 수 있다. 또한, 한 쪽에서 구현 클래스를 작성하면서 동시에 다른 개발을 진행할 수 있다.
아까부터 틀이라는 단어를 계속 사용하고 있는데, 이렇게 인터페이스로 틀을 잡아 놓고 개발을 하게 되면 여러 명의 개발자가 작업을 할 때도 일관된 틀안 에서 그 안의 내용을 구현하면서 개발이 진행되므로 정형화된 작업이 가능하다.
서로 상속(extends)관계도 아니고 조상 클래스도 갖고 있지 않은 아무런 관계도 없는 클래스들이 하나의 인터페이스를 공통적으로 구현하게 하면 관계를 맺어줄 수 있다.
클래스의 선언(interface > Service)과 구현(class > ServiceImpl)을 분리시킴으로써 독립적인 프로그래밍이 가능하다. 만약 모든 클래스들을 직접 관계로 한다면, 한 클래스를 변경할 때마다 직접 관계로 맺어진 클래스를 모두 수정해야 할 것이다. 하지만 선언과 구현을 나누면서 간접적인 관계로 변경하면, 하나의 클래스를 변경하더라도 다른 클래스에 영향을 미치지 않게 된다.
기존에 public abstract 추상 메서드만 가질 수 있었던 것에서 확장되어, 디폴트 메서드(default)를 추가할 수 있게 되었다.
항상 이 점이 의문이였는데, 자바의 정석을 다시 읽어보니 너무나 떡하니 이유가 나와있었다. 아까 인터페이스는 틀을 잡아주는 것이라고 했는데, 이상적으로는 이 틀이 처음부터 설계가 완벽하게 되어서 인터페이스를 수정하지 않고 구현 클래스만 수정하면서 프로그램을 작성하는 것이 좋겠지만, 현실적으로 언젠가 그 틀을 변경해야 할 일이 있는 경우가 많을 것이다.
이 경우에, 인터페이스에 추상 메서드를 추가하게 되면 아주 큰 일이 나게 된다. 이 인터페이스를 구현한 모든 클래스에서 추가된 메서드의 내용을 구현해줘야 하기 때문이다.
이럴 경우를 대비해서 추가된 것이 바로 디폴트 메서드이다.
(접근 제어자는 다른 것들과 마찬가지로 public)
디폴트 메서드는 추상 메서드가 아니기 때문에 추가되어도 인터페이스를 구현한 클래스를 변경하지 않아도 된다. 다만, 디폴트 메서드의 이름과 기존 메서드의 이름이 중복되는 경우에는 다음과 같은 규칙으로 해결할 수 있다.
사실 static 메서드는 인스턴스와 관련이 없는 독립적인 메서드이기 때문에 인터페이스에 추가하지 못할 이유가 없었다. (즉, static 메서드는 특정 객체에 속하는 것이 아니기 때문에)
인터페이스는 추상 메서드만 가져야 한다는 규칙 때문에 대표적으로 Collection 인터페이스의 관련된 static 메서드들이 Collections라는 클래스에 들어가게 되었다.
어쨋든, 1.8 이후부터는 public static 메서드를 선언할 수 있게 되었다.