Java 链表循环潜在异常

Java 链表循环潜在异常,java,linked-list,nodes,Java,Linked List,Nodes,下面是检测链表是否包含循环的代码: public static boolean containsCycle(LinkedListNode firstNode) { // start both runners at the beginning LinkedListNode slowRunner = firstNode; LinkedListNode fastRunner = firstNode; // until we hit the end of the list while (fast

下面是检测链表是否包含循环的代码:

  public static boolean containsCycle(LinkedListNode firstNode) {

// start both runners at the beginning
LinkedListNode slowRunner = firstNode;
LinkedListNode fastRunner = firstNode;

// until we hit the end of the list
while (fastRunner != null && fastRunner.next != null) {
    slowRunner = slowRunner.next;
    fastRunner = fastRunner.next.next;

    // case: fastRunner is about to "lap" slowRunner
    if (fastRunner == slowRunner) {
        return true;
    }
}

// case: fastRunner hit the end of the list
return false;
while循环的条件不应该是fastRunner!=null&&fastRunner.next.next!=无效的对于当前代码,fastRunner可能是链接列表中的最后一个节点,因此一旦进入while循环,最后一个节点的下一个节点将导致异常

使用当前代码,fastRunner可以是链接列表中的最后一个节点

fastRunner
不能是链接列表中的最后一个节点,因为您的
while
循环

while (fastRunner != null && fastRunner.next != null) {
检查
fastRunner
是否不是最后一个元素(因为
fastRunner.next==null
意味着
fastRunner
是最后一个元素)。这个作业在你的循环中

fastRunner = fastRunner.next.next;

当然可以将
fastRunner
设置为
null
,但您没有使用它来执行任何会导致null指针异常的操作,并且
while
循环的下一次迭代将退出(因为现在
fastRunner==null

只要线程安全不是问题,此算法肯定是正确的。 换句话说,如果在该方法运行时另一个线程中的代码更改了列表,那么它肯定会产生错误的结果或
NullPointerException

但是,如果您的代码是单线程的,
NullPointerException
就永远不会发生。要使此代码抛出一个
NullPointerException
,必须有一个
运算符,其左侧有一个空值。尽管还有其他类型的代码可以抛出
NullPointerException
,例如自动取消装箱空值,并在for each循环中使用空参数;你没有这些

<> p>因此,如果看到这个代码可以抛出 NulLoPoExtExeals,那么您应该依次考虑代码中的每个<代码> .<代码>运算符。有四个点要考虑。< /P>
  • while(fastRunner!=null&&fastRunner.next!=null){
    -这不会导致
    NullPointerException
    ,因为只有在
    fastRunner
    由于短路评估而不为null时,才会检查此代码
  • slowRunner=slowRunner.next;
    -这永远不会导致
    NullPointerException
    ,因为
    slowRunner
    获取的每个值都已经被
    fastRunner
    fastRunner.next
    获取。因此,如果
    slowRunner
    为null,您就已经获得了de>NullPointerException。您无法从此点获取它
  • fastRunner=fastRunner.next.next;
    -这不会导致
    NullPointerException
    ,因为您已经检查了
    fastRunner
    是否为空
  • fastRunner=fastRunner.next.next;
    -这不会导致
    NullPointerException
    ,因为您已经检查了
    fastRunner.next
    是否为空
  • 因此,代码中没有可能导致
    NullPointerException
    的点,除非在代码执行时第二个线程更改了列表