Java通过价值,优势还是劣势?

时间:2011-11-13 00:59:08

标签: java

Java是按值传递的。如果我需要参考通行证怎么办?例如,在以下代码中,我需要通过引用机制传递。

public class BinaryTree {
    public TreeNode root;

    public BinaryTree(){
        root = null;
    }

    public TreeNode insert(TreeNode temp,int x){
        if(temp == null){
            temp = new TreeNode();
            temp.key = x;
            temp.left = temp.right = null;
            return temp;
        }
        if(temp.key > x)
            temp.left = insert(temp.left,x);
        else if(temp.key < x)
            temp.right = insert(temp.right,x);
        return null;
    }
 }

使用insert调用root时,我需要将root作为参考传递,以便更改其值。但这不会发生在Java中,因为它是通过值传递的。在C / C ++中,可以轻松实现上述目标。难道你不认为这是Java的缺点吗?如何在Java中解决这些问题?

4 个答案:

答案 0 :(得分:8)

在Java中,如果您有引用类型,则按值传递引用

在方法内部,您可以改变传递的对象,调用者将看到这些更改。

答案 1 :(得分:3)

获取返回值可以更改

root

public void insert(int x) {
    root = insert(root, x);
}

我稍微更改了方法insert(...)

private TreeNode insert(TreeNode temp,int x){
    if(temp == null){
        temp = new TreeNode();
        temp.key = x;
        temp.left = temp.right = null;
    }
    if(temp.key > x)
        temp.left = insert(temp.left,x);
    else if(temp.key < x)
        temp.right = insert(temp.right,x);
    return temp;
}

答案 2 :(得分:3)

  

您认为这不是Java的缺点吗?

没有。这是因为:

  1. 很少有真正需要它的情况。
  2. 有解决方法(见下文)。
  3. 在Java中实现按引用传递将很困难。它使代码生成和垃圾收集变得更加复杂。
  4. (好吧......所以这些都是反驳论点。但我们在这里讨论语言设计问题,任何对语言设计的理性讨论都必须权衡支持特定功能的利弊。包括实施成本和性能问题。)

      

    如何在Java中解决这些问题?

    一般方法是重构代码,以便在被调用方法中需要更新的变量替换为对可变对象或数组的引用。这个可能需要调用者做更多的工作,但这通常是可以接受的。

    或者(在您的示例中)重构代码,以便不需要通过引用进行调用。


    在您的示例中,有两个观察结果:

    • “call-by-reference”机制仅用于树为空的情况。改变这一点并不困难,因此没有必要。

    • 事实上,您使用call-by-reference,实际上是整个insert方法,是一个漏洞的抽象。没有什么可以阻止您使用与当前BinaryTree实例无关的node对象调用该方法。您依靠调用者来维护树的(隐含)不变量。

    以下版本解决了这两个问题:

    public class BinaryTree {
        private static class TreeNode { ... }
    
        public TreeNode root;
    
        public BinaryTree(){
            root = null;
        }
    
        public void insert(int x) {
            root = insert(root, x);
        }
    
        private TreeNode insert (TreeNode node, int x) {
            if (node == null) {
                return new TreeNode(x);
            }
            if (node.key > x)
                node.left = insert(node.left, x);
            else if (node.key < x)
                node.right = insert(node.right, x);
            return node;
        }
     }
    

    (我不太喜欢在插入后我们在每个级别重新分配左/右指针的方式,但它确实使插入逻辑变得简单。)

答案 3 :(得分:1)

Java为所有东西传递价值。无论您是使用基元还是使用引用类型。

“value”或引用类型是引用本身,因此在使用引用类型时,将传递引用本身。