Bir ilan zaman String
(bir değişmez şekilde) değişken final
ve bir derleme zamanı sabiti ifade ile başlatmak, aynı zamanda bir derleme zamanı sabit ifade olur ve değeri kullanıldığı derleyici tarafından satır içi. Dolayısıyla, ikinci kod örneğinizde, değerleri satır içine aldıktan sonra, dize birleştirmesi derleyici tarafından şu dile çevrilir:
String concat = "str" + "ing"; // which then becomes `String concat = "string";`
hangi ile karşılaştırıldığında "string"
size verecektir true
, çünkü dize değişmezleri stajyer .
Gönderen §4.12.4 JLS - final
Değişkenler :
Basit tür ve tip bir değişken String
olan, final
bir derleme zamanı sabiti ekspresyonu (§15.28) ile başlatılır ve, bir adlandırılan sabit bir değişken .
Ayrıca JLS §15.28 - Sürekli İfade:
Derleme zamanı sabit tür ifadeleri , yöntemi kullanarak benzersiz örnekleri paylaşmak String
için her zaman "sabitlenir"String#intern()
.
String
Değişkenlerin olmadığı ilk kod örneğinizde durum böyle değildir final
. Yani, bunlar derleme zamanı sabit ifadeleri değildir. Buradaki birleştirme işlemi, çalışma zamanına kadar ertelenir ve böylece yeni bir String
nesnenin oluşturulmasına yol açar . Her iki kodun bayt kodunu karşılaştırarak bunu doğrulayabilirsiniz.
İlk kod örneği ( final
sürüm olmayan ) aşağıdaki bayt koduyla derlenir:
Code:
0: ldc #2; //String str
2: astore_1
3: ldc #3; //String ing
5: astore_2
6: new #4; //class java/lang/StringBuilder
9: dup
10: invokespecial #5; //Method java/lang/StringBuilder."<init>":()V
13: aload_1
14: invokevirtual #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
17: aload_2
18: invokevirtual #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
21: invokevirtual #7; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
24: astore_3
25: getstatic #8; //Field java/lang/System.out:Ljava/io/PrintStream;
28: aload_3
29: ldc #9; //String string
31: if_acmpne 38
34: iconst_1
35: goto 39
38: iconst_0
39: invokevirtual #10; //Method java/io/PrintStream.println:(Z)V
42: return
Açıkça , iki ayrı değişkente depolanıyor str
ve birleştirme işlemini gerçekleştirmek için ing
kullanıyor StringBuilder
.
Halbuki, ikinci kod örneğiniz ( final
versiyon) şöyle görünür:
Code:
0: ldc #2; //String string
2: astore_3
3: getstatic #3; //Field java/lang/System.out:Ljava/io/PrintStream;
6: aload_3
7: ldc #2; //String string
9: if_acmpne 16
12: iconst_1
13: goto 17
16: iconst_0
17: invokevirtual #4; //Method java/io/PrintStream.println:(Z)V
20: return
Bu nedenle string
, derleme zamanında Dize oluşturmak için son değişkeni doğrudan satır içine alır ve bu ldc
adımda işlemle yüklenir 0
. Sonra ikinci dize hazır bilgisi ldc
adım adım işlemle yüklenir 7
. Çalışma String
zamanında yeni bir nesnenin oluşturulmasını içermez . Dize derleme zamanında zaten bilinir ve stajyerdir.