CodeGym /Blog Java /Random-ES /Hablemos de la palabra clave final en Java
Autor
Oleksandr Miadelets
Head of Developers Team at CodeGym

Hablemos de la palabra clave final en Java

Publicado en el grupo Random-ES
Java tiene esta palabra clave: final. Se puede aplicar a clases, métodos, variables (incluidos los parámetros del método). Para una clase, la palabra clave final significa que la clase no puede tener subclases, es decir, la herencia está prohibida... Esto es útil cuando se crean objetos inmutables (no modificables). Por ejemplo, la clase String se declara como final.

    public final class String {
    }
    
    class SubString extends String { // Compilation error
    }
También debo señalar que el modificador final no se puede aplicar a clases abstractas (aquellas con la palabra clave resumen), porque estos son conceptos mutuamente excluyentes. Para un método final, el modificador significa que el método no se puede anular en las subclases. Esto es útil cuando queremos evitar la alteración de la implementación original.

    public class SuperClass {
        public final void printReport() {
            System.out.println("Report");
        }
    }

    class SubClass extends SuperClass { 
        public void printReport() { //Compilation error
            System.out.println("MyReport");
        }
    }
Para variables de tipo primitivo, la palabra clave final significa que el valor, una vez asignado, no se puede cambiar. Para las variables de referencia, significa que después de asignar un objeto, no puede cambiar la referencia a ese objeto. ¡Esto es importante! No se puede cambiar la referencia, pero se puede cambiar el estado del objeto. Java 8 introdujo un nuevo concepto: efectivamente final. Se aplica solo a las variables (incluidos los parámetros del método). La conclusión es que, a pesar de la clara ausencia de la palabra clave final, el valor de la variable no cambia después de la inicialización. En otras palabras, la palabra clave final se puede aplicar a dicha variable sin un error de compilación. Efectivamente, las variables finales se pueden usar dentro de clases locales (clases internas locales), clases anónimas (clases internas anónimas) y transmisiones (Stream API).

        public void someMethod() {
            // In the example below, both a and b are effectively final, since they are assigned values only once:
            int a = 1;
            int b;
            if (a == 2) b = 3;
            else b = 4;
            // c is NOT effectively final since its value changes
            int c = 10;
            c++;
            
            Stream.of(1, 2).forEach(s-> System.out.println(s + a)); // OK
            Stream.of(1, 2).forEach(s-> System.out.println(s + c)); // Compilation error
        }
Ahora, tengamos una pequeña entrevista. Después de todo, el objetivo de completar el curso de CodeGym es convertirse en desarrollador de Java y encontrar un trabajo interesante y bien remunerado. Vamos a empezar.
  1. ¿Qué podemos decir sobre una matriz que se declara final?

  2. Sabemos que la clase String es inmutable: la clase se declara final. Un valor de cadena se almacena en una matriz de caracteres que está marcada con la palabra clave final.


public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    /** The value is used for character storage. */
    private final char value[];

¿Podemos reemplazar el valor de un objeto String (sin cambiar la referencia al objeto)? Estas son preguntas reales de la entrevista. Y la práctica demuestra que muchos candidatos no las responden correctamente. Comprender cómo se usa la palabra clave final, especialmente para las variables de referencia, es muy importante. Mientras contemplas esto, haré una pequeña solicitud al equipo de CodeGym. Dale al editor de texto la capacidad de agregar un bloque cuyo contenido se pueda mostrar/ocultar al hacer clic en él. Respuestas:
  1. Una matriz es un objeto, por lo que la palabra clave final significa que una vez que se asigna una referencia a la matriz, la referencia no se puede cambiar. Dicho esto, puedes cambiar el estado del objeto.

    
            final int[] array = {1, 2, 3, 4, 5};
            array[0] = 9;	 // OK, because we're changing the contents of the array: {9, 2, 3, 4, 5}
            array = new int[5]; // Compilation error
    
  2. Si podemos. Lo principal es comprender qué significa la palabra clave final espinosa cuando se usa con objetos. La API de Reflection se puede utilizar para reemplazar valores.


import java.lang.reflect.Field;

class B {
    public static void main(String[] args) throws Exception {
        String value = "Old value";
        System.out.println(value);

        // Get the String class's value field
        Field field = value.getClass().getDeclaredField("value");
        // Make it mutable
        field.setAccessible(true);
        // Set a new value
        field.set(value, "CodeGym".toCharArray());

        System.out.println(value);

        /* Output:
         * Old value
         * CodeGym
         */
    }
}
Tenga en cuenta que si hubiéramos intentado cambiar la variable final de un tipo primitivo de esta manera, no habría pasado nada. Te sugiero que te convenzas: crea una clase Java, por ejemplo, con un campo int final e intenta cambiar su valor usando la API de Reflection. ¡Buena suerte a todos!
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION