Justin의 개발 로그

Java7 부터 Objects.requireNonNull() 메소드가 있어 더 이상 null 검사를 수동으로 하지 않아도 된다.

    //생성자
    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());
    }

Object.requireNonNull() : 반드시 not null 이어야 하는 경우 (java 1.8 지원)

  • null이면 NullPointException 발생
  • 사용 예)
    • this.fromMemberId = Objects.requireNonNull(fromMemberId) ;
    • this.fromMemberId = Objects.requireNonNull(fromMemberId, "fromMemberId에 값이 없습니다.") ;

 

Object.requireNonNullElse(객체, default) : null 일 경우 기본 값 리턴 (java 1.9 지원)

  • 사용 예)
    • this.createAt = Objects.requireNonNullElse(createAt, LocalDateTime.now());
  • Java 1.8까지는 아래와 같이 코딩
    • this.createAt = createAt == null ? LocalDateTime.now() : createAt;

 

public static <T> T requireNonNullElseGet(T obj, Supplier<? extends T> supplier)

  • 객체가 null이면, 람다식 결과를 리턴
  • 실행 시기 결정 가능 - Lazy Evaluation
  • 앞의 파라미터가 null인 경우에만 람다식을 실행하기 때문에 requireNonNullElse의 default에 메소드 리턴값을 넣는 것보다 성능이 빠르다.
  • requireNonNullElse 는 성능에 영향이 거의 없는 경우 사용
  • Object 생성 또는 메소드 호출로 인한 성능 지연을 줄이고 싶은 경우 requireNonNullElseGet 을 사용
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 구현이 왜 성능이 더 좋은가?

 

Test Case 작성 예

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

Objects.requireNonNullElse(Obj, null);
 ==> NullPointException 발생

Optional.ofNullable(nullStr).orElse(null);
==> null

jshell> Optional.ofNullable(nullStr).orElseGet(() -> null);
==> null

 

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의 개발 로그

@라이프노트

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