LinkedList实现出现空指针异常(NPE),已实例化对象仍报错?
先理清楚你遇到的问题场景:
运行main方法时,在
stringList.add("Test")这行触发了空指针异常,具体是在JAList的add方法里dummy.getNextNode().setNodePrev(node)这一行出的问题。你已经确认了dummy已经初始化,dummy.getNextNode()应该指向dummy本身,而且要添加的node也刚完成初始化,所以怀疑是JAList<String> stringList = new JAList<String>();的构造函数没正确设置值。
核心排查方向
从你说的细节来看,虽然你觉得dummy.getNextNode()指向自己,但空指针的根源大概率是**dummy.getNextNode()实际返回了null**,要么是构造函数初始化没做好,要么是其他地方把dummy的next节点搞成null了。咱们分几种情况拆解:
1. 构造函数里dummy的双向链表初始化不完整
你怀疑构造函数有问题,这个方向非常准。一个合格的双向循环链表的dummy头节点,必须同时满足:
dummy.nextNode = dummydummy.prevNode = dummy
如果你的构造函数只设置了其中一个,比如只给nextNode赋值但没管prevNode,甚至写错成dummy.setNextNode(null),那后续调用getNextNode()就会返回null,调用setNodePrev(node)自然就空指针了。
举个错误的构造函数例子:
public JAList() { dummy = new Node<>(); // 只设置了next,没设置prev,或者误写成null dummy.setNextNode(dummy); }
正确的构造逻辑得是这样:
public JAList() { dummy = new Node<>(); dummy.setNextNode(dummy); dummy.setNodePrev(dummy); // 必须同时把prev也指向自己,形成闭环 }
2. Node类的get/set方法有逻辑bug
还有一种可能是getNextNode()或者setNodePrev()本身写错了,比如:
getNextNode()没返回实例变量nextNode,反而错误返回了nullsetNodePrev()内部对参数做了错误的非空校验,或者变量名写错导致赋值失败
比如错误的get方法:
public Node<T> getNextNode() { // 这里写错了,返回了null而非nextNode return null; }
3. 多线程并发修改(单线程可忽略)
如果你的代码是在多线程环境跑的,有可能其他线程在你调用add方法前修改了dummy的nextNode,把它改成了null。但如果是单线程的main方法,这个情况可以直接排除。
快速验证的小技巧
你可以在add方法开头加几行调试代码,打印关键变量的状态,一眼就能找到问题:
public boolean add(T element) { Node<T> node = new Node<>(element); // 打印调试信息,确认各个节点的状态 System.out.println("dummy对象:" + dummy); System.out.println("dummy的next节点:" + dummy.getNextNode()); System.out.println("dummy的prev节点:" + dummy.getNodePrev()); System.out.println("要添加的node:" + node); // 原来的add方法逻辑 Node<T> nextNode = dummy.getNextNode(); node.setNextNode(nextNode); node.setNodePrev(dummy); dummy.setNextNode(node); nextNode.setNodePrev(node); // 如果这行空指针,说明nextNode是null size++; return true; }
运行后看控制台输出,就能明确是dummy.getNextNode()真的返回了null,还是其他变量出了问题。
总结
结合你提供的信息,最可能的原因就是JAList的构造函数没正确初始化dummy节点的双向闭环,导致dummy.getNextNode()实际是null。优先检查构造函数里dummy的nextNode和prevNode是不是都正确指向了自身,其次再检查Node类的get/set方法逻辑有没有写错。
内容的提问来源于stack exchange,提问作者Josh

