StringBuffer против String

Java предоставляет StringBufferи Stringклассы, и Stringкласс используется для манипулирования символьных строк , которые не могут быть изменены. Проще говоря, объекты типа Stringдоступны только для чтения и неизменны. StringBufferКласс используется для представления символов , которые могут быть изменены.

Существенная разница в производительности между этими двумя классами заключается в том, что они StringBufferбыстрее, чем Stringпри выполнении простых конкатенаций. В Stringкоде манипуляции символьные строки обычно объединяются. С помощью Stringкласса конкатенации обычно выполняются следующим образом:

Строка str = новая строка («Стэнфорд»); str + = "Заблудился !!";

Если бы вы использовали StringBufferтакую ​​же конкатенацию, вам понадобился бы код, который выглядит следующим образом:

StringBuffer str = новый StringBuffer ("Стэнфорд"); str.append ("Потеряно !!");

Разработчики обычно предполагают, что первый пример выше более эффективен, потому что они думают, что второй пример, в котором используется appendметод конкатенации, является более дорогостоящим, чем первый пример, в котором используется +оператор для объединения двух Stringобъектов.

+Оператор оказывается невиновным, но генерируемый код производит некоторые сюрпризы. StringBufferФактически, использование для конкатенации может привести к созданию кода, который значительно быстрее, чем при использовании String. Чтобы выяснить, почему это так, мы должны изучить сгенерированный байт-код из наших двух примеров. Байт-код для примера с использованием Stringвыглядит так:

0 new # 7 3 dup 4 ldc # 2 6 invokespecial # 12 9 astore_1 10 new # 8 13 dup 14 aload_1 15 invokestatic # 23 18 invokespecial # 13 21 ldc # 1 23 invokevirtual # 15 26 invokevirtual # 22 29 astore_1 

Байт-код в ячейках с 0 по 9 выполняется для первой строки кода, а именно:

 Строка str = новая строка («Стэнфорд»); 

Затем байт-код с 10 по 29 выполняется для конкатенации:

 str + = "Забыли !!"; 

Здесь все становится интересно. Байт-код, сгенерированный для конкатенации, создает StringBufferобъект, затем вызывает его appendметод: временный StringBufferобъект создается в местоположении 10, а его appendметод вызывается в местоположении 23. Поскольку Stringкласс неизменяемый, StringBufferдля объединения должен использоваться a .

После того, как объединение будет выполнено для StringBufferобъекта, его необходимо преобразовать обратно в String. Это делается с помощью вызова toStringметода в местоположении 26. Этот метод создает новый Stringобъект из временного StringBufferобъекта. Создание этого временного StringBufferобъекта и его последующее преобразование обратно в Stringобъект очень дороги.

Таким образом, две строки кода выше приводят к созданию трех объектов:

  1. StringОбъект в местоположении 0
  2. StringBufferОбъект , расположенный на месте 10
  3. StringОбъект , расположенный на месте 26

Теперь давайте посмотрим на байт-код, созданный для примера с использованием StringBuffer:

0 новый # 8 3 dup 4 ldc # 2 6 invokespecial # 13 9 astore_1 10 aload_1 11 ldc # 1 13 invokevirtual # 15 16 pop 

Байт-код в позициях от 0 до 9 выполняется для первой строки кода:

 StringBuffer str = новый StringBuffer ("Стэнфорд"); 

Затем байт-код с 10 по 16 выполняется для конкатенации:

 str.append ("Потеряно !!"); 

Обратите внимание, что, как и в первом примере, этот код вызывает appendметод StringBufferобъекта. Однако, в отличие от первого примера, нет необходимости создавать временный объект, StringBufferа затем преобразовывать его в Stringобъект. Этот код создает только один объект StringBuffer, в местоположении 0.

В заключение, StringBufferконкатенация значительно быстрее, чем Stringконкатенация. Очевидно, что StringBuffers следует использовать в этом типе операций, когда это возможно. Если функциональность Stringкласса желательна, рассмотрите возможность использования StringBufferдля конкатенации, а затем выполнения одного преобразования в String.

Реджи Хатчерсон - технологический евангелист Sun. Он пропагандирует технологии Sun Java 2 Platform по всему миру, уделяя особое внимание J2SE и движку производительности HotSpot.

Узнать больше по этой теме

  • « JavaWorld представляет новую еженедельную колонку о производительности Java», Реджи Хатчерсон ( JavaWorld, март 2000 г.)

    //www.javaworld.com/jw-03-2000/jw-03-javaperf.html

  • «Основы производительности Java», Реджи Хатчерсон ( JavaWorld, март 2000 г.)

    //www.javaworld.com/jw-03-2000/jw-03-javaperf_2.html

  • "Проблема с производительностью или проблема с дизайном?" Реджи Хатчерсон ( JavaWorld, март 2000 г.)

    //www.javaworld.com/jw-03-2000/jw-03-javaperf_3.html

  • "Оптимизация компилятора", Реджи Хатчерсон ( JavaWorld, март 2000 г.)

    //www.javaworld.com/jw-03-2000/jw-03-javaperf_4.html

Эта история «StringBuffer против String» изначально была опубликована JavaWorld.