Reputation: 4112
Let's say I have three Lists free
, home
and tableau
, they all contains different objects. I also have a class called History
and its constructor takes all these three lists and makes a new Object. Now, I am trying to make a List<History>
that contains all the history objects. I am adding all the <History>
objects as follows,
List<Hisotry> history = new ArrayList<>();
history.add(new History(free, home, tableau));
//make some changes in the lists (free, home, tableau),
//then add it again in the history list
history.add(new History(free, home, tableau));
//make some more changes again then add it
history.add(new History(free, home, tableau));
Although it's adding all the objects into the list, but they all referring to the same object. In other words, if I add 3 <History>
objects, it prints the same <Hisotry>
object 3 times, when they all should be different. I am not sure why it's adding or referring to the same object when each time I create a new object and add it to the list. What am I doing wrong while adding new objects?
**P.S. I hope I am making sense, if not, please feel free to let me know and I will upload my whole code.
Upvotes: 3
Views: 4326
Reputation: 338316
The Answer by Shesterov is correct.
Here is a diagram to show what you have as described in the Question. I added "Animal" objects as the elements contained in your "free"-"home"-"tableau" lists as you did not mention their contents.
That correct answer was making two points:
If you followed Shesterov’s code and duplicated each list during each History object’s construction, you would end up with 12 pink lists rather than 3: the original 3 plus 3 lists for each of the 3 History objects. So: 12 = 3 + ( 3 * 3 )
. But you still have the same 5 Animal objects. But going this route History "b", for example, could alter its "home" list to drop the reference to the bird named Bob while the original "home" list and the History "a" "home" list and the History "c" "home" list would still each have a pointer reference to the bird named Bob.
In other words, do not think of passing object references as going through a Xerox machine. Instead think of these objects as paper index cards, each connected as seen in this diagram by a string with Scotch tape attaching the string to the card. Passing an object does not xerox the card; passing an object attaches another string with tape.
One last point: Do not confuse a List/Collection object with the elements it "contains" (points to). In a warehouse, you may take an inventory of crates by listing the ID number of each crate on a clipboard. The clipboard is a "List" but is not itself the crates. The clipboard/inventory object is a collection that refers to completely separate distinct other objects, the crates.
Upvotes: 2
Reputation: 423
You are creating new History object each time, which is fine. But you said you are modified existing free, home and tableau array lists. These 3 arrays lists are still being modified using the same reference and therefore you are updating them in the other History objects as well.
Upvotes: 1
Reputation: 27525
You've already correctly figured out that the History
objects hold references to the same lists. Thus, you have 3 different History
objects, but all of the 3 instances "point" to the same lists.
You could clone the lists before modifying them for a new History
object, i.e.:
List<History> history = new ArrayList<>();
history.add(new History(free, home, tableau));
free = new ArrayList(free);
home = new ArrayList(home);
tableau = new ArrayList(tableau);
// make some changes to the lists
history.add(new History(free, home, tableau));
free = new ArrayList(free);
home = new ArrayList(home);
tableau = new ArrayList(tableau);
// make more changes to the lists
history.add(new History(free, home, tableau));
Please note that if the lists free
, home
, tableau
hold references to mutable objects, and these objects can be changed according to your program logic, then the above code won't work and you will need to clone every list item as well.
Upvotes: 2