Статьи

Последствия присутствия StringBuffer

Когда я работаю над устаревшим кодом и работаю с экземплярами StringBuffer , я обычно заменяю их экземплярами StringBuilder . Хотя от этого изменения можно получить преимущество в производительности, я часто меняю его в тех местах, которые, как я знаю, окажут незначительное влияние с точки зрения производительности. Я чувствую, что стоит внести изменения по ряду причин в дополнение к потенциальному выигрышу в производительности. Редко есть причина не выбирать StringBuilder вместо StringBuilder (ожидания API — наиболее распространенное исключение), а существование StringBuffer в коде вводит в заблуждение и является плохим примером для новичков в Java.

В книге «Прагматичный программист: от подмастерья до мастера» Энди Хант и Дэвид Томас обсуждают «важность исправления небольших проблем в вашем коде,« разбитых окон »». Джефф Этвуд затронул эту тему в посте «Теория разбитого окна», а недавно он был рассмотрен в постах « Программная гниль», «Энтропия» и «Теория разбитого окна» и « Не оставлять разбитые окна» . Наличие StringBuffer подразумевает устаревание кода. По сути, использование StringBuffer не может быть «разбитым окном», но это действительно старое, протекающее окно с одной панелью, которое следует заменить современным, энергоэффективным окном с двумя окнами .

Я нашел, что недавнее сообщение в блоге Питера Лоури StringBuffer , и как трудно избавиться от унаследованного кода, было интересным взятием других последствий StringBuffer которые все еще существуют в коде. Лоури цитирует последний абзац документации Javadoc класса StringBuffer : «Начиная с выпуска JDK 5 этот класс был дополнен эквивалентным классом, предназначенным для использования одним потоком, StringBuilder. Класс StringBuilder, как правило, следует использовать предпочтительнее этого, поскольку он поддерживает все те же операции, но он быстрее, так как он не выполняет синхронизацию ». Затем Лори использует простые методы Java и jmap, чтобы продемонстрировать, что экземпляры StringBuffer по-прежнему используются в классах и библиотеках, поставляемых с JDK, даже в Java 8.

Лоури отмечает, что присутствие StringBuffer в часто используемом коде Java более чем через десять лет после введения «замены без замены» StringBuilder свидетельствует о том, насколько трудно «очистить устаревший код». В полном заключении Лоури говорится: «Использование StringBuffer при запуске не имеет большого значения, но, учитывая, что он хорошо известен, имеет запасную замену, и он все еще используется, даже в новой функциональности, более десяти лет спустя, показывает, насколько трудной она может быть. очистить устаревший код или изменить мышление, чтобы заставить людей использовать лучшие библиотеки ».

Я решил опробовать один из самых простых примеров Лоури при компиляции с Java 8 Update 121 и при компиляции с недавним выпуском OpenJDK 9. Я (немного) адаптировал пример Лори к простому списку классов «Main», показанному ниже.

Main.java

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
import java.io.IOException;
 
/**
 * (Slightly) adapted class from blog post
 * "StringBuffer, and how hard it is to get rid of legacy code" at
 */
public class Main
{
   /**
    * Main function that instantiates this Java "application" and does nothing
    * else until "ENTER" is pressed.
    */
   public static void main(final String[] args) throws IOException
   {
      System.out.println("Waiting [press ENTER to exit] ..");
      System.in.read();
   }
}

На следующем снимке экрана показаны результаты использования jcmd с его параметром -all (включая недоступные объекты в проверке) для отображения количества экземпляров StringBuffer и StringBuilder в простом приложении Java при компиляции и запуске с тремя различными версиями Java ( Java 8 Обновление 102 , Java 8 Обновление 121 и OpenJDK 9.0 ea + 164 ). Выполнение jcmd выполняется в PowerShell, поэтому Select-String используется аналогично тому, как grep используется в Linux.

Хотя версии класса, скомпилированные и выполненные с версиями Java 8, имели экземпляры StringBuffer , версия, скомпилированная и выполненная на Java 9, имела только экземпляры StringBuilder . Похоже, что разрешение JDK-8041679 («Заменить использование StringBuffer на StringBuilder в классах базовой библиотеки») и JDK-8043342 («Заменить использование StringBuffer на StringBuilder в криптографическом коде») дало желаемый эффект.

Ссылка: Последствия присутствия StringBuffer от нашего партнера по JCG Дастина Маркса в блоге Inspired by Actual Events .