Конкатенация строк и autoboxing в Java


Когда вы соединяете строку с примитивом, таким как int, делает ли это autobox значение первым.

Исх.

String string = "Four" + 4;

Как он преобразует значение в строку в Java ?

3 5

3 ответа:

Чтобы увидеть, что производит компилятор Java, всегда полезно использовать javap -c, чтобы показать фактический байт-код, произведенный:

Например, следующий код Java:

String s1 = "Four" + 4;
int i = 4;
String s2 = "Four" + i;

Выдаст следующий байт-код:

   0:   ldc     #2; //String Four4
   2:   astore_1
   3:   iconst_4
   4:   istore_2
   5:   new     #3; //class java/lang/StringBuilder
   8:   dup
   9:   invokespecial   #4; //Method java/lang/StringBuilder."<init>":()V
   12:  ldc     #5; //String Four
   14:  invokevirtual   #6; //Method java/lang/StringBuilder.append:(Ljava/lang/
String;)Ljava/lang/StringBuilder;
   17:  iload_2
   18:  invokevirtual   #7; //Method java/lang/StringBuilder.append:(I)Ljava/lan
g/StringBuilder;
   21:  invokevirtual   #8; //Method java/lang/StringBuilder.toString:()Ljava/la
ng/String;
   24:  astore_3
   25:  return

Отсюда мы можем видеть:

  • в случае "Four" + 4 компилятор Java (я использовал JDK 6) был достаточно умен, чтобы вывести, что это константа, поэтому нет вычислительных усилий во время выполнения, поскольку строка сцепляется при компиляции время
  • в случае "Four" + i эквивалентным кодом является new StringBuilder().append("Four").append(i).toString()
  • Автобоксинг здесь не участвует, так как есть StringBuilder.метод append (int), который, согласно документам, использует строку .valueOf (int) для создания строкового представления целого числа.

Компилятор java фактически создает StringBuilder1 и вызывает метод append(). Это можно увидеть в байт-коде:

22  invokespecial java.lang.StringBuilder(java.lang.String) [40]
...   
29  invokevirtual java.lang.StringBuilder.append(int) : java.lang.StringBuilder [47]
32  invokevirtual java.lang.StringBuilder.toString() : java.lang.String [51]

Тем не менее, поведение идентично боксу, а затем вызову toString(): "Four" + new Integer(4).toString() - и я верю, что разработчики языка имели в виду именно это.


(1) если быть точным, компилятор уже объединяет строковый литерал и литерал int в один строковый литерал "Four4". Вы можете увидеть это в байт-коде на следующем рисунке строка в байт-коде:

 0  ldc <String "Four4"> [19]

Согласно http://jcp.org/aboutJava/communityprocess/jsr/tiger/autoboxing.html , автобоксинг выполняется на примитивном типе всякий раз, когда требуется ссылочный тип (например, класс Integer в этом случае)

Таким образом, int преобразуется в целое число, после чего вызывается метод integer objects toString() и его результат добавляется к предыдущей строке.