*

java8(JDK8)の新機能のラムダ式の利用方法をEclipseとJUnitで説明[その2:関数型インターフェースを例としたラムダ式]

公開日: : 最終更新日:2015/05/02 Eclipse, Java, JUnit ,


スポンサードリンク



「JDK8(Java 8)の新機能のラムダ式の利用方法[その1:概要]」では、
指定できる場所の概説と関数型インターフェースの初期化or代入の概要を記載させていただきました。

本エントリーでは「関数型インターフェースの初期化」と題して「関数型インターフェースの初期化」の詳細な説明をさせていただきます。
といっても、「メソッドの引数」に指定するラムダ式も考え方は同じです。ぱっと見が違うだけなのですが・・・

あと、これは完全な私の好みなのですが、TDD(Test Driven Development)的に進めていきます。
利用するIDEはEclipseでJUnit4です。
環境作成に関しましては、「JDT betaを利用してJDK8対応のEclipse開発環境を作成する[Mac編]」をご覧ください。

本エントリーの内容は、以下のようになります。

  1. ラムダ式(Lambda Expressions)の記述方法
  2. SAM(Single-Abstract-Method) Typeとラムダ式

 

と思ったのですが、行数が多くなりそうですので、「SAM(Single-Abstract-Method) Typeとラムダ式」は「その3」以降といたします。

ラムダ式(Lambda Expressions)の記述方法

前回説明させていただいたラムダ式は、引数無し、戻り値も無しの物でしたので
以下のような疑問がわいていたと思います。

  • ラムダ式の中身を複数行にしたい時は?
  • インターフェースの単一メソッドに引数がある時は?
  • インターフェースの単一メソッドが戻り値を持つ時は?

まずはこの疑問に対する説明をさせていただきますが、
それに先駆けてユニットテストが実行できるようにします。

ユニットテスト関連のファイルの作成

プロジェクト

プロジェクト名は何でもいいです。「JDT betaを利用してJDK8対応のEclipse開発環境を作成する[Mac編]」で作成した物をそのまま利用してもOKです。

関数型インターフェース

関数型インターフェースが1つ必要ですので、インターフェースをIFuncSampleとの名前で作成してください。
作成後に以下の内容に変更してください。このインターフェースはメソッド定義がhogeだけなので関数型インターフェースです。
なお、ユーザー定義の関数型インターフェースには@FunctionalInterfaceアノテーションを記述するのが暗黙の了解になっています。

どうでも良い話ですが、本当はILambdaSampleとの名前のインターフェースにしたかったのですが、
諸事情で断念しました。

テストクラス

JUnit4のテストケースを作成後、以下の内容に変更してください。

とりあえず、ユニットテストを実行するための環境ができましたので、実行してください。
以下のような結果になると思います。
スクリーンショット 2014-04-10 13.39.30

@FunctionalInterfaceアノテーション

ラムダ式の説明に移る前に「@FunctionalInterface」アノテーションの効果の説明をしたいと思います。

まずはIFuncSampleに@FunctionalInterfaceを付与します。
この時点では問題は発生しません。

次に、IFuncSampleインターフェースにhogehogeメソッドを追加します。

この時点でコンパイルエラーが発生します。
スクリーンショット 2014-04-10 18.25.20

エラーメッセージは以下のようになりました。
Invalid ‘@FunctionalInterface’ annotation; IFuncSample is not a functional interface IFuncSample.java

まあ、そのままですね、@FunctionalInterfaceを付与しておくことで、
関数型インターフェースにメソッドが追加されることをコンパイラが抑止します。
戻り値や、引数の変更は抑止できませんが、あ!@FunctionalInterfaceだ、何も考えずに変更するとまずいぞ!
と思わせる事ができるのでとても有効です。
こちらもプロジェクトが分かれていても、プロジェクトを直接参照している場合は。コンパイラがエラーを出力して
抑止されますが、jarに固めて、それを参照している場合だとコンパイラは気付けません。

