<p>当你声明一个引用变量(即一个对象)时,你实际上是在创建一个指向对象的指针。请考虑以下代码,其中声明了原始类型为<code>int</code>的变量:</p>
<pre><code>int x;
x = 10;
</code></pre>
<p>在本例中,变量<code>x</code>是一个<code>int</code>,Java将为您初始化它为<code>0</code>。当您在第二行给它赋值为<code>10</code>时,您的<code>10</code>值将写入<code>x</code>所引用的内存位置。</p>
<p>但是,当您试图声明引用<em>类型</em>时,会发生一些不同的情况。获取以下代码:</p>
<pre><code>Integer num;
num = new Integer(10);
</code></pre>
<p>第一行声明了一个名为<code>num</code>的变量,但它实际上还不包含基元值。相反,它包含一个指针(因为类型是一个引用类型<code>Integer</code>)。由于您还没有指出要指向什么,Java将其设置为<code>null</code>,这意味着“<strong>我指向的是<em>nothing</em></strong>”。</p>
<p>在第二行中,<code>new</code>关键字用于实例化(或创建)类型为<code>Integer</code>的对象,指针变量<code>num</code>被分配给该<code>Integer</code>对象。</p>
<p>当您声明一个变量,但在尝试使用该变量的内容之前没有创建对象并分配给该变量时,就会发生<code>NullPointerException</code>(称为<em>解引用</em>)。所以你指的是不存在的东西。</p>
<p>当使用<code>.</code>访问方法或字段,或使用<code>[</code>索引数组时,通常会发生取消引用。</p>
<p>如果在创建对象之前试图取消对<code>num</code>的引用,则会得到<code>NullPointerException</code>。在最简单的情况下,编译器会捕捉到问题并让您知道“<code>num may not have been initialized</code>”,但有时您可能会编写不直接创建对象的代码。</p>
<p>例如,可以使用以下方法:</p>
<pre><code>public void doSomething(SomeObject obj) {
//do something to obj
}
</code></pre>
<p>在这种情况下,您不是在创建对象<code>obj</code>,而是假设它是在调用<code>doSomething()</code>方法之前创建的。注意,可以这样调用方法:</p>
<pre><code>doSomething(null);
</code></pre>
<p>在这种情况下,<code>obj</code>就是<code>null</code>。如果该方法旨在对传入对象执行某些操作,则抛出<code>NullPointerException</code>是适当的,因为这是程序员错误,程序员将需要该信息进行调试。请在异常消息中包含对象变量的名称,如</p>
<pre><code>Objects.requireNonNull(a, "a");
</code></pre>
<p>或者,在某些情况下,方法的目的不仅仅是操作传入的对象,因此可以接受空参数。在这种情况下,您需要检查一个<strong>空参数并以不同的方式操作。您还应该在文档中对此进行解释。例如,<code>doSomething()</code>可以写成:</p>
<pre><code>/**
* @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
}
}
</code></pre>
<p>最后,<a href="https://stackoverflow.com/q/3988788/2775450">How to pinpoint the exception & cause using Stack Trace</a></p>
<blockquote>
<p>What methods/tools can be used to determine the cause so that you stop
the exception from causing the program to terminate prematurely?</p>
</blockquote>
<p>带有findbugs的声纳可以检测NPE。
<a href="https://stackoverflow.com/questions/20899931/can-sonar-catch-null-pointer-exceptions-caused-by-jvm-dynamically">Can sonar catch null pointer exceptions caused by JVM Dynamically</a></p>