[Java] Optional 사용 TIPS !

Song_Song·2021년 11월 19일
0
post-custom-banner

최근 개발을 할 때 Optional을 사용하는 경우가 많아졌다. Optional은 잘 쓰면 굉장히 파워풀한 기능이지만 잘못 사용하면 낭비가 될수 있다.
이왕 사용하는 김에 잘 사용하고 싶어서 Optional 사용 tip을 정리를 해보았다.

1. Optional 변수에 빈 값을 할당할 때는 Optional.empty()를 사용하자

Optional<Sample> sampleVar = null; // Bad!

Optional<Sample> sampleVar = Optional.empty(); // Good!

2. Optional.get()을 사용할 때는 값이 있는지 먼저 체크하자

if (sampleVar.isPresent()){
    sampleVar.get();
}else{
  // 
}

3. 고정값을 리턴할 때는 orElse()를 사용하자. 또한, isPresent()-get() 보다는 orElse()를 사용하자.

// Bad!
public static final String NO_VALUE = "UNKNOWN";  
 
pulic String findSample(Integer id){

    Optional<String> sampleVal = ... ;

    if (status.isPresent()) {
        return status.get();
    } else {
        return NO_VALUE;
    }
}  
// Good!
public static final String NO_VALUE = "UNKNOWN";  
 
pulic String findSample(Integer id){

    Optional<String> sampleVal = ... ;

    return sampleVal.orElse(NO_VALUE);
    }
}  

4. 고정값이 아닌 값을 사용할 시에는 orElse() 대신 orElseGet()을 사용하자.

orElse() 를 사용할 때, 옵셔널 값이 빈 값이 아니라서 orElse() 까지 도달하지 않더라도 그 내부에 있는 객체가 생성이 된다.

// Bad!
 
pulic String findSample(Integer id){

    Optional<String> sampleVal = ... ;

    return sample.orElse(new Sample()); // sample이 빈 값이여도 orElse()을 호출하여 객체를 생성한다 => 낭비
}  
// Good!
 
pulic String findSample(Integer id){

    Optional<String> sampleVal = ... ;

    return sample.orElseGet(Sample::new); // sample이 빈 값이면 orElseGet()은 호출되지 않는다.
}  
}  

orElseGet() 은 orElse() 와는 다르게 Supplier 함수형 인터페이스를 인자로 받기 때문에 람다식 혹은 메소드 레퍼런스를 인자로 넘겨주면 된다.

5. java.util.NoSuchElementException을 발생시키고 싶으면 orElseThrow()를 사용하자 (Java 10)

public String findSample(Integer id) {

    Optional<String> sample = ... ; 

    return sample.orElseThrow();
}  

자바 버전이 8 혹은 9라면 아래와 같은 방법으로 사용 가능하다.

public String findSample(Integer id) {

    Optional<String> sample = ... ; 

    return sample.orElseThrow(NoSuchElementException::new); 
}  

6. Optional을 사용하고 null을 참조하는 경우가 있을 땐 orElse(null)을 사용하자

// Bad!
 
Optional<Sample> sampleClass = ... ;

if (sampleMethod.isPresent()){
    myMethod.invoke(sampleClass.get(), ...);
}else{
	myMethod.invoke(null, ...);  
}
// Good!
 
Optional<Sample> sampleClass = ... ;

myMethod.invoke(sampleClass.get().orElse(null), ...);  

7. Optional의 isPresent()를 사용할 때, 존재하지 않는 경우에는 아무 것도 하지 말자(else 조건을 사용하지 말자)

// Bad!
 
Optional<Sample> sampleClass = ... ;

if (sampleMethod.isPresent()){
    System.out.println("Sample: " + sampleMethod.get());
}
// Good!
 
Optional<Sample> sampleClass = ... ;

sample.ifPresent(System.out::println); 

8. Optional의 isPresent()를 사용할 때, else 조건을 사용하고 싶을 땐 Optional.ifPresentOrElse()를 사용하자 (Java 9)

// Bad!
 
Optional<Sample> sampleClass = ... ;

if (sampleMethod.isPresent()){
    System.out.println("Sample: " + sampleMethod.get());
}else{
 	System.out.println("Status not found"); 
}  
// Good!
 
Optional<Sample> sampleClass = ... ;

sample.ifPresentOrElse(
  System.out::println, // if 절의 action
  () -> System.out.println("Status not found") // else 절의 action
); 

9. Optional이 empty일 때, 다른 Optional을 리턴하고 싶다면 Optional.or() 을 사용하자(Java9)

Optional.or()는 orElse()나 orElseGet()과는 다르게 Optional을 리턴한다

// Good!
 
Optional<Sample> sampleClass = ... ;
Optional<Sample> dafaultSample = Optional.of("DEFAULT");

return sampleClass.or(() -> defaultSample);  

10. Lambda를 사용할 땐 Optional.orElse / orElseXXX를 사용하자

// Bad!
 
Optional<Sample> sampleClass = sampleClasses.stream()
  				     .filter(x -> p.getNumber < num)
                                     .findFirst();

if (sampleClass.isPresent()) {
    return sample.get().getName();
} else {
    sampleClass "NOT FOUND";
}
// Good!
 
Optional<Sample> sampleClass = ... ;

Optional<Sample> sampleClass = sampleClasses.stream()
  				     .filter(x -> p.getNumber < num)
                                     .findFirst();
                                     .orElse("NOT FOUND");
profile
성장을 위한 정리 블로그
post-custom-banner

0개의 댓글