Java字符串常量池 - 创建的对象数

时间:2015-03-12 10:55:11

标签: java string object

以下代码将创建多少个字符串对象?

String s = "Mahendra" + "Singh" + "Dhoni";

它会在字符串池中创建4个字符串对象还是会创建更多?请详细解释。

P.S。我见过其他例子,他们只处理2个字符串对象。

编辑:我从答案中看到,在上面的情况下,只会创建一个对象。非常感谢一些非常好的建议。很抱歉问一个愚蠢的问题,但是你可以在下面的情况下告诉你将创建多少个对象吗?

String s = "Mahendra";
s = s + "Singh" + "Dhoni";
第二次编辑:再次抱歉,但我还有一些疑问。我在评论中看到,在上面的例子中,将创建3个对象" Mahendra"," SinghDhoni"和#34; MahendraSinghDhoni"。 我的疑问不应该从左到右计算。我错过了什么 - 概念明智吗?请帮忙。

另外,在另一种情况下,如果我扭曲这个问题,对象的数量将如何变化。我正在详细询问这一点,以便为很多同事清除它。所有的帮助表示赞赏。

String s = "Singh";
s = "Mahendra" + s + "Dhoni";

3 个答案:

答案 0 :(得分:5)

如果你的代码是:

public static void main(String[] args) {
    String s = "Mahendra" + "Singh" + "Dhoni";
    System.out.println(s);
}

查看字节代码:

 public static void main(java.lang.String[]);
   descriptor: ([Ljava/lang/String;)V
   flags: ACC_PUBLIC, ACC_STATIC
   Code:
     stack=2, locals=2, args_size=1
        0: ldc           #16                 // String MahendraSinghDhoni --> This line
        2: astore_1
        3: getstatic     #18                 // Field java/lang/System.out:Ljav
/io/PrintStream;
        6: aload_1
        7: invokevirtual #24                 // Method java/io/PrintStream.prin
ln:(Ljava/lang/String;)V
       10: return

如您所见,编译器在编译期间添加所有三个字符串 。因此 String常量池上只有只有一个字符串

编辑:根据编辑过的问题:

"Singh" + "Dhoni"将在编译时期间添加。所以总共会有3个String对象。 "Mahendra""SinghDhoni"将位于字符串常量池上,然后 mahendraSinghDhoni将位于

答案 1 :(得分:1)

这将在字符串池中仅创建1个字符串。请阅读差异bwt String对象和文字,它将帮助您理解。

答案 2 :(得分:1)

这是编译器进行优化的特殊条件。 不同的编译器可以进行不同的优化。 以下是可能发生的事情:

方案1

编译器查看已知值的字符串连接。如果值未在其他位置使用,则可以使用最终字符串替换串联,因此

String concatenation = "a" + "b" + "c";

编译为

的等效字节代码
String concatenation = "abc";

在这种情况下,您只需创建一个字符串。

方案2

在一定数量的字符串连接中,编译器可以决定用StringBuilderStringBuffer替换它们。 所以

String a;
String b;
String c;
String d;
String e;

// Initialization and use of a, b, c, d, e
String concat = a + b + c + d + e;

被编译为以下java代码的等效字节码:

String a;
String b;
String c;
String d;
String e;

// Initialization and use of a, b, c, d, e

String concat = new StringBuilder(a).append(b).append(c).append(d).append(e).toString();

在这种情况下,您将创建6个字符串:a,b,c,d,e,以及从+ b + c + d + e获得的字符串

方案3

如果StringBuilder的创建不方便,编译器可以应用正常的字符串连接,所以下面的代码

String a;
String b;
String c;


// Initialization and use of a, b, c
String concat = a + b + c;

编译为等效于以下java代码的字节码

String a;
String b;
String c;


// Initialization and use of a, b, c
String concat = a.concat(b).concat(c);

以下是concat代码的java实现:

public String concat(String str) {
    int otherLen = str.length();
    if (otherLen == 0) {
        return this;
    }
    char buf[] = new char[count + otherLen];
    getChars(0, count, buf, 0);
    str.getChars(0, otherLen, buf, count);
    return new String(0, count + otherLen, buf);
}

正如您在concat的最后一行所看到的,为每个连接创建了一个新的String。在这种情况下,您将创建5个字符串:a,b,c,a + b和a + b + c

注意:任何不同的编译器都可以选择从源代码到编译代码的不同内部优化。您需要知道的是,在最坏的情况下,每个起始字符串将生成1个字符串,每个连接将生成1个字符串(每个+)。因此,如果您有3个字符串与2个连接操作连接,则最多可创建5个字符串。