Java의 `Optional` 클래스는 값의 존재 여부를 나타내는 컨테이너 객체로, null을 안전하게 처리하기 위해 사용됩니다.
값이 존재하면 해당 값을 포함하고, 값이 없으면 비어 있는 객체를 반환합니다.
이를 통해 NullPointerException(NPE)을 방지하고 더 명확한 코드를 작성할 수 있습니다.
### 특징
1. null 대체
- `Optional`을 사용하면 null 값을 직접 다루지 않아도 되며, 값이 비어 있는 경우를 안전하게 처리할 수 있습니다.
2. 표준화된 API
- 값의 존재 여부를 확인하고 처리할 수 있는 다양한 메서드가 제공됩니다.
3. 함수형 프로그래밍
- 함수형 스타일로 값을 처리하고, 필요한 경우 추가 작업을 체이닝으로 처리할 수 있습니다.
### 사용법
#### 1. Optional 생성
`Optional` 객체를 생성하는 방법은 여러 가지가 있습니다.
import java.util.Optional;
public class OptionalExample {
public static void main(String[] args) {
// 빈 Optional 생성
Optional<String> emptyOptional = Optional.empty();
// 값이 존재하는 Optional 생성
Optional<String> optionalWithValue = Optional.of("Hello, Optional!");
// null일 수도 있는 값을 처리하는 Optional 생성
Optional<String> nullableOptional = Optional.ofNullable(null);
System.out.println("Optional with value: " + optionalWithValue);
System.out.println("Empty Optional: " + emptyOptional);
System.out.println("Nullable Optional: " + nullableOptional);
}
}
#### 출력 결과:
Optional with value: Optional[Hello, Optional!]
Empty Optional: Optional.empty
Nullable Optional: Optional.empty
### 결과 분석
1. `optionalWithValue`
- `Optional.of("Hello, Optional!")`로 생성했기 때문에 값이 존재합니다.
- 출력 시 `Optional[Hello, Optional!]` 형식으로 표시됩니다.
2. `emptyOptional`
- `Optional.empty()`로 생성했기 때문에 값이 존재하지 않습니다.
- 출력 시 `Optional.empty`로 표시됩니다.
3. `nullableOptional`
- `Optional.ofNullable(null)`로 생성했으며, `null` 값이 들어갔기 때문에 내부적으로 비어 있는 Optional이 됩니다.
- 출력 시 `Optional.empty`로 표시됩니다.
Optional 객체는 값이 있으면 `Optional[값]` 형태로, 값이 없으면 `Optional.empty`로 출력되는 특징이 있습니다.
#### 2. 값의 존재 확인
`Optional` 객체에 값이 존재하는지 확인할 수 있습니다.
Optional<String> optional = Optional.of("Value");
// 값이 존재하는지 확인
if (optional.isPresent()) {
System.out.println("값이 존재합니다: " + optional.get());
}
// 값이 없을 경우 실행
optional.ifPresentOrElse(
value -> System.out.println("값이 존재합니다: " + value),
() -> System.out.println("값이 없습니다.")
);
#### 3. 기본값 처리
`Optional`이 비어 있을 경우 기본값을 사용할 수 있습니다.
Optional<String> emptyOptional = Optional.empty();
// 기본값 반환
String defaultValue = emptyOptional.orElse("Default Value");
System.out.println(defaultValue);
// 기본값을 계산하는 메서드 사용
String computedValue = emptyOptional.orElseGet(() -> "Computed Value");
System.out.println(computedValue);
`orElse`와 `orElseGet` 메서드는 Optional 객체가 비어있을 때 사용할 값을 제공하는 방법이지만, 두 메서드의 작동 방식에 중요한 차이가 있습니다.
---
### 1. orElse
`orElse`는 기본값을 항상 계산하거나 평가합니다. Optional 값이 존재하든 존재하지 않든, 기본값을 미리 생성해 둡니다.
따라서 기본값을 생성하는 과정이 비용이 많이 드는 경우, 사용 시 주의가 필요합니다.
#### 예제:
String value = Optional.ofNullable(null).orElse(createDefaultValue());
System.out.println(value);
public static String createDefaultValue() {
System.out.println("기본값 생성...");
return "Default Value";
}
#### 출력 결과:
기본값 생성...
Default Value
- `createDefaultValue()`는 Optional 값이 없을 경우를 대비해 미리 실행됩니다.
- 기본값 생성 로직이 항상 실행되므로, 값이 존재하더라도 불필요하게 실행될 수 있습니다.
---
### 2. orElseGet
`orElseGet`은 Optional 값이 비어 있을 때만 기본값을 생성합니다. 기본값 생성 로직이 필요할 때만 실행되기 때문에 더 효율적입니다. 기본값을 제공하는 Supplier를 사용하여 계산을 지연할 수 있습니다.
#### 예제:
String value = Optional.ofNullable(null).orElseGet(() -> createDefaultValue());
System.out.println(value);
public static String createDefaultValue() {
System.out.println("기본값 생성...");
return "Default Value";
}
#### 출력 결과:
기본값 생성...
Default Value
- `createDefaultValue()`는 Optional 값이 없을 경우에만 실행됩니다.
- 기본값 생성 로직이 필요하지 않다면 해당 코드가 실행되지 않습니다.
---
### 차이점 요약
특징 | orElse | orElseGet |
실행 시점 | 항상 실행 (즉시 계산) | Optional 값이 없을 때만 실행 (지연 계산) |
성능 | 기본값 생성 비용이 클 경우 비효율적 | 필요할 때만 계산하여 더 효율적 |
사용 방식 | 값 직접 제공 | 값 제공을 위한 Supplier 사용 |
---
### 사용 권장 사례
- 비용이 적은 기본값: `orElse`를 사용해도 무방합니다.
- 비용이 큰 기본값: `orElseGet`을 사용하여 필요할 때만 기본값을 생성하도록 설정하세요.
#### 4. 값 변환
`Optional`의 값을 변환할 때 `map`과 `flatMap`을 사용할 수 있습니다.
Optional<String> optional = Optional.of("Optional Value");
// 값 변환
Optional<Integer> lengthOptional = optional.map(String::length);
System.out.println("문자열 길이: " + lengthOptional.orElse(0));
#### 5. 예외 처리
`Optional`이 비어 있을 경우, 예외를 던질 수 있습니다.
Optional<String> emptyOptional = Optional.empty();
// 예외 발생
String value = emptyOptional.orElseThrow(() -> new IllegalArgumentException("값이 없습니다!"));
### 장점
1. 안전한 Null 처리: `null`을 직접 다루지 않음으로써 NPE를 예방할 수 있습니다.
2. 가독성 증가: 값의 존재 여부와 기본값 처리 로직이 명확하게 표현됩니다.
3. 함수형 스타일 지원: `map`, `filter`, `flatMap` 등을 통해 간결하고 직관적인 코드 작성 가능.
### 단점
1. 오버헤드: `Optional` 객체는 값이 있는 경우에도 추가적인 래핑을 하기 때문에 성능상 약간의 비용이 발생할 수 있습니다.
2. 일관성 부족: 기존 코드베이스에 갑작스럽게 `Optional`을 추가하면 스타일에 불일치가 생길 수 있습니다.
### 활용 사례
- API 설계: 반환값이 있을 수도 없을 수도 있는 경우.
- 데이터베이스 조회 결과: 값이 존재하지 않으면 비어 있는 `Optional` 반환.
- null 위험 줄이기: 함수 내에서 null을 반환하거나 처리하지 않고 안전하게 값을 다룸.
`Optional`은 null 처리를 더욱 안전하고 가독성 있게 만들어 주는 강력한 도구입니다.
'프로그래밍 > Java' 카테고리의 다른 글
디자인패턴 - Strategy 패턴 (0) | 2025.04.10 |
---|---|
디자인패턴 (0) | 2025.04.09 |
Enum (0) | 2025.04.08 |
이클립스 SVN LOCK 해제하기 (0) | 2023.01.18 |
이클립스, STS 메모리 설정 (0) | 2023.01.18 |