Java | Optional

바다·2024년 5월 14일
0

Java

목록 보기
17/18
post-thumbnail

Optional... 너 뭔데

  • T 타입 객체의 Wrapper Class - Optional
  • null인 값을 참조해도 NullPointerException이 발생하지 않도록 값을 래퍼로 감싸주는 타입
public final class Optional<T> {
    private final T value;  //T 타입의 참조 변수
    ...
}

왜 필요한가?

  1. null을 직접 다루는 것은 위험하기 때문 -> NullpointException
  2. null 체크 -> if 문 필수 (코드가 지저분해진다)

Optional을 사용하다면?

  1. Wrapper로 감싸서 사용하기 때문에 NullPointerException이 발생하지 않는다
  2. if문으로 null을 체크하지 않아도 된다

하지만,,

  • Optional은 값을 Wrapping하고 다시 풀고, null일 경우에는 대체하는 함수를 호출하는 등 오버헤드가 있기 때문에 잘못 사용하면 시스템 성능이 저하된다
  • Optional은 메소드의 결과가 null이 될 수 있으며, null에 의해 오류가 발생할 가능성이 매우 높을 때 반환값으로 사용되어야 한다

Optional 활용하기

Optional 생성 static 메소드

1. empty()

.empty()

기능 : 비어 있는 Optional 객체를 생성
리턴 : Optional<T>

Optional<String> str = Optional.empty();

System.out.println(str.isEmpty());  //true

2. of()

.of(T value)

기능 : 전달된 값으로 새로운 Optional 객체를 생성
리턴 : Optional<T>

Optional<String> str = Optional.of("Hello, world!");

System.out.println(str.get());  //Hello, world!

3. ofNullable()

.ofNullable(T value)

기능 : 비어있을 수도 있고, 아닐 수도 있는 Optional 객체를 생성
리턴 : Optional<T>

String str = null;
Optional<String> optional1 = Optional.ofNullable(str);
Optional<String> optional2 = Optional.ofNullable("Hello");

System.out.println(optional1.isEmpty())     //true
System.out.println(optional2.isEmpty())     //false

Optional 활용 메소드

1. equals()

.equals(Object object)

기능 : Optional 객체의 값을 비교
리턴 : boolean

Optional<String> optional1 = Optional.of("Hi");
Optional<String> optional2 = Optional.of("Hi");
Optional<String> optional3 = Optional.of("Hello");

boolean result1 = optional1.equals(optional2);     //true
boolean result2 = optional1.equals(optional3);     //false

2. filter()

.filter(Predicate<? Super T> predicate)

기능 : Optional 객체의 값을 조건에 따라 필터링
리턴 : Optional

Optional<Integer> optional1 = Optional.of(100);
Optional<Integer> optional2 = Optional.of(10);

Optional<Integer> filter1 = optional1.filter(num -> num < 50);   //true
Optional<Integer> filter2 = optional2.filter(num -> num < 50);   //flase

3. map()

.map(Function<? Super T, ? Extends U> mapper)

기능 : Optional 객체 내부의 값을 변환하여 결과를 새로운 Optional 객체로 반환
리턴 : Optional<U>

Optional<String> optional = Optional.of("Hi");

Optional<Integer> result = Optional.map(str -> str.length());   //2

4. flatMap()

.flatMap(Function<? Super T, ? Extends Optional<? Extends U>> mapper)

기능 : 중첩된 Optional
리턴 : Optional<U>

Optional<String> optional = Optional.of("Hi");

Optional<String> flatResult = optional.flatMap(str -> Optional.of(str.toUpperCase()));  //Hi

map()과 flatMap()의 차이

  • map()은 값의 변환이 간단하게 이루어지는 경우에 사용
  • flatMap()은 중첩된 Optional 객체를 다루거나 매핑 함수 자체가 이미 Optional을 반환하는 경우에 사용

5. get()

.get()

기본 : Optional 객체의 값을 가져옴
리턴 : T

값이 존재하지 않는 경우 NoSuchElementException 발생

