Java

[Java] Optional 에 대한 개념 및 사용법

WOOOOJI 2023. 3. 10. 17:23

 
 

Java 공식 Docs에서의 Optional 소개


Optional을 알기 위해선 NullPointerException을 알아야 한다 !

모든 개발자들이 무서워하는 에러 중 하나인 NullPointerException.....

직역하면 알수있는데, 말 그대로 Null값을 참조하기에 예외를 발생시킨것이다 !

아래 코드와 같이 Null일수 있는 데이터가 있다면, 해당 값을 애초에 초기화를 시켜놓거나 Null인지 아닌지 검사를 해줘야 한다.

    public void nullException(){
		String name = ""; 		 
        name = makeName(name);	// 메소드를 통해 값을 초기화 했지만 Null일수 있다. 
		name.equals("Java");  	// Null값을 가지고 문자열과 비교를 하기에 예외가 발생한다.
    }
    
    
    public void notNull(){
        String name = "Java";
        name = makeName(name);  // name이라는 변수는 값이 있기에 다시 본인의 이름으로 값이 초기화 된다.
        name.equals("Java");
    }

    public String makeName(String name){  // 테스트를 위해 고의로 NUll값을 넘겼다.
       if(name.equals("")){
            return name;
       }
       return null;
    }

Null값과 문자열을 비교하기에 당연히 NullPointerException 예외가 발생했다.

 

 

 

Optional은 이러한 Null 참조 예외를 쉽게 처리하기 위해 등장했습니다 :)

Optional은 null이 될 수 있는 값을 감싸는 Wrapper클래스로 참조하더라도 예외 발생을 막아줍니다.

세가지 메소드를 통해 인스턴스 생성이 가능하며, 만약에 값이 비어있을 경우 비어있는

Optional객체를 return함으로써 null이 아니게 되는겁니다.

자 그러면 어떻게 써야 하는지 알아봐야겠죠 허헣.

 

 

 

 

        // Null상태로 생성되는 Optional
        Optional<String> optionalEmpty = Optional.empty();

        // Null이면 명시된 값을 가지는 Optional - 메소드 및 파라미터가 올 수 있다.
        Optional<String> optionalNotEmpty = Optional.ofNullable(makeName("woojin"));

        // Null이면 명시된 값을 가지는 Optional - 메소드 및 파라미터가 올 수 있다.
        Optional<String> optionalNeverEmpty = Optional.of("비어있으면 안댕");
  1. empty() 메소드 : 비어있는 Optional 객체를 생성한다.
  2. ofNullable() 메소드 : Null일 경우 명시된 값을 가지고 초기화 한다.
  3. of() 메소드 : Null일 경우 명시된 값을 가지고 초기화 한다.

 

 

 

 


?? ofNullable이랑 of가 똑같은거 아니에요 ??

중요한 차이점이 존재 합니다!

ofNullable()은 명시된 값이 null이여도 예외를 발생시키지 않습니다. 즉 말 그대로 Nullable하다는 뜻입니다.

of()는 명시된 값이 null이면 여전히 NullPointerException을 일으킵니다.

 


 

 

 

 

ofNullable() - null값을 가지게 되도 상관없다

    public String makeName(String name){
        if(!name.equals("")){
            return name;
        }

        return null;
    }
    
    
    // 메소드의 결과값이 Null을 반환하지만 NullPointerException이 발생하지 않는다.
    Optional<String> optionalNotEmpty = Optional.ofNullable(makeName(""));

 

 

 

of() - null값을 가지게 되면 예외 발생

    public String makeName(String name){
        if(!name.equals("")){
            return name;
        }

        return null;
    }
    
    // 결과값이 null이기에 NullPointerException을 발생시킨다.
    Optional<String> optionalNeverEmpty = Optional.of(makeName(""));

 


 

 

 

 

 

 

orElse(),  orElseGet()  의 사용법 & 차이점

 

둘 다 값이 비어있지 않을 경우에 어떤 행동을 취할지 명시하는 메소드입니다.

orElse() -> 직접적으로 값을 전달합니다.

orElseGet() -> 메소드 자체를 전달합니다.

이 둘의 차이점은 생각보다 매우 중요합니다. 코드와 함께 보시죠 !

 

 

    @Test
    void testElseGet(){
    	// orElseGet 사용시 함수가 넘어간다. 즉 함수는 있지만 null값이 아니라면 실행되지 않는다.
        String o = Optional.ofNullable("Java").orElseGet(this::areYouIn);

    }

    @Test
    void testElse(){
    	// orElse 사용시 값이 넘어간다. 즉 함수가 바로 실행이 되고 결과값을 가지고 있는 상태이다.
        // null유무와 상관없이 함수가 실행되고 그 결과값을 null유무에 따라 넘길지 말지 정한다.
        String o = Optional.ofNullable("Java").orElse(areYouIn());

    }

    public String areYouIn(){
        System.out.print("메소드에 들어왔어요!");
        return "Pyton";

 

 

 


 

 

1. orElse() ->  값을 넘긴다.

    public void testElse(){
        String o = Optional.ofNullable("Java").orElse(areYouIn());

    }

    public String areYouIn(){
        System.out.print("메소드에 들어왔어요!");
        return "Python";
    }

ofNullable("Java")가 있기에 orElse()는 실행이 안되는것 같지만, 앞서 말했듯이 값을 넘겨주기 때문에, 메소드의 실행 결과를 가지고 대기중인 상태다 ! 그리고 나서 null 유무에 따라 값을 초기화 하는것 입니다.

 

 

 

 

2. orElseGet() ->  Method를 넘긴다.

    void testElseGet(){
        String o = Optional.ofNullable("Java").orElseGet(this::areYouIn);

    }
    
    public String areYouIn(){
        System.out.print("메소드에 들어왔어요!");
        return "Python";
    }

메소드 자체를 넘기기에 null 유무에 따라서 함수 자체를 실행시킬지 말지 결정을 합니다. 그렇기에 orElse()와는 다르게 함수를 실행 시키지 않는것을 확인할 수 있습니다.

 

 

 

 

 

 


 

if문 쓰면 되는거 아닌가?

if를 이용하여 null값을 체크하고 대처할 수 있습니다.

하지만 if를 이용하여 null값을 체크하면 안좋은 이유가 있기에 등장했겠죠?

첫번째. 코드가 쓸모없이 길어진다 -> 가독성이 떨어진다

두번째. 각각의 변수마다 null값을 체크해야되는데 개발자의 실수로 인해 놓칠수 있다

 

 


 

 

 

 

 

Optional is intended to provide a limited mechanism for library method return types where there needed to be a clear way to represent “no result," and using null for such was overwhelmingly likely to cause errors.
- Brian Goetz(Java Architect) - Java 언어 설계자


대략 해석해보자면 :
Optional은 반환 타입으로 사용하도록 의도하여 설계하였다는 내용입니다. 무차별적인 Optional 사용은 성능을 저하시킬수 있으며 예측할 수 없는 결과가 발생한다고 경고를 하고 있습니다.
그래서 반환 타입으로만 사용하는걸 적극 권장하고 있습니다 !







오늘도 모두 슬기로운 코딩 생활 하십쇼!!
잘못 기재된 사실이나 부족한 부분은 피드백 주시면 감사하겠습니다 :)
더불어 궁금한 내용에 대해 댓글을 남겨주시면 답변해드리도록 하겠습니다 .
728x90