【第9回】初心者のJavaプログラミング【Stringクラスについて】
こんにちは、梅雨明けしたらしいですね。
毎日暑くてひからびそうです。
今日はStringクラスについてです。
String型ってクラスなんですよね。昨日、Stringクラスで宣言したオブジェクトは参照型ではないと書きましたが、間違ってましたw参照型ですwでも参照型なんですが、参照型っぽくないので、プリミティブ型と同じような扱いですと説明したみたいです。
さて今日の例題です。
class TestSample { public static void main( String args[] ) { String str1 = new String("aaa"); String str2 = new String("aaa"); // アドレスを比較 System.out.println(str1 == str2); // ケース1 // 実体を比較 System.out.println(str1.equals(str2)); // ケース2 String str3 = "aaa"; String str4 = "aaa"; // アドレスを比較 System.out.println(str3 == str4); // ケース3 // 実体を比較 System.out.println(str3.equals(str4)); // ケース4 } }
ケース1,2,3,4はそれぞれどんな結果がくるでしょうか。true or falseです。
ケース1
Stringクラスだけでなく、クラスのオブジェクトは参照型変数です。ですので、変数の中には実際の値が入っている訳ではありません。この場合だとstr1には"aaa"が入っていないです。"aaa"という文字列は別の領域に作られます。その領域を参照しにいく形でstr1は値を入手(入手という表現が正しいかわからないです)します。
そして、new演算子というものはクラスからインスタンスを生成するぞーという合図です。同じ値でも、別の場所にメモリを確保しにいきます。str1とstr2はアドレスが入っていますので、ケース1は偽になります。
ケース2
次にケース2ですが、equalsメソッドを使ってstr1とstr2が同じかどうか調べています。str1とstr2はメモリ上にある場所は違いますが、全く同じ文字列"aaa"が入っているのでこれは問題なくtrueが返ってきます。
ケース3
これもケース1同様にアドレス同士の比較です。メモリの別領域にstr3とstr4はそれぞれ作られているはずなので、str3とstr4のアドレスは別です。よって、これもfalseが返りますね。
...
...
...
...
ターミナル「trueです」
おれ「ん、なんかおかしいな。もう一回コンパイルしてと。ハイ実行っ!ッターン!!」
ターミナル「trueです」
おれ「おっと、別のjavaファイルをコンパイル、実行してしまったか。うっかりだぜ。ほらよっと。」
ターミナル「trueですが何か問題でも」
ふぅ...
調べたり聞いたりした結果分かったことを書きます。
newという演算子はそれはもう文字通りnewですから、メモリに新しい領域を確保しにいくんす。それが以前に使ったことがある文字列だったとしても。
もうほんとにnewって感じです。
それに対して
String str3 = "aaa";
というようにnewを使わずに宣言すると、いったんキャッシュメモリの方に実体が作られるとのこと。
んで、そのあと
String str4 = "aaa";
というようなstr4を宣言し初期化をすると。str3とstr4は別々のアドレスを指すはずなのだか、javaのコンパイラさんがめっちゃ気を使ってくれて、
javaコンパイラ「あ、str3とstr4の値おなじなのね。じゃあstr4さんはとりあえずキャッシュにあるstr3のアドレスを参照しときなさい。そうすればもんだいないでしょ。」
str4「はい!!」
というふうに内部ではなっているみたいです。
なのでこのケース3はtrueになります。
ケース4
まあこれはtrueでしょう。
こんなことが内部で起こっているらしいです。
なるほどーって感じです。
とりあえずStringクラスに関してはこれで終わりです。