tags:

views:

237

answers:

2

Ok, here is the code and then the discussion follows:

public class FlatArrayList {

    private static ArrayList<TestWrapperObject> probModel = new ArrayList<TestWrapperObject>();

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub

        int [] currentRow = new int[10];

        int counter = 0;

        while (true) {

          for (int i = 0; i < 10; i++) {
            currentRow[i] = probModel.size();
          }

          TestWrapperObject currentWO = new TestWrapperObject(currentRow);

          probModel.add(counter, currentWO);

          TestWrapperObject testWO = probModel.get(counter);
          // System.out.println(testWO);

          counter++;

          if (probModel.size() == 10) break;

       }

       // Output the whole ArrayList    
       for (TestWrapperObject wo:probModel) {
         int [] currentTestRow = wo.getCurrentRow();
       } 
    }
}

public class TestWrapperObject {

    private int [] currentRow;

    public void setCurrentRow(int [] currentRow) {
        this.currentRow = currentRow;
    }

    public int [] getCurrentRow() {
        return this.currentRow;
    }

    public TestWrapperObject(int [] currentRow) {
        this.currentRow = currentRow;
    }

}

What is the above code supposed to do? What I am trying to do is load an array as a member of some wrapper object (TestWrapperObject in our case). When I get out of the loop, the probModel ArrayList has the number of elements it is supposed to have but all have the same value of the last element (an array of size 10 with each item equal to 9). This is not the case inside the loop. If you perform the same "experiment" with a primitive int value everything works fine. Am I missing something myself regarding arrays as object members? Or did I just encounter a Java bug? I am using Java 6.

+6  A: 

You are only creating one instance of the currentRow array. Move that inside the row loop and it should behave more like you expect.

Specifically, the assignment in setCurrentRow does not create a copy of the object, but only assigns the reference. So each copy of your wrapper object will hold a reference to the same int[] array. Changing the values in that array will make the values appear to change for all other wrapper objects that hold a reference to the same instance of the array.

Greg Hewgill
+1: Java feature. Language works as advertised. You must create independent instances.
S.Lott
Thanks, it worked. However, the same ArrayList should not hold different data inside and outside the loop, right? Or is there a valid explanation for this?
atas
setCurrentRow is never called (but the constructor duplicates the mistake). The general point is that Java always copies the reference and not the object.
Tom Hawtin - tackline
@atas: you are updating the contents of currentRow each time through the loop. When you print the value inside the loop, you are printing the elements as they are at that point in time. When you print the values outside the loop, you are printing the last state of the currentRow array.
Greg Hewgill
Or, welcome to the world of pointers. And then you thought that java didn't have them :-).
Paul de Vrieze
At least with pointers it is clear when a pointer is a pointer! The thing is that an array is treated as a reference, but then it is assigned a value as it was primitive (you don't assign a new reference to it to fill its values), which was the main source of confusion.
atas
A: 

i don' t want to sound condescending, but always try to remember tip #26 from the excellent pragmatic programmer book

select isn't broken

it is very rare to find a java bug. keeping this in mind often helps me to look over my code again, turn it around, and shake out the loose bits until i finally discover where i was wrong. of course asking for help early enough is very encouraged, too :)

netzwerg
Sure, more of a rhetorical question. I didn't actually expect to find a Java bug. I just thought my testing assumption was not broken :-)
atas