Declaring Variables with var and Named Constants
A named constant is a value given a name that cannot be changed once declared, and in Java it is written as a final static member variable.
The Compiler's Limit on Constants
A named constant is a value given a name that cannot be changed once it has been declared. In Java, it is written as a final static member variable. Many learners meet this idea and assume that once a constant is declared, the whole program is automatically organized around it, with the name doing its work everywhere in the file. That assumption is understandable, but it is wrong, and the mistake it produces is quiet. The program still compiles and runs. It simply keeps using old literal numbers in places where the name was supposed to be the source of truth.
What do you think happens?
Suppose a program declares final static int SIZE = 10; and a later line in some method tries to write SIZE = 12;. What should the compiler do with that second line?
Reveal answer
The compiler rejects the second line, because a named constant cannot be changed once it has been declared.
The compiler catches a direct attempt to change a constant. It does not catch a different failure, where a number is typed into the code in place of the name. Nothing in the language tells the compiler that a literal number and a constant name are supposed to mean the same thing.
The promise a named constant makes has two sides. The first side is that the value is fixed, so no later line can quietly change it. The second side is that the name is shared, so the value can be read in many places. The language enforces the first side. The second side depends entirely on how carefully the rest of the code is written, and that is where the trouble starts.
Tracing Constants Through RandomMosaicWalk2
RandomMosaicWalk2 is a revised version of an earlier mosaic program. The new version declares named constants for the number of rows, the number of columns, and the size of each little square. The rest of the program was changed to use those names. For example, the mosaic window is opened with a statement that passes the constants rather than fixed numbers. The three names are ROWS, COLUMNS, and SQUARE_SIZE.
The same names appear in the setup code that starts the disturbance at the centre of the window, in the loops that fill every square with a random colour, and in the movement method. In the movement method, ROWS and COLUMNS decide when a disturbance that leaves one edge of the mosaic should re-enter from the opposite edge. Each of these places would need to change if the mosaic were resized, and each one stays correct only if it refers to the name.
Read this as a dependency map rather than a flow. Each named constant feeds several methods at once. This is the practical meaning of the claim that named constants help make a program more modular and maintainable. A reader can see at a glance what the program depends on, and a maintainer can change a dimension in one declaration instead of hunting through every method for the number it used to be.
Two Kinds of Named Value
A named constant is a value given a name that cannot be changed once declared. In Java it is written as a final static member variable. An ordinary variable also gives a name to a value, but it is meant to change while the program runs.
| Feature | Ordinary variable | Named constant (final static) |
|---|---|---|
| Is the value meant to change? | Yes, it can change while the program runs | No, it cannot change once declared |
| What stops an accidental change? | Nothing special; the value is expected to vary | The language rejects a direct attempt to change it |
| What keeps it consistent everywhere? | Ordinary care in the code | Ordinary care in the code, because a retyped literal is not caught |
| Typical use in RandomMosaicWalk2 | A value that is updated during the run | ROWS, COLUMNS, SQUARE_SIZE, which are fixed dimensions |
Named constants and ordinary variables both give a name to a value. The difference is whether the value is meant to change.
Where Drift Hides in the Code
The main risk is a number typed into the code in place of the name. The compiler does not know that a literal number and a constant are meant to match. So a program can declare a constant correctly and still contain a leftover literal that keeps the old value alive. The following case is an invented illustration, not part of the source program. A developer has declared ROWS as a named constant but wrote one loop with a literal number in its bound. That single leftover number makes results disagree with the declared size.
for (int r = 0; r < 20; r++) {
// fill row r
}The loop bound is a literal 20, so changing ROWS has no effect on this loop.
for (int r = 0; r < ROWS; r++) {
// fill row r
}The loop bound reads ROWS, so every change to the declaration reaches this loop.
Finding the Line Where Output Diverges
When a result diverges from what you expected, the practical method is to find the one line that still uses the old value. This is usually a literal in a loop bound or a calculation. Follow the named constant through the program and ask, at each use, whether the code reads the name or retypes the number. The first place where the number appears instead of the name is the likely source of the divergence.
Locating a Bypassed Constant
A mosaic is expected to show as many rows as ROWS declares. After the declaration is changed, the displayed grid no longer matches the new size. Where should you look?
- 1Start from the declaration
Confirm the value that ROWS currently holds, since that is the value the program should be using everywhere.
- 2List every use of the name
Find each place that refers to ROWS, such as the window setup, the centre disturbance, the fill loops, and the movement method.
- 3Check each use for a literal
At each place where a number would normally be expected, check whether the code uses ROWS or a typed number. A loop bound such as r < 20 is the kind of line that hides a leftover value.
- 4Compare the divergent line with the expected one
Once the literal is found, replacing it with ROWS should bring the output back in line with the declared size.
The line that still uses the old value is the one that is out of step with the declared constant. Replacing its literal with the name restores the single source of truth.
Planning Test Runs With Several Values
The source gives a direct habit for catching drift. Run the program with several different values for any named constant, and check that it works properly in every case. A single run with the original values cannot tell a correctly written program apart from one that hides its literal numbers behind matching defaults. Different values expose the difference, because a leftover literal stays fixed while the constant changes.
| Run | Value of ROWS | What to check |
|---|---|---|
| 1 | 20 (original) | Output matches the original expected grid |
| 2 | a smaller value | Every row count follows the new value, with no leftover 20 in any loop |
| 3 | a larger value | The movement wraparound and fill loops still cover the whole grid |
An illustrative test plan for ROWS. The second and third values are chosen by the tester.
Choose three different values for ROWS and predict, before running, which parts of the mosaic should change. Then run the program with each value. If one run shows a mismatch that the others do not, which line would you check first, and why?
Hints
- Start with the loops, since loop bounds are a common place for a leftover number.
- A run that works for one value but not another points to a literal, not to the declaration itself.
Keeping the Name in Charge
Declaring a named constant gives you one place to set a value. Getting the full benefit requires that every part of the program that needs the value refers to the name instead of retyping the number. The language protects the constant from direct change, but it cannot protect the program from a literal that stands in for the name.
Key Takeaways
- A named constant is a value given a name that cannot be changed once declared; in Java it is written as a final static member variable.
- The compiler rejects a direct attempt to change a constant, but it does not detect a literal number used in place of the constant's name.
- In RandomMosaicWalk2, ROWS, COLUMNS, and SQUARE_SIZE feed several methods, which makes the program more modular and easier to maintain.
- When output diverges, find the one line that still uses the old value, usually a literal in a loop bound or a calculation, and test several different values for each constant.