자바

[JAVA] 옵셔널(Optional)이란 ?

서견 2023. 11. 6. 22:33

 

자바 옵셔널(Optional) 개요

Java 8부터 도입된 Optional은 null을 직접 다루는 것을 피하고자하는 목적으로 만들어진 래퍼 클래스입니다. Optional을 사용하면 null 체크를 명시적으로 하지 않아도 되므로 NullPointerException을 방지할 수 있습니다.

 

Optional<String> optional = Optional.of("Hello, World!");

옵셔널 생성

Optional 인스턴스는 Optional.empty(), Optional.of(value), Optional.ofNullable(value) 세 가지 메소드를 통해 생성할 수 있습니다.

  • Optional.empty(): 빈 Optional 객체를 생성합니다.
  • Optional.of(value): 주어진 값이 null이 아닌 경우, Optional 객체를 생성합니다. 만약 null이 주어지면 NullPointerException이 발생합니다.
  • Optional.ofNullable(value): 주어진 값이 null인지 아닌지 모를 경우, Optional 객체를 생성합니다. 값이 null인 경우 빈 Optional 객체를 반환합니다.
Optional<String> emptyOptional = Optional.empty(); 
Optional<String> nonNullOptional = Optional.of("Hello, World!"); 
Optional<String> nullableOptional = Optional.ofNullable(null);

옵셔널 값 사용

Optional에 저장된 값은 get(), orElse(defaultValue), orElseGet(supplier) 등의 메소드를 통해 가져올 수 있습니다.

  • get(): Optional에 저장된 값을 가져옵니다. 값이 존재하지 않는 경우 NoSuchElementException이 발생합니다.
  • orElse(defaultValue): Optional에 저장된 값을 가져옵니다. 값이 존재하지 않는 경우 defaultValue를 반환합니다.
  • orElseGet(supplier): Optional에 저장된 값을 가져옵니다. 값이 존재하지 않는 경우 supplier가 제공하는 값을 반환합니다.
  • isPresent() 메소드는 Optional 인스턴스가 값을 포함하고 있는지를 확인하는 메소드입니다. 값이 존재하면 true를 반환하고, 값이 존재하지 않으면 false를 반환합니다.
Optional<String> optional = Optional.of("Hello, World!"); 
System.out.println(optional.get()); // 출력: Hello, World!  

optional = Optional.empty(); 
System.out.println(optional.orElse("Default Value")); // 출력: Default Value  

optional = Optional.empty(); 
System.out.println(optional.orElseGet(() -> "Generated Value")); // 출력: Generated Value  

Optional<String> optional = Optional.of("Hello, World!"); 
System.out.println(optional.isPresent()); // 출력: true  

optional = Optional.empty();
System.out.println(optional.isPresent()); // 출력: false

옵셔널 활용

Optional은 주로 메소드의 반환 값이 null일 수도 있는 경우, null 대신 Optional을 반환하도록 사용합니다. 이렇게 하면 메소드를 호출하는 측에서는 반환 값이 null인지 아닌지를 체크하지 않아도 되므로 코드의 가독성을 향상시킬 수 있습니다.

public Optional<String> findUserById(String id) {    
// 사용자를 찾는 로직     
// 사용자를 찾지 못한 경우 Optional.empty()를 반환     
	return Optional.empty(); 
 }  
 
 Optional<String> user = findUserById("1234"); 
 
 if (user.isPresent())  
 	System.out.println(user.get()); 
 else   
    System.out.println("사용자를 찾지 못했습니다.");

이처럼 Optional은 null을 직접 다루는 것을 피하고자 할 때, 특히 메소드의 반환 값이 null일 수도 있는 경우에 유용하게 사용할 수 있습니다.

orElseGet() 메소드와 Supplier

orElseGet() 메소드는 Optional 인스턴스가 값을 포함하고 있으면 그 값을 반환하고, 값이 존재하지 않으면 Supplier 인터페이스를 통해 제공된 값을 반환합니다.

