この問題いつまで消えないんだろ?
Javaの文字列比較で==
演算子は使っちゃダメ!
equals
メソッドを使え!
っていうコレ!
そろそろ、この問題をなくしたい!
- Javaの文字列比較で
==
演算子を使っている人! ==
演算子とequals
メソッドの違いが分からない- そもそも
equals
メソッドなんて知らない
◆解決できるかも知れないお悩み
==
演算子とequals
メソッドの違いが分かる- Stringクラスはポインタって事が分かる!
◆どうやって解決するか
- メモリの中のStringの状態を、図を書いて解説します
Contents
プログラマなら絶対に一度は聞いたことあるよね!
Javaの文字列比較に==
演算子を使うな!
equals
メソッドを使え!
結論を先に書きますが、
Javaで文字列と文字列が一致しているか否かをチェックする場合、==
演算子を使っちゃダメ!
equals
メソッドを使います!!!
え、でも、今まで
if( stringA == stringB )
って書いてちゃんと判断できていたよ
とおっしゃる方もいらっしゃるでしょう
それはたまたまです!
運が良かっただけ!
サンプルを見てみよう!
以下をご覧ください
どういう結果になるか分かりますか?
➊ ==
演算子を使うパターン
public class Sample1 { public static void main(String [] args) { String hoge = "aiueo"; String fuga = "aiu".concat("eo"); System.out.println("hoge : " + hoge.toString()); System.out.println("fuga : " + fuga.toString()); if( hoge == fuga ) { System.out.println("[==] 一致"); } else { // ★こっちに入るはず System.out.println("[==] 不一致"); } } }
> java Sample hoge : aiueo fuga : aiueo [==] 不一致
➋ equals
メソッドを使うパターン
public class Sample2 { public static void main(String [] args) { String hoge = "aiueo"; String fuga = "aiu".concat("eo"); System.out.println("hoge : " + hoge.toString()); System.out.println("fuga : " + fuga.toString()); if( hoge.equals(fuga) ) { // ★こっちに入るはず System.out.println("[equals] 一致"); } else { System.out.println("[equals] 不一致"); } } }
> java Sample2 hoge : aiueo fuga : aiueo [equals] 一致
➌ ==
演算子を使うパターン2
public class Sample3 { public static void main(String [] args) { String fuga = "aiu".concat("eo"); System.out.println("fuga : " + fuga.toString()); if( "aiueo" == fuga ) { System.out.println("[==] 一致"); } else { // ★こっちに入るはず System.out.println("[==] 不一致"); } } }
> java Sample3 fuga : aiueo [==] 不一致
➍ equals
メソッドを使うパターン2
public class Sample4 { public static void main(String [] args) { String fuga = "aiu".concat("eo"); System.out.println("fuga : " + fuga.toString()); if( "aiueo".equals(fuga) ) { // ★こっちに入るはず System.out.println("[equals] 一致"); } else { System.out.println("[equals] 不一致"); } } }
> java Sample4 fuga : aiueo [equals] 一致
結果をまとめると・・・
ね?
文字列比較の場合に==
演算子はダメっていうのが分かりますか?
比較方法 | 結果 | |
---|---|---|
➊ | == 演算子 |
合致しないと判定された! |
➋ | equals メソッド |
合致していると判定された! |
➌ | == 演算子 |
合致しないと判定された! |
➍ | equals メソッド |
合致していると判定された! |
理屈
理由を説明します
以下の図を見てください
青四角:文字列
黒文字:メモリ上に展開された番地
緑線 :参照の関係性を示しています
赤四角はnewされた時に、メモリ上のどこかに作られます
※図では100番地とか200番地とかって書いていますが、実際にはどこの番地に作られるかは分かりませんし、確認することもできません
青四角の文字列もメモリ上のどこかに作られます
※図では150番地とか280番地とかって書いていますが、実際にはどこの番地に作られるかは分かりません、確認することもできません
メモリって、人間世界で言えば土地みたいなものです
「メモリは机の上みたいなもの」と表現されることが多いんですけど、僕は土地に例える方が分かりやすいと考えています
そして、newや変数宣言とは、「空いてる土地を借りられる事」だと説明しています(後で返す必要があるので借りられると表現)
人間世界でも土地を借りたら、もちろん住所がつきます
土地に住所があるのと同じように、メモリにも住所(番地)があります
メモリを「机の上」と表現するのはいいのですが、メモリのアドレス(住所)の事がすっぽり抜け落ちてしまうため、プログラミング時においては良くない表現だと思います
パソコンに増設するメモリを購入するとかっていう場合なら「机の上」がピッタリですけどね
で、Javaではこのアドレスを見ることはできません
C言語ではアドレスを見ることはできます
==
演算子で比較するということは?
つまり、==
演算子で比較するということは、↓こういうことになるとイメージしてください
if (hoge == fuga) {
↓
if (“150番地” == “280番地”) {
“150番地”と”280番地”という住所そのものを比較しているため、それぞれが持つ文字列が同じでも一致しないのです
equals
メソッドで比較するということは?
equals
メソッドであれば、hogeとfugaが参照している先のものを比較します
if( hoge.equals(fuga) ) {
↓
hogeが参照しているのは? → 150番地にある”aiueo”
fugaが参照しているのは? → 180番地にある”aiueo”
ってことで、
if( “aiueo”.equals(“aiueo”) ) {
という感じになります
さいごに、
==
演算子とequals
メソッドの誤用問題は、いつまでたっても消えませんねコンピューターの知識をちゃんと持っていれば何ら難しくないんですけど・・・
最近では、
プログラミングという言葉は「単に命令を覚えて、ライブラリの使い方を覚えたらオッケー♪」という意味
と考えている方がいらっしゃるかも知れませんが、きちんとメモリ上での展開が頭に思い浮かべられなければいけません
この記事では、「文字列比較は==
演算子じゃなくてequals
メソッドと使いましょう」というそんな単純な一言を言いたいワケではありません
記事中で書いたメモリの図のような内容が頭の中に思い浮かぶよう、理解して欲しいと願っています
私がJavaでもC言語でもRubyでもPythonでもプログラミングを教える時はメモリ上の動きを必ず説明します
と言うか、言語はどーーでもいいです
まずはメモリ上の動き、メモリ上のデータの配置ありきです!
メモリに関してはプログラム言語が何であっても同じです
だって、CPUから見たら全てマシン語なんですからね
プログラミング のレッスンに興味がある方、レッスン内容を聞いてみたい方、なんなりとお問い合わせください。
無料体験レッスンもありますのでお気軽にどうぞ!!!
参考書籍
僕の知識の源になってるのはこの本だと思う
これで学習してから、プログラム言語とか、コンピューターとか、プログラムの動作原理が分かったような気がする
個人的には、プログラムはなぜ動くのかよりは、こっちの方がプログラムの仕組みが分かったように思う
でも、この本に掲載しているソースコードで爆笑しまくったので、暇つぶしにでも読んでみるといいと思うよ
・・・・しかし、現実には、この本に掲載されているソースコードなんて可愛いもんだったりするけどね(笑)