IllegalArgumentExceptionまたはnullパラメータのNullPointerException?[閉まっている]


547

プロパティの単純なセッターメソッドnullがあり、この特定のプロパティには適していません。私は常にこの状況で引き裂かれました:IllegalArgumentException、またはをスローする必要がありNullPointerExceptionますか?javadocsからは、どちらも適切と思われます。何らかの理解された基準はありますか?それとも、これはあなたが好きなことをすべきものの1つにすぎず、両方とも本当に正しいのですか?

回答:


299

許可された値にIllegalArgumentExceptionなりたくない場合はが呼び出されているようで、であることが判明した変数を使用しようとした場合にがスローされます。nullNullPointerExceptionnull


33
この質問への次の答えは、NullPointerExceptionが正しい例外であることを説得力のある引数を作る:stackoverflow.com/a/8160/372926をstackoverflow.com/a/8196334/372926 ; およびstackoverflow.com/a/6358/372926
SamStephens 2014

2
IllegalArgumentExceptionはJavaのObjects.requireNonNull(T)およびGuavaのPreconditions.checkNotNull(T)と矛盾しますNullPointerException。ただし、正しい答えは間違いなく IllegalArgumentExceptionジェイソンコーエンの優れた答えとコメントセクションで説明されています。
matoni

417

次の理由により、(NPE)IllegalArgumentExceptionではなく(IAE)を使用する必要がNullPointerExceptionあります。

まず、NPE JavaDocは、NPEが適切であるケースを明示的にリストしています。それらのすべてがスローされることに注意してくださいランタイムで時にnull不適切に使用されます。対照的に、IAEのJavaDocは、「メソッドに不正な引数または不適切な引数が渡されたことを示すためにスローされました」と明確にすることはできません。うん、それはあなたです!

次に、スタックトレースにNPEが表示された場合、何を想定していますか。おそらく誰かがを逆参照しましたnull。IAEが表示されたら、スタックの最上位にあるメソッドの呼び出し元が不正な値で渡されたと想定します。ここでも、後者の仮定は真実であり、前者は誤解を招くものです。

第3に、IAEはパラメーターの検証用に明確に設計されているため、例外のデフォルトの選択としてそれを想定する必要があるので、なぜ代わりにNPEを選択するのですか?確かに異なる動作ではありません-コードの呼び出しがIAEとは別にNPEをキャッチし、結果として何か異なることを実行することを本当に期待していますか?より具体的なエラーメッセージを伝えようとしていますか?ただし、他のすべての不正なパラメータに対して行う必要があるので、例外メッセージテキストでそれを行うことができます。

4番目に、他のすべての正しくないパラメーターデータはIAEになるので、一貫性がないのはなぜですか?なぜ違法なものnullが特別であり、他のすべてのタイプの違法な引数とは別個の例外に値するのはなぜですか?

最後に、Java APIの一部がこの方法でNPEを使用するという他の回答による引数を受け入れます。ただし、Java APIは例外タイプから命名規則まですべてに一貫性がないので、Java API(お気に入りの部分)を盲目的にコピーするだけでは、これらの他の考慮事項に勝る十分な議論ではないと思います。


120
有効なJava 2nd Edition、アイテム60:「間違いなく、すべてのエラーのあるメソッド呼び出しは、不正な引数または不正な状態に要約されますが、他の例外は、特定の種類の不正な引数および状態に対して標準的に使用されます。呼び出し元が、 null値は禁止されています。慣例により、IllegalArgumentExceptionではなくNullPointerExceptionがスローされることが規定されています。同様に、呼び出し元がインデックスを表すパラメーターの範囲外の値をシーケンスに渡す場合、IllegalArgumentExceptionではなくIndexOutOfBoundsExceptionがスローされる必要があります。
Gili

