JavaRush /Java Blog /Random-KO /커피 브레이크 #161. Optional을 사용하여 Java에서 Null을 처리하는 방법

커피 브레이크 #161. Optional을 사용하여 Java에서 Null을 처리하는 방법

Random-KO 그룹에 게시되었습니다
출처: 중간 이 기사는 Java 코드 작업 시 Optional의 목적을 더 잘 이해하는 데 도움이 될 것입니다. 커피 브레이크 #161.  Optional을 사용하여 Java에서 Null을 처리하는 방법 - 1처음 Java 코드 작업을 시작했을 때 Optional을 사용하라는 조언을 자주 받았습니다. 그러나 당시에는 null 값 처리를 구현하는 것보다 Optional을 사용하는 것이 더 나은 이유를 거의 이해하지 못했습니다. 이 기사에서는 우리 모두가 Optional을 더 많이 사용해야 하는 이유와 코드 품질에 해로운 코드를 과도하게 선택하는 것을 방지하는 방법을 공유하고 싶습니다.

선택 사항이란 무엇입니까?

Optional 매개변수는 객체를 전달하고 다양한 API에서 Null 참조를 처리할 수 있도록 하는 데 사용됩니다 . 코드 조각을 살펴보겠습니다.
Coffee coffee = new Coffee();
Integer quantity = coffee.getSugar().getQuantity();
Sugar 객체 의 인스턴스에서 설탕을 얻는 Coffee 인스턴스가 있습니다 . Coffee 생성자 에 수량 값이 설정되지 않았다고 가정하면 Coffee.getSugar ().getQuantity()는 NullPointerException 을 반환합니다 . 물론 문제를 해결하기 위해 언제든지 좋은 null 검사를 사용할 수 있습니다.
Coffee coffee = new Coffee();
Integer quantity = 0;
if (coffee.getSugar() != null) {
  quantity = coffee.getSugar().getQuantity();
}
이제 모든 것이 괜찮은 것 같습니다. 그러나 Java 코드를 작성할 때는 null 검사를 구현하지 않는 것이 좋습니다 . Optional을 사용하여 이 작업을 어떻게 수행할 수 있는지 살펴보겠습니다.

선택사항 생성 방법

Optional 개체를 만드는 방법에는 세 가지가 있습니다.
  • of(T value) — null이 아닌 Optional 개체의 인스턴스화입니다. null 객체를 참조하기 위해 of()를 사용하면 NullPointerException이 발생한다는 점에 유의하세요 .

  • ofNullable(T value) - null이 될 수 있는 객체에 대한 Optional 값을 생성합니다.

  • empty() - null 에 대한 참조를 나타내는 Optional 인스턴스를 만듭니다 .

// пример использования Optional.of(T Value)
String name = "foo";
Optional<String> stringExample = Optional.of(name)
// пример использования Optional.ofNullable(T Value)
Integer age = null;
Optional<Integer> integerExample= Optional.ofNullable(age)
// пример использования Optional.empty()
Optional<Object> emptyExample = Optional.empty();
따라서 Optional 개체가 있습니다. 이제 Optional의 두 가지 주요 메서드를 살펴보겠습니다.
  • isPresent() - 이 메소드는 Optional 객체에 null이 아닌 값이 포함되어 있는지 여부를 알려줍니다.

  • get() - 현재 값으로 Optional 값을 검색합니다. 빈 Optional에 대해 get()을 호출하면 NullPointerException이 발생한다는 점에 유의하세요 .

Optional로 작업할 때 get()isPresent() 만 사용하면 놓치게 된다는 점에 유의하세요 ! 이를 이해하기 위해 이제 위의 예를 Optional로 다시 작성해 보겠습니다.

Optional을 사용하여 Null 검사 개선

그렇다면 위의 코드를 어떻게 개선할 수 있을까요? Optional을 사용하면 isPresent()를 사용하여 객체의 존재를 이해 하고 get()을 사용하여 객체를 검색 할 수 있습니다 . Coffee.getSugar() 의 결과를 Optional 로 패키징하고 isPresent() 메서드를 사용하여 시작해 보겠습니다 . 이는 getSugar()가 null을 반환하는지 확인하는 데 도움이 됩니다.
Coffee coffee = new Coffee();
Optional<String> sugar = Optional.ofNullable(coffee.getSugar());
int quantity = 0;
if (sugar.isPresent()) {
  Sugar sugar = sugar.get();
  int quantity = sugar.getQuantity();
}
이 예를 보면, Coffee.getSugar() 의 결과 를 Optional로 패키징하는 것은 어떤 가치도 추가하지 않는 것처럼 보이지만 오히려 번거로움을 더합니다. Optional 클래스에서 제가 가장 좋아하는 기능을 사용하여 결과를 개선할 수 있습니다.
  • map(Function<? super T,?extends U> mapper) - Optional에 포함된 값을 제공된 함수에 매핑합니다. Optional 매개변수가 비어 있으면 map()은 Optional.empty()를 반환합니다 .

  • orElse(T other)는 get() 메소드 의 "특별한" 버전입니다 . Optional에 포함된 값을 가져올 수 있습니다. 그러나 빈 Optional의 경우 orElse() 메소드에 전달된 값을 반환합니다 .