Optional<String> optional1 = Optional.ofNullable("Hi");
Optional<String> optional2 = Optional.ofNullable(null);

System.out.println(optional1.get());    //Hi
System.out.println(optional2.get());    //NosuchElementException

6. isEmpty()

.isEmpty()

기능 : Optional 객체가 비어있는지 확인
리턴 : boolean

Optional<String> optional1 = Optional.ofNullable("Hello");
Optional<String> optional2 = Optional.ofNullable(null);

System.out.println(optional1.isEmpty());    //false
System.out.println(optional2.isEmpty());    //true

7. isPresent()

.isPresent()

기능 : Optional 객체가 있는지 확인
리턴 : booelan

Optional<String> optional1 = Optional.ofNullable("Hello");
Optional<String> optional2 = Optional.ofNullable(null);

System.out.println(optional1.isPresnet());    //true
System.out.println(optional2.isPresnet());    //false

8. ifPresnet()

.ifPresnet(Consumer<? Super T> action)

기능 : Optional 객체가 있다면 내부 연산을 실행
리턴 : void

Optional<String> optional1 = Optional.ofNullable("Hello");
Optional<String> optional2 = Optional.ofNullable(null);

optional1.ifPresnet(str -> System.out.println(str)); //Hello
optional2.ifPresnet(str -> System.out.println(str)); 

9. ifPresnetOfElse()

.ifPresnetOfElse(Consumer<? Super T> action, Runnable emptyAction)

기능 : Optional 객체가 있다면 내부 연산을 실행, 없다면 또 다른 내부 연산을 실행
리턴 : void

Optional<String> optional1 = Optional.ofNullable("Hello");
Optional<String> optional2 = Optional.ofNullable(null);

optional1.ifPresnetOrElse(str -> System.out.println(str),
        () -> System.out.println("null"));  //Hello

optional2.ifPresentOrElse(str -> System.out.println(str),
        () -> System.out.println("null")); //null

10. or()

.or(Supplier<? Extends Optional<? Extends T>> supplier)

기능 : Optional 객체가 비어있다면, 다른 Optional 객체를 반환
리턴 : Optional<T>

Optional<String> optional1 = Optional.empty();
Optional<String> optional2 = Optional.of("Hello");

Optional<String> result1 = optional1.or(() -> Optional.of("World"));    //World
Optional<String> result2 = optional2.or(() -> Optional.of("World"));    //Hello

11.orElseGet()

.orElseGet(Supplier<? Extends T>supplier)

기능 : Optional 객체가 비어있다면, 내부 함수를 실행하여 생성된 기본값을 반환
리턴 : T

Optional<String> optional1 = Optional.empty();
Optional<String> optional2 = Optional.of("Hello");

String result1 = optional1.orElse(null);    //null
String result2 = optional2.orElse(null);    //Hello

12. orElseThrow()

.orElseThrow()
.orElseThrow(Supplier<? Extends X>exceptionSupplier)

기능 : Optional 객체가 비어있다면 Exception 발생
리턴 : T

Optional<String> optional1 = Optional.emtpy();
String result1 = optional.orElseThrow();                //NoSuchElementException

Optional<String> optional2 = Optional.empty();

String result2 = optional2
        .orElseThrow(IllegalArgumentException::new);    //IllegalArgumentException

13. stream()

.stream()

기능 : Optional 객체의 값을 Stream으로 변환
리턴 : Stream<T>

Optional<String> optional = Optional.of("Hello");

optional.stream()
        .map(String::toUpperCase)
        .forEach(System.out::println); // HELLO

14. toString()

.toString()

기능 : Optional의 내부 값을 String 문자열로 바꿔 반환
리턴 : String

Optional<String> optional = Optional.of("Hello");
String str = optional.toString();   //Hello

15. hashCode()

.hashCode()

기능 : Optional 객체의 HashCode를 반환
리턴 : int

Optional<String> optional = Optional.of("Hello");
int hashCode = optional.hashCode();     //hashCode
profile
ᴘʜɪʟɪᴘᴘɪᴀɴs 3:14

0개의 댓글