Мета використання StringBuilder, тобто зменшення пам'яті. Чи досягнуто це?
Ні, зовсім ні. Цей код використовується StringBuilder
неправильно. (Мені здається, ви це неправильно вказали; звичайно там немає цитат навколо id2
таtable
?)
Зверніть увагу, що метою (як правило) є зменшення відтоку пам’яті, а не загальної використаної пам’яті, щоб полегшити життя збирача сміття.
Чи буде пам'ять рівною використанню рядка, як показано нижче?
Ні, це спричинить більший обсяг пам’яті, ніж просто прямий конкат, який ви цитували. (Поки / якщо JVM-оптимізатор не побачить, що явне 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 символів , що, як правило, занадто мало і призводить до StringBuilder
необхідності робити перерозподіли, щоб зробити себе більшим (IIRC, в Sun / Oracle JDK, він подвоюється [або більше, якщо він знає, що йому потрібно більше для задоволення конкретного append
] кожного разу, коли у нього закінчується місце).
Можливо , ви чули , що конкатенація буде використовувати StringBuilder
під ковдрою , якщо зібраний з компілятором Sun / Oracle. Це правда, він буде використовувати один StringBuilder
для загального виразу. Але він буде використовувати конструктор за замовчуванням, що означає, що в більшості випадків йому доведеться виконати перерозподіл. Однак читати його легше. Зверніть увагу, що це не відповідає серії об'єднань. Так, наприклад, для цього використовується одинStringBuilder
:
return "prefix " + variable1 + " middle " + variable2 + " end";
Це приблизно перекладається на:
StringBuilder tmp = new StringBuilder();
tmp.append("prefix ");
tmp.append(variable1);
tmp.append(" middle ");
tmp.append(variable2);
tmp.append(" end");
return tmp.toString();
Отже, це нормально, хоча конструктор за замовчуванням та подальший перерозподіл (и) не є ідеальними, шанси на те, що він досить хороший - і конкатенація багато читабельніша.
Але це лише для одного виразу. 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;
... що досить потворно.
Однак важливо пам’ятати, що у всіх випадках, окрім дуже рідких, це не має значення, і перевагу читання (що покращує ремонтопридатність) надає перевагу, якщо не брати до уваги певну проблему продуктивності.
PreparedStatement
або щось подібне: docs.oracle.com/javase/tutorial/jdbc/basics/prepared.html