[java] null 매개 변수에 대한 IllegalArgumentException 또는 NullPointerException? [닫은]

속성에 대한 간단한 setter 메서드가 있으며이 null특정 속성에는 적합하지 않습니다. 난 항상 이런 상황에서 찢어되었습니다 내가 던져해야한다 IllegalArgumentException, 또는를 NullPointerException? javadoc에서 두 가지 모두 적절 해 보입니다. 이해되는 표준이 있습니까? 아니면 이것은 당신이 원하는대로해야하고 둘 다 정말로 올바른 것 중 하나입니까?



답변

허용 된 값 IllegalArgumentExceptionnull되고 싶지 않다면 호출 된 것처럼 보이고 , 로 변하는 변수 NullPointerException사용 하려고하면 throw됩니다 null.


답변

다음과 같은 이유로 (NPE)가 IllegalArgumentException아닌 (IAE)를 사용해야합니다 NullPointerException.

먼저 NPE JavaDoc 은 NPE가 적절한 경우를 명시 적으로 나열합니다. 그들 모두가 발생하는 것을 알 수 런타임에서null부적절하게 사용됩니다. 반대로 IAE JavaDoc 은 더 명확하지 않았다. “메소드가 부적절하거나 부적합한 인수를 전달했음을 나타냅니다.” 그래, 너야!

둘째, 스택 추적에 NPE가 표시되면 무엇을 가정합니까? 아마도 누군가가 a null. IAE가 표시되면 스택 맨 위에있는 메소드 호출자가 잘못된 값으로 전달되었다고 가정합니다. 다시, 후자의 가정은 사실이며, 전자는 오도합니다.

셋째, IAE는 매개 변수를 검증하기 위해 명확하게 설계되었으므로이를 기본 예외 선택으로 가정해야하므로 왜 NPE를 선택해야합니까? 분명히 다른 행동을위한 것은 아닙니다. 전화 코드가 IAE와 별도로 NPE를 포착하고 결과적으로 다른 것을 수행 할 것으로 기대합니까? 보다 구체적인 오류 메시지를 전달하려고합니까? 그러나 다른 모든 잘못된 매개 변수와 마찬가지로 예외 메시지 텍스트에서 그렇게 할 수 있습니다.

넷째, 다른 모든 잘못된 매개 변수 데이터는 IAE이므로 일관성이없는 이유는 무엇입니까? 불법 null이 너무 특별하여 다른 모든 유형의 불법 주장과는 별도로 예외가 필요한 이유는 무엇 입니까?

마지막으로, 나는 Java API의 일부가 이런 식으로 NPE를 사용한다는 다른 답변에 의해 주어진 주장을 받아들입니다. 그러나 Java API는 예외 유형에서 명명 규칙에 이르기까지 모든 것과 일치하지 않으므로 Java API를 맹목적으로 복사하는 것만으로는 이러한 다른 고려 사항을 능가하기에 충분하지 않습니다.


답변

표준은을 던지는 것 NullPointerException입니다. 일반적으로 오류가없는 “유효한 Java”는 항목 42 (1 판), 항목 60 (2 판) 또는 항목 72 (3 판) “표준 예외 사용”에서 간단히 설명합니다.

“어쩌면 모든 잘못된 메소드 호출은 불법 인수 또는 불법 상태로 귀결되지만 다른 종류의 예외는 특정 종류의 불법 인수 및 상태에 표준으로 사용됩니다. 발신자가 null 값이 금지 된 일부 매개 변수에서 null을 전달하면 규칙에 따라 IllegalArgumentException이 아닌 NullPointerException이 발생합니다. “


답변

Java 7 IllegalArgumentException에서 java.util.Objects.requireNonNull메소드를 발견했을 때까지 오늘까지 null 매개 변수 를 처리하는 것에 찬성했습니다 . 해당 메소드를 사용하는 대신 다음을 수행하십시오.

if (param == null) {
    throw new IllegalArgumentException("param cannot be null.");
}

넌 할 수있어:

Objects.requireNonNull(param);

NullPointerException전달하는 매개 변수 가 인 경우 throw됩니다 null.

그 방법이 중간에 옳다는 것을 감안할 때, java.util던지는 NullPointerException것이 “일을하는 Java 방식” 이라는 꽤 강한 표시로 존재합니다 .

나는 어떤 속도로 결정되었다고 생각합니다.

NullPointerException널 (null)이 무엇인지, 왜 널 (null)이되지 않아야하는지에 대한 메시지를 제공 할 수 있기 때문에 하드 디버깅에 대한 논증은 허위 임에 유의하십시오 . 와 마찬가지로 IllegalArgumentException.

