"Старий" спосіб виводить купу StringBuilder
орієнтованих операцій. Розглянемо цю програму:
public class Example {
public static void main(String[] args)
{
String result = args[0] + "-" + args[1] + "-" + args[2];
System.out.println(result);
}
}
Якщо ми компілюємо це з JDK 8 або новішою javap -c Example
версією, а потім використовуємо для перегляду байт-коду, ми бачимо щось подібне:
Приклад публічного класу {
публічний приклад ();
Код:
0: aload_0
1: викликспеціальний №1 // Метод java / lang / Object. "<init>" :() V
4: повернення
public static void main (java.lang.String []);
Код:
0: новий №2 // клас java / lang / StringBuilder
3: дуб
4: invokespecial №3 // Метод java / lang / StringBuilder. "<init>" :() V
7: aload_0
8: iconst_0
9: завантаження
10: invokevirtual # 4 // Метод java / lang / StringBuilder.append: (Ljava / lang / String;) Ljava / lang / StringBuilder;
13: ldc № 5 // Рядок -
15: invokevirtual # 4 // Метод java / lang / StringBuilder.append: (Ljava / lang / String;) Ljava / lang / StringBuilder;
18: aload_0
19: iconst_1
20: aaload
21: invokevirtual # 4 // Метод java / lang / StringBuilder.append: (Ljava / lang / String;) Ljava / lang / StringBuilder;
24: ldc № 5 // Рядок -
26: invokevirtual # 4 // Метод java / lang / StringBuilder.append: (Ljava / lang / String;) Ljava / lang / StringBuilder;
29: aload_0
30: iconst_2
31: aaload
32: invokevirtual # 4 // Метод java / lang / StringBuilder.append: (Ljava / lang / String;) Ljava / lang / StringBuilder;
35: invokevirtual # 6 // Метод java / lang / StringBuilder.toString :() Ljava / lang / String;
38: astore_1
39: getstatic # 7 // Поле java / lang / System.out: Ljava / io / PrintStream;
42: aload_1
43: invokevirtual № 8 // Метод java / io / PrintStream.println: (Ljava / lang / String;) V
46: повернення
}
Як бачите, він створює StringBuilder
і використовує append
. Це відоме досить неефективно, оскільки ємність вбудованого буфера за замовчуванням StringBuilder
становить лише 16 символів, і компілятор не може знати заздалегідь виділити більше, тому в кінцевому підсумку потрібно перерозподілити. Це також купа методів викликів. (Зауважте, що JVM іноді може виявити та переписати ці схеми дзвінків, щоб зробити їх ефективнішими.)
Давайте розглянемо, що створює Java 9:
Приклад публічного класу {
публічний приклад ();
Код:
0: aload_0
1: викликспеціальний №1 // Метод java / lang / Object. "<init>" :() V
4: повернення
public static void main (java.lang.String []);
Код:
0: aload_0
1: iconst_0
2: завантаження
3: aload_0
4: iconst_1
5: завантаження
6: aload_0
7: iconst_2
8: завантаження
9: invokedynamic # 2, 0 // InvokeDynamic # 0: makeConcatWithConstants: (Ljava / lang / String; Ljava / lang / String; Ljava / lang / String;) Ljava / lang / String;
14: astore_1
15: getstatic # 3 // Field java / lang / System.out: Ljava / io / PrintStream;
18: aload_1
19: invokevirtual # 4 // Метод java / io / PrintStream.println: (Ljava / lang / String;) V
22: повернення
}
О, але це коротше. :-) Здійснює єдиний дзвінок makeConcatWithConstants
з StringConcatFactory
, який говорить про це у своєму Javadoc:
Методи, що сприяють створенню методів конкатенації рядків, які можуть бути використані для ефективного об'єднання відомої кількості аргументів відомих типів, можливо після адаптації типу та часткової оцінки аргументів. Ці методи, як правило, використовуються як методи завантаження для invokedynamic
веб-сайтів для викликів для підтримки функції рядкового конкатенації мови програмування Java.