Является ли конкатенация с пустой строкой для преобразования строк действительно такой плохой? - PullRequest
39 голосов
/ 24 марта 2010

Допустим, у меня есть две char переменные, а позже я хочу объединить их в строку. Вот как бы я это сделал:

char c1, c2;
// ...

String s = "" + c1 + c2;

Я видел людей, которые говорят, что "трюк" "" + "уродлив" и т. Д., И что вместо этого вы должны использовать String.valueOf или Character.toString. Я предпочитаю эту конструкцию, потому что:

  • Я предпочитаю использовать языковую функцию вместо вызова API, если это возможно
    • В общем, разве язык обычно не более стабилен, чем API?
    • Если языковая функция скрывает только вызов API, то это еще более веская причина для ее выбора!
      • Более абстрактно! Прятаться это хорошо!
  • Мне нравится, что c1 и c2 визуально находятся на одном уровне
    • String.valueOf(c1) + c2 предполагает что-то особенное в c1
  • Это короче.

Есть ли хороший аргумент, почему String.valueOf или Character.toString предпочтительнее "" +?


Пустяки: в java.lang.AssertionError следующая строка появляется 7 раз, каждая с разным типом:

    this("" + detailMessage);

Ответы [ 9 ]

25 голосов
/ 24 марта 2010

Ваши аргументы хороши; это одна из наиболее выразительных областей языка Java, и, как вы обнаружили, идиома "" + кажется укоренившейся

См. Объединение строк в JLS. Выражение типа

"" + c1 + c2

эквивалентно

new StringBuffer().append(new Character(c1).toString())
                  .append(new Character(c2).toString()).toString()

за исключением того, что все промежуточные объекты не являются необходимыми (поэтому эффективность не является мотивом). В спецификации сказано, что реализация может использовать StringBuffer или нет. Поскольку эта функция встроена в язык, я не вижу смысла использовать более многословную форму, особенно в уже многословном языке.

19 голосов
/ 24 марта 2010

Проблема этой конструкции в том, что она обычно не выражает намерение.

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

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

В более распространенном использовании этого подхода (String s = "" + intValue;) конкатенация является просто допустимым побочным эффектом, тогда как преобразование intValue является фактической целью. И простой String.valueOf(intValue) выражает это намерение гораздо яснее.

4 голосов
/ 20 апреля 2010

Я предпочитаю использовать String.valueOf для одиночных преобразований - но в вашем случае вам действительно нужна конкатенация.

Однако я бы предположил, что эта версия устранит всю потенциальную двусмысленность:

String s = c1 + "" + c2;

Таким образом, нет никакой возможности, пусть даже отдаленной, кого-либо обдумать, будут ли слиты c1 и c2 перед объединением.

2 голосов
/ 24 марта 2010

А как же

new String(new char[] {a, b})

и если вы делаете это много, вы можете создать класс "Strings" с:

public static String valueOf(char... chars) {
    return new String(chars);
}

Ваша строка будет тогда читать

String s = Strings.valueOf(a, b);

Хороший и короткий.

Отредактированный

Лучшее имя может быть:

String s = Chars.asString(a, b);
2 голосов
/ 24 марта 2010

На мой взгляд, "" + x очень читабелен, короток и точен. Я бы предпочел более длинные конструкции, такие как String.valueOf. Поведение четко определено, и оно настолько широко используется, что мне вообще трудно назвать это хаком.

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

2 голосов
/ 24 марта 2010

Я думаю, что в "" + var + фактически перегружен для преобразования:

Язык Java обеспечивает специальную поддержку оператора конкатенации строк (+) и преобразования других объектов в строки. Конкатенация строк реализуется с помощью класса StringBuilder (или StringBuffer) и его метода добавления. Строковые преобразования реализуются через метод toString, определяемый Object и наследуемый всеми классами в Java. Для получения дополнительной информации о конкатенации и преобразовании строк

Так что нет никакой разницы и нет проблем с технической точки зрения.

Формируйте удобочитаемую точку зрения - это вопрос личных предпочтений или согласованного стиля кодирования внутри команды.

1 голос
/ 31 марта 2015

Стиль "" + var, на мой взгляд, имеет одну очень большую проблему. Он просто использует метод toString var. Так что если вы измените тип var на что-то другое, вы не получите исключения. Хорошим примером, с которым я только что столкнулся, было то, что тип был изменен с int на Optional<Integer>. Код по-прежнему хорошо компилируется, но вы получите совершенно другой результат.

1 голос
/ 24 марта 2010

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

0 голосов
/ 06 декабря 2012

Лучший способ узнать это скомпилировать / декомпилировать ваш код, для этого я использовал Jad http://en.wikipedia.org/wiki/JAD_(JAva_Decompiler), вы увидите, что ваше выражение было преобразовано в

String s = (new StringBuilder ()). Append (""). Append (ci) .append (c2) .toString ();

Как вы можете видеть, что javac фактически включал вызов append (""), но его стоимость незначительна, если добавить к внутреннему буферу StringBuilder, вы можете проверить источник StringBuilder

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