?Java supports the use of various types of literals, such as integers (5, 2), floating point numbers (2.5, 6.022e+23), characters ('a', '\n'), booleans ('true', 'false'), and strings ("Hello\n"). Extensive use of literals within a program can lead to two problems: first, the meaning of the literal is often obscured or unclear from the context (from which they derive the name "magic numbers"), and second, changing a frequently-used literal requires the entire program source code to be searched for occurances occurrences of that literal, creating possible error sources if some of the occurances of the literal occurrences are overlooked.
A solution to this problem is to declare meaningfully-named constants at the start of the program whose values are set equal as class variables. Their values should be set to the desired literals, and to refrence one should reference these constants throughout the program rather than planting the literals themselves throughout the program. The advantages to this approach are that the constant's name can clearly indicate the its meaning or intended use of the constant, and should the constant need to be changed, this its declaration can be accomplished simply by editing the constant declaration modified without having to search the entire code for all uses of itits occurrences.
final
The final
keyword in Java is used to declare constants. Its effect is to render the affected variable immutable. Attempting to change the value of a final
-qualified variable results in a compile-time error. Since constants cannot be changed, it is desirable to define only one instance of them for the class; hence constants should be declared with the static
modifier as well.
The following code fragment demonstrates the use of static
and final
to create a constant:
Code Block |
---|
private static final int SIZE=25;
|
This code declares the value SIZE to be of type int
and to have store the immutable value 25. This constant can subsequently be used whenever wherever the value 25 would be is needed.
Although final
is useful more often safe for creating compile time immutable constants, its use can lead to other problemshas a few caveats when dealing with mutable data. See OBJ03-J. Be careful about final reference for more details.
...
The following noncompliant code snippet calculates various dimensions of a sphere, given its radius.
Code Block | ||
---|---|---|
| ||
double area(double radius) { return 12.56*radius*radius; } double volume(double radius) { return 4.19*radius*radius*radius; } double greatCircleCircumference(double radius) { return 6.28*radius; } |
The methods use the seemingly-random literals 12.56, 4.19, and 6.28 to represent various scaling factors used to calculate these dimensions. Someone reading this code would have no idea how they were generated or what they meant, and would therefore be unable to understand the function of this code.
...
Code Block | ||
---|---|---|
| ||
double area(double radius) { return 4.0*3.14*radius*radius; } double volume(double radius) { return 4.0/3.0*3.14*radius*radius*radius; } double greatCircleCircumference(double radius) { return 2*3.14*radius; } |
The code uses the literal "3.14" to represent the value pi. Although this removes some of the ambiguity from the literals, it complicates code maintenance. If the programmer were to decide that a more - precise value of pi
was needed is desired, he would need to find all occurances occurrences of "3.14" in the code and replace them.
...
In this compliant solution, a constant PI is first declared and set equal initialized to 3.14, and is thereafter referenced in the code whenever wherever the value of pi
is needed.
Code Block | ||
---|---|---|
| ||
private static final int PI = 3.14; double area(double radius) { return 4.0*PI*radius*radius; } double volume(double radius) { return 4.0/3.0*PI*radius*radius*radius; } double greatCircleCircumference(double radius) { return 2*PI*radius; } |
This both clarifies the code and allows easy editingreduces clutter and promotes maintainability, for if a different value for pi is required, the programmer can simply redefine the constant.
Compliant Solution: Predefined Constants
JavaThe class java.lang.Math
defines a large set of numeric constants, such as java.lang.Math. PI
and java.lang.Math.the exponential constant E
. If such constants exists, it is preferable to use them , rather than redefining the constant yourselftheir values.
Code Block | ||
---|---|---|
| ||
double area(double radius) { return 4.0*Math.PI*radius*radius; } double volume(double radius) { return 4.0/3.0*Math.PI*radius*radius*radius; } double greatCircleCircumference(double radius) { return 2*Math.PI*radius; } |
Exceptions
The use of symbolic constants should be restricted to cases where they improve the readability and maintainability of the code. Using them when the intent of the literal is obvious, or where the literal is not likely to change, can impair code readability. In the Compliant Solution above, the values 4.0 and 3.0 in the volume calculation are clearly scaling factors used to calculate the circle volume, and as such are not subject to change (unlike pi
, they can be represented exactly, so ; there is no reason to change them to increase precision). Hence, replacing them with symbolic constants would be inappropriate.
...
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Other Languages
This rule appears in the C++ Secure Coding Standard as DCL06-CPP. Use meaningful symbolic constants to represent literal values in program logic and in the C Secure Coding Standard as DCL06-C. Use meaningful symbolic constants to represent literal values in program logic.
...