programing

Objects.requireNonNull()을 사용해야 하는 이유는 무엇입니까?

prostudy 2022. 6. 9. 22:07
반응형

Objects.requireNonNull()을 사용해야 하는 이유는 무엇입니까?

8 은 Oracle JDK® Java 8을 사용하고 .Objects.requireNonNull() 슬로우)NullPointerException된 오브젝트가 "(복수:)"인 null.

public static <T> T requireNonNull(T obj) {
    if (obj == null)
        throw new NullPointerException();
    return obj;
}

★★★★★★★★★★★★★★★★★.NullPointerException null오브젝트는 참조되지 않습니다.왜 이 "" "" " " " " " " " " " " 행 " " " " " " 을 던질 ?NullPointerException

한 가지 분명한 답변(또는 이점)은 코드를 더 잘 읽을 수 있게 해준다는 것이며, 저도 동의합니다.에 또 이유를 쓰는지 궁금하네요.Objects.requireNonNull()이 방법의 선두에 있습니다.

그래야 일을 분명히 할 수 있기 때문입니다.예를 들어 다음과 같습니다.

public class Foo {
  private final Bar bar;

  public Foo(Bar bar) {
    Objects.requireNonNull(bar, "bar must not be null");
    this.bar = bar;
  }

또는 단축:

  this.bar = Objects.requireNonNull(bar, "bar must not be null");

이제 아시겠죠?

  • Foo 오브젝트가 정상적으로 생성되었을 때new()
  • 그러면 해당 막대 필드가 비균형임을 보증합니다.

오늘 Foo 객체를 만들고 내일 해당 필드를 사용하여 슬로우하는 메서드를 호출합니다.아마 내일이면 그 참조가 왜 어제 컨스트럭터에게 전달되었을 때 null이었는지 알 수 없을 것입니다.

즉, 이 메서드를 명시적으로 사용하여 수신 참조를 체크함으로써 예외가 발생하는 시점을 제어할 수 있습니다.그리고 대부분의 경우, 여러분은 가능한 한 빨리 실패하기를 원합니다!

주요 장점은 다음과 같습니다.

  • 앞서 말한 바와 같이, 통제된 행동
  • 디버깅이 쉬워집니다.오브젝트 작성 컨텍스트에서 토할 수 있기 때문입니다.로그/트레이스를 통해 무엇이 잘못되었는지 알 수 있는 특정 시점에!
  • 그리고 위와 같이: 이 아이디어의 진정한 힘은 최종 분야와 함께 펼쳐집니다.왜냐하면 이제 당신 클래스의 다른 어떤 코드도 안전하게bar 무효가 필요 .따라서 아무것도 필요 없습니다.if (bar == null)른른른른!

Fail-Fast

가능한 한 빨리 코드가 크래시됩니다.작업의 절반은 하지 않고 null을 참조하고 크래시만 하면 일부 작업이 완료되어 시스템이 비활성화 상태가 됩니다.

이것은 일반적으로 "fail early" 또는 "fail-fast"라고 불립니다.

단, Null Pointer는Null 객체가 참조되지 않으면 예외가 발생합니다.그럼 왜 이 추가 null 체크를 하고 null Pointer를 던질 필요가 있을까요?예외?

즉, 문제를 즉시 확실하게 검출할 수 있습니다.

고려사항:

  • 참조는 메서드의 후반부에서 코드가 이미 부작용을 수행한 후까지 사용되지 않을 수 있습니다.
  • 이 방법에서는 참조가 전혀 참조되지 않을 수 있습니다.
    • 완전히 다른 코드로 전달될 수 있습니다(즉, 코드 공간에서 원인과 오류가 멀리 떨어져 있습니다).
    • 훨씬 나중에 사용할 수 있습니다(즉, 원인과 오류는 시간적으로 멀리 떨어져 있습니다).
  • Null 참조가 유효한 곳에서 사용할 수 있지만 의도하지 않은 효과가 있습니다.

. 에서는, 을 하는 것으로써, 합니다.NET net net 、 NET net net net net 、 [ NET ]NullReferenceException(' 값'을 했습니다)에서('null 값'을 참조했습니다)ArgumentNullException(이 파라미터에 대한 인수로서 null을 전달하지 말았어야 합니다).자바도 그랬으면 좋겠지만NullPointerException에러가 검출될 수 있는 가장 이른 시점에서 에러가 발생했을 경우, 코드를 수정하는 것이 훨씬 쉬워집니다.

「」를 사용합니다.requireNonNull()메서드의 첫 번째 문장으로서 예외의 원인을 지금 바로/빠르게 식별할 수 있습니다.
스택 트레이스에서는, 발신자가 요건이나 계약을 따르지 않았기 때문에, 메서드의 입력과 동시에 예외가 발생했음을 명확하게 나타내고 있습니다.패스 anull다른 방법에 대한 반대는 실제로 한 번에 예외를 일으킬 수 있지만, 문제의 원인을 이해하는 것은 더 복잡할 수 있습니다. 왜냐하면 예외는 특정 호출에 던져지기 때문입니다.null을 사용하다


, 특히 fail fast를 해야 하는 이유를 를 제시하겠습니다.Object.requireNonNull() "no null check"가 것으로 null

를 들면,Dictionary LookupService a. a. a.ListString포함된 단어를 나타냅니다.이 필드들은 다음과 같이 설계되어 있습니다.null그 중 하나가 다음 단계로 넘어갑니다.Dictionary컨스트럭터

, 그럼 '나쁜을 '나쁜'으로 구현했다고 해 보겠습니다.Dictionary 없이null메서드 엔트리에 체크인을 합니다(여기서는 컨스트럭터입니다).

public class Dictionary {

