0

I am very confused.

This is my understanding of basic variable and assigning values:

int a = 9;
int b = a;
int a = 8;
System.out.println(b); // This will be 9 

Now I am trying the same thing but instead of basic types I am using an ArrayList two dimensional structure, see the following code:

public final class Matrix {
    private List<List<Double>> rawMatrix = new ArrayList<List<Double>>();
    private List<List<Double>> matrix = new ArrayList<List<Double>>();

    private void update(){
        matrix = rawMatrix;
        System.out.println("matrix: "+matrix.size()+", "+matrix.get(0).size());
        System.out.println("matrix: "+rawMatrix.size()+", "+rawMatrix.get(0).size());
        matrix.get(0).add(99.0);
        System.out.println("matrix: "+matrix.size()+", "+matrix.get(0).size());
        System.out.println("matrix: "+rawMatrix.size()+", "+rawMatrix.get(0).size());
    }
}

The problem is this output:

matrix: 4, 3
matrix: 4, 3
matrix: 4, 4
matrix: 4, 4

Now for some reason, rawMatrix has added an element the same as matrix even though I have never added anything onto the rawMatrix structure.

I assume this is some weird type of assigning variable by reference, I don't quite understand why this is the case and why it's the default in Java.

How do I overcome this? Do I have to use two for loops to make one of my matrix's equal the other, that seems very inefficient.

Joseph
  • 3,899
  • 10
  • 33
  • 52
  • 2
    This is an often asked question on stackoverflow. http://stackoverflow.com/questions/40480/is-java-pass-by-reference-or-pass-by-value will help you. – Chris K Jul 18 '14 at 10:21
  • This is how java works. If you do `anObject = anotherObject`, you are saying that `anObject` has the same reference of `anotherObject`, so they will refer to the same instance. You'll need to create a new arraylist and copy all data to it – BackSlash Jul 18 '14 at 10:22
  • @ChrisK, but that question is dealing with methods right? I know about methods, here I think it's just variables. (Perhaps I am wrong) – Joseph Jul 18 '14 at 10:23
  • @BackSlash, so I just have to use for loops to copy over the structure bit by bit? No way around this? – Joseph Jul 18 '14 at 10:23
  • @Joseph Copying is the only way to accomplish that. And please note that if you store objects into the arraylist, you'll need to also copy them, because otherwise object references will be shared by the two arraylists – BackSlash Jul 18 '14 at 10:25
  • 1
    @joseph, the premise is similar. Have you ever used a debugger before? Stepping through this code may give you some insight as to how it is really working. Specifically matrix, and rawMatrix are pointing at exactly the same instance. – Chris K Jul 18 '14 at 10:25
  • @ChrisK, I see that there is a difference between basic variables and objects, I never really saw that difference before. Thanks. This makes a lot more sense, I have used pointers in C++ but never really understood the same concept in Java before. – Joseph Jul 18 '14 at 10:25
  • 2
    This is very close to being a duplicate of http://stackoverflow.com/q/19504839/1081110 - you might want to read my answer there. – Dawood ibn Kareem Jul 18 '14 at 10:34

5 Answers5

2

Since ArrayLists are objects the assignment simply copies the pointer to the object. With primitive types you're actually copying values.

So that means your assingment matrix = rawMatrix; makes matrix point to the same memory location as rawMatrix, when that memory is updated the changes will also be reflected to where matrix points.

1

This line:

    matrix = rawMatrix;

makes matrix reference rawMatrix. After that, you only have a reference to one ArrayList<List<Double>> object, and both variables are set to this reference. (I suspect the other ArrayList will be inaccessible and get gc-ed, if you're not using it somewhere else, too)

blgt
  • 8,135
  • 1
  • 25
  • 28
1

first statement in update method is matrix = rawMatrix; Because of it your both reference varible matrix and rawMatrix refer to the same oblect of List>.

Because of this, Although you are adding an element using either of this variable, both result in same answer because both refer to the same object.

Dax Joshi
  • 143
  • 11
0

Because matrix is rawMatrix

You created two objects

private List<List<Double>> rawMatrix = new ArrayList<List<Double>>();
private List<List<Double>> matrix = new ArrayList<List<Double>>();

then you changed matrix(new object) that you have created to be assigned by rawMatrix so that the object matrix has been changed by rawMatrix and resulting that result.

matrix = rawMatrix;
Ungapps
  • 98
  • 3
  • 14
0

an int is a primitive data type. This means that when you assign to it you assign an actual value to it.

Objects are assigned by reference. This means the matrix = rawMatrix line will set the object that matrix is referring to to be the same as the object that rawMatrix refers to.

If you want a duplicate object you must use appropriate clone or copy methods or create a new object and populate it yourself. Keep in mind (when appropriate) you may want to keep a 'deep' duplicating the objects in the array itself. With a nested array like this you probably want to duplicate the 'inner' Lists.

Andrew G
  • 2,596
  • 2
  • 19
  • 26