Working with Constants Using the final Keyword
Course: Core Java Training
Topic: Working with Constants Using the final Keyword
Course Link: Core Java Training Course
Demo Link: Register for a Course Demo
JustAcademy Website: Visit JustAcademy
1. Introduction to Constants in Java
In Java programming, constants are values that should not be reassigned after they have been established. Examples include the number of minutes in an hour, a fixed tax rate used by an application, a maximum number of login attempts, and mathematical values such as pi.
Java provides the final keyword to prevent a variable from being assigned more than once. When a variable represents a value that should remain fixed, declaring it as final communicates that intention and helps prevent accidental reassignment.
For example, an application may use a constant to represent the maximum number of products allowed in a shopping cart.
final int MAX_CART_ITEMS = 50;
System.out.println(MAX_CART_ITEMS);
In this example, MAX_CART_ITEMS is initialized to 50. After initialization, Java does not allow the variable to be assigned another value.
2. Learning Objectives
After completing this topic, you should be able to:
- Understand the purpose of constants in Java.
- Explain the role of the
final keyword.
- Declare and initialize final variables correctly.
- Understand local, instance, and static final variables.
- Use
static final to define shared class constants.
- Understand blank final variables and constructor initialization.
- Distinguish final references from immutable objects.
- Identify common errors involving final variables.
- Apply constants in practical Java programs.
3. What Is the final Keyword?
The final keyword is a Java modifier that restricts certain kinds of changes. Its effect depends on whether it is applied to a variable, method, or class.
| Usage |
Purpose |
Example |
| Final variable |
Prevents reassignment after the variable has been initialized. |
final int AGE = 25; |
| Final method |
Prevents a subclass from overriding the method. |
final void display() |
| Final class |
Prevents the class from being extended. |
final class Utility |
This topic focuses primarily on constants and final variables. Final methods and classes are introduced here to explain the broader purpose of the keyword.
4. What Is a Constant?
A constant is a value that a program treats as fixed rather than changing throughout execution. Instead of repeating a literal value throughout the code, a developer can give it a meaningful name.
Example Without a Named Constant
double price = 2000.0;
double tax = price * 0.18;
System.out.println("Tax: " + tax);
The value 0.18 represents a rate, but its meaning is not immediately clear to every reader.
Example Using a Named Constant
final double TAX_RATE = 0.18;
double price = 2000.0;
double tax = price * TAX_RATE;
System.out.println("Tax: " + tax);
The name TAX_RATE communicates the purpose of the value. If the variable is accidentally reassigned later, the compiler reports an error.
Important distinction: In Java terminology, a constant variable specifically means a final variable of primitive type or type String initialized with a constant expression. In everyday programming, developers also commonly call other fixed static final fields constants.
5. Declaring and Initializing Final Variables
To declare a final variable, place the final keyword before its type.
Syntax
final dataType VARIABLE_NAME = value;
Examples
final int MAX_USERS = 100;
final double PI_VALUE = 3.14159;
final char GRADE = 'A';
final boolean IS_ACTIVE = true;
final String COUNTRY = "India";
Once these variables have been assigned their values, they cannot be reassigned.
Attempting to Reassign a Final Variable
final int MAX_USERS = 100;
MAX_USERS = 200; // Compilation error
The assignment fails because MAX_USERS is already initialized and declared as final.
Why Does Java Enforce This Rule?
- It prevents accidental changes to values intended to remain fixed.
- It makes the developer's intention clear to other programmers.
- It improves code readability and maintainability.
- It helps catch certain programming mistakes during compilation.
- It makes shared configuration values easier to identify and reuse.
6. Naming Conventions for Constants
Java naming conventions commonly use uppercase letters with underscores between words for constants. This style is known as UPPER_SNAKE_CASE.
| Purpose |
Recommended Name |
Example Declaration |
| Maximum login attempts |
MAX_LOGIN_ATTEMPTS |
static final int MAX_LOGIN_ATTEMPTS = 5; |
| Application name |
APPLICATION_NAME |
static final String APPLICATION_NAME = "ShopApp"; |
| Timeout in seconds |
REQUEST_TIMEOUT_SECONDS |
static final int REQUEST_TIMEOUT_SECONDS = 30; |
| Conversion factor |
KILOMETERS_TO_METERS |
static final int KILOMETERS_TO_METERS = 1000; |
Uppercase naming is a convention, not a requirement imposed by the compiler. A final local variable can also use camelCase if that is more appropriate to its context.
Good and Poor Naming Examples
// Less descriptive
final int X = 5;
final double N = 0.18;
// More descriptive
final int MAX_RETRY_COUNT = 5;
final double TAX_RATE = 0.18;
Meaningful names make it easier to understand what a value represents without searching through the entire program.
7. Understanding static final Constants
The combination of static and final is commonly used for class-level constants.
static means the field belongs to the class rather than to each individual object.
final means the field cannot be reassigned after initialization.
Syntax
static final dataType CONSTANT_NAME = value;
Example
class MathConstants {
static final double PI = 3.141592653589793;
static final int DAYS_IN_WEEK = 7;
static final int HOURS_IN_DAY = 24;
}
public class Main {
public static void main(String[] args) {
System.out.println(MathConstants.PI);
System.out.println(MathConstants.DAYS_IN_WEEK);
System.out.println(MathConstants.HOURS_IN_DAY);
}
}
Output
3.141592653589793
7
24
The constants are accessed through the class name, such as MathConstants.PI. Because the fields are static, creating a MathConstants object is unnecessary to access them.
Why Use static final Together?
- One class-level field can represent a value shared by all objects.
- It avoids creating a separate field for every object when a shared constant is appropriate.
- It clearly distinguishes class-wide fixed values from instance-specific state.
- It supports centralized definitions for commonly used values.
8. Types of Final Variables
Final variables can be declared in different locations depending on their intended use.
| Type |
Location |
Example |
Purpose |
| Local final variable |
Inside a method or block |
final int count = 10; |
Prevents reassignment within that local scope. |
| Instance final field |
Inside a class, outside methods, without static |
final int employeeId; |
Allows each object to receive its own fixed value. |
| Static final field |
Inside a class with static |
static final int MAX_SIZE = 100; |
Represents a shared class-level constant. |
| Final parameter |
Inside a method or constructor parameter list |
void print(final int value) |
Prevents reassignment of the parameter within the method. |
9. Local Final Variables
A local final variable is declared inside a method, constructor, or block. It can be initialized at the time of declaration or assigned later, provided it is assigned exactly once before use and all execution paths satisfy Java's definite-assignment rules.
Example: Initialization at Declaration
public class LocalConstantExample {
public static void main(String[] args) {
final int BONUS_POINTS = 10;
int score = 80;
int finalScore = score + BONUS_POINTS;
System.out.println(finalScore);
}
}
Output
90
Example: Assignment Later
public class BlankLocalFinal {
public static void main(String[] args) {
final int MAX_SCORE;
MAX_SCORE = 100;
System.out.println(MAX_SCORE);
}
}
This is valid because MAX_SCORE is assigned once before it is used. The variable cannot be assigned again after that.
10. Instance Final Variables
An instance final variable is a field that belongs to an individual object. Each object can have its own value, but that field cannot be reassigned after initialization.
Example
class Employee {
final int employeeId;
String employeeName;
Employee(int employeeId, String employeeName) {
this.employeeId = employeeId;
this.employeeName = employeeName;
}
void display() {
System.out.println("ID: " + employeeId);
System.out.println("Name: " + employeeName);
}
}
public class Main {
public static void main(String[] args) {
Employee first = new Employee(101, "Aarav");
Employee second = new Employee(102, "Riya");
first.display();
second.display();
}
}
Output
ID: 101
Name: Aarav
ID: 102
Name: Riya
Each employee receives a different employeeId during construction. After construction, the field cannot be reassigned. The employeeName field is not final, so it can be changed if required.
11. Static Final Variables
A static final variable is commonly used when a fixed value should be shared across all instances of a class.
Example: Application Configuration
class AppConfig {
static final String APP_NAME = "StudentPortal";
static final int MAX_LOGIN_ATTEMPTS = 3;
static final int SESSION_TIMEOUT_MINUTES = 20;
}
public class Main {
public static void main(String[] args) {
System.out.println(AppConfig.APP_NAME);
System.out.println(AppConfig.MAX_LOGIN_ATTEMPTS);
System.out.println(AppConfig.SESSION_TIMEOUT_MINUTES);
}
}
Output
StudentPortal
3
20
This approach is useful when the same fixed value is required in multiple parts of a program. Instead of repeating the same literal, code can refer to the named constant.
12. Blank Final Variables
A blank final variable is a final variable declared without an initializer. Java requires it to be assigned exactly once before it is used and, for a field, before the relevant constructor or class initialization completes.
Blank Final Instance Field
class Rectangle {
final int width;
final int height;
Rectangle(int width, int height) {
this.width = width;
this.height = height;
}
int calculateArea() {
return width * height;
}
}
public class Main {
public static void main(String[] args) {
Rectangle rectangle = new Rectangle(10, 5);
System.out.println(rectangle.calculateArea());
}
}
Output
50
The constructor initializes both final fields. Different rectangle objects may have different dimensions, but each object's dimensions cannot be reassigned after initialization.
Blank Final Static Field
A static final field can also be initialized inside a static initializer block when its value cannot conveniently be placed directly in the declaration.
class SystemSettings {
static final String MODE;
static {
MODE = "PRODUCTION";
}
}
The static initializer runs when the class is initialized. The field must receive its value before class initialization completes.
13. Final Variables and Reference Types
A frequent misunderstanding is that declaring an object reference as final makes the entire object immutable. This is not correct.
When a reference variable is final, the reference cannot be changed to point to another object after assignment. However, the referenced object may still be mutable.
Example with a Final Reference
class Student {
String name;
Student(String name) {
this.name = name;
}
}
public class Main {
public static void main(String[] args) {
final Student student = new Student("Aarav");
student.name = "Riya";
System.out.println(student.name);
// Not allowed:
// student = new Student("Kabir");
}
}
Output
Riya
The statement student.name = "Riya"; is allowed because it changes the object's field, not the reference stored in student. Assigning a different object to student is not allowed.
Final Arrays
final int[] numbers = {10, 20, 30};
numbers[0] = 99; // Allowed
// Not allowed:
// numbers = new int[] {1, 2, 3};
System.out.println(numbers[0]);
Output
99
The array's elements can change, but the final reference cannot be reassigned. If you need an object whose state cannot change, use an immutable class or design the class so that mutable state is not exposed.
14. The Difference Between final, finally, and finalize
These three terms look similar but serve different purposes in Java.
| Term |
Meaning |
Example |
final |
Keyword used with variables, methods, and classes to restrict reassignment, overriding, or inheritance. |
final int LIMIT = 10; |
finally |
Block associated with exception handling that normally executes when control leaves a try statement, subject to abrupt termination and other runtime conditions. |
try { } finally { } |
finalize() |
An old Object method associated with finalization. It is deprecated for removal and should not be relied on for resource cleanup. |
Avoid using it in new code. |
For releasing files, database connections, and other resources, prefer try-with-resources and explicit resource management rather than relying on finalize().
15. Constants in Real-World Java Applications
Constants are useful in many kinds of applications. They help centralize fixed values and communicate their purpose.
15.1 E-Commerce Applications
class ShoppingCartConfig {
static final int MAX_CART_ITEMS = 50;
static final int FREE_SHIPPING_MINIMUM = 1000;
}
These constants can represent application limits and a configured shipping threshold. In a real system, business rules that change frequently may belong in external configuration or a database rather than being compiled into the application.
15.2 Banking Applications
class BankingConfig {
static final int MAX_PIN_ATTEMPTS = 3;
static final int TRANSACTION_TIMEOUT_SECONDS = 30;
}
Named constants can make fixed technical limits clear. Security-sensitive and operational rules should still be reviewed carefully and configured appropriately for the production environment.
15.3 Education Applications
class ExamSettings {
static final int PASSING_MARKS = 40;
static final int MAX_MARKS = 100;
}
These constants help avoid repeated numeric literals when displaying or validating exam results.
15.4 Unit Conversion
class UnitConverter {
static final int METERS_PER_KILOMETER = 1000;
static double toMeters(double kilometers) {
return kilometers * METERS_PER_KILOMETER;
}
}
16. Complete Practical Program Using Constants
The following example uses constants to calculate the area of a circle and display its circumference.
class CircleCalculator {
static final double PI = 3.141592653589793;
static double calculateArea(double radius) {
return PI * radius * radius;
}
static double calculateCircumference(double radius) {
return 2 * PI * radius;
}
}
public class Main {
public static void main(String[] args) {
final double radius = 5.0;
double area = CircleCalculator.calculateArea(radius);
double circumference =
CircleCalculator.calculateCircumference(radius);
System.out.println("Radius: " + radius);
System.out.println("Area: " + area);
System.out.println("Circumference: " + circumference);
}
}
Output
Radius: 5.0
Area: 78.53981633974483
Circumference: 31.41592653589793
Program Explanation
PI is a static final field shared by the class.
radius is a local final variable that cannot be reassigned.
calculateArea() calculates the circle's area.
calculateCircumference() calculates the circle's circumference.
- The program avoids repeating the value of pi in multiple formulas.
17. Common Errors When Using final
Error 1: Reassigning a Final Variable
final int MAX_USERS = 100;
MAX_USERS = 150; // Compilation error
Solution: Do not reassign a final variable. If the value must change during execution, use a non-final variable instead.
Error 2: Using a Blank Final Field Without Initializing It
class Product {
final int productId;
Product() {
// productId is not initialized
}
}
Problem: The constructor does not assign a value to the blank final instance field.
Solution: Initialize the field at its declaration or assign it in every constructor that must initialize it.
class Product {
final int productId;
Product(int productId) {
this.productId = productId;
}
}
Error 3: Assuming a Final Object Is Immutable
final StringBuilder message = new StringBuilder("Hello");
message.append(" Java"); // Allowed
// message = new StringBuilder("New"); // Compilation error
Solution: Remember that final restricts reassignment of the reference. It does not automatically make the referenced object immutable.
Error 4: Trying to Initialize a Static Final Field in an Instance Constructor
class Configuration {
static final int PORT;
Configuration() {
// PORT = 8080; // Not a valid initialization location
}
}
Solution: Initialize a static final field at its declaration or in a static initializer block.
class Configuration {
static final int PORT = 8080;
}
Error 5: Declaring a Constant with a Vague Name
static final int VALUE = 60;
Solution: Use a name that explains the value's meaning, such as SECONDS_PER_MINUTE.
18. Best Practices for Working with Constants
- Use
final when a variable should not be reassigned after initialization.
- Use
static final for values shared by the class and intended to remain fixed.
- Follow the
UPPER_SNAKE_CASE convention for class constants.
- Choose descriptive names instead of unexplained numeric or string literals.
- Keep constants close to the class or module that owns their meaning.
- Avoid creating a single miscellaneous constants class containing unrelated values from the entire application.
- Do not assume that a final reference makes an object immutable.
- Use constructors to initialize instance final fields when each object requires its own fixed value.
- Use static initializer blocks only when static final fields cannot be initialized conveniently at the declaration.
- Keep environment-specific settings, secrets, and frequently changing business rules outside compiled constants when appropriate.
- Do not use
final automatically on every variable; use it where it improves correctness or communicates intent.
19. Practical Exercises
Exercise 1: Declare Basic Constants
Create final variables for the following values:
- Maximum number of students: 60
- Days in a week: 7
- Application name:
LearningPortal
- Conversion factor from kilometers to meters: 1000
Print all four values to the console.
Exercise 2: Fix the Compilation Error
public class Main {
public static void main(String[] args) {
final double PI = 3.14159;
PI = 3.14;
System.out.println(PI);
}
}
Identify why the program fails and rewrite it so that it compiles.
Exercise 3: Create an Employee Class
Create an Employee class with a final employee ID and a changeable employee name. Initialize the employee ID through the constructor and write a method to display both fields.
Exercise 4: Build a Unit Converter
Create a class with a static final conversion constant for centimeters per meter. Write a method that converts meters to centimeters and test it with multiple values.
Exercise 5: Understand Final References
Declare a final array containing three numbers. Change one array element and print the array. Then explain why assigning a new array to the same final variable is not allowed.
20. Interview Questions and Answers
Q1. What is the purpose of the final keyword in Java?
Answer: The final keyword restricts reassignment of variables, overriding of methods, and inheritance from classes, depending on how it is used.
Q2. How do you declare a constant in Java?
Answer: Use the final keyword for a variable that should not be reassigned. A common class-level constant declaration is static final int MAX_SIZE = 100;.
Q3. What is the difference between final and static final?
Answer: final prevents reassignment. static final also makes the field belong to the class rather than to each individual instance.
Q4. Can a final variable be initialized later?
Answer: Yes. A blank final variable may be initialized later, provided it is assigned exactly once and Java's definite-assignment rules are satisfied.
Q5. Can a final instance variable have different values in different objects?
Answer: Yes. A final instance field can be initialized separately in each object's constructor. Its value cannot be reassigned after initialization.
Q6. Can a final reference point to another object later?
Answer: No. Once assigned, a final reference cannot be reassigned to another object.
Q7. Can the contents of a final array be changed?
Answer: Yes. A final array reference cannot be reassigned, but its elements can be modified unless other restrictions apply.
Q8. Why are constants commonly written in uppercase?
Answer: Uppercase letters with underscores are a naming convention that makes constants easy to recognize. It is a convention rather than a compiler requirement.
Q9. Where can a static final field be initialized?
Answer: It can be initialized in its declaration or in a static initializer block.
Q10. What is a blank final variable?
Answer: A blank final variable is declared without an initial value and must be assigned exactly once before it is used and before its required initialization point is completed.
Q11. Is every final variable a compile-time constant?
Answer: No. A Java constant variable, in the language specification's precise sense, must be final, have primitive or String type, and be initialized with a constant expression. Other final variables may hold objects or values determined at runtime.
Q12. What is the difference between final and immutable?
Answer: Final prevents reassignment of a variable or reference. Immutability means an object's observable state cannot change after creation. A final reference may still point to a mutable object.
21. Quick Revision Checklist
- The
final keyword restricts reassignment of variables.
- A final variable must be assigned before use and cannot be reassigned after initialization.
static final is commonly used for class-level constants.
- Constants conventionally use uppercase names separated by underscores.
- Blank final fields can be initialized through constructors or initializer blocks as appropriate.
- Instance final fields can have different values in different objects.
- Static final fields represent shared class-level values.
- A final object reference cannot be reassigned, but the referenced object may still be mutable.
- Meaningful constant names make programs easier to understand.
- Final methods cannot be overridden, and final classes cannot be extended.
22. Conclusion
The final keyword is an important feature of Core Java. It allows developers to prevent unwanted variable reassignment, define class-level constants, and communicate which values are intended to remain fixed. Using final variables appropriately improves code clarity, reduces certain programming errors, and makes program behavior easier to reason about.
As you continue learning Java, practice creating local final variables, instance final fields, and static final constants. Pay special attention to the difference between a final reference and an immutable object, because this distinction is important when working with arrays and other reference types.
To continue learning, explore the Core Java Training Course, register through the JustAcademy course demo page, or visit the JustAcademy website.