研修のときに、口を酸っぱくして説明するんだけどみんな忘れちゃうやつ。
String型は参照型である
というのはどういうことかというと、
String str = "ABC";
と宣言したとき、メモリ上は、
となるのだけれど(イメージです。実際のメモリ配置を表してはいません)、これが例えば
public class Test { public static void main(String[] args){ String str = "ABC"; if(str == args[0]){ System.out.println("同じ文字列です"); } else { System.out.println("違う文字列です"); } } }
というコードのとき、コンパイルして実行したら、
>java Test ABC 違う文字列です
となる。これはメモリ上、
こういう状態で、●と□を比較しているので、等しくないと判断される。
public class Test { public static void main(String[] args){ String str = "ABC"; if(str.equals(args[0])){ System.out.println("同じ文字列です"); } else { System.out.println("違う文字列です"); } } }
と記述すれば、strが参照している文字列と、args[0]が参照している文字列の比較に鳴るので、等しいと判断される。
メモリ管理のやっかいなところ
で、問題は、
public class Test { public static void main(String[] args){ String str1 = "ABC"; String str2 = "ABC"; if(str == str2){ System.out.println("同じ文字列です"); } else { System.out.println("違う文字列です"); } } }
と書いたら、等しいと判断されること。
これはなぜかというと、
- String型はクラスで定義された型なので、正確には
String str1 = new String("ABC");
と書くべきである。 でもStringはとってもよく使うので例外的に、
String str1 = "ABC";
と書ける。
2.ただし、省略形の書き方は、明示的なオブジェクトの生成を指定していないので、
String str1 = "ABC"; String str2 = "ABC";
と書くと、str1はオブジェクト生成が行われるが、str2では先程生成したオブジェクトをそのまま参照する。 つまり、メモリ上は
になる。 これはJVMがそういうふうにメモリ管理することにしてるので。
なので最後のコード書いて、なーーんだ==で文字列比較してちゃんと出来るじゃ~んってならないでね。 そして、C++やC#だと、==で文字列比較できるのにー、っていう人、それはC++やC#には演算子のオーバーロードという機能があって、Javaにはないからです…