반응형

메소드에서 값을 제대로 반환할 수 없는 경우

1. 예외를 던진다. (비싸다, 스택트레이스를 찍어두니까.)
2. null을 리턴한다. (비용 문제가 없지만 그 코드를 사용하는 클리어인트 코드가 주의해야 한다.)
3. (자바 8부터) Optional을 리턴한다. (클라이언트에 코드에게 명시적으로 빈 값일 수도 있다는 걸 알려주고, 빈 값인 경우에 대한 처리를 강제한다.
 
 

Optional이란?

null-safe programming을 지원하기 위해 만들어진 인터페이스로 객체가 null인 경우, 대체값을 사용할 수 있도록 방법을 제공한다. 이는 NullPointerException을 방지하고, 코드의 안정성과 가독성을 높일 수 있다.
 
Optional을 반환값으로 사용함으로써 null 관련 문제를 해결하기에 반환값으로만 쓰기를 권장한다.
(메소드 매개변수 타입, 맵의 키 타입, 인스턴스 필드 타입으로 쓰지 말자.)
 
Optional을 반환하는 메소드에서 반환할 값이 없으면 null을 반환하지 말고 Optional.empty()를 반환하면 된다.
 
Collection, Map, Stream Array, Optional은 Opiontal로 감싸면 안된다.
 
 

Optional 객체 생성 방법

of() 메서드

of() 메서드는 매개변수로 전달된 객체가 null이 아닌 경우, Optional 객체를 생성하고 null인 경우에는 NullPointerException을 발생시킨다.
 

ofNullable() 메서드

ofNullable() 메서드는 매개변수로 전달된 객체가 null인 경우, Optional.empty()를 반환하고, null이 아닌 경우, Optional 객체를 생성한다.
 
예시)

String name = null;
Optional<String> optionalName = Optional.ofNullable(name);

 

프리미티브 타입용 Optional

이들 클래스는 기본형 값(int, long, double)을 감싸는 래퍼 클래스로 값이 없는 경우 기본값을 제공하거나 값을 안전하게 다룰 수 있는 기능을 제공한다.
 
프리미티브 타입용 Optional을 사용하지 않으면 오토 박싱과 오토 언박싱이 일어나서 성능상 좋지 않기에 프리미티프 타입용 Optional을 사용하는 것을 권장한다.
 
예시)

OptionalInt optionalInt = OptionalInt.of(10); // 값을 포함하는 OptionalInt 생성

// 값이 있는 경우 해당 값을 얻어옴
if (optionalInt.isPresent()) {
    int value = optionalInt.getAsInt();
    System.out.println("Value: " + value);
} else {
    System.out.println("Value is not available.");
}

// 값이 없는 경우 기본값 제공
int result = optionalInt.orElse(0); // 값이 있으면 해당 값을 반환하고, 없으면 기본값 0을 반환
System.out.println("Result: " + result);

 
 

Optional 메서드

1. isPresent()

Optional 객체에 값이 존재할 경우 true, 값이 없을 경우 false를 반환한다.
 

2. isEmpty() - (Java 11부터 제공)

Optional 객체에 값이 없을 경우 true, 값이 존재할 경우 false를 반환한다.
 
 
예시)

List<Member> memberList = new ArrayList<>();
memberList.add(new Member("Moon"));;

// Filtering with isPresent()
Optional<Member> member = memberList.stream()
        .filter(oc -> oc.getName().startsWith("M"))
        .findFirst();
        
boolean pre = member.isPresent();
// 출력 : true
System.out.println(pre);

boolean emp = member.isEmpty();
// 출력 : false
System.out.println(emp);

 

3. get()

Optional에 있는 값을 가져오는데 값이 존재하지 않을 경우 NoSuchElementException을 발생시킨다. 그러므로 get 메서드 사용전에  isPresent() 메서드를 사용하여 값의 존재 여부를 확인하는 것이 중요하다.
 
예시)

Optional<String> optionalValue = Optional.empty();

