在Java中传递对象,并尝试以多种方式更改它们[重复]

问题描述 投票:2回答:3

我有点了解如何通过值传递Java,以及如何将对象传递给方法可以改变对象的字段(例如Car类中的change1())。

但是,我的问题是为什么change2()和change3()不会改变任何东西(尤其是change3())

public class question {

    public static void main(String[] args)
    {
        Car c1 = new Car(1000,"Hyundai");
        Car c2 = new Car(2000,"BMW");

        c1.change3(c1);
        c1.change3(c2);

        System.out.println(c1.name  + " "+ c1.price );
        System.out.println(c2.name +  " " + c2.price);
    }
}

class Car
{   
    int price;
    String name;

    Car(int p , String n)
    {
        this.price=p;
        this.name=n;
    }

    void change1(Car c)
    {
        c.price=0;
        c.name="Changed";
    }

    void change2(Car c)
    {
        c = new Car(999,"Honda");
    }

    void change3(Car c)
    {
        c = new Car(888,"Audi");
        c.price=80;
        c.name="xxx";
    }   
}
java parameter-passing new-operator
3个回答
2
投票

每次JVM执行new运算符时,都会创建一个新的对象/实例。您正在change3(Car c)方法中创建Car类型的新对象,并将对该对象的引用存储到局部变量c中。此后,您在c上设置的任何内容都将修改新对象,而不是您传递引用的对象。

void change3(Car c) //receives the reference to the object you pass;
{
    c = new Car(888,"Audi"); //creates a new Car object and assigns reference to that **new object** to the variable c.
    c.price=80; //here, you're changing the price/name fields of different object.
    c.name="xxx";
}  

请注意,在change1(Car c)中您不会创建新对象,但是在change2(Car c)change3(Car c)中–您会[明确地]创建新对象。


0
投票

编辑:Java是基元和对象的按值传递,它是原始引用的副本。

更具体地说,它是相同引用的副本,这意味着它是指向同一对象的相同引用的不同指针,因此,如果您在方法中更改对象,则原始对象也将更改。但是,如果您再次分配它(使用new运算符),则将方法内的指针更新为新引用,但原始指针保持原样。


0
投票

关于StackOverflow上Java的另一种可能most upvoted question

值或引用的传递可能来自C ++语言中使用的理解和约定。

参数类型按值传递。但是,当传递对象时,它不会传递整个对象,而是传递指向该对象的内存(也称为引用)的地址副本。通过引用传递参数意味着可以在方法内部更改该参数,并且该更改在该方法外部可见。Java之所以“按值传递”,是因为在方法外部看不到更改/重新分配传递的参数。

在以下情况下:

void change1(Car c)
{
    c.price=0;
    c.name="Changed";
}

价格和名称的分配在该方法外部可见,因为该方法更改了所传递实例的成员字段,而不是实例本身。

change2change3方法未在其外部反映,因为重新分配了传递的c参数。重新分配传递的对象时,传递的对象参数后面的地址不再指向与原始传递的对象相同的对象。类似地,不可能反映已传递原语的更改或重新分配,或者:

void change4(String name) {
    name = "whoopsie";
}
//and later calling it with:
c1.change4(c1.name);

更改对象的内部状态与更改对象本身不同。

© www.soinside.com 2019 - 2024. All rights reserved.