Вопрос по stringbuilder, concatenation, string, java, performance – StringBuilder против конкатенации строк в toString () в Java

827

Учитывая 2toString() реализации ниже, какой из них является предпочтительным:

public String toString(){
    return "{a:"+ a + ", b:" + b + ", c: " + c +"}";
}

или же?

public String toString(){
    StringBuilder sb = new StringBuilder(100);
    return sb.append("{a:").append(a)
          .append(", b:").append(b)
          .append(", c:").append(c)
          .append("}")
          .toString();
}

Что еще более важно, учитывая, что у нас есть только 3 свойства, это может не иметь значения, но в какой момент вы бы переключились с+ согласен?StringBuilder

В какой момент вы переключаетесь на StringBuilder? Когда это влияет на память или производительность. Или когда это могло бы. Если ты'на самом деле делаю это только для пары строк один раз, не беспокойтесь. Но если ты'Если вы будете делать это снова и снова, вы должны увидеть ощутимую разницу при использовании StringBuilder. ewall
что означает 100 в параметре? Asif Mushtaq
@UnKnown 100 - начальный размер StringBuilder. non sequitor

Ваш Ответ

18   ответов
1

что если выВы собираетесь перебрать коллекцию и использовать StringBuilder, вы можете проверитьApache Commons Lang а такжеStringUtils.join () (в разных вкусов)?

Независимо от производительности, это 'избавит вас от необходимости создавать StringBuilders и циклы для чего-то вродемиллионный время.

-2

что мы должны пойти с подходом добавления StringBuilder. Причина в

Конкатенация String каждый раз будет создавать новый строковый объект (так как String является неизменным объектом), поэтому он создаст 3 объекта.

С помощью String Builder будет создан только один объект [StringBuilder является изменяемым], и к нему добавляется следующая строка.

68

Я предпочитаю:

String.format( "{a: %s, b: %s, c: %s}", a, b, c );

...потому что это'короткий и читаемый.

я мог быне оптимизируйте это для скорости, если вы не используете его в цикле с очень большим количеством повторенийа также измерили разницу в производительности.

Я согласен, что если вам нужно вывести много параметров, эта форма может запутаться (как сказано в одном из комментариев). В этом случае яd переключиться на более читаемую форму (возможно, используяToStringBuilder apache-commons - взято из ответа matt b) и снова проигнорируйте производительность.

@ Навин действительно.null + "issimo" производит "nullissimo». rds
Так ты бы сказалменее читабелен, чем один из других подходов? tangens
@rds Нет, простая конкатенацияa+b делает то же самое, что иformat еслиb нулевой. Оба метода приводят к добавлению строкиноль". Navin
В некоторых случаях он более читабелен, но вы легко можете забыть%s или params и должны проверять весь код, используя FindBugs или некоторую функцию IDE (например, для журналов). Christophe Roussy
64

двумя подходами, но этоЛегко построить худший сценарий, подобный этому:

public class Main
{
    public static void main(String[] args)
    {
        long now = System.currentTimeMillis();
        slow();
        System.out.println("slow elapsed " + (System.currentTimeMillis() - now) + " ms");

        now = System.currentTimeMillis();
        fast();
        System.out.println("fast elapsed " + (System.currentTimeMillis() - now) + " ms");
    }

    private static void fast()
    {
        StringBuilder s = new StringBuilder();
        for(int i=0;i<100000;i++)
            s.append("*");      
    }

    private static void slow()
    {
        String s = "";
        for(int i=0;i<100000;i++)
            s+="*";
    }
}

Выход:

slow elapsed 11741 ms
fast elapsed 7 ms

Проблема в том, что добавление + = к строке восстанавливает новую строку, поэтому она стоит что-то линейное по отношению к длине ваших строк (сумма обоих).

Итак - на ваш вопрос:

Второй подход будет быстрее, но этоменее читаемый и сложный в обслуживании. Как я уже сказал, в вашем конкретном случае вы, вероятно, не увидите разницу.

вполне может быть, этот ответ до того, как существовал String.concat. но продемонстрируйте с помощью кода вместо слов :) Omry Yadan
Пока ты'правы насчет+=, оригинальный пример был последовательностью+, что компилятор превращается в одинstring.concat вызов. Ваши результаты нет применяется. Blindy
String.concat примерно в два раза быстрее, чем StringBuffer.append jitendra varshney
Я попробовал этот пример, чтобы проверить скорость. Итак, мои результаты таковы: медленно прошло 29672 мс; быстро прошло 15 мс Так что ответ очевиден. Но если это будет 100 итераций - время одинаковое - 0 мс. Если 500 итераций - 16 мс и 0 мс. И так далее. Ernestas Gruodis
4