if (optionalValue.isPresent()) {
    String value = optionalValue.get();
    System.out.println("Value is present: " + value);
} else {
    System.out.println("Value is not present.");
}

 

4. ifPresent(Consumer<? super T> consumer)

Optional 객체에 값이 존재할 경우 주어진 Consumer 함수형 인터페이스를 실행하는 메소드이다.
 
예시)

Optional<String> optionalValue = Optional.of("Hello");

optionalValue.ifPresent(value -> {
    // 출력 : Value : Hello
    System.out.println("Value: " + sjmoon);
});

Optional<String> emptyOptional = Optional.empty();
emptyOptional.ifPresent(value -> {
    // 이 블록은 실행되지 않는다.
    System.out.println("Value is present: " + value);
});

 

5. orElse(T other)

Optional 객체가 값이 있으며 가져오고 없는 경우 대체값을 반환한다. 이마 만들어진 상수를 작업할 경우 사용하는 것이 좋다.
 
예시)

Optional<String> optionalValue = Optional.empty();
String result = optionalValue.orElse("sjmoon");

// 출력: sjmoon
System.out.println(result);

 

6. orElseGet(Supplier<? extends T> supplier)

Optional 객체가 값이 없을 경우, 대체값을 생성하는 함수형 인터페이스인 Supplier를 사용하여 대체값을 반환한다. 이 메소드는 값이 없을 때만 대체값을 생성하기에, 동적으로 객체를 생성하거나 대체값 생성에 복잡한 연산이 필요한 경우 유용하다.
 
예시)

Optional<String> optional = Optional.empty();
// 값이 없으면 member 객체를 생성
Member member = optional.orElse(() -> createMember());

// 인스턴스 생성
private static Member createMember(){
    // 출력 : Create Member
    System.out.println("Create Member");
    return new Member("sjmoon");
}

 

7. orElseThrow()

Optional 객체가 값이 없을 경우, 예외를 발생시키는데 일반적으로 NoSuchElementException이 발생하며, 필요에 따라 사용자 정의 예외를 지정할 수도 있다.
 
예시)

Optional<String> optionalValue = Optional.empty();
// NoSuchElementException 발생
String result = optionalValue.orElseThrow();

 

8. filter(Predicate<? super T> predicate)

Optional 객체에 저장된 값을 주어진 조건에 따라 필터링하는 데 사용된다..

Predicate는 함수형 인터페이스로서, 주어진 값에 대한 조건을 판별하는데 사용되는데 boolean test(T t) 메소드를 가지고 있으며, 주어진 조건에 따라 true 또는 false를 반환한다.
 
예시)

Optional<String> optionalValue = Optional.of("sjmoon");
// 이름의 길이가 7이상이어야한다.
Optional<String> filteredOptional = optionalValue.filter(value -> value.length() > 7);

if (filteredOptional.isPresent()) {
    System.out.println("Filtered value: " + filteredOptional.get());
} else {
    // 출력 : 필터링된 값이 없습니다.
    System.out.println("필터링된 값이 없습니다.");
}

 

9. map(Function<? super T, ? extends U> mapper) 

Optional 객체에 저장된 값을 주어진 함수를 적용하여 변환하는 데 사용된다. 변환된 결과는 새로운 Optional 객체로 감싸져 반환된다.
 

10. flatMap(Function<? super T, Optional<U>> mapper) 

Optional 객체에 저장된 값을 주어진 함수를 적용하여 변환하고, 변환된 Optional 객체를 평면화하여 반환하는 데 사용된다. 즉, flatMap() 메소드는 중첩된 Optional을 해제하여 단일 Optional 객체를 반환한다.
 
예시)

Optional<String> optionalValue = Optional.of("Hello");

Optional<Integer> mappedOptional = optionalValue.map(value -> value.length());

if (mappedOptional.isPresent()) {
    System.out.println("Mapped value: " + mappedOptional.get());
} else {
    System.out.println("No value present after mapping.");
}
반응형

+ Recent posts