4

This is more of a theory question than a solution question, so hear me out.

In C/C++ as well as PHP, you can declare constants. There are usually a couple of ways to do this (#DEFINE for example, or 'const type'...) and the ultimate effect of this is that during compilation a replace is done so that all of those named constants become literals. This helps because instead of having to access a memory location to find the data, the data is hardcoded in, but without the downside of hardcoding - recalling the value if it needs to be reused, and changing all of the instances of that value when it needs to be changed.

But Java's final declaration is slightly inscrutable; because I can create a class with unset final vars and initialize them on construction, it means that they are not precompiled as literals as far as I can tell. Other than guaranteeing that they cannot logically change afte construction, does the final declaration provide any benefit to efficiency?

References to articles are fine, as long as you make note of the part which explains what final really does and what are if any its benefits other than stopping value changes after construction.

As a corollary, is it possible to actually declare compilation-level constants in Java in any other way than simply using literals (a bad idea anyway?)

  • 1
    See here: http://stackoverflow.com/questions/4279420/does-use-of-final-keyword-in-java-improve-the-performance – nolegs Sep 12 '12 at 15:29

4 Answers4

5

Java does have constant expressions. See here in the java language specification.

A compile-time constant expression is an expression denoting a value of primitive type or a String that does not complete abruptly and is composed using only the following:

Literals of primitive type and literals of type String (§3.10.5)
Casts to primitive types and casts to type String
The unary operators +, -, ~, and ! (but not ++ or --)
The multiplicative operators *, /, and %
The additive operators + and -
The shift operators <<, >>, and >>>
The relational operators <, <=, >, and >= (but not instanceof)
The equality operators == and !=
The bitwise and logical operators &, ^, and |
The conditional-and operator && and the conditional-or operator ||
The ternary conditional operator ? :
Parenthesized expressions whose contained expression is a constant expression.
Simple names that refer to constant variables (§4.12.4).
Qualified names of the form TypeName . Identifier that refer to constant variables (§4.12.4).

But in Java, unlike C/C++, you also have a JIT compiler, so additional inlining is possible. So the bottom line is, don't worry about until you see a real performance problem.

Yishai
  • 90,445
  • 31
  • 189
  • 263
  • With simulations/games, I have to start by doing it the efficient way, or I will spend more time later optimizing. At 60fps the effect can be geometric or even exponential of inefficiencies. –  Sep 12 '12 at 15:40
  • 1
    @RiverC, with the JIT compiler in java, it is really something you cannot guess without measuring. Some of your premature optimizations can actually undermine the JIT compiler and make the result slower. It's fine to not wait until the final product is done, but you need to know what functions need to be executed so many times, and run them under test and actually measure performance. – Yishai Sep 12 '12 at 15:43
  • I find the performance measurement under test to be somewhat useless, as in my experience, certain aspects end up varying too much between environments, and the actual performance is always slowed by the performance testing rig. In short, it is only good to examine orders of magnitude - i.e what parts take the most time of the total, not absolute metrics, which are always skewed by an unknown amount. –  Sep 12 '12 at 15:49
  • To make a long story short, I would like actual universal constants to be as constant as they can be - since I will probably end up having to make that optimization at the end, why not do it now? The only reason I can see is if, as you've said, my premature optimization hinders the optimization of the compiler itself. If the compiler can convert static final's into constants in actuality, then it's immaterial and I'd rather use them. –  Sep 12 '12 at 15:53
  • After reading more thoroughly, it's evident that there *aren't* constants in a meaningful sense; it is up to the compiler. This is disappointing. –  Sep 12 '12 at 16:44
4

Java does have constants that the Java compiler will replace with their values at compile-time. For example, member variables that are final and that are of type String are effectively constants which are replaced in this way. (This is allowed because class String is immutable). One of the consequences of this is that if you change the string in your source code, but you don't recompile the classes where this string is used, those classes will not see the new value of the string.

The JLS explains this in the following paragraphs:

4.12.4 final variables

13.4.9 final Fields and Constants

Jesper
  • 202,709
  • 46
  • 318
  • 350
2

Final fields are aimed to make immutable objects.

Static final fields are your kind of constants.

Compiler optimisation, data flow analysis, happens to some degree. Try javap to see the jvm byte codes - if your are interested that far.

Joop Eggen
  • 107,315
  • 7
  • 83
  • 138
  • I'd like to do something so that I don't have to rely on the compiler optimization, but rather simply do the most optimal thing immediately for certain values. –  Sep 12 '12 at 16:07
  • "Final fields are aimed to make immutable objects." No argument in principle, but I find this statement possibly misleading. It is wrong to say that just because a field is `final` that its data is immutable. Reference types indicated by `final` variables are still mutable except in the special case that the referenced object is itself immutable. – scottb Sep 25 '14 at 18:05
1

does the final declaration provide any benefit to efficiency?

Not really. This is because the JIT can often determine that the value is not changed at runtime and can treat it as final. (Which is a problem if the value is not volatile and is changed in another thread)

In Java 8, you can use local variables in closures if they could be made final, rather than having to declare them as final.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130