Optional

GoshK·2021년 9월 11일
0

Optional
Optional은 Java 8 부터 도입 되었으며 이전 버전까지 Java 의 고질적인 문제였던 NullPointerException 을 해결하기 위해 등장하였습니다.

Optional 객체 생성
Optional 객체를 생성하기 위해서는 Optional.of/Optional.ofNullable/Optional.empty 이렇게 3가지 방법을 사용할 수 있습니다.

public class Main {
    public static void main(String[] args) {
        String str = "Hello";

        Optional<String> ofOpt = Optional.of(str);
        //null 값이 들어오는 경우 NullPointerException 이 발생하게 됩니다.

        Optional<String> nullableOpt = Optional.ofNullable(str);
        //null 값이 들어올 경우 예외 없이 빈 Optional 객체를 반환합니다.

        Optional<String> emptyOpt = Optional.empty();
        //비어있는 Optional 객체를 생성합니다.
    }
}

Optional 메서드

isPresent() 객체가 존재하면 true 를 반환해 줍니다.

        String str = "Hello";

        Optional<String> nullableOpt = Optional.ofNullable(str);

        System.out.println(nullableOpt.isPresent()); //true

get() 최종적으로 연산을 끝낸 후 객체를 반환합니다. 이때 값이 없다면 예외를 반환합니다.

        String str = "Hello";

        //값이 있는 경우
        Optional<String> nullableOpt = Optional.ofNullable(str);

        System.out.println(nullableOpt.get()); //Hello

        //값이 없는 경우
        nullableOpt = Optional.ofNullable(null);

        nullableOpt.get();//NoSuchElementException

orElse(), orElseGet() 최종적으로 연산을 끝낸 후에도 객체가 비어있다면 다른 제공할 객체를 지정하여 반환합니다. orElse 와 orElseGet 은 매우 유사하지만 orElseGet 메서드는 매개변수로 Supplier 를 받으며 Optional 에 값이 없을 경우에만 실행된다고 합니다.(orElse 는 값이 있던 없던 무조건 실행)


        String str = "Hello";
        String noValue = null;
		
        //orElse
        String s = Optional.ofNullable(noValue).orElse(str);
        System.out.println(s); //Hello
        
        //orElseGet
        String s = Optional.ofNullable(noValue).orElseGet(() -> str);
        System.out.println(s);//Hello
    

orElseThrow() 최종적으로 연산을 끝낸 후에도 값이 없을 경우 예외를 지정하여 던져줄 수 있습니다.

        String str = "Hello";
        String noValue = null;

        Optional.ofNullable(noValue).orElseThrow(() -> new MyException("값을 입력해 주세요"));

ifPresent() 값이 존재하는 경우 동작을 지정하여 실행시켜 줍니다.

        String str = "Hello";
        String noValue = null;

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

flatMap() Optional 구조로 감싸진 객체를 단일 요소로 만들어 줍니다.

class User {
    private String name;
    private int age;
	
    //나이가 null 일지도 모른다고 가정해서 Optional 로 감쌌다.
    public Optional<Integer> getAge() {
        return Optional.ofNullable(age);
    }
}

public class Main {
    public static void main(String[] args) {
    	//Optional[Optional[0]] - map 사용시
        System.out.println(Optional.ofNullable(new User()).map(User::getAge));
        
        //Optional[0] - flatMap 사용시
        System.out.println(Optional.ofNullable(new User()).flatMap(User::getAge));
    }
}

Optional 사용의 올바른 예

https://homoefficio.github.io/2019/10/03/Java-Optional-%EB%B0%94%EB%A5%B4%EA%B2%8C-%EC%93%B0%EA%B8%B0/

https://www.latera.kr/blog/2019-07-02-effective-optional/

if문 + isPresent() + get() 대신 orElse()/orElseGet() 을 사용하여 코드를 더욱 깔끔하게

String str = "Hello";

Optional<String> ofOpt = Optional.ofNullable(str);

//bad
if(ofOpt.isPresent()) {
System.out.println(ofOpt.get());
} else {
System.out.println("null");
} //Hello

//good
System.out.println(ofOpt.orElse(null)); //Hello

Optional 을 제너릭 타입에 맞춰야 할 경우가 아니라면 Optional 대신 OptionalXXX 타입을 사용할 것을 권장

        //soso
        Optional<Integer>.of(123);

        //good
        OptionalInt.of(123);
        OptionalDouble.of(10.0);
        OptionalLong.of(10L);

Optional 을 필드로 사용하지 말기

//bad
class User {
    private String name;
    private Optional<Integer> age;
}

//good
class User {
	private String name;
    private int age;
    
    public OptionalInt getAge() {
    	return OptionalInt age;
    }

0개의 댓글