Final Reference Variables Tutorial

When the final keyword is applied to a reference variable and the variable has been initialized, that reference variable cannot be reassigned to a different object instance. It is important to note that when final is applied to a reference variable it does not prevent the members of the object instance from changing values. A final reference variable can only be assigned to a reference of an object instance once and only once. The value does not need to be assigned when the reference variable is declared; this kind of a reference variable is called a blank final variable. A blank final instance reference variable must be assigned a value inside of a constructor or a compiler error will occur. A blank final local reference variable must be assigned a value before it is used. The optional common naming convention for final variables is to be in uppercase with an underscore (_) separating the words.



Open the command prompt (CMD - see the Getting Started ) and type in the following commands.

C:\Windows\System32>cd \
C:\>md Java
C:\>cd Java
C:\Java>
C:\Java>md FinalReference
C:\Java>cd FinalReference
C:\Java\FinalReference>Notepad FinalReference.java

Copy and Paste, or type the following code into Notepad and be sure to save the file when you are done.


class FinalReference {
    public static void main(String args[]) {
        Box myBox = new Box(5, 5, 5);        
        FinalInstanceTester fit = new FinalInstanceTester(myBox);
        fit.displayValues();
    
        System.out.println("-------Locals-------");

        final Box MISC_BOX = new Box(10, 10, 10);
        Box shoeBox = new Box(6, 15, 5);
        FinalLocalTester flt = new FinalLocalTester();
        flt.displayValues(MISC_BOX, shoeBox);
    }
}

class FinalInstanceTester {
    final Box BOX_ONE; // blank final reference instance variable
    final Box BOX_TWO = new Box(8, 8, 8);
    
    FinalInstanceTester() {
        super();
        BOX_ONE = new Box(); // must assign a value to a blank final reference instance variable in a constructor
    }
    FinalInstanceTester(Box paramBox) {
        BOX_ONE = paramBox; // must assign a value to a blank final reference instance variable in a constructor
    }
	
    void displayValues() {
        //BOX_ONE = new Box(12, 12, 12); // error, blank final must be initialized in a constructor
        BOX_ONE.displayDimensions("BOX_ONE");
        BOX_TWO.displayDimensions("BOX_TWO");
                         
        // BOX_ONE CANNOT change the reference to a different object. Final prevents that 
        //BOX_ONE = BOX_TWO; 

        // BOX_ONE MAY change the members of the object! Final does not prevent that
        BOX_ONE.length = 15;
        BOX_ONE.height = 15;
        BOX_ONE.width = 15;
        BOX_ONE.displayDimensions("BOX_ONE");
    }	
}

class FinalLocalTester {

      void displayValues(Box miscBox, final Box SHOE_BOX) {
        Box BLANK_BOX; // blank final local reference variable

        miscBox.displayDimensions("miscBox");        
        SHOE_BOX.displayDimensions("SHOE_BOX");
        
        // "Passing Variables to Methods and Constructors Tutorial" covers pass-by-value rules
        // pass-by-value rules dictate that the parameter miscBox (no final) can change its reference to an object, the parameter SHOE_BOX cannot     
        Box changeTo = new Box(41, 41, 41);
        miscBox = changeTo;
        miscBox.displayDimensions("miscBox");   

        // SHOE_BOX CANNOT change the reference to a different object. Final prevents that 
        // SHOE_BOX = changeTo; 

        // SHOE_BOX MAY change the members of the object! Final does not prevent that
        SHOE_BOX.length = 17;
        SHOE_BOX.height = 17;
        SHOE_BOX.width = 17;
        SHOE_BOX.displayDimensions("SHOE_BOX");    

        BLANK_BOX = new Box(33, 33, 33); // must initialize it before use
        BLANK_BOX.displayDimensions("BLANK_BOX");
    }

}

class Box {
    int length = 0;
    int height = 0;
    int width = 0; 
    
    Box() { 
        super(); 
    }   

    Box(int length, int height, int width) {
        this.length = length;
        this.height = height;
        this.width = width;
    }

    void displayDimensions(String refName) {
        System.out.println("The dimensions of " + refName + " (" + this + ") are: " + length + ", " + height + ", " + width);
    }
}

Now switch back to the command prompt (CMD) and type in javac FinalReference.java and press Enter.
Now type in java FinalReference and press Enter.


C:\Java\FinalReference>javac FinalReference.java
C:\Java\FinalReference>java FinalReference
The dimensions of BOX_ONE (Box@659e0bfd) are: 5, 5, 5
The dimensions of BOX_TWO (Box@2a139a55) are: 8, 8, 8
The dimensions of BOX_ONE (Box@659e0bfd) are: 15, 15, 15
-------Locals-------
The dimensions of miscBox (Box@15db9742) are: 10, 10, 10
The dimensions of SHOE_BOX (Box@6d06d69c) are: 6, 15, 5
The dimensions of miscBox (Box@15db9742) are: 41, 41, 41
The dimensions of SHOE_BOX (Box@6d06d69c) are: 17, 17, 17
The dimensions of BLANK_BOX (Box@4e25154f) are: 33, 33, 33


Final thoughts

The most important thing to learn from this tutorial is when the final keyword is applied to a reference variable and the variable has been initialized, that reference variable cannot be reassigned to a different object instance. The final keyword applied to a reference variable does not prevent the members of the object instance from changing values. I know this tutorial most likely caused some level of confusion and I was debating of splitting this tutorial into a part 1 and 2. I figured that if I did so you would be watching two tutorials anyway. If you got everything - great - if not, then feel free to watch it again.


Tutorials