Java 永远不会传递引用,对吗?...对吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/795160/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 19:35:26  来源:igfitidea点击:

Java is NEVER pass-by-reference, right?...right?

javapass-by-referencepass-by-value

提问by Troy Nichols

Possible Duplicate:
Is Java “pass-by-reference”?

可能的重复:
Java 是“传递引用”吗?

I found an unusual Java method today:

今天发现了一个不寻常的Java方法:

private void addShortenedName(ArrayList<String> voiceSetList, String vsName)
{
     if (null == vsName)
       vsName = "";
     else
       vsName = vsName.trim();
     String shortenedVoiceSetName = vsName.substring(0, Math.min(8, vsName.length()));
     //SCR10638 - Prevent export of empty rows.
     if (shortenedVoiceSetName.length() > 0)
     {
       if (!voiceSetList.contains("#" + shortenedVoiceSetName))
         voiceSetList.add("#" + shortenedVoiceSetName);
     }
}

According to everything I've read about Java's behavior for passing variables, complex objects or not, this code should do exactly nothing. So um...am I missing something here? Is there some subtlety that was lost on me, or does this code belong on thedailywtf?

根据我所读到的关于 Java 传递变量、复杂对象与否的行为的所有内容,这段代码应该什么都不做。所以嗯……我在这里遗漏了什么吗?我是否遗漏了一些微妙之处,或者这段代码是否属于 thedailywtf?

采纳答案by Michael Myers

As Rytmis said, Java passes references by value. What this means is that you can legitimately call mutating methods on the parameters of a method, but you cannot reassign them and expect the value to propagate.

正如 Rytmis 所说,Java 按值传递引用。这意味着您可以合法地对方法的参数调用变异方法,但您不能重新分配它们并期望值传播。

Example:

例子:

private void goodChangeDog(Dog dog) {
    dog.setColor(Color.BLACK); // works as expected!
}
private void badChangeDog(Dog dog) {
    dog = new StBernard(); // compiles, but has no effect outside the method
}

Edit:What this means in this case is that although voiceSetListmightchange as a result of this method (it could have a new element added to it), the changes to vsNamewill not be visible outside of the method. To prevent confusion, I often mark my method parameters final, which keeps them from being reassigned (accidentally or not) inside the method. This would keep the second example from compiling at all.

编辑:在这种情况下,这意味着尽管此方法voiceSetList可能会发生变化(它可能会添加一个新元素),但更改vsName不会在方法之外可见。为了防止混淆,我经常标记我的方法参数final,以防止它们在方法内被重新分配(无论是否意外)。这将使第二个示例根本无法编译。

回答by Rytmis

Java passes references by value, so you get a copy of the reference, but the referenced object is the same. Hence this method does modify the input list.

Java按值传递引用,因此您会获得引用的副本,但被引用的对象是相同的。因此这个方法确实修改了输入列表。

回答by Marc Gravell

Well, it can manipulate the ArrayList- which is an object... if you are passing an object reference around (even passed by value), changes to that object will be reflected to the caller. Is that the question?

好吧,它可以操纵ArrayList- 这是一个对象......如果你正在传递一个对象引用(甚至是按值传递),对该对象的更改将反映给调用者。这是问题吗?

回答by PhiLho

I think you are confused because vsName is modified. But in this context, it is just a local variable, at the exact same level as shortenedVoiceSetName.

我认为你很困惑,因为 vsName 被修改了。但在这种情况下,它只是一个局部变量,与shortenedVoiceSetName 处于完全相同的级别。

回答by the_new_mr

The references themselves are passed by value.

引用本身是按值传递的。

From Java How to Program, 4th Edition by Deitel & Deitel: (pg. 329)

从 Java 如何编程,Deitel 和 Deitel 第 4 版:(第 329 页)

Unlike other languages, Java does not allow the programmer to choose whether to pass each argument by value or by reference. Primitive data type variables are always passed by value. Objects are not passed to methods; rather, references to objects are passed to methods. The references themselves are passed by value—a copy of a reference is passed to a method. When a method receives a reference to an object, the method can manipulate the object directly.

与其他语言不同,Java 不允许程序员选择是按值还是按引用传递每个参数。原始数据类型变量始终按值传递。对象不会传递给方法;相反,对对象的引用被传递给方法。引用本身是按值传递的——引用的副本被传递给一个方法。当一个方法接收到一个对象的引用时,该方法可以直接操作该对象。

Used this book when learning Java in college. Brilliant reference.

在大学学习Java时使用了这本书。精辟的参考。

Here's a good article explaining it. http://www.javaworld.com/javaworld/javaqa/2000-05/03-qa-0526-pass.html

这是一篇解释它的好文章。 http://www.javaworld.com/javaworld/javaqa/2000-05/03-qa-0526-pass.html

回答by mark

It's not clear to me what the exact question within the code is. Java is pass-by-value, but arrays are pass-by-reference as they pass no object but only pointers! Arrays consist of pointers, not real objects. This makes them very fast, but also makes them dangerous to handle. To solve this, you need to clone them to get a copy, and even then it will only clone the first dimension of the array.

我不清楚代码中的确切问题是什么。Java 是按值传递的,但数组是按引用传递的,因为它们不传递对象而只传递指针!数组由指针组成,而不是真正的对象。这使它们非常快,但也使它们处理起来很危险。要解决这个问题,您需要克隆它们以获取副本,即使如此,它也只会克隆数组的第一维。

For more details see my answer here: In Java, what is a shallow copy?(also see my other answers)

有关更多详细信息,请参阅我的回答:在 Java 中,什么是浅拷贝?(另见我的其他回答)

By the way, there are some advantages as arrays are only pointers: you can (ab)use them as synchronized objects!

顺便说一句,数组只是指针有一些优点:您可以(ab)将它们用作同步对象!