23

假设我有这样的课程:

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";
}

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

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

4

6 回答 6

28

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

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

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

作为替代方案,您总是可以这样做

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

但是,这不会使用已编译的实习生字符串,它将在旧版本上创建一个新字符串。没什么大不了的,可能更容易阅读。无论哪种方式,由于这有点奇怪,您应该注释代码以告知维护它的人您在做什么。

Edit: Found another SO link that gives references to the JLS, for more information on this. When to use intern() on String literals

于 2010-02-25T22:14:05.623 回答
10

不,恐怕它是 JLS 的一部分。在 Java Puzzlers 中简要地提到了这一点,但我手头没有副本。

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

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

于 2008-12-18T13:23:03.623 回答
7

实际上,如果您删除final关键字,常量不再是编译时常量,那么您的配置就会像您想要的那样工作。

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

于 2008-12-18T13:23:16.757 回答
7

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

class ApplicationDefs {

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

}

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

于 2008-12-18T13:24:34.150 回答
6

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

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

public static final String configOption1 = null!=null?"": "some option";
于 2008-12-18T14:14:35.890 回答
-4

这里没有说这些值应该被内联。您只是在声明一些public成员static。那些其他类正在使用这些成员的值。不要求内联。就连final关键词

但是出于性能原因,一些 JVM 可能会将这些值内联到其他类中。这是一个优化。任何优化都不应该改变程序的行为。因此,如果您更改这些成员的定义,JVM 应该取消内联以前的值。

这就是为什么无法关闭内联的原因。要么JVM不内联,没有问题,要么内联,JVM保证不内联。

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

于 2008-12-18T13:38:46.493 回答