Единственное исключение для этого в моей книге, если вы можетедоказывать для меня это потребляет значительные ресурсы :) (да, это означает профилирование)

Также обратите внимание, что компилятор Java 5 генерирует более быстрый код, чем рукописный »StringBuffer» подход, используемый в более ранних версиях Java. Если вы используете "+" это и будущие улучшения предоставляются бесплатно.

3

есть некоторые споры о том, необходимо ли использование StringBuilder с текущими компиляторами. Так что я думал, чтоДадим свои 2 цента опыта.

у меня естьJDBC результирующий набор из 10 тыс. записей (да, мне нужно, чтобы все они были в одной партии). Использование оператора + занимает около 5 минут на моей машине сJava 1.8, С помощьюstringBuilder.append("") занимает меньше секунды для того же запроса.

Так что разница огромна. Внутри петлиStringBuilder намного быстрее

Я думаю, что дебаты об использовании этого вне петель. Я думаю, что есть консенсус, что вам нужно использовать его внутри цикла. Jordan
2

Смотрите пример ниже:

//java8
static void main(String[] args) {
    case1();//str.concat
    case2();//+=
    case3();//StringBuilder
}

static void case1() {
    List<long> savedTimes = new ArrayList();
    long startTimeAll = System.currentTimeMillis();
    String str = "";
    for (int i = 0; i < MAX_ITERATIONS; i++) {
        long startTime = System.currentTimeMillis();
        str = str.concat(UUID.randomUUID()+"---");
        saveTime(savedTimes, startTime);
    }
    System.out.println("Created string of length:"+str.length()+" in "+(System.currentTimeMillis()-startTimeAll)+" ms");
}

static void case2() {
    List<long> savedTimes = new ArrayList();
    long startTimeAll = System.currentTimeMillis();
    String str = "";
    for (int i = 0; i < MAX_ITERATIONS; i++) {
        long startTime = System.currentTimeMillis();
        str+=UUID.randomUUID()+"---";
        saveTime(savedTimes, startTime);
    }        
    System.out.println("Created string of length:"+str.length()+" in "+(System.currentTimeMillis()-startTimeAll)+" ms");
}

static void case3() {
    List<long> savedTimes = new ArrayList();
    long startTimeAll = System.currentTimeMillis();
    StringBuilder str = new StringBuilder("");
    for (int i = 0; i < MAX_ITERATIONS; i++) {
        long startTime = System.currentTimeMillis();
        str.append(UUID.randomUUID()+"---");
        saveTime(savedTimes, startTime);
    }        
    System.out.println("Created string of length:"+str.length()+" in "+(System.currentTimeMillis()-startTimeAll)+" ms");

}

static void saveTime(List<long> executionTimes, long startTime) {
        executionTimes.add(System.currentTimeMillis()-startTime);
        if(executionTimes.size()%CALC_AVG_EVERY == 0) {
            out.println("average time for "+executionTimes.size()+" concatenations: "+
                    NumberFormat.getInstance().format(executionTimes.stream().mapToLong(Long::longValue).average().orElseGet(()->0))+
                    " ms avg");
            executionTimes.clear();
        }
}
</long></long></long></long>

Выход:

среднее время для 10000 объединений: 0,096 мс

среднее время для 10000 конкатенаций: 0,185 мс

среднее время для 10000 конкатенаций: 0,327 мс

среднее время для 10000 объединений: 0,501 мс

среднее время для 10000 объединений: 0,656 мс

Создана строка длиной: 1950000 в17745 мс

среднее время для 10000 конкатенаций: 0,21 мс

среднее время для 10000 объединений: 0,652 мс

среднее время для 10000 конкатенаций: 1,129 мс

среднее время для 10000 объединений: 1,727 мс

среднее время для 10000 конкатенаций: 2,302 мс

Создана строка длиной: 1950000 в60279 мс

среднее время для 10000 объединений: 0,002 мс

среднее время для 10000 объединений: 0,002 мс

среднее время для 10000 объединений: 0,002 мс

среднее время для 10000 объединений: 0,002 мс

среднее время для 10000 объединений: 0,002 мс

Создана строка длиной: 1950000 в100 мс

По мере увеличения длины строки время конкатенации увеличивается.

