Justin의 개발 로그

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);

Supplier 구현이 왜 성능이 더 좋은가?

 

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");

 

profile

Justin의 개발 로그

@라이프노트

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!