ラムダ式の中身を複数行にしたい時は?

if文と同じ考え方です。
if文も1行だと{}で閉じないでいいですよね、逆に複数行になると{}で閉じないといけないです。
この考え方プラス、ラムダ式はそれ自体が式なので{};と最後にセミコロンが必要となります。

早速、IFuncSampleTestのtestHogeの中身を書き換えて、
ラムダ式の中身を複数行にしてみましょう!
testHogeメソッドを以下の様に変更しました。ポイントは5行目の}の後のセミコロンです。
ラムダ式がここで終了するのでifの{}とは異なりセミコロンが必要です。

テストも実行してみましょう。
スクリーンショット 2014-04-10 14.36.41

予想通り失敗しました。ちゃんと上記コードの4行目の処理もラムダ式として認識されていますね。
assertEqualsの期待値も変更してみます。

テストの実行結果は以下の様になりました。
スクリーンショット 2014-04-10 14.40.59

インターフェースの単一メソッドに引数がある時は?

インターフェースの単一メソッドに引数がある時は、当然ですがラムダ式でも引数を指定する必要があります。
ただそれだけですが、引数の指定時にのルールがいくつかあります。

関数型インターフェースのメソッドに引数を追加

IFuncSampleを以下の様に変更しました。

見たまんまですが、String型のnameとint型のageの引数を追加しました。
当然ですが、IFuncSampleTestのコンパイルが通らなくなりました。
スクリーンショット 2014-04-10 15.00.05

ラムダ式における引数指定

インターフェースのIFuncSampleにhogeメソッドの定義に変更が加わったので
ラムダ式も対応を行います。
ラムダ式でもインターフェースの任意のメソッド実装時と同様の指定方法で引数を指定できます。

引数を追加するだけの対応をしたラムダ式(引数の型を指定する例)

ラムダ式では、メソッド実装時のように引数の型を必ず指定しなくてもOKです。
インターフェースの単一メソッドと同じメソッド構文(シグネチャ)をラムダ式も取らざるおえず、
この例の場合は、第一引数はString、第二に日数はintと見なされます。

このメソッド構文と異なるラムダ式を敢えて記述した場合は構文エラーと見なされます。

引数の型を指定しても問題ないです。指定しているのが前述の例です。

引数の型を指定しない例

なお、仮引数名(この例だとname,age)に’_’単独の文字列は指定できません。
今後の拡張用に確保されているようです。

実際にhogeを呼び出している部分も修正したtestHogeメソッドは以下の様になります。

コンパイルエラーが無くなったのでテストを実行してみましたが、成功しました。
画像はスペースの無駄なので省略いたします。

せっかく引数が渡されているので使ってみましょう!
“Hello name(age)”になるように処理を変えます。

testHogeメソッドのassertEqualsの期待値を変更

テストを実行するともちろん失敗します。
ラムダ式の処理も変更

これでテストが成功しました。

インターフェースの単一メソッドが戻り値を持つ時は?

これも普通にインターフェースを実装する時と同じなのですが、
1点だけ異なる点があります。

まずは、IFuncSampleのhogeメソッドの戻り値をStringに変更してみます。
予想通りコンパイルエラーが発生します。
スクリーンショット 2014-04-10 17.37.09

一応、TDDって言葉出してますので、hogeの呼び出しの所の対応を行います。
単純にbufferに格納された文字列がリターンされることを想定した変更です。

ラムダ式の最後にbuffer.toString();をリターンする処理を追加します。

これでテスト通るはずです。
テスト実行は成功しました。久しぶりの画面イメージ
スクリーンショット 2014-04-10 17.51.30

最後に、普通にインターフェースを実装する時異なる点の説明です。
「ラムダ式の中身を複数行にしたい時は?」で説明させていただきましたが
単一行の場合は{}は省略可能ですし、記載してもよいです。

ラムダ式が単一行で{}でくくられてない時にみreturnが省略可能です。
その行の値がリターンされるとみなされます。
その行の値は当然ですが、インターフェースのメソッドの戻り値の型と同じである必要があります。