33
NPEのJavaDocは、次のようにも述べています。「アプリケーションは、このクラスのインスタンスをスローして、nullオブジェクトの他の不正な使用を示す必要があります。」これはもっと明確かもしれません:(
R. Martinho Fernandes

12
残念ながら、検証メソッドValidate.notNull(commons lang)とPreconditions.checkNotNull
guava

2
GuavaにはPreconditions.checkArgument()もIllegalArgumentExceptionをスローしますが、
michaelok

16
@ AaronDigulla、Guava docsから:「私たちはnull引数にIAEをスローすることを支持する多くの有効な引数があることを認識しています。実際、タイムマシンが15年以上前に戻る場合、ただし、私たちはNullPointerExceptionのJDKおよび効果的なJava設定に固執することを決定しました。IAEが正しいと確信している場合でもcheckArgument(arg != null)、argを返すという便利さはありませんが、プロジェクトのローカルユーティリティ。」 code.google.com/p/guava-libraries/wiki/IdeaGraveyard
Arto Bendiken 2014年

162

標準はをスローすることNullPointerExceptionです。一般に間違いのない「Effective Java」では、これについてItem 42(初版)、Item 60(第2版)、またはItem 72(第3版)の「標準例外の使用を好む」で簡単に説明しています。

「間違いなく、すべての誤ったメソッド呼び出しは不正な引数または不正な状態に要約されますが、その他の例外は、特定の種類の不正な引数および状態に対して標準的に使用されます。呼び出し側がnull値が禁止されているパラメータにnullを渡す場合、規則により、 IllegalArgumentExceptionではなく、NullPointerExceptionがスローされます。」


95
私は強く反対します。NullPointerExceptionsは、JVMが誤ってnull参照をたどった場合にのみスローされます。これが、午前3時にコードを確認するために呼び出されるときに役立つ違いです。
するThorbjörnRavnアンデルセン

26
私は必ずしも標準に同意するわけではありませんが(実際にはどちらかの方法で問題を解決することができます)、それがJDK全体での標準的な使用法です。これは、基準に従うか、正しいと思うことをするかの選択だと思います。あなたが非常に正当な理由がない限り(そしてこれは確かに資格があるかもしれません)、標準的な慣行に従うことが最善です。
GaryF 2009年

21
例外トレースは例外のポイントを示しているので、例外のタイプの違いがあなたに地獄を引き起こしたり、「あなたを助ける違い」である場合、あなたは何か非常に悪いことをしています。
ジムバルター2013年

8
ファンタジーとソフィストリー。すぐ下に、MBは「NullPointerExceptionに、何がnullだったのか、なぜnullであってはならないのかというメッセージを提供できるため、ハードデバッグに関する引数は偽物であることに注意してください。IllegalArgumentExceptionと同様です。」
ジムバルター2014

10
ここで元の回答者として、私はそれはそれほど重要ではないことを言いましょう。それは確かに6年間の会話を保証しません。どちらでも好きな方を選び、一貫性を保つ。私が指摘したように、標準はNPEです。なんらかの理由でIAEを好む場合は、それに従ってください。ただ一貫している。
GaryF 14

138

IllegalArgumentException今日までjava.util.Objects.requireNonNullJava 7 のメソッドに気付いたときまで、私はすべてnullパラメーターをスローすることに賛成でした。そのメソッドを使用する代わりに、

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

できるよ:

Objects.requireNonNull(param);

NullPointerException渡したパラメータがの場合は、がスローされますnull

そのメソッドがまさに真っ最中であるjava.utilことを考えると、その存在NullPointerExceptionは、スローが「Javaによる方法」であることをかなり強く示していると考えています。

とにかく決まっていると思います。

もちろん、NullPointerException何がnullであったのか、なぜnullであってはならないのかというメッセージを提供できるので、ハードデバッグに関する引数は偽です。と同じようにIllegalArgumentException

もう1つの利点はNullPointerException、非常にパフォーマンスが重要なコードでは、nullの明示的なチェック(およびNullPointerExceptionわかりやすいエラーメッセージ)を省略できNullPointerException、nullのメソッドを呼び出すときに自動的に取得されることを信頼できることです。パラメータ。メソッドをすばやく呼び出す(つまり、すぐに失敗する)場合、基本的に同じ効果がありますが、開発者にとってユーザーフレンドリーではありません。ほとんどの場合、明示的にチェックし、どのパラメーターがnullであったかを示す有用なメッセージをスローしてスローする方が良いでしょうが、メソッド/コンストラクターの公開されたコントラクトを壊すことなく、パフォーマンスが要求する場合はそれを変更するオプションがあると便利です。


14
グアバPreconditions.checkNotNull(arg)もNPEを投げます。
assylias 2012年

14
これは、不正なnull ARGUMENTSに対するNullPointerExceptionに重みを追加するものではありません。JDK requireNonNull()とGuava checkNotNull()はどちらも、コード内の任意のオブジェクトで呼び出すことができます。たとえば、ループ内で呼び出すことができます。requireNotNull()とcheckNotNull()は、いくつかのメソッド引数で呼び出され、IllegalArgumentExceptionをスローすると想定できませんでした。GuavaにはIllegalArgumentExceptionをスローするPreconditions.checkArgument()もあります。
ボグダンカルマック2013年

2
ボグダンによる公平な点はありますが、requireNonNullの典型的な(そして一般的に意図された)使用は引数のチェックのためだと思います。ループで何かがnullでないことを確認する必要がある場合、アサーションが典型的な方法であると思いました。
MB。

15
Object.requireNonNull()のJavaDocは引数に重みを追加すると思います:「このメソッドは主にメソッドとコンストラクターでパラメーター検証を行うために設計されています」
Richard Zschech

多くの場合、暗黙のnullチェックを優先するパフォーマンス引数は無効です。JITは、ユーザーのnullチェックを認識し、次の暗黙のnullチェックを省略できます。また、どちらのタイプのnullチェックにも同じ最適化セットを使用できます。特に詳細については、このWikiを参照してください。ユーザー作成のnullチェックは、ほとんどの場合、JVMによって挿入されたものと機能的に同じです。もちろん、カスタムメッセージのようにヌルでより凝った何かをしている場合、この最適化は適用されない可能性があります。
BeeOnRope

70

私はJDKライブラリ、特にコレクションと並行処理の設計に従う傾向があります(Joshua Bloch、Doug Lea、これらの人たちは、堅牢なAPIの設計方法を知っています)。とにかく、JDKの多くのAPIは積極的にをスローしNullPointerExceptionます。

たとえば、Map.containsKey州のJavadoc :

@throws NullPointerException-キーがnullであり、このマップがnullキーを許可しない場合(オプション)。

自分のNPEを投げることは完全に有効です。規則は、例外のメッセージにnullであったパラメーター名を含めることです。

パターンは次のとおりです。

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になるため、引数を含める必要はありません。「nullはnullであってはなりません」と表示され、あまり役に立ちません。:-)それ以外の場合は、同意します。意味のあるメッセージを使用して、「リッチな」NPEを作成できます。
PhiLho 2013

