初心者のJavaプログラミング

プログラミングガチ初心者がIT業界を目指して頑張ります。

【第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は偽になります。
f:id:fightingneetkun:20140723171933p:plain

ケース2

次にケース2ですが、equalsメソッドを使ってstr1とstr2が同じかどうか調べています。str1とstr2はメモリ上にある場所は違いますが、全く同じ文字列"aaa"が入っているのでこれは問題なくtrueが返ってきます。

ケース3

これもケース1同様にアドレス同士の比較です。メモリの別領域にstr3とstr4はそれぞれ作られているはずなので、str3とstr4のアドレスは別です。よって、これもfalseが返りますね。
...
...
...
...
ターミナル「trueです」
おれ「ん、なんかおかしいな。もう一回コンパイルしてと。ハイ実行っ!ッターン!!」
ターミナル「trueです」
おれ「おっと、別のjavaファイルをコンパイル、実行してしまったか。うっかりだぜ。ほらよっと。」
ターミナル「trueですが何か問題でも」


ふぅ...

調べたり聞いたりした結果分かったことを書きます。
newという演算子はそれはもう文字通りnewですから、メモリに新しい領域を確保しにいくんす。それが以前に使ったことがある文字列だったとしても。
もうほんとにnewって感じです。
f:id:fightingneetkun:20140723173111p:plain

それに対して

String str3 = "aaa";

というようにnewを使わずに宣言すると、いったんキャッシュメモリの方に実体が作られるとのこと。
んで、そのあと

String str4 = "aaa";

というようなstr4を宣言し初期化をすると。str3とstr4は別々のアドレスを指すはずなのだか、javaコンパイラさんがめっちゃ気を使ってくれて、
javaコンパイラ「あ、str3とstr4の値おなじなのね。じゃあstr4さんはとりあえずキャッシュにあるstr3のアドレスを参照しときなさい。そうすればもんだいないでしょ。」
str4「はい!!」
というふうに内部ではなっているみたいです。

なのでこのケース3はtrueになります。

ケース4

まあこれはtrueでしょう。

こんなことが内部で起こっているらしいです。
なるほどーって感じです。

とりあえずStringクラスに関してはこれで終わりです。