Core Java: Static and Final Keywords in Java
Now let’s talk about two important keywords in Java:
staticfinal
They are used for very different purposes.
The easiest way to remember them is:
static→ belongs to the class
final→ cannot be changed further
Static Keyword
The static keyword is used when something should belong to the class rather than to individual objects.
Normally, when we create objects, every object gets its own copy of instance variables.
For example:
class Student { String name;
int age;
}If we create two students:
Student s1 = new Student();
Student s2 = new Student();s1.name = "Aishu";
s2.name = "Rahul";Both objects have their own name.
s1 → name = Aishu
s2 → name = RahulChanging s1.name does not affect s2.name.
But sometimes we want a value that is common to all objects.
That’s where static comes in.
Static Variable
A static variable belongs to the class, not to individual objects.
For example, suppose every student belongs to the same school:
class Student { String name;
static String school = "ABC School";
}Now:
Student s1 = new Student();
Student s2 = new Student();s1.name = "Aishu";
s2.name = "Rahul";Both students share the same school variable.
We should access it using the class name:
Student.schoolSo:
System.out.println(Student.school);Output:
ABC SchoolThere is only one copy of the static variable for the class, rather than one copy for every object.
What happens if we change a static variable?
This is an important point.
class Student { String name;
static String school = "ABC School";
}Now:
Student s1 = new Student();
Student s2 = new Student();Student.school = "XYZ School";Now both objects see:
XYZ Schoolbecause they are sharing the same static variable.
Conceptually:
Student Class
|
school = XYZ School
/ \
/ \
s1 s2There is one shared school variable.
Static Variables Should Be Accessed Using the Class Name
Since a static variable belongs to the class, the preferred way to access it is:
Student.schoolrather than:
s1.schoolJava technically allows accessing a static member through an object reference, but it is not recommended, because it can make it look like the variable belongs to that particular object.
Prefer:
Student.school;Static Method
We can also make methods static.
Example:
class Calculator { static int add(int a, int b) {
return a + b;
}
}We don’t need to create a Calculator object to call this method.
We can directly do:
int result = Calculator.add(10, 20);because the method belongs to the class.
Why can’t a static method directly access instance variables?
This is an important concept.
Suppose we have:
class Student {String name; static void display() {
System.out.println(name);
}
}
This will give a compilation error.
Why?
Because name is an instance variable.
Every object has its own name:
s1 → name = Aishu
s2 → name = RahulBut a static method belongs to the class.
If we call:
Student.display();Java doesn’t know:
“Which student’s
nameshould I use?"
Should it use Aishu?
Or Rahul?
There is no particular object associated with the static method call.
Therefore, a static method cannot directly access instance variables or instance methods.
It can directly access static members.
For example:
class Student {static String school = "ABC School"; static void displaySchool() {
System.out.println(school);
}
}
This works because both school and displaySchool() belong to the class.
But remember:
A static method can access an instance variable if it is given an object reference.
For example:
class Student {String name; static void display(Student student) {
System.out.println(student.name);
}
}
Here we explicitly tell the method which object to use.
Static Block
A static block is a block of code declared using the static keyword.
Example:
class Student { static {
System.out.println("Static block executed");
}
}A static block is mainly used for static initialization.
For example:
class Database {static String url; static {
url = "jdbc:mysql://localhost:3306/test";
System.out.println("Database configuration loaded");
}
}
The static block executes when the class is initialized.
When does a Static Block Execute?
A static block executes when the class is initialized by the JVM, generally before the class is used to create objects or access its static members.
For example:
class Test {static {
System.out.println("Static block");
} Test() {
System.out.println("Constructor");
}
}
Now:
Test obj = new Test();Output:
Static block
ConstructorThe static initialization happens before the constructor.
Static Block vs Constructor
This is a very important difference.
Static block
- Belongs to the class
- Runs when the class is initialized
- Generally runs once per class initialization
- Used for static initialization
Constructor
- Belongs to object creation
- Runs whenever an object is created
- Used to initialize an object
For example:
class Test {static {
System.out.println("Static block");
} Test() {
System.out.println("Constructor");
}
}
If we create two objects:
Test t1 = new Test();
Test t2 = new Test();Output will generally be:
Static block
Constructor
ConstructorThe static initialization happens once, while the constructor runs for each object.
Class.forName()
You mentioned:
Class.forName("classname");This is another interesting concept.
Get Aishu Reddy’s stories in your inbox
Join Medium for free to get updates from this writer.
Class.forName() loads a class using its fully qualified class name.
For example:
Class.forName("com.example.Student");This is commonly associated with loading and initializing a class dynamically.
One important point: Class.forName() can trigger class initialization, so static initialization code can run.
For example:
class Test { static {
System.out.println("Test class initialized");
}
}Then:
Class.forName("Test");can cause:
Test class initializedto be printed when the class is initialized.
Historically, Class.forName() was commonly used for loading JDBC drivers, although modern JDBC drivers can often be discovered automatically through the JDBC driver mechanism.
Static Nested Class
There is one important correction regarding static class.
In Java, we cannot declare a top-level class as static.
This is invalid:
static class Student {
}However, we can have a static nested class inside another class.
For example:
class Outer {static class Inner { void display() {
System.out.println("Inner class");
}
}
}
Now we can create the nested class without creating an object of Outer:
Outer.Inner obj = new Outer.Inner();obj.display();A static nested class belongs to the outer class rather than to an instance of the outer class.
Final Keyword
Now let’s talk about the final keyword.
The final keyword is used when we want something to not be changed further.
It can be used with:
- Variables
- Methods
- Classes
Final Variable
A final variable can be assigned only once.
final int age = 25;Now we cannot do:
age = 30;This gives a compilation error.
Once a final variable has been assigned a value, it cannot be reassigned.
Final Variables Without Immediate Initialization
A final variable doesn’t necessarily need to be initialized on the same line.
For example:
final int age;age = 25;This is valid as long as it is assigned exactly once before it is used.
For instance variables, such a variable is often called a blank final variable and can be initialized in a constructor.
class Student {final int id; Student(int id) {
this.id = id;
}
}
Now:
Student s1 = new Student(101);
Student s2 = new Student(102);Each object can have a different id, but once assigned, that object's id cannot be reassigned.
Final Static Variable
A very common combination is:
static finalThis is used for constants.
For example:
class Constants { static final double PI = 3.14159;
}Now we access it using:
Constants.PIBecause:
static→ belongs to the classfinal→ cannot be reassigned
By convention, constants are written in UPPERCASE:
static final int MAX_USERS = 100;Final Method
A final method cannot be overridden by a child class.
Example:
class Parent { final void display() {
System.out.println("Parent method");
}
}Now:
class Child extends Parent { void display() {
System.out.println("Child method");
}
}This will result in a compilation error because display() is final in the parent.
Why would we want this?
Because sometimes we want to make sure that a particular method’s implementation cannot be changed by subclasses.
Final Class
A final class cannot be extended.
Example:
final class Vehicle { void start() {
System.out.println("Vehicle starts");
}
}Now this is not allowed:
class Car extends Vehicle {
}because Vehicle is final.
A common example from Java is:
public final class StringThe String class is final, so we cannot create a subclass of String.
Static vs Final
These keywords solve completely different problems.
static
Answers:
“Should this belong to the class rather than each object?”
Example:
static int count;final
Answers:
“Should this value/implementation/class be prevented from changing?”
Example:
final int age = 25;Together:
static final int MAX_USERS = 100;means:
This value belongs to the class and cannot be reassigned.
One More Important Example: Static Object Counter
A very common real-world use of static is counting how many objects have been created.
class Student {static int count = 0; Student() {
count++;
}
}
Now:
Student s1 = new Student();
Student s2 = new Student();
Student s3 = new Student();System.out.println(Student.count);Output:
3Why?
Because count is shared by all objects.
Each constructor call increments the same static variable.
Student Class
|
count = 3
/ | \
/ | \
s1 s2 s3If count were not static, every object would have its own separate counter, and this approach would not work.
Final Summary
The easiest way to remember is:
static
↓
Belongs to the CLASSfinal
↓
Cannot be changed / extended / overriddenSo when you see:
static final int MAX_LIMIT = 100;you can read it as:
MAX_LIMITbelongs to the class, and its reference/value cannot be reassigned.





