본문 바로가기

JAVA

240216 JAVA 옵셔널 공부하기

https://youtu.be/W_kPjiTF9RI?si=qrvIm_TJFy_zidyD

 

Optional 은 <T> 를 가지고 있는 래퍼 클래스

 

모든 종류, 어떤 타입인 변수도 가질 수 있음 -> null 도 저장할 수 있음

 

Optional 이 필요한 이유

  • null 을 직접 다루는 것은 위험 -> NullPointerException 이 발생할 수 있음
  • 객체 안에 담아 간접적으로 null 을 다루기 위함
  • 값의 null 을 체크하기 위해서는 if 문을 사용해야 해서 코드가 지저분해짐 -> 간접적으로 다룰 필요가 있음
Object result = getResult();

 

이런 메소드가 있는데 Optional 에 담긴 값의 타입으로 Object 가 결정됨

반환값

  1. null
  2. 객체

만약 result 로 무엇인가 작업을 하려고 하면 NullpointerException 이 발생

그래서 항상 if 문이 필요

 

이런 문제를 해결하기 위해 사용하는게 Optional

 

만약 result 에 null 이 담길 경우에 그 null 을 Optional 객체에 저장

그렇게 되면 result 에는 null 이 담긴 Optional 객체의 주소를 받게 되고

Optional 객체의 값은 null 이지만 객체 자체는 존재하기 때문에 항상 null 오류가 발생하지 않음

-> 간접적으로 다룬다

 

이러한 객체들을 간접적으로 다루기 위한 것이 Optional


Optional<T> 객체 생성하기

String str = "abc";

Optional<String> optVal = Optional.of(str);
Optional<String> optVal2 = Optional.of("abc");
Optional<String> optVal3 = Optional.of(null); // NullPointerException 발생
Optional<String> optVal4 = Optional.ofNullable(null); // 가능

of 는 null 을 받을 수 없지만
ofNullable 은 null 을 받을 수 있음

 

optVal 은 str 의 주소를 갖고, str 은 "abc" 의 주소를 가짐

 

Optional 객체 초기화 방법

Optional<String> optVal = null; // 가능은 하지만 바람직하지 않음
Optional<String> optVal2 = Optional.<String>empty();
// 뒤의 <String> 은 생략 가능

 

Optional 객체의 값 가져오기 - get(), orElse(), orElseGet(), orElseThrow()

Optional<String> optVal = Optional.of("abc");
String str = optVal.get(); // optVal 에 저장된 값을 반환, null 이면 예외 발생
String str2 = optVal.orElse(""); // optVal 에 저장된 값이 null 일 경우 "" 반환
String str3 = optVal.orElseGet(String::new); // 람다식 사용 가능 () -> new String()
String str4 = optVal.orElseThrow(NullPointerException::new); // null 이면 예외 발생

orElseGet 은 람다식 사용 시 Supplier 이기 때문에 입력값 없음, 반환값만 존재
람다식 : 입력값이 없으므로 () -> 로 시작, 새로운 문자열 객체를 반환 new String()

orElseThrow 는 예외 종류를 지정할 수 있음

 

isPresent() -> Optional 객체의 값이 null 이면 false, 아니면 true 를 반환

if (Optional.ofNullable(str).isPresent()) { // if (str != null)
  System.out.println(str); 
}

 

ifPresent() -> null 이 아닐때만 작업 수행, null 이면 아무 일도 안함

Optional.ofNullable(str).ifPresent(System.out::println);

Optional 객체의 값이 null 이 아니면, 출력문을 실행

System.out::println -> 람다식의 출력문

실습해보기

Optional<String> opt = Optional.empty();
System.out.println(opt); // Optional.empty 출력
System.out.println(opt.get()); // NoSuchElementException 오류 발생

 

Optional 객체를 get() 할 시 예외 처리하기

Optional<String> opt = Optional.empty();
String str = "";
    
try {
  str = opt.get();
} catch (Exception e) {
  str = "";
}

 

이렇게 만들 수 있지만..

 

orElse() 를 사용하면 더 편하게 할 수 있음

Optional<String> opt = Optional.empty();
str = opt.orElse("empty");
System.out.println(str); // empty 문자열 출력

 

orElseGet() 을 사용하여 람다식 사용해보기

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

str = opt.orElseGet(() -> new String());
str = opt.orElseGet(String::new); // 위와 같은 역할을 함
str = opt.orElseGet(() -> "empty");
System.out.println(str); // empty 출력

OptionalInt, OptionalLong, OptionalDouble

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

 

Optional<T> 는 String, Integer 등 참조형을 사용하였지만

OptinalInt 는 기본형인 int 을 사용

 

OptionalInt 클래스에는 value 와 isPresent 변수가 있음

빈 OptionalInt 를 생성하여도 value 값은 0 으로 초기화

 

그러면 0 을 저장한 것인지, 값이 없어 0 이 출력되는 것인지 확인하는 방법 -> isPresent() 사용

OptionalInt optInt = OptionalInt.of(0);
OptionalInt optInt2 = OptionalInt.empty();

System.out.println(optInt.isPresent()); // true
System.out.println(optInt2.isPresent()); // false
System.out.println(optInt.equals(optInt2)); // false

 

value 는 같지만 저장과 초기화된 값은 다르게 출력


전체 실습

Optional 만들고 출력해보기

map 은 값을 변환해주는 역할

Optional<String> optStr = Optional.of("apple");
Optional<Integer> optInt = optStr.map(s -> s.length());
System.out.println("optStr : " + optStr.get()); // optStr : apple
System.out.println("optInt : " + optInt.get()); // optInt : 5

 

Optional 객체 만들고 값 변환하고, 조건 걸고 람다식 쓰면서 다 해보기

int num = Optional.of("123").filter(str -> str.length() > 0)
            .map(str -> Integer.valueOf(str)).get();

int num2 = Optional.of("").filter(str -> str.length() > 0)
            .map(str -> Integer.parseInt(str)).orElse(-1);
// filter 를 통과하지 못해 Optional 값이 null 로 변함

System.out.println("num : " + num); // num : 123
System.out.println("num2 : " + num2); // num2 : -1

 

ifPresent() 사용해보기

Optional.of("456").map(i -> Integer.valueOf(i))
        .ifPresent(i -> System.out.printf("result : %d", i)); 
// result : 456

 

'JAVA' 카테고리의 다른 글

String, StringBuffer, StringBuilder  (0) 2024.08.05
240111 홈페이지 만들기  (2) 2024.01.11
240103 Java  (0) 2024.01.03
231227 Java  (0) 2023.12.27
231226 Java  (0) 2023.12.26