Всегда ли плохая идея использовать + для конкатенации строк
У меня есть код следующим образом:
String s = "";
for (My my : myList) {
s += my.getX();
}
Findbugs всегда сообщает об ошибке, когда я это делаю.
Ответы
Ответ 1
Я бы использовал +
, если вы вручную конкатенируете,
String word = "Hello";
word += " World!";
Однако, если вы выполняете итерацию и конкатенирование, я предлагаю StringBuilder
,
StringBuilder sb = new StringBuilder();
for (My my : myList) {
sb.append(my.getX());
}
Ответ 2
Объект String неизменен в Java. Каждый + означает другой объект. Вы можете использовать StringBuffer для минимизации количества созданных объектов.
Ответ 3
Каждый раз, когда вы выполняете string+=string
, он вызывает метод следующим образом:
private String(String s1, String s2) {
if (s1 == null) {
s1 = "null";
}
if (s2 == null) {
s2 = "null";
}
count = s1.count + s2.count;
value = new char[count];
offset = 0;
System.arraycopy(s1.value, s1.offset, value, 0, s1.count);
System.arraycopy(s2.value, s2.offset, value, s1.count, s2.count);
}
В случае StringBuilder он приходит к:
final void append0(String string) {
if (string == null) {
appendNull();
return;
}
int adding = string.length();
int newSize = count + adding;
if (newSize > value.length) {
enlargeBuffer(newSize);
}
string.getChars(0, adding, value, count);
count = newSize;
}
Как вы можете заключить, string + string
создает много накладных расходов, и, на мой взгляд, следует избегать, если это возможно. Если вы думаете, что использование StringBuilder громоздко или долго, вы можете просто сделать метод и использовать его косвенно, например:
public static String scat(String... vargs) {
StringBuilder sb = new StringBuilder();
for (String str : vargs)
sb.append(str);
return sb.toString();
}
И используйте его как:
String abcd = scat("a","b","c","d");
В С# мне говорят примерно так же, как string.Concat();
. В вашем случае было бы разумно написать перегрузку для scat, например:
public static String scat(Collection<?> vargs) {
StringBuilder sb = new StringBuilder();
for (Object str : vargs)
sb.append(str);
return sb.toString();
}
Затем вы можете вызвать его с помощью:
result = scat(myList)
Ответ 4
Компилятор может оптимизировать некоторые вещи, такие как
"Foo" + "бар"
Для
StringBuilder s1 = new StringBuilder();
. S1.append( "Foo" ) добавить ( "штрих" );
Однако это все еще субоптимально, так как он начинается с размера по умолчанию 16. Как и во многих вещах, хотя вы должны найти свои самые большие шеи бутылки и поработать над списком. Не вредно быть в привычном использовании SB-шаблона, хотя, особенно если вы можете рассчитать оптимальный размер инициализации.
Ответ 5
Преждевременная оптимизация может быть плохой, а также часто снижает читаемость и, как правило, совершенно не нужна. Используйте +
, если это более читаемо, если у вас нет основной проблемы.
Ответ 6
Не всегда "плохо" использовать "+" . Использование StringBuffer везде может сделать код действительно громоздким.
Если кто-то положил много "+" в середине интенсивного критического цикла, я был бы раздражен. Если кто-то поставил много "+" в редко используемом фрагменте кода, мне было бы все равно.
Ответ 7
Я бы сказал использовать плюс в следующем:
String c = "a" + "b"
И используйте класс StringBuilder везде.
Как уже упоминалось в первом случае, он будет оптимизирован компилятором и более читабельным.
Ответ 8
Одна из причин, почему FindBugs должен спорить об использовании оператора конкатенации (будь то "+" или "+ =" ), является локализуемостью. В примере, который вы дали, это не так очевидно, но в случае следующего кода это:
String result = "Scanning found " + Integer.toString(numberOfViruses) + " viruses";
Если это выглядит несколько знакомым, вам нужно изменить стиль кодирования. Проблема в том, что это будет отлично звучать на английском языке, но это может быть кошмаром для переводчиков. Это просто потому, что вы не можете гарантировать, что приговор будет оставаться неизменным после перевода - некоторые языки будут переведены на "1 бла-бла", а некоторые - на "бла-бла-3". В таких случаях вы всегда должны использовать MessageFormat.format() для построения сложных предложений, и использование оператора конкатенации явно является ошибкой интернационализации.
BTW. Я поставил здесь еще один дефект i18n, не могли бы вы его заметить?