Interromper a reatribuição de uma variável
Embora essas respostas sejam intelectualmente interessantes, não li a resposta curta e simples:
Use a palavra-chave final quando desejar que o compilador impeça a atribuição de uma variável a um objeto diferente.
Seja a variável estática, variável membro, variável local ou variável argumento / parâmetro, o efeito é totalmente o mesmo.
Exemplo
Vamos ver o efeito em ação.
Considere este método simples, onde as duas variáveis ( arg e x ) podem ser atribuídas novamente a objetos diferentes.
// Example use of this method:
// this.doSomething( "tiger" );
void doSomething( String arg ) {
String x = arg; // Both variables now point to the same String object.
x = "elephant"; // This variable now points to a different String object.
arg = "giraffe"; // Ditto. Now neither variable points to the original passed String.
}
Marque a variável local como final . Isso resulta em um erro do compilador.
void doSomething( String arg ) {
final String x = arg; // Mark variable as 'final'.
x = "elephant"; // Compiler error: The final local variable x cannot be assigned.
arg = "giraffe";
}
Em vez disso, vamos marcar a variável de parâmetro como final . Isso também resulta em um erro do compilador.
void doSomething( final String arg ) { // Mark argument as 'final'.
String x = arg;
x = "elephant";
arg = "giraffe"; // Compiler error: The passed argument variable arg cannot be re-assigned to another object.
}
Moral da história:
Se você deseja garantir que uma variável sempre aponte para o mesmo objeto, marque a variável final .
Nunca reatribuir argumentos
Como boa prática de programação (em qualquer idioma), você nunca deve atribuir novamente uma variável de parâmetro / argumento a um objeto que não seja o objeto passado pelo método de chamada. Nos exemplos acima, nunca se deve escrever a linhaarg =
. Como os humanos cometem erros e os programadores são humanos, vamos pedir ao compilador para nos ajudar. Marque cada variável de parâmetro / argumento como 'final' para que o compilador possa encontrar e sinalizar essas redesignações.
Em retrospecto
Como observado em outras respostas ... Dado o objetivo de design original do Java de ajudar os programadores a evitar erros estúpidos, como ler além do final de uma matriz, o Java deveria ter sido projetado para impor automaticamente todas as variáveis de parâmetro / argumento como 'final'. Em outras palavras, argumentos não devem ser variáveis . Mas a retrospectiva é uma visão 20/20, e os designers de Java estavam com as mãos cheias na época.
Então, sempre adicione final
a todos os argumentos?
Devemos adicionar final
a cada parâmetro de método declarado?
- Em teoria, sim.
- Na prática, não.
➥ Adicione final
apenas quando o código do método for longo ou complicado, onde o argumento pode ser confundido com uma variável local ou membro e possivelmente redesignado.
Se você adotar a prática de nunca reatribuir um argumento, estará inclinado a adicionar um final
a cada um. Mas isso é tedioso e torna a declaração um pouco mais difícil de ler.
Para um código simples e curto, onde o argumento é obviamente um argumento, e não uma variável local nem uma variável membro, não me importo em adicionar o final
. Se o código for bastante óbvio, sem nenhuma chance de eu ou qualquer outro programador fazer manutenção ou refatorar acidentalmente confundir a variável de argumento como algo que não seja um argumento, não se preocupe. No meu próprio trabalho, adiciono final
apenas códigos mais longos ou mais envolvidos, nos quais um argumento pode ser confundido com uma variável local ou membro.
Outro caso adicionado para a integridade
public class MyClass {
private int x;
//getters and setters
}
void doSomething( final MyClass arg ) { // Mark argument as 'final'.
arg = new MyClass(); // Compiler error: The passed argument variable arg cannot be re-assigned to another object.
arg.setX(20); // allowed
// We can re-assign properties of argument which is marked as final
}