Java是按引用传递吗?

10

Java真的支持按引用传递吗?

如果不支持,为什么我们有“==”运算符来查找具有相同引用的两个对象?


按引用调用和传递引用是一回事,对吧?如果不是,有人可以把问题改回原来的样子。 - Michael Myers
4个回答

15

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

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

因此,==比较对象的引用值。


但是在字节码级别上,它有引用...对吧?https://zh.wikipedia.org/wiki/Java%E5%AD%97%E8%8A%82%E7%A0%81 - Yousha Aleayoub

4
区别在于“按引用传递”和“传递引用”。有时你也会看到“调用方式”和“传递方式”互换使用。为简单起见,我将坚持使用“按……传递”。
在学术、旧式、与FORTRAN相关的计算机科学术语中,“按引用传递”意味着被调用的代码可以访问(引用)由调用者传递的变量。在被调用的代码中对形式参数进行赋值实际上是对调用者的变量进行赋值。区别在于(在其他情况下)“按值传递”,它使被调用的代码获得了调用者已知数据(无论是什么)的副本。
在当代与Java相关的面向对象世界中,“拥有对对象的引用”意味着能够访问对象本身。这与“拥有指针”不同,强调(在其他方面)不对引用进行“指针算术运算”。(实际上,在这种意义上,“引用”不一定是一个实际的类似指针的内存地址。)
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 艺术来说明该情况。

3

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

应使用==运算符比较原始值,并比较对象引用。


3

简短回答是不行的。在Java中只有值传递,当您使用对象(例如:Object obj = new Object();)时,您正在使用对象引用。这些引用被按值传递。

详情请见:Java中的参数传递


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接