Optional 클래스가 등장하기 전에는 Java에서는 null 처리가 항상 문제였습니다. null을 마주하는 경우 프로그램 실행 중에 NullPointerException(NPE)로 인해 프로그램이 죽는 경우가 자주 있습니다.
NullPointerException(NPE) 란❓
Java에서 가장 흔한 런타임 오류 중 하나로, null 참조를 가진 객체의 메서드나 필드에 접근하려고 할 때 발생합니다.
NPE가 발생하는 간단한 for문은 다음과 같습니다.
public class ForLoopNPEExample {
public static void main(String[] args) {
String[] array = null;
for (String element : array) { // 여기서 NPE 발생
System.out.println(element);
}
}
}
Optional이란 ❓
Java의 Optional 클래스는 java.util 패키지에 포함되어 있으며, 값이 없는 경우를 표현하기 위한 클래스입니다.
Optional클래스는 값이 있을 수 도 있고, 없을 수 도 있습니다.
Optional 클래스는 주로 NPE 에러를 피하기 위해 사용되며 코드의 안정성을 높이며 가독성을 향상시킵니다.
Optional 객체 생성
Optional 객체를 생성하는 방법은 크게 3가지 경우가 있습니다.
Optional.empty()
Optional emptyOptional = Optional.empty();
Optional<String> nonEmptyOptional = Optional.of("Hello");
Optional.empty() 메서드는 값을 갖지 않은 빈 Optional 객체를 생성합니다.
Optional.of(value)
Optional<String> nonEmptyOptional = Optional.of("Hello");
Optional.of(value)는 null이 아닌 경우에 사용합니다. 만약 값이 null이면 NPE가 발생합니다.
Optional.ofNullable(value)
Optional nullableOptional = Optional.ofNullable(null);
Optional<String> nullableOptional = Optional.ofNullable(null);
Optional.ofNullable(value)는 값이 null일 수도 있는 경우에 사용합니다. 만약 값이 null일 경우 Optional.empty()를 반환합니다.
import java.util.Optional;
public class OptionalTest {
public static void main(String[] args) {
String str = "Hello, World!"; // null이 아닌 값을 가지는 문자열 변수
Optional<String> optionalStr = Optional.of(str);
System.out.println(optionalStr); // 결과: Optional[Hello, World!]
String nullStr = null;
Optional<String> optionalNullStr = Optional.ofNullable(nullStr);
System.out.println(optionalNullStr); // 결과: Optional.empty
Optional<String> emptyOptional = Optional.empty();
System.out.println(emptyOptional); // 결과: Optional.empty
}
}
optional 값 존재여부 확인
Optional을 사용하면 Optional의 값을 접근할 때 Optional.get() 메서드를 통해 접근을 할 수 있습니다.
당연하게도 Optional의 값은 값이 있을 수 도 있고 없을 수 도 있기 때문에 반드시 get()을 통해 요소에 접근을 할 때 값이 있는지 검증을 하고 접근을 해야 합니다.
만약 값이 없을 경우에 접근을 하게 된다면 당연하게도 NPE에러가 발생합니다.
Optional 클래스는 값 존재 여부를 확인할 수 있는 메서드를 다음과 같이 제공합니다.
isPresent()
if (optional.isPresent()) {
System.out.println(optional.get());
}
isPresent()는 값이 존재하는지 확인합니다. 존재하면 true, 존재하지 않으면 false를 반환합니다.
isEmpty()
String imNull = null;
Optional<String> opt = Optional.ofNullable(imNull);
Optional<String> opt1 = Optional.ofNullable("Hello");
System.out.println(opt.isEmpty()); // true
System.out.println(opt1.isEmpty()); // false
isPresent()는 값이 없는지 확인합니다. 존재하지 않으면 true, 존재하면 false를 반환합니다.
기본값, 대체값 제공
Optional 클래스에는 Optional객체가 가지고 있는 값이 null 일 경우에 어떠한 값으로 대체하여 반환해줘야 하는지 정의하는 메서드가 있습니다.
orElse(T other)
Optional nullableOptional = Optional.ofNullable(null);
String value1 = nullableOptional.orElse("null이있습니다.");
String name1 = Optional.ofNullable("A").orElse("test");
System.out.println(name1); // 결과 : A
System.out.println(value1); // 결과 : null이있습니다.
orElse()는 값이 없으면(null) 기본값을 반환합니다.
위 코드에서는 nullalbeOptional은 null이므로 기본값인 "null이 있습니다."가 반환됩니다. 그리고 name1은 null이 아니기 때문에 A가 반환되는 것을 볼 수 있습니다.
orElseGet(Supplier <? extends T> other )
String value1 = nullableOptional.orElseGet(() -> "Default Value from Supplier");
String value2 = Optional.ofNullable("A").orElseGet(() -> "test");
System.out.println(value1); // 결과 : Default Value from Supplier
System.out.println(value2); // 결과 : A
orElseGet()은 값이 없으면 Supplier를 통해 기본값을 반환합니다.
Supplier 란 :인수를 받지 않고결과를 반환하는 함수형 인터페이스입니다
orElse() 사용 예제
import java.util.Optional;
public class OrElseExample {
public static void main(String[] args) {
Optional<String> optional = Optional.empty();
String defaultValue = "Default Value";
// 값이 없을 때와 있을 때 모두 기본값을 생성함
String result = optional.orElse(getDefaultValue());
System.out.println(result); // 출력: Default Value
}
public static String getDefaultValue() {
System.out.println("Generating default value...");
return "Default Value";
}
}
위 코드에서 orElse() 메서드는 값이 없을 때에는 getDefaultValue() 메서드를 호출하여 기본값을 생성하게 됩니다.
그러나 값이 있는 경우에도 getDefaultValue() 메서드가 호출되어 결과는 다음과 같이 나오게 됩니다.
Generating default value...
Default Value
orElseGet() 사용 예제
import java.util.Optional;
public class OrElseGetExample {
public static void main(String[] args) {
Optional<String> optional = Optional.empty();
String defaultValue = "Default Value";
// 값이 없을 때만 기본값을 생성함
String result = optional.orElseGet(() -> getDefaultValue());
System.out.println(result); // 출력: Default Value
}
public static String getDefaultValue() {
System.out.println("Generating default value...");
return "Default Value";
}
}
orElseGet 메서드는 값이 없을 때에만 getDefaultValue() 메서드를 호출하여 기본값을 생성합니다. 값이 있는 경우에는 getDefaultValue() 메서드를 호출하지 않습니다.
그렇기 때문에 위 코드에서는 optional에 빈 객체를 생성하여 저장하고, 값이 없기 때문에 orElseGet() 메서드를 호출하여 기본값을 생성합니다.
따라서 결과는 다음과 같습니다.
Generating default value...
Default Value
orElse와 orElseGet의 차이점을 정리하자면 다음과 같습니다.
- orElse
- Optional의 값이 NULL이든 아니든 항상 호출합니다.
- 그에 따라 Unique 한 객체들에는 주의해서 사용해야 합니다.
- 값이 미리 존재하는 경우에 사용합니다.
- orElseGet
- Optional의 값이 NULL일 경우에만 호출합니다.
- 값이 미리 존재하지 않는 거의 대부분의 경우에 사용합니다.
'Language > Java' 카테고리의 다른 글
[JAVA] contains() 메소드 알아보기 (문자열 포함 여부 확인) (0) | 2024.05.23 |
---|---|
[JAVA] Stream API에 대해 알아보기 _ Stream 최종 연산 Collect()(집계) (5/5) (1) | 2024.05.22 |
[JAVA] Stream API에 대해 알아보기 _ Stream 최종 연산(집계) (4/5) (0) | 2024.05.18 |
[JAVA] Stream API에 대해 알아보기 _ Stream 중간 연산(가공) (3/5) (0) | 2024.05.17 |
[JAVA] Stream API에 대해 알아보기 _ Stream 생성 (2/5) (0) | 2024.05.16 |