Search code examples
javafinal

Usage of final in java


I was wondering what the difference is between

public final type attribute_name;

and

private type attribute_name;
public type getA_name() {
  return attribute_name;
}

Basically I want to make an attribute read-only, so it can't change after it has been initialized.
Do I make it public final, or do I make it private, and only make it accesible through a get method (without a set method)?


Solution

  • A final field MUST be set before the constructor exits. Once set, the reference cannot be modified (the value cannot be reassigned). Emphasis on the cannot be reassigned. This means that while the reference cannot change, the value itself can change.

    This is legal:

    final List<Integer> list = new List<Integer>();
    list.add(5); // the value of list changes, but the reference doesn't
    

    This is not:

    final List<Integer> list = new List<Integer>();
    list = new List<Integer>(); // may seem sort of redundant but the compiler won't allow it nonetheless
    

    A private variable with a only getter can be reassigned internally by the class that holds it (but it's not visible externally so it cannot be reassigned outside the class holding it). Also, outside the class the reference is inaccessible so the variable cannot be modified except by the class holding it.

    A final variable cannot be reassigned anywhere, but if it's public, another class can still access the reference and change the value of whatever object it points to.

    If you don't want the variable to be reassigned after initialization as you described, use both final and private.


    Use final for something like this:

    public class User {
    
        private final long registrationTimeMillis;
    
        public User(/* various parameters probably would be here */) {
            registrationTimeMillis = System.currentTimeMillis();
        }
    
        public long getRegistrationTimeMillis() {
            return registrationTimeMillis;
        }
    }
    

    We don't expect that a user's registration time will change, so it makes sense to not allow it to change after construction.


    Use private with no setter for something like this:

    public class VendingController() {
    
        private int drinksStocked = 0;
        private int drinksDispensed = 0;
    
        public void dispenseDrink() {
            drinksDispensed++;
        }
    
        public void stockDrinks(int numberOfDrinks) {
            drinksStocked = getDrinksRemaining() + numberOfDrinks;
            drinksDispensed = 0;
        }
    
        public int getDrinksRemaining() {
            return drinksStocked - drinksDispensed;
        }
    }
    

    We don't want the value of drinksDispensed to change except when dispenseDrink() or stockDrinks(int numberOfDrinks) is called. It still needs to be able to be reassigned by it's own class when the vending machine is refilled though, so we shouldn't make it final


    With respect to using public final, generally in Java that's only done for constants and that static keyword is also included since constants shouldn't be dependent on an instance.

    An example of when it makes sense to use public static final

    public class UnitConversions {
    
        public static final double CENTIMETERS_PER_INCH = 2.54;
    
    }
    

    It could then be used in a method as follows

    public double convertFromCentimetersToInches(double centimeters) {
        return centimeters / UnitConversions.CENTIMETERS_PER_INCH;
    }
    

    Best of luck OP and happy coding.

    More reading on final fields