Вот гдеStringBuilder обязательно нужно.

Как видите, конкатенация:UUID.randomUUID()+"---", не очень влияет на время.

P.S .: Я недумаюКогда использовать StringBuilder в Java действительно дубликат этого.

Этот вопрос говорит оtoString() который в большинстве случаев не выполняет конкатенации огромных строк.

21

javap -c) показывает оптимизацию, представленную компилятором.+ такжеsb.append() сгенерирует очень похожий код. Тем не менее, стоит проверить поведение, если мы используем+ в цикле.

Добавление строк с помощью + в цикле for

Джава:

public String myCatPlus(String[] vals) {
    String result = "";
    for (String val : vals) {
        result = result + val;
    }
    return result;
}

ByteCode :(for отрывок цикла)

12: iload         5
14: iload         4
16: if_icmpge     51
19: aload_3
20: iload         5
22: aaload
23: astore        6
25: new           #3                  // class java/lang/StringBuilder
28: dup
29: invokespecial #4                  // Method java/lang/StringBuilder."<init>":()V
32: aload_2
33: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
36: aload         6
38: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
41: invokevirtual #6                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
44: astore_2
45: iinc          5, 1
48: goto          12
</init>

Добавление строк с использованием stringbuilder.append

Джава:

public String myCatSb(String[] vals) {
    StringBuilder sb = new StringBuilder();
    for(String val : vals) {
        sb.append(val);
    }
    return sb.toString();
}

ByteCdoe :(for отрывок цикла)

17: iload         5
19: iload         4
21: if_icmpge     43
24: aload_3
25: iload         5
27: aaload
28: astore        6
30: aload_2
31: aload         6
33: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
36: pop
37: iinc          5, 1
40: goto          17
43: aload_2

Есть немногоявная разница хоть. В первом случае, где+ был использован, новыйStringBuilder создается для каждой итерации цикла, а сгенерированный результат сохраняетсяtoString() звоните (с 29 по 41). Таким образом, вы генерируете промежуточные строки, которые вам действительно не нужны при использовании+ оператор вfor петля.

Это Oracle JDK или OpenJDK? Christophe Roussy
-4

Для таких простых строк я предпочитаю использовать

"string".concat("string").concat("string");

В порядке, я бы сказал, что предпочтительный метод построения строки использует StringBuilder, String # concat (), а затем перегруженный оператор +. StringBuilder - это значительное увеличение производительности, когда работа с большими строками так же, как использование оператора + - это значительное снижение производительности (экспоненциально большое уменьшение при увеличении размера строки). Единственная проблема с использованием .concat () заключается в том, что он может генерировать исключения NullPointerException.

Использование concat () может работать хуже, чем '+' так как JLS позволяет '+' быть преобразованным в StringBuilder и, скорее всего, все JVM 'это можно сделать или использовать более эффективную альтернативу - то же самое вряд ли будет верно для concat, которая должна создать и отбросить хотя бы одну полную промежуточную строку в вашем примере. Lawrence Dol
24

+" и StringBuilder.append () генерируют точно такой же байт-код.

Так что для удобства чтения кода используйте «+».

2 исключения:

многопоточная среда: StringBufferконкатенация в циклах: StringBuilder / StringBuffer
7

Apache Commons-Lang имеетToStringBuilder класс, который очень прост в использовании. Он отлично справляется как с логикой добавления, так и с форматированием того, как вы хотите, чтобы ваша строка была похожа.

public void toString() {
     ToStringBuilder tsb =  new ToStringBuilder(this);
     tsb.append("a", a);
     tsb.append("b", b)
     return tsb.toString();
}

Вернет вывод, который выглядит как.[email protected][a=whatever, b=foo]

Или в более сжатой форме, используя цепочку:

