선택 사항이란 무엇입니까?
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을 사용하여 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() 메소드에 전달된 값을 반환합니다 .
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을 사용하여 값이 없는 컬렉션을 나타내야 합니다.
GO TO FULL VERSION