Uso excesivo de la palabra clave "final" en Java [duplicado]

91

Aunque entiendo para qué se utiliza la palabra clave final en el contexto de clases y métodos, así como la intención de su uso en relación con las variables; sin embargo, el proyecto en el que comencé a trabajar parece tener un número excesivo de ellos y tengo curiosidad por la lógica que hay detrás.

El siguiente fragmento de código es solo un pequeño ejemplo, ya que no veo mucho en la palabra clave final para las variables key y value :

private <K, V> Collection<V> getValuesForKeys(
    final Map<K, V> map, final Collection<K> keys) 
{
    final Collection<V> values = new ArrayList<V>(keys.size());
    for (final K key : keys) {
        final V value = map.get(key);
        if (value != null) {
            values.add(value);
        }
    }
    return values;
}

He estado leyendo un poco el uso de los artículos que he encontrado en Google; sin embargo, ¿el patrón realmente hace cosas como ayudar al compilador a optimizar el código?

    
pregunta rjzii 04.08.2011 - 20:27
fuente

6 respuestas

101

Hay muchas referencias que sugieren un liberal use final . La especificación del lenguaje Java incluso tiene una sección sobre variables finales . Varias reglas en las herramientas de análisis estático también lo admiten: PMD incluso tiene una número de reglas para detectar cuándo se puede usar final . Las páginas que vinculé brindan una serie de puntos en cuanto a lo que hace final y por qué debería usarlo generosamente.

Para mí, el uso liberal de final logró dos cosas en la mayoría del código, y estas son probablemente las cosas que llevaron al autor de su ejemplo de código a utilizarlo:

  1. Hace que la intención del código sea mucho más clara, y lleva al código de auto-documentación. El uso de final evita que el valor de un objeto primitivo cambie o que se cree un nuevo objeto y sobrescriba un objeto existente. Si no hay necesidad de cambiar el valor de una variable y alguien lo hace, el IDE y / o el compilador proporcionarán una advertencia. El desarrollador debe solucionar el problema o eliminar explícitamente el modificador final de la variable. De cualquier manera, es necesario pensar para asegurar que se logre el resultado deseado.

  2. Dependiendo de su código, sirve como una sugerencia para que el compilador habilite potencialmente las optimizaciones. Esto no tiene nada que ver con el tiempo de compilación, sino lo que el compilador puede hacer durante la compilación. Tampoco se garantiza hacer nada. Sin embargo, indicar al compilador que el valor de esta variable o el objeto al que se refiere esta variable nunca cambiará podría permitir optimizaciones de rendimiento.

También hay otras ventajas relacionadas con la concurrencia. Cuando se aplica a nivel de clase o método, tiene que ver con garantizar lo que se puede anular o heredar. Sin embargo, estos están fuera del alcance de su ejemplo de código. Nuevamente, los artículos que vinculé son mucho más detallados sobre cómo se puede aplicar final .

La única forma de estar seguro de por qué el autor del código decidió usar final es encontrar al autor y preguntar por usted mismo.

    
respondido por el Thomas Owens 04.08.2011 - 21:08
fuente
30

Los principales beneficios de "final" en mi mente son dos:

  • Las variables finales son "más seguras" que las variables no finales, porque una vez que están vinculadas, nunca hay una pregunta sobre cuál es su estado actual.
  • Debido a lo anterior, hacer que una variable final libere al programador de un exceso de malabares mentales: no tiene que escanear el código para ver si la variable ha cambiado. Este feliz estado de cosas será familiar para cualquiera que haya pasado algún tiempo en un entorno de lenguaje funcional.

En cuanto a este ejemplo específico, puede ser que el programador haya adquirido el hábito "final" y simplemente aplique la palabra clave "final" en todas partes como una cuestión de rutina. (Soy escéptico de la idea de que la palabra clave final ayudaría al compilador cuando se habla de asignaciones individuales, ¿no es necesaria la ayuda para determinar que solo se realizó una asignación?)

Soy de la opinión de que Java lo hizo al revés: no debería haber una palabra clave "final" para las variables, todo debería ser "final" de forma predeterminada, y si desea una variable mutable, debe agregar una palabra clave para que ("var" o algo así). (Como mencionó otro comentarista, scala tiene dos palabras clave: "val" y "var" para las variables finales y no finales, respectivamente, lo tomaré).

    
respondido por el nerdytenor 05.08.2011 - 07:56
fuente
11

