简体   繁体   中英

Effect of Java 'final' declaration for class member variables

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?)

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.

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

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM