Конкат Java в вызове stringbuilder - PullRequest
5 голосов
/ 05 октября 2011

Насколько я знаю, StringBuilder помогает уменьшить использование памяти, не создавая временных экземпляров строк в пуле строк во время concats.Но что произойдет, если я сделаю вот что:

StringBuilder sb = new StringBuilder("bu");
sb.append("b"+"u");

Компилируется ли оно в

sb.append("b");
sb.append("u");

?Или это зависит от флагов оптимизации?Или я потеряю всю выгоду, если струностроители?Или этот вопрос не имеет смысла?:)

Ответы [ 4 ]

8 голосов
/ 05 октября 2011

Он компилируется в sb.append("bu"), потому что компилятор переводит конкатенацию нескольких строковых литералов в одну строковую литерал.

Если бы у вас было

String a = "a";
sb.append(a + "b");

это скомпилировало бы в

String a = "a";
String temp = a + "b"; // useless creation of a string here
sb.append(temp);

Так что вы должны предпочесть

sb.append(a);
sb.append("b");

в этом случае.

7 голосов
/ 05 октября 2011

Поскольку "b" + "u" является выражением, которое вычисляется во время компиляции, оно будет скомпилировано так же, как если бы вы имели "bu".

 0: new #2; //class StringBuilder
 3: dup
 4: ldc #3; //String bu
 6: invokespecial   #4; //Method StringBuilder."<init>":(String;)V
 9: astore_1
10: aload_1
11: ldc #3; //String bu
13: invokevirtual   #5; // StringBuilder.append:(String;)LStringBuilder;

Если бы у вас были две строковые переменные, эта оптимизация не сработала бы:

Следующий фрагмент ...

StringBuilder sb = new StringBuilder("bu");
String b = "b", u = "u";

sb.append(b + u);

... компилируется как:

0:  new #2; //class StringBuilder
3:  dup
4:  ldc #3; //String bu
6:  invokespecial   #4; //Method StringBuilder."<init>":(String;)V
9:  astore_1
10: ldc #5; //String b
12: astore_2
13: ldc #6; //String u
15: astore_3
16: aload_1
17: new #2; //class StringBuilder
20: dup
21: invokespecial   #7; //Method StringBuilder."<init>":()V
24: aload_2
25: invokevirtual   #8; //Method StringBuilder.append:(String;)StringBuilder;
28: aload_3
29: invokevirtual   #8; //Method StringBuilder.append:(String;)StringBuilder;
32: invokevirtual   #9; //Method StringBuilder.toString:()String;
35: invokevirtual   #8; //Method StringBuilder.append:(String;)StringBuilder;

т.е. что-то похожее на

StringBuilder sb = new StringBuilder("bu");
String b = "b", u = "u";

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

sb.append(result);

Как вы можете видеть в строке 17-21, создается дополнительный StringBuilder с целью объединения a и b. Полученный String этого временного StringBuilder затем выбирается в строке 32 и добавляется к исходному StringBuilder в строке 35.


(Байт-код был сгенерирован командой javap, которая является частью JDK. Попробуйте, это действительно просто!)

0 голосов
/ 05 октября 2011

НЕПРАВИЛЬНО:

StringBuilder sb = new StringBuilder();
sb.append("b"+"u");

ПРАВИЛЬНО:

StringBuilder sb = new StringBuilder();
sb.append("b").append("u");

ЛУЧШИЙ: // Поскольку вы уже знали, что там будет!;)

StringBuilder sb = new StringBuilder();
sb.append("bu");

:)

РЕДАКТИРОВАТЬ

Я думаю, мой ответ выше не является правильным, когда речь идет только о литералах ...

:/

0 голосов
/ 05 октября 2011

Нет, "b" + "u" создаст неизменяемую строку b, неизменную u строку, а затем создаст третью неизменяемую строку bu, которая будет передана в экземпляр StringBuilder.

...