JavaのOptional型について


Java SE 8から新たに追加されたOptionalを使うとnullになりうる型として明示できます。これによりNullPointerExceptionを防ぎ、安全にnullを扱うことができます。

🎳 Optionalの基礎

Optionalを使わない場合はif文でnullチェックを行っていました。

Article article = getArticle();
if (article != null) {
article.getTitle();
}

Optionalを利用することで、値が存在する場合だけ処理を行うことを明示的に記述できます。

Optional<Article> optionalArticle = Optional.ofNullable(getArticle());
optionalArticle.ifPresent(article -> article.getTitle());

🐰 Optionalの生成

Optionalコンストラクタの生成メソッドofofNullableの紹介です。

StringBuilder sb = null;
Optional<StringBuilder> osb = Optional.of(sb); // NullPointerException(例外)が発生
Optional<StringBuilder> osb2 = Optional.ofNullable(sb); // nullを受け入れる

これ以外に基本変数型のためにOptionalIntOptionalLongOptionalDoubleがあります。

OptionalInt optionalInt = OptionalInt.of(1);
OptionalLong optionalLong = OptionalLong.of(10L);
OptionalDouble optionalLong = OptionalDouble.of(10.0);

🚜 Optionalから

Optionalインスタンスを使うと、nullチェックを含めた値の取得を行うことができます。

StringBuilder sb = null; // or sb = new StringBuilder(hoge)
Optional<StringBuilder> osb = Optional.ofNullable(sb);
// opt == null なら NoSuchElementException
// opt != null なら StringBuilderのインスタンスを返す
StringBuilder sb1 = osb.get(new StringBuilder(none))
// osb == null なら new StringBuilder(none) を返す
// osb != null なら 単純な取り出し
StringBuilder sb2 = osb.orElse(new StringBuilder(none));
// osb == null なら何もしない
// osb != ならラムダ式を実行
osb.ifPresent(sb -> {
sb.insert(0, []);
sb.append(]);
});

🎃 Optionalを処理してOptionalを返すメソッド

### 条件に一致する場合のみ値をセット:filter

Optional<String> optArticle = Optional.ofNullable(getArticle());
Optional<String> filteredArticle = optArticle.filter(article -> article.getTitle().length() >= 2);

特定の処理をして結果をセット:map

Optional<String> str = Optional.of("article").map(String::toUpperCase);
System.out.println(str); //=> Article

🎉 Optionalによるnullチェックや置換え

多段でnullチェックをして値を取り出すのではなく、Optionalを使ってnullチェックを行うことでコードの可読性を向上できます。

// コンストラクタなどは省略しています
class Name {
private final Optional<String> first;
Optional<String> getFirst() {
return this.first;
}
}
class Person {
private final Optional<Name> name;
Optional<Name> getName() {
return this.name;
}
}
void showPersonFirstName(Optional<Person> person) {
person.flatMap(Person:getName) // getNameの結果をOptionalで返す
.flatMap(Name::getFirst) // getFirstの結果をOptionalで返す
.ifPresent(System.out::Println); // nullでなければprintln
}

😎 参照リンク

🖥 VULTRおすすめ

VULTR」はVPSサーバのサービスです。日本にリージョンがあり、最安は512MBで2.5ドル/月($0.004/時間)で借りることができます。4GBメモリでも月20ドルです。 最近はVULTRのヘビーユーザーになので、「ここ」から会員登録してもらえるとサービス開発が捗ります!

📚 おすすめの書籍