5
同意する必要があります-疑わしい場合は標準APIに従ってください。APIのすべてが最適であるとは限りませんが、それでも何百人もの開発者によって維持および反復され、何百万人ものプログラマーによって使用されています。Java 7では、このように使用されているNPEの別の例があります。Objects.requireNonNull(T obj)メソッド-オブジェクト参照がnullでないことを確認するために明確に指定され、メソッド/コンストラクターでパラメーター検証を行うために明確に指定され、オブジェクトがnullの場合にNPEをスローするよう明確に指定されます。終了
flamming_python 2014年

44

よく提示されたため、Jason Cohenの議論に賛成票を投じました。少しずつ解体しましょう。;-)

  • NPEのJavaDocは明示的に言う「ヌルオブジェクトの他の違法な使用」。ランタイムでnullが発生しないはずの状況に限定されている場合は、そのようなケースをすべてはるかに簡潔に定義できます。

  • 間違ったことが想定されている場合は役に立ちませんが、カプセル化が適切に適用されていると想定すると、nullが不適切に逆参照されているかどうか、またはメソッドが不適切なnullを検出して例外を発生させたかどうかを気にする必要はありません。

  • 複数の理由でIAEよりもNPEを選択します

    • 違法操作の性質についてより具体的です
    • nullを誤って許可するロジックは、不正な値を誤って許可するロジックとは大きく異なる傾向があります。たとえば、ユーザーが入力したデータを検証している場合、許容できない値を取得すると、そのエラーの原因はアプリケーションのエンドユーザーにあります。nullを取得した場合、それはプログラマエラーです。
    • 無効な値は、スタックオーバーフロー、メモリ不足エラー、解析例外などの原因となる可能性があります。実際、ほとんどのエラーは通常、ある時点で、メソッド呼び出しの無効な値として存在します。このため、私はIAEを、RuntimeExceptionの下のすべての例外の最も一般的なものとして見ています。
  • 実際、他の無効な引数は、他のあらゆる種類の例外を引き起こす可能性があります。UnknownHostExceptionFileNotFoundException、さまざまな構文エラー例外、IndexOutOfBoundsException、認証エラーなど。

