Why we use static final in Java for constants

Ever wonder why Java's const keyword is unimplemented?

More specifically, why do we mark global constants in Java with both the static and final keywords?

Why are Java constants static and final?

The reason why global constants in Java use the static and final keywords is because final ensures a variable cannot change, while static ensures only one copy of the constant variable is placed in memory, regardless of how many class instances are created.

To new developers, the use of the keywords static and final in Java might seem unintuitive. However, there's a very object-oriented reason why the Java language describes constants this way.

Java const keyword screenshot
Use of the keyword const in Java will trigger a compile error.

Keywords const vs. final in Java

The final keyword can be considered the Java languages equivalent for const.

If a Java developer wants a variable to be constant, they mark that variable as final. A final variable in Java can't change once it's been assigned a value.

For example, the ID of your bank account might be a good example of a final variable. Once you're assigned a bank account number, you have that account number for life.

However, your bank account ID is different from mine.

The variable is constant, but every instance of a bank account has a different number. The account ID is constant on a per-account basis, but it's not the same for every account. That's how final variables work.

What is a static variable in Java?

A static variable in Java is shared by every instance of a class.

For example, a bank account might include a static variable that represents the interest rate. When the interest rate changes, it changes for every bank account. If tomorrow the interest rate on savings accounts rises from 1.5% to 2.5%, the change impacts every account.

One benefit of the static variable being shared by every instance of a class is that it is very efficient.

If the interest rate is stored as a float or a double, it occupies 32 bits of memory. If the variable is static, you can have tens of thousands of instances pointing at the same 32 bits.

If the variable is not static, each instance gets its own copy, which for tens of thousands of instances means hundreds of thousands of wasted bits.

Difference between static and final in Java

While static variables use memory very efficiently, a static variable is not constant. It can be changed at any time.

Imagine that you want a constant that is the same for every instance of a class.

To create a global constant shared by every instance of a class, you combine Java's static and final keywords. The static keyword means the value is the same for every instance of the class. Final means the variable can't change.

That's why global constants in Java use the static and final keywords.

Example of static and final in Java

Here's a static final example to further demonstrate the point. The following Account class has three properties:

  • An accountId of type int marked as final.
  • An interestRate of type double marked as static.
  • A final static variable named odLimit of type int for the overdraft limit.
class Account {
	
  public Account(int id) { accountId = id; }
	
  //const int dne;
  final int accountId;
  static double rate = 1.5;
  static final int odLimit = 1000;
	
}

Even though the accountId is marked final, each individual account is allowed to have its own unique value. The only rule is that once the value is assigned, it can never be changed:

Account first = new Account(123);
Account second = new Account(456);

// The following prints 123
System.out.println(first.accountId);
// The following prints 456
System.out.println(second.accountId);

// Next line triggers a compile error
// first.accountId = 789;

With the non- final static variable, any instance can change it, but if the value is changed it affects every instance:

first.rate=2.5;
second.interestRate=3.5;

// Both lines print out 3.5
System.out.println(first.interestRate);
System.out.println(second.interestRate);

Finally, note that the static final variable is both the same for each class and it cannot be changed after being initialized:

// Both lines print out 1000
System.out.println(first.odLimit);
System.out.println(second.odLimit);
// Next line triggers a compile error
// first.odLimit = 500;

As you can see, the terms static and final in Java have very distinct meanings:

  • The final keyword implies something cannot be changed.
  • The static keyword implies class-level scope.

When you combine static final keywords in Java you create a variable that is global to the class and impossible to change. This creates what developers from other platforms would consider the equivalent to a global, constant variable.

You can find the code used in this static final variable example on GitHub.

View All Videos