0

我正在使用双端队列进行分配,我们遇到了一个问题,即对象引用在通过一个非常简单的方法传递后从节点中消失。

一些重要的定义:

class Node {
    String s;
    Node prev;
    Node next;

    ...

}

class Sentinel extends Node {
    Node prev;
    Node next;
   //Constructor uses that of Node
}

class Deque {
    Sentinel start;

    ...
}

我们正在编写的一种方法是根据给定的字符串从双端队列中删除一个节点。

在双端队列中:

public void removeSorted(String toRemove) {
    // System.out.println(this.start);
    // System.out.println(this.start.next);
    this.start.next.removeSorted(toRemove);
}

注释掉的 println 显示正确的 Sentinel 和 Node。

然后,在节点中:

public void removeSorted(String toRemove) {
    if (this.s.equals(toRemove)) {
        // System.out.println(this.prev);
        // System.out.println(this.prev.next);
        this.prev.next = this.next;
        this.next.prev = this.prev;
    } else if (this.s.compareTo(toRemove) > 0) {
        throw new RuntimeException("String does not exist in these nodes!");
    } else {
        this.next.removeSorted(toRemove);
    }
}

this.prev正如预期的那样,用于在第一次递归时输出 Sentinel的 println 。但是,this.prev.next 输出 null 而不是 Node。

此功能仅在尝试删除第一个节点时失败,直接在 Sentinel 之后。如果您尝试删除任何其他节点,它会正常工作,并且尝试调用this.prev.next会导致非空答案。

为什么在传递给函数时(立即)引用消失了,因为我们已经证明在调用函数之前引用就在那里?

4

1 回答 1

0

Node要么您的问题代码错误,要么您在和 中都有相同的字段Sentinel。这意味着,这两个是不同的:

  • start.nextnextSentinel 类的字段,它隐藏了 Node 类中的同名字段。
  • start.next.prev.next也是 的一个字段start,但现在它是 Node 类的字段,因为您通过 Node 引用访问它。

从 Sentinel 中移除prev和移除。next实际上删除整个哨兵,看起来你习惯于“删除” String s,这是不可能的,你不能“删除”超类字段。或者,如果您需要/想要哨兵,请参阅下面的替代设计。

此外,这说明了为什么您应该使用gettersetter而不是直接访问字段...您的 IDE 可能有很好的重构工具来添加 getter 等(右键单击字段,请参阅“重构”子菜单),使用它!如果您的 IDE 没有,请切换到有的(我更喜欢 NetBeans,但 Eclipse 和 IntelliJ 也值得),在没有这样的 IDE 的情况下编写 Java 是一种自虐练习......


此外,在 Java 中避免这种继承。你可能应该有这样的整体设计:

interface NodeInterface {...}
public class Node implements NodeInterface {...}
public class Sentinel implements NodeInterface {...}

然后在 中NodeInterface,定义 getter 和 setter,它们应该作为参数和返回NodeInterface类型。Sentinel类当然不会支持所有接口方法,因此这些方法可以return null;/不做任何事情,或者throw new IllegalStateException("Sentinel does not support Xxxx.");取决于方法,如果为哨兵调用该方法是否是调用代码中的错误(最好从抛出异常开始)。

如果这是学校作业并且您还没有研究过接口,那么替换interface NodeInterfaceclass NodeBase(最好是抽象的),但在“现实世界”中,这将是糟糕的代码,因为 Java 不支持多重继承。

于 2013-03-18T05:46:50.693 回答