Final variable manipulation in Java

It means that if your final variable is a reference type (i.e. not a primitive like int), then it's only the reference that cannot be changed. It cannot be made to refer to a different object, but the fields of the object it refers to can still be changed, if the class allows it. For example:

final StringBuffer s = new StringBuffer();

The content of the StringBuffer can still be changed arbitrarily:

s.append("something");

But you cannot say:

s = null;

or

s = anotherBuffer;

On the other hand:

final String s = "";

Strings are immutable - there simply isn't any method that would enable you to change a String (unless you use Reflection - and go to hell).


If you have a final reference to a Java object you can still manipulate it but cannot change its reference. For instance this code is perfectly legal:

import javax.swing.JLabel;

class Test1 {
    private final static JLabel l = new JLabel("Old text");
    public static void main(String[] args) {
        System.err.println(l.getText());
        l.setText("New Text");
        System.err.println(l.getText());
    }
}

But you can't say:

l = new JLabel("Newest Text");

After the first assignment to l. Note that you can do this though:

import javax.swing.JLabel;

class Test1 {
    public static void main(String[] args) {
        final JLabel l;
        String s = getArbitaryString(); // Assume this method returns a string
        l = new JLabel(s);
        System.err.println(l.getText());
    }
}

This can be done because when l is declared it is not assigned to anything not even null. So you are allowed to assign something to it one time only.

Same thing goes for primitives. You can assign a value to it like this:

class Test1 {
    public static void main(String[] args) {
        final int i;
        i = 2;
    }
}

But now you cannot manipulate it further since the only thing you can do to primitive types is to assign values to them.