또 하나의 이점은 NullPointerException고성능의 중요한 코드에서 널 (null)에 대한 명시 적 점검 (및 NullPointerException친숙한 오류 메시지)을 생략 할 수 있으며 널 (null )에서 NullPointerException메소드를 호출 할 때 자동으로 얻을 수 있다는 것입니다 매개 변수. 메소드를 빠르게 호출하면 (즉, 실패), 개발자에게 익숙하지 않은 본질적으로 동일한 효과가 있습니다. 대부분의 경우 명시 적으로 검사하고 어떤 매개 변수가 null인지 나타내는 유용한 메시지를 표시하는 것이 좋습니다. 그러나 퍼포먼스가 메소드 / 생성자의 공개 된 계약을 위반하지 않으면 서 변경하는 옵션을 갖는 것이 좋습니다.


답변

JDK 라이브러리의 디자인, 특히 컬렉션 및 동시성 (Joshua Bloch, Doug Lea, 견고한 API를 디자인하는 방법을 알고 있음)을 따르는 경향이 있습니다. 어쨌든 JDK의 많은 API가 능동적으로 발생 NullPointerException합니다.

예를 들어, Map.containsKey상태에 대한 Javadoc은 다음과 같습니다.

@throws NullPointerException 키가 null이고,이 맵이 null 키를 허용하지 않는 경우는 (옵션)

자신의 NPE를 던지는 것이 완벽하게 유효합니다. 규칙은 예외 메시지에서 널인 매개 변수 이름을 포함하는 것입니다.

패턴은 다음과 같습니다.

public void someMethod(Object mustNotBeNull) {
    if (mustNotBeNull == null) {
        throw new NullPointerException("mustNotBeNull must not be null");
    }
}

무엇을 하든지 나쁜 값을 설정하여 다른 코드에서 사용하려고 할 때 나중에 예외를 발생시키지 마십시오. 그것은 악몽을 디버깅합니다. 항상 “실패”원칙을 따라야합니다.


답변

Jason Cohen의 주장은 잘 발표 되었기 때문에 투표했습니다. 단계별로 설명하겠습니다. 😉

  • NPE의 javadoc에서는 명시 적으로 말한다 “널 객체의 다른 불법 사용” . 런타임에 null이 발생하지 않아야하는 상황으로 제한되는 경우 이러한 모든 경우를 간결하게 정의 할 수 있습니다.

  • 잘못된 것을 가정하면 도움이되지 않지만 캡슐화가 올바르게 적용되었다고 가정하면 null이 부적절하게 역 참조되었는지 여부와 메소드가 부적합한 null을 감지하여 예외를 발생했는지 여부를 신경 쓰지 않아야합니다.

  • 여러 가지 이유로 IAE 보다 NPE 를 선택했습니다.

    • 불법 운영의 성격에 대해 더 구체적입니다.
    • 실수로 널을 허용하는 논리는 실수로 잘못된 값을 허용하는 논리와는 매우 다른 경향이 있습니다. 예를 들어, 사용자가 입력 한 데이터의 유효성을 검사하는 경우 허용 할 수없는 값을 얻는 경우 해당 오류의 원인은 응용 프로그램의 최종 사용자에게 있습니다. null이 발생하면 프로그래머 오류입니다.
    • 유효하지 않은 값은 스택 오버플로, 메모리 부족 오류, 구문 분석 예외 등을 유발할 수 있습니다. 실제로 대부분의 오류는 어떤 시점에서 일부 메소드 호출에서 유효하지 않은 값으로 나타납니다. 이러한 이유로 나는 IAE가 실제로 RuntimeException 하의 모든 예외 중 가장 일반적인 것으로 본다 .
  • 실제로 다른 잘못된 인수로 인해 모든 종류의 다른 예외가 발생할 수 있습니다. UnknownHostException , FileNotFoundException , 다양한 구문 오류 예외, IndexOutOfBoundsException , 인증 실패 등

일반적으로 NPE는 전통적으로 페일 패스트 원칙 을 따르지 않는 코드와 관련되어 있기 때문에 NPE가 많이 악의적이라고 생각합니다 . 또한 JDK가 NPE를 메시지 문자열로 채우지 못하는 것은 실제로 제대로 확립되지 않은 강한 부정적인 감정을 만들어 냈습니다. 실제로 런타임 관점에서 NPE와 IAE의 차이점은 엄격하게 이름입니다. 이러한 관점에서 볼 때 이름이 정확할수록 발신자에게 더 명확 해집니다.


답변

“성전”스타일 질문입니다. 다시 말해, 두 가지 대안이 모두 좋지만 사람들은 자신이 선호하는 죽음을 방어 할 것입니다.