一般的に、NPEは、従来、フェイルファストの原則に従わないコードに関連付けられてきたため、非常に悪意があると感じています。さらに、JDKがNPEにメッセージ文字列を入力できなかったため、根本的に確立されていない強力な否定的な感情が生まれています。実際、ランタイムの観点から見たNPEとIAEの違いは、厳密にはその名前です。その観点から見ると、名前をより正確に表すほど、発信者により明確に伝えることができます。


ほとんどの未チェックの例外の違いは名前だけです。
するThorbjörnRavnアンデルセン

20

それは「聖戦」形式の質問です。言い換えれば、両方の選択肢は良いですが、人々は死を守る好みを持っています。


いいえ、この質問に対する正しい答えは1つだけです。それは、メソッドへの入力が正しくない場合にIllegalArgument例外をスローすることです。また、
開発

@ Mr.Qそして、私はそれを考えてNullPointerExceptionスローする必要があります。それは、JDKの用途、およびインタフェースのために必要ですが、それが(ちょうどのような、より具体的だと慣例だIndexOutOfBoundsException、などなど、)
ソロモンUcko

kekekekkek ...:D
Yousha Aleayoub

17

それがsetterメソッドでありnull、それに渡されている場合、をスローする方が理にかなっていると思いますIllegalArgumentExceptionNullPointerException実際にを使用しようとしている場合、Aの方が理にかなっているようですnull

あなたがそれを使用しているとあれば、それはですnullNullPointer。それが渡されて、それがであるnull場合IllegalArgument


9

Apache Commons Langには、ここで説明する多くのことを行うNullArgumentExceptionがあります。それはIllegalArgumentExceptionを拡張し、その唯一のコンストラクターは、nullでないはずの引数の名前を取ります。

NullArgumentExceptionやIllegalArgumentExceptionのようなものをスローすることは例外的な状況をより正確に説明していると私は感じていますが、私の同僚と私は、この件に関するBlochの助言に従うことにしました。


7
注彼らはコモンズ-lang3からそれを削除:apache-commons.680414.n4.nabble.com/...
artbristol

7

言われていることにこれ以上同意できませんでした。早く失敗し、速く失敗します。かなり良い例外のマントラ。

どの例外をスローするかという問題は、主に個人的な好みの問題です。私の考えでは、IllegalArgumentExceptionはNPEを使用するよりも具体的に思えます。問題はメソッドに渡した引数にあり、メソッドの実行中に生成された可能性のある値ではないということです。

私の2セント


7

実際、IllegalArgumentExceptionまたはNullPointerExceptionをスローするという質問は、私の控えめな見解では、Javaでの例外処理を完全には理解していない少数派にとっての「聖なる戦争」にすぎません。一般に、ルールは次のように単純です。

  • デバッグするのがはるかに難しい不正な状態を回避するために、引数制約違反はできるだけ早く(->高速失敗)示す必要があります。
  • 何らかの理由で無効なnullポインターの場合は、NullPointerExceptionをスロー
  • 不正な配列/コレクションインデックスの場合は、ArrayIndexOutOfBoundsをスローします
  • 配列/コレクションのサイズが負の場合は、NegativeArraySizeExceptionをスローします
  • 上記の対象外であり、さらに具体的な例外タイプがない不正な引数の場合は、IllegalArgumentExceptionをゴミ箱としてスローします。
  • 一方、何らかの妥当な理由で高速失敗で回避できなかったWITHIN A FIELD制約違反の場合は、キャッチして、IllegalStateExceptionまたはより具体的なチェック例外として再スローします。この場合、元のNullPointerException、ArrayIndexOutOfBoundsなどを渡さないでください。

すべての種類の引数制約違反をIllegalArgumentExceptionにマッピングする場合には、少なくとも3つの非常に適切な理由があります。

(1)プログラマーは、引数制約違反のすべてのケースがIllegalArgumentExceptionを引き起こすと安全に想定することはできません。これは、標準クラスの大多数が、特定の種類の例外が利用できない場合、ごみ箱としてではなく、この例外を使用するためです。標準ライブラリはほとんどの場合に違反するさまざまなルールに従っており、ほとんどのAPIユーザーもそれらを使用するため、APIで引数制約違反のすべてのケースをIllegalArgumentExceptionにマッピングしようとすると、クラスを使用したプログラマの不満が生じるだけです。

