Optional 개요
- Java 8에서 도입된 클래스로, null이 될 수 있는 객체를 감싸는 래퍼(wrapper)
- “값이 있을 수도 없을 수도 있음”을 명시적으로 표현하기 위해 도입된 클래스
- 명시적으로 null 가능성을 표현하고, NullPointerException을 방지
- Optional은 최대 하나의 요소를 포함
주의사항
- 반환 타입으로만 사용하고, 필드에는 가급적 쓰지 말기
- 메서드 매개변수로 Optional 을 사용하지 말기
- 컬렉션(Collection)이나 배열 타입을 Optional 로 감싸지 말기
- isPresent() 와 get() 조합을 직접 사용하지 않기
- orElseGet() vs orElse() 차이를 분명히 이해하기
- orElse(): 항상 계산:
즉시 평가 - orElseGet(): 값이 없을 경우에만 계산:
지연 평가
- orElse(): 항상 계산:
- 무조건 Optional 이 좋은 것은 아니다.
- “항상 값이 있는” 상황
- “값이 없으면 예외를 던지는 것”이 더 자연스러운 상황
- “흔히 비는 경우”가 아니라 “흔히 채워져 있는” 경우
- “성능이 극도로 중요한” 로우레벨 코드
- Optional 기본형 타입 지원하지만 잘 사용하지 않는다.
권장 예시
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static void main(String[] args) {
Optional<String> optStr = Optional.ofNullable("Hello");
// 1) orElse
System.out.println(optStr.orElse("Nothing"));
// 2) ifPresentOrElse
optStr.ifPresentOrElse(
System.out::println,
() -> System.out.println("Nothing")
);
// 3) map
int length = optStr.map(String::length).orElse(0);
System.out.println("Length: " + length);
}
Test Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class MemberTest {
private MemberRepository memberRepository;
@BeforeEach
void setUp() {
memberRepository = new MemberRepository();
Member member = Member.builder()
.loginId("test")
.password("test123")
.name("tester")
.build();
memberRepository.save(member);
}
@AfterEach
void tearDown() {
memberRepository.clearStore();
}
@Test
void optionalTest() {
Optional<Member> member = memberRepository.findByLoginId("test");
Optional<Member> member2 = memberRepository.findByLoginId("test2");
System.out.println("member: " + member);
System.out.println("member2: " + member2);
Member result = member.filter(v -> v.getPassword().equals("test123")).orElse(null);
Member result2 = member.filter(v -> v.getPassword().equals("test567")).orElse(null);
System.out.println("result: "+ result);
System.out.println("result2: "+ result2);
}
}
member: Optional[Member(id=1, loginId=test, name=tester, password=test123)]
member2: Optional.empty
result: Member(id=1, loginId=test, name=tester, password=test123)
result2: null