web-dev-qa-db-ja.com

プログラムでNullPointerExceptionをスローしている変数を調べます

次の手法を使用して、Java)で変数がnullであるかどうかを確認できます。

  • _(var==null)_->作業が多すぎる場合
  • try { ... } catch (NullPointerException e) { ...}->例外をスローしている行を教えてくれます
  • デバッガーの使用->手動、遅すぎる

次のコード行について考えてみます。

_if (this.superSL.items.get(name).getSource().compareTo(VIsualShoppingList.Source_EXTRA)==0)  {
_

コードの特定の領域で(行だけでなく)どの変数がNullPointerExceptionをスローしているかをプログラムで確認する一般的な方法があるかどうかを知りたいです。例では、それを知っている

24
Hectoret

変数を使用せずにnullポインタ例外を引き起こす可能性があるため:

throw new NullPointerException();

Nullポインタ例外を特定の変数に固定する一般的な方法はないと言わざるを得ません。

最善の策は、各行にできるだけ少ないステートメントを配置して、nullポインター例外の原因が明らかになるようにすることです。質問のコードをリファクタリングして、次のようにすることを検討してください。

List items = this.superSL.items;
String name = items.get(name);
String source = name.getSource();
if (source.compareTo(VIsualShoppingList.Source_EXTRA) == 0)  {
    // ...
}

確かにそれはより多くのコード行です。しかし、それはまた、より読みやすく、より保守しやすいです。

28
Asaph

申し訳ありませんが、いいえ、どの変数またはメソッド呼び出しが例外の原因であるかを判断する簡単なプログラムによる方法はありません。 アスペクト指向プログラミング(AOP) のようなものを使用できます。例: AspectJ ですが、これは言語に固有のものではなく、通常、単にデバッグ目的でプログラムに組み込まれることはありません。

  • if (var==null) -> too much work
  • try { } catch() { }
  • Debugger

私はあなたがこれを聞きたくないことを知っています、しかしこれらは単にビジネスをするためのコストです。

if (this.superSL.items.get(name).getSource().compareTo(VIsualShoppingList.Source_EXTRA)==0)  {

非常に多くのメソッド呼び出しがつなぎ合わされているのを見るのは珍しいことです。私はあなたが最善の策はこれらをもっと分割する習慣を身につけることだと信じています-回線ごとに1つの呼び出しに減らす必要はありませんが、これより少ないです。どうして?

1)Correctness-これらの呼び出しの1つがnullを返すことは、設計で有効ですか?もしそうなら、あなたはそれを分解し、それをテストし、そしてそれを適切に扱うべきです。

2)Understandability-将来のメンテナ(future youを含む)が、適切な名前の変数を中間にすると理解しやすくなりますこの行で何が起こっているのかを明確にするのに役立ちます。

3)Efficiency-通常、グラフの奥深くに入ると(一連のメソッド呼び出しをつなぎ合わせる)、後でそこに戻る必要がある可能性があります。この中間値を中間変数に取り込むということは、1つ以上のメソッド呼び出しを再度行わないようにすることを意味します。

4)Debugging-質問で示されているように、このように複雑な行を分割すると、デバッグが簡単になります。例外の考えられる原因を絞り込むことによって。

6
Bert F

ここで発表 として、JDK 14を含める必要があると考えるかもしれません JEP 358

JEP 358:役立つNullPointerExceptions

このコードでNPEが発生するとします。

a.b.c.i = 99;

ファイル名と行番号は、どの変数がnullであったかを正確に特定していません。
それはaまたはbまたはcでしたか?

アレイへのアクセスと割り当てでも同様の問題が発生します。このコードでNPEが発生するとします。

a[i][j][k] = 99;

ファイル名と行番号は、どの配列コンポーネントがnullであったかを正確に特定するものではありません。
それはaまたはa[i]またはa[i][j]でしたか?

説明:

より複雑なステートメントa.b.c.i = 99;がNPEをスローした場合、メッセージはステートメントを分析し、nullに至るまでのフルアクセスパスを表示することで原因を特定します。

Exception in thread "main" Java.lang.NullPointerException: 
        Cannot read field "c" because "a.b" is null
    at Prog.main(Prog.Java:5)

繰り返しますが、JDK14でテストされます。

2
VonC

「デバッガーを使用する->手動で、遅すぎる」とはどういう意味ですか?コードが適切に構造化されている場合、同じ行で使用される変数は2つまたは3つを超えることはありません。それらをチェックするのはとても遅いですか?毎分NullPointerがあるわけではありません。

2
Petar Minchev

私はあなたが(var==null)大変な作業ですが、Miguelがコメントで述べたように、それが私が行うことです。

1
Oren Hizkiya

注意すべきだと思います デメテルの法則

デリゲートメソッドが多くなるため、厳密にフォローしている人は多くありません。
しかし、それから離れすぎると、透過的である必要がある内部構造への依存が発生します。

1
Hardcoded

残念ながら、Javaは、変数の名前や行番号以外のエラーの正確な位置を表示しません。ただし、Eclipseを使用する場合は、null許容の注釈を使用できます。 を参照してください。 http://www.fosslc.org/drupal/content/bye-bye-npe たとえば。 どの@ NotNull Javaアノテーションを使用する必要がありますか? =他の注釈システムの場合。

0
Konrad Höffner

私にとって本当に美しく機能したのは、通常はスローされる例外をキャッチし、Logを使用してそれらのいずれかに「null」値があるかどうかを確認することです。

私のコード:

 try {
                 if (description_visible) advice_title_cur.setText(all_title_array[pos]);
                 else advice_title_cur.setText(all_title_array[pos] + "...");

             } catch (NullPointerException e) {
                 e.printStackTrace();
                 Log.e("My name", "description_visible " + description_visible);
                 Log.e("My name", "advice_title_cur " + advice_title_cur);
                 Log.e("My name", "all_title_array " + all_title_array);
                 Log.e("My name", "pos " + pos);
             }
0
Egis