Encontrei algumas referências ( por exemplo ) que sugerem usar final
o máximo possível e estou me perguntando o quanto isso é importante. Isso ocorre principalmente no contexto de parâmetros de método e variáveis locais, não de métodos ou classes finais. Para constantes, faz sentido óbvio.
Por um lado, o compilador pode fazer algumas otimizações e tornar mais clara a intenção do programador. Por outro lado, adiciona verbosidade e as otimizações podem ser triviais.
É algo que eu deveria fazer um esforço para lembrar?
Respostas:
Obcecado por:
Considere, mas use criteriosamente:
Ignore, a menos que sinta anal:
Parâmetros de método e variáveis locais - RARAMENTE faço isso em grande parte porque sou preguiçoso e acho que isso atrapalha o código. Admito plenamente que a marcação de parâmetros e variáveis locais que não vou modificar é "mais correta". Eu gostaria que fosse o padrão. Mas não é e acho o código mais difícil de entender com as finais por todo o lado. Se eu estiver no código de outra pessoa, não vou retirá-lo, mas se estiver escrevendo um novo código, não o colocarei. Uma exceção é o caso em que você precisa marcar algo final para poder acessar de dentro de uma classe interna anônima.
Edit: note que um caso de uso em que as variáveis locais finais são realmente muito úteis, como mencionado por @ adam-gent, é quando o valor é atribuído à var nos
if
/else
branches.fonte
final
por padrão. Você pode não perceber os benefícios, a menos que use um Java IDE verdadeiramente moderno (por exemplo, IDEA).final
classes / métodos. Por exemplo, se um método final declarar lançar uma exceção verificada, mas nunca a lançar, o IDEA informará isso e você poderá remover a exceção dathrows
cláusula. Às vezes, você também pode encontrar métodos inteiros que não são usados, detectáveis quando não podem ser substituídos.Não, se você estiver usando o Eclipse, porque você pode configurar uma Ação de salvamento para adicionar automaticamente esses modificadores finais para você. Então você obtém os benefícios por menos esforço.
fonte
Os benefícios em tempo de desenvolvimento de "final" são pelo menos tão significativos quanto os benefícios em tempo de execução. Ele informa aos futuros editores do código algo sobre suas intenções.
Marcar uma classe como "final" indica que você não fez um esforço durante o design ou a implementação da classe para lidar com a extensão normalmente. Se os leitores puderem alterar a classe e quiserem remover o modificador "final", poderão fazê-lo por sua conta e risco. Cabe a eles garantir que a classe lide bem com a extensão.
Marcar uma variável "final" (e atribuí-la no construtor) é útil com injeção de dependência. Indica a natureza "colaborador" da variável.
Marcar um método como "final" é útil nas classes abstratas. Delineia claramente onde estão os pontos de extensão.
fonte
Eu uso
final
o tempo todo para tornar o Java mais baseado em expressões. Veja que as condições de Java (if,else,switch
) não são baseadas em expressões que eu sempre odiei, especialmente se você está acostumado a programação funcional (por exemplo, ML, Scala ou Lisp).Portanto, você deve sempre tentar (IMHO) usar variáveis finais ao usar condições.
Deixe-me lhe dar um exemplo:
Agora, se adicionar outra
case
instrução e não definir,name
o compilador falhará. O compilador também falhará se você não interromper todos os casos (que você definiu a variável). Isso permite que você torne o Java muito semelhante àslet
expressões do Lisp e faz com que seu código não seja massivamente recuado (devido a variáveis de escopo lexicais).E como o @Recurse observou (mas aparentemente -1 me), você pode fazer o anterior sem
String name
final
obter o erro do compilador (o que eu nunca disse que não poderia), mas você poderia facilmente fazer com que o erro do compilador desaparecesse definindo o nome após a alternância declaração que joga fora a expressão semântica ou pior, para abreak
qual você não pode causar um erro (apesar do que @Recurse diz) sem usarfinal
:Por causa do nome da configuração do bug (além de esquecer para
break
qual outro bug), agora posso fazer isso acidentalmente:A variável final força uma avaliação única de qual nome deve ser. Semelhante à maneira como uma função que tem um valor de retorno sempre deve retornar um valor (ignorando exceções), o bloco de comutação de nomes terá que resolver o nome e, portanto, vinculado a esse bloco de comutação, o que facilita a refatoração de blocos de código (por exemplo, refator do Eclipe: método de extração) .
O acima em OCaml:
O
match ... with ...
avalia como uma função ie expressão. Observe como se parece com a nossa declaração de opção.Aqui está um exemplo no esquema (raquete ou frango):
fonte
else if (...)
em umif(...)
e, assim, redefiniu a variável. Eu mostrei a ele que nunca teria acontecido com uma variável final. Basicamente,final
obriga a atribuir a variável uma vez e apenas uma vez ... então: PEncontrei parâmetros e locals do método de marcação como
final
úteis para auxiliar na refatoração quando o método em questão é uma bagunça incompreensível com várias páginas. Polvilhefinal
generosamente, veja o que "não pode atribuir à variável final" erros que o compilador (ou seu IDE) lança e você pode descobrir por que a variável chamada "dados" acaba nula, apesar de vários comentários (desatualizados) jurarem que podem isso acontece.Em seguida, você pode corrigir alguns dos erros substituindo as variáveis reutilizadas por novas variáveis declaradas mais próximas do ponto de uso. Então você descobre que pode envolver partes inteiras do método em chaves de escopo e, de repente, você fica a um pressionamento de tecla IDE do "Extract Method" e seu monstro ficou mais compreensível.
Se o seu método ainda não é um destroço inatingível, acho que pode haver valor em tornar as coisas finais para desencorajar as pessoas a transformá-lo nos destroços; mas se for um método curto (consulte: não é sustentável), você corre o risco de adicionar muita verbosidade. Em particular, as assinaturas de funções Java são difíceis o suficiente para caber em 80 caracteres, sem adicionar mais seis por argumento!
fonte
final
parâmetro antes de cada parâmetro.Bem, tudo depende do seu estilo ... se você gosta de ver a final quando não modifica a variável, use-a. Se você NÃO GOSTA de vê-lo ... deixe-o de fora.
Pessoalmente, gosto da menor verbosidade possível, por isso evito usar palavras-chave extras que não são realmente necessárias.
Eu prefiro linguagens dinâmicas, então provavelmente não é nenhuma surpresa que eu goste de evitar verbosidade.
Então, eu diria que apenas escolha a direção na qual você está se inclinando e continue com ela (seja qual for o caso, tente ser consistente).
Como observação lateral, trabalhei em projetos que usam e não usam esse padrão, e não vi diferença na quantidade de bugs ou erros ... Não acho que seja um padrão que imensamente melhore sua contagem de bugs ou algo assim, mas, novamente, é estilo, e se você gosta de expressar a intenção de não modificá-lo, vá em frente e use-o.
fonte
É útil em parâmetros para evitar alterar o valor do parâmetro por acidente e introduzir um bug sutil. Eu uso para ignorar esta recomendação, mas depois de passar cerca de 4 horas. em um método horrível (com centenas de linhas de código e múltiplos fors, ifs aninhados e todo tipo de práticas ruins), eu recomendaria que você o fizesse.
É claro que em um mundo perfeito isso não aconteceria, mas ... bem ... às vezes você precisa dar suporte ao código de outras pessoas. :(
fonte
Se você estiver escrevendo um aplicativo em que alguém precisará ler o código após, digamos, 1 ano, então sim, use a variável final on que não deve ser modificada o tempo todo. Ao fazer isso, seu código será mais "auto-documentado" e você também reduzirá a chance de outros desenvolvedores fazerem coisas tolas, como usar uma constante local como uma variável temporária local.
Se você estiver escrevendo algum código descartável, não se preocupe em identificar todas as constantes e torná-las finais.
fonte
Vou usar final o máximo que puder. Isso sinalizará se você alterar o campo acidentalmente. Também defino os parâmetros do método como final. Ao fazer isso, peguei vários erros do código que assumi quando eles tentaram 'definir' um parâmetro esquecendo que o Java passa por valor.
fonte
Não está claro na questão se isso é óbvio, mas tornar o parâmetro do método final afeta apenas o corpo do método. Ele não transmitir qualquer informação interessante sobre as intenções do método para o invocador. O objeto que está sendo passado ainda pode ser alterado dentro do método (finais não são consts) e o escopo da variável está dentro do método.
Para responder sua pergunta precisa, eu não me incomodaria em tornar uma instância ou variável local (incluindo parâmetros do método) final, a menos que o código exigisse (por exemplo, a variável seja referenciada a partir de uma classe interna), ou para esclarecer alguma lógica realmente complicada.
Por exemplo, variáveis, eu as tornaria finais se forem constantes logicamente.
fonte
Há muitos usos para a variável
final
. Aqui estão apenas algunsConstantes Finais
Isso pode ser usado para outras partes dos seus códigos ou acessado por outras classes, dessa forma, se você alterar o valor, não precisará alterá-los um por um.
Variáveis finais
Nesta classe, você cria uma variável final com escopo que adiciona um prefixo ao parâmetro environmentKey. Nesse caso, a variável final é final apenas dentro do escopo de execução, que é diferente a cada execução do método. Cada vez que o método é inserido, a final é reconstruída. Assim que é construído, não pode ser alterado durante o escopo da execução do método. Isso permite que você corrija uma variável em um método pela duração do método. ver abaixo:
Constantes Finais
Isso é especialmente útil quando você tem realmente longas linhas de códigos e gera erros de compilador para que você não encontre erros de lógica / negócios quando alguém acidentalmente altera variáveis que não devem ser alteradas.
Coleções finais
Caso diferente, quando falamos de coleções, você precisa defini-las como não modificáveis.
caso contrário, se você não definir como modificável:
Classes finais e métodos finais não podem ser estendidos ou substituídos, respectivamente.
EDIT: ENDEREÇO AO PROBLEMA DA CLASSE FINAL RELATIVO AO ENCAPSULAMENTO:
Existem duas maneiras de fazer uma aula final. O primeiro é usar a palavra-chave final na declaração de classe:
A segunda maneira de finalizar uma classe é declarar todos os seus construtores como privados:
Marcá-lo como final evita o problema se descobrir que é realmente um final, para demonstrar o olhar para essa classe de teste. parece público à primeira vista.
Infelizmente, como o único construtor da classe é privado, é impossível estender essa classe. No caso da classe Teste, não há razão para que a classe seja final. A classe Test é um bom exemplo de como as classes finais implícitas podem causar problemas.
Portanto, você deve marcá-lo como final quando implicitamente tornar uma classe final, tornando seu construtor privado.
fonte
Um pouco de uma troca, como você mencionou, mas eu prefiro o uso explícito de algo sobre o uso implícito. Isso ajudará a remover alguma ambiguidade para futuros mantenedores de código - mesmo que seja apenas você.
fonte
Se você possui classes internas (anônimas) e o método precisa acessar a variável do método que contém, você precisa ter essa variável como final.
Fora isso, o que você disse está certo.
fonte
Use a
final
palavra-chave para uma variável se você estiver fazendo essa variável comoimmutable
Ao declarar a variável como final, ajuda os desenvolvedores a descartar possíveis problemas de modificação de variáveis em ambiente altamente multithread.
Com o lançamento do java 8, temos mais um conceito chamado "
effectively final variable
". Uma variável não final pode ser usada como variável final.variáveis locais referenciadas a partir de uma expressão lambda devem ser finais ou efetivamente finais
Até o Java 7, você não pode usar uma variável local não final dentro de uma classe anônima, mas no Java 8 você pode
Dê uma olhada neste artigo
fonte
Primeiro, a palavra-chave final é usada para tornar uma variável constante. Constante significa que não muda. Por exemplo:
Você declararia a variável final porque um centímetro por polegada não muda.
Se você tentar substituir um valor final, a variável será o que foi declarado primeiro. Por exemplo:
Há um erro de compilação que é algo como:
Se sua variável não puder ser declarada final ou se você não quiser declará-la final, tente o seguinte:
Isso imprimirá:
fonte