A Palavra Final

Nos últimos tempos tenho visto muito código a utilizar final nas variáveis e parâmetros. Quando programo não tenho o habito de utilizar e julgo que isso é generalizado – dai que [1] faça a pergunta When was the last time you used final in your code?.

De [1]:
The final modifier can be applied to four Java constructs:
   1. variables: a final variable can be set once and only once.
   2. fields: a final field

can also be set only once, by the constructor of the class which defines it.
   3. methods: a final method cannot be overridden nor hidden.
   4. classes: a final class cannot be extended.

Notice how using final is an entirely negative act. The final keyword works by subtracting, limiting default language mechanisms: the ability to override a method, to set a variable or a field. The motivations behind using final fall into three broad categories: correctness, robustness, and finally performance.

A principal razão que me leva a utilizar final em todos os parâmetros do método e na declaração de variaveis locais é que me traz muito mais garantia e segurança que estou a utilizar-los como desejo.Tal como [2] concluí:
Consistently using final with local variables (when appropriate) can be useful as well. It brings attention to the non-final local variables, which usually have more logic associated with them (for example, result variables, accumulators, loop variables).

Tudo muito interessante mas reparem na diferença:

  • se a variável/parâmetro for uma primitiva a utilização do final garante que só poderemos atribuir-lhe valor apenas uma vez.
  • se a variável/parâmetro for um objecto a utilização de final garante que só poderemos atribuir-lhe uma instância de objecto, mas o seu estado poderá ser alterado livremente.

O seguinte código é errado:

public void someMethod( final int a ) {
	a = 2;
}

Tal como este:

public void someMethod( final Bean1 a ) {
	a = new Bean1();
}

Mas este já não

public void someMethod( final Bean a ) {
	a.setSomeInt(2);
}

De [1]:
Note that final parameters are not considered part of the method signature, and are ignored by the compiler when resolving method calls. Parameters can be declared final (or not) with no influence on how the method is overriden.

Portanto podemos ter

public interface Interface1 {
	void someMethod(int a);
	
	void someMethod(Bean a);
}

public class Class1 implements Interface1 {
	public void someMethod( final int a ) {
	}
	
	public void someMethod( final Bean a ) {
	}
}

Leituras: