結論:Javaで変数に格納した文字列を比較する時はequals()を使おう。
やりたい事
- String str1 = "hoge"
- String str2 = "hoge"
- str1とstr2が等しい時はif文の処理に入れる
参考
文字列と文字列の比較
https://www.javadrive.jp/start/string/index4.html
【Java入門】文字列(String)を比較する方法(「==」と「equals」)
https://www.sejuku.net/blog/14621
変数に数値を代入して比較する場合
int num = 10
if (num == 10) {
System.out.println("numは10です。");
} else {
System.out.println("numは10ではありません。");
}
この式では、変数numに格納しているのは10なので処理結果は
numは10です。
変数に文字列型を代入して比較する場合
String str1 = "hoge"
String str2 = "hoge"
if (str1 == str2) {
System.out.println("str1とstr2は同じです。");
} else {
System.out.println("str1とstr2は違います。");
}
この式では変数str1と変数str2は同じ文字列hogeが格納されているので処理結果は「str1とstr2は同じです。」と返ってくると思っていました。
str1とstr2は違います。
。。。!?ほげ!?なんで!?
ここでドツボにはまり、300回くらいデバックしました。
文字列がメモリ上で格納されている場所が一緒かどうか比較するメソッド「==」
「==」で比較しても違う文字列として扱われてしまいます。これはJavaの参照といいます
文字列は生成されるとメモリ上に文字列を保存しておくための場所(領域)が確保されます。その確保した「場所」をhogeは保持しています
つまり値を変数に保存しているわけではなく、場所を覚えておきhogeを使う際にその場所をたどって値を引っ張り出してくるという仕組みになっています
この参照という仕組みがあるため「==」で比較した場合、文字列の値が一緒かどうかではなく文字列がメモリ上で格納されている場所が一緒かどうかという比較になります
同じメモリ領域に保存されていればtrue
そうでなければfalse
を返します
先程の式でいうと、str1とstr2は違うメモリ領域に保存されている為、false
を返します
equals()メソッドを使って文字列を比較する
String str1 = "hoge"
String str2 = "hoge"
if (str1.equals(str2)) {
System.out.println("str1とstr2は同じです。");
} else {
System.out.println("str1とstr2は違います。");
}
処理結果
str1とstr2は同じです。
想定していた結果が返ってきました。
ちなみにrubyで書くと「==」でも同じ結果が返ってきます
str1 = "hoge"
str2 = "hoge"
if str1 == str2 then
puts "str1とstr2は同じです。"
else
puts "str1とstr2は違います。"
end
# => str1とstr2は同じです。
まとめ
rubyやJavaScriptを使っている時は数値型
も文字列型
も「==」を使って比較できるのでJavaでも疑いなくプログラムを書いていましたが、Javaは違うんですねー
画面に穴が空くくらい文法ミスが無いかチェックしましたが、「参照」を知らないと私みたく余計な時間を使うので注意しましょう