質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

5回答

5565閲覧

java8でOptionalを使い何らかの値がnullの場合の処理の書き方。

koikuti

総合スコア50

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

1グッド

1クリップ

投稿2018/02/15 02:56

編集2018/02/15 04:07

前提・実現したいこと

java8を使用して、Optionalの値が存在する場合、Oprionalの値がnullの場合の処理を分岐させたい。

該当のソースコード

java

1List<String> filePaths = 「いくつかのファイルパス文字列」; 2Optional<String> targetFilePath = filePaths.stream().filter(path -> path.contain("hoge")).findFirst(); 3if(!tfFileOpt.isPresent()) { 4 // 処理対象のファイルが取得できなかった場合 5 // 例えば 6 // 1. ログ出力 7 // 2. DBのユーザステータスをエラーに更新。 8 // 3. throw new BusinessException(); // 上位層へ業務処理が失敗したことを通達 9} 10 11// 以下、対象ファイルが取得できた場合。 12// 例えば 13// 1. 対象ファイルの読み込み。 ここで、targetFilePath.get()を使う? 14// 2. 読み込んだファイルの中身を解析&業務処理。 15// 3. etc... ...

この処理がよろしくないっぽいことはわかるのですが、どうすればいいかわかりません。皆さんどうするものなのでしょうか?

よろしくないと思っている点。
・Optionalを取得して、わざわざisPresent()で値のあるなしを判定している。→ nullチェックやってるのと変わらないから、Optionlの思想(?)に反している。
※ ググるとOptional取得して、if(optional.isParent){ ... } は論外。と書かれていることが多かったので。
・正常業務で、値を使いたいときいちいちOptionlにget()をかけるのが微妙。かと言って、isPresent()で判定した後、正常処理の最初に、ローカル変数に入れるのも微妙。そもそも、Optionalを取得する流れの中で、getElse()とかで取得したり、nullの場合の処理も記述できないの?
・仮に、Optionalを取得する流れの中で値があるなら取得する、ない場合は処理を行うのができた場合、ない場合の処理はラムダ式(?)で書くことになるが、その中でログを出したりDB操作することに違和感がある。

yohhoy👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答5

0

おっしゃる通り、Java8の時点でのOptionalは少々使い勝手が悪いです。
それを受けてか、Java9でOptionalは少し改良されました。

・正常業務で、値を使いたいときいちいちOptionlにget()をかけるのが微妙。かと言って、isPresent()で判定した後、正常処理の最初に、ローカル変数に入れるのも微妙。そもそも、Optionalを取得する流れの中で、getElse()とかで取得したり、nullの場合の処理も記述できないの?

ifPresentOrElseというメソッドが追加され、ない場合の処理をRunnableで渡せます。

投稿2018/02/15 07:21

swordone

総合スコア20649

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

Optionalが後付けで登場したこともあって、そこまで使い勝手が良くないのは間違いありません(Kotlinでは、nullになりうる値のnullチェックを済ませれば、あとはnullなしの値として扱えるようになっています)。ただ、

nullチェックやってるのと変わらないから、Optionlの思想(?)に反している。

こちらについては、「nullチェックしなければ例外になる」という意味のクラスなので、そんなに間違ってはいないです。

投稿2018/02/15 03:03

maisumakun

総合スコア145123

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ifPresent()で何も問題ないと思いますが。

java

1String targetPath = filePaths.stream().filter(path -> path.contains("hoge")).findFirst().orElse(""); 2if(targetPath.isEmpty()) { 3 //null 4} else { 5 //not null 6}

これならnullチェックぽくないかな?

投稿2018/02/15 05:36

fuzzball

総合スコア16731

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

Optionalが一番気持ちよく使えるのは関数型プログラミングのモナド的な利用、例えば複数の関数間に無用な判定を介さずにそのまま状態を伝達出来て必要な箇所で「値がないかも知れないことを忘れようがないように表現できる」点なのだろうと自分は思っています。

Optionalによりスッキリ記述できる場面というのはよく用いられる次のような場合で、それはJavaであっても一応使えるようになっていると思います。

  • 値がない場合でもデフォルト値を仮定したい場合

orElseとかcall by name的にしたければorElseGetを使えばよいですね。

  • 値がないことが例外である場合

orElseThrowを用いればよいですね。call by name的に例外を書けるのでエラーでないケースのために無駄に例外インスタンスを生成するような気持ち悪さもありません。ここだけはJavaの検査例外とFunctionalInterfaceの相性の悪さが回避されており検査例外を指定すればorElseThrowは「その検査例外をハンドリングするかthrows句を書くかの選択を強制する働きを担い」RuntimeExceptionを選べば「そうしなくてよい」ように振舞ってくれますし。

  • 値がある場合だけそれに基づいた計算をして新たな値にする

mapやflatMapで比較的気持ちよくかけるのではないでしょうか。

質問者さんが挙げておられるうちの一部は上記で書けるものもありますね。しかし残りは「値があるかないかで制御を変える」ことなので、nullチェックしようがOptional#isPresentでやろうが記述上のスッキリ感に違いはでてこないと思います。mapなどを使えば「値がある場合のみ副作用を起こす」ような書き方はできますが、それは質問者さんがおっしゃるよう自分も「違和感」を持ちます。


ちなみに書き味(?)の点では確かにisPresentと書いたのにgetをかかなきゃいけないのは少々どんくさい感じはあります。その辺りはmaisumakunさんがおっしゃるとおり言語仕様を拡張することなくライブラリーで実現している関係上しかたないことだと思います。考えてみればこれ以外にも「こうなっていたらなぁ」と思える点はいくつかあると思います。例えば

java

1Base o = ...; 2if (o instanceof Derived) { 3 ((Derived)o).derivedMethod(); 4}

などは他の言語のように

java

1Base o = ...; 2if (o instanceof Derived) { 3 o.derivedMethod(); // oはDerivedのインスタンスであることが明らかなのでキャスト不要 4}

と書けたらなぁと思うことがありますよね。そう考えると(個人的には)Optional#getぐらいは許容範囲に思えてきます。(自分の場合、何事もほどほどで満足してしまうせいかも知れません。)

なんだか「もっと苦労している人もいるんだから自分も頑張ろう」みたいな精神論になってきて結論が何なのかがぼんやりしてしまいました。スミマセン・・・

投稿2018/02/15 04:45

KSwordOfHaste

総合スコア18392

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

koikuti

2018/02/16 03:44

解答ありがとうございます。 Optionalを使う際の例や、多言語での場合との比較など、例示が多く また、個人的な使用感やそれに対する割り切りかたなど、が入っているのがありがたかったので、ベストアンサーに選ばせて頂きました。 他の回答者様も、ご意見ありがとうございます。 ググって、トップに出てくる記事をいくつか読んだ所、 isPresentで値の有無を判定するのは論外。 isPresentは使わない!という記事が多くOptionalの使い方がよくわからなくなってしまっていました。 ``` if(optional.isPresent()){ // 正常処理 String target = optional.isPresent(); } else { // 業務エラー処理 } ``` のような形で進めていこうと思います。 みなさんありがとうございました。
guest

0

isPresent()使わず無理やり書いてみました

java

1public class Main { 2 public static void main(String[] args) throws Exception { 3 Optional<String> src = Optional.of("hoge"); 4 5 6 Runnable r = src.map(x -> 7 (Runnable)new Runnable(){ 8 public void run(){ 9 // 正常フロー 10 System.out.println("Some"); 11 System.out.println(x); 12 } 13 } 14 ).orElse((Runnable)new Runnable(){ 15 public void run(){ 16 // 異常フロー 17 System.out.println("None"); 18 } 19 }); 20 21 r.run(); 22 } 23} 24 25

投稿2018/02/15 03:59

ozwk

総合スコア13512

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問