是否所有编译时常量都内联?
假设我有一个这样的类:
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"; }
我的应用程序中的许多其他类都使用这些选项。 现在,我想单独更改其中一个选项并仅部署已编译的类。 但是,如果这些领域在消费者类别中排列,这就变得不可能了吗?
是否有任何选项可以禁用编译时常量的内嵌?
您可以使用String.intern()来获得所需的效果,但应该注释您的代码,因为没有多少人知道这一点。 即
public static final String configOption1 = "some option".intern();
这将阻止内联编译时间。 由于它指的是编译器将在烫发中放置的完全相同的字符串,因此您不会创建额外的任何内容。
作为替代方案,您可以随时做到
public static final String configOption1 = "some option".toString();
但是这不会使用编译的实习字符串,它将在旧版本上创建一个新字符串。 这不是一个大问题,也可能更容易阅读。 无论哪种方式,因为这有点奇怪,你应该评论代码,以通知那些维护它你正在做什么。
编辑:找到另一个SO链接,提供对JLS的引用,以获取有关此内容的更多信息。 何时在String文字上使用intern()
不,这是JLS的一部分,我很害怕。 在Java Puzzlers中简要介绍了这一点,但我手头没有我的副本。
我想你可能会考虑在属性文件中定义这些常量,并让类定期加载它们。
参考: http : //java.sun.com/docs/books/jls/third_edition/html/expressions.html#5313
不可以。你可以用静态方法调用替换它们,例如:
class ApplicationDefs { public static String configOption1() { return "some option"; } }
当然,它并不漂亮,但它可以满足您的要求。 🙂
实际上,如果删除final
关键字 ,常量将不再是编译时常量,那么您的配置将按您的意愿工作 。
但是,强烈建议如果这确实是您尝试的某种配置,那么您应该采用比某些类文件中的常量更易于管理的方式。
您可以通过使您的常量非编译时间常量来禁止内联…
例如, null
不是编译时常量。 任何涉及非编译时间常量的表达式都不是编译时常量,尽管javac可以在编译单元中进行常量折叠。
public static final String configOption1 = null!=null?"": "some option";
这里没有任何内容表明这些值应该被内联。 您只是宣布一些public
static
成员。 那些其他类正在使用这些成员的值。 没有内联问。 即使是final
关键字
但出于性能原因 ,一些JVM可能会在其他类中内联这些值。 这是一个优化。 没有优化应该改变程序的行为。 因此,如果更改这些成员的定义,JVM应该取消内联先前的值。
这就是为什么没有办法改变内联的原因。 JVM没有内联且没有问题,或者如果内联,JVM保证取消内联。
我不确定当你静态导入这个类时会发生什么。 我认为(不确定)是否已执行内联并可能导致您提到的麻烦。 如果是这种情况,你基本上可以删除静态导入,你没问题。