1

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

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

4 回答 4

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")
    

需要注意的关键是,在第 5 步中,我们没有更改 S2 对象的内容。相反,我们只是更改y为引用另一个对象。

于 2012-09-21T09:58:22.037 回答
0

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

在操作方法中更改b变量,因为您不能在 java 中传递指向变量的指针有点困难。您可以:

  • 把它返还 :b = operate...
  • 更改其内容(但那将是一个副本)
于 2012-09-21T09:58:03.000 回答
0

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

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

根据定义,什么都不做,因为x它是一个变量,而不是调用变量的别名。对变量的任何更改x都仅限于方法范围。注意x.setSomething可能还是修改了引用的内容。x

这实际上适用于大多数编程语言。它避免了错误,并且有一些方法可以显式地达到预期的结果。

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

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

于 2012-09-21T10:00:48.473 回答
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.

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

要点是,

Java 是按值传递

.

于 2012-09-21T10:06:51.450 回答