public void toString() {
     return new ToStringBuilder(this).append("a", a).append("b", b").toString();
}

Или, если вы хотите использовать отражение, чтобы включить каждое поле класса:

public String toString() {
    return ToStringBuilder.reflectionToString(this);
}

Вы также можете настроить стиль ToString, если хотите.

220

пишете ли вы одну конкатенацию в одном месте или накапливаете ее с течением времени.

Для примера, который вы дали, естьнет смысла явно использовать StringBuilder. (Посмотрите на скомпилированный код для вашего первого случая.)

Но если вы строите строку, например, внутри цикла используйте StringBuilder.

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

...
String result = "";
for (String s : hugeArray) {
    result = result + s;
}

очень трата времени и памяти по сравнению с:

...
StringBuilder sb = new StringBuilder();
for (String s : hugeArray) {
    sb.append(s);
}
String result = sb.toString();
@amitfr Я действительно проверил это (поискjavapвы можете проанализировать байт-код с его помощью) и, с немного измененным примером (String str = ((a == null) ? a1 : a) + ((b == null) ? b1 : b) + ((c == c1) ? null : c);), он по-прежнему производит оптимизации, работает с.javac 1.8.0_102 Adowrath
Кстати, вы можете использоватьresult += s; а также (в первом примере) RAnders00
сколько объектов будет создано этим утверждением?"{a:"+ a + ", b:" + b + ", c: " + c +"}"; Asif Mushtaq
Да, StringBuilder не делаетНе нужно заново создавать объект String снова и снова. Olga
2

потому что он должен сделать совершенно новую копию String, так как строки являются неизменяемыми в Java. Это играет особую роль, если конкатенация очень частая, например: внутри цикла. Вот что предлагает моя ИДЕЯ, когда я пытаюсь сделать такую вещь:

Основные правила:

Внутри одного строкового присваивания можно использовать конкатенацию строк.Если ты'повторяя цикл для создания большого блока символьных данных, перейдите к StringBuffer.Использование + = для String всегда будет менее эффективным, чем использование StringBuffer, поэтому он должен вызывать предупреждающие сигналы - но в некоторых случаях полученная оптимизация будет незначительной по сравнению с проблемами читабельности, поэтому используйте свой здравый смысл.

Вотхороший блог Джона Скита вокруг этой темы.

Вы никогда не должны использовать StringBuffer, если вам абсолютно не требуется синхронизированный доступ из нескольких потоков. В противном случае предпочтение отдается StringBuilder, который не синхронизирован и поэтому имеет меньше накладных расходов. Erki der Loony
7

+=String объединение) не рекомендуется. Причина почему: JavaString является неизменным, каждый раз, когда производится новая конкатенацияString (новый отпечаток уже отличается от старогов струнном пуле ). Создание новых строк оказывает давление на ГХ и замедляет программу: создание объектов стоит дорого.

Приведенный ниже код должен сделать его более практичным и понятным одновременно.

public static void main(String[] args) 
{
    // warming up
    for(int i = 0; i < 100; i++)
        RandomStringUtils.randomAlphanumeric(1024);
    final StringBuilder appender = new StringBuilder();
    for(int i = 0; i < 100; i++)
        appender.append(RandomStringUtils.randomAlphanumeric(i));

    // testing
    for(int i = 1; i <= 10000; i*=10)
        test(i);
}

public static void test(final int howMany) 
{
    List<string> samples = new ArrayList<>(howMany);
    for(int i = 0; i < howMany; i++)
        samples.add(RandomStringUtils.randomAlphabetic(128));

    final StringBuilder builder = new StringBuilder();
    long start = System.nanoTime();
    for(String sample: samples)
        builder.append(sample);
    builder.toString();
    long elapsed = System.nanoTime() - start;
    System.out.printf("builder - %d - elapsed: %dus\n", howMany, elapsed / 1000);

    String accumulator = "";
    start = System.nanoTime();
    for(String sample: samples)
        accumulator += sample;
    elapsed = System.nanoTime() - start;
    System.out.printf("concatenation - %d - elapsed: %dus\n", howMany, elapsed / (int) 1e3);

    start = System.nanoTime();
    String newOne = null;
    for(String sample: samples)
        newOne = new String(sample);
    elapsed = System.nanoTime() - start;
    System.out.printf("creation - %d - elapsed: %dus\n\n", howMany, elapsed / 1000);
}
</string>

Результаты пробега сообщаются ниже.

builder - 1 - elapsed: 132us
concatenation - 1 - elapsed: 4us
creation - 1 - elapsed: 5us

builder - 10 - elapsed: 9us
concatenation - 10 - elapsed: 26us
creation - 10 - elapsed: 5us

builder - 100 - elapsed: 77us
concatenation - 100 - elapsed: 1669us
creation - 100 - elapsed: 43us

builder - 1000 - elapsed: 511us
concatenation - 1000 - elapsed: 111504us
creation - 1000 - elapsed: 282us

builder - 10000 - elapsed: 3364us 
concatenation - 10000 - elapsed: 5709793us
creation - 10000 - elapsed: 972us

Не учитывая результаты для одной конкатенации (JIT еще не выполнил свою работу), даже для 10 конкатенаций снижение производительности является значимым; для тысяч конкатенаций разница огромна.

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

8

invokedynamic вызов. Более подробную информацию можно найти вСЭП-280:

Идея состоит в том, чтобы заменить весь танец добавления StringBuilder простым вызовом динамического вызова java.lang.invoke.StringConcatFactory, который будет принимать значения, требующие объединения.

864

компилятор фактически превратит его в версию 2 - никакой разницы в производительности вообще.

Что еще более важно, учитывая, что у нас есть только 3 свойства, это может не иметь значения, но в какой момент вы переключаетесь с concat на builder?

В тот момент, когда выповторное объединение в цикле - этоОбычно, когда компилятор можетт заменительStringBuilder само собой.

Байт-код можно увидеть здесь:bpaste.net/show/Z8o0hdiCerkFUXhaeU7L обратите внимание, что номера строк нене соответствует, но этоЯВЛЯЕТСЯ правильный код Raffael
Единственное отличие - это параметр размера, указанный при инициализации. Paŭlo Ebermann
Спасибо, это правда и для Visual Basic? lamarmora
Ребята, в этой документации написано, что StringBuffer не StringBuilder, а буфер определенно медленнее компоновщика, поскольку он синхронизируется, и каждая операция добавляет блокировку, получая и освобождая операции с ней ... Я понимаю это как есть? или яя что-то упустил? vach
1

чно неЯ не знаю, что происходит с gc, но для меня важно время. Важным фактором здесь является компилятор. Я использовал jdk1.8.0_45 под платформой window8.1.

concatWithPlusOperator = 8
concatWithBuilder = 130
concatWithConcat = 127
concatStringFormat = 3737
concatWithBuilder2 = 46



public class StringConcatenationBenchmark {

private static final int MAX_LOOP_COUNT = 1000000;

public static void main(String[] args) {

    int loopCount = 0;
    long t1 = System.currentTimeMillis();
    while (loopCount < MAX_LOOP_COUNT) {
        concatWithPlusOperator();
        loopCount++;
    }
    long t2 = System.currentTimeMillis();
    System.out.println("concatWithPlusOperator = " + (t2 - t1));

    long t3 = System.currentTimeMillis();
    loopCount = 0;
    while (loopCount < MAX_LOOP_COUNT) {
        concatWithBuilder();
        loopCount++;
    }
    long t4 = System.currentTimeMillis();
    System.out.println("concatWithBuilder = " + (t4 - t3));

    long t5 = System.currentTimeMillis();
    loopCount = 0;
    while (loopCount < MAX_LOOP_COUNT) {
        concatWithConcat();
        loopCount++;
    }
    long t6 = System.currentTimeMillis();
    System.out.println("concatWithConcat = " + (t6 - t5));

    long t7 = System.currentTimeMillis();
    loopCount = 0;
    while (loopCount < MAX_LOOP_COUNT) {
        concatStringFormat();
        loopCount++;
    }
    long t8 = System.currentTimeMillis();
    System.out.println("concatStringFormat = " + (t8 - t7));

    long t9 = System.currentTimeMillis();
    loopCount = 0;
    while (loopCount < MAX_LOOP_COUNT) {
        concatWithBuilder2();
        loopCount++;
    }
    long t10 = System.currentTimeMillis();
    System.out.println("concatWithBuilder2 = " + (t10 - t9));
}

private static void concatStringFormat() {
    String s = String.format("%s %s %s %s ", "String", "String", "String", "String");
}

private static void concatWithConcat() {
    String s = "String".concat("String").concat("String").concat("String");
}

private static void concatWithBuilder() {
    StringBuilder builder=new StringBuilder("String");
    builder.append("String").append("String").append("String");
    String s = builder.toString();
}

private static void concatWithBuilder2() {
    String s = new StringBuilder("String").append("String").append("String").append("String").toString();
}

private static void concatWithPlusOperator() {
    String s = "String" + "String" + "String" + "String";
}
}
"String" + "String" конвертируется компилятором в"StringString" - действительно для строковых литералов или, точнее, для строк, являющихся значениями константных выражений - поэтому concatWithPlusOperator не выполняет никакой конкатенации, проверьте ByteCode. Попробуйте это сString s = "String"; s = s + s + s + s; или так... Carlos Heuberger
27

