参考对象与值参考

Ste*_*ker 8 java pass-by-reference pass-by-value

我在这里阅读这篇评论:在Java中通过引用传递字符串?

是的,这是一种误解.这是一个巨大而广泛的误解.这导致我讨厌的一个采访问题:("Java如何传递参数").我讨厌它,因为大约一半的采访者实际上似乎想要错误的答案("基于价值的原语,通过引用的对象").正确的答案需要更长的时间,而且似乎会混淆其中一些.并且他们不会被说服:我发誓我在技术屏幕上不及格,因为CSMajor型筛选者在大学里听到了误解,并认为它是福音.FEH. - CPerkins于2009年8月13日14:34

有人可以解释一下,新程序员可以掌握,说:

"在Java中,原语通过值传递,对象通过引用传递."

和:

"在Java中,没有任何内容通过引用传递,引用按值传递."?

这些陈述在某种意义上都是真的吗? 我不想邀请咆哮游行,但这听起来像一个非常重要的概念,而我仍然不完全理解.

aio*_*obe 12

我认为错误观念在于变量不能包含一个开头的对象.如果你掌握了这一点,那么显然变量只能包含对象(或原始值)的引用.从那里开始实现引用按值传递的步骤(就像原始值一样)非常小.

您可以通过一个非常简单的测试来确定语言是否支持通过引用传递.问问自己是否可以用语言编写交换函数,即类似的东西

x == A, y == B

swap(x, y);

x == B, y == A
Run Code Online (Sandbox Code Playgroud)

作为一个Java程序员,你很快意识到,你不能在Java中实现这一点,所以你(正确地)得出Java没有结论参照具有通.

回到你的句子:

  • 在Java中,原语通过值传递,对象通过引用传递.

这是错误的.我认为你只能传递一个包含在变量中的东西,正如我上面所说的,变量不能包含一个对象,因此你无法在Java中传递一个对象.

  • 在Java中,没有任何内容通过引用传递,引用按值传递.

这是事实.


Hun*_*len 7

这样的事情在绘制时总是更容易.考虑以下两个变量,一个是基本类型,另一个是引用类型:

    int i    = 5;
    String s = "test";
Run Code Online (Sandbox Code Playgroud)

在内存中的某个地方有一个条目i,如下所示:

  i
-----
| 5 |
-----
Run Code Online (Sandbox Code Playgroud)

类似地s,内存中也有一个条目,但它引用堆上的位置,因为它s是一个引用类型变量,并且对象存储在堆上:

                            ----------- 
 s                 |------->|  "test" |
-----              |        |---------|
| --|--------------|        |         |
-----                       |         |
                            |         |
                            |---------|
Run Code Online (Sandbox Code Playgroud)

所以值s是对位于堆上的String对象的引用,所以如果s传递给方法:

printString(s);

public void printString(String arg)
{
   System.out.println(arg);
}
Run Code Online (Sandbox Code Playgroud)

实际复制到arg参数中的值是s对堆上的引用:

                            ----------- 
 s                 |------->|  "test" |<-----|
-----              |        |---------|      |
| --|--------------|        |         |      |
-----                       |         |      |
                            |         |      |
                            |---------|      |
 arg                                         |
-----                                        |
| --|----------------------------------------- 
-----
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助.


Joh*_*erg 6

好问题.请考虑以下示例

void foo(Object obj) {
  obj = new Foo(); 
}
Run Code Online (Sandbox Code Playgroud)
Object o = new Bar();
foo(o);
// is o Foo or Bar?
Run Code Online (Sandbox Code Playgroud)
  • 如果pass by-referenceo参考可能已经改变调用foo
  • 如果呼叫 pass by-reference-by-value参考o没有改变foo