【问题标题】:Java & Compile-Time ConstantsJava 和编译时常量
【发布时间】:2011-12-28 12:04:34
【问题描述】:

Java 编译器是否会将在定义时分配值的基元或 String 类型的 static final 变量视为 REAL 编译时常量?
会这样的变量获得了编译常量在其他语言中的性能奖励,比如 C++?

原始值或String 值的枚举是否被编译器视为常量?

据我了解,用常量替换变量总是好的当它不影响脚本的工作时所以我想知道java中const关键字的空含义.
提前致谢。

【问题讨论】:

标签: java performance constants


【解决方案1】:

是的,它们是编译时常量。比如代码

private static final boolean DEBUG = false;

...

if (DEBUG) {
   // some code
}

将被编译为字节码,它甚至不包含if 中的代码。它将被编译器删除。

如果您决定更改其值,则必须重新编译所有引用该常量的类。

但是请注意,它只是不能修改的引用。对象的内容(如果它是可变的),可以更改。例如,以下代码中的数组或StringBuilder的内容可能会被修改:

// don't do this:
public static final String[] seasons = new String[] {"Spring", "Summer", "Autumn", "Winter"};
public static final StringBuilder someBuffer = new StringBuilder("foo");

您关于枚举的问题没有意义。没有原始或字符串的枚举。每个枚举都定义了自己的类。

【讨论】:

  • 好吧,有多少类可以引用私有静态final? ;-)
  • 嗯,从技术上讲,很多:定义它的类及其所有内部类:-)
  • 在任何情况下枚举都可以是编译时常量吗?
  • 没有。如果枚举是编译时常量,您希望它们如何处理?
  • 我的意思不仅仅是编译时常量,只是询问它们是否可以。
【解决方案2】:

Java 编译器并没有进行太多优化,但它确实对最终原语进行了常量表达式评估,并对字符串和枚举进行了一些常见的优化。这是否是一件好事是相当主观的。例如假设您在库中有一个常量

public static final int MY_CONST = 1;

这将被内联。但是,如果您尝试在代码中或使用反射的运行时更改它,除非您重新编译依赖它的所有内容,否则这将不起作用。鉴于大多数 Java 都有动态延迟链接,这很容易被遗忘并在一定程度上破坏了动态链接。

恕我直言,如果他们今天再次设计编译器,他们不会做这个优化,而是让 JIT 做这个。

【讨论】:

  • 这可能在闭源项目中得到了适当的使用——一些使逆向工程更容易的仅调试代码将永远不会出现在编译的 .jar 文件中,例如...
【解决方案3】:

const 关键字未在 java 中使用。在创建语言时,它作为保留关键字被搁置一旁,但并未实现。

枚举和预定义的字符串值如下:

String foo = "foo";

被认为是编译时常量,它们被赋值且不可变。

您可以在 Java 语言规范中阅读有关编译时常量的更多信息:

http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#5313

【讨论】:

猜你喜欢
  • 2012-02-23
  • 1970-01-01
  • 2011-11-25
  • 2011-12-26
  • 1970-01-01
  • 1970-01-01
  • 2018-11-13
相关资源
最近更新 更多