Java permite marcar variáveis (campos / locais / parâmetros) como final
, para evitar a atribuição novamente a elas. Acho isso muito útil nos campos, pois me ajuda a ver rapidamente se alguns atributos - ou uma classe inteira - devem ser imutáveis.
Por outro lado, acho isso muito menos útil com locais e parâmetros, e geralmente evito marcá-los como final
se nunca fossem redesignados (com a exceção óbvia quando eles precisam ser usados em uma classe interna) . Ultimamente, no entanto, deparei-me com códigos que usavam final sempre que possível, e acho que tecnicamente fornece mais informações.
Não confiando mais no meu estilo de programação, pergunto-me quais são as outras vantagens e desvantagens de aplicar em final
qualquer lugar, qual é o estilo mais comum do setor e por quê.
fonte
final
ou não e foi otimizado de acordo. Os compiladores modernos são inteligentes o suficiente para descobrir por si mesmos. Pelo menos em variáveis locais,final
é estritamente para o benefício de leitores humanos. Se suas rotinas não são muito complicadas, a maioria dos leitores humanos deve ser capaz de descobrir por si também.Respostas:
Eu uso
final
da mesma maneira que você. Para mim, parece supérfluo em variáveis locais e parâmetros de método, e não transmite informações extras úteis.Uma coisa importante é que se esforçam para manter meus métodos curtos e limpos , cada um fazendo uma única tarefa. Assim, minhas variáveis e parâmetros locais têm um escopo muito limitado e são usados apenas para uma única finalidade. Isso minimiza as chances de redesigná-los inadvertidamente.
Além disso, como você certamente sabe,
final
não garante que você não possa alterar o valor / estado de uma variável (não-prioritária). Só que você não pode reatribuir a referência a esse objeto depois de inicializado. Em outras palavras, ele funciona perfeitamente apenas com variáveis de tipos primitivos ou imutáveis. ConsiderarIsso significa que, em muitos casos, ainda não facilita a compreensão do que acontece dentro do código, e entender isso de fato pode causar erros sutis, difíceis de detectar.
fonte
final
, obrigado :), mas um bom argumento sobre métodos curtos e limpos - acho que, se o método for curto o suficiente para que seja óbvio que uma variável não está sendo redesignada, haverá ainda menos motivo para considerar afinal
palavra - chave.Seu estilo e pensamentos de programação Java são bons - não precisa duvidar de si mesmo.
É exatamente por isso que você deve usar a
final
palavra - chave. Você afirma que você sabe que nunca vai ser re-atribuído, mas ninguém mais sabe disso. Usarfinal
imediatamente desambigua seu código um pouquinho mais.fonte
final
indica intenção, o que torna o código mais legível. Além disso, uma vez que você precise lidar com o código do mundo real, notará que ele raramente é claro e limpo, e a adição generosa definal
s em todos os lugares que você puder ajudará a detectar bugs e a entender melhor o código legado.final
declara a intenção, que geralmente é uma coisa boa em um pedaço de código, mas tem o preço de adicionar desorganização visual. Como a maioria das coisas em programação, há uma troca aqui: está expressando o fato de que sua variável será usada apenas uma vez que vale a verbosidade adicional?Uma vantagem de usar
final
/const
sempre que possível é que reduz a carga mental para o leitor do seu código.Ele pode ter certeza de que o valor / referência nunca será alterado posteriormente. Portanto, ele não precisa prestar atenção às modificações para entender o cálculo.
Eu mudei de idéia sobre isso depois de aprender linguagens de programação funcionais. Rapaz, que alívio, se você pode confiar em uma "variável" para manter sempre seu valor inicial.
fonte
final
não garante que você não possa alterar o valor / estado de uma variável (não-prioritária). Só que você não pode reatribuir a referência a esse objeto depois de inicializado.Eu considero
final
nos parâmetros do método e variáveis locais como ruído de código. As declarações de método Java podem ser bastante longas (especialmente com genéricos) - não há mais necessidade de fazê-las.Se os testes de unidade forem escritos corretamente, a atribuição de parâmetros "prejudiciais" será detectada, portanto nunca deve ser realmente um problema. A clareza visual é mais importante do que evitar um possível bug que não é detectado porque seus testes de unidade têm cobertura insuficiente.
Ferramentas como FindBugs e CheckStyle que podem ser configuradas para interromper a compilação se a atribuição for feita a parâmetros ou variáveis locais, se você se importar profundamente com essas coisas.
Obviamente, se você precisar finalizá-las, por exemplo, porque você está usando o valor em uma classe anônima, então não há problema - essa é a solução mais simples e limpa.
Além do efeito óbvio de adicionar palavras-chave extras aos seus parâmetros e, assim, camuflar o IMHO, adicionar parâmetros finais ao método geralmente pode tornar o código no corpo do método menos legível, o que torna o código pior - para ser "bom", código deve ser o mais legível e simples possível. Para um exemplo artificial, digamos que eu tenha um método que precise trabalhar com maiúsculas e minúsculas.
Sem
final
:Simples. Limpar \ limpo. Todo mundo sabe o que está acontecendo.
Agora com 'final', opção 1:
Embora a
final
definição dos parâmetros impeça o codificador de adicionar o código mais longe de pensar que ele está trabalhando com o valor original, há um risco igual que o código mais abaixo possa usar eminput
vez delowercaseInput
, o que não deveria e o que não pode ser protegido, porque você pode ' t levá-lo fora do escopo (ou mesmo atribuirnull
parainput
se isso fosse mesmo ajudar de qualquer maneira).Com 'final', opção 2:
Agora, acabamos de criar ainda mais ruído no código e introduzimos um impacto no desempenho de ter que invocar
toLowerCase()
n vezes.Com 'final', opção 3:
Fale sobre o ruído do código. Isto é um acidente de trem. Temos um novo método, um bloco de exceção necessário, porque outro código pode invocá-lo incorretamente. Mais testes de unidade para cobrir a exceção. Tudo para evitar uma linha simples, e IMHO, preferível e inofensiva.
Há também a questão de que os métodos não devem ser tão longos que você não pode visualmente visualizá-lo facilmente e saber rapidamente que uma atribuição ao parâmetro ocorreu.
Eu acho que é uma boa prática / estilo que, se você atribuir a um parâmetro, faça isso todo o começo do método, de preferência na primeira linha ou logo após a verificação básica de entrada, substituindo -o efetivamente por todo o método, o que tem um efeito consistente dentro do método método. Os leitores sabem que qualquer tarefa é óbvia (próximo à declaração da assinatura) e em um local consistente, o que atenua bastante o problema que a adição final está tentando evitar. Na verdade, raramente atribuo a parâmetros, mas, se o faço, sempre o faço no topo de um método.
Observe também que
final
, na verdade, não o protege como pode parecer à primeira vista:final
não o protege completamente, a menos que o tipo de parâmetro seja primitivo ou imutável.fonte
final
fornece a garantia parcial de que você está lidando com a mesmaDate
instância. Algumas garantias são melhores que nada (se é que você está argumentando por classes imutáveis desde o início!). De qualquer forma, na prática, muito do que você diz deve afetar os idiomas imutáveis por padrão existentes, mas não afeta, o que significa que não é um problema.final
, com a possibilidade de torná-los não finais para casos como o descrito acima. Não vale a pena enviar a assinatura com uma palavra-chave.Deixei o eclipse colocar
final
antes de cada variável local, já que considero facilitar a leitura do programa. Não faço isso com parâmetros, já que quero manter a lista de parâmetros o mais curta possível, idealmente, ela deve caber em uma linha.fonte
var
marcar variáveis não finais. YMMV.var
! Infelizmente, não é o padrão em Java e agora é tarde demais para mudar o idioma. Portanto, eu estou disposto a colocar-se com o pequeno inconveniente de escreverfinal
:)final
palavra-chave prefixado, enquanto que apenas 10-20% seria necessário umvar
...