こんにちは!ISAMU(@burlesca_isa)です!
今回の対象読者は
- Javaのラムダ式について知りたい方
この記事を読むと
ラムダ式を勉強するための準備
ラムダ式の書き方
が分かります。
javaのラムダ式とは?
ラムダ式とはインターフェースを実装するインスタンスを返す式のことです。
匿名クラスとラムダ式は同意です。
JavaのSE7までは匿名クラスを利用していましたが、
SE8からラムダ式が利用できるようになりました。
前途の通り、匿名クラスとラムダ式は構文は違えど機能は同じです。
匿名クラスは可読性が良くなく冗長になってしまうので、
SE8以降はラムダ式を使用することをおすすめします。
ラムダ式を使用するメリット
メソッドが一つしかないインターフェースを実装する場合など、
クラスファイルを大量に作成すると管理が大変になります。
わざわざクラスファイルを作成する必要がないような
プログラムを使用したい場合にラムダ式や匿名クラスを使用します。
ラムダ式を勉強するための準備
ラムダ式を書くために必要な知識として、
- 匿名クラス
- 総称型
- 関数型インターフェース
があります。
前途の通り、匿名クラスとラムダ式は構文が違うだけで同意です。
今でも匿名クラスを使用しているエンジニアもいるため、覚えておく必要があります。
また、匿名クラス→ラムダ式の順で学んだほうが理解しやすいと思います。
総称型はインターフェースでの型の指定で便利な機能のため多用されます。
関数型インターフェースは最初から用意されているインターフェースのため、
宣言する必要がなく、すぐに使用することができるため便利です。
匿名クラス
匿名クラスとはインターフェースを実装したクラスの宣言とインスタンスを作成を一つの式で記述することができます。
匿名クラスの構文
クラス名 変数名 = new インターフェース名(){
抽象メソッド(){}
}
匿名クラスの場合、newの後にインターフェース名を記述することで
このインターフェースを実装するクラスを作成するという意味になります。
サンプルプログラム
総称型
interface インターフェース名<パラメータ>{
パラメータ name; // 例
}
インターフェースの型パラメータとして多用されます。
クラス宣言やインターフェース宣言で「<パラメータ>」を指定します。
宣言時に<パラメータ>内には任意の英字を指定します。
インスタンス生成時にデータ型を<>内に記述することで、
メンバ変数やメソッドの引数、戻り値を英数字から指定のデータ型に置き換えることができます。
指定する英字(よく使用するもの)
- T 型
- R 戻り値
- S U V 2つ目以降の型として使用
サンプルプログラム
関数型インターフェース
関数型インターフェースは
コレクションAPIで提供されているインターフェースです。
準備されているインターフェースなので、
宣言しなくても利用することができます。
関数型インターフェース一覧
インターフェース : Function<T,R> メソッド: R apply(T 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メソッドをオーバーライドしています。
このメソッドは引数と戻り値のデータ型を指定する必要があるため、6行目で
Function<String, String>としています。
これはString型の引数を渡して、String型の戻り値を受けとることを意味します。
再度Functionインターフェースの構文を確認してみましょう。
インターフェース : Function<T,R> メソッド: R apply(T t)
applyメソッドをオーバーライドする時も、戻り値と引数の型にTとRをStringを指定する必要があります。
ラムダ式
クラスを一度だけ定義したい場合に利用します。
構文
(実装するメソッドの引数)→{処理};
先程記述した関数型インターフェースをラムダ式で実装してみます。
サンプルプログラム
Function
return "message : " + str;
};
と記述しています。
Functionインターフェースにはapplyという抽象メソッドが一つしか存在していないため、
明示的にメソッド名を記述する必要がありません。
なので、applyメソッド名は記述していませんが、
applyメソッドをオーバーライドしているということになります。
左辺にFunctionインターフェースで宣言した変数objを宣言しています。
右辺では(String str)でapplyメソッドの引数リスト、{}内に処理を記述しています。
右辺で生成されたインスタンスの参照が左辺のobj変数に格納されます。