티스토리 뷰

● 도입

- Optional을 이용해 해결할 수 있는 문제 = NPE(NullPointerException)

- Null 상태인 오브젝트를 레퍼런스 할 때 발생한다.
- Runtime error 이기 때문에 컴파일 과정에서는 발견할 수 없으며 실행 전 까지는 발생 여부를 알기 쉽지 않다.

 

출처 - 패스트캠퍼스

 

- NullPointerException 발생 예시

[두 object가 같은지 비교해보자]

package com.fastcampus.functionalprogramming.chapter7;

import com.fastcampus.functionalprogramming.chapter7.model.User;

public class Chapter7Section1 {
	public static void main(String[] args) {
		// 일부러 NullPointerException을 발생시켜보자
		User user1 = new User()
				.setId(1001)
				.setName("Alice")
				.setVerified(false);
		// user1은 setEmailAddress를 하지 않았다.
		  
		User user2 = new User()
				.setId(1001)
				.setName("Alice")
				.setEmailAddress("alice@fastcampus.co.kr")
				.setVerified(false);
		
		// 정상
		System.out.println(userEquals(user2, user1));
		
		// NullPointerException 발생
		System.out.println(userEquals(user1, user2));
	}
	
	  public static boolean userEquals(User u1, User u2) {
		  return u1.getId() == u2.getId()
				  && u1.getName().equals(u2.getName())
				  && u1.getEmailAddress().equals(u2.getEmailAddress())
				  && u1.isVerified() == u2.isVerified();
	  }
}

정상
user1 instance는 String인 emailAddressr 필드가 null 상태 / null.equals() 이기에 NullPointerException 발생

- 동일한 argument(user1, user2)를 넣었지만 단순히 순서를 바꾼 것만으로도 NullPointerException이 발생했다.

- null에 대한 체크를 사전에 제대로 하지 않았기 때문이다.

 

 

● Optional

- 이러한 문제를 해결하기 위해 필요한 것이 바로 Optional이다.

- Optional은 그 안에 Null 일수도 혹은 아닐 수도 있는 오브젝트를 담은 상자라고 생각하면 된다.

- 어떤 method의 return type이 Optional이라면 해당 return 값 안에 object가 있을 수도 or 없을 수도 있다고 예상할 수 있다.

java.util.Optional<T>

Optional<String> maybeString = Optional.of("Hello world");
String string = maybeString.get();

- String type의 Optional이 있을 때 maybeString 안에는 String instance가 있을 수도 있고 없을 수도 있다.
- get method를 통해 안에 있는 값을 꺼낼 수 있다.
[Optional 만드는 법]

public static <T> Optional<T> of(T value)
public static <T> Optional<T> empty()
public static <T> Optional<T> ofNullable(T value)

of
- Null이 아닌 오브젝트를 이용해 Optional을 만들 때
- 생성된 object instance가 이미 있을 때 해당 instance를 Optional 상자에 담을 때 사용
- Optional.of를 호출하고 Null을 넘기면 error 발생

Empty
- 빈 Optional을 만들 때
- 해당 type(= <T>)의 빈 상자를 만들 때

ofNullable
- Null인지 아닌지 알 지 못하는 오브젝트로 Optional을 만들 때
- Null이라면 알아서 빈 상자를 만들어준다.
- Null이 아니라면 해당 오브젝트가 들어있는 상자를 만들어준다.
[Optional 안에 있는 값을 확인하고 꺼내는 법]

public boolean isPresent()
public T get()
public T orElse(T other)
public T orElseGet(Supplier<? extends T> supplier)
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X

isPresent()
- Optional 안의 오브젝트가 null 인지 아닌지 체크(비어있는지 아닌지 체크)
- Null이 아닐 시 true(들어있으면 true)

get()
– Optional 안의 object를 추출
– Optional이 Null이면(비어있으면) 에러 발생

orElse(T other)
- 같은 타입의 object를 parameter로 받는다.
– Optional안에 object가 있다면(Optional이 null이 아니라면) Optional 안의 값을 return
- Optional안에 object가 null이라면(Optional이 비어있다면) parameter로 받은 other를 return

orElseGet(Supplier<? extends T> supplier)
- orElse와 다르게 return할 object를 바로 parameter로 받지 않는다.
- 대신 해당 type의 object를 받아 올 수 있는 supplier를 parameter로 받는다.
– Optional이 null이 아니라면 Optional 안의 값을, null이라면 supplier로 공급되는 값을 return

orElseThrow(Supplier<? extends X> exceptionSupplier)
- orElseGet와 비슷, 대신 exceptionSupplier를 parameter로 받는다.
– Optional이 null이 아니라면 Optional 안의 값을, null이라면 exceptionSupplier로 공급되는
exception을 던진다.
@FunctionalInterface
public interface Supplier<T> {
    T get();
}

- input은 없고 output(return)만 있는 함수형 인터페이스

 

 

● 실습

package com.fastcampus.functionalprogramming.chapter7;

import java.util.Optional;

import com.fastcampus.functionalprogramming.chapter7.model.User;

public class Chapter7Section1 {
	public static void main(String[] args) {
		// ------------------ Optional 만들기 ------------------
		String someEmail = "some@email.com";
		String nullEmail = null;
		
		// 1.
		Optional<String> maybeEmail = Optional.of(someEmail);
		// 2.
		Optional<String> maybeEmail2 = Optional.empty(); 			   // 빈 상자
		// 3.
		Optional<String> maybeEmail3 = Optional.ofNullable(someEmail); // null인지 아닌지 모르겠다.
		// 4.
		Optional<String> maybeEmail4 = Optional.ofNullable(nullEmail); // null인지 아닌지 모르겠다.
		
		// ------------------ Optional 안에 있는 값 꺼내기 ------------------
		// 1.
		String email1 = maybeEmail.get();
		System.out.println("email1 : " + email1);
		
		// 2.
		if(maybeEmail2.isPresent()) {							 // Optional 안에 값이 있는지 없는지 먼저 체크
			System.out.println("email2 : " + maybeEmail2.get()); // maybeEmail2 Optional이 비어있기 때문에 해당 부분은 실행될 수 없다.
		}
		
		// 3.
		String defaultEmail = "default@email.com";
		String email3 = maybeEmail2.orElse(defaultEmail);
		String email3_1 = maybeEmail.orElse(defaultEmail);
		System.out.println("email3 : " + email3);
		System.out.println("email3_1 : " + email3_1);
		
		// 4.
		String email4 = maybeEmail2.orElseGet(() -> defaultEmail);
		String email4_1 = maybeEmail.orElseGet(() -> defaultEmail);
		System.out.println("email4 : " + email4);
		System.out.println("email4_1 : " + email4_1);
		
		// 5.
		String email5 = maybeEmail.orElseThrow(() -> new RuntimeException("email not present"));
		System.out.println("email5 : " + email5);
		
		String email5_1 = maybeEmail2.orElseThrow(() -> new RuntimeException("email not present"));
		System.out.println("email5_1 : " + email5_1);
	}
}

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함