Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如果使用+;是使用StringBuilder实现的,那么为什么在连接过程中会创建额外的对象呢?_Java_String_Stringbuilder - Fatal编程技术网

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

Java 如果使用+;是使用StringBuilder实现的,那么为什么在连接过程中会创建额外的对象呢?,java,string,stringbuilder,Java,String,Stringbuilder,如果输入以下代码: String s = "a" + 1 + "b";// 1. String s = ""; for(int i = 0; i < 100000; i++) { s = s + "something"; } 使用相当于的StringBuilder实现 String s = new StringBuilder().append("a").append(1).append("b"); 那么在1中会创建额外的对象“a”和“b”吗?为什么?我想你把它弄混了一点 对于+

如果输入以下代码:

String s = "a" + 1 + "b";// 1.
String s = "";
for(int i = 0; i < 100000; i++) {
   s = s + "something";
}
使用相当于的StringBuilder实现

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

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

我想你把它弄混了一点

对于
+
-案例,在计算
“a”+1
时将创建一个额外的
“a1”
-对象(就在将
“a1”
“b”
连接之前)。使用
append
方法时,可以避免创建额外的对象。就这些


编译时将已经创建
“a”
“b”
。(这些常量文字将从一开始就出现在sting池中。)但您可能知道,这些常量也将在
append
案例中创建。

我想您可能想知道为什么在字符串上使用
StringBuilder
而不是
+
操作符更有效。在你的例子中,差异是可以忽略的,但是你必须考虑更大的问题,通常是由循环造成的。

以以下代码为例:

String s = "a" + 1 + "b";// 1.
String s = "";
for(int i = 0; i < 100000; i++) {
   s = s + "something";
}
String s=”“;
对于(int i=0;i<100000;i++){
s=s+“某物”;
}
不管您是否使用
StringBuilder
优化此
+
操作,您都会创建一个
String
对象来存储在
s
中。因此,每次循环迭代都将创建一个新的
字符串
对象,为您提供大量新创建的对象


相反,如果在循环中使用带有
sb.append(“某物”)
StringBuilder
,则不需要
StringBuilder
为每个循环迭代创建
String
对象。它可以自由地等待创建一个,直到循环后需要它。

您的示例实际上不会使用
StringBuilder
,因为没有任何元素是变量。因为“a”、“1”和“b”都是文本,编译器将为您生成一个
字符串
!但是,如果在该
字符串
串联中包含一个变量,则它将使用
StringBuilder
,并且需要为串联的元素使用单独的
字符串
s

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

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
const#20=Asciz a;
常数22=Asciz b;
公共空栏(java.lang.String);
代码:
堆栈=2,局部变量=3,参数大小=2
0:新#2//类java/lang/StringBuilder
3:dup
4:特别是#3//方法java/lang/StringBuilder。“”:()V
7:最不发达国家4//串a
9:invokevirtual#5//方法java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
12:aload_1
13:invokevirtual#5//方法java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
16:最不发达国家6//b串
18:invokevirtual#5//方法java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
21:invokevirtual#7//方法java/lang/StringBuilder.toString:()Ljava/lang/String;
24:astore_2
25:返回
LineNumberTable:
第7行:0
第8行:25

如果代码在Foo.java中编译为Foo.class,请使用
javap-c-vfoo
获得显示的反编译输出。这样做很有启发性,尤其是像你这样的简单例子。(我刚刚从javap输出中选择了一些有趣的位。)关于您的答案,必须创建a和b对象,以便将它们作为参数传递给
StringBuilder.append()