1

I am having a little trouble understanding the concept of final in Java.

I have a class that follows:

 public class MyClass 
 {
     private int[][] myArray; // intended to be changed
     private final int[][] MYARRAY_ORIGINAL; // intended to be unchangable

     public MyClass(int[][] array) 
     {
        myArray = array;
        MYARRAY_ORIGINAL = array;
     }

 }

I was under the understanding that final would make MYARRAY_ORIGINAL read only. But I have tried editing myArray, and it edits MYARRAY_ORIGINAL as well. My question is, in this context, what exactly does final do? And for extra credit, how can I copy the array passed through the constructor into MYARRAY_ORIGINAL so that I can have 2 arrays, one to edit, and one that will remain preserved?

vvvvv
  • 25,404
  • 19
  • 49
  • 81
Savid Abah
  • 15
  • 2

5 Answers5

3

Your final MYARRAY_ORIGINAL is indeed read only: you can't assign a new value to the MYARRAY_ORIGINAL reference in other side than class constructor or attribute declaration:

public void someMethod() {
    //it won't compile
    MYARRAY_ORIGINAL = new int[X][];
}

The values inside the array are not final. Those values can change anytime in the code.

public void anotherMethod() {
    MYARRAY_ORIGINAL[0][0] = 25;
    //later in the code...
    MYARRAY_ORIGINAL[0][0] = 30; //it works!
}

If you indeed need a List of final elements, in other words, a List whose elements can't be modified, you can use Collections.unmodifiableList:

List<Integer> items = Collections.unmodifiableList(Arrays.asList(0,1,2,3));

The last piece of code was taken from here: Immutable array in Java

Community
  • 1
  • 1
Luiggi Mendoza
  • 85,076
  • 16
  • 154
  • 332
  • Thank you for your response Luiggi. Another quick follow up question, what do you think I should do then to achieve two arrays, one for editing and one original? Is there a more convenient way than just looping through the 2D array and copying over all the values? – Savid Abah Oct 12 '12 at 04:21
  • @DavisSmith use an unmodifiable list as shown in the last edit or create a class wrapper for your unmodifiable array and make sure this class won't modify the array elements never. If you want the easy way, use the first option, if you can't use the `List` interface, go with the second option. – Luiggi Mendoza Oct 12 '12 at 04:23
0

In case of Objects, final makes reference can't be changed, but object state can be changed.

That is the reason why you are able to change values of final MYARRAY_ORIGINAL

kosa
  • 65,990
  • 13
  • 130
  • 167
0

MYARRAY_ORIGINAL is indeed read only variable. Your array reference can not be assigned a new value nor for their length of the arrays can be changed. A final variables initialization can be deferred till the constructors is called. If one tries to modify the reference of the final variable, compiler will throw an error message. But what is possible is, one can edit the elements of the MYARRAY_ORIGINAL and of the myArray i.e one can change the state of the object assigned to a final variable. For example

Class A { final int[] array;

 public A() {
  array = new int[10] // deferred initialization of a final variable
  array[0] = 10;
 }

 public void method() {

 array[0] = 3; // it is allowed

  array = new int[20] // not allowed and compiler will throw an error

 }
}

To understand more on final please take a look at Java Language Specification on final variable.

sakthisundar
  • 3,278
  • 3
  • 16
  • 29
0

Final does not mean 'read-only' per se, but more so "safe publication' for other threads than the one to which it is defined. Another aim of 'final' is that it ensures the latest object available in a multi-thread environment.

Secondly, if you define something as "final", for example:

 private final int[][] MYARRAY_ORIGINAL;

The reference is "final", but not the object itself. A much better way to understand it would be this:

public static final List myList = new ArrayList();

Now I can access myList from any other threads - I can modify it (add to it); but I cannot (a) Declare it again - myList = new ArrayList(); (b) Assign it another list - myList = anotherList;

The context for final I would see best, in a multiple-thread scenario.

Bonus: to answer your question, you cannot make a 'readonly' array, you will have to manage that yourself (as final, only maintains 'read-only' to reference not object)

Dane Balia
  • 5,271
  • 5
  • 32
  • 57
0

You can use the method System.arraycopy to make a copy of the array as follows -

int[][] source = {{1,2},{3,4}};
int[][] copy = new int[source.length][];
System.arraycopy(source, 0, copy, 0, source.length);

Also, you some problem with your code regarding what you are trying to do. If you look at the constructor

public MyClass(int[][] array) { //something else passes the array
    myArray = array;
    MYARRAY_ORIGINAL = array; // you are just keeping a reference to it can be modified from outside
}

If you really want nobody to modify the values in that array MYARRAY_ORIGINAL, you should make a copy of the source array that comes comes from outside.

public MyClass(int[][] array) { 
    myArray = array; //make a copy here also if you don't want to edit the argument array
    MYARRAY_ORIGINAL = new int[array.length][];
    System.arraycopy(array, 0, MYARRAY_ORIGINAL, 0, array.length); 
}

Now you shouldn't have to worry about the array's being modified from outside.

Bhesh Gurung
  • 50,430
  • 22
  • 93
  • 142