1

在java中,所有方法都是按值传递的。但是今天我了解到构造函数是通过引用传递的。

// Attack the internals of a Period instance
Date start = new Date();
Date end = new Date();
Period p = new Period(start, end);
end.setYear(78);  // Modifies internals of p!

这有效并且能够编辑私有字段。

这个决定的原因是什么?还是我错过了什么?

4

5 回答 5

8

你错了:

在java中,所有方法都是按值传递的。

相反:在 Java 中,所有参数都是按值传递的,甚至引用也是按值传递的。

你不“传递对象”,只引用对象。这对于方法和构造函数是一样的。

所以

end.setYear(78);  // Modifies internals of p!

不会更改引用,而只会更改引用指向的对象。

于 2013-07-13T09:12:07.280 回答
3

对于其他方法,它将以相同的方式工作。实际上引用是按值传递的。

Class A{
   B b;
   void setB(B b) {
       this.b = b;
   }
};

A a;
B b;
A.setB(b);

b.change(); //changed in A

引用按值传递是什么意思?

void f(A a) {
    a.change(); // caller will see that object is changed. We change it using reference
    a = new A(); // we change the value of refernce. No changes are visible outside the function
    a.change(); //new object is changing. No changes are visible outside the function
}

基本上,您只需按值传递对象(整数)的地址。一切都是整数。您的课程包含整数。它没有改变。该地址上的对象确实如此。

于 2013-07-13T09:10:53.970 回答
1

构造函数和方法的机制相同。从文档

引用数据类型参数(如对象)也按值传递给方法。这意味着当方法返回时,传入的引用仍然引用与之前相同的对象。但是,如果对象的字段具有适当的访问级别,则可以在方法中更改它们的值

于 2013-07-13T09:12:56.160 回答
1

不,您没有更改任何私有字段。Period 中的私有字段没有被触及,它们仍然引用同一个对象。不幸的是,一个 Date 对象是可变的。因此,您可以通过 Period 对象看到突变。

如果您想避免这种情况,请复制构造函数中传递的每个对象,只有这样您才能拥有自己的 Date 对象,Period 之外的任何人都无法修改。

于 2013-07-13T09:24:32.717 回答
0

您只处理引用,而不是对象。

价值传递的经典定义。

引用变量的值是 Java 中的“地址”。当你将一个引用变量传递给一个方法时,一个新的引用变量被放置在堆栈上,并且一个被传递的引用变量的值的副本被用来初始化新的局部引用变量的值,就像任何原始类型一样。

注意:虽然您可以将引用视为内存地址,但事实并非如此。底层机制使它在逻辑上表现得好像它是一样的。

简短版本:引用是简单的变量,就像其他原始类型一样,用于将参数传递给方法。一旦通过,你可以用它们做什么显然是不同的。

于 2013-07-13T09:12:43.960 回答