이 메서드는 Optional 인스턴스에 포함된 값을 반환합니다. 그러나 Optional 매개변수가 비어 있으면(값이 없음을 의미함) orElse()는 기본값으로 알려진 메소드 시그니처에 전달된 값을 반환합니다.
Coffee coffee = new Coffee();

Integer quantity = Optional.ofNullable(coffee.getSugar())
    .map(it -> it.getQuantity())
    .orElse(0);
정말 멋지네요. 적어도 저는 그렇게 생각합니다. 이제, 값이 비어 있는 경우 기본값을 반환하지 않으려면 일종의 예외를 발생시켜야 합니다. orElseThrow(Supplier<? 확장 X> 예외Supplier)는 Optional 매개변수에 포함된 값을 반환하거나 Optional이 비어 있는 경우 예외를 발생시킵니다.
Coffee coffee = new Coffee();

Integer quantity = Optional.ofNullable(coffee.getSugar())
  .map(it -> it.getQuantity())
  .orElseThrow(IllegalArgumentException::new);
보시다시피 Optional은 다음과 같은 몇 가지 장점을 제공합니다.
  • null 검사를 추상화합니다.
  • null 개체를 처리하기 위한 API를 제공합니다.
  • 달성되는 것을 표현하는 선언적 접근 방식을 허용합니다.

Optional을 효과적으로 사용하는 방법

내 작업에서는 메서드가 "결과 없음" 상태를 반환할 수 있는 경우 반환 유형으로 Optional을 사용합니다. 나는 보통 메소드의 반환 유형을 정의할 때 이를 사용합니다.
Optional<Coffee> findByName(String name) {
   ...
}
때로는 이것이 필요하지 않습니다. 예를 들어, Sugar 클래스 의 getQuantity() 와 같이 int를 반환하는 메서드가 있는 경우 결과가 null 이면 해당 메서드는 "수량 없음"을 나타내기 위해 0을 반환할 수 있습니다. 이제 이를 알면 Coffee 클래스 의 Sugar 매개변수가 Optional로 표현될 수 있다고 생각할 수 있습니다. 언뜻 보기에는 이론상 설탕이 커피에 포함될 필요가 없기 때문에 이는 좋은 생각처럼 보입니다. 그러나 이것이 Optional을 사용 하지 않는 경우에 대해 언급하고 싶은 부분입니다 . 다음 시나리오에서는 Optional을 사용하지 않아야 합니다.
  • DTO 와 같은 POJO 의 매개변수 유형 . Optional은 직렬화할 수 없으므로 POJO에서 이를 사용하면 객체를 직렬화할 수 없게 됩니다.

  • 메서드 인수로. 메서드 인수가 null 일 수 있는 경우 순수 코드 관점에서 보면 Optional을 전달하는 것보다 null을 전달하는 것이 더 좋습니다. 또한 null 메서드 인수가 없는 경우를 추상적으로 처리하기 위해 오버로드된 메서드를 만들 수 있습니다.

  • 누락된 Collection 개체를 나타냅니다. 컬렉션은 비어 있을 수 있으므로 빈 Set 또는 List 와 같은 빈 Collection을 사용하여 값이 없는 컬렉션을 나타내야 합니다.

결론

Optional은 Java 라이브러리에 강력한 추가 기능이 되었습니다. 존재하지 않을 수 있는 객체를 처리하는 방법을 제공합니다. 따라서 남용의 함정에 빠지지 않고 방법을 개발할 때 이를 고려해야 합니다. 예, null 검사와 null 처리를 구현하는 훌륭한 코드를 작성할 수 있지만 Java 커뮤니티에서는 Optional을 선호합니다. 누락된 값을 처리하는 방법을 효과적으로 전달하고 지저분한 Null 검사보다 읽기가 훨씬 쉬우며 장기적으로 코드의 버그가 줄어듭니다.
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION