Monday, January 27, 2014

Understanding final keyword part - 2 Just a small tidbit... 'njoy java

Now, here is an interesting scenario for you, a simple mind excercise.

Java understands final lil different from constant. Say I create a final array with the following code.

public class FinalArray1 {
    private final int[] arr = new int[5];
   
    public FinalArray1(){
        for(int i=0; i<arr.length;i++){
            arr[i]= (int)(Math.random()*25);
        }
    }
    public void printArray(){
        System.out.print("[ ");
        for(int i=0;i<arr.length;i++){
             System.out.print(arr[i]+" ");
        }
        System.out.println("]");
    }
    public void setNthElement(int index,int value){
        if(index<arr.length){
            arr[index]=value;
        }
    }
}

To test whether array is final or not, here is a Tester class:

public class TestFinalArray1 {
    public static void main(String[] args) {
        FinalArray1 arrayObj = new FinalArray1();
        arrayObj.printArray();
        arrayObj.setNthElement(2, (int)(Math.random()*100));
        arrayObj.printArray();
    }
}

On execution, we can see the data of 3rd element is changed.

run:
[ 11 15 11 10 11 ]
[ 11 15 30 10 11 ]
BUILD SUCCESSFUL (total time: 1 second)

So in what sense is it constant? let us take a look at this. We add newArray(int size) method to FinalArray1 class. 

public void newArray(int size){
        arr= new int[size];
    }



we can see an error on compile : "cannot assign a value to final variable arr". arr array reference variable is final and not the array elements.


1 comment:

  1. Quite weak isn't it, and the same goes for ordinary objects ─ only the reference is protected from modification not the object referenced. So, is there any point in using final?

    Well, as said the reference is protected and can only be set by object initialization or from within the constructor. If this is not done the compiler will pick this up so there is no chance of leaving a reference declared final uninitialized and pointing to null. Also there may be generated code and garbage collection advantages from using final – only hearsay from my level of under the hood but one instance, not covered in the Wikipedia 'final' article, I have subscribed to is:

    An equals() implementation for RegisteredItem using instanceof might be:

    @Override
    public boolean equals(Object obj) {
    if (this == obj) return true; // optional same-object check
    if (obj instanceof RegisteredItem) {
    final RegisteredItem other = (RegisteredItem) obj;
    return (this.itemID == other.itemID &&
    this.categoryID.equals(other.categoryID));
    }
    return false;
    }

    By making other final we can hope that the compiler will not allocate this local on the stack and generate the assignment but will use the now typechecked reference to obj instead.

    ATB, Martin Humby

    ReplyDelete