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


547

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

답변:


299

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


33
이 질문에 대한 다음 답변은 NullPointerException이 올바른 예외라는 설득력있는 주장을합니다. stackoverflow.com/a/8160/372926 ; stackoverflow.com/a/8196334/372926 ; 및 stackoverflow.com/a/6358/372926을 참조하십시오 .
SamStephens

2
IllegalArgumentException자바의와 모순에 Objects.requireNonNull (T) 와 구아바의 Preconditions.checkNotNull (T) 발생합니다 NullPointerException. 그러나 Jason Cohen의 탁월한 답변과 설명 섹션에 설명 된대로 정답은 확실 합니다 . IllegalArgumentException
matoni

417

다음과 같은 이유로 (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를 맹목적으로 복사하는 것만으로는 이러한 다른 고려 사항을 능가하기에 충분하지 않습니다.


119
효과적인 Java 2 판, 항목 60 : "모든 잘못된 메소드 호출은 잘못된 인수 또는 잘못된 상태로 귀속되지만 특정 종류의 잘못된 인수 및 상태에는 표준으로 다른 예외가 사용됩니다. 호출자가 어떤 매개 변수에서 null을 전달하는 경우 Null 값은 금지되며 규칙에 따라 IllegalArgumentException이 아닌 NullPointerException이 발생합니다. 마찬가지로 호출자가 색인을 나타내는 매개 변수의 범위를 벗어난 값을 시퀀스로 전달하면 IllegalArgumentException이 아닌 IndexOutOfBoundsException이 발생합니다. "
길리

33
NPE 용 JavaDoc은 또한 다음과 같이 설명합니다. "응용 프로그램은 널 오브젝트의 다른 불법적 인 사용을 나타 내기 위해이 클래스의 인스턴스를 던져야합니다." 이것은 더 분명 할 수 있습니다 :(
R. Martinho Fernandes

12
불행히도, 유효성 검사 방법 Validate.notNull(commons lang)과 Preconditions.checkNotNull(guava)는 모두 NPE를 던집니다 :-(
Aaron Digulla

2
구아바에도 Preconditions.checkArgument ()가 IllegalArgumentException을 던졌습니다.
michaelok

16
구아바 문서의 @AaronDigulla : "우리는 널 인수에 대해 IAE를 던지는 데 유리한 많은 주장이 있다는 것을 알고 있습니다. 사실, 15 년이 넘는 시간을 거슬러 올라가는 타임머신이 있다면 그러나 우리는 NullPointerException의 JDK 및 효과적인 Java 환경 설정을 고수하기로 결정했습니다 .IAE가 옳다고 믿는 것이 확실하다면 checkArgument(arg != null)arg를 반환하는 편리함없이 arg를 반환하거나 만들 수 있습니다. 프로젝트의 로컬 유틸리티입니다. " code.google.com/p/guava-libraries/wiki/IdeaGraveyard
Arto Bendiken '10

162

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

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


95
나는 매우 동의하지 않습니다. JVM이 실수로 널 참조를 따르는 경우에만 NullPointerException이 발생해야합니다. 그것은 아침 3시에 코드를 보도록 호출 할 때 도움이되는 차이점입니다.
Thorbjørn Ravn Andersen 님이

26
필자는 표준에 동의하지는 않지만 (실제로 문제를 해결할 수는 있지만) JDK 전체의 표준 사용법이 무엇인지에 따라 효과적인 Java가 이에 해당합니다. 나는 이것이 표준을 따를 지 아닌지, 자신이 옳다고 느끼는 것을 할 것인지를 선택하는 경우라고 생각합니다. 정당한 이유가없는 한 (그리고 확실하게 자격이있을 수있는 경우) 표준 관례를 따르는 것이 가장 좋습니다.
GaryF

21
예외 추적은 예외의 요점을 보여 주므로 예외 유형의 차이가 당신을 위해 지옥을 야기하거나 "도움을주는 차이"라면, 당신은 매우 잘못된 일을하고 있습니다.
Jim Balter

8
환상과 정교함. MB는 "하드 디버깅에 대한 논증은 허위 임에 유의해야한다. NullPointerException에 널 (null)이 무엇이고 왜 널이어서는 안되는지를 알려주는 메시지를 제공 할 수 있기 때문이다. IllegalArgumentException과 마찬가지로"
Jim Balter

10
여기의 최초의 답변자로서 그다지 중요하지 않다고 말하겠습니다. 6 년 간의 대화를 보증하지는 않습니다. 원하는 것을 고르고 일관성을 유지하십시오. 내가 지적했듯이 표준은 NPE입니다. 어떤 이유에서든 IAE를 선호하는 경우에는 IAE를 사용하십시오. 일관성을 유지하십시오.
GaryF

138

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인지 나타내는 유용한 메시지를 표시하는 것이 좋습니다. 그러나 퍼포먼스가 메소드 / 생성자의 공개 된 계약을 위반하지 않으면 서 변경하는 옵션을 갖는 것이 좋습니다.


14
구아바 Preconditions.checkNotNull(arg)도 NPE를 던졌습니다.
assylias

14
이것은 불법 null 인수에 대해 NullPointerException에 더 많은 가중치를 추가하지 않습니다. JDK requireNonNull ()과 Guava checkNotNull ()은 모두 객체와 함께 코드의 어느 곳에서나 호출 할 수 있습니다. 예를 들어 루프 안에서 호출 할 수 있습니다. requireNotNull () 및 checkNotNull ()은 일부 메소드 인수로 호출되어 IllegalArgumentException을 던질 것으로 가정 할 수 없습니다. 구아바에는 IllegalArgumentException을 발생시키는 Preconditions.checkArgument ()도 있습니다.
Bogdan Calmac

2
Bogdan의 요점은 requireNonNull의 일반적인 (그리고 일반적으로 의도 된) 사용이 인수 확인을위한 것이라고 생각합니다. 루프에서 무언가가 null이 아닌지 확인해야한다면 어설 션이 일반적인 방법이라고 생각했을 것입니다.
MB.

15
나는 Object.requireNonNull ()의 JavaDoc을이 인수에 무게를 추가 생각 : "이 방법은 주로 메소드와 생성자의 매개 변수 유효성 검사를 수행하도록 설계되었습니다"
리처드 Zschech을

암시 적 null 검사를 선호하는 성능 인수는 종종 유효하지 않습니다. JIT는 사용자 널 점검을 인식하고 다음과 같은 내재 된 널 점검을 생략하거나 널 점검 유형에 대해 동일한 최적화 세트를 사용할 수 있습니다. 자세한 정보는 이 위키 를 참조하십시오 . 특히 사용자 작성 널 확인은 대부분 기능적으로 JVM에 의해 삽입 된 널 점검과 동일합니다. 물론 사용자 지정 메시지와 같이 null에서 더 멋진 작업을 수행하는 경우이 최적화가 적용되지 않을 수 있습니다.
BeeOnRope

70

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

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


3
생각을위한 음식 : 아마도 NullPointerException이 IllegalArgumentException을 확장하지 않는 이유는 메소드 인수와 관련이없는 경우 전자가 발생할 수 있기 때문입니다.
길리

2
@Gili : Java가 다중 상속을 지원하지 않기 때문에이 문제가 처음에 존재할 수 있습니다. Java가 MI를 지원하는 경우 IllegalArgumentException 및 NullPointerException에서 상속되는 예외를 발생시킬 수 있습니다.
Lie Ryan

7
메시지는 항상 널이므로 인수를 포함 할 필요가 없습니다. "null은 널이 아니어야합니다". :-) 그렇지 않으면, 당신은 의미있는 메시지로 "풍부한"NPE를 만들 수 있다는 데 동의합니다.
PhiLho

5
동의해야합니다-확실하지 않은 경우 표준 API를 따르십시오. API의 모든 것이 최적 인 것은 아니지만 여전히 수백 명의 개발자가 유지 관리하고 수백만 명의 프로그래머가 사용하고 있습니다. 이제 Java 7에서는 이러한 방식으로 사용되는 NPE의 또 다른 예가 있습니다. Objects.requireNonNull (T obj) 메소드-오브젝트 참조가 널이 아닌지 확인하기 위해 명확하게 지정되고 메소드 / 생성자에서 매개 변수 유효성 검증을 수행하기 위해 명확하게 지정되며 오브젝트가 널인 경우 NPE를 발생 시키도록 명확하게 지정됩니다. 끝
flamming_python 17

44

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

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

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

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

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

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


대부분의 확인되지 않은 예외의 차이점은 단지 이름입니다.
Thorbjørn Ravn Andersen

20

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


아니요,이 질문에 대한 정답은 하나 뿐이며 메소드 입력이 올바르지 않은 경우 throw IllegalArgument 예외를 사용하는 것입니다. 또한 개발 환경에서는 어설 션을 사용하여 입력 유효성을 검사하고 적절한 예외를 throw 할 수 있습니다.)
Mr.Q

@ Mr.Q 그리고 나는 NullPointerException던져 져야 한다고 생각한다 : 그것은 JDK가 사용하고, 인터페이스를 위해 요구되는 관습이다. 더 구체적이다 (등과 같이 IndexOutOfBoundsException) 등등.
Solomon Ucko

kekekekkek ... : D
Yousha Aleayoub

17

그것이 setter메소드이고 null전달되고 있다면,를 던지는 것이 더 합리적이라고 생각합니다 IllegalArgumentException. NullPointerException실제로을 사용하려는 경우 A 가 더 의미가있는 것 같습니다 null.

그래서 당신이 그것을 사용하고 있다면 null, NullPointer. 전달되고 있으며 null, IllegalArgument.


9

Apache Commons Lang에는 NullArgumentException 이 있으며 여기에서 논의되는 많은 작업을 수행합니다. IllegalArgumentException을 확장하고 유일한 생성자는 널이 아닌 인수의 이름을 사용합니다.

NullArgumentException 또는 IllegalArgumentException과 같은 것을 던지면 예외적 인 상황을보다 정확하게 설명한다고 생각하지만 동료와 나는 주제에 대한 Bloch의 조언을 연기하기로 결정했습니다.


7
그들이 commons-lang3에서 그것을 제거함을 주목하라 : apache-commons.680414.n4.nabble.com/…
artbristol

7

말한 것에 더 동의하지 못했습니다. 일찍 실패하고 빨리 실패하십시오. 꽤 좋은 예외 만트라.

던질 예외에 대한 질문은 주로 개인적인 취향의 문제입니다. 내 생각에 IllegalArgumentException은 NPE를 사용하는 것보다 더 구체적 인 것처럼 보입니다. 문제를 내가 메서드에 전달한 인수가 아니라 메서드를 수행하는 동안 생성 된 값이 아니라고 말했기 때문입니다.

내 2 센트


7

실제로, IllegalArgumentException 또는 NullPointerException을 던지는 문제는 겸손한 견해로는 소수의 사람들에게 Java의 예외 처리에 대한 이해가 불완전한 이해에 불과합니다. 일반적으로 규칙은 간단하며 다음과 같습니다.

  • 디버깅이 훨씬 어려운 불법 상태를 피하려면 인수 제약 조건 위반을 가능한 빨리 표시해야합니다 (-> 빠른 실패).
  • 어떤 이유로 든 유효하지 않은 널 포인터가있는 경우 NullPointerException을 발생시킵니다.
  • 잘못된 배열 / 컬렉션 인덱스의 경우 ArrayIndexOutOfBounds를 발생시킵니다.
  • 배열 / 컬렉션 크기가 음수 인 경우 NegativeArraySizeException을 발생시킵니다.
  • 위의 내용을 다루지 않고 다른 특정 예외 유형이없는 잘못된 인수의 경우 IllegalArgumentException을 휴지통으로 처리하십시오.
  • 반면, 유효하지 않은 이유로 빠른 실패로 피할 수없는 필드 내에서 제한 조건 위반의 경우, IllegalStateException 또는보다 구체적인 점검 된 예외로 캐치하여 다시 던집니다. 이 경우 원래 NullPointerException, ArrayIndexOutOfBounds 등을 전달하지 마십시오!

모든 종류의 인수 제약 조건 위반을 IllegalArgumentException에 매핑하는 경우에 대해 적어도 세 가지 이유가 있습니다. 세 번째는 연습 스타일을 나쁜 스타일로 표시하는 것입니다.

(1) 프로그래머는 인수 제약 조건 위반의 모든 경우에 IllegalArgumentException이 발생한다고 안전하게 가정 할 수 없습니다. 표준 클래스의 대부분은 더 이상 사용할 수있는 특정 종류의 예외가없는 경우이 예외를 휴지통으로 사용하기 때문입니다. 표준 라이브러리는 대부분 자신을 위반하는 다른 규칙을 따르므로 대부분의 API 사용자도이를 사용하므로 API에서 인수 제약 조건 위반의 모든 사례를 IllegalArgumentException에 매핑하려고하면 클래스를 사용하는 프로그래머가 좌절하게됩니다.

(2) 예외를 매핑하면 실제로 단일 상속으로 인해 다른 종류의 예외가 발생합니다. 모든 Java 예외는 클래스이므로 단일 상속 만 지원합니다. 따라서 서브 클래스는 하나만 상속 할 수 있으므로 NullPointerException과 IllegalArgumentException을 모두 나타내는 예외를 만들 수있는 방법이 없습니다. 따라서 null 인수의 경우 IllegalArgumentException을 발생 시키면 프로그램이 프로그래밍 방식으로 문제를 수정하려고 할 때마다 (예 : 기본값을 호출 반복에 공급하여) API 사용자가 문제를 구분하기가 더 어려워집니다!

(3) 매핑은 실제로 버그 마스킹의 위험을 만듭니다. 인수 제약 조건 위반을 IllegalArgumentException에 매핑하려면 제한된 인수가있는 모든 메서드 내에서 외부 try-catch를 코딩해야합니다. 그러나이 catch 블록에서 RuntimeException을 단순히 포착하는 것은 의문의 여지가 없습니다. 왜냐하면 인수 제약 조건 위반으로 인한 것이 아니더라도 자신의 내부에서 사용되는 리버티 메소드에 의해 발생 된 문서화 된 RuntimeException을 IllegalArgumentException에 매핑 할 위험이 있기 때문입니다. 따라서 매우 구체적이어야하지만 그 노력으로도 다른 API의 문서화되지 않은 런타임 예외 (예 : 버그)를 API의 IllegalArgumentException에 실수로 매핑하는 경우를 막을 수는 없습니다.

반면에 표준 관행을 사용하면 규칙이 단순하게 유지되고 예외로 인해 예외가 발생하지 않고 구체적으로 유지됩니다. 메소드 호출자의 경우 규칙도 간단합니다.-잘못된 값을 전달하여 문서화 된 런타임 예외가 발생하는 경우 기본값을 사용하여 호출을 반복하거나 (이 특정 예외가 필요한 경우) 코드를 정정하십시오. -반면에 주어진 인수 집합에 대해 발생하지 않는 런타임 예외가 발생하면 메서드 제조업체에 버그 보고서를 작성하여 코드 또는 설명서가 수정되었는지 확인하십시오.


6

IllegalArgumentException (String message) 을 사용하여 매개 변수를 유효하지 않은 것으로 선언하고 가능한 한 자세하게 설명 하는 경우 허용되는 관행 ... 예외가 null이 아닌 동안 매개 변수가 null 인 것으로 판단되면 무언가를 수행합니다. 이처럼 :

if( variable == null )
    throw new IllegalArgumentException("The object 'variable' cannot be null");

"NullPointerException"을 암시 적으로 사용할 이유가 없습니다. NullPointerException은 null 참조 (Like toString () ) 에서 코드를 실행하려고 할 때 Java Virtual Machine에서 발생하는 예외 입니다.


6

null인수 에만 적용되는 예외 ( NullPointerException사용자 정의 유형에 관계없이 )를 발생 시키면 자동화 된 null테스트의 안정성이 향상됩니다. 이 자동화 된 테스트는 같이 반사 및 기본 값 세트와 함께 할 수 구아바NullPointerTester. 예를 들어 NullPointerTester다음 방법을 호출하려고 시도합니다.

Foo(String string, List<?> list) {
  checkArgument(string.length() > 0);
  // missing null check for list!
  this.string = string;
  this.list = list;
}

... 두 개의 인수 목록이 있습니다 : "", nullnull, ImmutableList.of(). 이러한 각 호출이 예상대로 발생하는지 테스트합니다 NullPointerException. 이 구현의 경우 null목록을 전달해 생성 되지 않습니다NullPointerException . 그러나 기본 문자열 인을 사용 IllegalArgumentException하기 때문에 를 생성합니다 . 경우 에만이 기대 에 대한 값은 버그를 잡는다. 기대 하면 놓칩니다.NullPointerTester""NullPointerTesterNullPointerExceptionnullIllegalArgumentException


5

일부 컬렉션에서는가 아닌을 null사용하여 거부 된 것으로 가정합니다 . 예를 들어,이 포함되는 세트 비교하면 불량이있는 세트로 , 첫 번째 세트가 호출 다른과의 잡을 -하지만를 . (의 구현을보고 있습니다.)NullPointerExceptionIllegalArgumentExceptionnullnullcontainsAllNullPointerExceptionIllegalArgumentExceptionAbstractSet.equals

당신은 합리적으로 포함 비교 컬렉션 것으로,이 방법으로 체크되지 않은 예외를 사용하여 안티 패턴이라고 주장 할 수 null포함 할 수 없습니다 컬렉션에이 null정말 가능성이 버그 한다 예외를 생산하는이, 또는 퍼팅 것을 null모두에서 컬렉션은 나쁜 생각 . 그럼에도 불구하고 equals그러한 경우에 예외를 던져야 한다고 말하지 않는다면 NullPointerException특정 상황에서는 필요하지만 다른 상황에서는 필요하지 않다는 것을 기억해야 합니다. ( " 'c'다음을 제외한 NPE 이전의 IAE ...")


컬렉션 내부의 요소에 따라 포함에 NPE가 어떻게 발생하는지 알 수 없습니다. NPE가 던져지는 이유 (faict)는 컬렉션 자체가 null 인 경우 (반복자에 액세스하려고하기 때문에 NPE가 던져지는 경우)입니다. 그러나 null 입력을 확인해야하거나 액세스하려고 할 때까지 전파되어야하는 경우 문제가 발생합니다.
Alowaniak

2
new TreeSet<>().containsAll(Arrays.asList((Object) null));던졌습니다 NPE(가) 때문에 List포함 null.
Chris Povirk

1
실제로 TreeSet # contains는 "지정된 요소가 널이고이 세트가 자연 순서를 사용하거나 그 비교기가 널 요소를 허용하지 않는 경우"NPE를 던집니다. null을 허용하는 AbstractSet 만 보았습니다. 개인적으로 나는 그것이 거짓을 반환하지 않는 것이 이상하다고 생각합니다.이 경우 null이 추가 될 수 없기 때문입니다.
Alowaniak

5

주관적인 질문으로 이것은 닫혀 있어야하지만 여전히 열려 있습니다.

이것은 이전 직장에서 사용 된 내부 정책의 일부이며 실제로 효과가있었습니다. 이것은 모두 기억에서 나왔으므로 정확한 문구를 기억할 수 없습니다. 그들이 확인 된 예외를 사용하지 않았다는 점은 주목할 가치가 있지만 그것은 질문의 범위를 벗어납니다. 그들이 사용하지 않은 예외는 세 가지 주요 범주로 나뉩니다.

NullPointerException : 의도적으로 던지지 마십시오. NPE는 null 참조를 역 참조 할 때 VM에서만 발생합니다. 이것들이 절대로 던져지지 않도록 가능한 모든 노력을 기울여야합니다. 이러한 오류를 찾으려면 @Nullable 및 @NotNull을 코드 ​​분석 도구와 함께 사용해야합니다.

IllegalArgumentException : 함수에 대한 인수가 공개 문서를 준수하지 않아 전달 된 인수로 오류를 식별하고 설명 할 수있을 때 발생합니다. OP의 상황은이 범주에 속합니다.

IllegalStateException : 함수가 호출되고 인수가 전달 될 때 예상치 못한 인수이거나 메소드가 속한 오브젝트의 상태와 호환되지 않는 경우 발생합니다.

예를 들어, 길이가있는 것들에 사용 된 IndexOutOfBoundsException의 두 가지 내부 버전이있었습니다. 색인이 길이보다 큰 경우 사용되는 IllegalStateException의 서브 클래스 중 하나입니다. 인덱스가 음수 인 경우 사용되는 IllegalArgumentException의 다른 하위 클래스입니다. 객체에 더 많은 항목을 추가 할 수 있고 인수는 유효하지만 음수가 유효하지 않기 때문입니다.

내가 말했듯이,이 시스템은 정말 잘 작동하며, 왜 그 차이가 있는지 설명하는 누군가가 필요했습니다. 무엇이 잘못되었는지 파악하여 오류를 잡아야 할 위치를 파악하고 추가 디버깅 정보를 만들 수 있습니다. "

NullPointerException : NPE가 처리되지 않도록 Null 케이스를 처리하거나 어설 션을 넣습니다. 어설 션을 입력하면 다른 두 가지 유형 중 하나 일뿐입니다. 가능하면 어설 션이 처음에있는 것처럼 디버깅을 계속하십시오.

IllegalArgumentException : 콜 사이트에 문제가 있습니다. 전달되는 값이 다른 함수에서 온 것이라면 왜 잘못된 값을 받는지 알아보십시오. 인수 중 하나를 전달하면 예상 한 결과를 반환하지 않는 함수를 찾을 때까지 오류가 호출 스택을 검사합니다.

IllegalStateException : 함수를 올바른 순서로 호출하지 않았습니다. 인수 중 하나를 사용하는 경우 인수를 확인하고 문제를 설명하는 IllegalArgumentException을 발생시킵니다. 그런 다음 문제를 찾을 때까지 뺨을 스택에 전파 할 수 있습니다.

어쨌든 그의 요점은 IllegalArgumentAssertions 만 스택에 복사 할 수 있다는 것입니다. IllegalStateExceptions 또는 NullPointerExceptions가 함수와 관련이 있기 때문에 스택에 전파 할 수있는 방법이 없습니다.


4

일반적으로 개발자는 NullPointerException을 발생 시키지 않아야합니다 . 이 예외는 코드에서 값이 null 인 변수를 역 참조하려고 할 때 런타임에 발생합니다. 따라서 null 값이 NullPointerException을 발생시키는 것과 달리 메서드가 null을 명시 적으로 허용하지 않으려면 IllegalArgumentException을 발생시켜야합니다.


9
NPE의 JavaDoc은 "응용 프로그램은 널 오브젝트의 다른 불법 사용을 나타 내기 위해이 클래스의 인스턴스를 던져야합니다."라는 또 다른 견해를 가지고 있습니다. 너무 범주
적이 지

4

다른 잘못된 인수에서 Null 인수를 선택하고 싶기 때문에 IAE에서 NullArgumentException이라는 예외를 파생했습니다. 예외 메시지를 읽을 필요조차없이 null 인수가 메서드에 전달되었음을 알고 메시지를 읽음으로써 어떤 인수가 null인지 알 수 있습니다. 나는 여전히 IAE 처리기로 NullArgumentException을 포착하지만 내 로그에서 차이점을 빠르게 볼 수 있습니다.


"새로운 IllegalArgumentException ("foo == null ")"접근 방식을 채택했습니다. 어쨌든 변수 이름을 기록해야합니다 (올바른 회전 등을보고 있는지 확인하십시오)
Thorbjørn Ravn Andersen

4

이분법은 ... 겹치지 않나요? 전체의 겹치지 않는 부분 만 이분법을 만들 수 있습니다. 내가 본대로 :

throw new IllegalArgumentException(new NullPointerException(NULL_ARGUMENT_IN_METHOD_BAD_BOY_BAD));

1
이것은 예외 생성에 대한 오버 헤드를 두 배로 늘리며 잡기 NullPointerException가 아무것도하지 않기 때문에 실제로 도움이되지 않습니다. 도움이 될 수있는 유일한 것은입니다 IllegalNullPointerArgumentException extends IllegalArgumentException, NullPointerException. 그러나 다중 상속이 없습니다.
maaartinus

좀 더 구체적인 예외는 더 일반적인 예외로 감싸 야한다고 생각합니다. NPE는 표현을위한 것이고 IAE는 방법을위한 것입니다. 메소드에는 표현식이 포함 된 명령문이 포함되므로 IAE가 더 일반적입니다.
Sgene9

오버 헤드에 관해서는 모르겠습니다. 그러나 예외의 이름이 중간에 변경되었다는 점을 제외하고 스택 추적은 기본적으로 동일하므로 이중 예외에 대한 오버 헤드가 너무 많지 않아야한다고 생각합니다. 오버 헤드가 걱정되면 "if"문을 사용하여 예외를 throw하는 대신 null 또는 -1을 반환 할 수 있습니다.
Sgene9

4

NullPointerException현재 값이 인 참조 변수를 사용하여 객체에 액세스하려고 할 때 발생 null합니다.

IllegalArgumentException 메소드가 예상 한 것과 다른 형식의 인수를받을 때 발생합니다.


3

귀하의 시나리오에 따르면, 귀하의 부동산에 유효한 값이 아니므로 IllegalArgumentException최선의 선택 null입니다.


0

이상적으로는 런타임 예외가 발생하지 않아야합니다. 시나리오에 대해 점검 된 예외 (비즈니스 예외)를 작성해야합니다. 이러한 예외 중 하나가 발생하여 기록되면 로그를 진행하는 동안 개발자를 잘못 안내합니다. 대신 비즈니스 예외로 인해 패닉이 발생하지 않으며 일반적으로 로그 문제를 해결하는 동안 무시됩니다.


-1

위의 두 예외에 대한 링크의 정의는 IllegalArgumentException입니다. 메소드에 부적절하거나 부적절한 인수가 전달되었음을 표시하기 위해 발생합니다. NullPointerException : 객체가 필요한 경우에 응용 프로그램에서 null을 사용하려고하면 발생합니다.

여기서 큰 차이점은 메서드에 대한 인수가 유효한지 확인할 때 IllegalArgumentException이 사용된다는 것입니다. NullPointerException은 개체가 null 일 때 개체를 "사용"할 때마다 사용됩니다.

나는 그것이 두 가지 관점에 도움이되기를 바랍니다.


1
두드러진 점은 그것이 런타임이 아닌 null을 사용 하는 응용 프로그램 이라는 것입니다. 따라서 "메소드가 부적절하거나 부적절한 인수를 전달했을 때"와 "응용 프로그램이 널을 사용하는 경우"사이에는 상당히 큰 차이가 있습니다. 이론적으로 앱이 null이 아닌 필드에 대해 null을 전달하면 두 기준이 모두 충족됩니다.
Christopher Smith

-1

"세터"이거나 나중에 사용할 멤버를 얻는 경우 IllegalArgumentException을 사용하는 경향이 있습니다.

메서드에서 지금 (참조 취소) 사용할 것이라면 NullPointerException을 미리 발생시킵니다. 나는 유용한 메시지를 제공 할 수 있기 때문에 런타임이 그것을하는 것보다 낫다.

메서드를 재정의하는 경우 재정의 된 메서드가 사용하는 모든 것을 사용합니다.


-1

프로그래머가 잘못된 것을 한 것이 분명해 지므로 IllegalArgumentException을 발생시켜야합니다. 개발자들은 VM에 의해 던져진 NPE를 보는 데 익숙해 져 프로그래머가 즉시 자신의 오류를 인식하지 못하고 무작위로 또는 더 나쁘게 둘러보기 시작하여 코드가 '버기'되었다고 비난합니다.


4
프로그래머가 어떤 종류의 예외를 겪을 때 "임의로"둘러 보면 예외 이름을 변경해도 큰 도움이되지 않습니다.
Christopher Smith

-1

이 경우, IllegalArgumentException은 API를 사용하여 "널이 아니어야합니다"라는 명확한 정보를 사용자에게 전달합니다. 다른 포럼 사용자가 지적했듯이 API를 사용하여 사용자에게 올바른 정보를 전달하기를 원한다면 NPE를 사용할 수 있습니다.

GaryF와 tweakt는 NPE 사용을 권장하는 "Effective Java"(내가 맹세 한) 참조를 삭제했다. 그리고 다른 좋은 API가 어떻게 구성되는지 보는 것이 API를 구성하는 방법을 보는 가장 좋은 방법입니다.

또 다른 좋은 예는 Spring API를 보는 것입니다. 예를 들어, org.springframework.beans.BeanUtils.instantiateClass (Constructor ctor, Object [] args)에는 Assert.notNull (ctor, "Constructor는 null이 아니어야합니다") 행이 있습니다. org.springframework.util.Assert.notNull (Object object, String message) 메소드는 전달 된 인수 (객체)가 null인지 확인하고 새로운 IllegalArgumentException (message)을 발생시키는 지 확인합니다. springframework.beans.BeanUtils.instantiateClass (...) 메소드.


-5

NPE를 던지려고 선택하고 메소드에서 인수를 사용하는 경우 널을 명시 적으로 검사하는 것이 중복되고 비용이 많이들 수 있습니다. VM이 이미 그렇게한다고 생각합니다.


런타임에는 의미있는 메시지가 포함되지 않습니다.
mP.

실제로이 의견은 다른 의견을 도출 할 수 있습니다. VM이 말을하도록 NPE하지만 프로그래머는 IAE원하는 경우 VM보다 먼저 말을 합니다.
Jin Kwon

1
비싼? == null이 그렇게 비싸다고 생각하지 않습니다 ... 게다가 null 인수는 나중에 사용하기 위해 저장할 수 있으며 메소드 호출 후에 오랫동안 예외를 throw하여 오류를 추적하기가 더 어려워집니다. 또는 null 인수 등을 사용하기 전에 값 비싼 객체를 만들 수 있습니다. 조기 탐지가 좋은 선택 인 것 같습니다.
PhiLho

이 답변에 대한 투표는 하드웨어의 오해입니다. 확실히 하드웨어 검사 (CPU가하는 것)는 명시적인 검사보다 저렴합니다. 널의 역 참조는 CPU / OS가 검사하고 JRE가 NullPointerException을 발생시키는 특수한 경우로 처리하는 SegV (SegmentationFault) 특수 사례 (프로세스가 소유하지 않은 페이지에 액세스)입니다.
digital_infinity
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.