[再Java Java 8]4Optional
ソース
4 Optional
Mapインタフェースの重要な特徴=keyは空にできません.
でも選んだら鍵が空いてるかもしれないなんて話にならない
フィールドがあってもなくてもいいです はドメインクラス設計の問題 である.は、むしろ高/低レベルに区分するか、依頼 を使用することを推奨する.
Optional.empty(); バックショットで nullを返すと、クライアントコードで「オブジェクト.getProgress().ifPresent()」と一緒に使用すると、NPEが表示される場合があります.
コンテナの性質を表すインスタンスが空です.
そのため、オプションで包むと2回の形になります.→意味がない
Optional.of() Optional.ofNullable() Optional.empty() isPresent() isEmpty()Java 11提供開始
get():できるだけ使わないことをお勧めします.nullの場合、NoSuchElementExceptionが起動します.
ifPresent(Consumer):値がある場合は、値~を使用します.
orElse(T):値がある場合、入力がない場合は*Tをインスタンスタイプとして返します.
orElseGet(Supplier):値がある場合は~を入力してください.
orElseThrow():値がある場合はインポートし、ない場合はエラーを投げ出す
Optional filter(Predicate) Optional map(Function) Optional FlatMap(機能):オプションのインスタンスがOptionalの場合、 が使用されます.
4 Optional
Optional=は空でもよいし、任意の値のみを含むインスタンスのタイプでもよい.
→オプションオブジェクトを囲む構造.
4.1出現背景:参照型メンバー変数とNPE
/* OnlineClass.java */
...
public Progress progress;
public Progress getProgress() {
return progress;
}
public void setProgress(Progress progress) {
this.progress = progress;
}
...
/* OptionalTestApp.java */
// 이슈상황 → 참조형 멤버변수 사용시 초기화 되지 않아 null값을 참조 할수 있다.
OnlineClass spring_boot = new OnlineClass(1, "spring boot", true);
Duration studyDuration = spring_boot.getProgress().getStudyDuration();// NullPointExecption 발생
System.out.println(studyDuration);
4.1.1 Java 8以前のソリューション
// 방법1. 사전에 null을 체크 → 에러에 대한 스택트레이스를 뽑는것 또한 리소스 낭비이다.
public Progress getProgress() {
if (progress == null) {
throw new IllegalStateException();
}
return progress;
}
// 방법2. 클라이언트 코드에서 null을 확인 → 이는 클라이언트에서 노친다면 에러가 발생할 수 있다.
Progress progress = spring_boot.getProgress();
if (progress != null) {
System.out.println(progress.getStudyDuration());
}
4.2オプションの注意事項
[1]推奨オプションは、戻りタイプにのみ使用されます。
/* OnlineClass.java */
...
// getter의 리턴타입을 optional로변경 *Optional을 리턴타입에만 사용함을 권장!
public Optional<Progress> getProgress() {
return Optional.ofNullable(progress);
}
...
①ofNullable:nullが入ってきてもエラーX
②of:null進入時NullpointExection
[2]メソッドパラメータタイプ&マッピングとして使用されるキータイプ&インスタンスフィールドタイプX
1)メソッドパラメータタイプ
// setter에 사용시
public void setProgress(Optional<Progress> progress) {
progress.ifPresent(p -> this.progress = p);
}
// 이와 같이 사용한다면 결국, null.ifPresent(...) → NullPointExecption이 발생. Optional사용의 의미가 없다.
객체.setProgress(null);
2)マッピングされたキータイプ
/* OnlineClass.java */
...
public Progress progress;
public Progress getProgress() {
return progress;
}
public void setProgress(Progress progress) {
this.progress = progress;
}
...
/* OptionalTestApp.java */
// 이슈상황 → 참조형 멤버변수 사용시 초기화 되지 않아 null값을 참조 할수 있다.
OnlineClass spring_boot = new OnlineClass(1, "spring boot", true);
Duration studyDuration = spring_boot.getProgress().getStudyDuration();// NullPointExecption 발생
System.out.println(studyDuration);
// 방법1. 사전에 null을 체크 → 에러에 대한 스택트레이스를 뽑는것 또한 리소스 낭비이다.
public Progress getProgress() {
if (progress == null) {
throw new IllegalStateException();
}
return progress;
}
// 방법2. 클라이언트 코드에서 null을 확인 → 이는 클라이언트에서 노친다면 에러가 발생할 수 있다.
Progress progress = spring_boot.getProgress();
if (progress != null) {
System.out.println(progress.getStudyDuration());
}
/* OnlineClass.java */
...
// getter의 리턴타입을 optional로변경 *Optional을 리턴타입에만 사용함을 권장!
public Optional<Progress> getProgress() {
return Optional.ofNullable(progress);
}
...
// setter에 사용시
public void setProgress(Optional<Progress> progress) {
progress.ifPresent(p -> this.progress = p);
}
// 이와 같이 사용한다면 결국, null.ifPresent(...) → NullPointExecption이 발생. Optional사용의 의미가 없다.
객체.setProgress(null);
Mapインタフェースの重要な特徴=keyは空にできません.
でも選んだら鍵が空いてるかもしれないなんて話にならない
3)インスタンスフィールドタイプ
フィールド
[3]元のタイプのオプションを適切に使用することを推奨
Optional.of(10); // 내부에서 boxing, unboxing이 이루어진다. → 성능에 좋지 않다.
OptionalInt.of(10); // 각 primitive타입에 맞는 클래스를 제공하므로 이를 사용하는것 권장
[4]Optional Return方式においてnull Return X
public Optional<Progress> getProgress() {
return null;
}
[5]Collection、Map、Stream Array、OptionはOptionalで包まない
コンテナの性質を表すインスタンスが空です.
そのため、オプションで包むと2回の形になります.→意味がない
4.2 Optional API
1)オプションの作成
2)オプション値のチェック
3)オプション値の取得
get():できるだけ使わないことをお勧めします.nullの場合、NoSuchElementExceptionが起動します.
ifPresent(Consumer):値がある場合は、値~を使用します.
orElse(T):値がある場合、入力がない場合は*Tをインスタンスタイプとして返します.
orElseGet(Supplier):値がある場合は~を入力してください.
orElseThrow():値がある場合はインポートし、ない場合はエラーを投げ出す
4)オプションフィルタ/変換
例
package java8.optionaltest;
import java8.domain.OnlineClass;
import java8.domain.Progress;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
public class OptionalTestApp {
public static void main(String[] args) {
List<OnlineClass> springClasses = new ArrayList<>();
springClasses.add(new OnlineClass(1, "spring boot", true));
springClasses.add(new OnlineClass(2, "spring data optional", true));
// optional을 리턴하는 stream의 메서드는 종료형 operation이라 할수잇다.
Optional<OnlineClass> optional = springClasses.stream()
.filter(oc -> oc.getTitle()
.startsWith("optional"))
.findFirst();
boolean present = optional.isPresent();
boolean empty = optional.isEmpty(); // Java11 부터 제공
System.out.println(present); // false
System.out.println(empty); // true;
/**
* optional 내부값 가져오기
* */
// 1. get()
//OnlineClass onlineClass = optional.get(); // NoSuchElementException 발생
// 2. isPresent() + get() = 먼저 확인후 꺼낸다 -> 번거롭다
/*if (optional.isPresent()) {
OnlineClass onlineClass = optional.get();
System.out.println(onlineClass.getTitle());
}*/
// 3. ifPresent(Consumer) = 값이 있는 경우만 함수가 동작한다!
optional.ifPresent(oc -> System.out.println(oc.getTitle()));
// 4. orElse() = 값이 없는 경우 리턴할 객체를 넣어줌 (이는 기존 Optional이 감싸고 있던 인스턴스 타입이다.)
// BUT, 이경우 값이 있던 없던 createNewClass()가 실행은 됨. (리턴은 있는경우 그게 리턴되나 createNewClass 함수는 실행이됨)
// 이미 만들어진 인스턴스를 사용한다면 orElse 함수로 만들어 줘야한다면, orElseGet권장!
OnlineClass onlineClass = optional.orElse(createNewClass());
System.out.println(onlineClass.getTitle());
// 5. orElseGet(Supplier) = 값이 없는 경우만 createNewClass 실행
OnlineClass onlineClass1 = optional.orElseGet(OptionalTestApp::createNewClass);
System.out.println(onlineClass1.getTitle());
// 6. orElseThrow(Supplier)
OnlineClass onlineClass2 = optional.orElseThrow(() -> {
return new IllegalArgumentException();
});
// 메소드 레퍼런스 사용
OnlineClass onlineClass3 = optional.orElseThrow(IllegalArgumentException::new);
// 7. Optional filter(Predicate) = Optional타입이 리턴됨
Optional<OnlineClass> onlineClass4 = optional.filter(oc -> oc.getId() > 10);
// 8. Optional map(Function) = map으로 변환한 타입을 Optional로 감싸서 리턴함
Optional<Integer> integer = optional.map(OnlineClass::getId);
// Optional을 리턴하는 경우 굉장히 복잡해짐
Optional<Optional<Progress>> progress = optional.map(OnlineClass::getProgress);
Optional<Progress> progress1 = progress.orElse(Optional.empty());
// 9. Optional flatMap(Function)
Optional<Progress> progress2 = optional.flatMap(OnlineClass::getProgress);
}
private static OnlineClass createNewClass() {
System.out.println("createNewClass 함수 실행");
return new OnlineClass(10 ,"New class", false);
}
}
Java 8,ホワイトベースラインReference
この問題について([再Java Java 8]4Optional), 我々は、より多くの情報をここで見つけました https://velog.io/@agpine12/더-자바-Java8-4.-Optionalテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol