本記事の目次( 前編はこちら )
本記事に掲載しているサンプルコードを一括ダウンロードできます(Sample1-9.zip)
デフォルトメソッドと関数型インタフェース
Java SE 7まで、インタフェースに宣言できるメソッドは抽象メソッドだけでしたが、Java SE 8から、デフォルトメソッドとstaticメソッドを記述できるようになりました。デフォルトメソッドとは、インタフェースの実装クラスで処理を実装されなかった場合に適用される(デフォルトの)処理を記述したメソッドです。この仕様変更を受け、コレクションAPIで提供されているインタフェースにも、デフォルトメソッドが追加されています。
ここでは、Java SE 8のSilver認定資格試験「Java SE 8 Programmer I」(試験番号:1Z0-808)の範囲に絞って、デフォルトメソッドとその使い方を解説します。
デフォルトメソッドを定義する構文は次のとおりです。
[修飾子] default 戻り値 メソッド名(引数リスト) {// 処理 }
(例)
default void foo() { System.out.println("foo()"); }
デフォルトメソッドに指定できる修飾子はpublicのみです。上記の例のように修飾子を指定していない場合には、強制的にpublic修飾子が付与されます。
デフォルトメソッドとstaticメソッドの詳細は、Gold SE 8試験(Java SE 8 Programmer II)で問われる内容であるため、以降の説明は、Silver SE 8試験(Java SE 8 Programmer I)の範囲に絞って解説します。
Java SE 8で導入されたデフォルトメソッドを2つ紹介しましょう。
| メソッド名 | default boolean removeIf(Predicate<? super E> filter) |
|---|---|
| 説明 | Collectionインタフェースで提供。指定された処理を満たすこのコレクションの要素をすべて削除する |
| メソッド名 | default void replaceAll(UnaryOperator<E> operator) |
|---|---|
| 説明 | Listインタフェースで提供。指定された処理を行い、現在のリストの要素を置きかえる |
まず、各メソッドの引数を見ると、PredicateやUnaryOperatorとなっています。これらもJava SE 8から導入されたAPIで、関数型インタフェースに分類されます。関数型インタフェースの特徴は「定義されている抽象メソッドが1つだけであること」です。なお、staticメソッドやデフォルトメソッドが含まれていても、抽象メソッドが1つだけであれば、関数型インタフェースとなります。
次表は、Java SE 8で導入された主な関数型インタフェースです。java.util.functionパッケージとして提供されています。
| インタフェース名 | 抽象メソッド | 概要 |
|---|---|---|
| Function<T,R> | R apply(T t) | 実装するメソッドは、引数としてTを受け取り、結果としてRを返す |
| Consumer<T> | void accept(T t) | 実装するメソッドは、引数としてTを受け取り、結果を返さない |
| Predicate<T> | boolean test(T t) | 実装するメソッドは、引数としてTを受け取り、boolean値を結果として返す |
| Supplier<T> | T get() | 実装するメソッドは、何も引数として受け取らず、結果としてTを返す |
| UnaryOperator<T> | T apply(T t) | 実装するメソッドは、引数としてTを受け取り、結果としてTを返すものになる。Functionを拡張したもの |
匿名クラスによる抽象メソッドの実装
ラムダ式の書き方の説明に入る前に、まず、独自クラスでFunctionインタフェースのapply()メソッドを使用しているコードを見てみましょう(Sample1.java)。
import java.util.function.Function;
class MyFunc implements Function<String, String> {
public String apply(String str) {
return "Hello " + str;
}
}
public class Sample1 {
public static void main(String[] args) {
MyFunc obj = new MyFunc();
String str = obj.apply("naoki");
System.out.println(str);
}
}
Hello naoki
Functionインタフェースの実装クラスとしてMyFuncを定義し、apply()メソッドを実装しています。引数に文字列を受け取り、「Hello」と結合させて戻り値として返しています。MyFuncクラスを使用しているのはSample1クラスです。
なお、Java言語には「匿名クラス」という、特定の場所のみで利用したい(再利用もしない)クラスを実装する方法があります。匿名クラスはSilver SE 8試験の範囲外ですが、Sample1.javaを匿名クラスで実装した場合を見てみましょう(Sample2.java)。実行結果はSample1.javaと同じであるため掲載を割愛します。
匿名クラスとは、クラス名を指定せずに、クラス定義とインスタンス化だけを1つの式として記述したクラスのことです。匿名クラスは、あるクラスのサブクラス、または、あるインタフェースを実装したクラスになります。new スーパークラスまたはnew インタフェースという記述の後に、オーバーライドする処理をブロックとして記述します。Sample2クラスの5行目では、=演算子の後に、new Function<String, String>(){……}として、{}ブロック内にapply()メソッドを実装しています。そして、9行目のapply("naoki")の呼び出しにより、6行目が実行されます。

本記事の目次
