質問: "hoge";
回答: あー、違う。けっこう勘違いしている人多いんだけど。 string str = "hoge"; string str = new string("hoge"); これは、実は「別のもの」なんだよ。コンパイル時に、"hoge"がnew string("hoge")に変換されたりはしない。なぜなら、これはjava内部ではまったく別のことを行っているからだ。実際、コンパイルしたものをデコンパイルしてみるとわかる。"hello"は”hello"だし、new stringはnew stringのままだ。これらは、シンタックスシュガーじゃない。それぞれ「別のことを行っている文法」なんだよ。 これは、javaの中でもかなり引っかかる部分なんだが、実は、"hello"は、「hello」というstringオブジェクト「ではない」んだ。これは、うーん、java仮想マシンの仕組みがわからないとうまく説明できないんだが。 ま、手っ取り早くいっちまえば、「stringリテラルは、javaの内部では特別なものとして扱われている」ということ。string str = "hello";みたいにソースコード内にstringリテラルが登場すると、java仮想マシンは定数プールと呼ばれるところにその値を保管し、次に同じリテラルが登場するとその定数プールに保管した値の参照を変数に渡す。つまり、 string a1 = "hello"; string a2 = "hello"; こんなふうにすると、a1にもa2にも常に同じオブジェクトへの参照が渡される(つまりどちらの変数も同じオブジェクトを見ている)。ところが、 string b1 = new string("hello"); string b2 = new string("hello"); このようにnew stringすると、java仮想マシンは、定数プールではなく、通常のオブジェクトを配置するヒープ内に新たにインスタンスを作成し、その参照を設定する。つまりこの場合、b1とb2は、それぞれ別のstringオブジェクトを参照していることになる。ためしに、 system.out.println(a1 == a2); system.out.println(b1 == b2); system.out.println(a1 == b1); このように、変数の参照が等しいかどうかをチェックすると、a1とa2は等しいが、b1とb2は等しくないし、またa1とb1も等しくないことがわかる。これらは、それぞれ別のオブジェクトを参照してるんだ。いずれもテキストとしての値はすべて「hello」なんだが、内部的にはまったく別のものだ。 というわけで、特別な理由がない限り、stringを変数に設定する場合は、string str = "hello";というようにリテラルを直接指定し、new stringは使わない。そうすることにより、stringオブジェクトを必要最低限で済ませることができ、メモリにもまたパフォーマンス的にもよい結果となる(ま、実際はほとんど違いはないけどな)。 ただし、この「stringリテラルとstringインスタンスは別のものだ」ということを利用して、わざとnew stringを使うこともある。が、このへんは、もう少しjavaに慣れてから知ればいいことだろう。