Цель использования StringBuilder, т. Е. Уменьшение объема памяти. Достигнуто ли это?
Нет, совсем нет. Этот код не правильно использует StringBuilder
. (Я думаю, что вы исказили его, хотя, конечно, там не кавычки id2
и table
?)
Обратите внимание, что цель (как правило) заключается в уменьшении модуля памяти маслобойки, а не использовали общий объем памяти, чтобы сделать жизнь немного легче в сборщике мусора.
Будет ли это иметь память равной использованию строки, как показано ниже?
Нет, это будет вызывать отток более памяти, чем просто прямой CONCAT вы цитируемый. (До /, если виртуальная машина оптимизатор не видит, что в коде явно StringBuilder
ненужно и оптимизирует его, если это возможно.)
Если автор этого кода хочет использовать StringBuilder
(нет аргументов в пользу, но и против ; см примечание в конце этого ответа), лучше сделать это правильно (здесь я предполагаю, что там на самом деле не приводит вокруг id2
и table
):
StringBuilder sb = new StringBuilder(some_appropriate_size);
sb.append("select id1, ");
sb.append(id2);
sb.append(" from ");
sb.append(table);
return sb.toString();
Обратите внимание, что я перечислил some_appropriate_size
в StringBuilder
, чтобы он начинался с достаточной емкости для полного содержимого, которое мы собираемся добавить. Размер по умолчанию, используемый, если вы не указываете один, равен 16 characters, который обычно слишком мал и приводит к тому, что StringBuilder
должен выполнить перераспределение, чтобы сделать себя больше (IIRC, в Sun/Oracle JDK, он удваивает себя [или больше, если он знает, что ему нужно больше, чтобы удовлетворить конкретный append
] каждый раз, когда он заканчивается из комнаты).
Возможно, вы слышали, что строка конкатенации будет использовать StringBuilder
под обложками, если она скомпилирована с помощью компилятора Sun/Oracle. Это верно, он будет использовать один StringBuilder
для общего выражения.Но он будет использовать конструктор по умолчанию, а это означает, что в большинстве случаев ему придется перераспределять ресурсы. Это легче читать. Обратите внимание, что это не true конкатенаций. Так, например, это использует один StringBuilder
:
return "prefix " + variable1 + " middle " + variable2 + " end";
Это примерно переводится:
StringBuilder tmp = new StringBuilder(); // Using default 16 character size
tmp.append("prefix ");
tmp.append(variable1);
tmp.append(" middle ");
tmp.append(variable2);
tmp.append(" end");
return tmp.toString();
Так что все в порядке, хотя конструктор по умолчанию и последующего перераспределения (s) не является идеальным, форы это достаточно хорошо — и конкатенация лот более читаемый.
Но это только для одного выражения. Несколько StringBuilder
s Для этого используются:
String s;
s = "prefix ";
s += variable1;
s += " middle ";
s += variable2;
s += " end";
return s;
Это заканчивает тем, что становится что-то вроде этого:
String s;
StringBuilder tmp;
s = "prefix ";
tmp = new StringBuilder();
tmp.append(s);
tmp.append(variable1);
s = tmp.toString();
tmp = new StringBuilder();
tmp.append(s);
tmp.append(" middle ");
s = tmp.toString();
tmp = new StringBuilder();
tmp.append(s);
tmp.append(variable2);
s = tmp.toString();
tmp = new StringBuilder();
tmp.append(s);
tmp.append(" end");
s = tmp.toString();
return s;
... который является довольно некрасиво.
Важно помнить, что во всех случаях, кроме очень небольшого количества случаев, не имеет значения и предпочитает чтение (что повышает ремонтопригодность), что препятствует определенной проблеме производительности.
Просьба уточнить, почему это не достигнуто, чтобы помочь ему понять это. :) – Thomas
Он не создает отдельный экземпляр StringBuilder для каждой конкатенации - он создает один для всего выражения. Поэтому '' select id1, «+ id2 +» из «+ table» создаст только один «StringBuilder», и будет значительно легче читать IMO. Попробуйте и декомпилируйте код, чтобы увидеть ... –
@JonSkeet: Спасибо, я думал о случае с несколькими выражениями, а не о одном выражении. Исправлена. Цените заметку. –