StringBuffer срещу String

Java осигурява StringBufferи Stringкласове и Stringклас се използва за манипулиране на символни низове, които не могат да бъдат променяни. Просто казано, обектите от тип Stringса само за четене и неизменни. В StringBufferклас се използва за представяне знаци, които могат да бъдат променени.

Значителната разлика в производителността между тези два класа е, че StringBufferе по-бърза, отколкото Stringпри извършване на прости конкатенации. В Stringманипулационния код символните низове се свързват рутинно. Използвайки Stringкласа, конкатенациите обикновено се извършват, както следва:

String str = new String ("Stanford"); str + = "Изгубени !!";

Ако трябваше да използвате StringBufferсъщата конкатенация, ще ви трябва код, който изглежда така:

StringBuffer str = нов StringBuffer ("Станфорд"); str.append ("Изгубени !!");

Разработчиците обикновено приемат, че първият пример по-горе е по-ефективен, тъй като смятат, че вторият пример, който използва appendметода за конкатенация, е по-скъп от първия пример, който използва +оператора за конкатенация на два Stringобекта.

На +оператора се появява невинен, но кода, генериран произвежда някои изненади. Използването на StringBufferза конкатенация всъщност може да създаде код, който е значително по-бърз от използването на String. За да открием защо е така, трябва да разгледаме генерирания байт код от нашите два примера. Байтовият код за примера, който използва, Stringизглежда така:

0 нов # 7 3 дуп 4 ldc # 2 6 invokespecial # 12 9 astore_1 10 нов # 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 се изпълнява за първия ред код, а именно:

 String str = new String ("Stanford"); 

След това байт кодът на място от 10 до 29 се изпълнява за конкатенацията:

 str + = "Изгубени !!"; 

Тук нещата стават интересни. Байтовият код, генериран за конкатенацията, създава StringBufferобект, след което извиква неговия appendметод: временният StringBufferобект се създава на място 10, а appendметодът му се извиква на място 23. Тъй като Stringкласът е неизменен, StringBufferтрябва да се използва за конкатенация.

След като обединяването е извършено върху StringBufferобекта, той трябва да бъде преобразуван обратно в String. Това се прави с извикването на toStringметода на място 26. Този метод създава нов Stringобект от временния StringBufferобект. Създаването на този временен StringBufferобект и последващото му превръщане обратно в Stringобект са много скъпи.

В обобщение, двата реда на кода по-горе водят до създаването на три обекта:

  1. Един Stringобект на място 0
  2. Един StringBufferобект на място 10
  3. А Stringобект на място 26

Сега, нека разгледаме байт кода, генериран за примера, като използваме StringBuffer:

0 нов # 8 3 дуп 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конкатенацията. Очевидно StringBufferпри този тип операции трябва да се използват s, когато е възможно. Ако Stringсе желае функционалността на класа, помислете дали да не използвате StringBufferконкатенация и след това да извършите едно преобразуване в String.

Реджи Хътчърсън е евангелизатор на технологиите на Sun. Той евангелизира технологиите Java 2 Platform на Sun по целия свят, като се концентрира върху J2SE и двигателя за производителност HotSpot.

Научете повече за тази тема

  • JavaWorld дебютира нова седмична колона за изпълнение на Java,“ Reggie Hutcherson ( 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

  • „Оптимизации на компилатора“, Reggie Hutcherson ( JavaWorld, март 2000 г.)

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

Тази история „StringBuffer срещу String“ първоначално е публикувана от JavaWorld.