Optional은 Java8에서 추가된 클래스이다. NullPointerException
예외를 방지해주는 역할을 한다.
개발을 하면서 가장 유의해야할 에러 중 하나이고, 개발하면서 굉장히 자주 만나게 되는 녀석이다.
Null
인 녀석의 변수나 메서드를 참조할 때 발생한다.
// Id가 1인 사용자를 찾아서 이름을 출력하는 코드
User user = userRepository.findById(1L);
String username = user.getName();
System.out.println(username);
예를 들어서 위와 같은 코드가 있다고 해보자.
이 코드는 사용자(user)가 정상적으로 조회됐다면 문제가 없다.
하지만, Id가 1인 사용자가 존재하지 않은 경우엔 문제가 되는 코드이다.
왜냐하면, 그때는 user
가 Null
이 되기 때문이다.
이렇게 된 상태에서 user.getName()
코드가 실행되면 Null에서 .getName()
메서드를 호출한 꼴이 되므로 NullPointerException
이 발생하게 된다.
그렇다면 이런 문제를 Optional로 어떻게 해결할 수 있을까?
위의 예제코드를 Optinal을 활용하여 보완해보자.
// Id가 1인 사용자를 찾아서 이름을 출력하는 코드
Optional<User> optionalUser = userRepository.findById(1L);
optionalUser.orElseThrow(() -> {
// 에러 던지기
});
User user = optionalUser.get();
String username = user.getName();
System.out.println(username);
레포지토리에서 user를 가져올 때, Optional로 감싸서 가져왔다.
그 후에는 Optional객체에 null이 들어있으면 에러를 던지도록하였고, 그렇지 않은 경우에만 사용자의 이름을 출력하도록 하였다.
이런식으로 Optional을 활용하면 NullPointerException이 터질 위험을 방지할 수 있게 된다.
DATA JPA와 같은 라이브러리를 써보면, 단 건의 데이터를 조회할 때는 Optional객체를 return해준다.
그리고 Optinal클래스는 다양한 기능을 제공하고 있는데 어떤 것들이 있는지 한번 살펴보도록하자.
Optional.empty()
내부가 비어있는(Null인) Optional객체를 생성한다.
Optional.of("hello world")
인자에 확실히 Null이 아닌 값을 넘겨줘서 생성한다.
인자가 Null이면, NullPointerException
이 발생한다.
Optional.ofNullable(IDontKnow)
인자에 Null일수도 있고 아닐수도 있는 값을 넘겨줘서 생성한다.
이렇게 Optional객체가 만들어지게 된다.
그렇다면 이번엔 이렇게 만들어진 Optional객체들을 어떻게 활용할 수 있는지 한번 알아보자.
User user = optional.get();
Optional객체가 감싸고 있는 녀석을 꺼내온다.
비어있는 Optional객체라면, NoSuchElementExeption
이 터진다.
Boolean exist = optional.isPresent();
내부가 비어 있는지 아닌지 확인하는 메서드이다.
내부가 비어있지 않다면, true
를 return한다.
optional.ifPresent(() -> {
// 뭔가 실행
})
Optional 객체의 내부가 비어있지 않다면, 콜백함수가 실행이 된다.
User user = optional.orElse("몰러");
Optional 객체의 내부가 비어있지 않다면, 그 값을 return하고 비어 있다면 다른 것을 return한다.
이 때 "다른 것"은 인자로 넘겨주면 된다.
Optional<User> user1 = userRepository.findById(1L);
User user = user1.orElseGet(() -> {
Optional<User> user2 = userRepository.findById(2L);
return user2.get();
});
orElse()와 비슷하게 동작하는 녀석이다.
Optional 객체의 내부가 비어있지 않다면, 그 값을 return하고 비어 있다면 인자로 넘어온 함수를 실행한다.
인자로 넘어온 함수에서도 null
이 반환되면 NullPointerException
이 터진다.
User user = optional.orElseThrow(() -> {
return new IllegalArgumentException("잘못됐어!");
});
이 메서드는 Optional객체의 내부가 비어있으면 예외를 던지는 녀석이다.
그 외에도 아래와 같은 메서드들이 있다 ㅎㅎ
아래의 메서드들에 대한 상세한 내용은 공식문서를 참고하도록 하자