Если конкатенация строк с использованием + реализована с использованием StringBuilder, то почему во время конкатенации создаются дополнительные объекты? - PullRequest
7 голосов
/ 13 ноября 2010

Если следующий код:

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

Реализуется с использованием StringBuilder, эквивалентного

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

тогда в 1 будут созданы дополнительные объекты "a" и "b" и почему?

Ответы [ 3 ]

5 голосов
/ 13 ноября 2010

Ваш пример фактически не будет использовать StringBuilder, потому что ни один из элементов не является переменным. Поскольку «a», 1 и «b» - все литералы, компилятор сделает для вас один String! Однако, если вы включили переменную в эту String конкатенацию, то она будет использовать StringBuilder и потребуются отдельные String 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
2 голосов
/ 13 ноября 2010

Полагаю, вам интересно, почему в целом более эффективно использовать StringBuilder вместо оператора + в строках.В вашем примере разница незначительна, но вы должны учитывать более крупные проблемы, обычно возникающие из-за зацикливания.

Возьмите, например, следующий код:

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

Не важно, используете ли выStringBuilder чтобы оптимизировать эту + операцию или нет, вы создаете String объект для хранения в s.Таким образом, каждая итерация цикла создаст новый объект String, который предоставит вам огромное количество вновь созданных объектов.

Напротив, если вы используете StringBuilder с sb.append("something") внутри цикла, StringBuilder не требуется для создания объекта String для каждой итерации цикла.Он может свободно ждать его создания до тех пор, пока он не потребуется после цикла.

1 голос
/ 13 ноября 2010

Я думаю, что вы немного перепутали ...

Для + -кейса будет создан дополнительный "a1" -объект, созданный при оценке "a" + 1 (прямо перед объединением"a1" с "b").Этого создания дополнительного объекта можно избежать при использовании метода append.Вот и все.

"a" и "b" будут уже созданы во время компиляции.(Эти константы будут присутствовать в пуле с самого начала.) Но, как вы, вероятно, знаете, эти константы будут созданы и в случае append.

...