Java permite marcar variables (campos / locales / parámetros) como final
, para evitar la reasignación en ellas. Me resulta muy útil con los campos, ya que me ayuda a ver rápidamente si algunos atributos, o toda una clase, están destinados a ser inmutables.
Por otro lado, me parece mucho menos útil con los parámetros locales y, y generalmente evito marcarlos como final
si nunca fueran reasignados (con la excepción obvia cuando necesitan ser utilizados en una clase interna) . Últimamente, sin embargo, me encontré con un código que usaba final siempre que podía, lo que supongo que técnicamente proporciona más información.
Ya no confío en mi estilo de programación, me pregunto cuáles son otras ventajas y desventajas de aplicar en final
cualquier lugar, cuál es el estilo más común de la industria y por qué.
fuente
final
o no, y se optimizaron en consecuencia. Los compiladores modernos son lo suficientemente inteligentes como para descubrirlo por sí mismos. Al menos en las variables locales,final
es estrictamente para el beneficio de los lectores humanos. Si sus rutinas no son demasiado complicadas, entonces la mayoría de los lectores humanos también deberían poder resolverlo por sí mismos.Respuestas:
Yo uso
final
lo mismo que tú. Para mí, parece superfluo en variables locales y parámetros de métodos, y no transmite información adicional útil.Una cosa importante es esforzarme por mantener mis métodos cortos y limpios , cada uno haciendo una sola tarea. Por lo tanto, mis variables y parámetros locales tienen un alcance muy limitado y se usan solo para un único propósito. Esto minimiza las posibilidades de reasignarlos inadvertidamente.
Además, como seguramente sabe,
final
no garantiza que no pueda cambiar el valor / estado de una variable (no primitiva). Solo que no puede reasignar la referencia a ese objeto una vez inicializado. En otras palabras, funciona a la perfección solo con variables de tipos primitivos o inmutables. ConsiderarEsto significa que en muchos casos aún no hace que sea más fácil entender lo que sucede dentro del código, y un malentendido de hecho puede causar errores sutiles que son difíciles de detectar.
fuente
final
, gracias :) pero buen punto sobre los métodos cortos y limpios: supongo que si el método es lo suficientemente corto como para que sea obvio que no se reasigna una variable, hay incluso menos motivo para considerar lafinal
palabra clave.Su estilo de programación Java y sus pensamientos están bien, no necesita dudar de sí mismo allí.
Esto es exactamente por qué debe usar la
final
palabra clave. Usted declara que USTED sabe que nunca será reasignado, pero nadie más lo sabe. Usarfinal
inmediatamente desambigua su código un poquito más.fuente
final
indica intención, lo que hace que el código sea más legible. Además, una vez que deba lidiar con el código del mundo real, notará que rara vez es prístino y claro, y agregar generosamentefinal
s en todas partes puede ayudarlo a detectar errores y comprender mejor el código heredado.final
establece la intención, que generalmente es algo bueno en un fragmento de código, pero tiene el precio de agregar desorden visual. Como la mayoría de las cosas en la programación, hay una compensación aquí: ¿está expresando el hecho de que su variable solo se usará una vez que valga la verbosidad adicional?final
. Eso puede ser la mayoría de los lugareños, pero claramente no todos . Para mí no hay "que nunca cambie". Hay 2 tipos de locales claramente separados en mi mundo. Aquellos que se supone que nunca volverán a cambiar (final) y aquellos que deben cambiar como resultado de lo que dicta la tarea en cuestión (de los cuales hay muy poco, lo que hace que las funciones sean bastante fáciles de razonar).Una ventaja de usar
final
/const
siempre que sea posible es que reduce la carga mental para el lector de su código.Puede estar seguro de que el valor / referencia nunca se modifica más adelante. Por lo tanto, no necesita prestar atención a las modificaciones para comprender el cálculo.
He cambiado de opinión al respecto después de aprender lenguajes de programación puramente funcionales. Chico, qué alivio, si puedes confiar en una "variable" para mantener siempre su valor inicial.
fuente
final
no garantiza que no pueda cambiar el valor / estado de una variable (no primitiva). Solo que no puede reasignar la referencia a ese objeto una vez inicializado.Considero
final
que los parámetros del método y las variables locales son ruido de código. Las declaraciones de métodos Java pueden ser bastante largas (especialmente con los genéricos); no es necesario hacerlas por más tiempo.Si las pruebas unitarias se escriben correctamente, la asignación de parámetros que es "perjudicial" va a ser recogido, por lo que nunca debería realmente ser un problema. La claridad visual es más importante que evitar un posible error que no se detecta porque las pruebas de su unidad no tienen una cobertura suficiente.
Herramientas como FindBugs y CheckStyle que se pueden configurar para romper la compilación si se realiza una asignación a parámetros o variables locales, si se preocupa profundamente por tales cosas.
Por supuesto, si necesita hacerlos finales, por ejemplo, porque está usando el valor en una clase anónima, entonces no hay problema: esa es la solución más simple y limpia.
Además del efecto obvio de agregar palabras clave adicionales a sus parámetros y, por lo tanto, en mi humilde opinión, camuflarlas, agregar los parámetros finales al método a menudo puede hacer que el código en el cuerpo del método sea menos legible, lo que empeora el código: para ser "bueno", el código debe ser lo más legible y simple posible. Para un ejemplo artificial, digamos que tengo un método que debe funcionar sin distinción entre mayúsculas y minúsculas.
Sin
final
:Sencillo. Limpiar. Todos saben lo que está pasando.
Ahora con 'final', opción 1:
Si bien la configuración de los parámetros
final
impide que el codificador agregue código más abajo de pensar que está trabajando con el valor original, existe el mismo riesgo de que el código más abajo pueda usar eninput
lugar delowercaseInput
, lo que no debería y de lo que no puede protegerse, porque puede ' t sacarlo del alcance (o incluso asignarnull
ainput
si eso ayudaría de todos modos).Con 'final', opción 2:
Ahora acabamos de crear aún más ruido de código e introdujimos un golpe de rendimiento al tener que invocar
toLowerCase()
n veces.Con 'final', opción 3:
Habla sobre el ruido de código. Este es un choque de trenes. Tenemos un nuevo método, un bloque de excepción requerido, porque otro código puede invocarlo incorrectamente. Más pruebas unitarias para cubrir la excepción. Todo para evitar una línea simple, y en mi humilde opinión preferible e inofensiva.
También está el problema de que los métodos no deberían ser tan largos que no se puedan asimilar visualmente y saber de un vistazo que se ha realizado una asignación a un parámetro.
Creo que es una buena práctica / estilo que si asigna un parámetro lo hace al principio del método, preferiblemente en primera línea o inmediatamente después de la verificación de entrada básica, reemplazándolo efectivamente por todo el método, lo que tiene un efecto consistente dentro del método método. Los lectores saben que cualquier tarea debe ser obvia (cerca de la declaración de firma) y en un lugar coherente, lo que mitiga en gran medida el problema que está tratando de evitar la adición final. En realidad, rara vez asigno parámetros, pero si lo hago, siempre lo hago en la parte superior de un método.
Tenga en cuenta también que en
final
realidad no lo protege como puede parecer a primera vista:final
no lo protege completamente a menos que el tipo de parámetro sea primitivo o inmutable.fuente
final
proporciona la garantía parcial de que se trata de la mismaDate
instancia. Algunas garantías son mejores que nada (en todo caso, ¡estás defendiendo clases inmutables desde cero!). En cualquier caso, en la práctica, gran parte de lo que diga debería afectar a los idiomas existentes inmutables por defecto, pero no lo hace, lo que significa que no es un problema.final
, con la posibilidad de hacerlos no finales para casos como el anterior. Simplemente no vale la pena enviar spam a la firma con una palabra clave.input
lugar delowercaseInput
discutible. Si bien es técnicamente correcto, es un error fácil de detectar una vez que le causa un error, ya que puede ver claramente las diferentes semánticas de las 2 variables nombradas por separado en su punto de uso (siempre que les dé buenos nombres). Para mí, es más peligroso combinar 2 usos semánticamente diferentes de valores separados en la misma variable y, por lo tanto, el mismo nombre. Puede hacer que el seguimiento de errores sea más difícil, ya que tendrá que leer y comprender todo el código anterior que de alguna manera está relacionado con la variable 1.Dejo que eclipse se coloque
final
antes de cada variable local, ya que considero que hace que el programa sea más fácil de leer. No lo hago con parámetros, ya que quiero mantener la lista de parámetros lo más corta posible, idealmente debería caber en una línea.fuente
var
para marcar variables no finales. YMMV.var
! Desafortunadamente, no es el predeterminado en Java y ahora es demasiado tarde para cambiar el idioma. Por lo tanto, estoy dispuesto a soportar el pequeño inconveniente de escribirfinal
:)final
palabra clave antepuesta, mientras que solo 10-20% necesitaría unvar
...