我对这个变得疯狂。
我想要做的是从ArrayList获取一个对象,并在修改它之后将其添加到其他3个对象中。
问题在于,当我修改其他对象时,我从ArrayList获取的对象也被修改了......无法找出原因,这是正常的吗?
以下代码:
final Product tmpRef = productsRef.get(i);
Product tmp = tmpRef;
tmp.setPos(products1.size());
Log.d("test2","tmpRef:"+tmpRef.getPos()+";tmp:"+tmp.getPos());
Product tmp2 = tmpRef;
tmp2.setPos(products2.size());
Log.d("test2","tmpRef:"+tmpRef.getPos()+";tmp:"+tmp.getPos()+";tmp2:"+tmp2.getPos());
Product tmp3 = tmpRef;
tmp3.setPos(products3.size());
Log.d("test2","tmpRef:"+tmpRef.getPos()+";tmp:"+tmp.getPos()+";tmp2:"+tmp2.getPos()+";tmp3:"+tmp3.getPos());
tmp.setPos(products1.size());
“pos”只是一个简单的int,带有getter / setter。
LogCat输出:
03-21 09:56:14.926: D/test2(6200): tmpRef:9;tmp:9
03-21 09:56:14.926: D/test2(6200): tmpRef:7;tmp:7;tmp2:7
03-21 09:56:14.926: D/test2(6200): tmpRef:0;tmp:0;tmp2:0;tmp3:0
通过@FD_,@ glackbelt和@Guidobaldo da Montefelt的解释,我结束了创建一个简单的新Porduct的构造函数,以便能够复制对象,而不仅仅是引用。谢谢你们。
答案 0 :(得分:4)
基本上,您只需在ArrayList
中存储引用,因此使用Product tmp = tmpRef;
之类的内容无关紧要。 tmp
仍然指向同一个对象,因此更改将应用于两者。
在这种情况下,final
只是意味着指针一旦设置就无法更改。
只需搜索深拷贝java以寻找可能的解决方案。
答案 1 :(得分:3)
final Product tmpRef
表示对象的tmpRef引用不能更改。这意味着你无法做到
tmpRef = null;
或
tmpRef = anotherProdocut;
之后
final Product tmpRef = productsRef.get(i);
,
但如果其成员不是最终成员,则对象的内容可能会发生变化。
答案 2 :(得分:3)
除了@blackbelt所说的,你之间的混淆 "最终"和"不可变的"概念。如果你不想要"对象 值"要改变,那么你必须让它变得不可变(java不会 为此提供任何内置机制)。最终只会阻止你 从重新分配引用到另一个对象。
编辑:
1. final - if a "reference" is made final, then you cannot reassign it to point to something else. if a primitive is made final, then it's value cannot change.
eg:
final int i=5;
i=10; // error
final List<String> l = new ArrayList<String>();
l.add("one"); // works
l =new ArrayList<String>() // fails
2. Immutable - you cannot change the values of attributes of the object.
if list l were immutable, then
List<String> l = new ArrayList<String>();
l.add("one"); // fails, depending on your definition/implementation of immutablility
l =new ArrayList<String>() // l is not final, so it works fine
答案 3 :(得分:3)
在做这样的事情之前,你应该真正尝试理解引用和对象之间的区别,更深层次的是,复制引用与复制对象之间的区别。
Product是存储在名为Heap的内存区域中的对象。 “tmpRef”是包含指向该对象的地址的引用。
此代码:
Product tmp = tmpRef;
不会复制任何“Product”对象,但它只是将tmpReference分配给名为tmp的新引用变量。因此,您将有2个引用指向的1个对象。传递参考(32位系统中的4个字节)非常便宜。这就是为什么你可以将方法中的对象作为参数传递。它被称为“通过引用复制”。
final
关键字表示引用是不可变的,而不是Product
对象。
可能你有困惑,因为这些逻辑不适用于原始对象,其中引用副本不存在,但原语总是按值复制,而不是通过引用复制。
因此,如果您不想更改原始对象,则需要在堆中创建新的Product
个对象。
希望这有帮助。