본문 바로가기
프로그래밍/Java

Optional

by freeelifee 2025. 4. 8.
728x90

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 처리를 더욱 안전하고 가독성 있게 만들어 주는 강력한 도구입니다.

728x90

'프로그래밍 > 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