Java7 부터 Objects.requireNonNull() 메소드가 있어 더 이상 null 검사를 수동으로 하지 않아도 된다.
<java />//생성자 public ClassName(Long id, Long fromMemberId, Long toMemberId, LocalDateTime createAt) { this.id = id; this.fromMemberId = Objects.requireNonNull(fromMemberId) ; this.toMemberId = Objects.requireNonNull(toMemberId); this.createAt = Objects.requireNonNullElse(createAt, LocalDateTime.now()); }
1. Object.requireNonNull() : 반드시 not null 이어야 하는 경우 (java 1.8 지원)
- null이면 NullPointException 발생
- 사용 예)
- this.fromMemberId = Objects.requireNonNull(fromMemberId) ;
- this.fromMemberId = Objects.requireNonNull(fromMemberId, "fromMemberId에 값이 없습니다.") ;
2. Object.requireNonNullElse(객체, default) : null 일 경우 기본 값 리턴 (java 1.9 지원)
- 사용 예)
- this.createAt = Objects.requireNonNullElse(createAt, LocalDateTime.now());
- Java 1.8까지는 아래와 같이 코딩
- this.createAt = createAt == null ? LocalDateTime.now() : createAt;
- 객체가 null이면, 람다식 결과를 리턴
- 실행 시기 결정 가능 - Lazy Evaluation
- 앞의 파라미터가 null인 경우에만 람다식을 실행하기 때문에 requireNonNullElse의 default에 메소드 리턴값을 넣는 것보다 성능이 빠르다.
- requireNonNullElse 는 성능에 영향이 거의 없는 경우 사용
- Object 생성 또는 메소드 호출로 인한 성능 지연을 줄이고 싶은 경우 requireNonNullElseGet 을 사용
<java />this.direction = Objects.requireNonNullElseGet(direction, () -> System.getProperty(“com.direction.default”)) this.modulemdApi = Objects.requireNonNullElseGet(modulemdApiIn, ModulemdApi::new); this.color = Objects.requireNonNullElseGet(color, () -> new Color(0, 0, 0)); service = Objects.requireNonNullElseGet(val, () -> "rmi://localhost:" + Registry.REGISTRY_PORT + "/" + ReflectionHelper.getClassBaseName(this.getClass())); Supplier<String> defaultMemberName = () -> "홍길동"; this.memberName = Objects.requireNonNullElseGet(memberName, defaultMemberName);
4. Test Case 작성 예
<java />class A { private final String x; public A(String x) { this.x = x; } public String getX() { return x; } } //Test Java public class ATests { private A createNonNullA() { return new A("x"); } private A createNullA() { return null; } @DisplayName("requireNonNull - not null 일때 통과한다.") @Test void testRequireNonNull1() { A a = createNonNullA(); Objects.requireNonNull(a); assertDoesNotThrow(() -> (Objects.requireNonNull(a))); } @DisplayName("requireNonNull - null 일때 빈 메시지의 NPE 를 던진다.") @Test void testRequireNonNull2() { A a = createNullA(); assertThrows(NullPointerException.class, () -> Objects.requireNonNull(a)); } @DisplayName("requireNonNull - null 일때 2번 매개변수 메시지의 NPE 를 던진다.") @Test void testRequireNonNull3() { A a = createNullA(); Exception exception = assertThrows(NullPointerException.class, () -> Objects.requireNonNull(a, "For input A instance")); String expectedMessage = "For input A instance"; String actualMessage = exception.getMessage(); assertTrue(actualMessage.contains(expectedMessage)); } @DisplayName("requireNonNull - null 일때 Supplier<String> 메시지를 NPE 에 담아 를 던진다.") @Test void testRequireNonNull4() { A a = createNullA(); Exception exception = assertThrows(NullPointerException.class, () -> Objects.requireNonNull(a, () -> ("hello"))); String expectedMessage = "hello"; String actualMessage = exception.getMessage(); assertTrue(actualMessage.contains(expectedMessage)); } @DisplayName("requireNonNullElse - 둘 다 not null 일때 1번 매개변수를 리턴한다.") @Test void testRequireNonNullElse1() { A a1 = new A("x"); A a2 = new A("y"); A actualA = Objects.requireNonNullElse(a1, a2); assertEquals(a1, actualA); } @DisplayName("requireNonNullElse - 1번 매개변수가 null 일때 2번 매개변수를 리턴한다.") @Test void testRequireNonNullElse2() { A a1 = createNullA(); A a2 = new A("y"); A actualA = Objects.requireNonNullElse(a1, a2); assertEquals(a2, actualA); } @DisplayName("requireNonNullElse - 둘 다 null 일때 NPE 를 던진다.") @Test void testRequireNonNullElse3() { A a1 = createNullA(); A a2 = createNullA(); assertThrows(NullPointerException.class, () -> Objects.requireNonNullElse(a1, a2)); } @DisplayName("requireNonNullElseGet - 1번 매개변수가 null이면 Supplier 를 리턴한다.") @Test void testRequireNonNullElseGet() { String expected = "x"; String actual = Objects.requireNonNullElseGet(null, () -> "x"); assertEquals(expected, actual); } // ---------------------------------------------------------------- @DisplayName("checkIndex - 0 <= index < length 일때 index 반환한다.") @Test void testCheckIndex1() { int index = 4; int length = 5; assertEquals(index, Objects.checkIndex(index, length)); } @DisplayName("checkIndex - index >= length 일때 IndexOutOfBoundsException 던진다.") @Test void testCheckIndex2() { int index = 5; int length = 3; assertThrows(IndexOutOfBoundsException.class, () -> Objects.checkIndex(index, length)); } @DisplayName("checkFromToIndex - from ~ to 가 0 ~ length 사이에 있으면 fromIndex 를 리턴한다.") @Test void testCheckFromToIndex1() { int fromIndex = 0; int toIndex = 3; int length = 3; assertEquals(fromIndex, Objects.checkFromToIndex(fromIndex, toIndex, length)); } @DisplayName("checkFromToIndex - from ~ to 가 0 ~ length 사이에 없으면 IndexOutOfBoundsException 를 던진다.") @Test void testCheckFromToIndex2() { int fromIndex = 0; int toIndex = 5; int length = 3; assertThrows(IndexOutOfBoundsException.class, () -> Objects.checkFromToIndex(fromIndex, toIndex, length)); } @DisplayName("checkFromIndexSize - from ~ from+size 가 0~length 사이에 있으면 from을 리턴한다.") @Test void checkFromIndexSize1() { int length = 5; assertEquals(3, Objects.checkFromIndexSize(3, 2, length)); } @DisplayName("checkFromIndexSize - from ~ from+size가 0~length 사이에 없으면 IndexOutOfBoundsException 를 던진다.") @Test void checkFromIndexSize2() { int length = 5; assertThrows(IndexOutOfBoundsException.class, () -> Objects.checkFromIndexSize(3, 3, length)); } }
추가 참고 Java 8의 Optional
https://blog.naver.com/ghdalswl77/222892924327
Objects.requireNonNullElse VS Optional
<java />Objects.requireNonNullElse(Obj, null); ==> NullPointException 발생 Optional.ofNullable(nullStr).orElse(null); ==> null jshell> Optional.ofNullable(nullStr).orElseGet(() -> null); ==> null
<java />String str = null; String result = str == null ? "other string" : str; //or result = Objects.requireNonNullOrElse(str,"other string); //or result = Optional.ofNullable(str).orElse("other string");
'프로그래밍 > Java-Spring' 카테고리의 다른 글
Java 함수형 프로그래밍 (0) | 2023.01.17 |
---|---|
Java 8 함수형 인터페이스 (Functional Interface) (0) | 2023.01.11 |
5. 와일드카드 타입 <?>, <? extends ...> <? super ...> (0) | 2023.01.11 |
@RequiredArgsConstructor 를 이용한 의존성 주입 (0) | 2022.12.14 |
Multi SpringApplication 을 선택 처리하는 방법 (0) | 2021.02.26 |