-2

我有这个构造函数:

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

4 回答 4

2

好吧,永远this不可能null。因此,要么 要么prev必须nextnull。您的构造函数this同时分配给prevand next,因此这不能成为其中之一的原因null。因此,必须有其他您没有显示的代码将其中一个(或两个)设置为null.

编辑

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

第二次编辑

随着testIsEmpty代码被揭示,那么要么tstringHeader必须是null.

于 2013-03-09T00:34:44.327 回答
1

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

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

于 2013-03-09T00:34:21.790 回答
0

我能看到这种情况发生的唯一方法是如果stringHeader或者tnull......

(给 jlordo 的道具t)...

于 2013-03-09T00:43:24.180 回答
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。

  • 如果stringHeader是,null那么stringHeader.isEmpty()将抛出一个 NPE。
  • 如果t是,则调用null将抛出 NPE 。t.checkExpect

也有可能(理论上)在checkExpectorisEmpty调用中抛出 NPE,但堆栈跟踪将提供发生这种情况的证据。


从中吸取的教训:

  • 仔细阅读堆栈跟踪,并学会正确解释它。
  • 阅读您编写的代码。仔细阅读。
  • 确保您了解 Java 构造可以和不能抛出 NPE ... 或其他内在异常。(在某些情况下有一些微妙之处......虽然不是在这里。)
  • 不要贸然下没有证据支持的结论。'因为你这样做可能会浪费很多时间......如果你的“结论”被证明是不正确的。
  • 如果您无法弄清楚,请寻找更多证据:
    • 使用调试器设置断点、检查变量、单步执行代码等
    • 添加日志记录或(临时)跟踪打印。
    • 在您的脑海中或在纸上“手动执行”。
  • 如果您向其他人寻求帮助,他们将需要查看所有相关的代码堆栈跟踪和其他证据,以便他们可以自己推理。如果您只是提供对证据的(可能不正确的)解释,您将不会获得有用的帮助。
  • 不要假设问题出在别人的代码中:“也许这是我的教授让我们使用的这个测试程序包的问题?” .... 错误的!
于 2013-03-09T01:53:43.310 回答