java - Java 是 "pass-by-reference"还是 "pass-by-value"?

标签 java methods parameter-passing pass-by-reference pass-by-value

我一直认为Java使用按引用传递。但是,我读到a blog post它声称 Java 使用按值传递。我认为我不明白作者所做的区分。

解释是什么?

最佳答案

术语“按值传递”和“按引用传递”有特殊之处,precisely defined计算机科学中的含义。这些含义与许多人第一次听到这些术语时的直觉不同。这次讨论中的大部分困惑似乎都来自这个事实。

术语“按值传递”和“按引用传递”谈论的是变量。按值传递意味着变量的被传递给函数/方法。引用传递意味着对该变量的引用被传递给函数。后者为函数提供了更改变量内容的方法。

根据这些定义,Java 始终是按值传递。不幸的是,当我们处理保存对象的变量时,我们实际上是在处理称为引用的对象句柄,它们也是按值传递的。这种术语和语义很容易让许多初学者感到困惑。

事情是这样的:

public static void main(String[] args) {
    Dog aDog = new Dog("Max");
    Dog oldDog = aDog;

    // we pass the object to foo
    foo(aDog);
    // aDog variable is still pointing to the "Max" dog when foo(...) returns
    aDog.getName().equals("Max"); // true
    aDog.getName().equals("Fifi"); // false
    aDog == oldDog; // true
}

public static void foo(Dog d) {
    d.getName().equals("Max"); // true
    // change d inside of foo() to point to a new Dog instance "Fifi"
    d = new Dog("Fifi");
    d.getName().equals("Fifi"); // true
}

在上面的示例中,aDog.getName() 仍将返回 "Max"main 中的值 aDog 在函数 foo 中不会随着 Dog "Fifi" 发生变化,因为对象引用是按值传递的。如果通过引用传递,则 main 中的 aDog.getName() 将在调用 foo 后返回 "Fifi"

同样:

public static void main(String[] args) {
    Dog aDog = new Dog("Max");
    Dog oldDog = aDog;

    foo(aDog);
    // when foo(...) returns, the name of the dog has been changed to "Fifi"
    aDog.getName().equals("Fifi"); // true
    // but it is still the same dog:
    aDog == oldDog; // true
}

public static void foo(Dog d) {
    d.getName().equals("Max"); // true
    // this changes the name of d to be "Fifi"
    d.setName("Fifi");
}

在上面的示例中,Fifi 是调用 foo(aDog) 后狗的名称,因为对象的名称是在 foo(...) 内部设置的。 food 上执行的任何操作,出于所有实际目的,它们都是在 aDog 上执行的,但不可能可以更改变量 aDog 本身的值。

有关按引用传递和按值传递的更多信息,请参阅以下答案:https://stackoverflow.com/a/430958/6005228 。这更彻底地解释了两者背后的语义和历史,也解释了为什么 Java 和许多其他现代语言似乎在某些情况下同时执行这两种操作。

关于java - Java 是 "pass-by-reference"还是 "pass-by-value"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27153812/

相关文章:

java - 返回按钮未正确响应

java - 如何让 ScrollView 自动滚动到底部?

javascript - 在Javascript中,为什么要用函数来制作对象呢?

java - Java 方法中的 return 语句

python - 使用不存在的可选参数运行函数

windows - 对带有特殊符号的文件进行 CALL 失败

java - 这种 AES 加密是否足够安全?

java - 当没有删除任何内容时,为什么我会收到 java.util.ConcurrentModificationException?

objective-c - Cocoa:为什么在方法调用之前设置 'nil'?

C将指针传递给函数混淆