Bir ilan zaman String(bir değişmez şekilde) değişken finalve 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 - finalDeğişkenler :
Basit tür ve tip bir değişken Stringolan, finalbir 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 Stringiçin her zaman "sabitlenir"String#intern() .
StringDeğ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 Stringnesnenin oluşturulmasına yol açar . Her iki kodun bayt kodunu karşılaştırarak bunu doğrulayabilirsiniz.
İlk kod örneği ( finalsü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 strve birleştirme işlemini gerçekleştirmek için ingkullanıyor StringBuilder.
Halbuki, ikinci kod örneğiniz ( finalversiyon) şö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 ldcadımda işlemle yüklenir 0. Sonra ikinci dize hazır bilgisi ldcadım adım işlemle yüklenir 7. Çalışma Stringzamanında yeni bir nesnenin oluşturulmasını içermez . Dize derleme zamanında zaten bilinir ve stajyerdir.