【问题标题】:Java : setting object to null within a method has no effect (Reusing code)Java:在方法中将对象设置为 null 无效(重用代码)
【发布时间】:2015-05-31 16:29:03
【问题描述】:

我正在尝试编写一种从二叉搜索树中删除节点的方法。这是我删除节点的方法。

public void delete(int deletionNodeValue) {
    Node<Integer> nodeToBeDeleted = getNode(deletionNodeValue);
    if(nodeToBeDeleted == null) return; // No node with such value exists throw an error
    if(isLeafNode(nodeToBeDeleted)) {
        nodeToBeDeleted = null;
    } else if (nodeToBeDeleted.getNumChildren() == 1) {
        bypassNode(nodeToBeDeleted);
    }else {
        replace(nodeToBeDeleted, getSuccessor(nodeToBeDeleted.getValue()));
    }
}

我在一个叶子节点上检查了这个方法,虽然在调试之后我发现nodeToBeSelected=null的执行发生了,这个节点实际上并没有被删除。因为我仍然可以搜索已删除的值,并且程序仍然设法获取它。

tree.add(5);
tree.delete(5);
System.out.println(tree.getNode(5).getValue()); // Output : 5, should've been deleted

这是我的 getNode() 方法

public Node<Integer> getNode(int searchValue) {
    Node<Integer> currentNode = root;
    while(currentNode != null) {
        int currentNodeValue = currentNode.getValue();
        if(searchValue == currentNodeValue)
            return currentNode;
        else if(searchValue < currentNodeValue)
            currentNode = currentNode.getLeftChild();
        else
            currentNode = currentNode.getRightChild();
    }

    // if no node with given value is found
    return null;
}

getNode() 方法是否按值返回找到的节点?如何让它返回引用并直接操作找到的节点?

【问题讨论】:

    标签: java algorithm reference binary-search-tree


    【解决方案1】:

    您必须从树中删除节点,而不是在程序中本地删除。

    Node<Integer> nodeToBeDeleted = getNode(deletionNodeValue);
    

    为您提供树中节点的副本。

    nodeToBeDeleted = null;
    

    将此副本设置为空。与树的连接不会被删除,因为它是节点对象的一部分。要删除连接,您必须编写另一种方法来删除节点,这应该包含类似

    parent.leftNode = null; // if nodeToBeDeleted == leftNode
    parent.rightNode = null; // if nodeToBeDeleted == rightNode
    

    【讨论】:

    • @NashVali 我认为您不应该将leftNoderightNode 定义为public 字段。使用 setter 是更好的选择。
    • 是的,它们不应该公开。这段代码是虚构方法void deleteChild(Node nodeToBeDeleted) 方法的sn-p。
    • 虚构的方法仍然可以使用虚构的 setter,而不是使用虚构的公共字段。看我的回答。
    【解决方案2】:

    当你在delete 方法中说nodeToBeDeleted = null; 时,你并没有真正导致getNode 方法返回的Node 开始指向null

    Java 总是pass-by-value。这意味着您不能将传递给方法的引用指向方法内的新内存位置。同样,您不能将方法调用点返回的引用指向另一个方法内的新内存位置。 (即使位置是,嗯.. null)。

    根据上面的解释,几乎不可能使用getNode方法来获取你不想删除的Node,然后用其他方法使这个节点指向null。一个快速的解决方案是将getNode 方法中的代码也复制到delete 方法中。您应该在Node 中添加setLeftChildsetRightChild 方法(而不是像其他人建议的那样公开leftChild 和rightChild)。然后,您可以将其设置为 null,如下所示:

    nodeToBeDeleted.setLeftChild(null)

    【讨论】:

      【解决方案3】:

      当您将nodeToBeDeleted 设置为null 时,您只需设置保存对实际对象的引用的局部变量的值。实际对象不会以任何方式被删除。

      使用您在此处显示的代码,要删除节点,您应该找到其父节点并将对该节点的引用(leftChild 或 rightChild)设置为 null。这将确保对象不被其父对象引用,可能不再被任何引用可见,因此有资格进行垃圾回收。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-03-05
        • 2011-10-13
        • 2020-03-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多