如果字符串连接使用 +是使用 StringBuilder 实现的,那么为什么在串联过程中会创建额外的对象呢?

发布于 2024-10-02 08:31:48 字数 236 浏览 5 评论 0原文

如果以下代码:

String s = "a" + 1 + "b";// 1.

使用 using StringBuilder 实现相当于

String s = new StringBuilder().append("a").append(1).append("b");

那么会在 1 中创建额外的对象“a”和“b”,为什么?

If the following code:

String s = "a" + 1 + "b";// 1.

Is implemented using using StringBuilder equivalent to

String s = new StringBuilder().append("a").append(1).append("b");

then will extra objects "a" and "b" be created in 1 and why?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

多情出卖 2024-10-09 08:31:48

您的示例实际上不会使用 StringBuilder,因为所有元素都不是变量。因为“a”、1 和“b”都是文字,所以编译器将为您生成一个 String!但是,如果您在该 String 连接中包含一个变量,那么它将使用 StringBuilder 并且需要单独的 String 来存储连接的元素。

对于您的示例,编译器将创建单个字符串文字:

const #2 = String       #21;    //  a1b

public void foo();
  Code:
   Stack=1, Locals=2, Args_size=1
   0:   ldc     #2; //String a1b
   2:   astore_1
   3:   return
  LineNumberTable: 
   line 7: 0
   line 8: 3

假设我们改为编写

public void bar(String c)
{
    String s = "a" + c + "b";// 1.
}

现在编译器需要创建一个 StringBuilder,并且它将使用 a 和 b 常量 ASCII 文字以及 StringBuilder

const #20 = Asciz       a;
const #22 = Asciz       b;

public void bar(java.lang.String);
  Code:
   Stack=2, Locals=3, Args_size=2
   0:   new     #2; //class java/lang/StringBuilder
   3:   dup
   4:   invokespecial   #3; //Method java/lang/StringBuilder."<init>":()V
   7:   ldc     #4; //String a
   9:   invokevirtual   #5; //Method java/lang/StringBuilder.append:(Ljava    /lang/String;)Ljava/lang/StringBuilder;
   12:  aload_1
   13:  invokevirtual   #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   16:  ldc     #6; //String b
   18:  invokevirtual   #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   21:  invokevirtual   #7; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
   24:  astore_2
   25:  return
  LineNumberTable: 
   line 7: 0
   line 8: 25

Your example will not actually use a StringBuilder because none of the elements are variables. Because "a", 1, and "b" are all literals, the compiler will make a single String for you! If, however, you included a variable in that String concatenation, then it would use a StringBuilder and would need separate Strings for the concatenated elements.

For your example the compiler would create a single String literal:

const #2 = String       #21;    //  a1b

public void foo();
  Code:
   Stack=1, Locals=2, Args_size=1
   0:   ldc     #2; //String a1b
   2:   astore_1
   3:   return
  LineNumberTable: 
   line 7: 0
   line 8: 3

Let's say we had instead written

public void bar(String c)
{
    String s = "a" + c + "b";// 1.
}

Now the compiler will need to create a StringBuilder, and it will use the a and b constant ASCII literals with the StringBuilder.

const #20 = Asciz       a;
const #22 = Asciz       b;

public void bar(java.lang.String);
  Code:
   Stack=2, Locals=3, Args_size=2
   0:   new     #2; //class java/lang/StringBuilder
   3:   dup
   4:   invokespecial   #3; //Method java/lang/StringBuilder."<init>":()V
   7:   ldc     #4; //String a
   9:   invokevirtual   #5; //Method java/lang/StringBuilder.append:(Ljava    /lang/String;)Ljava/lang/StringBuilder;
   12:  aload_1
   13:  invokevirtual   #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   16:  ldc     #6; //String b
   18:  invokevirtual   #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   21:  invokevirtual   #7; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
   24:  astore_2
   25:  return
  LineNumberTable: 
   line 7: 0
   line 8: 25
很糊涂小朋友 2024-10-09 08:31:48

我假设您想知道为什么通常在字符串上使用 StringBuilder 而不是 + 运算符更有效。在您的示例中,差异可以忽略不计,但您必须考虑更大的问题,通常是由循环引起的。

以下面的代码为例:

String s = "";
for(int i = 0; i < 100000; i++) {
   s = s + "something";
}

不管你是否使用StringBuilder来优化这个+操作,你都会创建一个String对象来存储在s中。因此,每次循环迭代都会创建一个新的 String 对象,从而为您提供大量新创建的对象。

相反,如果您在循环内使用带有 sb.append("something")StringBuilder,则不需要 StringBuilder 来创建每次循环迭代的 String 对象。它可以自由地等待创建一个,直到循环后需要它为止。

I assume you are wondering why it is more efficient in general to use StringBuilder instead of the + operator on Strings. In your example, the difference is negligible, but you have to consider larger problems, usually resulting from looping.

Take for example the following code:

String s = "";
for(int i = 0; i < 100000; i++) {
   s = s + "something";
}

No matter, if you use a StringBuilder to optimize this + operation or not, you create a String object to store in s. So each loop iteration will create a new String object, giving you a huge number of newly created objects.

In contrast, if you use a StringBuilder with sb.append("something") inside the loop, the StringBuilder is not required to create a String object for each loop iteration. It can freely wait to create one, until it is required after the loop.

新雨望断虹 2024-10-09 08:31:48

我认为你有点混淆了......

对于 +-情况,在评估 " 时会创建一个额外的 "a1"-对象a" + 1(就在将 "a1""b" 连接之前)。使用 append 方法可以避免这种额外的对象创建。就这样。

"a""b" 已在编译时创建。 (这些常量文字将从一开始就存在于字符串池中。)但您可能知道,这些常量也会在 append 情况下创建。

I think you're mixing it up a bit...

For the +-case, there will be an extra "a1"-object created when evaluating "a" + 1 (right before concatenating "a1" with "b"). This extra object creation can be avoided when using the append method. Thats all.

The "a" and "b" will already be created during compile time. (Those constant literals will be present in the sting pool from the beginning.) But as you probably know, those constants will be created also in the append case.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文