En Java, el único lugar donde sé que la palabra clave final es required es hacer que una variable esté disponible de manera confiable para una clase anónima (ya que el compilador hace algunos trucos bajo las cubiertas que requieren que esto el valor no puede cambiar).

Según mi conocimiento, es un mito que la palabra clave final permita al compilador de Java optimizar el código, ya que todas las optimizaciones que importan ocurren en la parte JIT del tiempo de ejecución.

Por lo tanto, es una cuestión de gusto. Sin embargo, hay un beneficio muy importante para el uso de muchas finales, a saber, hacer que el código sea más fácil de leer para futuros mantenedores.

Marcar una variable como final le dice al lector que esta variable nunca cambia cuando se asigna. Esto es muy importante cuando lea el código, ya que cuando necesite saber el valor de la variable es el mismo que en la asignación inicial y no tiene que analizar mentalmente todo el código intermedio para ver si la variable se asigna nuevamente. con algo mas

También si ve que una variable no está marcada con final , sabe que se cambiará más adelante . Esta es una información extremadamente importante que se puede transmitir al lector simplemente con la falta de cinco caracteres.

¡Cualquier cosa que pueda ayudar al mantenedor a hacer su trabajo más rápido y de manera más confiable significa que la aplicación es más barata de mantener! En otras palabras, final ahorra dinero real.

Nota: Eclipse tiene una opción de "limpieza de origen" que puede insertar finales cuando sea posible. Esto puede ser útil tanto para escribir un nuevo código como para mantener el antiguo (insertar finales, si faltan algunos, la variable se cambia después de la asignación inicial). Mi intuición es que esto es lo que el autor original descubrió y decidió usar.

El tema se trata más detalladamente en enlace

    
respondido por el user1249 08.08.2011 - 19:17
fuente
6

Creo que la respuesta a esto es más simple de lo que otros sugieren. No se trata de intención, o diseño. Hace un buen tiempo, era cierto que la adición final en algunos lugares (particularmente, para métodos y clases) permitía que la JVM se optimizara más agresivamente. Como resultado, algunas personas se volvieron locas y pusieron el literal literalmente everywhere para intentar que su código fuera más rápido.

Debo agregar que no es el compilador, sino la JVM que hace la optimización. Además, dudo que poner una final en una variable local alguna vez hubiera hecho una diferencia en el rendimiento.

Finalmente, el uso final probablemente no haría mucha diferencia en estos días ya que las optimizaciones de JVM han avanzado un poco.

    
respondido por el redjamjar 04.08.2011 - 23:02
fuente
1

Me parece que la palabra clave final se está utilizando en este contexto para crear una colección inmutable. Las colecciones inmutables son más fáciles de usar y más seguras de usar en programas que requieren concurrencia (varios subprocesos ).

No es cierto, por supuesto. La palabra clave final solo garantiza que la referencia a la colección no se puede reemplazar con una referencia a una colección diferente o nula.

    
respondido por el Robert Harvey 04.08.2011 - 21:03
fuente
-2

En una clase, final evita que se extienda. También evita que un usuario anule un método en una subclase. Haría esto, ya sea para proteger la funcionalidad de su clase o para evitar que alguien manipule la forma básica en que funciona. También es más eficiente una vez compilado: no sé exactamente cómo en este momento, solo sé que es.

Lo utilizarías para una variable como forma abreviada de un valor. Este es el reemplazo de java para c / c ++ #define nombre valor o la palabra clave const. La razón principal por la que haces esto es aumentar la legibilidad y ahorrarte la molestia de tener que escribir un valor varias veces en tu código. Especialmente porque cuando quieres cambiar ese valor, deberías cambiarlo en todas partes. La palabra clave final garantiza que no pueda cambiar accidentalmente su valor en otro lugar de su código.

Parece ser excesivo en el código que publicaste anteriormente.

Además, obviamente es diferente de c ++ en el sentido de que no se puede cambiar un valor constante dentro de un método, mientras que este obviamente se está cambiando.

Además, una vez que una variable se establece en final, se garantiza la seguridad del hilo, ya que es imposible escribir en el valor.

    
respondido por el Jonathan Henson 04.08.2011 - 20:38
fuente

Lea otras preguntas en las etiquetas