如果可以在编译时确定Java,则可以保证Java内联字符串常量 [英] Is Java guaranteed to inline string constants if they can be determined at compile time

查看:194
本文介绍了如果可以在编译时确定Java,则可以保证Java内联字符串常量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑这种情况:

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

通常你会期望编译器内联ONE和两个常数。但是,这种行为有保证吗?你可以在类路径中没有Class1的运行时Class2部署,并期望它无论编译器如何工作,或者这是一个可选的编译器优化?

Typically you would expect the compiler to inline the ONE and TWO constants. However, is this behavior guaranteed? Can you deploy at runtime Class2 without Class1 in the classpath, and expect it to work regardless of compilers, or is this an optional compiler optimization?

编辑:为什么在地球上做这个?好吧,我有一个常量,它将在应用程序的两端(客户端和服务器通过RMI)之间共享,在这种特殊情况下将常量放在一个只能位于该除法的一侧的类上是非常方便的(因为它在逻辑上是拥有该常量值的那个而不是将它放在任意常量类中,因为它需要由代码的两端共享。在编译时它的所有一组源文件,但在构建时它被包分开。

Why on earth do this? Well I have a constant that would be shared between two ends of an application (client and server over RMI) and it would be very convenient in this particular case to put the constant on a class that can only be on one side of that divide (as it is logically the one that owns that constant value) rather than have it in an arbitrary constants class just because it needs to be shared by both sides of the code. At compile time its all one set of source files, but at build time it is divided by package.

推荐答案

它保证是作为常量表达式处理,并保证由 JLS第15.28节

It's guaranteed to be treated as a constant expression, and guaranteed to be interned by section 15.28 of the JLS:


编译时常量表达式是
表达式
原始类型的值或者
的字符串突然不完整,仅使用以下内容组成

A compile-time constant expression is an expression denoting a value of primitive type or a String that does not complete abruptly and is composed using only the following:


  • 原始类型的文字和String类型的文字(§3.10.5)

  • 转换为基本类型并转换为类型String

  • 一元运算符+, - ,〜,和! (但不是++或 - )

  • 乘法运算符*,/和%

  • 加法运算符+和 -

  • ...

  • Literals of primitive type and literals of type String (§3.10.5)
  • Casts to primitive types and casts to type String
  • The unary operators +, -, ~, and ! (but not ++ or --)
  • The multiplicative operators *, /, and %
  • The additive operators + and -
  • ...

...


String
类型的编译时常量始终是interned,以便使用
方法共享
唯一实例String.intern。

Compile-time constants of type String are always "interned" so as to share unique instances, using the method String.intern.

现在,这并不能说它保证内联。但是,规范的第13.1节说:

Now, that doesn't quite say it's guaranteed to be inlined. However, section 13.1 of the spec says:


对常量
变量(§4.12.4)的字段的引用已解决在
编译时间到表示的常量值
。这个
a常量字段的引用不应该出现在
二进制文件中的代码中(
除了包含
常量字段的类或接口,其代码为$ b) $ b来初始化它),这样的常量
字段必须总是看起来是
初始化;这种字段类型的默认初始值
必须永远不会被观察到

References to fields that are constant variables (§4.12.4) are resolved at compile time to the constant value that is denoted. No reference to such a constant field should be present in the code in a binary file (except in the class or interface containing the constant field, which will have code to initialize it), and such constant fields must always appear to have been initialized; the default initial value for the type of such a field must never be observed.

换句话说,即使表达式本身不是常量,也不应该引用 Class1 。所以,是的,你没事。这不是必然保证在字节码中使用连接值,但前面引用的位保证连接值被实现,所以我非常惊讶如果它不只是内联连接值。即使没有,你也可以保证在没有 Class1 的情况下工作。

In other words, even if the expression itself weren't a constant, there should be no reference to Class1. So yes, you're okay. That doesn't necessarily guarantee that the concatenated value is used in the bytecode, but the bits referenced earlier guarantee that the concatenated value is interned, so I'd be hugely surprised if it didn't just inline the concatenated value. Even if it doesn't, you're guaranteed that it'll work without Class1.

这篇关于如果可以在编译时确定Java,则可以保证Java内联字符串常量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