2009-07-27 15 views
5

これは主に純粋な好奇心から生まれた質問です。私は具体性のためにJavaについて具体的に尋ねています。私は空の文字列と文字列(任意の文字列)を連結する場合は、メモリに、何が起こるJavaで空文字列を連結すると、コンパイルと実行時にはどうなりますか?

、例えば:

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

私はその後、Sの内容はまだ「古い文字列」になることを知っています空のASCII文字列はASCIIヌルとしてメモリに格納されるため(少なくともJavaでは文字列は常にNULLで終了するため)しかし、Java(コンパイラ?VM?)がsが変更されないことを知るのに十分な最適化を実行するかどうか、またバイトコード内の命令を完全に省略することができるか、コンパイル時と実行時に何か異なることがあるかどうかを知りたい。

答えて

16

バイトコードの時間です!

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 

} 

あなたは+=は関係なく、それが連結しているものの作成するStringBuilderを引き起こし、それが実行時に最適化することができないことがわかります。

あなたは同じ式で両方の文字列リテラルを置く場合一方、それらはコンパイラによって連結されています

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 - greatjustice – Alex

+0

のためのクールな。ありがとうございました! –

+1

@ mmyers:1)放出されるバイトコードは(理論上は)Javaコンパイラ固有であり、2)JITコンパイラは(理論上は)さらに最適化できることを指摘しておきます。 –

2

あなたがライン

s += ""; 

Javaは、新しいStringオブジェクトを割り当て、文字列連結の後に割り当てを実行した後、新しいStringを取得します。あなたは便利です(と私はあなたがNetBeansで同じことをすることができますが、私は今まで使用したことを前提としていますがeclipseを使用している)場合は、その行をブレークポイントし、オブジェクトのオブジェクトIDを見ることができますは、その行私の場合は、そのコード行がid = 20で、その後はid = 24だった前に、というオブジェクトIDがありました。

関連する問題