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

问题描述:

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

static final String memFriendly = "Efficiently stored String"; 
System.out.println(memFriendly); 

2.

System.out.println("Efficiently stored String"); 

威尔Java编译器处理两个(1 2和)的这些相同的方式?通过高效率,我指的是运行时内存利用率以及代码执行时间。例如第一种情况可以在堆栈加载变量memFriendly上花费更多时间吗?

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

    String hola = "Hola, mundo!"; 
    System.out.println(hola); 
} 

这里是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 

外貌像第二个字符串被存储,w这里第一个直接传递给方法。

这是用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 

在这种情况下,编译器将处理两者相同。

任何时候在编译时定义一个字符串,Java都会优化字符串的存储。

如果在运行时定义字符串,则Java无法执行相同的optomization。

+0

我也相信,但我找不到具体的参考,我的意思是理论上的。谢谢 这是一篇很好的文章,但没有找到我想要的: http://muzso.hu/2009/03/05/strange-behaviour-in-java-compilers-string-concatenation-caused-by-编译时常量 – 2009-07-23 13:17:26

+0

我找不到任何特定的文章或规格,很抱歉。 – jjnguy 2009-07-23 13:21:35

您拥有的代码是平等的,因为字符串文字会被编译器自动执行。

如果你真的关心字符串性能,并且会一遍又一遍地重复使用相同的字符串,那么应该查看字符串类的实习方法。

http://java.sun.com/javase/6/docs/api/java/lang/String.html#intern()

+5

不,不,* no!*因为“性能原因”(这个词已经差不多让我吐了)实习字符串是错误的*。除非你正在做大量的字符串处理,否则它不会给你带来麻烦。 – Bombe 2009-07-23 13:27:36

+0

除了厌恶之外,你还有什么能够支持你毫无根据的要求?我给出了一个很好的理由来使用实习生,一个相同的字符串需要反复使用的情况。为什么每次都创造新的?实习生唯一的缺点是,实习生的字符串永远不会被垃圾收集。我想这就是你所抱怨的。但是如果你将在节目的整个生命周期中重复使用相同的字符串,那么每次都要实习他们,而不是创造新的。 – anio 2009-07-23 13:41:24

这被覆盖在Java Language Spec

每个字符串文字是参考 (§4.3)到一个实例(第4.3.1节,§12.5)类字符串 ( §4.3.3)。字符串 对象具有固定值。字符串 文字 - 或者更一般地说,字符串 即表达式(§15.28)的值 - 被“interned”如此 以共享唯一实例,使用 方法String.intern。

您还可以使用javap工具查看自己。

对于此代码:

System.out.println("Efficiently stored String"); 
final String memFriendly = "Efficiently stored String"; 
System.out.println(memFriendly); 

的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