1
static final String memFriendly = "Efficiently stored String";
System.out.println(memFriendly);
2
System.out.println("Efficiently stored String");
Java编译器会以同样的方式处理这些(1和2)吗?
仅供参考:有效地,我指的是运行时内存利用率以及代码执行时间。例如第一种情况可以在堆栈上加载变量memFriendly吗?
答案 0 :(得分:14)
每个字符串文字都是一个参考 (§4.3)实例(§4.3.1,§12.5) String类(第4.3.3节)。串 对象具有常量值。串 文字 - 或者更一般地说,字符串 这是常数的值 表达式(§15.28) - 实际上是“实习” 至于共享唯一的实例,使用 方法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
答案 1 :(得分:5)
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
看起来第二个字符串正在存储,而第一个字符串只是直接传递给方法。
这是使用Eclipse的编译器构建的,这可以解释我的答案和McDowell的差异。
更新:以下是hola
被声明为final
的结果(结果为无aload_1
,如果我正在读取此权利则意味着正如您所料,这个String既存储又内联:
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
答案 2 :(得分:3)
在这种情况下,编译器将处理两者。
无论何时在编译时定义String,Java都将优化字符串的存储。
如果在运行时定义了字符串,则Java无法进行相同的验证。
答案 3 :(得分:-2)
您拥有的代码是等效的,因为字符串文字会由编译器自动实现。
如果你真的关心字符串性能并且会反复使用相同的字符串,那么你应该看一下字符串类的intern方法。
http://java.sun.com/javase/6/docs/api/java/lang/String.html#intern()