Project Lambdaではインタフェースの仕様も変更されている。
変更点は2つあり、一方がデフォルトメソッド、もう一方がstaticメソッド。
デフォルトメソッドは、インタフェースにデフォルトの実装を書くためのもの。
IterableインタフェースのforEachメソッドもデフォルトメソッドで実装されている。
デフォルメソッドを記述できるようになると、抽象クラスが必要なくなるような感じを受ける。しかし、デフォルトメソッドは振る舞いを定義できるが、状態を扱うことはできない。
したがって、インスタンス変数が必要な場合は抽象クラスを使う必要がある。
デフォルトメソッドの構文は以下のようになる。
interface インタフェース名 {
default 戻り値の型 メソッド名(引数) {
// 処理
}
}
インタフェースの実装クラスはデフォルトメソッドをそのまま使用することもできるし、オーバーライドして独自の実装にすることもできる。
IterableインタフェースのforEachメソッドはつぎの用にデフォルト実装されている。
forEachメソッドでは拡張for文を使用して、Consumerオブジェクトのacceptメソッドをコールしている。
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
デフォルトメソッドの例
interface Foo {
default void print() {
System.out.println(FOO);
}
}
public void test() {
Foo foo = new Foo() { };
foo.print();
}
デフォルトメソッドを再び抽象メソッド化するには、サブインタフェースで抽象メソッドとしてオーバライドする。
次の例はFoo2インタフェースではprintメソッドを抽象クラスとして、再定義している。
このため、Foo2の実装クラスを定義する場合、青字で示したようにprintメソッドを実装する必要がある。
interface Foo {
default void print() {
System.out.println(FOO);
}
}
interface Foo2 extends Foo {
@Override
void print();
}
public void test() {
Foo2 foo = new Foo2() {
@Override
public void print() {
System.out.println(FOO2);
}
};
foo.print();
}