использовать ли append или +. Поскольку они используют Append (я до сих пор не могу понять, как они говорят каждый раз, когда создается новый объект). Поэтому я подумал сделать несколько R &D. Хотя мне нравится объяснение Майкла Боргвардта, я просто хотел показать объяснение, если кому-то действительно понадобится знать в будущем.

/**
 *
 * @author Perilbrain
 */
public class Appc {
    public Appc() {
        String x = "no name";
        x += "I have Added a name" + "We May need few more names" + Appc.this;
        x.concat(x);
        // x+=x.toString(); --It creates new StringBuilder object before concatenation so avoid if possible
        //System.out.println(x);
    }

    public void Sb() {
        StringBuilder sbb = new StringBuilder("no name");
        sbb.append("I have Added a name");
        sbb.append("We May need few more names");
        sbb.append(Appc.this);
        sbb.append(sbb.toString());
        // System.out.println(sbb.toString());
    }
}

и разборка вышеупомянутого класса выходит как

 .method public <init>()V //public Appc()
  .limit stack 2
  .limit locals 2
met001_begin:                                  ; DATA XREF: met001_slot000i
  .line 12
    aload_0 ; met001_slot000
    invokespecial java/lang/Object.<init>()V
  .line 13
    ldc "no name"
    astore_1 ; met001_slot001
  .line 14

met001_7:                                      ; DATA XREF: met001_slot001i
    new java/lang/StringBuilder //1st object of SB
    dup
    invokespecial java/lang/StringBuilder.<init>()V
    aload_1 ; met001_slot001
    invokevirtual java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lan\
g/StringBuilder;
    ldc "I have Added a nameWe May need few more names"
    invokevirtual java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lan\
g/StringBuilder;
    aload_0 ; met001_slot000
    invokevirtual java/lang/StringBuilder.append(Ljava/lang/Object;)Ljava/lan\
g/StringBuilder;
    invokevirtual java/lang/StringBuilder.toString()Ljava/lang/String;
    astore_1 ; met001_slot001
  .line 15
    aload_1 ; met001_slot001
    aload_1 ; met001_slot001
    invokevirtual java/lang/String.concat(Ljava/lang/String;)Ljava/lang/Strin\
g;
    pop
  .line 18
    return //no more SB created
met001_end:                                    ; DATA XREF: met001_slot000i ...

; ===========================================================================

;met001_slot000                                ; DATA XREF: <init>r ...
    .var 0 is this LAppc; from met001_begin to met001_end
;met001_slot001                                ; DATA XREF: <init>+6w ...
    .var 1 is x Ljava/lang/String; from met001_7 to met001_end
  .end method
;44-1=44
; ---------------------------------------------------------------------------


; Segment type: Pure code
  .method public Sb()V //public void Sb
  .limit stack 3
  .limit locals 2
met002_begin:                                  ; DATA XREF: met002_slot000i
  .line 21
    new java/lang/StringBuilder
    dup
    ldc "no name"
    invokespecial java/lang/StringBuilder.<init>(Ljava/lang/String;)V
    astore_1 ; met002_slot001
  .line 22

met002_10:                                     ; DATA XREF: met002_slot001i
    aload_1 ; met002_slot001
    ldc "I have Added a name"
    invokevirtual java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lan\
g/StringBuilder;
    pop
  .line 23
    aload_1 ; met002_slot001
    ldc "We May need few more names"
    invokevirtual java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lan\
g/StringBuilder;
    pop
  .line 24
    aload_1 ; met002_slot001
    aload_0 ; met002_slot000
    invokevirtual java/lang/StringBuilder.append(Ljava/lang/Object;)Ljava/lan\
g/StringBuilder;
    pop
  .line 25
    aload_1 ; met002_slot001
    aload_1 ; met002_slot001
    invokevirtual java/lang/StringBuilder.toString()Ljava/lang/String;
    invokevirtual java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lan\
g/StringBuilder;
    pop
  .line 28
    return
met002_end:                                    ; DATA XREF: met002_slot000i ...


;met002_slot000                                ; DATA XREF: Sb+25r
    .var 0 is this LAppc; from met002_begin to met002_end
;met002_slot001                                ; DATA XREF: Sb+9w ...
    .var 1 is sbb Ljava/lang/StringBuilder; from met002_10 to met002_end
  .end method
;96-49=48
; ---------------------------------------------------------------------------
</init></init></init></init></init></init>

Из приведенных выше двух кодов видно, что Майкл прав. В каждом случае создается только один объект SB.

Похожие вопросы