简体   繁体   English

Java'final'声明对类成员变量的影响

[英]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. 在C / C ++和PHP中,您可以声明常量。 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. 通常有两种方法可以做到这一点(例如#DEFINE ,或' const type '......),这样做的最终效果是在编译期间完成替换,以便所有这些命名常量都成为文字。 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; 但Java的final声明有点难以理解; 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? 除了保证他们不能在逻辑上改变建筑后, final声明是否为效率提供了任何好处?

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. 参考文章是好的,只要你记下解释final真正做什么的部分,除了在施工后停止价值变化之外还有什么好处。

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中声明编译级常量(无论如何都是一个坏主意?)

Java does have constant expressions. Java确实有常量表达式。 See here in the java language specification. 这里的Java语言规范。

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. 但是在Java中,与C / C ++不同,您还有一个JIT编译器,因此可以进行额外的内联。 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. Java确实具有Java编译器在编译时将用其值替换的常量。 For example, member variables that are final and that are of type String are effectively constants which are replaced in this way. 例如, final成员变量和String类型的成员变量实际上是以这种方式替换的常量。 (This is allowed because class String is immutable). (这是允许的,因为类String是不可变的)。 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: JLS在以下段落中解释了这一点:

4.12.4 final variables 4.12.4 final变量

13.4.9 final Fields and Constants 13.4.9 final字段和常量

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. 尝试使用javap查看jvm字节代码 - 如果您对此感兴趣那么远。

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. 这是因为JIT通常可以确定该值在运行时未更改,并可将其视为最终值。 (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. 在Java 8中,如果可以将闭包中的局部变量设置为final,则可以使用它们,而不必将它们声明为final。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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