코린이의 소소한 공부노트

Optional 클래스 본문

Java

Optional 클래스

무지맘 2023. 2. 7. 20:56

[Optional<T>]

1. T타입 객체의 래퍼클래스이다.

public final class Optional<T> {
    private final T value; // T 타입의 참조변수. null을 포함한 모든 종류의 객체 저장 가능
    ...
}

2. Optional<T>가 필요한 이유

- null을 직접 다루는 것은 위험하다. 직접 다루다보면 NullPointerException이 발생할 수 있다.

- 예외처리를 하려면 try-catch문을 이용하거나, null을 체크하기 위한 if문이 필수적이다. 이때문에 코드가 지저분해진다.

- null을 간접적으로 다루려면 null을 참조변수에 직접 넣기보다는 Optional 객체에 넣은 다음, 그 주소값을 참조변수에 저장한다.

- 이렇게 하면 참조변수 값을 불러왔을 때 항상 값이 있게끔 해줘 NullPointerException을 발생하지 않게 해준다.

- try-catch문이나 if문을 사용할 필요도 없어졌기 때문에 코드도 간결해진다.

 

[Optional 객체 생성하기]

// of()를 이용해 Optional 객체를 생성한다.

String str = "abc"; // 문자열의 주소: 0x100
Optional<String> optVal = Optional.of(str); // optVal은 Optional객체의 주소를 담고,
                                            // Optional객체에서는 0x100이 담겨있다.
Optional<String> optVal = Optional.of("abc"); // 위 두 문장을 하나로 합친것

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

// null 대신 빈 Optional<T> 객체 사용하기
// Optional<String> optVal = null; // 바람직하지 않음
Optional<String> optVal = Optional.<String>empty();// 빈 객체로 초기화. 뒤쪽 지네릭 타입은 생략 가능

 

[Optional 객체의 값 가져오기]

1. 값 읽어오기 - get(), orElse(), orElseGet(), orElseThrow()

Optional<String> optVal = Optional.of("abc");

String str1 = optVal.get(); // optVal에 저장된 값을 반환. null이면 예외발생

String str2 = optVal.orElse(""); // optVal에 저장된 값이 null일 때는 ""를 반환
                                 // 빈 문자열은 길이가 0인 char[]

String str3 = optVal.orElseGet(String::new); // 람다식 사용가능. () -> new String()

String str4 = optVal.orElseThrow(NullPointerException::new); // null이면 예외발생

// orElse( ), orElseGet( )를 많이 사용한다.

// orElseGet( ), orElseThrow( ) 비교
T orElseGet(Supplier<? extends T> other)
T orElseThrow(Supplier<? extends X> exceptionSupplier) // 예외 종류 지정 가능

2. 값이 null이 아니면 true 반환 - isPresent()

if(Optional.ofNullable(str).isPresent()) { // if(str!=null)과 같은 의미
    System.out.println(str);
}

// 위 코드를 한줄로 바꾸면
Optional.ofNullable(str).ifPresent(System.out::println);
// ifPresnt(Consumer): 널이 아닐때만 작업을 수행하는 Optional 클래스의 메서드

 

[기본형 값을 감싸는 래퍼클래스]

1. 종류: OptionalInt, OptionalLong, OptionalDouble

- 기본형을 다룰 때 Optional<T>보다 더 높은 성능이 필요한 경우에 사용한다.

public final class OptionalInt { // Optional<Integer>대신 사용하는 래퍼클래스
    ...
    private final boolean isPresent; // 값이 저장되어 있으면 true
    private final int value; // int타입의 변수
    ...
}

2. OptionalXXX의 값 가져오기 int getAsXXX( )

// Optional클래스 - 값을 반환하는 메서드
Optional<T> - T get()
OptionalInt - int getAsInt()
OptionalLong - long getAsLong()
OptionalDouble - double getAsDouble()

// 예시
OptionalInt opt = OptionalInt.of(1234);
System.out.println(opt); // OptionalInt[1234]
System.out.println(opt.getAsInt()); // 1234

3. Optional객체의 비교

OptionalInt opt1 = OptionalInt.of(0); // OptionalInt에 0을 저장
OptionalInt opt2 = OptionalInt.empty(); // 빈 OptionalInt객체. OptionalInt에 0이 저장됨

// opt1과 opt2 모두 0이 저장되어 있지만, 어떤 0인지 구분 가능하다.
System.out.println(opt1.isPresent()); // true (0이라는 값이 저장되어 있다는 뜻)
System.out.println(opt2.isPresent()); // false (값이 없음 = 비어있다는 뜻)
System.out.println(opt1.equals(opt2)); // false (0이 저장되어있지만 0의 의미가 다름)

Optional<String> opt3 = Optional.ofNullable(null); // null이 저장된 Optional객체
Optional<String> opt4 = Optional.empty(); // 빈 Optional객체. null이 저장됨
System.out.println(opt3.equals(opt4)); // true (null = 비어있음)

[쿠키글] orElse()를 사용하는 이유 - 코드 리팩터링

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

System.out.println(opt); // Optional.empty
System.out.println(opt.get()); // NoSuchElementException 발생. 아무것도 저장되어있지 않기 때문

// Optional 객체에서 값을 불러올 때 예외가 발생할 수 있기 때문에 try-catch문을 써야 한다.
String str = ""; // opt의 값을 저장할 변수
try{
str = opt.get();
} catch(Exception e){
str = ""; // 예외가 발생하면 빈 문자열로 초기화
}

// 위의 try-catch문을 한 문장으로 줄이면 다음과 같다.
str = opt.orElse(""); // Optional에 저장된 값이 null이면 "" 반환

'Java' 카테고리의 다른 글

스트림의 그룹화와 분할  (0) 2023.02.22
스트림의 최종 연산  (0) 2023.02.21
스트림의 중간 연산  (0) 2023.02.07
스트림 생성하기  (0) 2023.02.01
스트림의 정의와 특징  (0) 2023.01.30