La palabra clave final
Parte de la sección Programación Orientada a Objetos del Journey de Java de Coddy. Lección 13 de 87.
La palabra clave final en Java impide la modificación. Se puede aplicar a variables, métodos y clases, con un efecto diferente en cada caso.
Cuando se aplica a una variable, final la convierte en una constante: una vez asignado, su valor no puede cambiar:
public class Circle {
private final double PI = 3.14159;
private final double radius;
public Circle(double radius) {
this.radius = radius; // Se puede asignar una vez en el constructor
}
public void setRadius(double r) {
// this.radius = r; // ¡Error! No se puede volver a asignar una variable final
}
}Una variable final debe inicializarse al declararla o en el constructor. Después de eso, cualquier intento de reasignarla provoca un error de compilación.
Para los tipos de referencia, final significa que la referencia no puede apuntar a un objeto diferente, pero el contenido del objeto todavía puede cambiar:
private final StringBuilder name = new StringBuilder("John");
// name = new StringBuilder("Jane"); // ¡Error! No se puede reasignar
name.append(" Doe"); // ¡Correcto! El contenido del objeto puede cambiarUsar final con campos comunica claramente la intención: indica a otros desarrolladores que este valor nunca debe cambiar después de la inicialización. Esto resulta especialmente útil para valores de configuración, identificadores o cualquier dato que deba permanecer constante durante toda la vida útil de un objeto.
Un final método no se puede sobrescribir en una subclase:
class Base {
public final void greet() {
System.out.println("Hi");
}
}
class Child extends Base {
// public void greet() { } // ¡Error! greet() es final en Base
}Una final clase no se puede extender en absoluto. String es una clase final, así que ninguna clase puede extenderla:
final class Config { }
// class MyConfig extends Config { } // ¡Error! Config es finalDesafío
FácilVamos a crear un sistema de registro de Student que use la palabra clave final para proteger los datos que nunca deberían cambiar después de registrar a un estudiante.
Crearás dos archivos para organizar tu código:
Student.java: Crea una clase Student en la que cierta información quede bloqueada permanentemente una vez establecida:- Un campo
finalstudentId(String): se asigna al crear el objeto y nunca puede cambiar - Un campo
finalenrollmentYear(int): el año en que se matriculó el estudiante; también es permanente - Un campo privado normal
name(String): se puede actualizar si el estudiante cambia de nombre - Un constructor que recibe los tres valores e inicializa los campos
- Un getter
getStudentId()para el ID del estudiante - Un getter
getEnrollmentYear()para el año de matriculación - Un getter
getName()y un settersetName()para el nombre - Un método
getInfo()que devuelve:"ID: [studentId] | Name: [name] | Enrolled: [enrollmentYear]"
- Un campo
Main.java: Crea un objeto Student, luego actualiza su nombre y muestra su información. Recibirás cuatro entradas: el ID del estudiante, el nombre inicial, el año de matriculación y un nombre nuevo para actualizarlo. Imprime dos líneas:- La información del estudiante antes del cambio de nombre
- La información del estudiante después del cambio de nombre
Recibirás cuatro entradas en este orden: studentId (String), name (String), enrollmentYear (int) y newName (String).
Observa cómo los campos final protegen el ID del estudiante y el año de matriculación: son datos permanentes que no deberían cambiar, mientras que el nombre se puede actualizar mediante su setter.
Pruébalo tú mismo
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Leer las entradas
String studentId = scanner.nextLine();
String name = scanner.nextLine();
int enrollmentYear = scanner.nextInt();
scanner.nextLine(); // consumir el salto de línea
String newName = scanner.nextLine();
// TODO: Crear un objeto Student con los valores iniciales
// TODO: Imprimir la información del estudiante antes del cambio de nombre
// TODO: Actualizar el nombre del estudiante usando el setter
// TODO: Imprimir la información del estudiante después del cambio de nombre
}
}
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Programación Orientada a Objetos
1Fundamentos de OOP
Archivos externosIntroducción a la OOPClases vs. ObjetosLa palabra clave thisMétodosCampos (Atributos)Método constructorSobrecarga de constructoresResumen - Calculadora simple4Herencia
Herencia básica (extends)La palabra clave superSobrescritura de métodos (@Override)Encadenamiento de constructoresLa clase ObjectHerencia simple y multinivelPor qué no hay herencia múltiple de clasesResumen - Jerarquía de empleados7Métodos especiales y la clase Object
Método toString()equals() y hashCode()Método clone()compareTo() y ComparableInterfaz ComparatorResumen - Ordenamiento personalizado2Modificadores de acceso y encapsulamiento
Visión general de los niveles de accesoMétodos Getter y SetterOcultamiento de informaciónLa palabra clave finalResumen - Gestor de cuentas bancarias5Polimorfismo
Fundamentos de sobrecarga de métodosSobrescritura de métodos (tiempo de ejecución)Upcasting y DowncastingEl operador instanceofClases y métodos abstractosResumen - Calculadora de figuras8Conceptos avanzados de POO
Composición vs. HerenciaAgregación vs. ComposiciónClases internas, anidadas y anónimasEnums y métodos de EnumRecords (Java 16+)Clases selladas (Java 17+)11Patrones de diseño - Parte 1
Introducción a los patrones de diseñoPatrón SingletonPatrón FactoryPatrón BuilderPatrón ObserverPatrón Strategy3Propiedades de clase y miembros estáticos
Variables de instancia vs. estáticasMétodos estáticosBloques estáticosConstantes (static final)Repaso - Contador y utilidad6Interfaces y Clases Abstractas
Introducción a las InterfacesImplementación de InterfacesImplementación de Múltiples InterfacesMétodos Default y Static en InterfacesClases Abstractas vs InterfacesInterfaces FuncionalesResumen - Sistema de Pagos9Genéricos
Introducción a los genéricosClases genéricasMétodos genéricosParámetros de tipo delimitadosComodines (?, extends, super)Resumen - Contenedor genérico12Patrones de diseño Parte 2
Patrón CommandPatrón AdapterPatrón DecoratorPatrón Template MethodPatrón StatePatrón CompositePatrón IteratorPractica por tu cuenta: Compilador de Java online