Developer Cafe

Optional 본문

JAVA

Optional

개발자 카페 2021. 5. 21. 17:45
728x90

JAVA 8 전에는 메서드가 특정 조건에서 값을 반환할 수 없을 때 취할 수 있는 선택지가 2가지였다.

  • Exception Throw
  • Null Return

예외는 반드시 예외적인 상황에서만 사용해야 한다.

예외는 실행 스택을 추적을 캡쳐하기 때문에 비용이 비싸다

null을 리턴하는 경우에는 NPE(Null Pointer Exception)을 항상 조심해야한다.

Optional 이란

  • Optional은 값이 있을 수도 있고 없을 수도 있는 객체다. 참조 타입의 객체를 한 번 감싼 일종의 래퍼 클래스 이다.
  • Optional은 원소를 최대 1개 가질 수 있는 불변 Collection 이다.
  • 자바 8 이전의 코드보다 null-safe한 로직을 처리 할 수 있게 해준다.
  • Optional을 반환하여 좀 더 로직을 유연하게 작성할 수 있게 해준다.

Person p = new Person()은 Person을 사용하기 위해 메모리를 할당 한 후, 그 레퍼런스를 p
에게 할당하라는 뜻이다. 그러나 Person p = null 은 아무런 레퍼런스도 없으므로 NPE가 발생

public class Optional1 {
	public static void main(String[] args) {
    		Person p = null;
		System.out.println(p.name);
    	}
}

매서드 종류

※ 코드 예시 기본 세팅

public class Optional1 {

      static List<Person> persons = new ArrayList<>();
      public static void main(String[] args) {

          .
          .
          .
          각 메서드별 코드 예시
          .
          .
          .

      }
      static class Person {
        String name;
        int age;
        Person(String name, int age) {
            this.name = name;
            this.age = age;
          }
      }
    public static Person search(final String name) {
        for(Person p : persons) {
            if(p.name.equalsIgnoreCase(name)) {
                return p;
            }
        }
        return null;
    }

    public static Person createPerson(final String name, final int age) {
        return new Person(name, age);
    }
}
  • Optional.empty()
    • 내부 값이 비어있는 Optional 객체 반환
  • T get()
    • Optional 내의 값을 반환
    • 만약 Optional 내부 값이 null인 경우 NoSuchElementException 발생
  • boolean isPresent()
    • Optional 내부 값이 null이면 false, 있으면 true
    • Optional 내부에서만 사용해야하는 메서드라고 생각
  • boolean isEmpty()
    • Optional 내부의 값이 null이면 true, 있으면 false
    • isPresent() 메서드의 반대되는 메서드
public class Optional1 {
	static List<Person> persons = new ArrayList<>();
	public static void main(String[] args) {
    		Optional<Person> oP = Optional.empty(); // 이 Optional클래스는 Person타입의 오브젝트를 저장 할 것.
                                                // Optional 오브젝트를 생성하되 안의 Person은 null로 지정 할 것

                if(oP.isPresent()) {                    // Optional안에 Person오브젝트가 존재하나? return ture false
                    Person p = oP.get();                // Optional안의 Person 오브젝트 가져올것
                    System.out.println("p exists " + p.name);
                }

    	}
        .
        .
        .
        .
        .
}

  • Optional.of(T value)
    • 내부 값이 value인 Optional 객체 반환
    • 만약 value가 null인 경우 NullPointerException 발생
public class Optional1 {
	static List<Person> persons = new ArrayList<>();
	public static void main(String[] args) {
    		Optional<Person> oP = Optional.of(new Person("zzimcarOf", 17)); // of는 오브젝트가 확실히 null이 아닐경우
                if(oP.isPresent()) {
                    Person p = oP.get();
                    System.out.println("p name " + p.name);
                }
    	}
        .
        .
        .
        .
        .
        .
}

  • Optional.ofNullable(T value)
    • 가장 자주 쓰이는 Optional 생성 방법
    • value가 null이면, empty Optional을 반환하고, 값이 있으면 Optional.of로 생성
public class Optional1 {
	static List<Person> persons = new ArrayList<>();
	public static void main(String[] args) {
    		Optional<Person> oP = Optional.ofNullable(new Person("zzimcarOfNull", 17)); // ofNullable는 오브젝트가 null인지 아닌지 알수 없음
                if(oP.isPresent()) {
                    Person p = oP.get();
                    System.out.println("p name " + p.name);
                }
    	}
        .
        .
        .
        .
        .
        .
}

  • void ifPresent(Consumer<? super T> consumer)
    • Optional 내부의 값이 있는 경우 consumer 함수를 실행
  • Optional<T> filter(Predicate<T> predicate)
    • Optional에 filter 조건을 걸어 조건에 맞을 때만 Optional 내부 값이 있음
    • 조건이 맞지 않으면 Optional.empty를 리턴
  • Optional<U> map(Funtion<? super T, ? extends U> f)
    • Optional 내부의 값을 Function을 통해 가공
  • T orElse(T other)
    • Optional 내부의 값이 있는 경우 그 값을 반환
    • Optional 내부의 값이 null인 경우 other을 반환
public class Optional1 {
	static List<Person> persons = new ArrayList<>();
	public static void main(String[] args) {
    		String name = "zzimcarOrElse";
                // orElse는 오브젝트가 null이든 말든 일단 실행하고 본다.
                Person p = Optional.ofNullable(search(name)).orElse(new Person(name, 17));
                System.out.println("p name " + p.name + " p age = " + p.age);
    	}
        .
        .
        .
        .
        .
        .
}

  • T orElseGet(Supplier<? extends T> supplier)
    • Optional 내부의 값이 있는 경우 그 값을 반환
    • Optional 내부의 값이 null인 경우 supplier을 실행한 값을 반환
public class Optional1 {
	static List<Person> persons = new ArrayList<>();
	public static void main(String[] args) {
    		String name = "zzimcarOrElseGet";
                // orElseGet은 오브젝트가 null일 경우에만 쓸 수 있다.
                Person p = Optional.ofNullable(search(name)).orElseGet(() -> createPerson(name, 17));
                System.out.println("p name " + p.name + " p age = " + p.age);
    	}
        .
        .
        .
        .
        .
        .
}

  • T orElseThrow()
    • Optional 내부의 값이 있는 경우 그 값을 반환
    • Optional 내부의 값이 null인 경우 NoSuchElementException 발생
public class Optional1 {
	static List<Person> persons = new ArrayList<>();
	public static void main(String[] args) {
    		Person person = null;
                Person p = Optional.ofNullable(person).orElseThrow(() -> new RuntimeException()); // orElseThrow()는 null 일경우 발생시킬 Exception을 쓸때 사용한다.
                System.out.println("p exists " + p.name + " " + p.age);
    	}
        .
        .
        .
        .
        .
        .        
}
  • T orElseThrow(Supplier<? extends X> exceptionSupplier)
    • Optional 내부의 값이 있는 경우 그 값을 반환
    • Optional 내부의 값이 null인 경우 exceptionSupplier을 실행하여 Exception 발생
728x90
Comments