프로그래밍 언어/JAVA

<JAVA> Optional

창조적생각 2021. 10. 4. 02:49

 

김영한 선생님의 인프런 강의 스프링 스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술을 듣던 중에 MemberRepository를 짜던 도중에 나온 Optional<T>를 처음 봤습니다.

 

 처음 본 제네릭을 보고 그냥 넘어갈 수는 없어 Optional에 대해서 찾아보았습니다. 역시 자바의 정석 유튜브에서 그에 대해 상세히 설명을 해주셨습니다.

 

 사실 제 블로그보다는 자바의 정석 유튜브-Optional 편을 보시는 것이 훨씬 나으실 겁니다.

 

저는 그냥 배운것을 정리하기 위해 씁니다.

 

Optional<T>는 간단히 이야기 하자면 "NullPointException"의 발생을 좀 더 간단하고 깔끔하게 예외처리를 해주기 위해 사용하는 제네릭입니다.

예를 들자면, NullPointException가 발생하지 않게 코드를 짜기 위해서는 if문을 사용해주어야 합니다.

1
2
3
4
String id = null;
        if(session.getAttribute("id"!= null){
            id = (String)session.getAttribute("id");
        }
cs

위의 코드는 제가 학습관리시스템을 만드는 JSP 팀 프로젝트를 할 때 회원관리 메인 페이지를 만들던 친구가 만들어 놓은 코드입니다.

 

session으로 id값을 받아서 String id에 저장하는 코드인데,  NullPointException을 피하기 위해서 if를 사용하여 받은 어트리뷰트가 null이 아닐때만 String id에 어트리뷰션값을 넣어주었습니다.

 

 이 코드를 Optional 코드로 바꿔주면

1
2
3
4
String id = "";
Optional<String> opt_id = Optional.ofNullable(session.getAttribute("id"));
id = opt_id.orElse("");
 
cs

이렇게 바꿔줄 수 있습니다.

 

그렇다면 왜 굳이 Optional로 한번 감싸서 쓰는 코드를 사용해야 하는 것일까요?

 

자바의 정석에 남궁성선생님은 두가지를 들어서 설명해주셨습니다.

 

1. null을 직접 다루는 것은 위험하다.

 - 아직 자바를 배우는 학생의 입장이라서 많은 경험이 없어 크게 와 닿지는 않습니다. 하지만 함께 공동으로 코드 작업을 하는 상황에서 함부러 null을 직접적으로 다룬다면 문제를 발생시킬 수 있다는 것을 어렴풋이 생각하게 합니다.

 null과 관련된 에러로는 NullPointException이 있는데 이 친구가 다른 친구들에 비해서 굉장히 모호하여 디버깅을 어렵게 한다고 합니다. 그렇기에 이 에러를 방지하는 코드를 짜는 것이 중요하다고 합니다.

 

2. null체크를 위한 if문들이 코드를 지저분하게 만들기 때문에 보다 가시성있고 깔끔한 코드를 위해 사용한다

 - 이 역시 공동작업에 관련된 것일 것입니다.

 

기본형식

1
2
3
4
5
6
7
        String str = "abc";
 
        Optional<String> optVal = Optional.of(str);
        Optional<String> optVal2 = Optional.of("abc");
        //Optional<String> optVal3 = Optional.of(null); nullpointexception!
        Optional<String> optVal4 = Optional.ofNullable(null);
 
cs


Optional로 감싸주는 방식은 기존의 제네릭을 사용할 때와 비슷합니다.

 

Optional로 null을 다루는 방법은 optVal4의 방식(Optional.ofNullable())을 사용하는 것인데, optVal3 처럼 그냥 of를 사용할 경우 nullpointexception이 뜹니다.

 

다만 감싸줬기 때문에 이대로 사용할 수 없습니다. 각각의 변수들을 프린트해보면 그 안의 value를 Optional이 그대로 감싼 형태로 출력됩니다.

 

<프린트 결과>

 

Optional로 감싼 값들을 빼내는 방법은 아래와 같습니다.

1
2
3
4
        String str1 = optVal.get(); //optVal에 저장된 값을 반환 null이면 예외발생
        String str2 = optVal.orElse("null떴음!"); //optVal에 저장된 값이 null일 때는 ""반환
        String str3 = optVal.orElseGet(()->new String("뭐임!")); //람다식 사용가능 () ->new String()
        String str4 = optVal.orElseThrow(NullPointerException::new); //null 이면 예외발생
cs

 

<print 결과>

1
2
3
4
        System.out.println("str1="+str1);
        System.out.println("str2="+str2);
        System.out.println("st3r="+str3);
        System.out.println("str4="+str4);
cs

 

 

"abc" 대신에 null값 혹은 Optional.empty를 넣어줬다면

str1은 nullpointerexception

str2는 "null떴음!"

 

str3은 "뭐임!"

 

str4는 예외가 발생하고 그 예외를 :: 뒤에서 다시 처리를 지정합니다.

 

 

 

 

728x90