【问题标题】:Passing object in Java and try to change them in many ways [duplicate]在Java中传递对象并尝试以多种方式更改它们[重复]
【发布时间】:2020-02-08 09:03:00
【问题描述】:

我对 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


【解决方案1】:

每次 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) 中 - 您会[明确] 创建新对象。

【讨论】:

  • 感谢您回答我的问题!但是如果我写“c2 = c1.change3(c1);”怎么会改变c2在 main 中并更改 chnage3() 函数以返回 c 而不是 void,
  • 一般来说,支持对您有帮助的答案并接受您认为解决了您的问题/问题的答案总是一个很好的 SO 标准。不客气。
  • 因为如果在函数中从 new 接收对象后局部变量 ( c ) 将消失,则为 true
  • 您正在 change2() 方法中创建一个新对象。注意..所以你以前做的任何事情都会失去意义,因为你在那里分配了全新的对象。
  • 你在哪里写c2=c1.change(c1)
【解决方案2】:

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

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

【讨论】:

  • 错了。 Java 总是按值传递。
  • 第二段中指定的是“引用的值”
  • @EduardoPérez,但第一句话(大多数人会读到的)具有误导性。
  • “所以如果你改变方法中的对象,原来的对象也会改变”,这也不是……唯一的例外是“集合”是指向对象引用的指针,例如 ListArrays 等。
  • 对不起,伙计,但你的答案非常模棱两可,会让学习者陷入更多的困惑。首先它说它有pass by reference。 .then 它说that is a different reference to the same object - 这也是错误的。构成引用的地址值将被复制,这再次证明了Java总是按值传递。
【解决方案3】:

另一个关于可能most upvoted question 在 StackOverflow 上的 Java :)

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

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

如果是:

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

price 和 name 的分配在该方法之外是可见的,因为该方法更改了传递实例的成员字段,而不是实例本身。

change2change3 方法不会反映在它们之外,因为重新分配了传递的 c 参数。
重新分配传递的对象时,传递的对象参数后面的地址不再指向与最初传递的对象相同的对象。
同样,无法反映传递的原语的更改或重新分配,或者:

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

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

【讨论】:

  • 我怀疑@Oscar 的困惑与pass by 策略无关。而是一种新的对象创建范例:)
猜你喜欢
  • 2020-08-22
  • 2016-08-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-05
  • 1970-01-01
相关资源
最近更新 更多