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

相关文章:

php - 如何[专业/正确地] 将 php 代码插入到 javascript 和/或 html 中?

C# 线程参数在线程执行期间发生变化 - 为什么?

c++ - 通过引用问题传递 const 对象

java.lang.reflect.InitationTargetException

javascript - ExtJS 3 使用注册组件的方法

java - 递归程序执行期间出现 Truffle 语言运行时错误

java - 是否可以在同一方法中使用 (string, int) 来获得 return (string) 和 return (int) ?

C 中函数结构错误的类型冲突

java - eclipse 无法运行 kotlin (JDK 10)

java - 如何在设备关机和开机后让闹钟响起到设定的时间事件?