옵셔널

김민성·2022년 7월 14일
0

Java

목록 보기
40/47
post-thumbnail

옵셔널 (Optional)

Optional<T> 는 제네릭 클래스로 'T 타입의 객체' 를 감싸는 래퍼 클래스이다.

public final class Optional<T>{
    private final T value;	// T 타입의 참조변수
    ...
}

Optional 타입의 객체에는 모든 타입의 참조변수를 담는 것이 가능하다. (null 도 가능)

이러한 특징 덕분에, 반환 결과가 null이 될 수 있는 객체를 항상 조건식으로 처리하는 것 대신 Optional에 정의된 메서드를 통해 간단히 처리할 수 있다. (NullPointerException이 발생하지 않아, 보다 안전한 코드를 작성할 수 있다.)

옵셔널 객체의 생성

// .of() 이용
String str = "java";
Optional<String> optVal = Optional.of(str);

// .ofNullable() 이용
Optional<String> optVal = Optional.ofNullable(null);
// Optional<String> optVal = Optional.of(null); -> NullPointerException 발생

// .empty()를 이용한 초기화
Optional<String> optVal = null;	// null로 초기화
Optional<String> optVal = Optional.empty();	// 빈 객체로 초기화

참조변수의 값이 null일 가능성이 있으면 ofNullable() 을 사용한다.

Optional<T> 타입의 참조변수를 null로 초기화 하는 것이 가능하긴 하지만, empty()로 초기화 하는것이 바람직하다.

옵셔널 객체의 값 가져오기

Optional<String> optVal = Optional.of("abc");
// optVal에 저장된 값 반환. null이면 NoSuchElementException 발생
String str1 = optVal.get();
// 객체의 값이 null일 때를 대비해 orElse()로 대체값 지정 가능
String str2 = optVal.orElse("null 입니다!");	// 저장된 값이 null일때는 "null 입니다!" 를 반환
import java.util.Optional;

public class Main{
    public static void main(String[] args) {
        Optional<String> opt1 = Optional.of("opt1 입니다.");
        Optional<String> opt2 = Optional.ofNullable(null);
        printmsg(opt1);
        printmsg(opt2);
    }

    private static void printmsg(Optional<String> opt){
        String getOpt = opt.orElse("null 입니다.");
        System.out.println("optValue = " + getOpt);
    }
}

/* 
실행 결과
optValue = opt1 입니다.
optValue = null 입니다.
*/

isPresent() : 옵셔널 객체의 값이 null이면 false를, 아니면 true를 반환한다.

import java.util.Optional;

public class Main{
    public static void main(String[] args) {
        Optional<String> opt1 = Optional.of("opt1 입니다.");
        Optional<String> opt2 = Optional.ofNullable(null);

        System.out.println(opt1.isPresent());	// true
        System.out.println(opt2.isPresent());	// false
    }
}

Stream처럼 Optional 객체에도 filter(), map() 같은 메서드를 사용할 수 있다.

만약 Optional 객체의 값이 null이면 이 메서드는 아무 일도 하지 않는다.

OptionalInt, OptionalLong, OptionalDouble

기본형 값을 감싸는 옵셔널 래퍼클래스이다. (성능의 향상을 위함)

getAsInt() , getAsLong(), getAsDouble() 메서드로 접근한다.

int의 기본값은 0이기 때문에 아래와 같은 혼동이 일어날 수 있다.

// 아래의 두 OptionalInt 객체는 같은 것일까?
OptionalInt opt = OptionalInt.of(0);	// 0 저장
OptionalInt opt2 = OptionalInt.empty();	// 0 저장

이러한 혼동을 방지하기 위해 isPresent()를 통해 구별할 수 있다.

System.out.println(opt.isPresent());	// true
System.out.println(opt2.isPresent());	// false

System.out.println(opt.getAsInt());	// 0
System.out.println(opt2.getAsInt());	// NoSuchElementException 예외

System.out.println(opt.equals(opt2));	// false

위의 코드를 통해 empty()를 통해 생성한 객체는 기본값으로 0이 저장은 되지만, 실제로 0이라는 값을 저장한 것과는 다르게 취급한다는 것을 알 수 있다.

0개의 댓글