🏃♂️ 들어가기 앞서..
본 게시물은 스터디 활동 중에 작성한 게시물로 자바의 정석-기초편 교재를 학습하여 정리하는 글입니다.
※ 스터디 Page : 〔투 비 마스터 : 자바〕
*해당 교재의 목차 순서와 구성을 참고하여 작성하며
각 내용마다 부족할 수 있는 내용이나 개인적으로 궁금한 점은
추가적인 검색을 통해 채워나갈 예정입니다.
Optional<T>
" T타입 객체의 래퍼(Wrapper) 클래스 "로
어떠한 타입이든 모든 객체를 담을 수 있다.
java.util.Optional
은 JDK 1.8부터 추가되었다.
public final class Optional<T> {
private final T value ; // T타입 참조변수 --> 모든 종류의 객체 저장 가능 (null 까지)
...
}
null
값 까지 담아서 간접적으로 다룰 수 있다.
null
을 직접 다루는 것은 NullPointerException
때문에 위험한데 이를 방지 할 수 있다.Optional<T>
객체 생성of()
String str = "abc" ; // "abc" 값을 가진 String 객체1
Optional<String> optVal = Optional.of(str); // Optional 객체로 Wrapping
// -> "abc"값의 주소를 참조하는 String 객체를 가진 < Optional 객체 1 >
Optional<String> optVal = Optional.of("abc");
// -> "abc"값의 String 객체를 가진 < Optional 객체 2 >
Optional<String> optVal = Optional.of(new String("abc"));
// -> "abc"값을 가진 새로운 String 객체를 가진 < Optional 객체 3 >
Wrapper 클래스이기 때문에
한 단계를 더 거쳐서 감싸는 형태인 것이다.
단, null
값을 사용할 땐 of()
메서드를 사용하면 안된다.
ofNullable()
참조 변수의 값이 null일 가능성 이 있을 경우,
of()
대신ofNullable()
을 사용해야 한다.
String str = "abc" ; // "abc" 값을 가진 String 객체1
Optional<String> optVal = Optional.ofNullable(str); // Optional 객체로 Wrapping
Optional<String> optVal = Optional.ofNullable(null);
Optional<String> optVal = Optional.of(null); // NullPointerException 발생
물론 Optional<T>
타입의 참조변수를 초기화할 때,
null이 가능하긴 하나 바람직하지 않다.
따라서
【Optional<T>
타입 참조변수 초기화】 : <T>empty()
메서드 사용
empty()
메서드는 지네릭 메서드Optional<String> optVal = null ; //가능은 하나 "비권장"
Optional<String> optStrVal = Optional.empty() ;
Optional<Integer> optIntVal = Optional.empty() ;
...
Optional<T>
객체 " 값 " 가져오기get()
Optional 객체에 저장된 값을 가져올 때는 보통 get()
메서드를 잘 사용하지는 않는데
잘 쓰이지 않는 이유는
값이 null 일 때는 NoSuchElementException
예외가 발생하기 때문이다.
이 경우에는 아래의
orElse()
메서드로 대체해서 사용해야 한다.
orElse()
값이 null 일 때, 매개변수로 입력된 대체값 을 반환한다.
Optional<String> optVal = Optional.of("abc") ;
String str1 = optVal.get(); // str1 == "abc"
String str2 = optVal.orElse("EMPTY"); // str2 = "abc"
Optional<String> optVal = Optional.ofNullable(null) ;
String str1 = optVal.get(); // NoSuchElementException 예외
String str2 = optVal.orElse("EMPTY"); // str2 = "EMPTY"
orElseGet()
null일 때, null을 대체할 값을 반환하는 람다식 지정
orElseThrow()
null일 때, 지정된 예외를 발생시키는 메서드
orElseGet()
와 orElseThrow()
둘 다
orElse()
메서드를 변형한 형태로
반환값만 있는 Supplier
함수형식으로 매개변수를 받는다.
T orElseGet( Supplier<? extends T> other )
T orElseGet( Supplier<? extends T> exceptionSupplier )
Optional<String> optVal = Optional.ofNullable(null) ;
String str3 = optVal.orElseGet(String::new); // null 이면 () -> new String()과 동일하게 객체 생성
String str4 = optVal.orElseThrow(NullPointerException::new);
// NoSuchElementException 가 아닌 NullPointerException 예외를 생성해서 던짐.
isPresent()
Optional 객체의 값이 null 이면 false
null이 아니면 true를 반환한다. ( 반환타입 : boolean )
ifPresent()
매개변수로
Cunsumer
타입 반환값은 없는 람다식을 받을 수 있는데
해당 경우에는 값이 있으면 " 람다식 실행 "
값이 없으면 " 아무 작업도 하지 않는다 "
구조는ifPresent( Consumer<T> block )
인데
// isPresent() 활용
if ( Optional.ofNullable(str).isPresent() ) {// null이면 false
System.out.println(str) ; // --> null이면 해당 코드 수행 X
}
Optional.ofNullable(str).ifPresent(System.out::println) ; // null이면 "반환 없이" 해당 코드 수행 X
OptionalInt
/ OptionalLong
/ OptionalDouble
" 기본형 타입 값의 래퍼(Wrapper) 클래스 "로
Optional<T>
보다 더 높은 성능 효율을 위해!!
실제 모습은 Optional<T>
와 크게 다를 바 없다.
public final class OptionalInt {
private final int value ; // int 타입(기본형) 참조변수
// 비어있는 기본값 0인지 진짜 정수값 0인지 비교하기 위해서 필요
private final boolean isPresent ; // --> 값이 저장되어 있으면 true
...
}
그리고 값을 가져오는 메서드는
앞선 Optional<T>
의 경우는 get()
이였는데
이를 단순히 응용해서
OptionalInt
: int getAsInt()
OptionalLong
: long getAsLong()
OptionalDouble
: double getAsDouble()
이런 메서드를 사용한다.
그런데
아까 Optianal<T>
에서는
비어있는 값/초기값/초기화 를 String 경우에서 null을 사용했지만
기본형 int의 경우,
기본값이 0이다.
"""
즉, 이렇게 된다면 진짜 값 0이 들어간 경우와,
비어있는 OptionalInt 객체를 나타내는 기본값 0은 어떻게 비교할까?
"""
다행히
위 OptionalInt
코드에서 본
비어있는지 확인해주기 위한 인스턴스 변수 isPresent
를 비교해
이를 구분해준다.
( 해당 변수 값이 true : 실제 값이 저장되어 있는 상태 )