Question

I'm turning crazy on this one.

What I want to do is to get an object from an ArrayList, and add it in 3 others after modifying it.

The problem is that the object I get from my ArrayList is modified aswell when I modify the others... Can't figure out why, is this normal?

Code below:

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" is just a simple int, with a getter/setter.

LogCat output:

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

With @FD_, @blackbelt and @Guidobaldo da Montefelt's explainations, I ended creating a simple new Porduct's constructor to be able to copy the object, and not only the reference. Thanks guys.

Was it helpful?

Solution

Essentially, you just store references in your ArrayList, so it does not matter whether you use something like Product tmp = tmpRef;. tmp still points to the same object, thus changes are applied to both.

In this case, final just means that a pointer cannot be changed once it has been set.

Just search for deep copy java for possible solutions.

OTHER TIPS

final Product tmpRef

means that the Object's reference of tmpRef can not be change. Meaning that you can not do

tmpRef = null;

or

tmpRef = anotherProdocut;

after

final Product tmpRef = productsRef.get(i);,

but the content of the object could change if its member are not final.

Adding to what @blackbelt said, you are getting confused between "final" and "immutable" concepts. If you don't want the "object's value" to change, then you have to make it immutable (java doesn't provide any built-in mechanism for this). final merely prevents you from reassigning the reference to another object.

EDIT:

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

Before doing such a thing, you should really try to understand the difference between references and objects, and more deeply, the difference between copying a reference vs copying an object.

Product is an object stored in a memory zone called Heap. "tmpRef" is a reference that contains the address that points to that object.

This code:

Product tmp = tmpRef;

does not copy any "Product" objects but it simply assign the tmpReference in a new reference variable called tmp. So, you´ll have 1 Object pointed by 2 references. Passing a reference (4 bytes in a 32bit system) is very cheap. That´s why you can pass objects in your methods as parameters. It´s what it is called "copy by reference".

The final keyword means that the reference is immutable, not the Product object.

Probably you have confusion because these logic is not applied to primitive objects, where reference copy does not exist, but primitives are always copied by value, and never by reference.

So if you want to do not change the original object, you do need to create new Product objects in the heap.

Hope this helps.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top