1. Optional
# Optional : 자바에서 비어있는 값인 null을 처리하기 위해 사용되는 클래스
NullPointerException 을 피하려면 null에 대한 처리를 해야 하는데, Optional을 이용하면 가독성 높은 코드를 만들 수 있다.
2. NullPointerException이 발생하는 코드
# NullPointerException : null이 들어있는 레퍼런스 변수를 대상으로 필드 참조나 메서드 호출할 때 발생
NullPointerException 을 피하려면 null이 들어올 수 있는 변수에 대한 null 체크를 진행
- src/main/java/kr/co/programmersoop/example/section_01_08/without_optional/MapRepository.java
public class MapRepository {
private Map<String, String> map = new HashMap<>();
MapRepository() {
map.put("EXIST_KEY", "value");
}
public String getValue(String key) {
return map.get(key);
}
}
Map 안에 존재하지 않는 key를 get할 때 null 반환됨
- src/main/java/kr/co/programmersoop/example/section_01_08/without_optional/WithoutOptionalExampleMain.java
public class WithoutOptionalExampleMain {
public static void main(String[] args) {
MapRepository mapRepository = new MapRepository();
String string = mapRepository.getValue("NOT_EXIST_KEY");
System.out.println("string=" + string);
// System.out.println(string.toUpperCase());
// NullPointerException을 피하려면 이렇게 Null 체크를 해야함.
if (string != null)
System.out.println(string.toUpperCase());
}
}
하지만, if문을 사용하면 코드 가독성 좋지 않음
3. Optional 사용하는 코드로 변경
1) Optional을 왜 사용하는가?
Having Optional enables me to do fluent API thingies like: stream.getFirst().orElseThrow(() -> new MyFancyException())
-> Optional을 사용하면 API 호출을 유창하게(세련되게) 할 수 있다.
출처 : https://mail.openjdk.org/pipermail/lambda-dev/2012-September/005952.html
java.util.Optional fields
mail.openjdk.org
#1 Optional 사용 : 반환된 결과에 대해 계속해서 메서드 호출하여 한 줄로 코드 작성 -> 가독성 좋음
stream.getFirst().orElseThrow(() -> new MyFancyException())
#2 Optional 미사용 : 무언가를 가져오는 행위와 가져온 결과가 null이면 예외를 던진다는 행위가 같이 묶여 있느냐, 떨어져 있느냐로 나뉘어 여러 줄로 코드 나뉨 -> 가독성 나쁨
Object obj = stream.getFirst();
// 다른 코드들 있을 수 있음
if (obj == null)
new MyFancyException();
2) Optional이 보통 하는 일
메서드 호출 결과가 null?
#1 인스턴스 생성하여 메서드 호출 계속 진행 (보통 인스턴스를 조회하거나 값을 바꾸려고 하는 경우)
#2 예외를 던짐
-> 예외 던지는 경우가 더 많음
3) Optional 인스턴스 생성 방법
3가지의 정적 팩토리 메서드를 활용
MapRepository mapRepository = new MapRepository();
Optional<String> string = mapRepository.getOptionalValue("NOT_EXIST_KEY");
// 파라미터 값이 null이면 NullPointerException 던짐 (레퍼런스 변수 참조 시점이 아닌 Optional 객체 생성 시점에 발생 : 개발자가 의도적으로 예외 발생시키는 것에 가까움)
Optional.of(string);
// 파라미터 값이 null이면 비어있는 Optional을 생성, null 아니면 값이 들어있는 Optional을 생성
Optional.ofNullable(string);
// 고의로 비어있는 Optional 객체 생성 (null 반환하는 것과 같은 효과줄 수 있음)
Optional.empty();
코드 설명)
#1 Optional.ofNullable()
Optional.ofNullable() 메서드 처럼 해당 클래스의 인스턴스 생성하는 static 메서드를, 정적 팩토리 메서드라고 한다.
- src/main/java/kr/co/programmersoop/example/section_01_08/with_optional/MapRepository.java
public class MapRepository {
private Map<String, String> map = new HashMap<>();
MapRepository() {
map.put("EXIST_KEY", "value");
}
public Optional<String> getOptionalValue(String key) {
return Optional.ofNullable(map.get(key));
}
public String getValue(String key) {
return map.get(key);
}
}
#2 Optional.ifPresentOrElse()
- src/main/java/kr/co/programmersoop/example/section_01_08/with_optional/WithOptionalExampleMain.java
public class WithOptionalExampleMain {
public static void main(String[] args) {
MapRepository mapRepository = new MapRepository();
Optional<String> string = mapRepository.getOptionalValue("NOT_EXIST_KEY");
string.ifPresentOrElse(
str -> System.out.println(str.toUpperCase()), // Optional이 Empty가 아닐 때 실행
() -> {
throw new RuntimeException("키가 존재하지 않습니다."); // Optional이 Empty일 때 실행
}
);
}
}
#3 Optional.orElseThrow()
- src/main/java/kr/co/programmersoop/example/section_01_08/with_optional/WithOptionalExampleMain2.java
public class WithOptionalExampleMain2 {
public static void main(String[] args) {
// 이전 코드보다 간결한 코드
MapRepository mapRepository = new MapRepository();
// 비어있는 값이 들어올 경우에만 orElseThrow() 메서드의 람다 표현식 실행, 비어있지 않은 값이 들어오면 string 반환
String string = mapRepository.getOptionalValue("NOT_EXIST_KEY").orElseThrow(
() -> {throw new RuntimeException("키가 존재하지 않습니다.");}
);
System.out.println(string.toUpperCase());
}
}
#4 Optional 직접 생성하여 사용
메서드 참조 문법 : 메서드 호출 간결하게 해줌
- [Java]메서드 참조(Method reference) : https://developer-talk.tistory.com/462
[Java]메서드 참조(Method reference)
메서드 참조(Method reference)란? Java 8에 도입된 메서드 참조는 class::methodName 구문을 사용하여 클래스 또는 객체에서 메서드를 참조할 수 있습니다. 람다식(Lambda Expression)의 가장 큰 장점 중 하나는
developer-talk.tistory.com
- src/main/java/kr/co/programmersoop/example/section_01_08/with_optional/WithOptionalExampleMain3.java
public class WithOptionalExampleMain3 {
public static void main(String[] args) {
// Optional의 정적 팩토리 메서드 사용
MapRepository mapRepository = new MapRepository();
// null이 들어올지 안 들어올지 모르는 값을 Optional.ofNullable() 매개변수로 넣기 -> 매개변수를 가지고 Optional 객체 생성
String string = Optional.ofNullable(mapRepository.getValue("NOT_EXIST_KEY"))
.orElseThrow(RuntimeException::new); // 생성자 참조
System.out.println(string.toUpperCase());
}
}
4. Optional 실제 활용
1) 내가 쓰는 라이브러리의 메서드 반환 타입이 Optional인 경우
그대로 받아서 orElseThrow() 같은 메서드 사용
2) 내가 쓰는 라이브러리의 메서드 반환 타입이 Optional이 아닌 경우
Optional.ofNullable()로 Optional 객체 생성 후, orElseThrow() 같은 메서드 사용
5. Optional을 쓰면 안되는 상황 - Optional 안티 패턴
기존 null체크 하는 것과 동일한 유형으로 사용
- src/main/java/kr/co/programmersoop/example/section_01_08/with_optional/OptionalAntiPatternExampleMain.java
public class OptionalAntiPatternExampleMain {
public static void main(String[] args) {
MapRepository mapRepository = new MapRepository();
Optional<String> string = mapRepository.getOptionalValue("NOT_EXIST_KEY");
if (string.isPresent())
System.out.println(string.get().toUpperCase());
else
throw new RuntimeException("키가 존재하지 않습니다.");
}
}
6. Optional 활용 - Stream API 연계
서로 잘 어울려 앞으로 많이 사용할 것이다.
- src/main/java/kr/co/programmersoop/example/section_01_08/with_optional/ListOptionalExampleMain.java
public class ListOptionalExampleMain {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
// list.add(100);
Integer filteredInteger = list.stream()
.filter(value -> value.equals(100))
.findFirst()
.orElseThrow(() -> {
throw new RuntimeException("100에 해당하는 요소가 없습니다.");
});
System.out.println(filteredInteger);
}
}
관련 내용 참고 링크 : https://www.baeldung.com/java-optional
실무 자바 개발을 위한 OOP와 핵심 디자인 패턴
@media (max-width: 991px) { .content { width: 100%; } } #landingPage { width: 100%; max-width: 848px; padding: 0 20px; letter-spacing: -0.02em; overflow-wrap: break-word; word-break: keep-all; word-wrap: break-word; } @media (max-width: 991px) {
school.programmers.co.kr
'강의 실습 > 실무 자바 개발을 위한 OOP와 핵심 디자인 패턴' 카테고리의 다른 글
| getter와 setter (0) | 2026.01.27 |
|---|---|
| if문 제거하기 (0) | 2026.01.26 |
| Object 클래스 (1) | 2026.01.24 |
| 예외 (0) | 2026.01.22 |
| Enum (0) | 2026.01.21 |
댓글