¿Hay alguna razón de rendimiento para declarar los parámetros del método finales en Java?

117

¿Hay alguna razón de rendimiento para declarar los parámetros del método finales en Java?

Como en:

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

Versus:

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

Suponiendo que barsolo se lee y nunca se modifica en foo().

Dormir
fuente
No puedo pensar en una razón por la que al compilador le importaría si declaras un parámetro de método final o no. Pero la respuesta real a esta pregunta es: escriba dos funciones, una con parámetros finales y otra con parámetros regulares. Ejecútelos un millón de veces cada uno y vea si hay alguna diferencia notable en el tiempo de ejecución. Si le preocupa el rendimiento, es muy importante que realice un trabajo de creación de perfiles en su código y descubra exactamente qué lo está frenando. Es casi seguro que no es lo que esperarías que fuera :)
Mike Blandford
1
Le sugiero que nunca escriba micro benchmarks. No sabe qué optimización puede hacer el JIT y cuándo, y probablemente tendrá una idea equivocada de cómo se comporta simplemente haciendo un "caso de prueba simple"
Edmondo1984
bueno, puede ser, pero nadie aquí ha escrito o sugerido un microbenchmark ...
Kip
1
La respuesta de @Mike Blandford sugiere usar un micro-benchmark, ¿no es así?
Ben Page
Escribir micro benchmarks en Java es algo muy, muy complicado
Edmondo 1984

Respuestas:

97

La palabra clave final no aparece en el archivo de clase para variables y parámetros locales, por lo que no puede afectar el rendimiento en tiempo de ejecución. Su único uso es aclarar la intención de los codificadores de que la variable no se cambie (lo que muchos consideran una razón dudosa para su uso) y tratar con clases internas anónimas.

Hay muchos argumentos sobre si el modificador final en el método en sí tiene alguna ganancia de rendimiento, ya que el compilador optimizador integrará los métodos en tiempo de ejecución de todos modos, independientemente del modificador. En este caso, también debe usarse solo para restringir la invalidación del método.

Robin
fuente
5
Sin embargo, pensaría que las variables / parámetros finales podrían optimizarse como variables de ciclo ... pero un buen compilador / tiempo de ejecución debería poder resolver eso sin final de todos modos ...
John Gardner
9
He visto que el compilador de Sun emite un código de bytes ligeramente más corto cuando la única diferencia entre los dos métodos ha sido la "finalidad" de las variables locales. Las microoptimizaciones son algo real y los compiladores las hacen. Lo que realmente importa, por supuesto, es lo que hace el JIT con el bytecode, y las referencias locales pierden su "finalidad" cuando se compilan en bytecode. Creo que esta es la razón por la que hay tanta especulación sobre las variables locales finales: los resultados no son determinantes. Sin embargo, el uso de locales finales puede afectar el código de bytes, por lo que vale.
Christopher Schultz
Como no es determinista, tampoco hay forma de depender de la optimización. Por supuesto, muchas cosas pueden haber cambiado en las implementaciones de VM desde la respuesta original en 2008 ;-)
Robin
15

El único beneficio de un parámetro final es que se puede usar en clases anónimas anidadas. Si un parámetro nunca se cambia, el compilador ya lo detectará como parte de su operación normal incluso sin el modificador final. Es bastante raro que los errores sean causados ​​por la asignación inesperada de un parámetro; si sus métodos son lo suficientemente grandes como para necesitar este nivel de ingeniería, hágalos más pequeños; los métodos que llama no pueden cambiar sus parámetros.

Dobes Vandermeer
fuente
8
"Es bastante raro que los errores sean causados ​​por la asignación inesperada de un parámetro". Es más común de lo que piensas ...
RAY
2
@RAY, puede que tengas razón, de hecho, no tengo ningún dato (más allá de mi propia experiencia) para respaldar esa afirmación.
Dobes Vandermeer
@DobesVandermeer para ser más precisos, eso no es realmente un "beneficio para un parámetro final ". Lo que está describiendo es simplemente la sintaxis necesaria para que las variables locales (de las cuales incluyo parámetros) se hagan visibles en el ámbito local de la clase anónima anidada.
swooby
0

Los compiladores que operan después de la carga de clases, como los compiladores JIT, pueden aprovechar los métodos finales. En consecuencia, los métodos declarados definitivos podrían tener algún beneficio en el rendimiento.

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

Oh y otro buen recurso

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

Branchgabriel
fuente
10
La pregunta se refería a la declaración final de los parámetros, lo que no tiene ningún impacto en el rendimiento.
Robin
En el moderno JIT's (Hotspot) final no tiene ninguna influencia (medible) en el rendimiento en absoluto, ya sea que se aplique a los parámetros o la clase
Kohlerm
2
Los dos artículos que vincula ambos sugieren que final es más bien una marca semántica para los desarrolladores, y que los compiladores JIT pueden usar final (pero como otros señalaron, realmente no necesitan esa información). Por lo tanto, final es bastante semántico, lo que va en paralelo con la capacidad de los compiladores modernos de C / ++ para inferir la constidad de las variables y métodos, incluso si no están marcados explícitamente como const.
ron
0

Solo un punto más que anterior al uso de variables locales no finales declaradas dentro del método: la instancia de la clase interna puede sobrevivir al marco de la pila, por lo que la variable local puede desaparecer mientras el objeto interno aún está vivo

usuario666
fuente
-2

Supongo que el compilador podría eliminar todas las variables finales estáticas privadas que tienen un tipo primitivo, como int, e incorporarlas directamente en el código como con una macro de C ++.

Sin embargo, no tengo ni idea de si esto se hace en la práctica, pero podría hacerse para ahorrar algo de memoria.

user1402866
fuente
La pregunta no se trata de variables finales estadísticas privadas.
Marqués de Lorne