    private final List<String> words;
    private final LookupService lookupService;

    public Dictionary(List<String> words) {
        this.words = this.words;
        this.lookupService = new LookupService(words);
    }

    public boolean isFirstElement(String userData) {
        return lookupService.isFirstElement(userData);
    }        
}


public class LookupService {

    List<String> words;

    public LookupService(List<String> words) {
        this.words = words;
    }

    public boolean isFirstElement(String userData) {
        return words.get(0).contains(userData);
    }
}

이번에는 ' 아, 아, 아, 아, 아, 맞다'를 불러볼까요?Dictionary with a 를 가진 null에 참조words: " " " : "

Dictionary dictionary = new Dictionary(null); 

// exception thrown lately : only in the next statement
boolean isFirstElement = dictionary.isFirstElement("anyThing");

JVM은 다음 스테이트먼트에서 NPE를 슬로우합니다.

return words.get(0).contains(userData); 
스레드 "main" java.lang에 예외가 있습니다.특수한 포인터예외.LookupService.isFirstElement(LookupService).자바:5)Dictionary.isFirstElement(Dictionary.java:15)에 있는Dictionary.main (Dictionary.java:22)에 있는

는 「」로 됩니다.LookupService이전인 (클래스)Dictionary하게 할 수 없습니다.이로 인해 전체적인 문제 분석이 훨씬 덜 명확해집니다.
이는?words null? ? ??words.get(0) null? 왜 둘 ?null에서의 코딩 에러입니까?Dictionary(혹은?)호출된 메서드) ?의 코딩 오류입니까?LookupService ( (된 메서드는 호출된 메서드입니까는 호출된 메서드입니까?
마지막으로 에러 발생원을 찾기 위해 더 많은 코드를 검사해야 하며, 더 복잡한 클래스에서는 무슨 일이 일어났는지 더 쉽게 이해하기 위해 디버거를 사용할 수도 있습니다.
하지만 왜 단순한 것(무효 체크의 결여)이 복잡한 문제가 되는가?
하부 컴포넌트의 특정 컴포넌트 누출에 대해 초기 버그/부족을 식별할 수 있도록 했기 때문입니다.
해 보세요.LookupService 서드파티 오브젝트 해 주세요.2 .null the the the the?그 가 더 할 것이다.그 문제는 분석하기가 여전히 더 복잡할 것이다.

그래서 선호하는 방법은 다음과 같습니다.

public Dictionary(List<String> words) {
    this.words = Objects.requireNonNull(words);
    this.lookupService = new LookupService(words);
}

이렇게 하면 두통이 발생하지 않습니다.이것을 수신하는 즉시 예외가 발생합니다.

// exception thrown early : in the constructor 
Dictionary dictionary = new Dictionary(null);

// we never arrive here
boolean isFirstElement = dictionary.isFirstElement("anyThing");
스레드 "main" java.lang에 예외가 있습니다.특수한 포인터예외.를 참조해 주세요.Objects.requireNonNull(Objects.java:203)com에서.사전.(사전.java:15)com에서.Dictionary.main (Dictionary.java:24)

여기서 컨스트럭터의 문제를 설명했지만 메서드 호출은 null이 아닌 체크 제약 조건이 같을 수 있습니다.

는 Null 포인터이다 때 .null★★★★★★★★★★★★★★★★★★.Objects.requireNonNull()는 값을 즉시 체크하고 예외를 즉시 슬로우합니다.이것에 의해, 앞으로 진행되지 않고, 눌 예외가 실제로 발생한 장소를 간단하게 검출할 수 있습니다.

은 빨리 한다, 빨리 실패한다.Object#requireNotNulljre 클래스 자체 내에서 java-9 이전과 약간 다르게 구현되었습니다.를 들어 다음과 같습니다

 Consumer<String> consumer = System.out::println;

Java-8에서는 (관련 부분만)로 컴파일됩니다.

getstatic Field java/lang/System.out
invokevirtual java/lang/Object.getClass

기본적으로는 다음과 같은 조작입니다.yourReference.getClass가 - 조음음 -음 、 음음 、 음음 、 - - - - 。null

jdk-9에서는 같은 코드가 컴파일 되어 있습니다.

getstatic Field java/lang/System.out
invokestatic java/util/Objects.requireNonNull

기본적으로는 ★★★★★★★★★★★★★★★★★★★★」Objects.requireNotNull (yourReference)

후 입니다.NullPointerException지금 당장.

같은 요건을 충족하기 위한 더 나은 대안(바로가기) 중 하나는 롬복의 @NonNull 주석입니다.

로 - 에겐 - 을 사용합니다.requireNonNull코드를 좀 더 편리하게 만들 수 있습니다(때로는 읽기 쉬울 수도 있습니다).

예를 들어 - 아래 코드를 조사하겠습니다.

private int calculateStringLength(String input) {
        return Objects.
                requireNonNull(input, "input cannot be null").
                length();
    }

, 「」의 경우는 를 .NPE를 하다, NPE를 사용하다inputnull.

바와 같이, 「 」를 해 주세요.requireNonNull 수동으로 - null은 null입니다.

은 ' 메시지쓴 것입니다.input cannot be null(어느 쪽인가)

카피 컨스트럭터나 DI 등의 입력 파라미터가 오브젝트인 경우에 사용하는 것이 좋다고 생각합니다만, 파라미터가 늘인지 아닌지를 확인해 주십시오.이러한 경우 이 정적 방법을 편리하게 사용할 수 있습니다.

Nullability Check(예: uber/NullAway)를 구현하는 컴파일러 확장 기능에서는Objects.requireNonNull당신이 알기가 발생한 nullable필드 코드의 특정한 지점에서가 null이 아닙니다 다소 부족한 행사를 위해 사용되어야 합니다.는, 코드내의 특정의 시점에서 늘이 아닌 것을 알고 있는 늘 가능한 필드가 있는 경우는,다소신중하게 사용해 주세요.

이 방법에는 주로 다음 두 가지 방법이 있습니다.

  • 확인

    • 여기에서는 이미 다른 응답에 대응하고 있습니다.
    • 오버헤드 및 잠재적인 NPE를 사용한 런타임 체크
  • Nullability 마킹(@Nullable에서@Nonnull로 변경)

    • 컴파일 시간 체크를 위해 런타임 체크를 최소한으로 사용
    • (컴파일러에 의해 설명됨)주석이 정확할 때만 기능합니다.

Nullability 마킹의 사용 예:

@Nullable
Foo getFoo(boolean getNull) { return getNull ? null : new Foo(); }

// Changes contract from Nullable to Nonnull without compiler error
@Nonnull Foo myFoo = Objects.requireNonNull(getFoo(false));

모든 정답과 더불어 다음 항목도 있습니다.

우리는 반응성 하천에 그것을 사용한다.반응하는 스트림에 사용합니다.보통 결과보통 결과물은NullpointerException다른 예외는 스트림에 그들의 경우에 따라에 포장되어 있다.는 스트림에서의 발생에 따라 다른 예외로 분류됩니다.따라서, 우리는 나중에 쉽게 어떻게 오류를 처리하기로 결정할 수 있다.따라서 나중에 오류 처리 방법을 쉽게 결정할 수 있습니다.

예를 들면 다음과 같습니다.상상해 보세요

<T> T parseAndValidate(String payload) throws ParsingException { ... };
<T> T save(T t) throws DBAccessException { ... };

어디 어디에parseAndValidate그랩으로 싸다 wrappsNullPointerException부터에서requireNonNull한에 있어서에ParsingException.

이제 재시도 시기를 결정할 수 있습니다.

...
.map(this::parseAndValidate)
.map(this::save)
.retry(Retry.<T>allBut(ParsingException.class))

확인 없이, NullPointer체크하지 않으면 없으면 Null이고 Pointer는.예외는에 예외가 발생합니다에 occure 것이다.save방법은 끝없는 재시도로 이어질 것이다.방법있는 한, 장기 .

.onErrorContinue(
    throwable -> throwable.getClass().equals(ParsingException.class),
    parsingExceptionConsumer()
)

, 이제 ㅇㅇ, ㅇㅇ.RetryExhaustException구독이 중지됩니다.

스태틱 분석 툴이 표준 라이브러리에 대해 일반적으로 @NonNull 및 @Null(명시적으로 늘을 확인하는 것과 동일)을 알고 있는 이점도 있습니다.

public static <T> @NonNull T requireNonNull(@Nullable T obj) {
    if (obj == null)
        throw new NullPointerException();
    return obj;
}

언급URL : https://stackoverflow.com/questions/45632920/why-should-one-use-objects-requirenonnull

반응형