(2)例外をマッピングすると、実際には、単一継承が原因で別の種類の異常が発生します。すべてのJava例外はクラスであるため、単一継承のみをサポートします。したがって、サブクラスはどちらか一方からしか継承できないため、NullPointerExceptionとIllegalArgumentExceptionの両方を実際に示す例外を作成する方法はありません。したがって、引数がnullの場合にIllegalArgumentExceptionをスローすると、プログラムがプログラムで問題を修正しようとするたびに、APIユーザーが問題を区別することが難しくなります。

(3)マッピングは実際にバグマスキングの危険を生み出します。引数制約違反をIllegalArgumentExceptionにマッピングするには、制約された引数を持つすべてのメソッド内で外側のtry-catchをコーディングする必要があります。ただし、このcatchブロックで単にRuntimeExceptionをキャッチすることは問題外です。これは、引数制約違反が原因ではない場合でも、自分の内部で使用されているliberyメソッドによってスローされた文書化された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参照でコードを実行しようとすると(toString()のように)、Java仮想マシンによってスローされる例外です。


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

... 2つの引数リスト:"", nullおよびnull, ImmutableList.of()。これらの呼び出しのそれぞれが予期しNullPointerExceptionたものをスローすることをテストします。この実装では、nullリストを渡しても生成されませNullPointerException。ただし、たまたまデフォルトの文字列を使用しているIllegalArgumentExceptionため、NullPointerTester偶然にが生成されます""。値NullPointerTesterのみNullPointerExceptionを期待する場合はnull、バグをキャッチします。それが期待するなら、それはIllegalArgumentExceptionそれを逃します。


5

一部のコレクションは、ではなくnullを使用して拒否されると想定しています。たとえば、を含むセットを拒否するセットと比較すると、最初のセットは他のセットを呼び出してキャッチしますが、キャッチしません。(私はの実装を見ています。)NullPointerExceptionIllegalArgumentExceptionnullnullcontainsAllNullPointerExceptionIllegalArgumentExceptionAbstractSet.equals

このように未チェックの例外を使用することはアンチパターンであり、含むコレクションと含まnullないコレクションを比較することnullは、本当に例外生成する可能性のあるバグである、またはnullコレクションをまったく配置することが悪い考えであると合理的に主張することができます。それにもかかわらず、そのequalsような場合に例外をスローする必要があると断言しない限りNullPointerException、特定の状況では必須であるが他の状況では不要であることを思い出して立ち往生しています。(「「c」の後を除く、NPEの前のIAE ...」)


コンテナがコレクション内の要素に応じてNPEをスローする方法がわかりません。NPEがスローされる(唯一の理由)の唯一の理由は、コレクション自体がnullの場合です(その場合、NPEがイテレーターにアクセスしようとするため、NPEがスローされます)。ただし、これにより、null入力をチェックする必要があるかどうか、またはアクセスを試行するまで入力を伝播する必要があるかどうかという問題が発生します。
Alowaniak

2
new TreeSet<>().containsAll(Arrays.asList((Object) null));が含まれているNPEためにスローさListれますnull
Chris Povirk 16

1
確かに、TreeSet#containsはNPEをスローします。「指定された要素がnullであり、このセットが自然順序付けを使用している場合、またはそのコンパレータがnull要素を許可していない場合」。nullを許可するAbstractSetのみを確認しました。個人的には奇妙なことに、単にfalseを返すだけではありません。
Alowaniak

5

主観的な質問として、これはクローズされるべきですが、まだオープンです:

これは、私の以前の勤務先で使用されていた社内ポリシーの一部であり、非常に効果的でした。これはすべてメモリからのものなので、正確な表現を思い出せません。彼らがチェック例外を使用しなかったことは注目に値しますが、それは質問の範囲を超えています。彼らが使用した未チェックの例外は、3つの主要なカテゴリに分類されました。

NullPointerException:意図的にスローしないでください。NPEは、null参照を逆参照するときにVMによってのみスローされます。これらがスローされないことを確実にするために、可能な限りの努力を払う必要があります。@Nullableおよび@NotNullをコード分析ツールと組み合わせて使用​​して、これらのエラーを見つける必要があります。

IllegalArgumentException:関数への引数が公開ドキュメントに準拠していない場合にスローされるため、渡された引数に関してエラーを識別および説明できます。OPの状況はこのカテゴリに分類されます。

IllegalStateException:関数が呼び出され、その引数が渡されたときに予期しないものであるか、メソッドがメンバーであるオブジェクトの状態と互換性がない場合にスローされます。

