The final Keyword
Part of the Object Oriented Programming section of Coddy's Java journey — lesson 13 of 87.
The final keyword in Java prevents modification. It can be applied to variables, methods, and classes, each with a different effect.
When applied to a variable, final makes it a constant - once assigned, its value cannot change:
public class Circle {
private final double PI = 3.14159;
private final double radius;
public Circle(double radius) {
this.radius = radius; // Can assign once in constructor
}
public void setRadius(double r) {
// this.radius = r; // Error! Cannot reassign final variable
}
}A final variable must be initialized either at declaration or in the constructor. After that, any attempt to reassign it causes a compilation error.
For reference types, final means the reference cannot point to a different object, but the object's contents can still change:
private final StringBuilder name = new StringBuilder("John");
// name = new StringBuilder("Jane"); // Error! Can't reassign
name.append(" Doe"); // OK! Object contents can changeUsing final with fields communicates intent clearly - it tells other developers that this value should never change after initialization. This is especially useful for configuration values, IDs, or any data that must remain constant throughout an object's lifetime.
Challenge
EasyLet's build a Student registration system that uses the final keyword to protect data that should never change after a student is registered.
You'll create two files to organize your code:
Student.java: Create a Student class where certain information is permanently locked once set:- A
finalfieldstudentId(String) - assigned at creation and can never change - A
finalfieldenrollmentYear(int) - the year the student enrolled, also permanent - A regular private field
name(String) - can be updated if the student changes their name - A constructor that takes all three values and initializes the fields
- A getter
getStudentId()for the student ID - A getter
getEnrollmentYear()for the enrollment year - A getter
getName()and settersetName()for the name - A method
getInfo()that returns:"ID: [studentId] | Name: [name] | Enrolled: [enrollmentYear]"
- A
Main.java: Create a Student object, then update their name and display their information. You'll receive four inputs: the student ID, initial name, enrollment year, and a new name to update to. Print two lines:- The student info before the name change
- The student info after the name change
You will receive four inputs in order: studentId (String), name (String), enrollmentYear (int), and newName (String).
Notice how the final fields protect the student's ID and enrollment year - these are permanent records that shouldn't change, while the name can be updated through its setter.
Cheat sheet
The final keyword prevents modification in Java. It can be applied to variables, methods, and classes.
When applied to a variable, final makes it a constant - once assigned, its value cannot change:
public class Circle {
private final double PI = 3.14159;
private final double radius;
public Circle(double radius) {
this.radius = radius; // Can assign once in constructor
}
public void setRadius(double r) {
// this.radius = r; // Error! Cannot reassign final variable
}
}A final variable must be initialized either at declaration or in the constructor. After that, any attempt to reassign it causes a compilation error.
For reference types, final means the reference cannot point to a different object, but the object's contents can still change:
private final StringBuilder name = new StringBuilder("John");
// name = new StringBuilder("Jane"); // Error! Can't reassign
name.append(" Doe"); // OK! Object contents can changeUsing final with fields communicates intent - it indicates that a value should never change after initialization, useful for configuration values, IDs, or constant data.
Try it yourself
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Read inputs
String studentId = scanner.nextLine();
String name = scanner.nextLine();
int enrollmentYear = scanner.nextInt();
scanner.nextLine(); // consume newline
String newName = scanner.nextLine();
// TODO: Create a Student object with the initial values
// TODO: Print the student info before the name change
// TODO: Update the student's name using the setter
// TODO: Print the student info after the name change
}
}
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Object Oriented Programming
1Fundamentals of OOP
External FilesIntroduction to OOPClasses vs ObjectsThe this KeywordMethodsFields (Attributes)Constructor MethodConstructor OverloadingRecap - Simple Calculator4Inheritance
Basic Inheritance (extends)The super KeywordMethod Overriding (@Override)Constructor ChainingThe Object ClassSingle & Multilevel InheritWhy No Multi Class InheritRecap - Employee Hierarchy7Special Methods & Object Class
toString() Methodequals() and hashCode()clone() MethodcompareTo() and ComparableComparator InterfaceRecap - Custom Sorting2Access Modifiers & Encapsulate
Access Levels OverviewGetter and Setter MethodsInformation HidingThe final KeywordRecap - Bank Account Manager5Polymorphism
Method Overloading BasicsMethod Overriding (Run-Time)Upcasting and DowncastingThe instanceof OperatorAbstract Classes and MethodsRecap - Shape Calculator8Advanced OOP Concepts
Composition vs InheritanceAggregation vs CompositionInner Nested & Anonymous ClassEnums and Enum MethodsRecords (Java 16+)Sealed Classes (Java 17+)3Class Props & Static Member
Instance vs Static VariablesStatic MethodsStatic BlocksConstants (static final)Recap - Counter & Utility6Interfaces & Abstract Classes
Introduction to InterfacesImplementing InterfacesMulti Interface ImplemenDefault & Static in InterfaceAbstract Classes vs InterfacesFunctional InterfacesRecap - Payment System