Dichiarare una variabile final vuol dire rendere impossibile la reinizializzazione dopo che la variabile è stata inizializzata con un valore esplicito.

Per i tipi primitivi questo vuol dire che, una volta assegnato loro un valore iniziale, non può essere più assegnato alcun valore. Ad esempio:

public class Main
{
	public static void main(String[] args)
	{
		final int i = 10;
		i = 11;
	}
}

Produce un errore di compilazione:

Main.java:6: cannot assign a value to final variable i

Per quanto riguarda invece le variabili reference, la parola chiave final indica che la variabile, dopo essere inizializzata, non può essere riassegnata ad un oggetto diverso.
Lo stato dell’oggetto però potrà ancora essere modificato:

public class Main
{
	public static class T { int i = 0; }

	public static void main(String[] args)
	{
		final T t = new T();
		t.i = 10;
		t.i++;
		T u = new T();
		t = u;
	}
}

In questo esempio, l’oggetto a cui si riferisce la variabile t può essere modificato, ma quando si tenta di cambiare l’oggetto a cui si riferisce t, si ottiene un errore di compilazione:

Main.java:11: cannot assign a value to final variable t