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

时间:2008-12-18 13:20:51

标签: 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";
}

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

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

6 个答案:

答案 0 :(得分:27)

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

public static final String configOption1 = "some option".intern();

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

作为替代方案,您可以随时

public static final String configOption1 = "some option".toString();

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

修改 找到另一个SO链接,提供对JLS的引用,以获取有关此内容的更多信息。 When to use intern() on String literals

答案 1 :(得分:10)

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

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

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

答案 2 :(得分:7)

实际上,如果您删除final关键字,常量将停止为编译时常量,然后您的配置将正常工作

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

答案 3 :(得分:7)

没有。您可以使用静态方法调用替换它们,例如:

class ApplicationDefs {

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

}

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

答案 4 :(得分:6)

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

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

public static final String configOption1 = null!=null?"": "some option";

答案 5 :(得分:-4)

这里没有任何内容表明这些值应该被内联。您只是声明了一些publicstatic成员。那些其他类正在使用这些成员的值。没有内联问。甚至是final关键字

但是出于性能原因,某些JVM可能内联这些其他类中的值。这是一个优化。没有优化应该改变程序的行为。因此,如果您更改这些成员的定义,JVM应取消内联之前的值。

这就是无法关闭内联的原因。 JVM没有内联且没有问题,或者如果内联,JVM保证不内联。

我不确定在静态导入此类时会发生什么。我认为(不确定)内​​联是否会执行并可能导致您提到的麻烦。如果是这种情况,你基本上可以删除静态导入,你没事。