1. ホーム

[解決済み】NullPointerExceptionとは何ですか、そしてどのようにそれを修正すればいいですか?

2022-04-20 12:47:17

質問

Null Pointer Exceptionとは( java.lang.NullPointerException また、その原因は何ですか?

例外が原因でプログラムが早期に終了するのを防ぐために、どのような方法/ツールを使って原因を特定できますか?

解決方法は?

参照変数(つまりオブジェクト)を宣言するとき、実際にはオブジェクトへのポインタを作成していることになります。プリミティブ型の変数を宣言している次のコードを考えてみましょう。 int :

int x;
x = 10;

この例では、変数 xint で、Javaはこれを初期化して 0 を使用します。の値を代入すると 10 の値は、2行目では 10 が参照するメモリロケーションに書き込まれます。 x .

しかし、参照を宣言しようとすると タイプ となると、何か違うことが起こる。次のコードを見てください。

Integer num;
num = new Integer(10);

最初の行では、変数 num しかし、それはまだプリミティブな値を持っていません。代わりにポインタを含んでいます(型が Integer は参照型である)。何を指すかはまだ言っていないので、Javaはそれを null という意味で、quot; を指しています。 何もない "です。

2行目では new キーワードを使用して、以下のタイプのオブジェクトをインスタンス化 (または作成) しています。 Integer で、ポインタ変数 num は、その Integer オブジェクトを作成します。

は、その NullPointerException (NPE) は、変数を宣言したものの、変数の内容を使おうとする前にオブジェクトを作成して変数に代入していない場合に発生します (これを デリフェレンス ). つまり、実際には存在しないものを指し示していることになります。

デリファレンスは通常 . を使ってメソッドやフィールドにアクセスしたり、あるいは [ を使用して配列のインデックスを作成します。

を参照解除しようとした場合 num 以前 オブジェクトを作成すると NullPointerException . 最も些細なケースでは、コンパイラが問題をキャッチして、" を知らせてくれます。 num may not have been initialized ," しかし、時には、オブジェクトを直接生成しないコードを書くこともあるでしょう。

例えば、次のようなメソッドがあるとします。

public void doSomething(SomeObject obj) {
   // Do something to obj, assumes obj is not null
   obj.myMethod();
}

この場合、オブジェクトを作成するのではなく obj よりも前に作成されたと仮定しています。 doSomething() メソッドが呼び出されました。なお、このようにメソッドを呼び出すことは可能です。

doSomething(null);

その場合 objnull という文があり obj.myMethod() を投げます。 NullPointerException .

上記のメソッドのように、渡されたオブジェクトに対して何かを行うことを意図している場合、このメソッドでは NullPointerException なぜなら、それはプログラマーのエラーであり、プログラマーはデバッグのためにその情報を必要とするからです。

に加えて NullPointerException メソッドのロジックの結果として投げられたものをチェックし、 メソッドの引数に null の値で明示的にNPEを投げるには、メソッドの冒頭付近に以下のような記述をします。

// Throws an NPE with a custom error message if obj is null
Objects.requireNonNull(obj, "obj must not be null");

なお、エラーメッセージにははっきりと どの オブジェクトは null . これを検証する利点は、1) より明確なエラーメッセージを返すことができる、2) 残りのメソッドで obj が再割り当てされても、NULLではないので、安全に再参照することができます。

また、メソッドの目的が渡されたオブジェクトを操作することだけではない場合、NULL パラメータが許容されることもあります。このような場合には ヌルパラメータ であり、動作が異なる。このこともドキュメントで説明する必要があります。例えば doSomething() と書くことができる。

/**
  * @param obj An optional foo for ____. May be null, in which case
  *  the result will be ____.
  */
public void doSomething(SomeObject obj) {
    if(obj == null) {
       // Do something
    } else {
       // Do something else
    }
}

最後に スタックトレースで例外の原因を特定する方法

<ブロッククオート

原因を特定するために、どのような方法/ツールを使えばよいでしょうか。 例外が原因でプログラムが早期に終了してしまうことはありませんか?

バグを見つける機能を持つSonarは、NPEを検出することができます。 JVMによるNULLポインタ例外をソナーで動的に捕捉できるか

現在Java 14では、NullPointerExceptionの根本原因を表示する新しい言語機能が追加されています。この言語機能は、2006年以来、SAP商用JVMの一部となっている。

Java14では、NullPointerExceptionのExceptionメッセージのサンプルは以下のとおりです。

<ブロッククオート

スレッド "main" で java.lang.NullPointerException を発生させました。java.util.List.size()を呼び出すことができません。