Existe algum motivo de desempenho para declarar parâmetros de método finais em Java?


117

Existe algum motivo de desempenho para declarar parâmetros de método finais em Java?

Como em:

public void foo(int bar) { ... }

Versus:

public void foo(final int bar) { ... }

Supondo que barseja apenas lido e nunca modificado em foo().


Não consigo pensar em uma razão pela qual o compilador se importaria se você declarasse um parâmetro de método final ou não. Mas a verdadeira resposta a esta pergunta é - escreva duas funções, uma com parâmetros finais e outra com parâmetros regulares. Execute-os um milhão de vezes cada e veja se há alguma diferença perceptível no tempo de execução. Se você está preocupado com o desempenho, é muito importante fazer algum trabalho de criação de perfil em seu código e descobrir exatamente o que está deixando você lento. É quase certo que não é o que você esperaria que fosse :)
Mike Blandford

1
Eu sugiro que você nunca escreva benchmarks micro. Você não sabe qual otimização o JIT pode fazer e quando, e provavelmente terá uma ideia errada de como ele se comporta apenas fazendo um "caso de teste simples"
Edmondo1984

bem pode ser, mas ninguém aqui escreveu ou sugeriu um microbenchmark ...
Kip

1
A resposta de @Mike Blandford sugere o uso de um micro-benchmark, não é?
Ben Page

Escrever micro benchmarks em Java é algo muito complicado
Edmondo1984,

Respostas:


97

A palavra-chave final não aparece no arquivo de classe para variáveis ​​e parâmetros locais, portanto, não pode afetar o desempenho do tempo de execução. Seu uso é apenas para esclarecer a intenção do codificador de que a variável não seja alterada (o que muitos consideram uma razão duvidosa para seu uso) e lidar com classes internas anônimas.

Há muitos argumentos sobre se o modificador final no próprio método tem algum ganho de desempenho, uma vez que os métodos serão sequenciados pelo compilador de otimização no tempo de execução de qualquer maneira, independentemente do modificador. Nesse caso, ele também deve ser usado apenas para restringir a substituição do método.


5
você pensaria que variáveis ​​/ parâmetros finais poderiam ser otimizados como variáveis ​​de loop embora ... mas um bom compilador / tempo de execução deve ser capaz de descobrir isso sem o final de qualquer maneira ...
John Gardner

9
Eu vi o compilador da Sun emitir bytecode marginalmente mais curto quando a única diferença entre os dois métodos era a "finalidade" das variáveis ​​locais. Micro-otimizações são reais e os compiladores realmente as fazem. O que realmente importa, é claro, é o que o JIT faz com o bytecode, e as referências locais perdem sua "finalidade" quando compiladas para o bytecode. Acho que é por isso que há tanta especulação sobre as variáveis ​​locais finais: é bastante não determinístico quais são os resultados. No entanto, usar locais finais pode afetar o bytecode - se vale a pena.
Christopher Schultz

Por não ser determinístico, também não há como depender da otimização. Claro, muito pode ter mudado nas implementações de VM desde a resposta original em 2008 ;-)
Robin

15

O único benefício de um parâmetro final é que ele pode ser usado em classes anônimas aninhadas. Se um parâmetro nunca for alterado, o compilador já detectará isso como parte de sua operação normal, mesmo sem o modificador final. É muito raro que os bugs sejam causados ​​por um parâmetro atribuído inesperadamente - se seus métodos são grandes o suficiente para precisar desse nível de engenharia, torne-os menores - os métodos que você chama não podem alterar seus parâmetros.


8
"É muito raro que os bugs sejam causados ​​por um parâmetro atribuído inesperadamente". É mais comum do que você pensa ...
RAY

2
@RAY você pode estar certo, na verdade eu não tenho nenhum dado (além da minha própria experiência) para fazer backup dessa afirmação.
Dobes Vandermeer

@DobesVandermeer para ser mais preciso, isso não é realmente um "benefício para um parâmetro final ". O que você está descrevendo é simplesmente uma sintaxe necessária para que quaisquer variáveis ​​locais (das quais estou incluindo parâmetros) se tornem visíveis ao escopo local da classe anônima aninhada.
swooby

0

Compiladores que operam após o carregamento da classe, como compiladores JIT, podem tirar proveito dos métodos finais. Conseqüentemente, os métodos declarados finais podem ter algum benefício de desempenho.

http://www.javaperformancetuning.com/tips/final.shtml

Ah e outro bom recurso

http://mindprod.com/jgloss/final.html


10
A questão era sobre os parâmetros serem declarados finais, o que não tem impacto no desempenho.
Robin

No JIT'S (Hotspot) moderno, o final não tem nenhuma influência (mensurável) no desempenho, seja aplicado aos parâmetros ou à classe
kohlerm

2
Os dois artigos que você vincula sugerem que final é mais uma marca semântica para os desenvolvedores e que os compiladores JIT podem usar final (mas, como outros apontaram, eles realmente não precisam dessa informação). Portanto, final é bastante semântico, o que está em paralelo com a capacidade dos compiladores C / ++ modernos de inferir a constância de variáveis ​​e métodos, mesmo se eles não estiverem marcados explicitamente como const.
ron

0

Apenas mais um ponto acima disso, usando variáveis ​​locais não finais declaradas dentro do método - a instância da classe interna pode sobreviver ao frame da pilha, então a variável local pode desaparecer enquanto o objeto interno ainda está vivo


-2

Presumo que o compilador poderia remover todas as variáveis ​​finais estáticas privadas que têm um tipo primitivo, como int, e embuti-las diretamente no código, assim como com uma macro C ++.

No entanto, não tenho ideia se isso é feito na prática, mas poderia ser feito para economizar memória.


A questão não é sobre variáveis ​​finais estatísticas privadas.
Marquês de Lorne
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.