はじめに
Javaの学習を始めて間も無いです。 私が学習を進めていく中で理解に苦労したのがラムダ式です。 そんなラムダ式を自分なりに理解できたので、自分のような初心者の方向けにメモを残します。 内容に間違いがある可能性がありますのでご了承ください。ラムダ式とは
無名クラスを表現する際に使われる記法のこと。 コード量を少なくできると言うメリットがある。ただ楽に書けるというだけで、使わなくても問題ない。
無名クラスとは
インナークラスを省略したもの。 無名クラスをを使うことで、インナークラスをわざわざ定義することなく実現できる。 コードを量を少なくできると言うメリットがある。ただ楽に書けるというだけで、使わなくても(インナークラスを使っても)問題ない。
インナークラスとは
クラスの中に定義されたクラス。 インナークラスは内部に定義されたメソッドなどの内容を外部に漏らさずに提供することを目的とし、情報隠蔽を実現する。ラムダ式の目的
上記をまとめるとラムダ式の目的は、定義されたメソッドを情報隠蔽を保持したまま使うことである。上記を踏まえて、ラムダ式を使うまで
①情報隠蔽を実現した簡単なプロジェクトを作る
------------------------
|パッケージA |
| Sampleインターフェース | //公開
| SampleImplementsクラス | //非公開
| SampleSupplyクラス | //公開
------------------------
------------------------
|パッケージB |
| Mainクラス |
------------------------
上記のようなプロジェクト構成があったとする。
public interface Sample{
public void hello();
}
↑ Sampleインターフェースはhello()という抽象メソッドを提供しているのみ。
class SampleImplements implements Sample{
@Override
public void hello(){
System.out.print("Hello");
}
}
↑ SampleImplementsクラスはSampleインターフェースを実現したクラス。
処理内容などは隠蔽したいのでパッケージ外には非公開にする。
public class SampleSupply{
public static Sample create(){
return new SampleImplements();
}
}
↑ SampleSupplyクラスは、SampleImplementsクラスのインスタンスをSample型として返すだけのクラス。
public class Main{
Sample sample = SampleSupply.create();
sample.hello();
}
↑ これでMainクラスは公開されているSampleインターフェースとSampleSupplyクラスの情報を知っているだけで、SampleImplementsクラスの機能を使うことができる。
また、SampleImplementsクラスに修正があった場合も、Mainクラス側の変更をする必要がなくなる。
しかし懸念点があり、SampleImplementsクラスが同じパッケージ内の別のクラスにアクセスされてしまう可能性がある。
そこでインナークラスを使用する。
②インナークラスを定義する
```SampleSupply.java public class SampleSupply{ public static Sample create{ //インナークラスのインスタンスを生成して返す return new SampleSupply.new SampleImplements(); }//privateのインナークラスを定義
private class SampleImplements implements Sample{
@Override
public void hello(){
System.out.print("Hello");
}
}
}
↑ これでSampleImplementsクラスがSampleSupplyクラス以外からアクセスされる心配がなくなった。
また、使用する側のMainクラスは変更する必要がない。
しかし、わざわざ一つのメソッドを実現するためにクラスを定義するのは面倒である。
ここで無名クラスを使用する。
<h2>③無名クラスを定義する</h2>
```SampleSupply.java
public class SampleSupply{
public static Sample create(){
return new Sample{
//クラスの定義
@Override
public void hello(){
System.out.print("Hello");
}
}
}
}
↑ これでインナークラスをさらに省略して記述できた。
しかし、それでもまだコードが長いので最後にラムダ式を使用する。
##④ラムダ式を使用する
public class SampleSupply{
public static Sample create(){
return () -> {System.out.print("Hello");};
}
}
↑ これで初めは一つのクラスだったSampleImplementsクラスを一行で記述することができた。
##なぜ無名クラスをラムダ式で省略できるのか?
それは、Sampleインターフェースが抽象メソッド一つのみを持つ関数型インターフェースだからである。
(関数型インターフェースはラムダ式を使って実装することを目的としたインターフェース)
上記のラムダ式の詳細は
(引数) -> { 処理の内容 }
//上記のhelloメソッドは引数なしのため空欄になる
Sampleインターフェースの抽象メソッドは一つしかないため自動的にメソッドが選択される(天才)
今回はSampleインターフェースはhelloメソッドしか持っていない為、ラムダ式ではhelloメソッドに対する引数と処理内容を記載すれば良い。
ここまで散々SampleSupplyクラスを修正してきましたが、使用する側のMainクラスは全く変更する必要がなく最初の状態のまま使えると言う点もポイントです。