TIL 2021.03.20

Kyu·2021년 3월 20일
0

TIL

목록 보기
69/322

오늘은 Optional 을 사용하는 방법을 배웠다.

Optional

Optional은 null값을 피하기 위해서 나온 기능이다. Optinal variables_name 이렇게 쓰면 된다. T에는 넣고 싶은 객체를 넣는다.

Optinal의 isPresent() 메서드와 isEmpty() 메서드는 객체에 null값이 아니라 어떤 값을 가지고 있는지 묻는 메서드이다.

empty()

예를 들어서,
Optional str1 = Optional.empty(); 라고 라면 null값을 담고있는 Optional을 str1에 주입을 한 것인데, print()로 str1.isPresent()와 str1.isEmpty()를 확인해보면 각각 false, true가 나오게 된다.

of()

또 다른 예시로,
Optional.empty() 대신에 of() 메서드를 활용하면 Optional.of("Test Value") 이런 식으로 쓸 수 있고 Test Value를 담고있는 Optional을 주입할 후 있다. 이전 예시와 똑같이 isPresent()와 isEmpty()를 print()로 확인해보면 각각 true, false가 나오게 된다.

orElse()

현재 Optinal인 str1에서 여러가지 메서드를 사용 할 수 있는데, 그 중에 orElse()는 str1이 null이면 설정하도록 하는 기본값을 넣을 수 있다. str1.orElse("This sentence is shown when str1 is null.")를 print() 해보자. 이전에 of()의 인자로 넣었던 Test Value가 출력된다.

헷갈리는 부분

참고로 str1.orElse("This sentence is shown when str1 is null.") 부분을 String 변수에 담을 수 있는데 이부분이 조금헷갈렸다. 왜냐하면 str1은 Optional을 주입받은 것이고 거기에서 메서드를 꺼내 쓰는 거였기 때문이다. 근데 생각해보니 여기서 메서드를 꺼내쓴다고 당연히 Optional만 리턴하는 것은 아닐것이다. 그리고 지금 orElse()에 인자로 넣은 문자열을 리턴하는 것 자체가 String 타입을 리턴하기 때문이지 않은가?

ofNullable()

어쨋든 다시 처음으로 돌아가서,
str1이 null일지 아닐지 확신이 없을 땐 어떻게 해야할까? 현재 str1은 of()에 의해 Test Value를 담고 있는 Optional이다. of()에 null을 넣어볼까? of()를 사용한다는 것은 값이 들어오길 기대하면서 사용하는 것이기 때문에 null을 넣으면 NullPointerException이 발생한다.

이때 of 뒤에 Nullable를 붙여서 사용하면 된다. Optional str1 = Optional.ofNullable(null); 이라고 하면, 현재 str1은 아무것도 담고 있지 않았기 때문에 ofNullable에 의해 NullPointerException은 발생하지 않고 Null이 된다.

모르겠는 부분

ofNullable()을 쓰는 이유는 무엇인가? str1에 일부러 null을 주입하는 상황도 있나? 여기서 str1이 아무것도 담고있지 않기때문에 null이라고 하는데 무슨 말인지 이해가 안된다. 내가 null을 넣어줬잖아.

이때 isPresent()와 isEmpty()를 사용해서 확인해보면 각각 false, true가 나오는 것을 확인할 수 있다. 또 orElse() 인자로 넣었던 문장도 확인할 수 있을 것이다.

위에 과정을 이때까지 해오던 방식대로 작성하면 어떻게 될까? 일단 코드는 아래와 같이 작성될 것이다.

String str1 = null;
String substitutedStr1;

if (str1 != null) {
substitutedStr1 = "This sentence is shown when str1 is null.";
}

간략히 말해서 위와 같이 작성하면 이런저런 문제가 많기 때문에 Optional을 사용하는 것이다.

map()

그리고 추가적으로 str1.orElse("This sentence is shown when str1 is null.") 사이에 map()을 이용해서 str1에 대한 함수를 넣을 수 있다.

예를 들어서

String str2 = str1
                     .map(System::toUpperCase)
                     .orElse("This sentence is shown when str1 is null.")

이런 식으로 람다식을 이용해 넣으면 그대로 반영되서 모두 대문자로 나오는 식으로 만들수가 있다.

orElseGet()

그리고 orElse() 대신에 orElseGet() 이라는 것을 사용할 수 있는데 여기에도 람다식을 이용할 수 있다. 예를 들어, 이미 결정된 상수가 아니라 때에 따라 리턴값을 달리하기 위해서 추가적인 로직을 구현할 수있다. 코드로 표현하면 아래와 같다.

String str2 = str1
                      .map(System::toUpperCase)
                      .orElseGet(() -> {
                      [...extra computation to retrieve the value...] 
                      return "Hello World";
                      });

이렇게 적으면 str1이 null일 경우에 대신할 어떤 데이터를 꺼내쓰는 로직을 구현하고 리턴할 수 있을 것이다.

or(), orElseThrow()

그리고 or()을 이용해서 Optional을 리턴해주는 방법도 있도 orElseThrow()를 이용해서 예외처리를 해줄수도 있다

profile
TIL 남기는 공간입니다

0개의 댓글