考虑这样的情况:

public Class1 {
   public static final String ONE = "ABC";
   public static final String TWO = "DEF";
}

public Class2 {

  public void someMethod() {
    System.out.println(Class1.ONE + Class1.TWO);
  }
}

通常,你会期望在编译器内联的一个和两个常数。然而,这种行为的保证?你可以部署在运行时2级,而不1级的类路径,并期望它的工作无论编译器,或者这是一个可选编译器优化?

编辑:为什么地球上这样做?嗯,我有一个恒定的,将以共享之间的两端应用程序(客户和服务器在马绍尔群岛共和国),这将会非常方便地在这个特定的情况下把常的一类,只能在一边的划分(因为这在逻辑上是一个拥有这一恒定值),而不是在一个任意的常数类仅仅是因为它需要共享,双方的代码。在编制时间,它的所有一定的源文件,但在建立时,它是分包。

有帮助吗?

解决方案

它保证到被视为一个恒的表达,并保证被拘留过 部分15.28的捷尔思:

编译时间常数表达式 表表示值的 基本类型或一串,不 不完整的突然和组成 只使用如下:

  • 文本的基本类型,并文本的类型字符串(§3.10.5)
  • 转换到基本类型和铸型字符串
  • 这一元的运营商+,-,~,!(但不++或者...)
  • 乘法运算符*、/和%
  • 添加剂的运营商和
  • ...

...

编译时间常数类型字符串 总是"拘留",以分享 唯一的实例,使用的方法 String.实习生。

现在,不太说这是保证内联。但是,第13.1节的规格说:

提到田恒 变量(§4.12.4)解决 编译时间到恒定值 这就是表示。没有提到这样的 恒定领域应该存在 代码以二进制文件(除了在 类或接口含有 恒定的领域,这将有代码 初始化),而这样的恒 领域必须始终似乎已经 初始化;默认的初始价值 对于这种类型的这样一个领域必须 从来没有得到遵守。

换句话说, 即使表达自身是不是一定, 应该没有参考 Class1.所以,是的,你没事。那不 一定是 确保连接的价值是使用在码,但位被引用的先前的保证,连接价值的被拘留,所以我会 巨大的 感到惊讶,如果它不仅连接的内联价值。甚至如果它不,你保证,它将工作没有 Class1.

其他提示

使用javac 1.6.0_14进行编译会生成以下字节码:

public void someMethod();
  Code:
   0:   getstatic       #2; //Field java/lang/System.out:Ljava/io/PrintStream;
   3:   ldc     #3; //String ABCDEF
   5:   invokevirtual   #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   8:   return

因此字符串在编译时连接,结果包含在Class2的常量池中。

它不会被编译器内联,而是由运行时的解释器内联,如果可能的话转换为汇编代码。

无法保证,因为并非所有解释器(JVM)都以相同的方式工作。但最重要的实现方式是可行的。

不幸的是我没有维持这个的链接:(

我怀疑,但不确定,这会起作用,但听起来不是一个好主意。

“正常”这样做的方法是:

  1. 将常量放在客户端和服务器之间共享的包中。据推测,有这样一个包,因为这就是接口所在的地方。
  2. 如果没有这样的包,请使用共享常量创建2个类:一个用于服务器,另一个用于客户端。

请参阅 JLS 13.4.9 。虽然它没有明确要求编译器内联常量,但它暗示条件编译和对 switch 语句中常量的支持会导致编译器始终内联常量。

看起来您正在编写自己的 enum 内置功能版本,它为您执行 public static final ,通过 name正确命名( ) toString()(以及具有一些其他优点,但可能具有更大内存占用的缺点)。

您使用的是不包含enum的旧版Java吗?

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top