String変数を比較する場合の注意点
Javaの学習で、String型変数を比較する場合の処理が分かり辛かったので復習のために記事にしてみます。
関係演算子(==)で比較してみる
String型変数を関係演算子(==)で比較する場合の挙動を下記のコードで一度確認してみましょう。
String a = "hoge";
String b = new String("hoge");
String c = "hoge";
String d = b.intern();
System.out.println("a = b : " + (a == b));
System.out.println("a = c : " + (a == c));
System.out.println("a = d : " + (a == d));
System.out.println("b = d : " + (b == d));
変数aはnewを使用していないため、Stringが管理する領域に文字列("hoge")が作成され、参照されます。
変数bはnewを使用しているため、ヒープ領域に文字列("hoge")が作成され、参照されます。
変数cは変数aと同じく、newを使用していないため、Stringが管理する領域の文字列("hoge")を参照を参照します。
※変数aの作成時にStringが管理する領域に"hoge"が生成されているため、変数cの作成時は同じものを参照するようになります。
変数dは変数bに対してintern()メソッドを使用した値を代入していますが、intern()メソッドは参照先ではなく参照先の値を返しているため、Stringが管理する領域に同じ文字列が存在しないか確認し、存在する場合はその領域を返します。
実行結果
a = b : false
a = c : true
a = d : true
b = d : false
実行結果
1行目:変数aとbが比較されますが、参照先が違うため(aはStringの領域、bはnewで作成されたため別の領域)falseになります。
2行目:変数aとcは同じ参照先(Stringの領域の"hoge")なので、trueになります。
3行目:変数aとdは同じ参照先(Stringの領域の"hoge")なので、trueになります。
4行目:変数bとdされていますが、参照先が違うため(bはnewで作成された領域、dはStringの領域)falseになります。
このように参照型変数を関係演算子(==)で比較する場合、参照先の値ではなく参照先が比較され、同じ参照先の場合にtrueを返します。
equals()メソッドを利用してみる
関係演算子(==)を利用するだけではString型変数の参照先の値では比較できないのでequals()メソッドを利用して参照先の値で比較を行ってみます。
String a = "hoge";
String b = new String("hoge");
String c = "hoge";
String d = b.intern();
System.out.println("a.equals(b) : " + (a.equals(b) ) );
System.out.println("a.equals(c) : " + (a.equals(c) ) );
System.out.println("a.equals(d) : " + (a.equals(d) ) );
System.out.println("b.equals(d) : " + (b.equals(d) ) );
実行結果
a.equals(b) : true
a.equals(c) : true
a.equals(d) : true
b.equals(d) : true
equals()メソッドでは参照先の値を比較しているため、全てtrueとなります。
まとめ
- 参照型変数(String等)を関係演算子(==)で比較すると参照先の値ではなく、参照先が一致しているかを比較する。
- 参照型変数をnewを使って生成すると、値が同じものでも別の領域に値が生成されて参照される。
- String型変数の参照先の値を比較したい場合はequals()メソッドを利用すれば比較できる。