在 Java 中传递对象并尝试以多种方式更改它们
Passing object in Java and try to change them in many ways
我知道一点 Java 是如何按值传递的,以及如何将对象传递给方法可以更改对象的字段(例如 Car class 中的 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";
}
}
每次 JVM 执行 new
运算符时,都会创建一个新的 Object/Instance。您正在 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)
中 - 您会 [明确地] 创建新对象。
已编辑:
Java 对于基元和对象来说是按值传递的,它是原始引用的副本。
更具体地说,它是同一个引用的副本,这意味着它是指向同一个对象的同一个引用的不同指针,所以如果你改变你的方法中的对象,原始对象也会改变也。但是如果你再次分配它(在你的情况下使用 new 运算符),你将把你的方法内部的指针更新为一个新的引用,但原始指针保持原样。
Whosebug 上的另一个关于 most upvoted question 关于 Java :)
按值或引用传递可能来自于C++语言中使用的理解和约定。
参数类型按值传递。
但是当传递一个对象时,它不会传递整个对象,而是传递内存中指向该对象的地址副本(也称为引用)。
通过引用传递参数意味着可以在方法内部更改该参数,并且该更改在该方法外部可见。
Java in "passed by value" 因为 changing/reassigning 传递的参数在方法外部不可见。
如果是:
void change1(Car c)
{
c.price=0;
c.name="Changed";
}
对 price 和 name 的赋值在该方法之外是可见的,因为该方法更改了传递实例的成员字段而不是实例本身。
change2
和 change3
方法不会反映在它们之外,因为重新分配传递的 c
参数。
重新分配传递的对象时,传递的对象参数后面的地址不再指向与最初传递的对象相同的对象。
类似地,不可能反映传递的原语的更改或重新分配或:
void change4(String name) {
name = "whoopsie";
}
//and later calling it with:
c1.change4(c1.name);
更改对象的内部状态与更改对象本身不同。
我知道一点 Java 是如何按值传递的,以及如何将对象传递给方法可以更改对象的字段(例如 Car class 中的 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";
}
}
每次 JVM 执行 new
运算符时,都会创建一个新的 Object/Instance。您正在 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)
中 - 您会 [明确地] 创建新对象。
已编辑: Java 对于基元和对象来说是按值传递的,它是原始引用的副本。
更具体地说,它是同一个引用的副本,这意味着它是指向同一个对象的同一个引用的不同指针,所以如果你改变你的方法中的对象,原始对象也会改变也。但是如果你再次分配它(在你的情况下使用 new 运算符),你将把你的方法内部的指针更新为一个新的引用,但原始指针保持原样。
Whosebug 上的另一个关于 most upvoted question 关于 Java :)
按值或引用传递可能来自于C++语言中使用的理解和约定。
参数类型按值传递。
但是当传递一个对象时,它不会传递整个对象,而是传递内存中指向该对象的地址副本(也称为引用)。
通过引用传递参数意味着可以在方法内部更改该参数,并且该更改在该方法外部可见。
Java in "passed by value" 因为 changing/reassigning 传递的参数在方法外部不可见。
如果是:
void change1(Car c)
{
c.price=0;
c.name="Changed";
}
对 price 和 name 的赋值在该方法之外是可见的,因为该方法更改了传递实例的成员字段而不是实例本身。
change2
和 change3
方法不会反映在它们之外,因为重新分配传递的 c
参数。
重新分配传递的对象时,传递的对象参数后面的地址不再指向与最初传递的对象相同的对象。
类似地,不可能反映传递的原语的更改或重新分配或:
void change4(String name) {
name = "whoopsie";
}
//and later calling it with:
c1.change4(c1.name);
更改对象的内部状态与更改对象本身不同。