안녕하세요. 씨엔스입니다.
우리가 개발을 할 때 가장 많이 발생하는 예외 처리 중 하나가 바로 NullPointerException 이라 생각합니다.
Null 오류를 발생시키지 않기 위해서 지금까지는 분기처리를 통해 Null 체크 여부를 확인했는데,
자바 8 버전에서 나온 Optional 클래스를 통해 NPE 방지를 알아보도록 하겠습니다.
- Java 8 버전 이전 null 예외처리 방식
1
2
3
4
5
6
7
8
9
10
11
|
class CodeRunner{
public static void main(String[] args){
List<String> names = null;
List<String> list = getNames();
// null 인 경우
if(list != null) {
// next step
}
}
}
|
cs |
ㅇㅇㅇㅇㅇ
기존에는 null이 발생하는 상황이 생길 경우 if문을 이용하여 null을 체크 하지만, 이와 같은 경우 코드의 가독성이 떨어지고 해당 객체가 null을 가질 수 있는 객체인지, 필수 값인지 직관적으로 알 수 있는 방법이 없어 오류를 찾더라도 해결하기에 어려움이 발생할 수 있었습니다.
- Java 8 버전에 나온 Optional을 사용한 방식
1
2
3
4
5
6
7
8
9
10
|
class CodeRunner{
public static void main(String[] args){
List<String> list = getNames();
// list 가 null 인지 아닌지 체크
Optional <List<String>> optional = Optional.ofNullable(list);
System.out.println(optional); // Optional.empty
System.out.println(optional.isPresent()); // false
}
}
|
cs |
Java 8 버전에 처음 도입된 Optional은 값이 존재할 수도 있고, 아닐 수도 있는 값을 객체로 포장해주는 클래스입니다.
null 체크를 직접 할 필요가 없고 NPE가 발생할 가능성이 있는 값을 다룰 필요가 없다는 장점이 있습니다.
Optional 사용하기
- Optional.empty() : 비어있는 Optional 객체 생성하기(return : Optional.empty)
1
|
Optional<String> opt = Optional.empty(); // 비어있는 Optional 객체를 생성
|
cs |
- Optional.of() : Null 값이 없는 Optional 객체 생성하기(값이 null 이면 NPE 발생)
1
|
Optional<String> opt = Optional.of("value 존재"); // 값이 존재하는 Optional 객체 생성(Optional[value 존재])
|
cs |
- Optional.ofNullable() : null 이거나 값이 있을 수 있는 객체를 생성한다. (null 여부를 확신할 수 없을 때)
1
2
3
|
// Optional의 value는 값이 있을 수도 있고 null 일 수도 있다.
Optional<String> optional1 = Optional.ofNullable(null);
Optional<String> optional2 = Optional.ofNullable("value 존재");
|
cs |
Optional 값 체크하기
- get() : Optional의 값을 가져오고, 비어있는 Optional 객체에 대해서는 NoSuchElementException 오류가 발생한다.
1
2
|
Optional<String> opt = Optional.of("value 존재"); // Optional 값이 존재
System.out.println(opt.get()); // return value 존재
|
cs |
- orElse() : 비어있는 Optional 객체에 대하여 orElse로 넘어온 값을 반환한다.
1
2
|
Optional<String> opt1 = Optional.empty(); // 빈 Optional 객체
System.out.println(opt1.orElse("value")); // return value
|
cs |
- orElseGet() : 비어있는 Optional 객체에 대하여 orElseGet로 넘어온 함수형 값을 통해 생성된 객체를 전달한다.
1
2
|
Optional<String> opt2 = Optional.empty(); // 빈 Optional 객체
System.out.println(opt2.orElseGet(() -> new String("새로운 값"))); // return value
|
cs |
- orElseThrow() : 비어있는 Optional 객체에 대하여 orElseThrow로 넘어온 함수형 값을 통해 오류를 발생시킨다.
1
2
|
Optional<String> opt3 = Optional.empty(); // 빈 Optional 객체
System.out.println(opt3.orElseThrow(RuntimeException::new)); // return value
|
cs |
- map() : Optional 객체의 값을 원하는 형태로 형변환을 할 수 있다.
1
2
|
Optional<String> opt = Optional.of("TEST"); // Optional 객체 값 존재할 경우
System.out.println(opt.map(String::length)); // Optional 객체의 형태를 변경
|
cs |
- filter() : filter 메소드의 인자로 받은 람다 식이 참이면 Optional 객체를 그대로 통과시키고 거짓이면 Optional.empty()를 반환해서 추가로 처리가 안되도록 한다.
1
2
|
Optional<String> opt = Optional.of("test");
System.out.println(opt.filter(v -> v.equals("TEST"))); // true : Optional[TEST] , false : Optional.empty
|
cs |
정리
- Optional 객체를 사용할 경우 null을 선언할 필요가 없습니다.
- 반환하는 경우에만 사용하자.
- 상황에 맞게 사용해야한다. (남발하지말라, 오히려 독이 된다.)
아직 실무에서 적용해본 적이 없어 저도 미숙하기에 이렇게 정리를 하면서 공부해보았는데, 실제 소스에서의 null 처리를 Optional을 통해 진행해볼까 합니다.
감사합니다.
-참고자료
- https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html
- https://hbase.tistory.com/212
- https://tecoble.techcourse.co.kr/post/2021-06-20-optional-vs-null/
- https://lee1535.tistory.com/139
'Language > Java' 카테고리의 다른 글
[JPA] 공통 Entity 에 사용되는 @MappedSuperClass 과 상속 관계 (1) | 2024.01.03 |
---|---|
[Swagger docs]Spring 3.x.x 버전에서 swagger 사용법 (1) | 2023.12.27 |