164 lines
5.7 KiB
Markdown
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`을 활용하면 **예외 없이 더 깔끔하고 안전한 코드**를 작성할 수 있다. |