如何在Java中识别pass-by-value或pass-by引用?

时间:2012-09-21 09:56:31

标签: java

请原谅初学者的问题。我在互联网上遇到了这段代码片段:

public class Person {

public static void main(String [] args)
{
    StringBuffer a = new StringBuffer("A");
    StringBuffer b = new StringBuffer("B");
    operate(a,b);
    System.out.println(a+","+b);
}


static void operate(StringBuffer x, StringBuffer y)
{
    y.append(x);
    y=x;

 }
}

我发现运行输出应该是A,A,但是,正确的输出应该是A,BA,专家可以帮助我理解为什么b的值仍然是AB?为什么“y.append(x)”会影响b的值,而不是“y = x”?这就是我感到困惑的地方。

提前致谢。

4 个答案:

答案 0 :(得分:6)

简短的回答是Java参数是按值传递的,因此operate中的最终赋值没有任何影响。

详细的事件顺序如下:

  1. ab被初始化为两个StringBuffer对象。让我们把它写成

     a -> S1{"A"}
     b -> S2("B")
    
  2. 评估operator调用参数的(普通)参数表达式,给出S1 {“A”}和S2 {“B”}。

  3. 调用开始,两个引用分配给局部变量xy。现在状态如下:

     a -> S1{"A"}
     x -> |
    
     b -> S2("B")
     y -> |
    
  4. y.append(x)调用会修改S2对象:

     a -> S1{"A"}
     x -> |
    
     b -> S2("BA")
     y -> |
    
  5. 执行y = x;分配:

     a -> S1{"A"}
     x -> |
     y -> |
    
     b -> S2("BA")
    
  6. operate方法返回,导致xy超出范围。

     a -> S1{"A"}
     b -> S2("BA")
    
  7. 需要注意的关键是在步骤5中我们不能更改S2对象的内容。相反,我们只是将y更改为引用另一个对象。

答案 1 :(得分:0)

在该方法中,y=x行仅更改局部变量y,不会影响调用者范围中的b变量。

更改操作方法中的b变量,因为您无法将指针传递给java中的变量,这有点困难。你可以:

  • 返回:b = operate...
  • 更改其内容(但这将是副本)

答案 2 :(得分:0)

Java不使用按名称调用按引用调用

void replace(Anything x) {
  x = y;
}

无效,按定义,因为x new 变量,而不是调用变量的别名。对变量x的任何更改都仅限于方法范围。请注意,x.setSomething可能仍会修改x引用的内容

这实际上适用于大多数编程语言。它避免了错误,并且有方法可以明确地实现所需的结果。

Java始终按值调用。即使使用引用,它们在技术上也作为值传递(对象引用类型)。

即。变量“Integer example;”在技术上不是Integer,但它是null实例的引用(可能是Integer)。 引用被复制(按值调用),但当然它之后仍然引用同一个对象。所以你可以修改对象,但你不能改变实际的引用,因为你只有它的副本。

答案 3 :(得分:0)

让干运行方法:

  1. 参考状态是 a -> A, x -> A, b -> B, y -> B.

  2. append执行 a -> A, x -> A, b -> BA, y -> BA.

  3. y=x执行 a -> A, x -> A, b -> BA, y -> A.

  4. 现在,打印输出应该是什么? : - )

    要点是,

    Java是Pass-By-Value