일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 프로그래머스
- ac 5430번
- hash
- 프로그래머스 자바
- HashSet
- 백준 2473번 세 용액 - java
- mysql hy000 에러
- append
- Stack
- 프로그래머스 java
- 백준 1541
- Java
- 18111번 마인크래프트 - java 구현
- 백준 3190번
- 백준 14938번 서강그라운드
- StringBuilder
- 백준 1197번 최소 스패닝 트리 - java
- 백준 2467번 용액 자바 - 이분탐색
- map
- dp
- 백준 1806번 부분합 java
- StringTokenizer
- 백준 1043번 거짓말 - java 분리 집합
- 백준 1647번 도시 분할 계획 - java
- replace()
- kotlin
- toUpperCase
- 코틀린기초
- 최소 힙 1927
- HashMap
- Today
- Total
말하는 컴공감자의 텃밭
Java - Optional<> 본문
1. Optional이란 무엇인가?
Optional은 Java 8에서 추가된 클래스다.
이 클래스는 null이 들어올 수 있는 값을 감싸는 컨테이너 역할을 한다.
Optional을 사용하면 null 값을 직접 다루지 않고도 null 처리를 할 수 있다.
예를 들어, 다음과 같은 JPA 메서드에서 Optional을 사용할 수 있다.
Optional<StudyMember> findByMemberAndStudy(Member member, Study study);
현재 개발중인 프로젝트에서 Jpa 메서드를 작성할때도 사용했었다.
2. 왜 Optional을 사용하는가?
2.1 NullPointerException 방지 일명 "NPE"
Optional을 사용하면 null 값을 직접 다루지 않기 때문에 NullPointerException을 방지할 수 있다.
이는 코드의 안정성을 높여주고, 예외 처리 코드를 줄여준다.
Optional<StudyMember> studyMemberOptional = findByMemberAndStudy(member, study);
if (studyMemberOptional.isPresent()) {
StudyMember studyMember = studyMemberOptional.get();
// 값 처리
} else {
System.out.println("없는 멤버에요!: " + activeMember.getName());
}
2.2 코드 가독성 향상
null 체크를 위한 if 문을 줄이고, 의도를 명확하게 드러내는 코드를 작성할 수 있다.
Optional을 사용하면 값이 존재하는지 여부를 명시적으로 표현할 수 있다.
activeStudyMembers.forEach(activeMember -> {
System.out.println("활동중인 멤버: " + activeMember.getName());
});
2.3 함수형 프로그래밍 스타일 지원
Optional은 함수형 프로그래밍 스타일을 지원한다. map, flatMap, filter 등 다양한 메서드를 제공하여, 값이 존재하는 경우에만 해당 연산을 수행할 수 있게 해준다.
Optional<String> memberName = studyMemberOptional.map(StudyMember::getName);
memberName.ifPresent(System.out::println);
Optional<StudyMember> activeStudyMember = studyMemberOptional
.filter(studyMember -> studyMember.getStatus() == Status.ACTIVE);
activeStudyMember.ifPresent(activeMember -> {
System.out.println("현재 활동중인 스터디 멤버: " + activeMember.getName());
});
3. Optional의 문제점
3.1 남용 문제
Optional을 남용하면 오히려 코드가 복잡해질 수 있다.
모든 nullable 값을 Optional로 처리하려고 하면, 불필요한 객체 생성과 메서드 호출이 늘어나 성능에 악영향을 줄 수 있다.
3.2 직렬화 문제
Optional은 Serializable 인터페이스를 구현하지 않는다.
따라서, 직렬화가 필요한 상황에서는 사용할 수 없다.
3.3 컬렉션과의 조합 문제
Optional을 컬렉션 내부에 사용하는 것은 권장되지 않는다.
대신, 빈 컬렉션을 반환하거나 특별한 값 객체를 사용하는 것이 더 바람직하다.
4. 고려해야 할 사항
4.1 Optional의 반환
메서드의 반환 타입으로 Optional을 사용하는 것은 좋지만, 필드 타입으로 Optional을 사용하는 것은 피해야 한다.
Optional은 메서드 시그니처에서 의도를 명확히 하기 위해 사용되는 것이지, 객체의 상태를 표현하는 데 사용되는 것은 아니다.
4.2 기본 값 제공
Optional의 orElse나 orElseGet 메서드를 사용하여 기본 값을 제공할 수 있다.
이를 통해 null 대신 기본 값을 사용하는 코드를 간단하게 작성할 수 있다.
StudyTitle studyTitle = studyTitleOptional.orElse(new studyTitle());
System.out.println("기존의 제목: " + studyTitle.getName());
studyTitleOptional이 비어 있을 때 new StudyTitle() 객체를 반환하여 사용한다.
이 방법은 Optional이 비어 있지 않더라도 new StudyTitle() 객체가 항상 생성된다.
StudyTitle defaultStudyTitle = new StudyTitle();
defaultStudyTitle.setName("스터디 제목을 입력하세요");
StudyTitle studyTitle = studyTitleOptional.orElse(defaultstudyTitle);
System.out.println("스터디 제목: " + studyTitle.getName());
기본값으로 사용할 객체를 미리 생성하고, orElse를 통해 studyTitleOptional이 비어 있을 때 이 기본 객체를 반환한다.
이 방법은 미리 생성된 객체를 사용하므로, Optional이 비어 있지 않더라도 객체 생성이 추가로 발생하지 않는다.
Optional<StudyTitle> studyTitleOptional = findStudyTitleBySomeCriteria();
StudyTitle studyTitle = studyTitleOptional.orElseGet(() -> new StudyTitle());
System.out.println("기존의 제목: " + studyTitle.getName());
4.3 스트림과 함께 사용
스트림과 함께 사용하면 Optional을 더욱 효율적으로 활용할 수 있다.
예를 들어, Optional을 스트림으로 변환하여 처리할 수 있다.
List<StudyMember> activeStudyMembers = studyMemberOptional
.stream()
.filter(studyMember -> studyMember.getStatus() == Status.ACTIVE)
.collect(Collectors.toList());
activeStudyMembers.forEach(activeMember -> {
System.out.println("활동중인 스터디 멤버: " + activeMember.getName());
});
4.4 예외 처리
Optional의 orElseThrow 메서드를 사용하여 예외를 던질 수 있다.
이를 통해 값이 존재하지 않을 때 명확하게 예외를 처리할 수 있다.
StudyMember studyMember = studyMemberOptional.orElseThrow(() ->
new NoSuchElementException("존재하지 않는 멤버입니다"));
Optional은 null 처리를 더욱 안전하고 명확하게 해주는 유용한 도구지만, 남용하지 않도록 주의해야 한다.
적절한 상황에서 Optional을 사용하여 코드의 가독성과 안정성을 높여보자.
'백엔드 > Java' 카테고리의 다른 글
최소 신장 트리를 위한 프림, 크루스칼 알고리즘 (1) | 2024.08.28 |
---|---|
알고리즘 시간관련 - 시간 제한, 시간 복잡도 (0) | 2024.08.08 |
Java clone - 얕은복사 깊은복사 (0) | 2024.02.20 |
Java - BufferedReader, StringTokenizer, BufferedWriter (1) | 2023.12.02 |