Tuesday, January 28, 2014

Using the Java Keyword: final

So, you have been coding for some time and you happen across the occurrence of the Java keyword final. What does it mean? How does it apply to what I am doing? I thought I would give some examples of the use of the word in order to better aid in clearing up the use of this keyword.

The 'final' Class

Declaring a class final makes it so no other code can subclass it. This prevents a stable, reliable class from being changed in a way so as to break code dependent on it. This can be seen in many classes in the Java standard library such as java.lang.String and java.lang.System.

Example 1:
package com.blogspot.howdoidothatinjava;

public final class UnextendableClass {
    
}

If you were to try compiling the following:
package com.blogspot.howdoidothatinjava;

public class ExtendedClass extends UnextendableClass {
    
}

... you would get the following compiler error:
ExtendedClass.java:3: error: cannot inherit from final UnextendableClass
public class ExtendedClass extends UnextendableClass {
                                   ^

The 'final' Method

A method that is marked final cannot be overridden by any of its subclasses. Typically a method is marked final when it should no longer be changed because it behaves exactly as it is desired and no further change could improve it or if changing it would cause critical functionality to break. At times, constructors call methods and these should generally be final because a subclass could cause unexpected behavior if it were to override that method.

Example 2:
package com.blogspot.howdoidothatinjava;

public class FinalMethodClass {
    
    public void nonFinalMethod(){
        // does something can be redefined
    }
    
    public final void finalMethod(){
        // does something that shouldn't be changed
    }
}

If you tried compiling the following subclass:
package com.blogspot.howdoidothatinjava;

public class FinalMethodClassSubclass extends FinalMethodClass {
    
    public void nonFinalMethod(){
        // does something differently from super class implementation
    }
    
    public void finalMethod(){
        // this causes compiler error
    }
}

You would recieve the following error at compile time:
FinalMethodClassSubclass.java:9: error: finalMethod() in FinalMethodClassSubclass cannot override finalMethod() in Final
MethodClass
    public void finalMethod(){
                ^

The 'final' Variable

final variable is a variable that can only be initialized one time, either at declaration or in the class constructor. Any attempt to initialize the variable outside the constructor or any attempt to reassign a final variable will result in a compile error. A final variable which is declared only first and then initialized in the constructor is called a blank final.

Typically, constants in a Java program are declared static final. This is because the constant only needs to be declared once so it should be "static" and it is final because it cannot be changed. Common practice is to give constants names which are all uppercase and words are separated with underscore characters. (i.e. SECONDS_IN_MINUTE, HOURS_IN_DAY, PI, etc.)

Any mutable object declared final can be modified by any class or method referencing it.  It cannot be reassigned.  The declaration of a mutable object only makes the variable name of the object final.

Example 3:
package com.blogspot.howdoidothatinjava;

import java.util.ArrayList;
import java.util.List;

public class FinalVariableClass {
    
    private final static int SECONDS_IN_MINUTE = 60;
    private final static int MINUTES_IN_HOUR = 60;
    private final static int SECONDS_IN_HOUR;
    
    { SECONDS_IN_HOUR = SECONDS_IN_MINUTE * MINUTES_IN_HOUR; }
    
    private final List<String> finalThings = new ArrayList<String>();
    private final int int1, int2;
    private int total;
    
    public FinalVariableClass(){
        int1 = 17;
        int2 = 42;
        total = getTotal();
    }
    
    public int getTotal(){
        return int1 + int2;
    }
    
    public void setInt1(int in){
        int1 = in;
    }
    
    public void setupFinalThings(){
        String[] strings = new String[]{"ball", "cat", "tree"};
        for(String s : strings){
            finalThings.add(s);
        }
    }
}

There are several issues which will prevent the code from compiling. First, the static final SECONDS_IN_HOUR is not initialized. The attempt to initialize it in a static block failed because you cannot initialize a final variable outside of  a constructor and final static fields must be declared in the same manner as SECONDS_IN_MINUTE or MINUTES_IN_HOUR.

FinalVariableClass.java:12: error: cannot assign a value to final variable SECONDS_IN_HOUR
    { SECONDS_IN_HOUR = SECONDS_IN_MINUTE * MINUTES_IN_HOUR; }
      ^

Additionally, there is an issue with the method setInt1(int in). This method is trying to reassign the value of the variable 'in' to 'int1' which is final. The compiler promptly tells us so.

FinalVariableClass.java:29: error: cannot assign a value to final variable int1
        int1 = in;
        ^

I would like to also direct your attention to the setupFinalThings() method. This is an example of a method altering a mutable object which was declared final.  As you can see, we can add new items to the List (or we could have removed them) even though the variable finalThings is final. We can do this outside any constructor because the variable was initialized with a mutable object when it was declared. We could never reassign a new list to the variable but we can modify the list whenever and wherever we like without fear of compile-time errors.

It should be pointed out here that the method getTotal() called in the constructor would have been better declared as a final method as described previously to avoid unexpected results.

"Final"-ly

That about covers most things you would need to know about the Java final keyword. It certainly can be very useful and at times troublesome if you don't pay attention to what you are doing. In the end though, you should be sure to exercise the right to make use of this keyword for its intended purpose.

No comments :

Post a Comment

All comments are moderated. NO ADS. NO SPAM.