10

Java真的支持引用传递吗?

如果没有,为什么我们要使用 == 运算符来查找具有相同引用的两个对象?

4

4 回答 4

15

Java 使用按值传递,而不是按引用传递...

但是,对于非原始类型,值是引用的值。

所以 == 比较对象的引用值。

于 2009-02-26T10:14:54.070 回答
4

区别在于“通过**引用”和“通过**引用”。您有时还会看到“call-by-...”和“pass-by-...”可以互换使用。为简单起见,我将坚持使用“pass-by-...”。

  1. 在学术的、老式的、与 FORTRAN 相关的、comp-sci 术语中,按引用传递意味着被调用的代码可以访问(引用)调用者传递的变量。赋值给被调用代码中的形参实际上是对调用者的变量进行赋值。区别在于(除其他外)传递值,它为被调用代码提供调用者已知的数据(无论是什么)的副本。

  2. 在当代与 Java 相关的 OO 世界中,对对象的“引用”意味着能够访问对象本身。这与“有一个指针”不同,以强调(除其他外)一个人不对引用进行“指针算术”。(实际上,这种意义上的“引用”不一定是实际的类似指针的内存地址。)

Java 通过值传递参数(在第一种意义上),但对于对象参数,值是一个引用(在第二种意义上)。这是一些依赖于差异的代码。

// called
public void munge(List<String> a0, List<String> a1) {
    List<String> foo = new List<String>(); foo.add("everybody");
    a0.set(0, "Goodbye");
    a1 = foo;
}

// caller
...
List<String> l0 = new List<String>(); l0.add("Hello");
List<String> l1 = new List<String>(); l1.add("world");
munge(l0, l1);
...

从 调用返回后munge,调用者的第一个列表l0将包含"Goodbye". 对该列表的引用被传递给munge,它在该被引用对象上调用了一个变异方法。(换句话说,a0收到的值的副本l0,它是对已修改的字符串列表的引用。)

但是,在从munge调用者的第二个列表返回时,l1仍然包含,"world"因为没有在传递的对象引用上调用任何方法( 的值l1按值传递munge)。相反,参数变量a1被设置为一个新值(本地对象引用也保存在 中foo)。

如果Java 使用了传递引用,那么在返回时,l1将包含"everybody",因为a1会引用变量 l1而不是简单地初始化为其值的副本。因此,对的分配a1也将是对的分配l1

另一个问题中讨论了同样的问题,用 ASCII-art 来说明这种情况。

于 2009-02-27T13:20:13.443 回答
3

Java使用按引用传递,而是按值传递。原始值参数被复制到堆栈中,以及指向对象的指针。

==运算符应该用于比较原始值和比较对象引用。

于 2009-02-26T10:16:50.150 回答
3

简短的回答是否定的。在Java 中只有值传递,当您使用对象(例如Object obj = new Object();)时,您正在使用对象引用。哪个按值传递。

详见:Java中的参数传递

于 2009-02-27T12:05:50.643 回答