You do not have to use final
, but the final
is making clear to everyone else - including the compiler - that this is a constant, and that's the good practice in it.
Why people doe that even if the constant will be used only in one place and only in the same class: Because in many cases it still makes sense. If you for example know it will be final during program run, but you intend to change the value later and recompile (easier to find), and also might use it more often later-on. It is also informing other programmers about the core values in the program flow at a prominent and combined place.
An aspect the other answers are missing out unfortunately, is that using the combination of public final
needs to be done very carefully, especially if other classes or packages will use your class (which can be assumed because it is public
).
Here's why:
- Because it is declared as
final
, the compiler will inline this field during compile time into any compilation unit reading this field. So far, so good.
- What people tend to forget is, because the field is also declared
public
, the compiler will also inline this value into any other compile unit. That means other classes using this field.
What are the consequences?
Imagine you have this:
class Foo {
public static final String VERSION = "1.0";
}
class Bar {
public static void main(String[] args) {
System.out.println("I am using version " + Foo.VERSION);
}
}
After compiling and running Bar
, you'll get:
I am using version 1.0
Now, you improve Foo
and change the version to "1.1".
After recompiling Foo
, you run Bar
and get this wrong output:
I am using version 1.0
This happens, because VERSION
is declared final
, so the actual value of it was already in-lined in Bar
during the first compile run. As a consequence, to let the example of a public static final ...
field propagate properly after actually changing what was declared final
(you lied!;), you'd need to recompile every class using it.
I've seen this a couple of times and it is really hard to debug.
If by final
you mean a constant that might change in later versions of your program, a better solution would be this:
class Foo {
private static String version = "1.0";
public static final String getVersion() {
return version;
}
}
The performance penalty of this is negligible, since JIT code generator will inline it at run-time.
public static final String TILDE_EQUAL = "~=";
really upsets me. When can "tilde-equal" be anything other than~=
? – Avril