たとえば、長さのあるもので使用されるIndexOutOfBoundsExceptionの2つの内部バージョンがありました。IllegalStateExceptionのサブクラスの1つ。インデックスが長さより大きい場合に使用されます。もう1つはIllegalArgumentExceptionのサブクラスで、インデックスが負の場合に使用されます。これは、オブジェクトに項目を追加でき、引数が有効になる一方で、負の数が有効になることはないためです。

私が言ったように、このシステムは非常にうまく機能し、なぜその違いがあるのか​​を説明するのに誰かを要しました。何が問題だったかがわかると、そのエラーをどこでキャッチして、追加のデバッグ情報を作成できるかがわかります。」

NullPointerException:NPEがスローされないように、Nullケースを処理するかアサーションに入れます。アサーションを入れると、他の2つのタイプの1つになります。可能であれば、アサーションがそもそもあったかのようにデバッグを続行します。

IllegalArgumentException:呼び出しサイトに問題があります。渡される値が別の関数からのものである場合は、誤った値を受け取っている理由を調べてください。引数の1つを渡した場合、期待どおりの結果を返さない関数が見つかるまで、エラーが呼び出しスタックを調べます。

IllegalStateException:関数を正しい順序で呼び出していません。引数の1つを使用している場合は、それらを確認し、問題を説明するIllegalArgumentExceptionをスローします。その後、問題が見つかるまで、スタックに対して頬を伸ばすことができます。

とにかく、彼のポイントは、IllegalArgumentAssertionsをスタックにしかコピーできないということでした。IllegalStateExceptionsまたはNullPointerExceptionsは、関数と関係があるため、スタックに伝達する方法はありません。


4

一般的には、開発者がすべき決して NullPointerExceptionがスローません。この例外は、コードが値がnullである変数を逆参照しようとしたときにランタイムによってスローされます。したがって、メソッドがnullを明示的に禁止したい場合は、たまたまnull値がNullPointerExceptionを発生させるだけではなく、IllegalArgumentExceptionをスローする必要があります。


9
NPEのJavaDocには別の意見があります。「アプリケーションは、このクラスのインスタンスをスローして、nullオブジェクトの他の不正な使用を示す必要があります。」それほど
断定

4

他の不正な引数からNull引数を選び出したかったので、IAEからNullArgumentExceptionという例外を導出しました。例外メッセージを読む必要すらなくても、null引数がメソッドに渡されたことを知っているので、メッセージを読むことで、どの引数がnullだったかがわかります。私はまだIAEハンドラーでNullArgumentExceptionをキャッチしますが、ログで違いをすばやく確認できます。


「新しいIllegalArgumentException( "foo == null")をスローする」アプローチを採用しました。あなたは(あなたが右sttatementなどを見ていることは確かであることを)とにかく変数名をログに記録する必要がある
するThorbjörnRavnアンデルセン

4

二分法...それらは重なっていませんか?全体の重複しない部分のみが二分法を作成できます。私の考えでは:

throw new IllegalArgumentException(new NullPointerException(NULL_ARGUMENT_IN_METHOD_BAD_BOY_BAD));

1
これは、例外の作成のオーバーヘッドを2倍にし、キャッチNullPointerExceptionしても何も起こらないため、実際には役に立ちません。役立つ唯一のものはですがIllegalNullPointerArgumentException extends IllegalArgumentException, NullPointerException、多重継承はありません。
maaartinus 2014年

より具体的な例外は、より一般的な例外でラップする必要があると思います。NPEは式用、IAEはメソッド用です。メソッドには式を含むステートメントが含まれるため、IAEがより一般的です。
Sgene9 2018年

諸経費についてはわかりません。ただし、スタックトレースは、例外の名前が途中で変更されていることを除いて、基本的に同じであるため、二重例外のオーバーヘッドが多すぎてはいけないと思います。オーバーヘッドが心配な場合は、「if」ステートメントを使用して、例外をスローする代わりにnullまたは-1を返すことができます。
Sgene9

4

NullPointerException現在の値がである参照変数を持つオブジェクトにアクセスしようとするとスローされますnull

IllegalArgumentException メソッドが予期するものとは異なる形式の引数をメソッドが受け取ったときにスローされます。


3

シナリオによると、IllegalArgumentExceptionnullプロパティの有効な値ではないため、が最適です。


0

理想的には、実行時例外はスローされるべきではありません。シナリオには、チェック済み例外(ビジネス例外)を作成する必要があります。これらの例外のいずれかがスローされてログに記録されると、ログの処理中に開発者に誤解を与えるためです。代わりに、ビジネス例外はそのパニックを引き起こさず、通常はログのトラブルシューティング中に無視されます。


