检查非空值时,为什么会出现NullPointerException?

时间:2013-03-09 00:27:29

标签: java generics null nullpointerexception

我有这个构造函数:

public class SentinelT<T> extends NodeT<T> {

    //constructs an empty Sentinel linked to no other Nodes
    public SentinelT() {
        super(null, null, null);
    this.prev = this;
    this.next = this;
    }
...
}

因此每当我尝试更改this.prev或this.next的值,或者我尝试对这些值使用布尔运算符时,我会得到NullPointerException。例如:

public boolean isEmpty() {
    return this.prev == this && this.next == this;
}

抛出NullPointerException。我有一种感觉,我只是不理解超级构造函数或空值...感谢任何帮助。

*编辑:添加了NodeT构造函数,将添加抛出异常的实例化

//NodeT class for a doubly linked list of T
public class NodeT<T> {
    T data;
    NodeT<T> prev;
    NodeT<T> next;

    //constructs a Node object
    public NodeT(T data, NodeT<T> prev, NodeT<T> next) {
    this.data = data;
    this.prev = prev;
    this.next = next;
    }

* edit2:不同的类,假设stringHeader是发生这种情况的类的字段         SentinelT stringHeader = new SentinelT();

    public void testIsEmpty(Tester t) {
    initData();

    t.checkExpect(stringHeader.isEmpty(), true);
}

4 个答案:

答案 0 :(得分:2)

好吧,this不能null。因此,prevnext必须为null。您的构造函数会将this分配给prevnext,因此这不是其中一个null的原因。因此,必须有其他您未展示的代码,将其中一个(或两个)设置为null

修改

第二个想法,仅仅因为值为null,并不意味着它会在这里抛出NPE。

第二次编辑

如果显示testIsEmpty代码,则tstringHeader必须为null

答案 1 :(得分:1)

我很难在没有看到更多代码的情况下确定错误,但是在检查非空值时你说你得到了“NullPointerException”。您是否使用过调试器,并在isEmpty中放置一个断点并证明在执行isEmpty期间this.prev和this.next是非空的?我强烈建议使用断点来验证您对这些数据成员的值的假设。

编辑 - 看到你的编辑:这是一个很好的例子,说明为什么你必须显示的代码多于你提出错误的地方。这个故事往往更多。调试器是编码员最好的朋友。验证调试器中的假设。

答案 2 :(得分:0)

我能看到这种情况的唯一方法是stringHeadertnull ......

(jlordo for t的道具)...

答案 3 :(得分:0)

让我们明白这一点:

public boolean isEmpty() {
    return this.prev == this && this.next == this;
}

该方法不能抛出NullPointerException。它执行的任何操作都不会抛出任何异常:

  • this不能null因此,this.prevthis.next无法抛出NPE
  • 使用==将引用与null(或任何其他引用)进行比较,不能抛出NPE。

因此,如果你正在获得一个NPE,那么它来自其他地方......你错误地解释了堆栈跟踪。


第二个例子:

t.checkExpect(stringHeader.isEmpty(), true);

在此示例中,有几种方法可以抛出NPE

  • 如果stringHeadernull,则stringHeader.isEmpty()将投放NPE。
  • 如果tnull,那么t.checkExpect电话会抛出一个NPE。

理论上也可能在checkExpectisEmpty调用中抛出NPE,但堆栈跟踪会提供已发生的证据。


从中吸取教训:

  • 仔细阅读堆栈跟踪,并学会正确解释它。
  • 阅读您编写的代码。仔细阅读。
  • 确保您了解Java构造可以做什么,什么不能引发NPE ...或其他内在异常。 (在某些情况下有一些细微之处......虽然不在这里。)
  • 不要跳到证据不支持的结论。 “如果你的”结论“证明不正确,你可能会浪费很多时间。
  • 如果您无法弄明白,请寻找更多证据:
    • 使用调试器设置断点,检查变量,单步执行代码,等等
    • 添加日志记录或(临时)跟踪打印。
    • 在你的头上或纸上“手执行”。
  • 如果您要求其他人寻求帮助,他们需要查看所有相关代码堆栈跟踪和其他证据,以便他们可以自行推理。如果您只提供(可能不正确的)证据解释,您将无法获得有用的帮助。
  • 不要认为问题出现在别人的代码中:“也许这是我教授让我们使用的测试包的问题?” ....错!