2009-07-27 5 views
5

Bu, çoğunlukla saf bir meraktan (ve bir süre öldürme) oluşan bir sorudur. Ben somutluk uğruna özellikle Java hakkında soruyorum. Ben boş bir dize ile bir dize (herhangi bir dize) bitiştirmek eğer bellekte, ne olurJava'da boş bir dizeyi birleştirirken derleme ve çalışma zamanında ne olur?

, örneğin:

String s = "any old string"; 
s += ""; 

Ben sonra, s 'nin içindeki hala "herhangi bir eski dizesi" olacağını biliyor boş bir ASCII dizgisi bellekte bir ASCII boş olarak saklandığından (en azından Java'da, dizeler her zaman boşta sonlandırılmıştır). Ancak Java'nın (derleyici? VM), değişmeyeceğini bilmek için yeterli optimizasyon yapıp yapmadığını ve bu kodu bayt koduyla tamamen ya da derleme ve çalışma zamanlarında farklı bir şey yapıp yapmadığını bilmek merak ediyorum.

cevap

16

Bu bayt kodu zamanı!

class EmptyString { 
    public static void main(String[] args) { 
     String s = "any old string"; 
     s += ""; 
    } 
} 

javap -c EmptyString

:

 
Compiled from "EmptyString.java" 
class EmptyString extends java.lang.Object{ 
EmptyString(); 
    Code: 
    0: aload_0 
    1: invokespecial #1; //Method java/lang/Object."":()V 
    4: return 

public static void main(java.lang.String[]); 
    Code: 
    0: ldc  #2; //String any old string 
    2: astore_1 
    3: new  #3; //class java/lang/StringBuilder 
    6: dup 
    7: invokespecial #4; //Method java/lang/StringBuilder."":()V 
    10: aload_1 
    11: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 
    14: ldc  #6; //String 
    16: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 
    19: invokevirtual #7; //Method java/lang/StringBuilder.toString:()Ljava/lang/String; 
    22: astore_1 
    23: return 

} 

Sen += bir StringBuilder olursa olsun birleştirerek neler olup oluşturulmasına neden olur, bu nedenle zamanında optimize edilemez olduğunu görebiliriz. Aynı ifadede her iki dize değişmezleri koyarsanız Öte yandan

, bunlar derleyici tarafından birleştirilmiş:

class EmptyString { 
    public static void main(String[] args) { 
     String s = "any old string" + ""; 
    } 
} 

javap -c EmptyString:

 
Compiled from "EmptyString.java" 
class EmptyString extends java.lang.Object{ 
EmptyString(); 
    Code: 
    0: aload_0 
    1: invokespecial #1; //Method java/lang/Object."":()V 
    4: return 

public static void main(java.lang.String[]); 
    Code: 
    0: ldc  #2; //String any old string 
    2: astore_1 
    3: return 

} 
+3

+1 - Serin greatjustice – Alex

+0

için . teşekkür ederim! –

+1

@mmyers: 1) yayımlanan bayt kodlarının (teoride) Java derleyicisine özgü olduğunu ve 2) JIT derleyicisinin (teoride) daha fazla optimize edebileceğini belirtmelisiniz. –

2

Çizgiyi

s += ""; 

Java yeni bir String nesnesi ayırır ve s dizisi birleştirme sonrasında atar yürüttükten sonra yeni bir dize alırsınız. Eğer elipsiniz varsa (ve ben aynı şeyi NetBeans'de yapabileceğinizi varsayalım, ama sadece bir tutku kullandım) bu satırı kesebilir ve nesnenin nesne kimliklerini s işaretini yürütmeden önce ve sonra izleyebilirsiniz. bu çizgi. Benim durumumda, bu kod satırından önce s nesne kimliği id = 20 ve sonra da id = 24 idi.

İlgili konular