-1

上記の2つの例外へのリンクからの定義はIllegalArgumentExceptionです。メソッドに不正または不適切な引数が渡されたことを示すためにスローされます。NullPointerException:オブジェクトが必要な場合にアプリケーションがnullを使用しようとするとスローされます。

ここでの大きな違いは、IllegalArgumentExceptionは、メソッドへの引数が有効であることを確認するときに使用されることになっています。NullPointerExceptionは、オブジェクトがnullのときに「使用」されているオブジェクトを使用することになっています。

それが2つを見通しに役立つことを願っています。


1
重要なのは、ランタイムではなくnullを使用しているアプリケーションであることです。したがって、「メソッドに不正または不適切な引数が渡されたとき」と「アプリケーションがnullを使用しているとき」の間にはかなり大きなオーバーラップがあります。理論的には、アプリがnull以外を必要とするフィールドにnullを渡す場合、両方の基準が満たされています。
クリストファー・スミス

-1

それが「セッター」である場合、または後でメンバーが使用するようにしている場合は、IllegalArgumentExceptionを使用する傾向があります。

メソッドで今すぐ使用する(参照解除する)ものである場合は、プロアクティブにNullPointerExceptionをスローします。ランタイムに任せるよりも、私はこれが好きです。なぜなら、私は有益なメッセージを提供できるからです(ランタイムもこれを行うことができるようですが、それは別の日の怒りです)。

メソッドをオーバーライドする場合は、オーバーライドされたメソッドが使用するものをすべて使用します。


-1

IllegalArgumentExceptionをスローする必要があります。これにより、プログラマーが何か無効なことをしたことが明らかになります。開発者はVMによってNPEがスローされるのを見慣れているため、プログラマーはすぐにエラーを認識せず、ランダムに周りを見回し始めます。


4
申し訳ありませんが、プログラマーが何らかの種類の例外を受け取ったときに「ランダムに」周りを見回すと...例外の名前を変更してもあまり役に立ちません。
クリストファー・スミス

-1

この場合、IllegalArgumentExceptionは、APIを使用して、「nullであってはならない」という明確な情報をユーザーに伝えます。他のフォーラムユーザーが指摘したように、APIを使用して適切な情報をユーザーに伝えたい限り、NPEを使用できます。

GaryFとtweaktは、NPEの使用を推奨する「Effective Java」(私が誓う)のリファレンスを削除しました。そして、他の優れたAPIがどのように構築されるかを見ることが、APIを構築する方法を確認するための最良の方法です。

別の良い例は、Spring APIを調べることです。たとえば、org.springframework.beans.BeanUtils.instantiateClass(Constructor ctor、Object [] args)にはAssert.notNull(ctor、 "Constructor not be null")行があります。org.springframework.util.Assert.notNull(Object object、String message)メソッドは、渡された引数(オブジェクト)がnullであるかどうかを確認し、それがnullの場合は新しいIllegalArgumentException(message)をスローして、それを組織でキャッチします。 springframework.beans.BeanUtils.instantiateClass(...)メソッド。


-5

NPEをスローすることを選択し、メソッドで引数を使用している場合、nullを明示的にチェックすることは冗長でコストがかかる可能性があります。VMはすでにそれを行っていると思います。


ランタイムには、意味のあるメッセージは含まれません。
mP。

実際、このコメントは他の意見を導き出す可能性があります。VMがで話しましょうNPE、まだプログラマはで話すIAE、彼らがしたい場合は、VMの前に。
ジンクォン

1
高価な?== nullはそれほど高価ではないと思います...さらに、null引数は後で使用するために保存するだけで、メソッド呼び出しのかなり後に例外をスローするため、エラーの追跡が難しくなります。または、null引数を使用する前に高価なオブジェクトを作成することもできます。早期発見は良いオプションのようです。
PhiLho 2013

この回答に対する反対投票は、背後にあるハードウェアの誤解です。確かに、ハードウェアチェック(CPUが行う)は、明示的なチェックよりも安価です。nullの逆参照は、CPU / OSがチェックし、JREがNullPointerExceptionをスローする特殊なケースとして処理するSegmentationFault(SegV)の特殊なケース(プロセスが所有していないページへのアクセス)です。
digital_infinity 2017
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.