2012-08-15 68 views
3

String a = "abc";
String b = "xyz";
String result = a + b;字符串存储器分配使用+运算

我想知道如果“结果”的字符串是在串池中字符串常量分配的内存或堆上创建一个新对象。

我知道新的字符串()上堆和字符串常量像创建对象,B在PermGen的串池空间上面的例子。

+2

结果是什么==“abcxyz”return?这应该给你一个关于答案的暗示。 – Scorpion 2012-08-15 14:09:58

回答

7

的重要说明:

String a = "abc"; 
String b = "xyz"; 
String result = a + b; 

相同

// creates a number of objects. 
String result = new StringBuilder().append(a).append(b).toString(); 

final String a = "abc"; 
final String b = "xyz"; 
String result = a + b; 

String result = "abcxyz"; // creates no new objects. 
+0

换句话说,由于变量是'final',因此可以对其进行优化,并且Java编译器足够聪明,可以在编译时进行串联。 – Jesper 2012-08-15 14:15:31

+0

正确,它是'javac'执行的少数优化之一。第一个示例可能会在每次运行时创建3-5个对象,第二个示例不会创建任何对象。 – 2012-08-15 14:19:53

+0

了解。但看起来如果我想动态地使用a + b(不知道a和b的值),那么它确实创建了很多对象(由StringBuilder()创建),如果它在循环内部会更糟。 – 2012-08-15 14:32:04

2

如果编译和反编译代码,它会给下面的结果:

String result = new StringBuilder().append(a).append(b).toString(); 
0

在一个StringBuilder分配的级联结果来创建连接字符串。

来源:

public class Hello { 

    public static final String CONST1 = "cafe"; 
    public static final String CONST2 = "babe"; 

    public static void main(String[] args){ 
     String a = "abc"; 
     String b = "xyz"; 
     String result = a + b; 

     String result2 = CONST1 + CONST2; 
    } 
} 

通过javap的拆解:

public class Hello extends java.lang.Object{ 
public static final java.lang.String CONST1; 

public static final java.lang.String CONST2; 

public Hello(); 
    Code: 
    0: aload_0 
    1: invokespecial #1; //Method java/lang/Object."<init>":()V 
    4: return 

public static void main(java.lang.String[]); 
    Code: 
    0: ldc  #2; //String abc 
    2: astore_1 
    3: ldc  #3; //String xyz 
    5: astore_2 
    6: new  #4; //class java/lang/StringBuilder 
    9: dup 
    10: invokespecial #5; //Method java/lang/StringBuilder."<init>":()V 
    13: aload_1 
    14: invokevirtual #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 
    17: aload_2 
    18: invokevirtual #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 
    21: invokevirtual #7; //Method java/lang/StringBuilder.toString:()Ljava/lang/String; 
    24: astore_3 
    25: ldc  #8; //String cafebabe 
    27: astore 4 
    29: return 

} 

你可以看到在第10行的StringBuilder分配串联字符串ab。通知CONST1和CONST2的串联由编译器在线路25处理所以,如果你的字符串是final它不会导致StringBuilder分配