現状のテストメソッドtestHogeの中で記載しているラムダ式をreturnが
省略できるように書き換えてみると以下のようになります。

書き換え後のラムダ式

確かに単一行ですね・・・、むりくりですがw
appendの繰り返し&最後にtoString()で行の値がStringになるようにしています。
繰り返しになりますが、最後のtoString()が無いとコンパイルエラーとなります。

テストも通りますね。

「JDK8(Java 8)の新機能のラムダ式の利用方法[その2:関数型インターフェースを例としたラムダ式]」は以上です。

「JDK8(java 8)の新機能のラムダ式の利用方法[その3:java8が用意している関数型インターフェース]」に続く。


スポンサードリンク



関連記事

Selenium入門その5[ページオブジェクトパターン(Page Object Design Pattern)を利用して変更に強いテストを作成する方法]

Selenium入門その2 では「UIマップファイル」と言う仕組みが存在していることに言及させてい

記事を読む

Eclipseの使い方(Eclipse4.4のブックマーク機能とタスク機能)

今回は、Eclipseのブックマーク機能とタスク機能の説明をさせていただきます。 両機能とも効率的

記事を読む

Eclipseの使い方(Windows環境のEclipse4.3、Eclipse4.4)

Eclipse4.4.0よりJDK8を正式サポートするそうです。 Eclipseトップレベルプ

記事を読む

Spring5入門[簡単なWebアプリのユニットテストをJUnit5とJMockitで作成]

Spring5入門ではJUnit4とmockitを利用したSpringのController、Ser

記事を読む

Eclipseの「DBViewer」プラグインを利用して「Java DB」の環境を作成し、SQLを発行してみる

EclipseのJUnitプラグインとDBUnitを併用したDB(データベース)のアクセス処理のユニ

記事を読む

JDK8(Java8)のインストール方法[Windows]

本エントリーは、Windows7 64bitにJDK8(Java8)をインストールする説明を記載させ

記事を読む

Java超入門 with Eclipse[1:Eclipse環境の作成とEclipseの使い方の説明]

「JDT betaを利用してJDK8(java 8)対応のEclipse開発環境を作成する」では、最

記事を読む

Eclipse(4.3,4.4)のJava言語のリファクタリング機能の使い方[リファクタリングの説明と「名前変更」と「移動」]

本エントリーでは、Eclipse(4.3,4.4)の「リファクタリング」機能の使い方を説明させていた

記事を読む

Javaによる非同期処理入門その1[非同期処理の実装方法の概説]

Javaによる非同期処理に関するエントリーを前々から作成したいと思っていたのですが、ついに作成してみ

記事を読む

Eclipse(4.3,4.4)の使い方[各画面エリアの名称とパースペクティブのビューのカスタマイズ]

本エントリーでは、Eclipse(Eclipse4.3,4.4)の各画面エリアの名称の説明と、ビュー

記事を読む

Message

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

Spring5入門[簡単なWebアプリのユニットテストをJUnit5とJMockitで作成]

Spring5入門ではJUnit4とmockitを利用したSpring

Spring5入門[STS(Spring Tool Suite)で簡単なWebアプリの典型的なユニットテストの実現方法]

前回は「Spring入門」で、Spring MVCを利用した簡単なWe

Spring5入門[STS(Spring Tool Suite)の環境作成と簡単なWebアプリの作成]

Struts1ももう過去の遺物になり、SAStrutsもEOLとなりも

Selenium入門その6[Selenium3でWebDriver(Java/Junit4)の環境を作成しEdge,Chrome,Firefoxで確認してみる]

Selenium3も3.0.1がリリースされましたし、今後は本格的にS

Selenium利用時のトラブルシューティング方法[クリック編]

Seleniumは便利なテスト自動化ツールですし、今後は更なる利用者の

→もっと見る

Optimization WordPress Plugins & Solutions by W3 EDGE
PAGE TOP ↑