Optional

SeokHwan An·2022년 7월 7일
0

java8

목록 보기
2/2

java8이 들어오고 나서 Optional 이라는 개념이 등장하게 되었습니다. Optional에 대해서 알아보기에 앞서 Optional이 등장하게 된 배경에 대해 얘기해보겠습니다.

NPE(NullPointerException)

웹, 앱 애플리케이션을 개발하거나 알고리즘 문제를 풀 때 종종 NPE(NullPoinerException)이라는 오류를 종종 보게됩니다. 이는 실제 값이 아닌 null을 가지고 있는 객체 혹은 변수를 호출할 때 발생하는 예외입니다.
다음과 같은 코드가 있을 때 NullPointerException이 발생하게 됩니다.

package me.whiteship.java8to11;

public class Practice {
    public static void main(String[] args) {
        Integer id = null;
        String str_id = id.toString();
        System.out.println(str_id);
    }
}
NullPointerException이 발새하는 코드 이외에도 다양한 상황에서 NullPointerException이 발생하는 상황이 종종 나타나고 이를 해결하는 방법에는 크게 3가지가 있습니다.

NPE(NullPointerException)을 해결하는 방법(Optional 등장이전)

💡 Try Catch 문 이용
위의 코드를 Try Catch문을 이용해 해결하면 다음과 같습니다.

package me.whiteship.java8to11;

public class Practice {
    public static void main(String[] args) {
        Integer id = null;

        try{
            String str_id = id.toString();
            System.out.println(str_id);
        } catch (NullPointerException e){
            id = 111111;
            String str_id = id.toString();
            System.out.println(str_id);
        } finally{
            System.out.println("항상 실행");
        }
    }
}

위의 코드의 경우 성공과 실패의 코드가 모두 드러나며 변수 하나의 상황에서도 여려줄의 코드들이 작성되는데 더 복잡한 상황(여려개의 변수가 null 경우 혹은 객체가 null인 경우)에서는 개발자가 감당하기가 어려울 것입니다.

💡 if문 활용
위의 코드를 if문을 활용해서 해결하면 다음과 같습니다.

package me.whiteship.java8to11;

public class Practice {
    public static void main(String[] args) {
        Integer id = null;

        if(id == null){
            System.out.println("id가 null입니다");
        }else{
            String str_id = id.toString();
            System.out.println(str_id);
        }
    }
}

if문 역시 변수 하나에 대해서 null인지 아닌지를 판단하는 코드 역시 여러줄이 나타나게 되며 더 복잡한 상황(여려개의 변수가 null 경우 혹은 객체가 null인 경우)에서는 비효율적인 코드가 만들어지는 경우가 생길 것입니다.

위와 같이 null로 인해 발생하는 비효율적인 코드를 제거하기 위해 Optional이라는 개념이 등장하게 되었습니다.

📙 OPtional

Optional이란 NPE(NullPointerException)을 방지하기 위해 NPE가 발생할 수 있는 변수나 객체들에 대해 Option 클래스로 감싸주는 Wrapper 클리스입니다. Optional에 경우 값이 들어있을 수 도 있고 값이 들어있지 않을 수 있는 컨테이너 입니다.

Optional의 장점

  • NPE를 유발할 수 있는 null을 직접 다루거나 체크를 하지 않아도 됩니다.
  • 명시적으로 해당 변수가 null일 수도 있다는 가능성을 표현이 가능합니다.

주의할 점

  • 리턴값으로만 사용하기(메소드 매개변수 타입, map의 키 타입, 인스턴스의 필드 타입으로 쓰지 않기)
  • Optional을 리턴하는 메소드에서 null을 리턴하지 않기

Optional 사용법

Optional의 경우 static method인 empty(), of(), ofNullable()을 통해 Optional 객체를 생성할 수 있습니다. of()의 경우 매개변수 값이 null인 경우에 NPE가 발생할 수 있기에 null 가능성이 있는 경우에는 ofNullable()을 사용해야합니다.

  • empty()를 활용한 Optional 생성
package me.whiteship.java8to11;

import java.util.Optional;

public class Practice {
    public static void main(String[] args) {
        Optional<Integer> id = Optional.empty();
        System.out.println(id.isPresent()); //false를 반환
    }
}

empty를 통해 Optional을 생성하면 값이 없는 것을 알 수 있습니다. isPresent()는 값이 null인 경우에는 false를 반환하며 있는 경우에는 true를 반환해주는 메소드입니다.

  • of()를 활용한 Optional 생성
package me.whiteship.java8to11;

import java.util.Optional;

public class Practice {
    public static void main(String[] args) {
        Optional<Integer> id = Optional.of(1234);
        System.out.println(id.isPresent());
    }
}

of() 경우 무조건 값을 인자로 받아야하면 없는 경우에는 NPE가 발생하게 됩니다.

  • ofNullable을 활용한 Optional 생성
package me.whiteship.java8to11;

import java.util.Optional;

public class Practice {
    private static Integer student_id;

    public static Integer getStudent_id() {
        return student_id;
    }

    public void setStudent_id(Integer student_id) {
        this.student_id = student_id;
    }

    public static void main(String[] args) {
        Optional<Integer> id = Optional.ofNullable(getStudent_id());
        System.out.println(id.orElse(1234));
    }
}

ofNullable()의 경우에는 null이 올수도 있고 아닌 경우도 있습니다. 그렇기에 orElse()를 활용해 값이 null인 경우에는 사용자가 지정한 default값을 가져올 수 있습니다.

이제 맨 위에서 발생한 NPE를 Optional를 활용해 해결하면 다음과 같습니다.
💡 Optional를 통해 해결

package me.whiteship.java8to11;

import java.util.Optional;

public class Practice {

   public static void main(String[] args) {
       Optional<Integer> id = Optional.ofNullable(null);
       String str_id = id.orElse(111111).toString();
       System.out.println(str_id);
   }
}

0개의 댓글