I am quite new to programming in Java, but I have some experience in c/c++, I am noticing some unwanted behaviour in some of my code, and I am just wondering how to fix it.
This is what I have:
List<State> list = new ArrayList<State>();
State cur = new State();
cur.x = 1;
cur.y = 1;
list.add(cur);
cur.x = 2;
cur.y = 3;
list.add(cur);
cur.x = 3;
cur.y = 4;
list.add(cur);
for (State i : list)
System.out.println(i.x + " " + i.y);
class State
{
public int x = 0;
public int y 开发者_运维技巧= 0;
}
This gives me an output of: 3 4 3 4 3 4
Where as I want the output to be: 1 1 2 3 3 4
How do I fix this? Thanks, paintstripper
In C++ you may be expecting this List.add() function to use a copy constructor, but in Java all objects (i.e. not primitive types) are essentially references. This means that after you add cur
into the list you're adding a reference to it there. You're then modifying the values below through the cur
reference so that they are all 3 and 4.
To fix your problem you should use different State objects and add them separately.
Edit: Just to add a little bit more information here, Java always by value. When you pass an object into a function however, since that object is essentially a reference, the reference is passed by value. This means that while you could modify the original object inside a function, if you assign new things to the reference inside that function (such as swapping two objects with a temp value) it won't work.
You have one and only one object, but you add 3 different references to it to the list and change it's state (x and y) meanwhile. So at the end its x is 3 and its y is 4.
You probably want to add different objects. So:
List<State> list = new ArrayList<State>();
State cur = new State();
cur.x = 1;
cur.y = 1;
list.add(cur);
cur = new State();
cur.x = 2;
cur.y = 3;
list.add(cur);
cur = new State();
cur.x = 3;
cur.y = 4;
list.add(cur);
for (State i : list)
System.out.println(i.x + " " + i.y);
class State
{
public int x = 0;
public int y = 0;
}
The problem you have is that you're mutating a single object. It's better to avoid publicly mutable member variables. If you write the State class as below you would not have been able to make the programming error.
List<State> list = new ArrayList<State>();
State cur = new State(1,1);
list.add(cur);
cur = new State(2,3);
list.add(cur);
cur = new State(3,4);
list.add(cur);
for (State i : list)
System.out.println(i.x + " " + i.y);
class State
{
public final int x;
public final int y;
public State(int x, int y)
{
this.x = x;
this.y = y;
}
}
Note the final keyword on the x and y members, this means they cannot be assigned to after construction.
Quite simple, do a cur = new State() after each list.add() so that you get a new instance of State in 'cur'. What you are doing instead is adding the same instance to list, this is no different from C++ if you used pointer or reference of State in cur.
精彩评论