[자바]/자바

[Java] Optional<T> 클래스

쿠릉쿠릉 쾅쾅 2022. 2. 7. 14:11
728x90

 

Optional<T> 클래스

  • Optional<T>는 제네릭 클래스로 T타입의 객체를 감싸는 래퍼 클래스다.
  • Optional 타입의 객체에는 모든 타입의 참조변수를 담을 수 있다.
  • Optional<T>에 객체를 담아서 반환하면 반환된 결과가 null인지 아닌지 매번 if문으로 검사하지 않아도 Optional 클래스에 정의된 메서드를 통해서 간단히 처리할 수 있다.
  • 간접적으로 null 값을 다룰 수 있다.

 

🔍 Optional<T> 객체 생성

💡 of()

  • 참조변수의 값이 null일 경우 NullPointerExcpetion 예외가 발생한다.

 

예제

String str = "abc";

Optional<String> optVal1 = Optional.of(str);
Optional<String> optVal2 = Optional.of("abc");
Optional<String> optVal3 = Optional.of(new String("abc"));

 

 

💡 ofNullable()

  • 참조변수의 값이 null 값이 들어와도 NullPointerExcpetion 예외가 발생하지 않는다.

 

예제

String str = "abc";

Optional<String> optVal1 = Optional.ofNullable(str);
Optional<String> optVal2 = Optional.ofNullable("abc");
Optional<String> optVal3 = Optional.ofNullable(null);  // null값 허용

 

 

💡 Optional<T> 초기화

  • Optional<T> 타입의 참조변수를 기본값으로 초기화할 때는 empty() 메서드를 사용한다.
  • null로 초기화할 수 있지만, empty() 메서드로 초기화하는 것이 좋다.

 

예제

/* ex.1 null 값으로 초기화 (비추) */
Optional<String> optVal1 = null;  // null로 초기화


/* ex.2 empty() 메서드로 초기화 (권장O) */
Optional<String> optVal2 = Optional.<String>empty();  // 빈 객체로 초기화


/* ex.3 empty() 메서드로 초기화 (권장O, 제네릭 생략) */
Optional<String> optVal3 = Optional.empty(); // 제네릭 생략 가능
  • empty() 메서드는 제네릭 메서드라서 참조타입에 제네릭이 있을 경우 생략 가능하다.

 

 

 

🔍 Optional<T> 객체 값 가져오기

💡 get()

T get()
  • Optional 객체에 저장된 값을 가져올 때 사용한다.
  • 저장된 값이 null 일 경우 NoSuchElementException 예외가 발생한다.
  • 자주 안쓰인다.

 

예제

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

String str = optVal.get();  // optVal에 저장된 값 반환

 

 

💡 orElse()

T orElse(T other)
  • Optional 객체에 저장된 값을 가져올 때 사용한다.
  • 저장된 값이 null 일 경우 파라미터 값이 반환이 된다.
  • 자주 쓰인다.

 

예제

/* ex.1 */
Optional<String> optVal = Optional.ofNullable("abc");

String str = optVal.orElse("");  // optVal에 저장된 값 반환


/* ex.2 */
Optional<String> optVal = Optional.ofNullable(null);

String str = optVal.orElse("");  //  "" 값 반환

 

 

 

💡 orElseGet()

T orElseGet(Supplier<? extend T> other)
  • Optional 객체에 저장된 값을 가져올 때 사용한다.
  • orElse() 메서드의 변형으로 저장된 값이 null 일 경우 예외가 발생하지 않으며, 람다식으로 대체할 값을 반환한다.
  • 자주 쓰인다.

 

예제

/* ex.1 */
Optional<String> optVal = Optional.ofNullable("abc");

String str = optVal.orElseGet(String::new);  // optVal에 저장된 값 반환


/* ex.2 */
Optional<String> optVal = Optional.ofNullable(null);

String str = optVal.orElseGet(String::new);  // String 객체 반환

 

 

💡 orElseThrow()

T orElseThrow(Supplier<? extend T> exceptionSupplier)
  • Optional 객체에 저장된 값을 가져올 때 사용한다.
  • 저장된 값이 null 일 경우 지정된 예외를 발생하도록 람다식으로 지정할 수 있다.

 

예제

/* ex.1 */
Optional<String> optVal = Optional.ofNullable("abc");

String str = 
    optVal.orElseThrow(NullPointerException::new);  // optVal에 저장된 값 반환


/* ex.2 */
Optional<String> optVal = Optional.ofNullable(null);

String str = 
    optVal.orElseThrow(NullPointerException::new);  // NullPointerException 예외 발생

 

 

💡 isPresent()

boolean isPresent()
  • Optional 객체의 값이 null이면 false 를 반환하고 아니면 true를 반환한다.

 

예제

String str = "abc";

if(Optional.ofNullable(str).isPresent()) {
    System.out.println(str);
}

 

 

💡 ifPresent(Consumer<? super T> consumer)

void ifPresent(Consumer<? super T> consumer)
  • Optional 객체에 값이 null이 아닐 경우 파라미터의 람다식이 실행되고, null일 경우 아무것도 실행되지 않는다.

 

예제

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

 

