小编典典

Java怀疑中通过引用传递

java

因此,我正在阅读这篇文章,并没有回复。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
}

阅读 200

收藏
2020-11-30

共1个答案

小编典典

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退出时有资格进行垃圾回收。

指向“流动站”的传入引用具有可变的数据成员:其名称。在AAA行更改其值将反映在传入的引用中。因此输出不同。

2020-11-30