Optional.of()の使い所
本記事は
はじめてのアドベントカレンダー Advent Calendar 2023
参加記事です。
こんにちは。株式会社クラス システム開発本部の青木です。
初めてのテックブログということで何を書こうか迷っていたのですが、
先日、開発を行っている中で表題の通りOptional.of()の使い所に疑問を持ちましたので、その話をしようと思います。
クラスに入社する前の現場ではOptionalをほぼ使っていなかったというのもあって、Optionalについての私の認識はNullを扱いやすくするもの程度でした。
なので、Nullを入れることができないOptional .of()はどういう時に使うんだろう?と疑問を持ち、調べてみました。
Optional.of()を使うことで以下のようなメリットがあるようです。
Nullを許容しないということを明示できる
以下のような場合ソースコードを読むだけでstrという変数のNullを許容していないということがわかります。
仮にstrという変数には必ず値が入るようになっていたとしても、処理を修正や追加などを行った際に誤ってNullが入るようになった場合でもNPEが発生するので処理の誤りに気がつくことができます。
Optional<String> strOptional = Optional.of(str);
また、Objects#requireNonNullも同じようにNullを許容しないという場合に使用できますが、Optionalであれば、次のメリットであるmapなどを使用することができます。
mapやfilterなどのオペレーターを使うことができる
例えば、以下のようなソースコードがあるとします。
public int getXXX(String str) {
if (!str.chars().allMatch(Character::isDigit)) {
return 0;
}
int value = Integer.valueOf(str);
if (value > 0) {
return i * 2;
} else {
return 0;
}
}
if文によって多少ソースコードの見通しが悪くなっているかと思います。
これをOptionalのオペレーターとラムダを使うことによって以下のように記載できます。
public int getXXX(String str) {
return Optional.of(str)
.filter(s -> s.chars().allMatch(Character::isDigit))
.map(Integer::parseInt)
.filter(i -> i > 0)
.map(i -> i * 2)
.orElse(0);
}
コードがスッキリして見通しが良くなりました。
同じような動作をするコードでもここまでスマートに書けると驚きですね。
また、以下のような場合も便利です。
public String methodA(String str) {
//何かしら処理
return 何かしらの値
}
public String methodB(String str) {
//何かしら処理
return 何かしらの値
}
public String methodC(String str) {
//何かしら処理
return 何かしらの値
}
上記のようなメソッドがあった場合にmethodAから順番に処理を適用していきたいという場合、オペレーターを使わずに書こうとすると以下のようになるかと思います。
this.methodC(this.methodB(this.methodA(target)));
methodAから順番に適用するように記載すると上記のように入れ子になり処理の流れを直感で理解しにくいかと思います。
これをオペレーターを利用して書くと
Optional.of(str).map(this::methodA).map(this::methodB).map(this::methodC)
このようにできます。
methodAから順番に適用されていることが視覚的にもわかりやすくなったかと思います。
私自身、Optionalやラムダなどを用いてコードを書いた経験が浅いということもあって慣れていない部分もありますが、便利な書き方なので使いこなせるようになっていきたいですね。
12/13には株式会社クラスと株式会社アイスタイルの有志による合同勉強会を開催します。興味があれば、覗きに来てみてください。
https://clas-istyle.connpass.com/event/303453/