ソフトコミュ開発ブログ

SoftCommu は Javaアプリ、Androidアプリの開発を行うディベロッパーです。人材教育もやっています。企業の新人研修の講師からスカイプでのオンライン家庭教師まで!技術書の執筆や翻訳もしています。
2016.12.27 Tuesday
ズバリ、ラムダ式 (Lambda)とは何か? それを使うと何がうれしいのか?

Java8で導入されたラムダ式 (Lambda)ですが、ネット上を見ると下記のような論議が良く出てきます。

 

Java の ラムダ式 (Lambda)と他の言語のクロージャー(Closure) はどう違うのか?
Java の ラムダ式 (Lambda)と他の言語のクロージャー(Closure) は違う!なぜなら・・・うんぬんうんぬん。

 

上記のような論議はコンピューターサイエンス的な議題としては興味深いものです。


ただ、内容を見ていると、いろんな理論というか理屈が出てくるのですが、どの記事を読んでもいまいちしっくりきません。


この点は、私自身もいろいろ考えていたのですが、いざ他人に説明するとなると答えに窮してしまいます。
このあたりの理屈に関しては、プログラマによっても意見が分かれるようです。

 

それで、とりあえず上記のような理屈はおいておいて
実際に Java でプログラムをする際に皆が気にしているあろう実務的な点だけを説明するようにしています。

 

#なので、この記事には、上記のクロージャーに関する質問の答えは記載されていません。
#それを求めてここにたどり着いた方ごめんなさい!

 

この記事では、下記の二つの質問だけ取り上げます。

 

Q1. ズバリ、ラムダ式 (Lambda)とは何か?
Q2. ラムダ式 (Lambda)を使うと何がうれしいのか?

 

上記の二点を説明するのに、言葉で説明するとややこしいので、サンプルコードを示します。

まず、 ラムダ式 (Lambda)を使わないコードの例です。

 

 

getMesssenger() というメソッドに注目してください。

無名クラスをインスタンス化しているだけです。
その際には、呼び出し側から「こんにちは!」という文字列を引き渡して初期化しています。
その後、get()メソッドが時間差を置いて3回ほど実行されますが、
その時に返す値は、getMesssenger() メソッドに引き渡された「こんにちは!」という文字列と
get()メソッドが実行された時点の時刻(ミリセコンド秒)を合成した文字列です。

上記のコードの実行結果は下記のとおりです。

 

こんにちは! 現在の時刻は 250です
こんにちは! 現在の時刻は 351です
こんにちは! 現在の時刻は 465です

 

ちなみに、ここで出てくる Supplier は、java.util.function.Supplier というパッケージに定義されている

Java の標準APIで、get()というメソッドが一つ定義されただけのインターフェースです。

 

public interface Supplier<T>

{

    T get();
}

 

Supplier に似たものとして、Runnable というインターフェースがあります。

そちらは、run() というメソッドを一つだけ持っています。

Supplier は、Runnable の「値を返すバージョン」みたいな位置づけのインターフェースとなります。

Supplier も Runnable も別にラムダ式(Lambda)とは直接関係ないのですが、

メソッドが一つだけ定義されていることから、ラムダ式(Lambda)の説明に良く使われるようです。

というもの、この後説明しますが、メソッドが一つだけの無名クラスを作成する際に威力を発揮するのがラムダ式(Lambda)だからです。

 

さて、上記の Test1.java 内のコードをラムダ式 (Lambda)を使って書くとどうなるのでしょうか?
下記がそのサンプルコードです。

 

 

Test1.java と Test2.java は全く同じことをしています。

main()メソッドの中の実装は完全に一緒です。

違うのは、getMesssenger()メソッド内で無名クラスを生成する際のコードの書き方だけです。
ラムダ式 (Lambda)を使う場合・・・

 

Supplier messenger = new Supplier()

 

・・・とクラス名(インターフェース名)を二回書かなくてよい。

 

そして、無名クラス内の get()メソッドの定義では・・・

 

