今更ながらJava8についてまとめてみた
今更ながらJava8についてまとめてみた:
Java11が公式リリースされて2か月くらいが経ちました。
JDKの有償化など色々な意味で変化していくJavaですが、
ここで基本に立ち返って、Java8についてまとめてみました。
主によく使用する機能について記載していきます。
因みに筆者は前の現場まではJava7しか経験がなく、
Java8歴は半年くらいです。
別名ではクロージャ(Closure)とも呼ばれているらしいです。(そう呼ぶ人間を見たことありませんが)
どんなものか実際の記述を見てみましょう。
実際に上記を走らせると、
…だからなんやねん、て感じですよね。
そもそもラムダ式が何なのかというと、
関数型インターフェースの実装を式として簡潔に記述できる機能です。
…また関数型インターフェースというよくわからない言葉が出てきました。
これを大まかに言いますと、抽象メソッドが1つしか実装されていないインターフェースのこと1と考えてください。
なのでもう少し細かくまとめますと、
抽象メソッドが1つしか実装されていないインターフェースの実装を簡潔に記述できる機能となります。
例えば以下のような関数型インターフェースを実装してみましょう。
普通にインターフェースを実装してみます。
挨拶したいだけなのに、わざわざnewして処理を実装しないといけないのが非常に億劫ですね。
ではラムダ式を使ってみます。
大分すっきりしたと思いませんか?
簡潔に書けることは実装者にとって優しいのはもちろんですが、冗長な記述が不要になるので読み手にとっても分かりやすいコードになり、
プロジェクト全体にも良い影響を与えられます。
こうやって記事で目にしたり書籍で読むより、実際にコードを書いてみるとより理解しやすいと思いますので、
まだ書いたことがない、現場でも見たことがない方はぜひ書いてみてください!!
今でもかなりお世話になっているOptional。個人的には一番便利さを感じています。
一体どんな機能かというと、そのオブジェクトがnullかもしれないことを示してくれる機能です。
実際の細かい機能(メソッド)については公式リファレンスに譲りますが、
今回紹介するコードを読むためには以下のメソッドだけ予習していただければと思います。
では例えばDB参照を行い、何も取得できなかった場合に独自例外を投げたいケースを見てみましょう。
まずはOptionalを使わなかった場合。
比較的シンプルな部類ですが、わざわざif文を書かなきゃいけないのが嫌ですね。
この例だとネストを気にしなくてもよいですが、
現場コードだとすでにネストが結構深かったりしてif分岐すら煩わしく感じる時があります。
それではOptionalを使いましょう。
…なんと一行で終わりました。ちょっと長くはなっちゃいましたが。。
それとちゃっかりラムダ式出てきます。便利だから出てきちゃう。仕方ない。
以下、簡単な解説です。
先ほど紹介したリファレンスをちょこっと除いた方なら分かるかと思いますが、
先述した通り、Optionalはnullかもしれないことを表現してくれます。
その方法はOptionalでラップする際、または中の値を取り出す際のメソッドで表現します。
それにより後からそのコードを見た人が「この項目はnullの可能性がないんだな」と理解できます。
不要なテストも書かずに済みます。
結局どんなに便利な機能が提供されても、使う人が理解していないと効果を発揮しません。(戒め)
名前がかっこいいですね。
Streamは配列やListの操作を簡潔に書ける機能です。
またまた細かい機能は公式リファレンスに譲らせていただきまして、
以下について予習していただければと思います。
DBから一括取得できた名前を順に出力する処理があったとしましょう。
拡張for文でやってみます。
冷静に考えなくても人の名前を出力する処理なんてあんまりないと思いますが。例なので。
またネスト深くなっちゃいますね。嫌いです。
Streamを使いましょ。
これまた1行で終わりました。それに短い。
簡単な説明です。
他にも
そちらも使ってみてください。
改めて書いてみると、新機能というよりは、既存機能の記述を簡単にできるものが多く追加され、
またそれを実際によく使っているんだなと思いました。
えらい人たちもシンプルが一番!と思っているようですし、
これらが読んだり書けたりするだけでよりエンジニアらしくなるんではないかと思います!
最後までお読みいただきありがとうございました!
ご指摘などコメントお待ちしております!!
はじめに
Java11が公式リリースされて2か月くらいが経ちました。JDKの有償化など色々な意味で変化していくJavaですが、
ここで基本に立ち返って、Java8についてまとめてみました。
主によく使用する機能について記載していきます。
因みに筆者は前の現場まではJava7しか経験がなく、
Java8歴は半年くらいです。
よく使用する追加された機能
- Lambda(ラムダ式)
- Optional
- Stream
Lambda(ラムダ式)
別名ではクロージャ(Closure)とも呼ばれているらしいです。(そう呼ぶ人間を見たことありませんが)どんなものか実際の記述を見てみましょう。
Sample.java
(x, y) -> {return x + y;} /* (実装するメソッドの引数) -> {処理} */
x + y
の結果がresult
に入ります。…だからなんやねん、て感じですよね。
そもそもラムダ式とは
そもそもラムダ式が何なのかというと、関数型インターフェースの実装を式として簡潔に記述できる機能です。
…また関数型インターフェースというよくわからない言葉が出てきました。
これを大まかに言いますと、抽象メソッドが1つしか実装されていないインターフェースのこと1と考えてください。
なのでもう少し細かくまとめますと、
抽象メソッドが1つしか実装されていないインターフェースの実装を簡潔に記述できる機能となります。
どんな時にラムダ式の旨味を感じるか
例えば以下のような関数型インターフェースを実装してみましょう。Sample.java
@FunctionalInterface public interface SampleInterface { void sayHi(); }
SampleImpl1.java
public class SampleImple1 { public void greeting() { SampleInterface sample = new SampleInterface() { // インターフェースを実装 void sayHi() { System.out.println("Hi!"); // 実装したい処理を記述 } } sample.sayHi(); // 処理実行 } }
ではラムダ式を使ってみます。
SampleImpl2.java
public class SampleImpl2 { public void greeting(String name) { SampleInterface sample = () -> System.out.println("Hi!"); // 実装と処理記述をまとめてできる sample.sayHi(): // 処理実行 } }
簡潔に書けることは実装者にとって優しいのはもちろんですが、冗長な記述が不要になるので読み手にとっても分かりやすいコードになり、
プロジェクト全体にも良い影響を与えられます。
こうやって記事で目にしたり書籍で読むより、実際にコードを書いてみるとより理解しやすいと思いますので、
まだ書いたことがない、現場でも見たことがない方はぜひ書いてみてください!!
Optional
今でもかなりお世話になっているOptional。個人的には一番便利さを感じています。一体どんな機能かというと、そのオブジェクトがnullかもしれないことを示してくれる機能です。
実際の細かい機能(メソッド)については公式リファレンスに譲りますが、
今回紹介するコードを読むためには以下のメソッドだけ予習していただければと思います。
- ofNullable()
- orElseThrow()
- empty()
実際の記述と旨味を感じるシーン
では例えばDB参照を行い、何も取得できなかった場合に独自例外を投げたいケースを見てみましょう。まずはOptionalを使わなかった場合。
OptionalService1.java
SampleEntity sampleEntity = sampleDao.selectById(String id); // DB参照を実行 if (isNull(sampleEntity)) { // エンティティがnullだったら throw new ApplicationException("errorCode", "DBから値が取得できませんでした"); // 例外を投げる }
この例だとネストを気にしなくてもよいですが、
現場コードだとすでにネストが結構深かったりしてif分岐すら煩わしく感じる時があります。
それではOptionalを使いましょう。
OptionalService2.java
Optional<SampleEntity> sampleEntity = Optional.ofNullable(sampleDao.selectById(String id)) .orElseThrow(() -> new ApplicationException("errorCode", "DBから値が取得できませんでした"));
それとちゃっかりラムダ式出てきます。便利だから出てきちゃう。仕方ない。
以下、簡単な解説です。
-
ofNullable()
を使用して、sampleDao.selectById()
の戻り値がnullならOptional.empty()
を、何か取得できていればOptional<SampleEntity>
のオブジェクトを返してくれます。 -
orElseThrow()
で取得結果がOptional.empty()
の時に例外をスローしてくれます。
sampleEntity
はOptional.empty()ではないことが確定しています。分かりやすい!先ほど紹介したリファレンスをちょこっと除いた方なら分かるかと思いますが、
map
やorElseGet
などなど、他にも便利な機能が提供されています。がしがし使っていきましょう!
注意点
先述した通り、Optionalはnullかもしれないことを表現してくれます。その方法はOptionalでラップする際、または中の値を取り出す際のメソッドで表現します。
- Optionalにラップするメソッド
- of…ラップするオブジェクトがnullの場合に例外をスローする
- ofNullable
- Optionalから値を取り出すメソッド
- get…取り出そうとしたOptionalがemptyだった場合に例外をスローする
- orElseGet
- orElseThrow
それにより後からそのコードを見た人が「この項目はnullの可能性がないんだな」と理解できます。
不要なテストも書かずに済みます。
結局どんなに便利な機能が提供されても、使う人が理解していないと効果を発揮しません。(戒め)
Stream
名前がかっこいいですね。Streamは配列やListの操作を簡潔に書ける機能です。
またまた細かい機能は公式リファレンスに譲らせていただきまして、
以下について予習していただければと思います。
- map()
- forEach()
実際の記述と旨味を感じるシーン
DBから一括取得できた名前を順に出力する処理があったとしましょう。拡張for文でやってみます。
ForSample.java
for (SampleEntity entity : entityList) { // Listの中身を一つずつ取得 System.out.println(entity.getName()); }
またネスト深くなっちゃいますね。嫌いです。
Streamを使いましょ。
StreamSample.java
entityList.stream.map(x -> x.getName()).forEach(System.out::println);
簡単な説明です。
-
map()
でListから取り出したEntityから名前を取得しストリームに返します。(中間操作)
-
forEach()
がストリームの各要素に対して`System.out::println'を実行します。(終端操作)
他にも
filter()
、sorted()
やdistinct()
など便利すぎるメソッドがありますので、そちらも使ってみてください。
最後に
改めて書いてみると、新機能というよりは、既存機能の記述を簡単にできるものが多く追加され、またそれを実際によく使っているんだなと思いました。
えらい人たちもシンプルが一番!と思っているようですし、
これらが読んだり書けたりするだけでよりエンジニアらしくなるんではないかと思います!
最後までお読みいただきありがとうございました!
ご指摘などコメントお待ちしております!!
コメント
コメントを投稿