Добавить пустую строку vs toString - почему это плохо?

Согласно инструменту PMD, следующее является плохой практикой:

String s = "" + 123; // bad 
String t = Integer.toString(456); // ok 


This is an inefficient way to convert any type to a `String`.

Почему это плохо?


person corgrath    schedule 02.09.2010    source источник
comment
Судя по всему, для констант (static / final) + 123 работоспособнее. Для других значений использование toString более эффективно.   -  person corgrath    schedule 02.09.2010
comment
Статический / финальный результат может вводить в заблуждение. Поле должно быть одновременно статическим и конечным, чтобы считаться константой, и только для примитивов и строк. (Локальные переменные никогда не считаются постоянными.)   -  person Chris Jester-Young    schedule 02.09.2010
comment
возможный дубликат Преобразование в строку с использованием (+ ‹int value› ) плохая практика?   -  person McDowell    schedule 02.09.2010


Ответы (4)


String s = "" + 123; // bad     
String t = Integer.toString(456);

Будет скомпилирован в:

String s = "123";
String t = Integer.toString(456);

так: "" +123, очевидно, немного лучше! Проверено с помощью JAD

public static void main(String args[])
{
//    0    0:ldc1            #16  <String "123">
//    1    2:astore_1
//    2    3:sipush          456
//    3    6:invokestatic    #18  <Method String Integer.toString(int)>
//    4    9:astore_2
//    5   10:getstatic       #24  <Field PrintStream System.out>
//    6   13:new             #30  <Class StringBuilder>
//    7   16:dup
//    8   17:aload_1
//    9   18:invokestatic    #32  <Method String String.valueOf(Object)>
//   10   21:invokespecial   #38  <Method void StringBuilder(String)>
//   11   24:aload_2
//   12   25:invokevirtual   #41  <Method StringBuilder StringBuilder.append(String)>
//   13   28:invokevirtual   #45  <Method String StringBuilder.toString()>
//   14   31:invokevirtual   #48  <Method void PrintStream.println(String)>
//   15   34:return
}

РЕДАКТИРОВАТЬ:

Для непостоянных значений:

int i = 123;
String s = (new StringBuilder()).append(i).toString();
String t = Integer.toString(i);
System.out.println((new StringBuilder(String.valueOf(s))).append(t).toString());

    public static void main(String args[])
    {
    //    0    0:bipush          123
    //    1    2:istore_1
    //    2    3:new             #16  <Class StringBuilder>
    //    3    6:dup
    //    4    7:invokespecial   #18  <Method void StringBuilder()>
    //    5   10:iload_1
    //    6   11:invokevirtual   #19  <Method StringBuilder StringBuilder.append(int)>
    //    7   14:invokevirtual   #23  <Method String StringBuilder.toString()>
    //    8   17:astore_2
    //    9   18:iload_1
    //   10   19:invokestatic    #27  <Method String Integer.toString(int)>
    //   11   22:astore_3
    //   12   23:getstatic       #32  <Field PrintStream System.out>
    //   13   26:new             #16  <Class StringBuilder>
    //   14   29:dup
    //   15   30:aload_2
    //   16   31:invokestatic    #38  <Method String String.valueOf(Object)>
    //   17   34:invokespecial   #44  <Method void StringBuilder(String)>
    //   18   37:aload_3
    //   19   38:invokevirtual   #47  <Method StringBuilder StringBuilder.append(String)>
    //   20   41:invokevirtual   #23  <Method String StringBuilder.toString()>
    //   21   44:invokevirtual   #50  <Method void PrintStream.println(String)>
    //   22   47:return
    }
person stacker    schedule 02.09.2010
comment
Я не уверен, что слежу за тобой. Вы доказали, что +123 лучше Integer.toString (123)? - person corgrath; 02.09.2010
comment
+1 за фактическую проверку. А как насчет типов объектов, а не типов контейнеров? - person Philip Potter; 02.09.2010
comment
@corgrath, поскольку jad показал, что он скомпилирован в String s = 123; он преобразуется во время компиляции в строковый литерал. - person stacker; 02.09.2010
comment
+ 123 - постоянное выражение, которое уже вычислено компилятором как 123. - person jarnbjo; 02.09.2010
comment
"" + 123 становится "123", потому что вы указываете константу. Теперь попробуйте "" + Math.random() против String.valueOf(Math.random()). - person Chris Jester-Young; 02.09.2010
comment
@corgrath: Не обращайте внимания на Филиппа, я думаю, он имел в виду примитивные типы, а не типы POD как таковые (что является концепцией C ++). В C ++ POD означает простые старые данные, что означает (очень грубо), что объекты таких типов имеют семантику значений. (Настоящее определение типа POD гораздо более строгое.) - person Chris Jester-Young; 02.09.2010
comment
Ох, хорошо. Итак, x = 4 + 5; + x также является постоянным выражением, означающим одинаковую стоимость? - person corgrath; 02.09.2010
comment
@corgrath: только если x равно static final. - person Chris Jester-Young; 02.09.2010
comment
Итак, для нестатических финалов использование toString более эффективно? - person corgrath; 02.09.2010
comment
@corgrath: для нестатических или нефинальных результатов постоянная оптимизация, описанная в этом ответе, не применяется. - person Chris Jester-Young; 02.09.2010
comment
@stacker: итак: +123 очевидно немного лучше лучше субъективно единственное очевидное - это быстрее. Это приносит в жертву удобочитаемости ради производительности без каких-либо известных проблем с производительностью, что преждевременная оптимизация, которая обычно считается плохой. - person Rune FS; 02.09.2010
comment
Я думаю, что пометка об этом как ответ вводит в заблуждение и бесполезно. Как указывает Крис Джестер-Янг, это быстрее только в тех случаях, когда int является окончательным. Чтобы создать лучший код, в случаях, когда int является final, у вас должно быть соответствующее строковое представление этого int в виде строки, которая также является окончательной (это то, что компилятор делает автоматически). "" + 123 ничуть не лучше, это эквивалентно объявлению новой статической строки со значением "123" и не имеет ничего общего с int 123. - person Nathan; 17.09.2012

Это неэффективно, так как включает ненужную конкатенацию строк, таким образом, создание одного или двух дополнительных String объектов - хотя я считаю, что JIT может оптимизировать его.

Для меня большая проблема в том, что код менее понятен. Вызов toString - это стандартная идиома, понятная каждому Java-разработчику (надеюсь :-), так что вам следует предпочесть это.

person Péter Török    schedule 02.09.2010
comment
Для меня прозрачность кода очень важна. - person Bart; 02.09.2010
comment
Ясность кода всегда должна быть важнее микрооптимизации. - person JesperE; 02.09.2010

Он расширяется до "" + String.valueOf (yourObject) и, таким образом, выполняет ненужную конкатенацию. Конкатенация включает выделение дополнительной строки и создание дополнительной копии значения строки.

person jkff    schedule 02.09.2010
comment
а версия tostring четко заявляет о намерении. Преобразуйте это значение в строку - person Rune FS; 02.09.2010
comment
Это не совсем правильно с точки зрения генерации кода, поэтому я воздержусь от голосования за. Фактически (для Java 6u20, с которым я тестировал) он расширяется до: new StringBuilder().append("").append(yourObject).toString(), предполагая, что yourObject не является константой. - person Chris Jester-Young; 02.09.2010

String s = "" + 123; // bad

Приведенный выше код создает временную строку для объединения "" и 123

person Dead Programmer    schedule 02.09.2010
comment
Не все так просто. См. Ответ укладчика. Если вместо 123 у вас непостоянное значение, то вы правы. - person Chris Jester-Young; 02.09.2010