본문 바로가기
java

Optional

by 킹차니 2021. 12. 30.

optional -optional<T>

T타입 객체의 래퍼클래스 (래퍼클래스의 예 : Integer, Long)

public fianl class Optional<T>{
	private final T value; //T타입의 참조변수 (모든 종류의 객체 저장 가능)
	...
}

왜 사용하나?

1. null을 직접다루는 것은 NullPointerException이 발생할 수 있어 위험하다. —> 하여 간접적으로 null을 다루는 것.

2. null을 직접다루면 null체크를 위해 if문이 필요하다. —> 코드가 지저분해진다.

하여 null이 생성될 수 있는 객체는 Optional로 한번 감싸서 사용한다.

 

만약 아래와 같은 코드가 있을 시에

Object result = getResult();

result는 Result타입 객체이거나, null이다.

하여 만약 null일 시에 아래와 같이 한다면 NullPointerException이 발생한다.

result.메소드()

그래서 Optional 객체로 result를 감싸면 NullPointerException가 발생하지 않는다.

 

이와 관련된 예로 String타입이나 배열은 아래와 같이 초기화한다.

String str = null // X 이렇게하면 NullPointerException이 발생할 위험
String str = ""   // O 빈문자열로 초기화한다.

int[] arr = null  // X 이렇게하면 NullPointerException이 발생할 위험
int[] arr = new int[0] // O 이렇게 빈 문자열로 초기화한다.

 

Optional<T> 객체 생성하는 방법

String str = "abc";
Optional<String> optVal = Optional.of(str);
Optional<String> optVal = Optional.of("abc");
Optional<String> optVal = Optional.of(null); // NullPointerException 발생. 이건 안됨
Optional<String> optVal = Optional.ofNullable(null); // OK

null이 발생할 수 있는 객체는 Optional<T> 객체를 사용하자

Optional<String> optVal = null; //널로 초기화. 바람직하지 않음. 에러는 발생하지 않는다.
Optional<String> optVal = Optional.<String>empty(); // 빈 객체로 초기화

 

Optional<T> 객체의 값 가져오기 - get(), orElse(), orElseGet(), orElseGet(), orElseThrow()

Optional<String> optVal = Optional.of("abc");
String str1 = optVal.get(); //optVal에 저장된 값을 반환. null이면 예외발생
String str2 = optVal.orElse(""); //optVal에 저장된 값이 null일 때는 ""를 반환
String str3 = optVal.orElseGet(String::new);//람다식 사용가능 ()->new String()
String str4 = optVal.orElseThrow(NullPointerException::new);//예외 종류 지정가능(현재는 널이면 NullPointerException발생예약)

 

isPresent() - Optional객체의 값이 null이면 false, 아니면 true를 반환

if(Optional.ofNullable(str).isPreSent()){ // if(str!=null)
	System.out.println(str);
}

//널이 아닐때만 작업 수행. 널이면 아무것도 안함
Optional.ofNullable(str).isPreSent(System.out.println);

 

OptioanlInt, OptionalLong, OptionalDouble - 기본형 값을 감싸는 래퍼 클래스

Optioanl<T> 보다는 성능이 좋기 때문에 쓴다.

public final class OptionalInt{
	...
	private final boolean isPresent; //값이 저장되어 있으면 true
	private final int value;         //int타입의 변수
}

 

 

예제들

EX1)

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

//        Optional<String> opt = null;//OK! 하지만 바람직하지 않다.
        Optional<String> opt = Optional.empty();
        System.out.println(opt);//Optional.empty    NullExceptionPointer 발생 안함

        String str = opt.orElse("null 이었네요"); // Optional에 저장된 값이 Null이면 "null 이었네요"반환
        System.out.println(str); // "null 이었네요"

        //람다식으로 사용하기
        str = opt.orElseGet(() -> "null 이었네요2");
        str = opt.orElseGet(() -> new String("null 이었네요2"));
        System.out.println(str);//"null 이었네요2"

        //메소드 참조로 바꾸기
        str = opt.orElseGet(String::new);
        System.out.println(str);// 빈문자열이 출력된다.
    }
}

 

EX2)

public class Ex02 {
    public static void main(String[] args) {
        Optional<String> optStr = Optional.of("abcde");
        Optional<Integer> optInt = optStr.map(String::length);//Optional은 map을 제공한다.
//        Optional<Integer> optInt = optStr.map(s->s.length());//위와 같다.
        System.out.println(optStr.get());//abcde
        System.out.println(optInt.get());//5

        int int1 = Optional.of("123")
                .filter((s) -> s.length() > 0)
                .map(Integer::parseInt).get();

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

        System.out.println(int1);//123
        System.out.println(int2);//-1

        Optional.of("456").map(Integer::parseInt).ifPresent(System.out::println);//456

        OptionalInt optInt1 = OptionalInt.of(0);
        OptionalInt optInt2 = OptionalInt.empty();

        System.out.println(optInt1.isPresent()); //true
        System.out.println(optInt2.isPresent()); //false

        System.out.println(optInt1.getAsInt()); // 0
        System.out.println(optInt2.getAsInt()); // NoSuchElementException

        System.out.println("optInt1 = " + optInt1);//OptionalInt[0]
        System.out.println("optInt2 = " + optInt2);//OptionalInt.empty
        System.out.println(optInt1.equals(optInt2));//false
    }
}

 

 

출처: 남궁성님 유튜브 강의
https://www.youtube.com/user/MasterNKS

'java' 카테고리의 다른 글

Generics 01 제네릭스란?  (0) 2021.12.31
Lambda 07 Collector  (0) 2021.12.30
Lambda 06 Stream의 연산 (중간 연산과 최종 연산)  (0) 2021.12.29
Lambda 05 Stream  (0) 2021.12.27
Lambda 04 메소드 참조  (0) 2021.12.26