开发者

Java class confusion

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