因此,我正在阅读这篇文章,并没有回复。2.在该示例中,调用该方法后,地址42处的Dog值是否更改为Max?
Dog myDog; Dog myDog = new Dog("Rover"); foo(myDog); public void foo(Dog someDog) { someDog.setName("Max"); // AAA someDog = new Dog("Fifi"); // BBB someDog.setName("Rowlf"); // CCC }
Java通过值传递- 始终 为基元和对象传递值。
就对象而言,传递的是对存在于堆中的对象的引用。当传入引用时,方法不能更改该引用所指向的内容。
如果该引用指向具有可变数据的对象,则该方法可以更改其状态。
摘自Ken Arnold和James Gosling撰写的“ Java编程语言第二版”(ISBN 0-201-31006-6)(可能来自第40页-现在暂时没有书):
有人会错误地说Java对象是“按引用传递”。术语“按引用传递”正确地表示,当将参数传递给函数时,调用的函数将获得对原始值的引用,而不是其值的副本。如果函数修改了其参数,则调用代码中的值将被更改,因为参数和参数使用内存中的同一插槽。[…] Java中只有一种ParameterPassing模式(按值传递),这有助于使事情变得简单。
因此,让我们看一下您的示例(进行一些改进):
public class Dog { private String name; public static void main(String [] args) { Dog myDog = new Dog("Rover"); System.out.println("before foo: " + myDog); foo(myDog); System.out.println("after foo: " + myDog); } public static void foo(Dog someDog) { someDog.setName("Max"); // AAA someDog = new Dog("Fifi"); // BBB someDog.setName("Rowlf"); // CCC } public Dog(String n) { this.name = n; } public String getName() { return this.name; } public void setName(String n) { this.name = n; } public String toString() { return this.name; } }
这是输出:
before foo: Rover after foo: Max Tool completed successfully
您无法更改传递到的引用所foo指向的内容,因此将其设置为BBB行处名称为“ Fifi”的引用,然后在CCC行处更改该对象的名称,则无济于事。该实例在foo退出时有资格进行垃圾回收。
foo
指向“流动站”的传入引用具有可变的数据成员:其名称。在AAA行更改其值将反映在传入的引用中。因此输出不同。