Java编译器是否有效地处理内联字符串?

Mon*_*bal 4 java compiler-construction string optimization

1.

static final String memFriendly = "Efficiently stored String";
System.out.println(memFriendly);
Run Code Online (Sandbox Code Playgroud)

2.

System.out.println("Efficiently stored String");
Run Code Online (Sandbox Code Playgroud)

Java编译器会以同样的方式处理这些(1和2)吗?

仅供参考:有效地说,我指的是运行时内存利用率以及代码执行时间.例如,第一种情况可以在堆栈加载变量memFriendly上花费更多时间吗?

McD*_*ell 14

这包含在Java语言规范中:

每个字符串文字都是类String(第4.3.3节)的实例(第4.3.1节,第12.5节)的引用(第4.3节).String对象具有常量值.字符串文字 - 或者更一般地说,作为常量表达式(第15.28节)的值的字符串 - 是"实例化"以便使用String.intern方法共享唯一实例.

您也可以使用javap工具自己查看.

对于此代码:

System.out.println("Efficiently stored String");
final String memFriendly = "Efficiently stored String";
System.out.println(memFriendly);
Run Code Online (Sandbox Code Playgroud)

javap给出以下内容:

0:   getstatic     #2; //Field java/lang/System.out:Ljava/io/PrintStream;
3:   ldc       #3; //String Efficiently stored String
5:   invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
8:   getstatic     #2; //Field java/lang/System.out:Ljava/io/PrintStream;
11:  ldc       #3; //String Efficiently stored String
13:  invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
Run Code Online (Sandbox Code Playgroud)


mat*_*t b 5

public static void main(String[] args) {
    System.out.println("Hello world!");

    String hola = "Hola, mundo!";
    System.out.println(hola);
}
Run Code Online (Sandbox Code Playgroud)

以下是javap显示为此代码的反汇编:

0:   getstatic       #16; //Field java/lang/System.out:Ljava/io/PrintStream;
3:   ldc     #22; //String Hello world!
5:   invokevirtual   #24; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
8:   ldc     #30; //String Hola, mundo!
10:  astore_1
11:  getstatic       #16; //Field java/lang/System.out:Ljava/io/PrintStream;
14:  aload_1
15:  invokevirtual   #24; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
18:  return
Run Code Online (Sandbox Code Playgroud)

看起来第二个字符串正在存储,而第一个字符串直接传递给方法.

这是使用Eclipse的编译器构建的,这可以解释我的答案和McDowell的差异.

更新:如果hola声明为final结果aload_1,则结果如下(结果为否,如果我正确读取,则表示此字符串存储和内联,如您所料):

0:   getstatic       #16; //Field java/lang/System.out:Ljava/io/PrintStream;
3:   ldc     #22; //String Hello world!
5:   invokevirtual   #24; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
8:   ldc     #30; //String Hola, mundo!
10:  astore_1
11:  getstatic       #16; //Field java/lang/System.out:Ljava/io/PrintStream;
14:  ldc     #30; //String Hola, mundo!
16:  invokevirtual   #24; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
19:  return
Run Code Online (Sandbox Code Playgroud)