在没有抛出NullPointerException的情况下执行空检查的最佳方法是什么?

PhD*_*PhD 0 java nullpointerexception

所以我知道我可能有一个空List(特别是ArrayList).现在对它进行简单检查就像在我检查它时实际抛出NullPointerException一样.这个让我难过,因为我总是成功使用它,但我确信我错过了一些东西:

public class MyPost {

private int id;

private List<Label> labels;

public MyPost(int id){ this.id = id }

//getter setters for both plus this added method:

public void addLabel(Label aLabel)
  {
     if(labels == null)
       labels = new ArrayList<Label>();

     labels.add(aLabel);
  }

}
Run Code Online (Sandbox Code Playgroud)

现在在我的代码的另一部分,我正在迭代客户端发送的ID列表.为简单起见,假设循环变量'i'正在提供id

MyPost aPost = new MyPost(i);
Run Code Online (Sandbox Code Playgroud)

在我的逻辑中,我可能会也可能不会在帖子中添加标签.所以在继续之前,我检查是否存在这样的标签:

if(aPost.getLabels()!=null)
   //process labels
Run Code Online (Sandbox Code Playgroud)

现在,如果没有添加任何标签列表,则抛出空指针异常!但这正是我想要检查的,我仍然得到一个NPE!

我知道aPost.getLabels()如果没有添加任何内容则为null.但这种比较似乎失败了,并引发了一场NPE.如何解决这个问题?只是让我难过!

更新: 这是获取标签代码.只是一个微不足道的吸气鬼......

public List<Label> getLabels() { return labels;}
Run Code Online (Sandbox Code Playgroud)

我们注意到以前忽略过的东西.我确定java用来"短路"它的if条件,即在OR条件下,如果第一个条件被评估为true,它将不会检查第二个条件(如果第一个条件被评估为false,则类似于AND的短路) ).我不完全确定这是否是原因,但这里是if子句:

if(aPost.getLabels()!=null || !aPost.getLabels().isEmpty())
//process labels
Run Code Online (Sandbox Code Playgroud)

如果列表确实为空,则短路不应该评估第二个条件,正确吗?似乎可能是原因,但我们仍在测试它.现在只是预感......

biz*_*lop 10

一般来说,调试NPE时要做的第一件事就是仔细检查堆栈跟踪,并确定从中抛出的确切行.

下一步是检查该行上解除引用运算符()左侧的所有值..NPE的另一个来源是for循环的新风格,第三个是自动拆箱,据我所知,没有其他结构固有地抛出NPE,尽管当然总有代码可以明确抛出它.

所有这些意味着没有堆栈跟踪和完整的代码我们也只能猜测.

(或者,如果您正在使用IDE,则可以简单地设置异常断点并在抛出NPE时检查变量的运行时值.但是您应该能够通过离线分析代码来查找NPE.堆栈跟踪.这是一项重要技能.)

更新:查看更新的问题很明显if语句是错误的.它应该是:

if(aPost.getLabels()!=null && !aPost.getLabels().isEmpty())
//process labels
Run Code Online (Sandbox Code Playgroud)

OR不是正确的操作,因为您希望aPost.getLabels()不为空且不为空.一旦知道了值,Java确实会停止布尔表达式求值,但在原始表达式中,如果aPost.getLabels()为null 则不是这种情况.