Java传递值,优势还是劣势?

Java传递值,优势还是劣势?,java,Java,Java是按值传递的。如果我需要一个通行证怎么办。例如,在下面的代码中,我需要一个传递引用机制 public class BinaryTree { public TreeNode root; public BinaryTree(){ root = null; } public TreeNode insert(TreeNode temp,int x){ if(temp == null){ temp = ne

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;
    }
 }
公共类二进制树{
树根;
公共二叉树(){
root=null;
}
公共树节点插入(树节点温度,int x){
if(temp==null){
temp=新的树节点();
温度键=x;
temp.left=temp.right=null;
返回温度;
}
如果(温度键>x)
左侧温度=插入(左侧温度,x);
否则,如果(温度键

当使用
root
调用
insert
时,我需要将
root
作为引用传递,以便更改其值。但这在Java中不会发生,因为它是按值传递的。在C/C++中,上述功能很容易实现。你不认为这是Java的一个缺点吗?如何在Java中解决这些问题?

在Java中,如果您有一个引用类型,那么引用是按值传递的


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

Java是所有内容的传递值。无论您是使用基本体还是使用引用类型


“值”或引用类型是引用本身,因此当使用引用类型时,引用本身被传递。

根目录可以通过获取返回值来更改

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;
}
专用树节点插入(树节点温度,int x){
if(temp==null){
temp=新的树节点();
温度键=x;
temp.left=temp.right=null;
}
如果(温度键>x)
左侧温度=插入(左侧温度,x);
否则,如果(温度键
你不认为这是Java的一个缺点吗

不,因为:

  • 很少有情况下你真的需要它
  • 有一些变通办法(见下文)
  • 在Java中实现按引用传递是困难的。它使代码生成和垃圾收集变得更加复杂
  • (好的……这些都是相反的论点。但我们这里讨论的是语言设计问题,任何关于语言设计的理性讨论都必须权衡支持特定功能的利弊。这包括实现成本和性能问题。)

    如何用Java解决这些问题

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

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


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

    • “引用调用”机制仅在树为空的情况下使用。改变这一点并不困难,因此不需要这样做

    • 事实上,您对引用调用的使用,以及整个
      insert
      方法,都是一个漏洞百出的抽象。没有什么可以阻止您使用与当前BinaryTree实例无关的
      节点
      对象调用方法。您依赖调用方来维护树的(隐含的)不变量

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

    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;
        }
     }
    
    公共类二进制树{
    私有静态类TreeNode{…}
    树根;
    公共二叉树(){
    root=null;
    }
    公共空白插入(int x){
    根=插入(根,x);
    }
    专用TreeNode插入(TreeNode节点,int x){
    if(node==null){
    返回新的TreeNode(x);
    }
    如果(node.key>x)
    node.left=插入(node.left,x);
    else if(node.key

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

    Java根本无法通过引用传递。我不确定我是否完全理解你的问题,你能不能在上面的例子中使用
    this.root
    ?如果你的意思是
    insert(null,n)
    创建一个新树,请设置
    root
    。返回空对我来说似乎很奇怪。@ BaluSc:我的意思是如果我使用上面的代码……发生的事情是插入到树中的时候会成功,但是因为只有一个根副本被传递到插入,根永远不会被更新,并且总是保持空的。即使你在C++中这样做,我也会叫你出来。这里的逻辑是,如果你没有一个该死的根,创建一个无根的ctor。如果要指定root,请在重载中接受一个。凌乱的if语句是通过重载解决的。另外,如果root为null,则在insert上设置root。这比你想做的更有意义,而且是Java强迫你做一些更有意义的事情(特别是对其他人来说)的案例之一。@nikhil:对不起,我不知道你在说什么。我只是从你的问题中剔除了一些蹩脚的英语,这样它就有更多的生存机会,然后就进一步忽略了它。也许你把我和别人搞混了。我从来没有就这个问题发表过答案或评论(现在我有,但不是在你的评论回复之前)。改变对象意味着改变对象的状态,例如
    temp.key=x在您的示例中。好的。现在您将如何更改root的内容?我的意思是只传递一个root的副本,如何在这里更新root?@nikhil通过设置
    root
    ?但我不认为你应该传入一个节点