What is the significance of final instance variables?

Ankit picture Ankit · Oct 31, 2012 · Viewed 7.3k times · Source

I am having some confusion between static final class variable and final instance variable.

Here is the sample code:-

class Foof{
final int size=3;
final int whuffie;

    Foof()
    {
        whuffie=42; 
    }

    public static void main(String [] args){
        Foof obj1 = new Foof();
        Foof obj2 = new Foof();

        obj1.size=53;    //compile time error
        System.out.println(obj1.size);
        obj2.whuffie=45; //compile time error
        System.out.println(obj2.whuffie);
    }
}

Error:-

ankit@stream:/home/Data/JAVA/practice/src/test.com/test-20121031_static_demystified$ javac Foof.java 
Foof.java:14: error: cannot assign a value to final variable size
obj1.size=53;    //compile time error
    ^
Foof.java:16: error: cannot assign a value to final variable whuffie
obj2.whuffie=45;
    ^
2 errors

So my question is, what is the point of having final instance variables if they can't have a different values per different instance. I mean if they have same value for each instance then why don't we declare them as class variable(static final class variable) as this would serve the same purpose and the we don't need to create objects in order to access them.


EDIT -1:-

class Foof{
    final int size=3;
    final int whuffie;

    Foof()
    {
        whuffie=42;
        size = 23;  //compile-time error.
    }

    public static void main(String [] args){
        Foof obj1 = new Foof();
        Foof obj2 = new Foof();

        //obj1.size=53;    
        System.out.println(obj1.size);
        //obj2.whuffie=45; 
        System.out.println(obj2.whuffie);
    }
}

Error:-

Foof.java:8: cannot assign a value to final variable size
size = 23;
^
1 error

According to the error, i can make out that first size is assigned a value =3 during object creation.

Answer

Jon Skeet picture Jon Skeet · Oct 31, 2012

So my question is, what is the point of having final instance variables if they can't have a different values per different instance.

They can, but those values can't be changed after creation. You can only assign values to final instance fields within instance variable initializers and constructors, and you must assign values to all instance fields that way.

Note that in your code here:

Foof()
{
    whuffie=42;  //compile time error
}

... the comment is incorrect. That assignment should be perfectly valid.

Final fields are useful for implementing immutability - which helps make it easy to reason about an object. For example, String is immutable, so if you validate a string and then keep a copy of the reference, you know that validation will still be correct later on.

Compare that with java.util.Date, where if you really want to have any faith in validation being useful, you need to create a defensive copy of the Date value and not provide the reference to any other code, in case it changes the underlying instant being represented.