オプション


public class Classes {

    private Integer id;
    private String title;
    private boolean closed;
    
    private Progress progress;

}

public class Progress {

    private Duration studyDuration;
    private boolean finished;
    
    public Progress() {};

    public Progress(boolean finished) {
        this.finished = finished;
    }

}

public class OptionalApp {

    public static void main(String[] args) {
        List<Classes> springClasses = new ArrayList<>();
        springClasses.add(new Classes(1, "spring boot", true));
        springClasses.add(new Classes(2, "spring jpa", true));
        springClasses.add(new Classes(3, "spring mvc", true));
    }
 	   
}
例として、ClassクラスにProgressという参照タイプフィールドを追加します.
ドライバアプリケーションでは、CLASESを作成するジェネレータにProgressインスタンスはありません.
System.out.println(springClasses.get(0).getProgress().getStudyDuration());
この場合、上記のコードが実行されるとnullになります.
NPE(null point exception)が表示されます.
if (springClasses.get(0).getProgress() != null) {
    System.out.println(springClasses.get(0).getProgress().getStudyDuration());
}
Java 8の前に、上記のコード(if(a!=null)を使用してNPEを防止します.
これは面倒で、どんな状況でNPEが発生するか分かりません.
NULLのチェックが漏れたり、不要になったりした場合があります.
これらの問題を解決するためにJava 8から出現したのがOptionalである.

OptionalはWrappingクラスで、必要な値を囲むことができ、少なくともnullを防止することができます.
// return 타입에만 Optional을 쓰는 것이 권장됨!
public Optional<Progress> getProgress() {
    // null일 수 있는 경우
    return Optional.ofNullable(progress);
}
上記の場合、Optionを使用してreturn typeをOptionalに置き換えます.
Optionalラップで返す値がofNullable()の場合
getProgress()は、Progressではなくオプションを返します.
Progressがnullであっても、空のオプションが返されるため、NPEは生成されません.
Optional<Progress> optionalProgress = springClasses.get(0).getProgress();
// Progress progress = springClasses.get(0).getProgress(); 컴파일 에러 발생
getterはOptionをreturnタイプとして宣言します.
Progress受信を使用しようとすると、コンパイルエラーが発生し、オブジェクトが空になる可能性があります.
// 인자는 Supplier 형태
boolean isClassFinished = optionalProgress.orElseGet(OptionalApp::createProgress).isFinished();

private static Progress createProgress(){
    return new Progress(false);
}
もちろん、これらだけでは不十分であることを知り、受信したオプションオブジェクトを利用する必要があります.
最も重要なAPIはorElseGet()であり、nullでない場合はインポートされます.
またはnullは、実行に必要な操作を決定することができる.
(類似のAPIにはorelse(value)がありますが、createProgress()がnullであるかどうかにかかわらず無条件に実行されるため、問題が発生する可能性があります.コストが高い>可能であればorelseGet()を使用することをお勧めします.
注意:https://mangkyu.tistory.com/70
if(optionalProgress.isPresent()) { 
    System.out.println("optionalProgress is not null");
}

optionalProgress.ifPresent(p -> System.out.println(p.isFinished()));
isPresent()は名前の通りnullではなくflag値で使いやすいオプションです.
Java 11から、isEmpty()も追加!optionalProgress.isPresent()で表現することもできます.
ifPresent()がnullでない場合は、その要素を使用して操作を返すことはできません.
これは私たちが主に知っている内容です.
次は、追加の機能やオプションを使用するべきではない場合です.
optionalProgress.orElseThrow(IllegalStateException::new);
orElseThrow()は本当に仕方なくnullなら例外を投げ出しますが、いつ使うべきか分かりません.
if(progress.isPresent()) {
    System.out.println(progress.get().isFinished());
}
get()はOptionから取り出した要素であり、nullの場合はNPEではなくNoSuchElementExceptionが発生するため、nullであることを事前に確認して書き込む必要がある.
Optional<Classes> optionalClass = springClasses.stream()
                                  .filter(c -> c.getTitle().startsWith("spring")).findFirst();
filter()またはmap()は、オプションと組み合わせて使用することもできます.
以上の場合、springで始まるカリキュラム名がない場合がありますので、オプションが必要です.
Optional<Classes> filterClass = optionalClass.filter(c -> c.isClosed());

Optional<Integer> integerClass = optionalClass.map(Classes::getId);
上のように簡単に使えます.
フィルタ()-フィルタがない場合は、空のオプションを返します.
map()-非オプションタイプがポップアップされた場合:
Optional<Optional<Progress>> progress = optionalClass.map(Classes::getProgress);
Optional<Progress> progress1 = progress.orElseThrow(IllegalStateException::new);
Progress progress2 = progress1.orElseThrow(IllegalStateException::new);

Optional<Progress> flatMapProgress = optionalClass.flatMap(Classes::getProgress);
Progress自体がOptionalである場合は、Optionalを2つの部分に分ける必要があります.
flatMap()を使って一度に取り出すことができます.
Optional.of(10);
OptionalInt.of(10);
Primitive TypeをOptionで包むと、ボクシングで使うリソースを節約できる方法があります.
  • のみで値を返すことを推奨します.
    (メソッドパラメータタイプ、マッピングのキータイプ、インスタンスフィールドタイプとして使用しないでください.)
  • オプションを返すメソッドでnullを返さないでください.
  • Collection、Map、Stream、Array、OptionはOptionalで包まないでください.
    関連項目:第8回Javaの注釈
  • 前述したように、オプションは限られたニーズにのみ使用することを推奨します.
    理由ごとに覚えにくいのであれば、Optionalは戻り値だけを覚えておきましょう.
    https://mangkyu.tistory.com/203
    上記の記事では、オプションは最初から限られた目的で作成されており、よくわかりません.
    乱発選択はかえって資源の浪費、誤りの発生、毒性の低下などの副作用をもたらす.

    いわゆるModern Java(ランダ式、Streamなど)を学び、適切に使えば便利です.
    下手に書くより書かないほうがいいのではないかと心配する人もいる.
    Optionalの場合ももっと正確に、慎重に応用してください!