Files
java-examples/docs/Optional.md

164 lines
5.7 KiB
Markdown

## 자바 `Optional` 주요 메서드 정리
| 메서드 | 설명 |
|-----|-----|
| `of(T value)` | `null`이 아닌 값을 감싸는 `Optional` 생성 |
| `ofNullable(T value)` | `null`일 수도 있는 값을 감싸는 `Optional` 생성 |
| `empty()` | 비어 있는 `Optional` 생성 |
| `isPresent()` | 값이 존재하면 `true`, 없으면 `false` 반환 |
| `isEmpty()` | 값이 없으면 `true`, 있으면 `false` 반환 |
| `get()` | 값이 존재하면 반환, 없으면 `NoSuchElementException` 발생 |
| `orElse(T other)` | 값이 존재하면 반환, 없으면 기본값 반환 |
| `orElseGet(Supplier)` | 값이 존재하면 반환, 없으면 함수 실행 결과 반환 |
| `orElseThrow()` | 값이 존재하면 반환, 없으면 예외 발생 |
| `or(Supplier)` | 값이 존재하면 현재 `Optional` 반환, 없으면 다른 `Optional` 반환 |
| `ifPresent(Consumer)` | 값이 존재하면 실행할 코드 지정 |
| `ifPresentOrElse(Consumer, Runnable)` | 값이 존재하면 실행할 코드, 없으면 실행할 코드 지정 |
| `map(Function)` | 값을 변환하여 새로운 `Optional` 반환 |
| `flatMap(Function)` | 중첩된 `Optional`을 평탄화하여 반환 |
| `filter(Predicate)` | 조건을 만족하면 `Optional` 유지, 아니면 비움 |
---
## 자바 `Optional` 쉽게 설명하기
### `Optional`이란?
자바에서는 `null`이 자주 등장한다. 하지만 `null`을 잘못 다루면 `NullPointerException`(NPE)이 발생한다.
이 문제를 해결하기 위해 나온 것이 **`Optional`(옵셔널)**이다.
> **"옵셔널은 값이 있을 수도 있고 없을 수도 있는 박스다."**
즉, **값을 안전하게 감싸고 다룰 수 있도록 도와주는 도구**다.
값이 있으면 꺼내서 사용하고, 없으면 `null` 대신 기본값을 사용하거나 예외를 발생시킬 수 있다.
---
### `Optional` 사용 예제
#### 1. `Optional` 생성하기
```java
Optional<String> name = Optional.of("Alice"); // 값이 있는 Optional
Optional<String> emptyName = Optional.empty(); // 비어 있는 Optional
Optional<String> nullableName = Optional.ofNullable(null); // null 가능
```
- `Optional.of(value)`: `null`이 아닌 값을 감쌈 (null이면 예외 발생)
- `Optional.empty()`: 비어 있는 `Optional` 생성
- `Optional.ofNullable(value)`: `null`일 수도 있는 값을 감쌈
---
#### 2. 값이 있는지 확인하기
```java
Optional<String> name = Optional.of("Alice");
System.out.println(name.isPresent()); // true
System.out.println(name.isEmpty()); // false
```
- `isPresent()`: 값이 있으면 `true`
- `isEmpty()`: 값이 없으면 `true`
---
#### 3. 값 가져오기
```java
Optional<String> name = Optional.of("Alice");
System.out.println(name.get()); // "Alice"
```
하지만 **값이 없을 때 `get()`을 호출하면 예외가 발생**하므로 주의해야 한다.
```java
Optional<String> emptyName = Optional.empty();
System.out.println(emptyName.get()); // NoSuchElementException 발생!
```
그래서 **`orElse()` 또는 `orElseGet()`을 사용하는 것이 안전하다.**
```java
Optional<String> emptyName = Optional.empty();
String result1 = emptyName.orElse("Unknown"); // 기본값 제공
String result2 = emptyName.orElseGet(() -> "Generated Name"); // 함수로 기본값 제공
System.out.println(result1); // "Unknown"
System.out.println(result2); // "Generated Name"
```
---
#### 4. 값이 없을 때 예외 던지기
```java
Optional<String> emptyName = Optional.empty();
String name = emptyName.orElseThrow(() -> new IllegalArgumentException("이름이 없습니다!"));
```
값이 없으면 `IllegalArgumentException`을 던진다.
---
#### 5. 값이 있을 때만 실행하기 (`ifPresent`)
```java
Optional<String> name = Optional.of("Alice");
name.ifPresent(n -> System.out.println("이름: " + n)); // 이름이 있으면 출력
```
값이 없으면 아무 일도 일어나지 않는다.
---
#### 6. 값이 있으면 실행, 없으면 다른 작업 수행 (`ifPresentOrElse`)
```java
Optional<String> name = Optional.empty();
name.ifPresentOrElse(
n -> System.out.println("이름: " + n), // 값이 있을 때 실행
() -> System.out.println("이름이 없습니다!") // 값이 없을 때 실행
);
```
---
#### 7. 값 변환하기 (`map`)
```java
Optional<String> name = Optional.of("Alice");
Optional<Integer> length = name.map(String::length);
System.out.println(length.get()); // 5
```
- `map(Function)`: 값이 있으면 변환하고, 없으면 `Optional.empty()` 유지
---
#### 8. 중첩된 `Optional`을 평탄화 (`flatMap`)
```java
Optional<Optional<String>> nested = Optional.of(Optional.of("Alice"));
Optional<String> flat = nested.flatMap(n -> n);
System.out.println(flat.get()); // "Alice"
```
- `flatMap(Function)`: 중첩된 `Optional`을 단일 `Optional`로 변환
---
#### 9. 조건에 맞는 값만 유지하기 (`filter`)
```java
Optional<String> name = Optional.of("Alice");
Optional<String> filtered = name.filter(n -> n.startsWith("A"));
System.out.println(filtered.get()); // "Alice"
```
- `filter(Predicate)`: 조건을 만족하면 `Optional` 유지, 아니면 `Optional.empty()` 반환
---
### `Optional`을 사용하면 좋은 이유
1. **`null` 체크가 필요 없음** → `if (value != null)` 같은 코드 제거 가능
2. **코드가 더 읽기 쉬움**`Optional` 메서드를 통해 명확한 의도를 전달
3. **안전한 값 처리 가능**`orElse()`, `ifPresent()` 등을 활용하여 `null`을 안전하게 대체
즉, **"옵셔널은 값이 있을 수도 있고 없을 수도 있는 안전한 박스"**다.
무작정 `null`을 다루는 것보다 `Optional`을 활용하면 **예외 없이 더 깔끔하고 안전한 코드**를 작성할 수 있다.