関数型インタフェースは実装すべきメソッドが1つのインタフェースのこと。
たとえば、java.lang.Runnableインタフェースは実装すべきメソッドがrunメソッドだけなので、関数型インタフェースということになる。
その他に関数型インタフェースとして、次のようなインタフェースがあります。
・java.util.concurrent.Callable
・java.util.function.Consumer
・javafx.event.EventHandler
ところで、Comparatorインタフェースの定義は次のようになっています。
public interface Comparator<T> {
int compare(T o1, T o2);
boolean equals(Object obj);
}
java.util.Comparatorインタフェースは関数型インタフェースだろうか?
Comparatorインタフェースが定義しているメソッドは2つだが、Comparatorインタフェースは関数型インタフェースとなる。
これはequalsメソッドがObjectクラスで定義されているため、Comparatorインタフェースの実装クラスで実装する必要がないことによる。
Java SE 8ではインタフェースにデフォルトの実装を記述できるようになった。これをデフォルトメソッドと呼ぶ。このため、メソッドが単一ではない関数 型インタフェースが多く存在する。
また、次のjava.security.cert.CertPathBuilderResultインタフェースを考える。
public interface CertPathBuilderResult extends Cloneable {
CertPath getCertPath();
Object clone();
}
clone()はObjectクラスで定義されているので関数型インタフェースと考えがちだが、そうではない。
Objectのclone()はアクセス修飾子がprotectedであり、CertPathBuilderResultインタフェースのclone()はpublicである。したがって、2つのメソッドをオ ーバライドする必要があるので、関数型インタフェースではないということになる。
関数型インタフェースかどうかを示すために、@FunctionalInterfaceアノテーションが導入されている。@FunctionalInterfaceアノテーションを付加することは必須ではないが、つけておくと、インタフェースのコンパイル時に関数型インタフェースかどうかをチェックするようになる。