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/55928965/

相关文章:

c# - 使用 C# 中的参数化查询发送 SQL 中 IN 运算符的参数

java - Hibernate 5.2 native 查询与 void 函数 Postgresql

algorithm - Iterative recurrent... 迭代法

c++ - 我可以使一个成员函数只能通过另一个类成员函数访问吗?

c++ - C++ 编译器实际上是如何传递引用参数的?

java - 无法检索jsp页面中参数化方法返回的值

Java - 计算字符串中符号的数量

java - 通过 .nextLine 从文件中读取

java - 如何使用 j8583 库将 ISO8583 消息长度添加到 ISO8583 消息中

.net - VB.Net 片段 - 获取函数或子名称