Java (both the language and the JVM) are not aware of constants. To reduce confusion it’s better to not use the term “constant” in Java code, unless it’s actually a universal constant.
As programmers we need to distinguish between different types of variables:
- non-final variables: value changes over time.
- final variables: Once assigned, the value doesn’t change.
- Always the same value (constant).
- Value depends on parameters, configuration or it is pseudo-random.
This is read-only, but not constant.
The number π is a mathematical constant. But since the keyword “const” isn’t used in Java we can’t tell the compiler nor the JVM that this is a constant. Math.PI
is static final and the compiler might inline the value during compilation. That’s because the compiler knows the value (it’s a decimal number, in the JLS this is actually called a “Constant Expression“).
The compiler can just expect that any expression that is a literal (a number or quoted string) is to be treated as a constant. If the value is set in a initializer block or if it is an expression that needs to be evaluated, then it’s not really a constant.
In my post about the final keyword I explain how it is used and what it really means. It certainly doesn’t make anything a constant, as some online tutorials claim.
Another problem, when all static final fields are called constants, is that they sometimes reference a mutable object. Then the reference itself can not be changed, but the object can change. It makes little sense to claim that the field is a constant. The javadoc for String actually uses the term constant to mean immutable: Strings are constant; their values cannot be changed after they are created.
In Java you can define some static final variable and say that it is a constant. But it makes no sense to just call everything constant just because it’s static and final. The only place to say it is a constant is the javadoc for the field. If it really is a constant, then it can be helpful to other programmers if that is mentioned in the javadoc. So programmers know they can’t just change it. This is similar to how you define functions in Java. There’s no keyword for functions. It’s up to you to declare in the documentation what is a constant or a function.
Some other languages use const or a similar keyword for something that cannot be reassociated with a different value. Because of the keyword it is called a constant, even if the value actually changes with every release or if it depends on a configuration, such as the build settings.
Constants in the JLS:
The Java Language Specification doesn’t really say much about constants. But it does use the term and in some cases they actually use the term when they mean “final Variables“.
However, the JLS does recommend not using static final fields:
Other than for true mathematical constants, we recommend that source code make very sparing use of
static
constant variables.
You can read this in Chapter 13.4.9. final Fields and static Constant Variables.
So in the JLS a constant is a final variable, which has the value of a constant expression assigned to it. Final fields are constant during the compilation and the execution of the code. Just don’t forget that you need to recompile all your source code, if you change just one of those “constants”. The compiler inlines those values and so the referencing classes still have the old value. That’s why the JLS recommends using a suitable accessor method to prevent “inconstant constants”.
Enum Constants
The term is also used when it comes to enums. And simple enums usually work like constants. They do have a value. To get the value of FOO
you’d simply call FOO.ordinal()
. It returns the ordinal of this enumeration constant
. Note that the enumeration is the (ordered) set of all constants.
But enums can change. They can be mutable and you can rename them or add new constants to the enumeration. However, you really should make them immutable and you shouldn’t change them once you have defined the enumeration. So enum constants often qualify as a constants.
Checklist:
- Is it static and final? If not, then how would it be a constant?
- Is it always the same value?
- Will it be the same value tomorrow? In a billion years?
- Is it independent of any configuration and parameters?
- Is it immutable? If it isn’t a primitive (int, double, etc) it must be of immutable type. If not, then it makes no sense to say the field is a constant. The type could be String, Long, BigDecimal, LocalDate, Color etc.
Examples of Constants:
- java.lang.Math.PI:
public static final double PI = 3.14159265358979323846;
- java.lang.Double.NaN:
public static final double NaN = 0.0d / 0.0;
- java.awt.Color.white:
public final static Color white = new Color(255, 255, 255);
java.time.Month.JANUARY;
Examples of Read-Only Values (not Constants)
- Version number of application. This will change with every release.
- Values defined by a configuration file, the environment, or command line parameters. They are different for each incarnation of your application.
- Named numbers. Numbers without names are also known as magic numbers (a kind of code smell). Those should be named and in Java you’d use an enum, public final static fields, or just a final local variable. But those are usually not constants. They can be changed for a newer release of you application.
public enum MySingleton { INSTANCE = ... }
In Java singletons are often implemented as enums (c.f. Item 3). Those are not regular enumerations and the value is usually mutable. So they are not really constants.
5 thoughts on “Java knows no Constants”