是否所有编译时常量都内联?

Sar*_*n M 22 java inlining compile-time-constant

假设我有这样一个类:

class ApplicationDefs{
public static final String configOption1 = "some option";
public static final String configOption2 = "some other option";
public static final String configOption3 = "yet another option";
}
Run Code Online (Sandbox Code Playgroud)

我的应用程序中的许多其他类都使用这些选项.现在,我想单独更改其中一个选项并仅部署已编译的类.但是,如果这些领域在消费者类中被列入,这就变得不可能了吗?

是否有任何选项可以禁用编译时常量的内嵌?

rec*_*les 27

您可以使用String.intern()来获得所需的效果,但应该注释您的代码,因为没有多少人知道这一点.即

public static final String configOption1 = "some option".intern();
Run Code Online (Sandbox Code Playgroud)

这将阻止内联编译时间.由于它指的是编译器将在perm中放置的完全相同的字符串,因此您不会创建任何额外的内容.

作为替代,你可以随时做

public static final String configOption1 = "some option".toString();
Run Code Online (Sandbox Code Playgroud)

但是这不会使用编译的实习字符串,它将在旧版本上创建一个新字符串.这不是一个大问题,可能更容易阅读.无论哪种方式,因为这有点奇怪,你应该评论代码,以通知那些维护它你正在做什么.

编辑: 找到另一个SO链接,提供对JLS的引用,以获取有关此内容的更多信息. 何时在String文字上使用intern()

  • 代码`aString.toString()`返回`aString`本身,而不是新的,因此就此问题而言,它与`intern()`一样有效.一个新的String拷贝将由很少使用的构造函数`new String(aString)`创建. (5认同)
  • 对于 `intern()` 字符串文字来说是没有用的。他们已经被“拘留”了。请参阅[此处](/sf/ask/404399201/)。 (2认同)
  • @ceving - 在这种情况下它不是无用的,因为它可以防止 `configOption1` 等被内联到其他类中。否则,如果某些其他类引用了 `configOption1`,然后您更改了常量并且不重新编译其他类,则行为将不会是您期望的(或可能想要的)。这就是 OP 问题的全部意义所在。 (2认同)

Gar*_*ryF 10

不,这是JLS的一部分,我很害怕.在Java Puzzlers中简要介绍了这一点,但我手头没有我的副本.

我想你可能会考虑在属性文件中定义这些常量,并让类定期加载它们.

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


Yuv*_*dam 7

实际上,如果删除final关键字,常量将不再是编译时常量,那么您的配置将按您的意愿工作.

但是,强烈建议如果这确实是您尝试的某种配置,那么您应该采用比某些类文件中的常量更易于管理的方式.

  • 实际上,如果删除final关键字,常量将不再是常量,它们将是变量. (9认同)

Bom*_*mbe 7

不.您可以使用静态方法调用替换它们,例如:

class ApplicationDefs {

    public static String configOption1() { return "some option"; }

}
Run Code Online (Sandbox Code Playgroud)

当然,它并不漂亮,但它可以满足您的要求.:)

  • @Yuval - 除了在您建议的答案中,变量可以由外部类更改. (6认同)

Tom*_*ine 6

您可以通过使您的常量非编译时间常量来禁止内联...

例如,null不是编译时常量.任何涉及非编译时间常量的表达式都不是编译时常量,尽管javac可以在编译单元中进行常量折叠.

public static final String configOption1 = null!=null?"": "some option";
Run Code Online (Sandbox Code Playgroud)