Как найти все наивные (на основе "+") конкатенации строк в большой кодовой базе Java? - PullRequest
6 голосов
/ 17 июня 2009

У нас огромная база кода, и мы подозреваем, что в коде довольно много конкататов строк, основанных на «+», которые могут выиграть от использования StringBuilder / StringBuffer. Есть ли эффективный способ или существующие инструменты для их поиска, особенно в Eclipse?

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

Ответы [ 11 ]

13 голосов
/ 17 июня 2009

Я почти уверен, FindBugs может их обнаружить. Если нет, то все равно чрезвычайно полезно иметь.

Редактировать: Он действительно может найти конкатенации в цикле , что является единственным разом, когда это действительно имеет значение.

12 голосов
/ 17 июня 2009

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

String foo = "Your age is: " + getAge();

и превратить его в:

StringBuilder builder = new StringBuilder("Your age is: ");
builder.append(getAge());
String foo = builder.toString();

, который является менее читаемой версией того же самого. Часто наивным решением является лучшее решение. Также некоторые люди беспокоятся о:

String x = "long line" + 
    "another long line";

когда на самом деле эта конкатенация выполняется во время компиляции.

Как правильно сказал Нсандер, сначала выясните, есть ли у вас проблемы ...

10 голосов
/ 17 июня 2009

Почему бы не использовать профилировщик для поиска "наивных" конкатенаций строк, которые действительно имеют значение? Переключайтесь на более подробный StringBuffer, только если он вам действительно нужен.

3 голосов
/ 23 июня 2009

Скорее всего, вы снизите производительность и код станет менее читабельным . Компилятор уже выполняет эту оптимизацию, и если вы не зациклены, он, как правило, будет работать лучше. Кроме того, в JDK 8 они могут выйти с StringUberBuilder, и весь ваш код, который использует StringBuilder, будет работать медленнее, в то время как сцепленные строки "+" получат выгоду от нового класса.

«Мы должны забыть о малой эффективности, скажем, в 97% случаев: преждевременная оптимизация - корень всего зла. И все же мы не должны упускать наши возможности в эти критические 3% ». - Дональд Кнут

2 голосов
/ 17 июня 2009

Джон Скит (как всегда) и другие уже сказали все, что нужно, но я действительно хотел бы подчеркнуть, что, возможно, вы стремитесь к несуществующему повышению производительности ...

Посмотрите на этот код:

public class StringBuilding {
  public static void main(String args[]) {
    String a = "The first part";
    String b = "The second part";
    String res = a+b;

    System.gc(); // Inserted to make it easier to see "before" and "after" below

    res = new StringBuilder().append(a).append(b).toString();
  }
}

Если вы скомпилируете и разберете его с помощью javap, это то, что вы получите.

public static void main(java.lang.String[]);
  Code:
   0:   ldc     #2; //String The first part
   2:   astore_1
   3:   ldc     #3; //String The second part
   5:   astore_2
   6:   new     #4; //class java/lang/StringBuilder
   9:   dup
   10:  invokespecial   #5; //Method java/lang/StringBuilder."<init>":()V
   13:  aload_1
   14:  invokevirtual   #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   17:  aload_2
   18:  invokevirtual   #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   21:  invokevirtual   #7; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
   24:  astore_3
   25:  invokestatic    #8; //Method java/lang/System.gc:()V
   28:  new     #4; //class java/lang/StringBuilder
   31:  dup
   32:  invokespecial   #5; //Method java/lang/StringBuilder."<init>":()V
   35:  aload_1
   36:  invokevirtual   #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   39:  aload_2
   40:  invokevirtual   #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   43:  invokevirtual   #7; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
   46:  astore_3
   47:  return

Как видите, 6-21 в значительной степени идентичны 28-43. Не большая часть оптимизации, верно?

Редактировать: проблема с циклом допустима ...

2 голосов
/ 17 июня 2009

Я предлагаю использовать профилировщик. Это действительно вопрос производительности, и если вы не можете сделать так, чтобы код отображался с приемлемыми тестовыми данными, вряд ли его можно будет изменить.

2 голосов
/ 17 июня 2009

IntelliJ может найти их, используя «структурный поиск». Вы ищете «$ a + $ b» и задаете характеристики как $ a, так и $ b как тип java.lang.String.

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

1 голос
/ 17 июня 2009

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

Было бы странным подходом исправить только один класс (потенциальных) узких мест, а не исправлять фактические узкие места.

1 голос
/ 17 июня 2009

Вместо поиска просто + для поиска "+ и +" они, вероятно, найдут подавляющее большинство. случаи, когда вы объединяете несколько переменных, будут более жесткими.

0 голосов
/ 17 июня 2009

Забудьте - ваша JVM, скорее всего, уже это делает - см. JLS, 15.18.1.2 Оптимизация конкатенации строк :

Реализация может выбрать выполнение преобразования и объединения за один шаг, чтобы избежать создания, а затем отбрасывания промежуточного объекта String. Чтобы повысить производительность многократной конкатенации строк, компилятор Java может использовать класс StringBuffer или аналогичный метод для уменьшения числа промежуточных объектов String, которые создаются путем вычисления выражения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...