是Java保证联string constants如果他们能够确定在编制时间
题
考虑这样的情况:
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)都以相同的方式工作。但最重要的实现方式是可行的。
不幸的是我没有维持这个的链接:(
我怀疑,但不确定,这会起作用,但听起来不是一个好主意。
“正常”这样做的方法是:
- 将常量放在客户端和服务器之间共享的包中。据推测,有这样一个包,因为这就是接口所在的地方。
- 如果没有这样的包,请使用共享常量创建2个类:一个用于服务器,另一个用于客户端。 醇>
请参阅 JLS 13.4.9 。虽然它没有明确要求编译器内联常量,但它暗示条件编译和对 switch
语句中常量的支持会导致编译器始终内联常量。
看起来您正在编写自己的 enum
内置功能版本,它为您执行 public static final
,通过 name正确命名( )
和 toString()
(以及具有一些其他优点,但可能具有更大内存占用的缺点)。
您使用的是不包含enum的旧版Java吗?