4

这更像是一个理论问题而不是解决方案问题,所以请听我说。

在 C/C++ 和 PHP 中,您可以声明常量。通常有几种方法可以做到这一点(#DEFINE例如,或' const type'......),其最终效果是在编译期间完成替换,以便所有这些命名常量都变为文字。这很有帮助,因为不必访问内存位置来查找数据,而是将数据硬编码在其中,但没有硬编码的缺点 - 如果需要重用,则调用该值,并在该值时更改该值的所有实例需要改变。

但是 Java 的final声明有点不可思议。因为我可以使用未设置的最终变量创建一个类并在构造时初始化它们,这意味着据我所知它们没有被预编译为文字。除了保证它们在构造后不能在逻辑上改变之外,final声明是否对效率有任何好处?

对文章的引用很好,只要您记下解释final真正起作用的部分以及除了在构造后停止值更改之外它的好处是什么。

作为推论,除了简单地使用文字之外,是否有可能以任何其他方式在 Java 中实际声明编译级常量(无论如何都是个坏主意?)

4

4 回答 4

5

Java 确实有常量表达式。请参阅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).

但在 Java 中,与 C/C++ 不同,您还拥有 JIT 编译器,因此可以进行额外的内联。所以底线是,在你看到真正的性能问题之前不要担心。

于 2012-09-12T15:27:07.037 回答
4

Java 确实有一些常量,Java 编译器将在编译时将其替换为它们的值。例如,属于final和属于类型的成员变量实际上是String常量,它们以这种方式被替换。(这是允许的,因为类String是不可变的)。这样做的后果之一是,如果您更改源代码中的字符串,但不重新编译使用该字符串的类,这些类将看不到该字符串的新值。

JLS 在以下段落中对此进行了解释:

4.12.4final变量

13.4.9final字段和常量

于 2012-09-12T15:37:23.460 回答
2

最终字段旨在制作不可变对象。

静态最终字段是您的常量

编译器优化、数据流分析在某种程度上发生。尝试使用 javap 来查看 jvm 字节码 - 如果您对此感兴趣的话。

于 2012-09-12T15:38:57.620 回答
1

最后的声明对效率有什么好处吗?

并不真地。这是因为 JIT 通常可以确定该值在运行时没有更改,并且可以将其视为最终值。(如果值不是 volatile 并且在另一个线程中更改,这是一个问题)

在 Java 8 中,如果可以将局部变量设为 final,则可以在闭包中使用它们,而不必将它们声明为 final。

于 2012-09-12T15:39:58.217 回答