最终参考对象得到修改

时间:2014-03-21 09:08:26

标签: java android arraylist final

我对这个变得疯狂。

我想要做的是从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的构造函数,以便能够复制对象,而不仅仅是引用。谢谢你们。

4 个答案:

答案 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个对象。

希望这有帮助。