Free Lines Arrow
본문 바로가기
Language/Java

[Java] Optional<T> 기본

by skahn1215 2023. 2. 6.
728x90
반응형

Optional에 대해 알아보자

 

Optional 이란?

Optional<T> 는 지네릭 클래스로 T 타입의 객체를 감싸는 래퍼 클래스이다.

모든 타입의 참조 변수를 담을수 있다.

최종 연산결과를 단순히 반환하는게 아니라 Optional 객체에 담아서 반환한다.

 

장점?

반환된 결과가 null 인지 매번 if 문으로 체크를 안해도된다.

제공되는 메서드를 사용하면 된다.

 

 

 

Optional 객체 생성하기

of 와 ofNullable 를 이용해서 생성하면된다.

차이점

  • of : null 값이 들어갈수 없다.
  • ofNullable : null 값이 들어 갈수 있다.

만일 null 값이 들어 가는 경우가 있다면 무조건 ofNullable 을 사용하자. 

import java.util.Optional;

public class OptionalTest {
    public static void main(String[] args) {
        String str = "string";
        Optional<String> optVal1 = Optional.of(str);
        Optional<String> optVal2 = Optional.of("test");
        Optional<String> optVal3 = Optional.of(new String("AAA"));

        //Optional<String> optVal4 = Optional.of(null); //null exception 발생
        Optional<String> optVal4 = Optional.ofNullable(null); //null exception 발생
    }
}

 

기본 값으로 초기화를 하고 싶으면 empty를 이용하자

import java.util.Optional;

public class OptionalTest {
    public static void main(String[] args) {

        // 권장하지 않음.
        //Optional<String> optVal1 = null;

        // 권장
        Optional<String> optVal1 = Optional.<String>empty() ;

    }
}

 

 

 

Optional 객체의 값 가져오기

get, orElse를 사용하거나 orElseGet, orElseThrow를 사용하자

차이점

  • get: null 이면 예외 발생
  • orElse: null 일경우 대체된 값을 가져옴 
  • orElseGet: 람다 식을 지정 할 수 있음.
  • orElseThrow: null 일때 지정된 예외를 발생 시킬수 있음.
import java.util.Optional;

public class OptionalTest {
    public static void main(String[] args) {
        String str = "abc";
        Optional<String> optVal1 = Optional.of(str);
        Optional<String> optVal2 = Optional.ofNullable(null);

        String str1 = optVal1.get();
        String str2 = optVal2.orElse("NULL!!");

        System.out.println("str1 = " + str1);
        System.out.println("str2 = " + str2);


        Optional<String> optVal3 = Optional.of(null);

        String str3 = optVal1.orElseGet(String::new);
        System.out.println("str3 = " + str3);

        // exception!!!!!
        String str4 = optVal2.orElseThrow(NullPointerException::new);
    }
}

 

 

 

Optional에서 filter, map, flatMap 사용하기

Stream 처럼 Optional객체에도 filter, map flatMap을 사용 할 수 있다.

객체의 값이 null 인경우 아무 일도 하지 않는다.

 

flatMap

map() 의 연산 결과가 Optional<Optional<T>> 인경우 Optional<T> 를 결과 값으로 얻는다.

 

filter, map

import java.util.Optional;

public class OptionalTest {
    public static void main(String[] args) {
        int result1;
        result1 = Optional.of("123")
                        .filter( x->x.length() > 0)
                        .map(Integer::parseInt).orElse(-1);

        // 123
        System.out.println(result1);

        int result2;
        result2 = Optional.of("")
                .filter( x->x.length() > 0)
                .map(Integer::parseInt).orElse(-1);

        // -1
        System.out.println(result2);
        
    }
}

 

Optional을 이용하여 null  값 check 하기

isPresent 와 ifPresent를 사용하자.

isPresent(): Optional의 객체값이 null 이면 false, 아니면 true를 return 한다.

ifPresent(Consumer<T> block) : 값이 있으면 주어진 람다식을 실행하고, 없으면 아무것도 하지 않는다.

 

import java.util.Optional;

public class OptionalTest {
    public static void main(String[] args) {

        String name = null;


        if (name != null) {
            System.out.println("is not null");
        } else {
            System.out.println("is null");
        }

        // isPresent 사용
        if (Optional.ofNullable(name).isPresent()) {
            System.out.println("is not null");
        } else {
            System.out.println("is null");
        }

        // ifPresent 사용
        String name2 = "test";
        Optional.ofNullable(name2).ifPresent(
                name3->System.out.println(name3)
                );

    }
}

 

ifPresent 는 findAny() 와 findFirst() 와 같은 최종 연산과 어울린다.

값을 filter를 통해서 조회후 값이 null 인경우와 아닌경우를 처리할수 있기 때문이다.

 

import java.util.List;
import java.util.Optional;

public class OptionalTest {
    public static void main(String[] args) {
        List<String> list=List.of("test!","test!!","test!!!","item!!!!");
        list.stream()
                .filter(s ->s.length() == 5)
                .findAny()
                .ifPresent( s-> System.out.println(s) );
    }
}

 

 

OptionalInt, OptionalLong, OptionalDouble

IntStream과 같은 기본형 스트림에는 Optional도 기본형을 값으로 하는

OptionalInt, OptionalLong, OptionalDouble을 반환한다.

 

반환타입이 Optional<T> 가 아닌 것을 제외 하고는 Stream에 정의된 것과 비슷하다.

그리고 기본형 Optional에 저장된 값을 꺼낼 때 사용하는 메서드의 이름이 조금 다르다.

 

Optional<t> : T get()

OptionalInt : int getAsInt()

OptionalLong: long getAsLong()

OptionalDouble: double getAsDouble()

 

중요점

그럼 다음과 같은 예제를 보자

// 두값을 같은가?
OptionalInt opt1 = OptionInt.of(0);
OptionalInt opt2 = OptionInt.empty();

opt1.isPresent(); // true
opt2.isPresent(); // false

opt1.getAsInt(); // 0
opt2.getAsInt(); // Exception 발생

opt1.equals(opt2); // false


// null 일 때는 동일하다.
OptionalInt opt3 = OptionInt.ofNullablenull0);
OptionalInt opt4 = OptionInt.empty();

opt3.equals(opt4); // true

 

 

참고: Java의정석

 

728x90
반응형

'Language > Java' 카테고리의 다른 글

[Java] sort, nullsLast, nullsFirst  (0) 2024.03.17
[Java] Optional 제대로 쓰기  (0) 2023.02.06
[Java] SQL Mapper 만들기  (0) 2022.10.20
[Java] Generic 메서드  (0) 2022.06.25
[Java] Generic 와일드 카드  (0) 2022.06.25

댓글