安卓 Java总是按值传递,所以为什么我在使用数组时会得到引用。获取(索引)?
我在应用程序中处理这个bug时发现了一些非常奇怪的东西:
selectedService = dataResponse.getServices().get(position);
selectedService.setPrice(3000);
dataResponse.getServices().get(position).getPrice(); // Returns 3000 which should be 0
get方法不应该将对象复制到selectedService
中吗?如果没有,如何复制
# 1 楼答案
不,不应该
Java总是按值传递,但该值本身就是一个引用。所以,如果你调用一个方法来改变那个特定对象的数据,它会反映到从那个特定对象检索数据的所有方法中
解决这个问题的一个可能办法是使immutable types。有些类已经实现了这一点,例如,}
java.time
包中的所有类都是不可变的。这些类的所有“setter”都返回实例的新副本,并设置了指定的值。例如^{下面是传递值和传递引用之间差异的一个小示例
看看这个代码
这里发生了什么?我们将名为“布鲁特斯”的狗传递给
change
方法。在这种方法中,我们用一只名叫“杰克”的新狗来代替布鲁特斯。如果我们打印myLittleDog
的名字,他的名字是什么?会是“杰克”吗答案是否定的。对狗的引用的值被复制,并在
change
方法中以aDog
的名称提供。myLittleDog
和aDog
都是指记忆中的同一个实际的狗对象。但是现在change
方法用new
对象重新分配aDog
。此时,变量myLittleDog
和aDog
都指向不同的对象。一旦change
方法退出,变量aDog
就不可访问,并且Jack
被垃圾收集myLittleDog
仍然被称为“布鲁特斯”相反,如果Java是通过引用传递的,情况就不是这样了。那么
aDog
的重新分配也意味着myLittleDog
的重新分配另见:What's the difference between passing by reference vs. passing by value?
但是为什么我的
selectedService
仍然在变异呢虽然引用的值在传递给方法时会被复制,但这不意味着对象不能更改(也就是说,不能被修改)。假设我给你一份我的房子钥匙。你去我家把沙发搬到厨房去。如果我进了我的房子,我会看到沙发被挪动了。参考值会被复制,但每个访问参考对象(房屋)的人都会看到对其的修改
# 2 楼答案
selectedService
这里有一个引用变量,它指向您分配给它的任何对象。当将dataResponse.getServices().get(position)
赋值给selectedService
时,看起来好像是在给它赋值,然而,实际上赋值的是对原始对象的引用如https://www.geeksforgeeks.org/clone-method-in-java-2/所述
创建对象副本的步骤
使用
clone()
方法创建对象的副本,如中所示