public String get()

 

・・・とメソッド名を書かなくてよい。

 

その代わり・・・

 

Supplier<String> messenger = () ->

 

・・・と書くだけで良い。

 

これだけです。

つまり、ちょっとタイプ量が減るということですね。

 

ラムダ式を使えば、無名クラスをインスタンス化する際に、new Supplier() と書かずに済みます。

その代わり () -> と書きます。


さらに、Supplier が持っているメソッドは1つだけなので、わざわざプログラマがメソッド名をタイプしなくても、
Javaコンパイラは、プログラマが何をやりたいのかわかるよ!
なので、めんどくさいメソッド名のタイプを省略してもいいよ!ということになります。

 

あれえ、なんか、ラムダ式 (Lambda)に関して、いろんなところで論議されている割には、大したことない感じですね。
「えっ、それだけ?」みたいな。

なんで、人々は ラムダ式 (Lambda)に関して、そんなに熱く語っているのだろう・・・

実は私が一番わからないのはそこなのです・・・

単にこの記述方法がわかりにくいから、あれこれ言わざるを得なくなる・・・そんなところでしょうか?

 

さて、上記の二種類のコードを左右に並べてみましたので、下記の26行目以降を比べてみてください。

 

左:ラムダ式なし 

右:ラムダ式あり

 

 

というわけで、まとめると前述した質問二つに対する答えは下記のとおりです。

 

Q1. ズバリ「ラムダ式」とは何か?
A1. メソッドが一つしかない無名クラスを書くときのちょっと便利な記述方法です。

 

Q2. 「ラムダ式」を使うと何がうれしいのか?
A2. 文字をタイプする量がちょっと減るのでうれしいです。

 

Java8から導入されたラムダ式 (Lambda)が何か?を理解するカギとなるのは、

別にこれによって何か新しいことができるようになったわけではなく

今までも普通にできていたことをちょっとだけタイプ量を少なくして書けるようになっただけという点を知ることかと思います。

この点を知っておくだけで、今まで何か得体のしれないものだったラムダ式 (Lambda)が、ちょっと身近なものになりますよね!

 

私個人としては、ラムダ式 (Lambda)の書き方に慣れていないこともあって、
ラムダ式 (Lambda)を使うとちょっとソースコードが読みにくくなってしまうように感じています。

 

だって、() -> という表記ってパッと見、良くわからないですよね!

それよりは、多少タイプ量が増えたとしても new Supplier() と書いてあった方が何をやっているかはっきりわかるように思えます。

 

また、上記右側のコードでは、main()メソッド内で、get()メソッドを呼び出していますが、無名クラスの定義の中には get() という文字は全く出てきません。なので、このコードを読む第三者は、一瞬「あれっ、あれっ、この get() って何?どこから来たの?」みたいなことになると思うんですよ。

 

Supplierインターフェースに get() というメソッドがあるという知識がないと理解できないコードになってしまうんですね。「それくらい知っているよ!」という人には何も問題ないかもしれませんが、やはり人のコードを読む際には、前提となる知識はなるべく少なくても済む方が良いかと思います。

 

というわけで、タイプ量を減らすメリットと、コードが読みにくく感じるという(個人的な)デメリットをはかりにかけ、私自身はラムダ式 (Lambda)を使ってコードを書くことはほとんどありません!

 

 

ソフトコミュでは、スカイプによる Java や Androidプログラムの

オンライン家庭教師を受け付けています。

料金は30分2,000円から。

ネット検索しながら何日も悩んだ問題が、たった30分で解決すると大好評です!

興味のある方はソフトコミュのホームページからご連絡ください!

 

 

 

 

 

 

| SoftCommu | Java | 12:24 | comments(0) | - |
  12345
6789101112
13141516171819
20212223242526
2728293031  
<< August 2017 >>
+ 人気の記事
+ ARCHIVES
+ CATEGORIES
+ MOBILE
qrcode
(C) 2016 SoftCommu All Rights Reserved.