
오늘은 Optional에 대해서 알아보자
Optional
Java8에서 나온 문법으로 NullPointerException(NPE)을 방지하도록 도와주는 클래스이다. Optional <T>을 이용하여 사용할 수 있으며 null이 올 수 있는 값을 감싸는 Wrapper 클래스로 나타낸다. 아래 코드와 같이 값을 저장하기 때문에, 참조하더라도 NPE가 발생하지 않도록 도와준다.
public final class Optional<T> {
// If non-null, the value; if null, indicates no value is present
private final T value;
...
}
사용방법
- Optional.empty() : 값이 null인 경우
Optional은 Wrapper 클래스이기 때문에 값이 없을 수도 있는데, 이때 Optional.empty()로 생성할 수 있다.
Optional<String> optional = Optional.empty();
System.out.println(optional); // Optional.empty
System.out.println(optional.isPresent()); // false
- Optional.of() : 값이 null이 아닐 경우
만약 어떤 데이터가 절대 null이 아니라면, Optional.of()을 통해 값을 가져올 수 있다. 만약 Optional.of()에 null을 저장하려고 하면 NullPointerException이 발생한다.
Optional<String> optional = Optional.of("MyName");
- Optional.ofNullable() : 값이 null일수도, 아닐 수도 있는 경우
만약 어떤 데이터가 null 혹은 데이터가 올 경우에는 Optional.ofNullable로 생성이 가능하다. 이후 orElse, orElseGet 메서드를 이용하여 값을 가져올 수 있다.
// Optional의 value는 값이 있을 수도 있고 null 일 수도 있다.
Optional<String> optional = Optional.ofNullable(getName());
String name = optional.orElse("anonymous"); // 값이 없다면 "anonymous" 를 리턴
orElse와 orElseGet 차이
- orElse : 파라미터로 값을 받는다.
- orElseGet: 파라미터로 함수형 인터페이스(함수)를 받는다.
해당 메서드를 이렇게 구별한 이유는 작동방식 때문인데 그 예시로 아래 코드를 살펴보자.
public void findUserEmailOrElse() {
String userEmail = "Empty";
String result = Optional.ofNullable(userEmail)
.orElse(getUserEmail());
System.out.println(result);
}
public void findUserEmailOrElseGet() {
String userEmail = "Empty";
String result = Optional.ofNullable(userEmail)
.orElseGet(this::getUserEmail);
System.out.println(result);
}
private String getUserEmail() {
System.out.println("getUserEmail() Called");
return "JHeaon@tistory.com";
}
=================================================
// orElse인 경우
getUserEmail() Called
Empty
// orElseGet인 경우
Empty
OrElse인 경우 아래와 같이 동작한다.
- Optional.ofNullable로 Optional 객체 생성
- getUserEmail()이 실행되어 반환값을 orElse 파라미터로 전달
- orElse가 호출되어 "EMPTY"가 Null이 아니므로 "EMPTY"을 가짐
하지만 이 경우에 getUserEmail() 함수가 무조건 실행이 되는데 이는 추후 큰 문제를 불러일으킬 수 있다. 예를 들어서 유저 이메일을 등록하는 코드를 작성했다고 가정한다. 이때 userEmail은 Unique 한 값으로 작성되었다고 가정한다.
public void findByUserEmail(String userEmail) {
// orElse에 의해 userEmail이 이미 존재해도 유저 생성 함수가 호출되어 에러 발생
return userRepository.findByUserEmail(userEmail)
.orElse(createUserWithEmail(userEmail));
}
private String createUserWithEmail(String userEmail) {
User newUser = new User(userEmail);
return userRepository.save(newUser);
}
이 경우 조회결과에 무관하게 createUserWithEmail() 함수가 반드시 실행되게 된다. 하지만 DB에서 userEamil은 Unique로 설정되어 있기 때문에 해당 코드를 실행 시 오류가 난다.
따라서 이러한 문제를 해결하기 위해 나온 함수가 orElseGet()이다. orElseGet()은 파라미터로 함수 자체를 전달받아 함수가 반드시 실행되는 것을 막아준다.
- Optional.orElseThrow() : 값이 null 일 때, 예외를 던지고 싶을 경우
Optional<String> nameOpt = Optional.ofNullable(getName());
String result = nameOpt.orElseThrow(CustomUpperCaseExcpetion::new)
.toUpperCase();
'Programing Language > Java' 카테고리의 다른 글
Lambda Expression (0) | 2024.06.05 |
---|---|
Enum (0) | 2024.05.31 |
Stream (0) | 2024.05.09 |
Thread (수정중) (1) | 2024.05.01 |
String 객체 (0) | 2024.04.30 |