我知道dart就像Java一样按值传递,但我不明白为什么在下面的示例中它的行为就像按引用传递?
class A {
int y = 10;
}
class B {
List<A> list = [];
void add(A a) {
a.y = 20;
list.add(a);
}
void runtest() {
print(list[0].y);
}
}
void main() {
A a = A();
B b = B();
b.add(a);
print(a.y);
b.runtest();
}
结果将会是
20
20
为什么当对象(a)的变量(y)在(b)内的方法(add)内改变时,它也改变了对象(a)在main()内的变量(y)?
Dart 中的某些对象是不可变的(如 String、int、double 等),因此方法无法更改这些类型对象的内部状态。因此,即使我们获得了对其中某些对象的引用的副本,我们也无法更改状态,因此我们看到这就像“按值传递”行为。
但是如果一个对象(例如
List
)能够改变其内部状态,我们就可以进行修改,例如向
List
对象添加项目。由于我们从不创建新对象,因此我们将在方法之外看到这种变化,因为我们对对象本身进行了更改,而没有对引用进行任何更改。这给出了您在示例中看到的“按引用传递”行为。
但这并没有改变变量本身是一个引用的事实,当作为参数传递给方法时,它总是“按值传递”。一个小例子展示了当我们谈论方法参数时“按值传递”的含义,可以在这里看到:class A {
int value;
A(this.value);
}
void main() {
final a = A(1);
print(a.value); // 1
myMethod(a);
print(a.value); // 1
}
void myMethod(A a) {
a = A(2);
}
如示例所示,
a
中的
myMethod
变量可以更改为指向另一个对象,但由于该变量是按值传递的,因此更改不会在
main
中发生。好吧,让我们先设置一件事,dart 是按值传递的。总是。
string
或
int
这样的基本类型,它的含义很明显,这意味着正在传递基本数据类型的实际值,但对于像对象这样的非基本类型(包括列表、映射和用户实例)定义的类),传递的
值是
对对象的引用。 因此,在您的情况下,当您调用
b.add(a);
时,您正在按值传递 a 的引用。它仍然是
按值传递,但是被传递的是引用,而不是对象本身。 因此,对 a 的引用所做的任何更改都会得到反映。