Ответ 1
Посмотрите на следующие простые выражения в Java
int x=15;
String temp="x = "+x;
Компилятор преобразует "x = "+x;
в StringBuilder
внутренне и использует .append(int)
для "добавления" целых чисел в строку.
Любой тип может быть преобразован в тип String путем преобразования строки.
Значение х примитивного типа T сначала преобразуется в опорное значение как если бы он передал его как аргумент соответствующему экземпляру класса (§15.9):
- Если T булево, то используйте новый Boolean (x).
- Если T char, используйте новый символ (x).
- Если T является байтом, коротким или int, то используйте новый Integer (x).
- Если T длинно, используйте новый Long (x).
- Если T является float, используйте новый Float (x).
- Если T двойное, используйте новый Double (x).
Это ссылочное значение затем преобразуется в тип String по строке преобразование.
Теперь нужно учитывать только опорные значения:
- Если ссылка имеет значение null, она преобразуется в строку "null" (четыре символа ASCII n, u, l, l).
- В противном случае преобразование выполняется как бы путем вызова метода toString ссылочного объекта без аргументов; но если результат вызова метода toString равен нулю, тогда Вместо этого используется строка "null".
Метод toString определяется примитивным классом Object (§4.3.2). Многие классы переопределяют его, в частности Boolean, Character, Integer, Long, Float, Double и String.
Подробнее о контексте преобразования строк см. в п. 5.4.
Оптимизация конкатенации строк:Реализация может выбрать выполнение преобразования и конкатенации в один шаг, чтобы избежать создания и затем отбрасывания промежуточного Строковый объект. Чтобы увеличить производительность повторяющейся строки concatenation, компилятор Java может использовать класс StringBuffer или аналогичная техника для уменьшения количества промежуточных объектов String которые создаются путем оценки выражения.
Для примитивных типов реализация также может оптимизировать создание объекта-обертки путем преобразования непосредственно из примитива введите строку.
Оптимизированная версия на самом деле не сделает полное завершенное преобразование String.
Это хорошая иллюстрация оптимизированной версии, используемой компилятором, хотя и без преобразования примитива, где вы можете видеть, как компилятор меняет вещи на StringBuilder в фоновом режиме:
http://caprazzi.net/posts/java-bytecode-string-concatenation-and-stringbuilder/
Этот код Java:
public static void main(String[] args) {
String cip = "cip";
String ciop = "ciop";
String plus = cip + ciop;
String build = new StringBuilder(cip).append(ciop).toString();
}
Генерирует это - посмотрим, как два стиля конкатенации приводят к одному и тому же байт-коду:
L0
LINENUMBER 23 L0
LDC "cip"
ASTORE 1
L1
LINENUMBER 24 L1
LDC "ciop"
ASTORE 2
// cip + ciop
L2
LINENUMBER 25 L2
NEW java/lang/StringBuilder
DUP
ALOAD 1
INVOKESTATIC java/lang/String.valueOf(Ljava/lang/Object;)Ljava/lang/String;
INVOKESPECIAL java/lang/StringBuilder.<init>(Ljava/lang/String;)V
ALOAD 2
INVOKEVIRTUAL java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lang/StringBuilder;
INVOKEVIRTUAL java/lang/StringBuilder.toString()Ljava/lang/String;
ASTORE 3
// new StringBuilder(cip).append(ciop).toString()
L3
LINENUMBER 26 L3
NEW java/lang/StringBuilder
DUP
ALOAD 1
INVOKESPECIAL java/lang/StringBuilder.<init>(Ljava/lang/String;)V
ALOAD 2
INVOKEVIRTUAL java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lang/StringBuilder;
INVOKEVIRTUAL java/lang/StringBuilder.toString()Ljava/lang/String;
ASTORE 4
L4
LINENUMBER 27 L4
RETURN
Посмотрев на пример выше и как генерируется байт-код на основе исходного кода в данном примере, вы сможете заметить, что компилятор внутренне преобразовал следующий оператор
cip+ciop;
в
new StringBuilder(cip).append(ciop).toString();
Другими словами, оператор +
в конкатенации строк является эффективным сокращением для более подробного StringBuilder
-идиома.