Supplier 인터페이스는 Java 8부터 도입된 함수형 인터페이스로, 입력값은 없고 반환값만 있는 함수를 정의할 때 사용됩니다. orElseGet() 메소드에서는 Supplier를 통해 Optional의 값이 없을 때 대신 반환할 값을 정의합니다.

Optional<String> optional = Optional.of("Hello, World!"); 
System.out.println(optional.orElseGet(() -> "Default Value")); // 출력: Hello, World!  

optional = Optional.empty(); 
System.out.println(optional.orElseGet(() -> "Default Value")); // 출력: Default Value

위 코드에서 () -> "Default Value" 부분이 Supplier 인터페이스를 구현한 람다 표현식입니다. 이 람다 표현식은 입력값 없이 "Default Value"라는 문자열을 반환하는 함수를 정의하고 있습니다. 따라서 orElseGet() 메소드는 Optional의 값이 존재하지 않을 때 "Default Value"를 반환하게 됩니다.

 

주의 및 참고

 

Optional 객체 생성 최소화

Optional 객체는 필요할 때만 생성하는 것이 좋다. Optional 객체를 불필요하게 생성하면 메모리 사용량이 증가하고, 성능이 저하될 수 있다. 따라서 메소드에서 Optional을 반환할 때는 가능한 빈 Optional을 재사용하는 것이 좋다.

// 좋은 예
public Optional<String> getOptionalGood() {     
	return Optional.empty(); 
}  

// 나쁜 예 
public Optional<String> getOptionalBad() {     
	return Optional.ofNullable(null); 
 }

Optional 반환값의 null 체크

Optional을 반환하는 메소드를 호출한 후, 반환값을 null로 체크하지 않도록 주의해야 한다. Optional을 반환하는 메소드는 null 대신 빈 Optional을 반환하므로, 반환값의 null 체크는 불필요! OptionalisPresent(), isEmpty(), orElse(), orElseGet() 등의 메소드를 사용하여 Optional의 값을 안전하게 처리하는게 좋다 !

// 좋은 예 
Optional<String> optional = getOptional(); 
if (optional.isPresent()) {     
	System.out.println(optional.get()); 
}  
    
    
// 나쁜 예 
Optional<String> optional = getOptional(); 
if (optional != null) {     
	System.out.println(optional.get()); 
}

Optional의 get() 메소드 사용 주의

Optionalget() 메소드는 Optional에 값이 존재할 때만 사용해야 한다. 값이 존재하지 않는데 get() 메소드를 호출하면 NoSuchElementException 발생. get() 메소드를 호출하기 전에 항상 isPresent() 메소드를 사용하여 값의 존재 여부를 확인하거나, orElse(), orElseGet() 등의 메소드를 사용하여 값이 없을 때의 대체 값을 지정하는 것이 좋다.

// 좋은 예 
Optional<String> optional = getOptional(); 
if (optional.isPresent()) {     
	System.out.println(optional.get()); 
}  

// 나쁜 예 
Optional<String> optional = getOptional(); 
System.out.println(optional.get());

Optional의 이점을 최대한 활용하여 사용하자!

 

 

 

 

참고 블로그

 

[SPSP] Bellman Ford

단일 최단경로를 구하는 알고리즘인 Bellman Ford알고리즘에 대해 정리하고 직접 구현해보는 글

gowoonsori.com

 

Java Optional 바르게 쓰기

Java Optional 바르게 쓰기Brian Goetz는 스택오버플로우에서 Optional을 만든 의도에 대해 다음과 같이 말했다. … it was not to be a general purpose Maybe type, as much as many people would have liked us to do so. Our intention w

homoefficio.github.io

 

[Java8] Optional 이란?

이번에는 Java 8에 추가된 새로운 인터페이스 Optional에 정리할 것이다. 1. Optional 이란? 오직 값이 1개가 들어있을 수도 없을 수도 있는 컨테이너 (1) Optional 등장 배경 먼저 Java 8 이전에 null 값을 체

backendcode.tistory.com