✔ 참고

  • ifPresent() 메서드는 Stream 클래스에서 Optional<T>를 반환하는 최종 연산과 잘 어울린다.
  • Stream 클래스에서 Optional<T>를 반환하는 메서드 목록
    • Optional<T> findAny()
    • Optional<T> findFirst()
    • Optional<T> max(Comparator<? super T> comparator)
    • Optional<T> min(Comparator<? super T> comparator)
    • Optional<T> reduce(BinaryOperator<T> accumulator)

 

 

🔍 Optional<T> 클래스의 중간 처리  작업

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

<U> Optional<U> map(Function<? super T, ? extends U> mapper)
  • 입력값을 다른 값으로 변환하는 메서드다.
  • map() 메서드는 apply 메서드가 반환하는 대상을 Optional 인스턴스에 담아서 반환한다.
  • Optional에 저장된 값을 꺼내서 파라미터 값인 람다식으로 작업한 후 다시 Optional에 담아서 반환한다.

 

더보기
더보기

예제1

import java.util.Optional;

public  class Prac {	
    public static void main (String[] args) { 
    	
    	Optional<String> os1 = Optional.of("Optional String");
    	Optional<String> os2 = os1.map(String::toUpperCase);
    	System.out.println(os2.orElse(""));
    	
    	Optional<String> os3 = os1.map(s -> s.replace(' ', '_'))
    			.map(String::toLowerCase);
    	System.out.println(os3.orElse(""));
    	
	}
	
}
OPTIONAL STRING
optional_string

 

 

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

<U> Optional<U> flatMap(Function<? super T, Optional U> mapper)
  • 입력값을 다른 값으로 변환하는 메서드다.
  • 파라미터의 인스턴스가 Optinal에 저장된 객체이며 그 객체 안에 멤버변수도 Optional로 되어 있을 경우 사용한다.
  • flatMap() 메서드는 Optional에 저장된 값을 파라미터 값인 람다식으로 작업을 한 후 Optional에 담지 않고 값을 그대로 반환한다.

 

더보기
더보기
import java.util.Optional;

public  class Prac {	
    public static void main (String[] args) { 
    	Optional<ContInfo> ci = 
    			Optional.of(new ContInfo(Optional.ofNullable(null), Optional.of("Republic of Korea")));
    	
    	String phone = ci.flatMap(ContInfo::getPhone).orElse("There is no phone number");
    	
    	String addr = ci.flatMap(ContInfo::getAdrs).orElse("There is no address");
    	
    	System.out.println(phone);
    	System.out.println(addr);
    	
	}
	
}

class ContInfo {
	Optional<String> phone;
	Optional<String> adrs;
	
	public ContInfo(Optional<String> ph, Optional<String> ad) {
		phone = ph;
		adrs = ad;
	}
	
	public Optional<String> getPhone() {return phone;}
	public Optional<String> getAdrs() {return adrs;}
}
There is no phone number
Republic of Korea

 

 

💡 filter(Predicate<? super T> predicate)

Optional<T> filter(Predicate<? super T> predicate)
  • filter() 메서드는 Optional 내부의 객체가 Predicate 조건에 부합하면 이 객체를 포함한 Optional 객체가 반환이 된다. 그렇지 않으면 Empty(빈) Optional 객체가 리턴이 된다.

 

더보기
더보기

예제1

import java.util.Optional;

public  class Prac {	
    public static void main (String[] args) { 
    	
    	Optional<String> opStr1 = Optional.of("first string");
    	Optional<String> opStr2 = Optional.of("second string");
    	
    	Optional<String> f1 = opStr1.filter(s -> s.contains("first"));
    	Optional<String> f2 = opStr2.filter(s -> s.contains("first"));
    	
    	f1.ifPresent(System.out::println);
    	f2.ifPresent(System.out::println);
    	
	}
	
}
first string

 

 

 

 

 

OptionalInt 클래스, OptionalLong 클래스, OptionalDouble 클래스

  • 기본형을 값으로하는 Optional 클래스다.
Optional 클래스 값을 반환하는 메서드
Optional<T> T get()
OptionalInt int getAsInt()
OptionalLong long getAsLong()
OptionalDouble double getAsDouble()

 

💡 참고

  • 기본형 Optional 클래스에서 empty optional 과 기본형 타입의 기본값과 다르다.
OptionalInt opt1 = OptionalInt.of(0);  // OptionalInt에 0을 저장
OptionalInt opt2 = OptionalInt.empty();  // OptionalInt에 0을 저장

System

 

더보기
더보기

예제1

import java.util.OptionalInt;

public  class Prac {	
    public static void main (String[] args) { 
    	
    	OptionalInt opt1 = OptionalInt.of(0);  // OptionalInt에 0을 저장
    	OptionalInt opt2 = OptionalInt.empty();  // OptionalInt에 0을 저장
    	
    	System.out.println(opt1.isPresent());  // true
    	System.out.println(opt2.isPresent());  // false
    	
    	System.out.println(opt1.getAsInt());  // 0
//    	System.out.println(opt2.getAsInt());  // NoSuchElementExcpetion 예외 발생
    	
    	System.out.println(opt1.equals(opt2));  // false
	}
	
}
true
false
0
false
  • OptionalInt에 저장된 값이 '0'인 것과 없는 것은 구별 가능하다.

 

 

 

 

728x90