Когда я компилирую этот фрагмент.
public class InternTest {
public static void main(String...strings ){
final String str1="str";
final String str2="ing";
String str= str1+str2;
}
}
Что создает следующий байтовый код
public static void main(java.lang.String...);
flags: ACC_PUBLIC, ACC_STATIC, ACC_VARARGS
Code:
stack=1, locals=4, args_size=1
0: ldc #16 // String str
2: astore_1
3: ldc #18 // String ing
5: astore_2
6: ldc #20 // String string
8: astore_3
9: return
поэтому строковая литерал "string" уже присутствует в пуле констант, который нажимается на 6: ldc #20 // String string
на стеке в этой строке.
Цитирование JSL
Из JLS §4.12.4 - окончательные переменные:
Переменная примитивного типа или типа String, которая является окончательной и инициализированное выражением константы времени компиляции (§15.28), является называемой постоянной переменной.
Также из JLS §15.28 - ConstantExpression:
Выражения константы времени компиляции типа String всегда "интернированы" чтобы обмениваться уникальными экземплярами, используя метод String # intern().
Итак, я знаю, что str1 и str2 будут интернированы с момента его создания. "str" и "ing" будут иметь одну и ту же память в строке String str= str1+str2;
Но как str1 + str2 напрямую создает строку в пуле строк. Без вызова любого класса String Builder, как это происходит, когда я не пишу final
.? Чтобы узнать, есть ли у него какие-либо действия в отношении стажеров.
Я написал этот фрагмент
public class IntermTest {
public static void main(String...strings ){
String str1=("str").intern();
String str2=("ing").intern();
String str= str1+str2;
}
}
Но когда я сгенерировал байтовый код, я получил этот
public static void main(java.lang.String...);
flags: ACC_PUBLIC, ACC_STATIC, ACC_VARARGS
Code:
stack=3, locals=4, args_size=1
0: ldc #16 // String str
2: invokevirtual #18 // Method java/lang/String.intern:
()Ljava/lang/String;
5: astore_1
6: ldc #24 // String ing
8: invokevirtual #18 // Method java/lang/String.intern:
()Ljava/lang/String;
11: astore_2
12: new #26 // class java/lang/StringBuilder
15: dup
16: aload_1
17: invokestatic #28 // Method java/lang/String.valueOf
:(Ljava/lang/Object;)Ljava/lang/String;
20: invokespecial #32 // Method java/lang/StringBuilder.
"<init>":(Ljava/lang/String;)V
23: aload_2
24: invokevirtual #35 // Method java/lang/StringBuilder.
append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
27: invokevirtual #39 // Method java/lang/StringBuilder.
toString:()Ljava/lang/String;
30: astore_3
31: return
В действительности он также использует stringBuilder
для конкатенации. Так что он сделал что-то с финалом. Есть ли что-то особенное в строках final
, о которых я точно не знаю?