Является ли конкатенация пустой строкой, чтобы сделать преобразование строк действительно так плохо?

Скажем, у меня есть две переменные 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);

Ответ 1

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

См. Конкатенация строк в JLS. Выражение типа

"" + c1 + c2

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

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

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

Ответ 2

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

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

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

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

Ответ 3

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

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

String s = c1 + "" + c2;

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

Ответ 4

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

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

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

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

Ответ 5

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

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

Ответ 6

Что насчет

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

и если вы это сделаете, вы можете создать класс "Строки" с помощью:

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

Затем ваша строка будет читать

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

Приятный и короткий.

Edited

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

String s = Chars.asString(a, b);

Ответ 7

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

Ответ 8

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

Ответ 9

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

String s = (новый StringBuilder()). append (""). append (ci).append(c2).toString();

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